@zeit/cosmosdb-query
Advanced tools
Comparing version 0.0.8 to 0.0.9
// | ||
exports.AVG = (a ) => exports.SUM(a) / a.length; | ||
exports.AVG = (a ) => { | ||
if ( | ||
!a.length || | ||
a.some(v => typeof v !== "number" && typeof v !== "undefined") | ||
) { | ||
return undefined; | ||
} | ||
const aa = a.filter(v => typeof v === "number"); | ||
const sum = exports.SUM(aa); | ||
return typeof sum !== "undefined" ? sum / aa.length : undefined; | ||
}; | ||
exports.COUNT = (a ) => a.filter(v => typeof v !== "undefined").length; | ||
exports.MAX = (a ) => Math.max(...a); | ||
exports.MAX = (a ) => { | ||
if (!a.length || a.some(v => v && typeof v === "object")) { | ||
return undefined; | ||
} | ||
exports.MIN = (a ) => Math.min(...a); | ||
return a | ||
.filter(v => typeof v === "number" || typeof v === "string") | ||
.reduce((max, v) => { | ||
if (typeof max === "undefined") return v; | ||
return max > v ? max : v; | ||
}, undefined); | ||
}; | ||
exports.SUM = (a ) => a.reduce((s, n) => s + n, 0); | ||
exports.MIN = (a ) => { | ||
if (!a.length || a.some(v => typeof v !== "number")) { | ||
return undefined; | ||
} | ||
return Math.min(...a); | ||
}; | ||
exports.SUM = (a ) => | ||
a.reduce((s, n) => { | ||
if (typeof n === "undefined") return s; | ||
return typeof n === "number" ? s + n : undefined; | ||
}, 0); |
// | ||
const ifDefined = f => (...a ) => | ||
a.every(v => typeof v !== "undefined") ? f(...a) : undefined; | ||
const typeOf = (v ) => { | ||
const t = typeof v; | ||
if (t !== "object") return t; | ||
if (v === null) return "null"; | ||
return Array.isArray(v) ? "array" : t; | ||
}; | ||
exports.ABS = ifDefined((v ) => Math.abs(v)); | ||
const def = (name , argTypes , f) => { | ||
const lastType = argTypes[argTypes.length - 1]; | ||
const variableType = lastType && lastType.variable ? lastType : null; | ||
const types = (variableType ? argTypes.slice(0, -1) : argTypes).map( | ||
t => (typeof t === "string" ? { type: t, optional: false } : t) | ||
); | ||
const requiredTypes = types.filter(t => !t.optional); | ||
const isVariable = variableType || requiredTypes.length !== types.length; | ||
exports.ACOS = ifDefined((v ) => Math.acos(v)); | ||
return function fn(...a ) { | ||
if ( | ||
isVariable | ||
? a.length < requiredTypes.length | ||
: a.length !== requiredTypes.length | ||
) { | ||
throw new Error( | ||
`The ${name} function requires ${isVariable ? "at least " : ""}${ | ||
requiredTypes.length | ||
} argument(s)` | ||
); | ||
} | ||
if ( | ||
!types.every( | ||
(t, i) => | ||
t.type === "any" || | ||
typeOf(a[i]) === t.type || | ||
(typeOf(a[i]) === "undefined" && t.optional) | ||
) | ||
) { | ||
return undefined; | ||
} | ||
if ( | ||
variableType && | ||
variableType.type !== "any" && | ||
!a.slice(types.length).every(v => typeOf(v) === variableType.type) | ||
) { | ||
return undefined; | ||
} | ||
return f(...a); | ||
}; | ||
}; | ||
exports.ARRAY_CONCAT = ifDefined((...a ) => | ||
a.reduce((b, c) => [...b, ...c], []) | ||
const deepEqual = (a , b , partial ) => { | ||
const typeOfA = typeOf(a); | ||
const typeOfB = typeOf(b); | ||
if (typeOfA === "array" && typeOfB === "array") { | ||
if ((a ).length !== (b ).length) return false; | ||
return a.every((v, i) => deepEqual(v, b[i], partial)); | ||
} | ||
if (typeOfA === "object" && typeOfB === "object") { | ||
const aEntries = Object.entries(a); | ||
const bEntries = Object.entries(b); | ||
if (!partial && aEntries.length !== bEntries.length) return false; | ||
return bEntries.every(([k, v]) => deepEqual(a[k], v, partial)); | ||
} | ||
return a === b; | ||
}; | ||
exports.ABS = def("ABS", ["number"], (v ) => Math.abs(v)); | ||
exports.ACOS = def("ACOS", ["number"], (v ) => Math.acos(v)); | ||
exports.ARRAY_CONCAT = def( | ||
"ARRAY_CONCAT", | ||
["array", "array", { type: "array", variable: true }], | ||
(...a ) => a.reduce((b, c) => [...b, ...c], []) | ||
); | ||
exports.ARRAY_CONTAINS = ifDefined((a , c ) => | ||
a.some( | ||
i => | ||
exports.IS_OBJECT(c) ? Object.keys(c).every(k => i[k] === c[k]) : i === c | ||
) | ||
exports.ARRAY_CONTAINS = def( | ||
"ARRAY_CONTAINS", | ||
["array", "any", { type: "boolean", optional: true }], | ||
(a , c , partial = false) => | ||
a.some(v => deepEqual(v, c, partial)) | ||
); | ||
exports.ARRAY_LENGTH = ifDefined((a ) => a.length); | ||
exports.ARRAY_LENGTH = def("ARRAY_LENGTH", ["array"], (a ) => a.length); | ||
exports.ARRAY_SLICE = ifDefined((a , b , c ) => | ||
// $FlowFixMe | ||
a.slice(b, c != null ? b + c : undefined) | ||
exports.ARRAY_SLICE = def( | ||
"ARRAY_SLICE", | ||
["array", "number", { type: "number", optional: true }], | ||
(a , b , c ) => | ||
// $FlowFixMe | ||
a.slice(b, c != null ? b + c : undefined) | ||
); | ||
exports.ASIN = ifDefined((v ) => Math.asin(v)); | ||
exports.ASIN = def("ASIN", ["number"], (v ) => Math.asin(v)); | ||
exports.ATAN = ifDefined((v ) => Math.atan(v)); | ||
exports.ATAN = def("ATAN", ["number"], (v ) => Math.atan(v)); | ||
exports.ATN2 = ifDefined((a , b ) => Math.atan2(b, a)); | ||
exports.ATN2 = def("ASN2", ["number", "number"], (a , b ) => | ||
Math.atan2(b, a) | ||
); | ||
exports.CEILING = ifDefined((v ) => Math.ceil(v)); | ||
exports.CEILING = def("CEILING", ["number"], (v ) => Math.ceil(v)); | ||
exports.CONCAT = ifDefined((...a ) => a.join("")); | ||
exports.CONCAT = def( | ||
"CONCAT", | ||
["string", "string", { type: "string", variable: true }], | ||
(...a ) => a.join("") | ||
); | ||
exports.CONTAINS = ifDefined((a , b ) => a.includes(b)); | ||
exports.CONTAINS = def( | ||
"CONTAINS", | ||
["string", "string"], | ||
(a , b ) => a.includes(b) | ||
); | ||
exports.COS = ifDefined((v ) => Math.cos(v)); | ||
exports.COS = def("COS", ["number"], (v ) => Math.cos(v)); | ||
exports.COT = ifDefined((v ) => 1 / Math.tan(v)); | ||
exports.COT = def("COT", ["number"], (v ) => 1 / Math.tan(v)); | ||
exports.DEGREES = ifDefined((v ) => (v * 180) / Math.PI); | ||
exports.DEGREES = def( | ||
"DEGREES", | ||
["number"], | ||
(v ) => (v * 180) / Math.PI | ||
); | ||
exports.ENDSWITH = ifDefined((a , b ) => a.endsWith(b)); | ||
exports.ENDSWITH = def( | ||
"ENDSWITH", | ||
["string", "string"], | ||
(a , b ) => a.endsWith(b) | ||
); | ||
exports.EXP = ifDefined((v ) => Math.exp(v)); | ||
exports.EXP = def("EXP", ["number"], (v ) => Math.exp(v)); | ||
exports.FLOOR = ifDefined((v ) => Math.floor(v)); | ||
exports.FLOOR = def("FLOOR", ["number"], (v ) => Math.floor(v)); | ||
exports.INDEX_OF = ifDefined((a , b ) => a.indexOf(b)); | ||
exports.INDEX_OF = def( | ||
"INDEX_OF", | ||
["string", "string"], | ||
(a , b ) => a.indexOf(b) | ||
); | ||
exports.IS_ARRAY = (v ) => Array.isArray(v); | ||
exports.IS_ARRAY = def("IS_ARRAY", ["any"], (v ) => Array.isArray(v)); | ||
exports.IS_BOOL = (v ) => typeof v === "boolean"; | ||
exports.IS_BOOL = def("IS_BOOL", ["any"], (v ) => typeof v === "boolean"); | ||
exports.IS_DEFINED = (v ) => typeof v !== "undefined"; | ||
exports.IS_DEFINED = def( | ||
"IS_DEFINED", | ||
["any"], | ||
(v ) => typeof v !== "undefined" | ||
); | ||
exports.IS_NULL = (v ) => v === null; | ||
exports.IS_NULL = def("IS_NULL", ["any"], (v ) => v === null); | ||
exports.IS_NUMBER = (v ) => typeof v === "number"; | ||
exports.IS_NUMBER = def( | ||
"IS_NUMBER", | ||
["any"], | ||
(v ) => typeof v === "number" | ||
); | ||
exports.IS_OBJECT = (v ) => | ||
Boolean(v) && typeof v === "object" && !Array.isArray(v); | ||
exports.IS_OBJECT = def( | ||
"IS_OBJECT", | ||
["any"], | ||
(v ) => Boolean(v) && typeof v === "object" && !Array.isArray(v) | ||
); | ||
exports.IS_PRIMITIVE = (v ) => | ||
exports.IS_NULL(v) || | ||
exports.IS_NUMBER(v) || | ||
exports.IS_STRING(v) || | ||
exports.IS_BOOL(v); | ||
exports.IS_PRIMITIVE = def( | ||
"IS_PRIMITIVE", | ||
["any"], | ||
(v ) => | ||
exports.IS_NULL(v) || | ||
exports.IS_NUMBER(v) || | ||
exports.IS_STRING(v) || | ||
exports.IS_BOOL(v) | ||
); | ||
exports.IS_STRING = (v ) => typeof v === "string"; | ||
exports.IS_STRING = def( | ||
"IS_STRING", | ||
["any"], | ||
(v ) => typeof v === "string" | ||
); | ||
exports.LEFT = ifDefined((a , b ) => a.slice(0, b)); | ||
exports.LEFT = def("LEFT", ["string", "number"], (a , b ) => | ||
a.slice(0, b) | ||
); | ||
exports.LENGTH = ifDefined((v ) => v.length); | ||
exports.LENGTH = def("LENGTH", ["string"], (v ) => v.length); | ||
exports.LOG = ifDefined((v ) => Math.log(v)); | ||
exports.LOG = def("LOG", ["number"], (v ) => Math.log(v)); | ||
exports.LOG10 = ifDefined((v ) => Math.log10(v)); | ||
exports.LOG10 = def("LOG10", ["number"], (v ) => Math.log10(v)); | ||
exports.LOWER = ifDefined((v ) => v.toLowerCase()); | ||
exports.LOWER = def("LOWER", ["string"], (v ) => v.toLowerCase()); | ||
exports.LTRIM = ifDefined((v ) => v.trimLeft()); | ||
exports.LTRIM = def("LTRIM", ["string"], (v ) => v.trimLeft()); | ||
exports.PI = () => Math.PI; | ||
exports.PI = def("PI", [], () => Math.PI); | ||
exports.POWER = ifDefined((a , b ) => a ** b); | ||
exports.POWER = def( | ||
"POWER", | ||
["number", "number"], | ||
(a , b ) => a ** b | ||
); | ||
exports.RADIANS = ifDefined((v ) => (v * Math.PI) / 180); | ||
exports.RADIANS = def( | ||
"RADIANS", | ||
["number"], | ||
(v ) => (v * Math.PI) / 180 | ||
); | ||
exports.REPLACE = ifDefined((a , b , c ) => | ||
a.replace(b, c) | ||
exports.REPLACE = def( | ||
"REPLACE", | ||
["string", "string", "string"], | ||
(a , b , c ) => a.replace(b, c) | ||
); | ||
exports.REPLICATE = ifDefined((a , b ) => a.repeat(b)); | ||
exports.REPLICATE = def( | ||
"REPLICATE", | ||
["string", "number"], | ||
(a , b ) => a.repeat(b) | ||
); | ||
exports.REVERSE = ifDefined((v ) => | ||
exports.REVERSE = def("REVERSE", ["string"], (v ) => | ||
v | ||
@@ -106,30 +233,48 @@ .split("") | ||
exports.RIGHT = ifDefined((a , b ) => a.slice(-b)); | ||
exports.RIGHT = def("RIGHT", ["string", "number"], (a , b ) => | ||
a.slice(-b) | ||
); | ||
exports.ROUND = ifDefined((v ) => Math.round(v)); | ||
exports.ROUND = def("ROUND", ["number"], (v ) => Math.round(v)); | ||
exports.RTRIM = ifDefined((v ) => v.trimRight()); | ||
exports.RTRIM = def("RTRIM", ["string"], (v ) => v.trimRight()); | ||
exports.SIGN = ifDefined((v ) => Math.sign(v)); | ||
exports.SIGN = def("SIGN", ["number"], (v ) => Math.sign(v)); | ||
exports.SIN = ifDefined((v ) => Math.sin(v)); | ||
exports.SIN = def("SIN", ["number"], (v ) => Math.sin(v)); | ||
exports.SQRT = ifDefined((v ) => Math.sqrt(v)); | ||
exports.SQRT = def("SQRT", ["number"], (v ) => Math.sqrt(v)); | ||
exports.SQUARE = ifDefined((v ) => v ** 2); | ||
exports.SQUARE = def("SQUARE", ["number"], (v ) => v ** 2); | ||
exports.STARTSWITH = ifDefined((a , b ) => a.startsWith(b)); | ||
exports.STARTSWITH = def( | ||
"STARTSWITH", | ||
["string", "string"], | ||
(a , b ) => a.startsWith(b) | ||
); | ||
exports.SUBSTRING = ifDefined((a , b , c ) => | ||
a.substring(b, c != null ? b + c : undefined) | ||
exports.SUBSTRING = def( | ||
"SUBSTRING", | ||
["string", "number", { type: "number", optional: true }], | ||
(a , b , c ) => | ||
a.substring(b, c != null ? b + c : undefined) | ||
); | ||
exports.TAN = ifDefined((v ) => Math.tan(v)); | ||
exports.TAN = def("TAN", ["number"], (v ) => Math.tan(v)); | ||
exports.ToString = ifDefined((v ) => String(v)); | ||
exports.TOSTRING = def("ToString", ["any"], (v ) => { | ||
const t = typeOf(v); | ||
if (t === "undefined") { | ||
return undefined; | ||
} | ||
if (t === "object" || t === "array") { | ||
JSON.stringify(v); | ||
} | ||
return String(v); | ||
}); | ||
exports.TRIM = ifDefined((v ) => v.trim()); | ||
exports.TRIM = def("TRIM", ["string"], (v ) => v.trim()); | ||
exports.TRUNC = ifDefined((v ) => Math.trunc(v)); | ||
exports.TRUNC = def("TRUNC", ["number"], (v ) => Math.trunc(v)); | ||
exports.UPPER = ifDefined((v ) => v.toUpperCase()); | ||
exports.UPPER = def("UPPER", ["string"], (v ) => v.toUpperCase()); |
// | ||
const aggregateFunctions = require("./aggregate-functions"); | ||
const builtinFunctions = require("./builtin-functions"); | ||
const helpers = require("./helpers"); | ||
function removeUndefined(obj) { | ||
if (Array.isArray(obj)) { | ||
// remove `undefined` from array unlike JSON | ||
return obj.reduce( | ||
(o, v) => (typeof v !== "undefined" ? [...o, removeUndefined(v)] : o), | ||
[] | ||
); | ||
} | ||
if (obj && typeof obj === "object") { | ||
return Object.entries(obj).reduce((o, [k, v]) => { | ||
if (typeof v !== "undefined") { | ||
// eslint-disable-next-line no-param-reassign | ||
o[k] = removeUndefined(v); | ||
} | ||
return o; | ||
}, {}); | ||
} | ||
return obj; | ||
} | ||
module.exports = ( | ||
@@ -43,9 +22,9 @@ collection , | ||
// $FlowFixMe | ||
const result = execute( | ||
return execute( | ||
aggregateFunctions, | ||
builtinFunctions, | ||
collection, | ||
helpers, | ||
params | ||
); | ||
return result.map(removeUndefined); | ||
}; |
@@ -34,2 +34,6 @@ // | ||
const { code } = this; | ||
if (!code) { | ||
throw new Error("Missing code"); | ||
} | ||
return execute(coll, { code, parameters }); | ||
@@ -36,0 +40,0 @@ } |
@@ -5,6 +5,2 @@ // | ||
const jsEqualityOperators = new Set(["===", "!==", "==", "!="]); | ||
const jsRelationalOperators = new Set([">", "<", ">=", "<="]); | ||
const jsAndOrOperators = new Set(["&&", "||"]); | ||
function transform(ctx , node ) { | ||
@@ -20,6 +16,2 @@ // eslint-disable-next-line no-use-before-define | ||
function clone(node) { | ||
return JSON.parse(JSON.stringify(node)); | ||
} | ||
function isAggregateFunction({ type, name, udf }) { | ||
@@ -37,13 +29,3 @@ return ( | ||
function strictTrue(node) { | ||
if ( | ||
node.type === "BinaryExpression" && | ||
(jsAndOrOperators.has(node.operator) || | ||
jsEqualityOperators.has(node.operator) || | ||
jsRelationalOperators.has(node.operator)) | ||
) | ||
return node; | ||
if (node.type === "UnaryExpression" && node.operator === "!") return node; | ||
if (node.type === "BooleanLiteral" && node.value === true) return node; | ||
function strictTrueNode(node) { | ||
return { | ||
@@ -60,2 +42,37 @@ type: "BinaryExpression", | ||
function isNotUndefinedNode(argument) { | ||
return { | ||
type: "BinaryExpression", | ||
left: { | ||
type: "UnaryExpression", | ||
operator: "typeof", | ||
prefix: true, | ||
argument | ||
}, | ||
operator: "!==", | ||
right: { | ||
type: "StringLiteral", | ||
value: "undefined" | ||
} | ||
}; | ||
} | ||
function callHelperNode(name, ...args) { | ||
return { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: { | ||
type: "Identifier", | ||
name: "$h" | ||
}, | ||
property: { | ||
type: "Identifier", | ||
name | ||
} | ||
}, | ||
arguments: args | ||
}; | ||
} | ||
const definitions = { | ||
@@ -103,4 +120,4 @@ array_constant(ctx, { elements }) { | ||
type: "ArrowFunctionExpression", | ||
params: [ctx.document], | ||
body: strictTrue(transform(ctx, condition)) | ||
params: ctx.document ? [ctx.document] : [], | ||
body: strictTrueNode(transform(ctx, condition)) | ||
} | ||
@@ -116,120 +133,142 @@ ] | ||
from_specification(ctx, { source, joins }) { | ||
ctx.document = transform(ctx, source); | ||
const exp = transform(ctx, source.expression); | ||
return [source, ...(joins || [])].reduce( | ||
(object, { expression, alias, iteration }) => { | ||
const exp = transform(ctx, expression); | ||
const node = alias ? transform(ctx, alias) : exp; | ||
const nameNode = node.property || node; | ||
let arg; | ||
traverse( | ||
{ type: "Program", body: [exp] }, | ||
{ | ||
MemberExpression(path) { | ||
const { object } = path.node; | ||
if (object.type === "Identifier") { | ||
arg = object; | ||
path.stop(); | ||
if (!ctx.document) { | ||
if (exp.type !== "MemberExpression") { | ||
ctx.document = exp; | ||
} else { | ||
traverse( | ||
{ type: "Program", body: [exp] }, | ||
{ | ||
MemberExpression(path) { | ||
const { object: o } = path.node; | ||
if (o.type === "Identifier") { | ||
ctx.document = o; | ||
path.stop(); | ||
} | ||
} | ||
} | ||
); | ||
} | ||
} | ||
} | ||
); | ||
let object; | ||
if (source.iteration) { | ||
// e.g, "FROM c IN Families.children" | ||
// collection.reduce(($, Families) => [...$, ...Families.children], []) | ||
object = { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: ctx.ast, | ||
property: { | ||
type: "Identifier", | ||
name: "reduce" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [{ type: "Identifier", name: "$" }, arg], | ||
body: { | ||
type: "ArrayExpression", | ||
elements: [ | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
}, | ||
{ | ||
type: "SpreadElement", | ||
argument: exp | ||
} | ||
] | ||
const { document } = ctx; | ||
ctx.document = { | ||
type: "ObjectPattern", | ||
properties: [ | ||
...(document.type === "ObjectPattern" ? document.properties : []), | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: nameNode, | ||
value: nameNode | ||
} | ||
}, | ||
{ | ||
type: "ArrayExpression", | ||
elements: [] | ||
} | ||
] | ||
}; | ||
} else if (exp.type === "MemberExpression") { | ||
object = { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: ctx.ast, | ||
property: { | ||
type: "Identifier", | ||
name: "map" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [arg], | ||
body: exp | ||
} | ||
] | ||
}; | ||
} else { | ||
object = ctx.ast; | ||
} | ||
] | ||
}; | ||
return (joins || []).reduce((obj, { expression, alias, iteration }) => { | ||
const node = transform(ctx, alias || expression); | ||
const nameNode = alias ? node : node.property; | ||
const { document } = ctx; | ||
ctx.document = { | ||
type: "ObjectPattern", | ||
properties: [ | ||
...(document.type === "ObjectPattern" | ||
? document.properties | ||
: [ | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: document, | ||
value: document | ||
if (iteration) { | ||
// e.g, | ||
// FROM Families f | ||
// JOIN c IN f.children | ||
// JOIN p IN c.pets | ||
// | ||
// collection | ||
// .reduce(($, Families) => [...$, { f: Families }], []) | ||
// .reduce(($, { f }) => [...$, ...(f.children || []).map(c => ({ c, f }))], []) | ||
// .reduce(($, { f, c }) => [...$, ...(c.pets || []).map(p => ({ c, f, p }))], []) | ||
return { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object, | ||
property: { | ||
type: "Identifier", | ||
name: "reduce" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [{ type: "Identifier", name: "$" }, document], | ||
body: { | ||
type: "ArrayExpression", | ||
elements: [ | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
}, | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: { | ||
type: "LogicalExpression", | ||
left: exp, | ||
operator: "||", | ||
right: { | ||
type: "ArrayExpression", | ||
elements: [] | ||
} | ||
}, | ||
property: { | ||
type: "Identifier", | ||
name: "map" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [nameNode], | ||
body: { | ||
type: "ObjectExpression", | ||
properties: [ | ||
...(document.type === "ObjectPattern" | ||
? document.properties | ||
: []), | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
key: nameNode, | ||
value: nameNode | ||
} | ||
] | ||
} | ||
} | ||
] | ||
} | ||
} | ||
] | ||
} | ||
]), | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: nameNode, | ||
value: nameNode | ||
} | ||
] | ||
}; | ||
}, | ||
{ | ||
type: "ArrayExpression", | ||
elements: [] | ||
} | ||
] | ||
}; | ||
} | ||
if (iteration) { | ||
// e.g, | ||
// FROM Families.children[0] c | ||
// | ||
// collection | ||
// .reduce(($, Families) => [...$, { c: Families.children[0] }], []) | ||
// | ||
// FROM Families f | ||
// JOIN c IN f.children | ||
// JOIN p IN c.pets | ||
// JOIN f.children | ||
// | ||
// collection | ||
// .reduce(($, f) => [...$, ...(f.children || []).map(c => ({ c, f }))], []) | ||
// .reduce(($, { f, c }) => [...$, ...(c.pets || []).map(p => ({ c, f, p }))], []) | ||
// .reduce(($, Families) => [...$, { f: Families }], []) | ||
// .reduce(($, f) => (typeof f.children !== 'undefined' ? [...$, { f, children: f.children }] : $), []) | ||
return { | ||
@@ -239,3 +278,3 @@ type: "CallExpression", | ||
type: "MemberExpression", | ||
object: obj, | ||
object, | ||
property: { | ||
@@ -251,63 +290,34 @@ type: "Identifier", | ||
body: { | ||
type: "ArrayExpression", | ||
elements: [ | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
}, | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: { | ||
type: "LogicalExpression", | ||
left: transform(ctx, expression), | ||
operator: "||", | ||
right: { | ||
type: "ArrayExpression", | ||
elements: [] | ||
} | ||
}, | ||
property: { | ||
type: "Identifier", | ||
name: "map" | ||
} | ||
}, | ||
arguments: [ | ||
type: "ConditionalExpression", | ||
test: isNotUndefinedNode(exp), | ||
consequent: { | ||
type: "ArrayExpression", | ||
elements: [ | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
}, | ||
{ | ||
type: "ObjectExpression", | ||
properties: [ | ||
...(document.type === "ObjectPattern" | ||
? document.properties | ||
: []), | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [nameNode], | ||
body: { | ||
type: "ObjectExpression", | ||
properties: [ | ||
...(document.type === "ObjectPattern" | ||
? document.properties | ||
: [ | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: document, | ||
value: document | ||
} | ||
]), | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: nameNode, | ||
value: nameNode | ||
} | ||
] | ||
} | ||
type: "ObjectProperty", | ||
computed: false, | ||
key: nameNode, | ||
value: exp | ||
} | ||
] | ||
} | ||
} | ||
] | ||
] | ||
}, | ||
alternate: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
} | ||
@@ -321,88 +331,5 @@ }, | ||
}; | ||
} | ||
// e.g, | ||
// FROM Families f | ||
// JOIN f.children | ||
// | ||
// collection | ||
// .reduce(($, f) => (typeof f.children !== 'undefined' ? [...$, { f, children: f.children }] : $), []) | ||
return { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: obj, | ||
property: { | ||
type: "Identifier", | ||
name: "reduce" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [{ type: "Identifier", name: "$" }, document], | ||
body: { | ||
type: "ConditionalExpression", | ||
test: { | ||
type: "BinaryExpression", | ||
left: { | ||
type: "UnaryExpression", | ||
operator: "typeof", | ||
prefix: true, | ||
argument: node | ||
}, | ||
operator: "!==", | ||
right: { | ||
type: "StringLiteral", | ||
value: "undefined" | ||
} | ||
}, | ||
consequent: { | ||
type: "ArrayExpression", | ||
elements: [ | ||
{ | ||
type: "SpreadElement", | ||
argument: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
}, | ||
{ | ||
type: "ObjectExpression", | ||
properties: [ | ||
...(document.type === "ObjectPattern" | ||
? document.properties | ||
: [ | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: document, | ||
value: document | ||
} | ||
]), | ||
{ | ||
type: "ObjectProperty", | ||
computed: false, | ||
shorthand: true, | ||
key: nameNode, | ||
value: node | ||
} | ||
] | ||
} | ||
] | ||
}, | ||
alternate: { | ||
type: "Identifier", | ||
name: "$" | ||
} | ||
} | ||
}, | ||
{ | ||
type: "ArrayExpression", | ||
elements: [] | ||
} | ||
] | ||
}; | ||
}, object); | ||
}, | ||
ctx.ast | ||
); | ||
}, | ||
@@ -506,16 +433,3 @@ | ||
type: "ConditionalExpression", | ||
test: { | ||
type: "BinaryExpression", | ||
left: { | ||
type: "UnaryExpression", | ||
operator: "typeof", | ||
prefix: true, | ||
argument: l | ||
}, | ||
operator: "!==", | ||
right: { | ||
type: "StringLiteral", | ||
value: "undefined" | ||
} | ||
}, | ||
test: isNotUndefinedNode(l), | ||
consequent: l, | ||
@@ -526,19 +440,43 @@ alternate: r | ||
const op = | ||
if (operator === "AND") { | ||
return callHelperNode("and", l, r); | ||
} | ||
if (operator === "OR") { | ||
return callHelperNode("or", l, r); | ||
} | ||
if (operator === "=") { | ||
return callHelperNode("equal", l, r); | ||
} | ||
if (operator === "!=" || operator === "<>") { | ||
return callHelperNode("notEqual", l, r); | ||
} | ||
if ( | ||
operator === ">" || | ||
operator === "<" || | ||
operator === ">=" || | ||
operator === "<=" | ||
) { | ||
return callHelperNode( | ||
"compare", | ||
{ | ||
type: "StringLiteral", | ||
value: operator | ||
}, | ||
l, | ||
r | ||
); | ||
} | ||
if (operator === "||") { | ||
return callHelperNode("concat", l, r); | ||
} | ||
return callHelperNode( | ||
"calculate", | ||
{ | ||
"=": "===", | ||
"!=": "!==", | ||
"<>": "!==", | ||
"||": "+", | ||
AND: "&&", | ||
OR: "||" | ||
}[operator] || operator; | ||
const mustStrictTrue = operator === "AND" || operator === "OR"; | ||
return { | ||
type: "BinaryExpression", | ||
left: mustStrictTrue ? strictTrue(l) : l, | ||
operator: op, | ||
right: mustStrictTrue ? strictTrue(r) : r | ||
}; | ||
type: "StringLiteral", | ||
value: operator | ||
}, | ||
l, | ||
r | ||
); | ||
}, | ||
@@ -549,3 +487,3 @@ | ||
type: "ConditionalExpression", | ||
test: transform(ctx, test), | ||
test: strictTrueNode(transform(ctx, test)), | ||
consequent: transform(ctx, consequent), | ||
@@ -560,2 +498,5 @@ alternate: transform(ctx, alternate) | ||
const f = transform(ctx, name); | ||
f.name = f.name.toUpperCase(); | ||
return { | ||
@@ -570,3 +511,3 @@ type: "CallExpression", | ||
}, | ||
property: transform(ctx, name) | ||
property: f | ||
}, | ||
@@ -638,17 +579,23 @@ arguments: aggregation | ||
scalar_unary_expression(ctx, { operator, argument }) { | ||
const op = operator === "NOT" ? "!" : operator; | ||
return { | ||
type: "UnaryExpression", | ||
operator: op, | ||
argument: transform(ctx, argument) | ||
}; | ||
const node = transform(ctx, argument); | ||
if (operator === "NOT") { | ||
return callHelperNode("not", node); | ||
} | ||
return callHelperNode( | ||
"calculateUnary", | ||
{ | ||
type: "StringLiteral", | ||
value: operator | ||
}, | ||
node | ||
); | ||
}, | ||
select_query(ctx, { top, select, from, where, orderBy }) { | ||
const name = "$c"; | ||
if (from) { | ||
ctx.ast = { | ||
type: "Identifier", | ||
name | ||
name: "$c" | ||
}; | ||
@@ -697,4 +644,9 @@ ctx.ast = transform(ctx, from); | ||
type: "Identifier", | ||
name | ||
name: "$c" | ||
}, | ||
// helper functions | ||
{ | ||
type: "Identifier", | ||
name: "$h" | ||
}, | ||
// parameters | ||
@@ -711,3 +663,3 @@ { | ||
], | ||
body: ctx.ast | ||
body: callHelperNode("stripUndefined", ctx.ast) | ||
}; | ||
@@ -718,3 +670,24 @@ }, | ||
if (all) { | ||
return ctx.ast; | ||
if (ctx.document.properties > 1) { | ||
throw new Error("'SELECT *' is only valid with a single input set."); | ||
} | ||
return { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: ctx.ast, | ||
property: { | ||
type: "Identifier", | ||
name: "map" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [ctx.document], | ||
body: ctx.document.properties[0] | ||
} | ||
] | ||
}; | ||
} | ||
@@ -771,52 +744,14 @@ | ||
sort_specification(ctx, { expressions }) { | ||
return { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: ctx.ast, | ||
property: { | ||
type: "Identifier", | ||
name: "slice" | ||
} | ||
}, | ||
arguments: [] | ||
}, | ||
property: { | ||
type: "Identifier", | ||
name: "sort" | ||
} | ||
}, | ||
arguments: [ | ||
{ | ||
type: "ArrowFunctionExpression", | ||
params: [ | ||
{ type: "Identifier", name: "$1" }, | ||
{ type: "Identifier", name: "$2" } | ||
], | ||
body: expressions.reduce((left, right) => { | ||
if (left) { | ||
return { | ||
type: "LogicalExpression", | ||
left, | ||
operator: "||", | ||
right: transform(ctx, right) | ||
}; | ||
} | ||
return transform(ctx, right); | ||
}, null) | ||
} | ||
] | ||
}; | ||
return callHelperNode( | ||
"sort", | ||
ctx.ast, | ||
...expressions.map(e => transform(ctx, e)) | ||
); | ||
}, | ||
sort_expression(ctx, { expression, order }) { | ||
const left = transform(ctx, expression); | ||
const right = clone(left); | ||
const node = transform(ctx, expression); | ||
[["$1", left], ["$2", right]].forEach(([name, node]) => { | ||
const elements = []; | ||
if (node.type === "MemberExpression") { | ||
traverse( | ||
@@ -826,20 +761,12 @@ { type: "Program", body: [node] }, | ||
MemberExpression(path) { | ||
const { object } = path.node; | ||
if (object.type === "Identifier") { | ||
// eslint-disable-next-line no-param-reassign | ||
path.node.object = | ||
ctx.document.type === "ObjectPattern" | ||
? { | ||
type: "MemberExpression", | ||
object: { | ||
type: "Identifier", | ||
name | ||
}, | ||
property: object | ||
} | ||
: { | ||
type: "Identifier", | ||
name | ||
}; | ||
path.stop(); | ||
elements.unshift({ | ||
type: "StringLiteral", | ||
value: path.node.property.name | ||
}); | ||
if (path.node.object.type === "Identifier") { | ||
elements.unshift({ | ||
type: "StringLiteral", | ||
value: path.node.object.name | ||
}); | ||
} | ||
@@ -849,41 +776,17 @@ } | ||
); | ||
}); | ||
} | ||
const ast = { | ||
type: "ConditionalExpression", | ||
test: { | ||
type: "MemberExpression", | ||
object: left, | ||
property: { | ||
type: "Identifier", | ||
name: "localeCompare" | ||
return { | ||
type: "ArrayExpression", | ||
elements: [ | ||
{ | ||
type: "ArrayExpression", | ||
elements | ||
}, | ||
{ | ||
type: "BooleanLiteral", | ||
value: order === "DESC" | ||
} | ||
}, | ||
consequent: { | ||
type: "CallExpression", | ||
callee: { | ||
type: "MemberExpression", | ||
object: left, | ||
property: { | ||
type: "Identifier", | ||
name: "localeCompare" | ||
} | ||
}, | ||
arguments: [right] | ||
}, | ||
alternate: { | ||
type: "BinaryExpression", | ||
left, | ||
operator: "-", | ||
right | ||
} | ||
] | ||
}; | ||
return order === "DESC" | ||
? { | ||
type: "UnaryExpression", | ||
operator: "-", | ||
argument: ast | ||
} | ||
: ast; | ||
}, | ||
@@ -890,0 +793,0 @@ |
{ | ||
"name": "@zeit/cosmosdb-query", | ||
"version": "0.0.8", | ||
"version": "0.0.9", | ||
"license": "UNLICENSED", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
199896
11
7020