"use strict"; const assureArray = require("assure-array"); const assert = require("assert"); // moreThan, lessThan, equals, not, where, select, insert, update (set), delete, collapse, collapseBy, count, parameter module.exports = { insertInto: function (collection, clauses) { return { type: "insert", collection: collection, clauses: assureArray(clauses) }; }, update: function (collection, clauses) { return { type: "insert", collection: collection, clauses: assureArray(clauses) }; }, selectFrom: function (collection, clauses) { return { type: "select", collection: collection, clauses: assureArray(clauses) }; }, deleteFrom: function (collection, clauses) { return { type: "delete", collection: collection, clauses: assureArray(clauses) }; }, moreThan: function (value) { return { type: "moreThan", value: value }; }, lessThan: function (value) { return { type: "lessThan", value: value }; }, equals: function (value) { return { type: "equals", value: value }; }, not: function (value) { return { type: "not", value: value }; }, where: function (conditions) { return { type: "where", conditions: conditions }; }, collapse: function (reducers) { return { type: "collapse", fields: null, reducers: reducers }; }, collapseBy: function (fields, reducers) { return { type: "collapse", fields: assureArray(fields), reducers: reducers }; }, item: function (item) { return { type: "items", items: [ item ] }; }, items: function (items) { return { type: "items", items: items }; }, set: function (properties) { return { type: "set", properties: properties }; }, anyOf: function (options) { return { type: "anyOf", options: options }; }, allOf: function (options) { return { type: "allOf", options: options }; }, parameter: function (name) { return { type: "parameter", name: name }; }, average: average, count: count, sum: sum }; function generateGetter(propertyPath) { assert(propertyPath != null); let segments = (Array.isArray(propertyPath)) ? propertyPath : propertyPath.split("."); let propertyGetters = segments .map((segment) => { // FIXME: Escape! // TODO: Can this be further optimized by using regular dot properties where safely possible? return `["${segment}"]`; }) .join(""); return new Function("item", ` return item${propertyGetters}; `); } function average(propertyPath) { let getter = generateGetter(propertyPath); return { onValue: (total, item, _i) => total + getter(item), onEnd: (total, count) => total / count }; } function count() { return (total) => total + 1; } function sum(propertyPath) { let getter = generateGetter(propertyPath); return (total, item, _i) => total + getter(item); }