+
+
diff --git a/src/logic/jsCreateQuery.js b/src/logic/jsCreateQuery.js
new file mode 100644
index 0000000..754831f
--- /dev/null
+++ b/src/logic/jsCreateQuery.js
@@ -0,0 +1,47 @@
+import { last } from 'lodash-es'
+
+export function createQuery (json, queryOptions) {
+ console.log('createQuery', queryOptions)
+
+ const { filter, sort, projection } = queryOptions
+ const queryParts = []
+
+ if (filter) {
+ // Note that the comparisons embrace type coercion,
+ // so a filter value like '5' (text) will match numbers like 5 too.
+ const getActualValue = filter.field.length > 0
+ ? `item => _.get(item, ${JSON.stringify(filter.field)})`
+ : 'item => item'
+ queryParts.push(` data = data.filter(${getActualValue} ${filter.relation} '${filter.value}')\n`)
+ }
+
+ if (sort) {
+ // The '@' field name is a special case,
+ // which means that the field itself is selected.
+ // For example when we have an array containing numbers.
+ if (sort.field !== '@') {
+ queryParts.push(` data = _.orderBy(data, '${sort.field}', '${sort.direction}')\n`)
+ } else {
+ queryParts.push(` data = _.sortBy(data, '${sort.direction}')\n`)
+ }
+ }
+
+ if (projection) {
+ // It is possible to make a util function "pickFlat"
+ // and use that when building the query to make it more readable.
+ if (projection.fields.length > 1) {
+ const fields = projection.fields.map(field => {
+ const name = last(field)
+ return ` ${JSON.stringify(name)}: _.get(item, ${JSON.stringify(field)})`
+ })
+ queryParts.push(` data = data.map(item => ({\n${fields.join(',\n')}})\n )\n`)
+ } else {
+ const field = projection.fields[0]
+ queryParts.push(` data = data.map(item => _.get(item, ${JSON.stringify(field)}))\n`)
+ }
+ }
+
+ queryParts.push(' return data\n')
+
+ return `function query (data) {\n${queryParts.join('')}}`
+}