@osqd/jql 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/conformance/cases.json +2 -0
- package/dist/chunk-2ZMIVDES.cjs +1661 -0
- package/dist/chunk-2ZMIVDES.cjs.map +1 -0
- package/dist/chunk-6PWYYYWU.js +1637 -0
- package/dist/chunk-6PWYYYWU.js.map +1 -0
- package/dist/chunk-74QKHM6Y.cjs +145 -0
- package/dist/chunk-74QKHM6Y.cjs.map +1 -0
- package/dist/chunk-ATRXHPBJ.js +112 -0
- package/dist/chunk-ATRXHPBJ.js.map +1 -0
- package/dist/chunk-EJFHVGBC.cjs +63 -0
- package/dist/chunk-EJFHVGBC.cjs.map +1 -0
- package/dist/chunk-ITPY6VTV.cjs +115 -0
- package/dist/chunk-ITPY6VTV.cjs.map +1 -0
- package/dist/chunk-JK6OYDLX.js +712 -0
- package/dist/chunk-JK6OYDLX.js.map +1 -0
- package/dist/chunk-N7DS4QNW.js +60 -0
- package/dist/chunk-N7DS4QNW.js.map +1 -0
- package/dist/chunk-PNBQ2HIJ.js +133 -0
- package/dist/chunk-PNBQ2HIJ.js.map +1 -0
- package/dist/chunk-VMFEQXBB.js +578 -0
- package/dist/chunk-VMFEQXBB.js.map +1 -0
- package/dist/cjs/text/index.d.ts +1 -1
- package/dist/cjs/text/parse.d.ts +2 -1
- package/dist/cjs/text/quote.d.ts +17 -0
- package/dist/cjs/text/suggest.d.ts +27 -5
- package/dist/cli.js +13 -2395
- package/dist/cli.js.map +1 -1
- package/dist/global.cjs +26 -1849
- package/dist/global.cjs.map +1 -1
- package/dist/global.js +8 -1831
- package/dist/global.js.map +1 -1
- package/dist/index.cjs +143 -1996
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -2493
- package/dist/index.js.map +1 -1
- package/dist/mongo.cjs +20 -119
- package/dist/mongo.cjs.map +1 -1
- package/dist/mongo.js +2 -101
- package/dist/mongo.js.map +1 -1
- package/dist/text/index.d.ts +1 -1
- package/dist/text/parse.d.ts +2 -1
- package/dist/text/quote.d.ts +17 -0
- package/dist/text/suggest.d.ts +27 -5
- package/dist/text.cjs +146 -101
- package/dist/text.cjs.map +1 -1
- package/dist/text.js +3 -665
- package/dist/text.js.map +1 -1
- package/docs/course/11-the-search-box.md +49 -2
- package/docs/course/16-extending.md +1 -1
- package/docs/reference/api.md +14 -1
- package/docs/reference/specification.md +9 -2
- package/docs/reference/text-syntax.md +41 -6
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,1937 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* `$or[1].age.$gt`. Empty for the query as a whole.
|
|
8
|
-
*/
|
|
9
|
-
at;
|
|
10
|
-
constructor(message, at = "") {
|
|
11
|
-
super(at === "" ? message : `at ${show(at)}: ${message}`);
|
|
12
|
-
this.name = "JqlError";
|
|
13
|
-
this.at = at;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
function show(at) {
|
|
17
|
-
return at.length > 80 ? `${at.slice(0, 80)}\u2026` : at;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// src/internal/closest.ts
|
|
21
|
-
function closest(word, candidates) {
|
|
22
|
-
let best;
|
|
23
|
-
let bestDistance = 3;
|
|
24
|
-
for (const candidate of candidates) {
|
|
25
|
-
const distance = editDistance(word.toLowerCase(), candidate.toLowerCase(), bestDistance);
|
|
26
|
-
if (distance < bestDistance) {
|
|
27
|
-
best = candidate;
|
|
28
|
-
bestDistance = distance;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return best;
|
|
32
|
-
}
|
|
33
|
-
function editDistance(a, b, ceiling) {
|
|
34
|
-
if (Math.abs(a.length - b.length) >= ceiling) return ceiling;
|
|
35
|
-
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
36
|
-
for (let i = 1; i <= a.length; i++) {
|
|
37
|
-
const current = [i];
|
|
38
|
-
let rowBest = i;
|
|
39
|
-
for (let j = 1; j <= b.length; j++) {
|
|
40
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
41
|
-
const value = Math.min(previous[j] + 1, current[j - 1] + 1, previous[j - 1] + cost);
|
|
42
|
-
current.push(value);
|
|
43
|
-
if (value < rowBest) rowBest = value;
|
|
44
|
-
}
|
|
45
|
-
if (rowBest >= ceiling) return ceiling;
|
|
46
|
-
previous = current;
|
|
47
|
-
}
|
|
48
|
-
return previous[b.length];
|
|
49
|
-
}
|
|
50
|
-
function didYouMean(word, candidates) {
|
|
51
|
-
const guess = closest(word, candidates);
|
|
52
|
-
return guess === void 0 ? "" : `; did you mean "${guess}"?`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/internal/path.ts
|
|
56
|
-
var FANOUT = /* @__PURE__ */ Symbol("jql.fanout");
|
|
57
|
-
var INDEX = /^(?:0|[1-9]\d{0,8})$/;
|
|
58
|
-
var INHERITED = /* @__PURE__ */ new Set([...Object.getOwnPropertyNames(Object.prototype), ...Object.getOwnPropertyNames(Map.prototype), "__proto__"]);
|
|
59
|
-
function needsGuard(key) {
|
|
60
|
-
return INHERITED.has(key);
|
|
61
|
-
}
|
|
62
|
-
var PLAIN = Object.prototype;
|
|
63
|
-
function segment(key) {
|
|
64
|
-
return { key, index: INDEX.test(key) ? Number(key) : -1 };
|
|
65
|
-
}
|
|
66
|
-
function readOwn(value, key) {
|
|
67
|
-
if (value instanceof Map) return value.get(key);
|
|
68
|
-
return Object.hasOwn(value, key) ? value[key] : void 0;
|
|
69
|
-
}
|
|
70
|
-
function readOne(value, step) {
|
|
71
|
-
return readOwn(value, step.key);
|
|
72
|
-
}
|
|
73
|
-
var readSelf = (document) => document;
|
|
74
|
-
function reachPath(keys) {
|
|
75
|
-
const steps = keys.map(segment);
|
|
76
|
-
return (document, test) => {
|
|
77
|
-
let value = document;
|
|
78
|
-
for (let at = 0; at < steps.length; at++) {
|
|
79
|
-
if (value === null || typeof value !== "object") return test(void 0);
|
|
80
|
-
if (Array.isArray(value)) return walk(value, steps, at, test);
|
|
81
|
-
value = readOne(value, steps[at]);
|
|
82
|
-
}
|
|
83
|
-
return test(value);
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
function probePath(keys) {
|
|
87
|
-
const steps = keys.map(segment);
|
|
88
|
-
const last = steps.length - 1;
|
|
89
|
-
const [first, second] = steps;
|
|
90
|
-
if (steps.length === 1 && first.index === -1) {
|
|
91
|
-
const only = first.key;
|
|
92
|
-
const guarded = needsGuard(only);
|
|
93
|
-
return (document) => {
|
|
94
|
-
if (document === null || typeof document !== "object") return void 0;
|
|
95
|
-
if (Array.isArray(document)) return FANOUT;
|
|
96
|
-
if (!guarded && document.__proto__ === PLAIN) return document[only];
|
|
97
|
-
return readOwn(document, only);
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
if (steps.length === 2 && first.index === -1 && second.index === -1) {
|
|
101
|
-
const outer = first.key;
|
|
102
|
-
const inner = second.key;
|
|
103
|
-
const outerGuarded = needsGuard(outer);
|
|
104
|
-
const innerGuarded = needsGuard(inner);
|
|
105
|
-
return (document) => {
|
|
106
|
-
if (document === null || typeof document !== "object") return void 0;
|
|
107
|
-
if (Array.isArray(document)) return FANOUT;
|
|
108
|
-
const value = !outerGuarded && document.__proto__ === PLAIN ? document[outer] : readOwn(document, outer);
|
|
109
|
-
if (value === null || typeof value !== "object") return void 0;
|
|
110
|
-
if (Array.isArray(value)) return FANOUT;
|
|
111
|
-
return !innerGuarded && value.__proto__ === PLAIN ? value[inner] : readOwn(value, inner);
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return (document) => {
|
|
115
|
-
let value = document;
|
|
116
|
-
for (let at = 0; at <= last; at++) {
|
|
117
|
-
if (value === null || typeof value !== "object") return void 0;
|
|
118
|
-
if (Array.isArray(value) && steps[at].index === -1) return FANOUT;
|
|
119
|
-
const step = steps[at];
|
|
120
|
-
value = Array.isArray(value) ? value[step.index] : readOwn(value, step.key);
|
|
121
|
-
}
|
|
122
|
-
return value;
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
function probeFrom(read, keys) {
|
|
126
|
-
const probe = probePath(keys);
|
|
127
|
-
return (document) => probe(read(document));
|
|
128
|
-
}
|
|
129
|
-
function reachFrom(read, keys) {
|
|
130
|
-
const steps = keys.map(segment);
|
|
131
|
-
return (document, test) => walk(read(document), steps, 0, test);
|
|
132
|
-
}
|
|
133
|
-
var MAX_DOCUMENT_DEPTH = 512;
|
|
134
|
-
function walk(value, steps, at, test, depth = 0) {
|
|
135
|
-
if (at === steps.length) return test(value);
|
|
136
|
-
if (value === null || typeof value !== "object" || depth > MAX_DOCUMENT_DEPTH) return test(void 0);
|
|
137
|
-
const step = steps[at];
|
|
138
|
-
if (Array.isArray(value)) {
|
|
139
|
-
if (step.index !== -1) return walk(value[step.index], steps, at + 1, test, depth + 1);
|
|
140
|
-
if (value.length === 0) return test(void 0);
|
|
141
|
-
for (let i = 0; i < value.length; i++) if (walk(value[i], steps, at, test, depth + 1)) return true;
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
return walk(readOne(value, step), steps, at + 1, test, depth + 1);
|
|
145
|
-
}
|
|
146
|
-
var MAX_PATH_SEGMENTS = 512;
|
|
147
|
-
function splitPath(path) {
|
|
148
|
-
if (path === "") return "an empty field name reaches nothing";
|
|
149
|
-
const keys = path.split(".");
|
|
150
|
-
if (keys.length > MAX_PATH_SEGMENTS) {
|
|
151
|
-
return `the path has ${keys.length} segments, past the limit of ${MAX_PATH_SEGMENTS}; nothing nests that deep`;
|
|
152
|
-
}
|
|
153
|
-
for (const key of keys) if (key === "") return `the path "${path.length > 80 ? `${path.slice(0, 80)}\u2026` : path}" has an empty segment, which reaches nothing`;
|
|
154
|
-
return keys;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// src/internal/duration.ts
|
|
158
|
-
var PART = /(\d+)(ms|s|m|h|d|w)/g;
|
|
159
|
-
var SHAPE = /^(?:\d+(?:ms|s|m|h|d|w))+$/;
|
|
160
|
-
var UNITS = {
|
|
161
|
-
ms: 1,
|
|
162
|
-
s: 1e3,
|
|
163
|
-
m: 6e4,
|
|
164
|
-
h: 36e5,
|
|
165
|
-
d: 864e5,
|
|
166
|
-
w: 6048e5
|
|
167
|
-
};
|
|
168
|
-
var DURATION_UNITS = Object.keys(UNITS);
|
|
169
|
-
function parseDuration(text2) {
|
|
170
|
-
if (!SHAPE.test(text2)) return void 0;
|
|
171
|
-
let total = 0;
|
|
172
|
-
PART.lastIndex = 0;
|
|
173
|
-
for (; ; ) {
|
|
174
|
-
const part = PART.exec(text2);
|
|
175
|
-
if (part === null) break;
|
|
176
|
-
const count4 = Number(part[1]);
|
|
177
|
-
if (!Number.isSafeInteger(count4)) return void 0;
|
|
178
|
-
total += count4 * UNITS[part[2]];
|
|
179
|
-
}
|
|
180
|
-
return Number.isSafeInteger(total) ? total : void 0;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// src/internal/values.ts
|
|
184
|
-
function isPlainObject(value) {
|
|
185
|
-
if (value === null || typeof value !== "object") return false;
|
|
186
|
-
const prototype = Object.getPrototypeOf(value);
|
|
187
|
-
return prototype === Object.prototype || prototype === null;
|
|
188
|
-
}
|
|
189
|
-
function isDateLiteral(value) {
|
|
190
|
-
if (!isPlainObject(value) || !("$date" in value)) return false;
|
|
191
|
-
for (const key in value) if (key !== "$date") return false;
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
function isFieldReference(value) {
|
|
195
|
-
if (!isPlainObject(value) || typeof value.$field !== "string") return false;
|
|
196
|
-
for (const key in value) if (key !== "$field") return false;
|
|
197
|
-
return true;
|
|
198
|
-
}
|
|
199
|
-
function resolveDate(value, now) {
|
|
200
|
-
if (typeof value === "number") return value;
|
|
201
|
-
if (typeof value === "string") return value === "now" ? now : instant(value);
|
|
202
|
-
if (isPlainObject(value)) {
|
|
203
|
-
const keys = Object.keys(value);
|
|
204
|
-
if (keys.length !== 1) return Number.NaN;
|
|
205
|
-
const amount = keys[0] === "$ago" || keys[0] === "$ahead" ? value[keys[0]] : void 0;
|
|
206
|
-
if (typeof amount !== "string") return Number.NaN;
|
|
207
|
-
const span = parseDuration(amount);
|
|
208
|
-
if (span === void 0) return Number.NaN;
|
|
209
|
-
return keys[0] === "$ago" ? now - span : now + span;
|
|
210
|
-
}
|
|
211
|
-
return Number.NaN;
|
|
212
|
-
}
|
|
213
|
-
var ISO_8601 = /^\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
|
|
214
|
-
var NO_OFFSET = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?)$/;
|
|
215
|
-
function instant(text2) {
|
|
216
|
-
const bare = NO_OFFSET.exec(text2);
|
|
217
|
-
return bare === null ? Date.parse(text2) : Date.parse(`${bare[1]}T${bare[2]}Z`);
|
|
218
|
-
}
|
|
219
|
-
function toTime(value) {
|
|
220
|
-
if (typeof value === "number") return value;
|
|
221
|
-
if (value instanceof Date) return value.getTime();
|
|
222
|
-
if (typeof value === "string") return ISO_8601.test(value) ? instant(value) : Number.NaN;
|
|
223
|
-
return Number.NaN;
|
|
224
|
-
}
|
|
225
|
-
var TYPE_NAMES = ["string", "number", "integer", "bigint", "boolean", "null", "array", "object", "date"];
|
|
226
|
-
function isOfType(value, type) {
|
|
227
|
-
switch (type) {
|
|
228
|
-
case "string":
|
|
229
|
-
return typeof value === "string";
|
|
230
|
-
case "number":
|
|
231
|
-
return typeof value === "number" || typeof value === "bigint";
|
|
232
|
-
case "integer":
|
|
233
|
-
return Number.isInteger(value) || typeof value === "bigint";
|
|
234
|
-
case "bigint":
|
|
235
|
-
return typeof value === "bigint";
|
|
236
|
-
case "boolean":
|
|
237
|
-
return typeof value === "boolean";
|
|
238
|
-
case "null":
|
|
239
|
-
return value === null;
|
|
240
|
-
case "array":
|
|
241
|
-
return Array.isArray(value);
|
|
242
|
-
case "date":
|
|
243
|
-
return value instanceof Date;
|
|
244
|
-
case "object":
|
|
245
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
function describe(value) {
|
|
249
|
-
if (value === null) return "null";
|
|
250
|
-
if (typeof value === "function") return "a function";
|
|
251
|
-
if (Array.isArray(value)) return "an array";
|
|
252
|
-
if (value instanceof RegExp) return "a RegExp object";
|
|
253
|
-
if (value instanceof Date) return "a Date object";
|
|
254
|
-
if (value instanceof Map) return "a Map";
|
|
255
|
-
if (value instanceof Set) return "a Set";
|
|
256
|
-
if (typeof value === "object") {
|
|
257
|
-
if (isPlainObject(value)) return "an object";
|
|
258
|
-
const name = nameOf(value);
|
|
259
|
-
return name === void 0 ? "an object" : `an instance of ${name}`;
|
|
260
|
-
}
|
|
261
|
-
if (typeof value === "string") return `the string ${JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}\u2026` : value)}`;
|
|
262
|
-
return `${typeof value} ${String(value)}`;
|
|
263
|
-
}
|
|
264
|
-
function nameOf(value) {
|
|
265
|
-
const prototype = Object.getPrototypeOf(value);
|
|
266
|
-
const name = prototype?.constructor?.name;
|
|
267
|
-
return typeof name === "string" && name !== "" && name !== "Object" ? name : void 0;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// src/limits.ts
|
|
271
|
-
var DEFAULT_LIMITS = Object.freeze({
|
|
272
|
-
maxDepth: 32,
|
|
273
|
-
maxNodes: 1e4,
|
|
274
|
-
maxPatternLength: 1024,
|
|
275
|
-
maxGlobLength: 1024,
|
|
276
|
-
maxTextDepth: 16,
|
|
277
|
-
allowRegex: true,
|
|
278
|
-
allowOperators: "all"
|
|
279
|
-
});
|
|
280
|
-
var UNTRUSTED_LIMITS = Object.freeze({
|
|
281
|
-
maxDepth: 16,
|
|
282
|
-
maxNodes: 512,
|
|
283
|
-
maxPatternLength: 0,
|
|
284
|
-
maxGlobLength: 256,
|
|
285
|
-
maxTextDepth: 8,
|
|
286
|
-
allowRegex: false,
|
|
287
|
-
// Still every operator but `$regex`: which of the rest an endpoint wants is a decision
|
|
288
|
-
// only that endpoint can make, and a list guessed here would be one nobody had chosen.
|
|
289
|
-
allowOperators: "all"
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// src/internal/equal.ts
|
|
293
|
-
function sameInteger(a, b) {
|
|
294
|
-
const big = typeof a === "bigint" ? a : typeof b === "bigint" ? b : void 0;
|
|
295
|
-
const other = typeof a === "bigint" ? b : a;
|
|
296
|
-
if (big === void 0) return false;
|
|
297
|
-
if (typeof other === "bigint") return big === other;
|
|
298
|
-
return typeof other === "number" && Number.isInteger(other) && big === BigInt(other);
|
|
299
|
-
}
|
|
300
|
-
var MAX_EQUAL_DEPTH = 64;
|
|
301
|
-
function alsoBig(literal2) {
|
|
302
|
-
return typeof literal2 === "number" && Number.isInteger(literal2) ? BigInt(literal2) : void 0;
|
|
303
|
-
}
|
|
304
|
-
function equalsLiteral(literal2, now, ignoreCase = false) {
|
|
305
|
-
if (literal2 === null) return (value) => value === null;
|
|
306
|
-
if (typeof literal2 !== "object") {
|
|
307
|
-
if (ignoreCase && typeof literal2 === "string") {
|
|
308
|
-
const wanted = literal2.toLowerCase();
|
|
309
|
-
return (value) => typeof value === "string" && value.toLowerCase() === wanted;
|
|
310
|
-
}
|
|
311
|
-
const big = alsoBig(literal2);
|
|
312
|
-
if (big !== void 0) return (value) => value === literal2 || value === big;
|
|
313
|
-
return (value) => value === literal2;
|
|
314
|
-
}
|
|
315
|
-
if (isDateLiteral(literal2)) {
|
|
316
|
-
const time = resolveDate(literal2.$date, now);
|
|
317
|
-
return (value) => toTime(value) === time;
|
|
318
|
-
}
|
|
319
|
-
return (value) => deepEqual(value, literal2, 0, ignoreCase, now);
|
|
320
|
-
}
|
|
321
|
-
function valuesEqual(a, b) {
|
|
322
|
-
if (a === void 0 || b === void 0) return false;
|
|
323
|
-
if (a instanceof Date || b instanceof Date) {
|
|
324
|
-
const left = toTime(a);
|
|
325
|
-
const right = toTime(b);
|
|
326
|
-
return a instanceof Date && b instanceof Date && left === right && !Number.isNaN(left);
|
|
327
|
-
}
|
|
328
|
-
return deepEqual(a, b, 0);
|
|
329
|
-
}
|
|
330
|
-
function deepEqual(actual, wanted, depth, ignoreCase = false, now = 0) {
|
|
331
|
-
if (actual === wanted) return true;
|
|
332
|
-
if (typeof actual === "bigint" || typeof wanted === "bigint") return sameInteger(actual, wanted);
|
|
333
|
-
if (actual instanceof Date && wanted instanceof Date) return actual.getTime() === wanted.getTime();
|
|
334
|
-
if (depth > MAX_EQUAL_DEPTH) return false;
|
|
335
|
-
if (ignoreCase && typeof actual === "string" && typeof wanted === "string") return actual.toLowerCase() === wanted.toLowerCase();
|
|
336
|
-
if (wanted === null || typeof wanted !== "object") return false;
|
|
337
|
-
if (isDateLiteral(wanted)) return toTime(actual) === resolveDate(wanted.$date, now);
|
|
338
|
-
if (actual === null || typeof actual !== "object") return false;
|
|
339
|
-
if (Array.isArray(wanted)) {
|
|
340
|
-
if (!Array.isArray(actual) || actual.length !== wanted.length) return false;
|
|
341
|
-
for (let i = 0; i < wanted.length; i++) if (!deepEqual(actual[i], wanted[i], depth + 1, ignoreCase, now)) return false;
|
|
342
|
-
return true;
|
|
343
|
-
}
|
|
344
|
-
if (Array.isArray(actual) || !isPlainObject(wanted)) return false;
|
|
345
|
-
if (actual instanceof Map) {
|
|
346
|
-
let size2 = 0;
|
|
347
|
-
for (const key in wanted) {
|
|
348
|
-
const expected = wanted[key];
|
|
349
|
-
if (expected === void 0) continue;
|
|
350
|
-
size2++;
|
|
351
|
-
if (!actual.has(key) || !deepEqual(actual.get(key), expected, depth + 1, ignoreCase, now)) return false;
|
|
352
|
-
}
|
|
353
|
-
let present2 = 0;
|
|
354
|
-
for (const value of actual.values()) if (value !== void 0) present2++;
|
|
355
|
-
return present2 === size2;
|
|
356
|
-
}
|
|
357
|
-
const record = actual;
|
|
358
|
-
let size = 0;
|
|
359
|
-
for (const key in wanted) {
|
|
360
|
-
const expected = wanted[key];
|
|
361
|
-
if (expected === void 0) continue;
|
|
362
|
-
size++;
|
|
363
|
-
if (!Object.hasOwn(record, key) || !deepEqual(record[key], expected, depth + 1, ignoreCase, now)) return false;
|
|
364
|
-
}
|
|
365
|
-
let present = 0;
|
|
366
|
-
for (const key in record) if (Object.hasOwn(record, key) && record[key] !== void 0) present++;
|
|
367
|
-
return present === size;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// src/internal/glob.ts
|
|
371
|
-
var ANY = { any: true };
|
|
372
|
-
var ONE = { one: true };
|
|
373
|
-
function compileGlob(pattern) {
|
|
374
|
-
const tokens = tokenize(pattern);
|
|
375
|
-
const stars = tokens.includes(ANY);
|
|
376
|
-
const questions = tokens.includes(ONE);
|
|
377
|
-
if (!stars && !questions) {
|
|
378
|
-
const literal2 = tokens.join("");
|
|
379
|
-
return (text2) => text2 === literal2;
|
|
380
|
-
}
|
|
381
|
-
if (!questions) {
|
|
382
|
-
const segments = [""];
|
|
383
|
-
for (const token of tokens) {
|
|
384
|
-
if (token === ANY) segments.push("");
|
|
385
|
-
else segments[segments.length - 1] += token;
|
|
386
|
-
}
|
|
387
|
-
const open = segments[0] === "";
|
|
388
|
-
const close = segments[segments.length - 1] === "";
|
|
389
|
-
const parts = segments.filter((segment2) => segment2 !== "");
|
|
390
|
-
if (parts.length === 0) return () => true;
|
|
391
|
-
if (open && close && parts.length === 1) {
|
|
392
|
-
const inside = parts[0];
|
|
393
|
-
return (text2) => text2.includes(inside);
|
|
394
|
-
}
|
|
395
|
-
if (!open && close && parts.length === 1) {
|
|
396
|
-
const prefix = parts[0];
|
|
397
|
-
return (text2) => text2.startsWith(prefix);
|
|
398
|
-
}
|
|
399
|
-
if (open && !close && parts.length === 1) {
|
|
400
|
-
const suffix = parts[0];
|
|
401
|
-
return (text2) => text2.endsWith(suffix);
|
|
402
|
-
}
|
|
403
|
-
return (text2) => scan(text2, parts, open, close);
|
|
404
|
-
}
|
|
405
|
-
return (text2) => walk2([...text2], tokens);
|
|
406
|
-
}
|
|
407
|
-
function tokenize(pattern) {
|
|
408
|
-
const tokens = [];
|
|
409
|
-
let escaped = false;
|
|
410
|
-
for (const character of pattern) {
|
|
411
|
-
if (escaped) {
|
|
412
|
-
tokens.push(character);
|
|
413
|
-
escaped = false;
|
|
414
|
-
continue;
|
|
415
|
-
}
|
|
416
|
-
if (character === "\\") {
|
|
417
|
-
escaped = true;
|
|
418
|
-
continue;
|
|
419
|
-
}
|
|
420
|
-
if (character === "*") {
|
|
421
|
-
if (tokens[tokens.length - 1] !== ANY) tokens.push(ANY);
|
|
422
|
-
continue;
|
|
423
|
-
}
|
|
424
|
-
tokens.push(character === "?" ? ONE : character);
|
|
425
|
-
}
|
|
426
|
-
if (escaped) tokens.push("\\");
|
|
427
|
-
return tokens;
|
|
428
|
-
}
|
|
429
|
-
function scan(text2, parts, open, close) {
|
|
430
|
-
let at = 0;
|
|
431
|
-
const last = parts.length - 1;
|
|
432
|
-
for (let i = 0; i <= last; i++) {
|
|
433
|
-
const part = parts[i];
|
|
434
|
-
if (i === 0 && !open) {
|
|
435
|
-
if (!text2.startsWith(part)) return false;
|
|
436
|
-
at = part.length;
|
|
437
|
-
continue;
|
|
438
|
-
}
|
|
439
|
-
if (i === last && !close) {
|
|
440
|
-
return text2.length - part.length >= at && text2.endsWith(part);
|
|
441
|
-
}
|
|
442
|
-
const found = text2.indexOf(part, at);
|
|
443
|
-
if (found === -1) return false;
|
|
444
|
-
at = found + part.length;
|
|
445
|
-
}
|
|
446
|
-
return true;
|
|
447
|
-
}
|
|
448
|
-
function walk2(characters, tokens) {
|
|
449
|
-
let at = 0;
|
|
450
|
-
let token = 0;
|
|
451
|
-
let star = -1;
|
|
452
|
-
let mark = 0;
|
|
453
|
-
while (at < characters.length) {
|
|
454
|
-
const current = tokens[token];
|
|
455
|
-
if (current !== void 0 && (current === ONE || current === characters[at])) {
|
|
456
|
-
at++;
|
|
457
|
-
token++;
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
if (current === ANY) {
|
|
461
|
-
star = token++;
|
|
462
|
-
mark = at;
|
|
463
|
-
continue;
|
|
464
|
-
}
|
|
465
|
-
if (star !== -1) {
|
|
466
|
-
token = star + 1;
|
|
467
|
-
at = ++mark;
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
return false;
|
|
471
|
-
}
|
|
472
|
-
while (tokens[token] === ANY) token++;
|
|
473
|
-
return token === tokens.length;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// src/operators.ts
|
|
477
|
-
var NEVER = () => false;
|
|
478
|
-
function lower(value) {
|
|
479
|
-
return value.toLowerCase();
|
|
480
|
-
}
|
|
481
|
-
function equalsTest(literal2, ignoreCase, at, now) {
|
|
482
|
-
checkLiteral(literal2, at);
|
|
483
|
-
if (literal2 === null) return (value) => value === null || value === void 0;
|
|
484
|
-
return equalsLiteral(literal2, now, ignoreCase);
|
|
485
|
-
}
|
|
486
|
-
function inTest(list, ignoreCase, at, now) {
|
|
487
|
-
if (!Array.isArray(list)) throw new JqlError(`takes a list of values, not ${describe(list)}`, at);
|
|
488
|
-
if (list.length === 0) return NEVER;
|
|
489
|
-
const primitives = /* @__PURE__ */ new Set();
|
|
490
|
-
const complex = [];
|
|
491
|
-
let bigints;
|
|
492
|
-
let matchesMissing = false;
|
|
493
|
-
list.forEach((item, index) => {
|
|
494
|
-
checkLiteral(item, `${at}[${index}]`);
|
|
495
|
-
if (item === null) matchesMissing = true;
|
|
496
|
-
else if (typeof item === "object") complex.push(equalsLiteral(item, now, ignoreCase));
|
|
497
|
-
else {
|
|
498
|
-
primitives.add(ignoreCase && typeof item === "string" ? lower(item) : item);
|
|
499
|
-
const big = alsoBig(item);
|
|
500
|
-
if (big !== void 0) (bigints ??= /* @__PURE__ */ new Set()).add(big);
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
const fold2 = ignoreCase;
|
|
504
|
-
const whole = bigints;
|
|
505
|
-
return (value) => {
|
|
506
|
-
if (value === void 0 || value === null) return matchesMissing;
|
|
507
|
-
if (primitives.has(fold2 && typeof value === "string" ? lower(value) : value)) return true;
|
|
508
|
-
if (whole !== void 0 && typeof value === "bigint" && whole.has(value)) return true;
|
|
509
|
-
for (let i = 0; i < complex.length; i++) if (complex[i](value)) return true;
|
|
510
|
-
return false;
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
function orderTest(operator, bound, at, now) {
|
|
514
|
-
if (typeof bound === "number") {
|
|
515
|
-
if (Number.isNaN(bound)) throw new JqlError("NaN compares false with everything, so this would match nothing", at);
|
|
516
|
-
switch (operator) {
|
|
517
|
-
case "$gt":
|
|
518
|
-
return (value) => (typeof value === "number" || typeof value === "bigint") && value > bound;
|
|
519
|
-
case "$gte":
|
|
520
|
-
return (value) => (typeof value === "number" || typeof value === "bigint") && value >= bound;
|
|
521
|
-
case "$lt":
|
|
522
|
-
return (value) => (typeof value === "number" || typeof value === "bigint") && value < bound;
|
|
523
|
-
case "$lte":
|
|
524
|
-
return (value) => (typeof value === "number" || typeof value === "bigint") && value <= bound;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
if (typeof bound === "string") {
|
|
528
|
-
switch (operator) {
|
|
529
|
-
case "$gt":
|
|
530
|
-
return (value) => typeof value === "string" && value > bound;
|
|
531
|
-
case "$gte":
|
|
532
|
-
return (value) => typeof value === "string" && value >= bound;
|
|
533
|
-
case "$lt":
|
|
534
|
-
return (value) => typeof value === "string" && value < bound;
|
|
535
|
-
case "$lte":
|
|
536
|
-
return (value) => typeof value === "string" && value <= bound;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
if (isDateLiteral(bound)) {
|
|
540
|
-
const time = resolveDate(bound.$date, now);
|
|
541
|
-
if (Number.isNaN(time)) throw new JqlError(`${JSON.stringify(bound.$date)} is not a date, so every comparison with it would be false`, at);
|
|
542
|
-
switch (operator) {
|
|
543
|
-
case "$gt":
|
|
544
|
-
return (value) => value !== null && value !== void 0 && toTime(value) > time;
|
|
545
|
-
case "$gte":
|
|
546
|
-
return (value) => value !== null && value !== void 0 && toTime(value) >= time;
|
|
547
|
-
case "$lt":
|
|
548
|
-
return (value) => value !== null && value !== void 0 && toTime(value) < time;
|
|
549
|
-
case "$lte":
|
|
550
|
-
return (value) => value !== null && value !== void 0 && toTime(value) <= time;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
throw new JqlError(`compares with a number, a string, a {"$date": \u2026} or a {"$field": \u2026}, not ${describe(bound)}`, at);
|
|
554
|
-
}
|
|
555
|
-
function stringTest(operator, operand2, ignoreCase, at, maxGlobLength = Number.POSITIVE_INFINITY) {
|
|
556
|
-
const list = typeof operand2 === "string" ? [operand2] : operand2;
|
|
557
|
-
if (!Array.isArray(list)) throw new JqlError(`takes a string or a list of strings, not ${describe(operand2)}`, at);
|
|
558
|
-
if (list.length === 0) return NEVER;
|
|
559
|
-
const wanted = list.map((item, index) => {
|
|
560
|
-
if (typeof item !== "string") throw new JqlError(`takes strings, not ${describe(item)}`, `${at}[${index}]`);
|
|
561
|
-
return ignoreCase ? lower(item) : item;
|
|
562
|
-
});
|
|
563
|
-
if (operator === "$glob") {
|
|
564
|
-
for (const pattern of wanted) {
|
|
565
|
-
if (pattern.length > maxGlobLength) throw new JqlError(`the glob is ${pattern.length} characters, past the limit of ${maxGlobLength}`, at);
|
|
566
|
-
}
|
|
567
|
-
const globs = wanted.map(compileGlob);
|
|
568
|
-
if (globs.length === 1) {
|
|
569
|
-
const only = globs[0];
|
|
570
|
-
return ignoreCase ? (value) => typeof value === "string" && only(lower(value)) : (value) => typeof value === "string" && only(value);
|
|
571
|
-
}
|
|
572
|
-
return (value) => {
|
|
573
|
-
if (typeof value !== "string") return false;
|
|
574
|
-
const actual = ignoreCase ? lower(value) : value;
|
|
575
|
-
for (let i = 0; i < globs.length; i++) if (globs[i](actual)) return true;
|
|
576
|
-
return false;
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
const one = (actual, value) => {
|
|
580
|
-
switch (operator) {
|
|
581
|
-
case "$contains":
|
|
582
|
-
return actual.includes(value);
|
|
583
|
-
case "$startsWith":
|
|
584
|
-
return actual.startsWith(value);
|
|
585
|
-
case "$endsWith":
|
|
586
|
-
return actual.endsWith(value);
|
|
587
|
-
case "$word":
|
|
588
|
-
return containsWord(actual, value);
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
if (wanted.length === 1) {
|
|
592
|
-
const only = wanted[0];
|
|
593
|
-
if (operator === "$contains") return ignoreCase ? (value) => typeof value === "string" && lower(value).includes(only) : (value) => typeof value === "string" && value.includes(only);
|
|
594
|
-
return (value) => typeof value === "string" && one(ignoreCase ? lower(value) : value, only);
|
|
595
|
-
}
|
|
596
|
-
return (value) => {
|
|
597
|
-
if (typeof value !== "string") return false;
|
|
598
|
-
const actual = ignoreCase ? lower(value) : value;
|
|
599
|
-
for (let i = 0; i < wanted.length; i++) if (one(actual, wanted[i])) return true;
|
|
600
|
-
return false;
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
var ALPHANUMERIC = /[\p{L}\p{N}]/u;
|
|
604
|
-
function containsWord(actual, wanted) {
|
|
605
|
-
if (wanted === "") return false;
|
|
606
|
-
const characters = [...wanted];
|
|
607
|
-
const startsAlphanumeric = ALPHANUMERIC.test(characters[0]);
|
|
608
|
-
const endsAlphanumeric = ALPHANUMERIC.test(characters[characters.length - 1]);
|
|
609
|
-
let from = 0;
|
|
610
|
-
for (; ; ) {
|
|
611
|
-
const at = actual.indexOf(wanted, from);
|
|
612
|
-
if (at === -1) return false;
|
|
613
|
-
const end = at + wanted.length;
|
|
614
|
-
const startsClean = at === 0 || !startsAlphanumeric || !ALPHANUMERIC.test(before(actual, at));
|
|
615
|
-
const endsClean = end >= actual.length || !endsAlphanumeric || !ALPHANUMERIC.test(after(actual, end));
|
|
616
|
-
if (startsClean && endsClean) return true;
|
|
617
|
-
from = at + 1;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
function before(text2, at) {
|
|
621
|
-
const code = text2.charCodeAt(at - 1);
|
|
622
|
-
return code >= 56320 && code <= 57343 && at >= 2 ? text2.slice(at - 2, at) : text2[at - 1];
|
|
623
|
-
}
|
|
624
|
-
function after(text2, end) {
|
|
625
|
-
const code = text2.charCodeAt(end);
|
|
626
|
-
return code >= 55296 && code <= 56319 ? text2.slice(end, end + 2) : text2[end];
|
|
627
|
-
}
|
|
628
|
-
var OPTION_FLAGS = /* @__PURE__ */ new Set(["i", "m", "s", "u"]);
|
|
629
|
-
function parseOptions(options, at) {
|
|
630
|
-
if (typeof options !== "string") throw new JqlError(`takes a string of flags such as "i", not ${describe(options)}`, at);
|
|
631
|
-
for (const flag of options) {
|
|
632
|
-
if (!OPTION_FLAGS.has(flag)) {
|
|
633
|
-
const why = flag === "g" || flag === "y" ? ": it makes a pattern stateful, so it would match on every other document" : "";
|
|
634
|
-
throw new JqlError(`"${flag}" is not a flag this language takes (i, m, s, u)${why}`, at);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
if (new Set(options).size !== options.length) throw new JqlError(`"${options}" repeats a flag`, at);
|
|
638
|
-
return options;
|
|
639
|
-
}
|
|
640
|
-
function regexTest(pattern, flags, limits, at) {
|
|
641
|
-
if (!limits.allowRegex) throw new JqlError("patterns are turned off for this query; $contains, $startsWith, $endsWith and $word cover most of what one is for", at);
|
|
642
|
-
if (typeof pattern !== "string") throw new JqlError(`takes the pattern as a string, not ${describe(pattern)}`, at);
|
|
643
|
-
if (pattern.length > limits.maxPatternLength) throw new JqlError(`the pattern is ${pattern.length} characters, past the limit of ${limits.maxPatternLength}`, at);
|
|
644
|
-
let expression;
|
|
645
|
-
try {
|
|
646
|
-
expression = new RegExp(pattern, flags);
|
|
647
|
-
} catch (error) {
|
|
648
|
-
throw new JqlError(`the pattern does not compile: ${error instanceof Error ? error.message : String(error)}`, at);
|
|
649
|
-
}
|
|
650
|
-
return (value) => typeof value === "string" && expression.test(value);
|
|
651
|
-
}
|
|
652
|
-
function typeTest(operand2, at) {
|
|
653
|
-
const list = typeof operand2 === "string" ? [operand2] : operand2;
|
|
654
|
-
if (!Array.isArray(list) || list.length === 0) throw new JqlError(`takes a type name or a non-empty list of them, not ${describe(operand2)}`, at);
|
|
655
|
-
const types = list.map((name, index) => {
|
|
656
|
-
if (typeof name !== "string" || !TYPE_NAMES.includes(name)) {
|
|
657
|
-
throw new JqlError(`${describe(name)} is not a type name (${TYPE_NAMES.join(", ")})${typeof name === "string" ? didYouMean(name, TYPE_NAMES) : ""}`, `${at}[${index}]`);
|
|
658
|
-
}
|
|
659
|
-
return name;
|
|
660
|
-
});
|
|
661
|
-
if (types.length === 1) {
|
|
662
|
-
const only = types[0];
|
|
663
|
-
return (value) => isOfType(value, only);
|
|
664
|
-
}
|
|
665
|
-
return (value) => types.some((type) => isOfType(value, type));
|
|
666
|
-
}
|
|
667
|
-
function modTest(operand2, at) {
|
|
668
|
-
if (!Array.isArray(operand2) || operand2.length !== 2 || typeof operand2[0] !== "number" || typeof operand2[1] !== "number") {
|
|
669
|
-
throw new JqlError(`takes [divisor, remainder], not ${describe(operand2)}`, at);
|
|
670
|
-
}
|
|
671
|
-
const [divisor, remainder] = operand2;
|
|
672
|
-
if (divisor === 0 || !Number.isFinite(divisor)) throw new JqlError("a divisor of zero leaves no remainder to compare, so this would match nothing", at);
|
|
673
|
-
const big = Number.isInteger(divisor) ? BigInt(divisor) : void 0;
|
|
674
|
-
return (value) => {
|
|
675
|
-
if (typeof value === "number") return value % divisor === remainder;
|
|
676
|
-
if (typeof value === "bigint") return big !== void 0 && Number(value % big) === remainder;
|
|
677
|
-
return false;
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
function allTest(list, ignoreCase, at, now) {
|
|
681
|
-
if (!Array.isArray(list)) throw new JqlError(`takes a list of values, not ${describe(list)}`, at);
|
|
682
|
-
if (list.length === 0) return NEVER;
|
|
683
|
-
const tests = list.map((item, index) => {
|
|
684
|
-
if (isPlainObject(item) && Object.keys(item).some((key) => key.startsWith("$")) && !isDateLiteral(item)) {
|
|
685
|
-
throw new JqlError("takes values, not conditions; use $elemMatch inside $and for that", `${at}[${index}]`);
|
|
686
|
-
}
|
|
687
|
-
return equalsTest(item, ignoreCase, `${at}[${index}]`, now);
|
|
688
|
-
});
|
|
689
|
-
return (value) => {
|
|
690
|
-
for (const test of tests) {
|
|
691
|
-
if (test(value)) continue;
|
|
692
|
-
if (!Array.isArray(value)) return false;
|
|
693
|
-
let found = false;
|
|
694
|
-
for (let i = 0; i < value.length; i++) {
|
|
695
|
-
if (test(value[i])) {
|
|
696
|
-
found = true;
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
if (!found) return false;
|
|
701
|
-
}
|
|
702
|
-
return true;
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
function orderOf(a, b) {
|
|
706
|
-
if ((typeof a === "number" || typeof a === "bigint") && (typeof b === "number" || typeof b === "bigint")) {
|
|
707
|
-
if (Number.isNaN(a) || Number.isNaN(b)) return void 0;
|
|
708
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
709
|
-
}
|
|
710
|
-
if (typeof a === "string" && typeof b === "string") return a < b ? -1 : a > b ? 1 : 0;
|
|
711
|
-
if (a instanceof Date && b instanceof Date) {
|
|
712
|
-
const left = a.getTime();
|
|
713
|
-
const right = b.getTime();
|
|
714
|
-
return Number.isNaN(left) || Number.isNaN(right) ? void 0 : left - right;
|
|
715
|
-
}
|
|
716
|
-
return void 0;
|
|
717
|
-
}
|
|
718
|
-
function checkLiteral(value, at, depth = 0) {
|
|
719
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") return;
|
|
720
|
-
if (typeof value === "number") {
|
|
721
|
-
if (!Number.isFinite(value)) throw new JqlError(`${String(value)} is not a JSON number`, at);
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
if (depth > 64) throw new JqlError("the literal nests deeper than 64 levels", at);
|
|
725
|
-
if (Array.isArray(value)) {
|
|
726
|
-
value.forEach((item, index) => checkLiteral(item, `${at}[${index}]`, depth + 1));
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
if (isPlainObject(value)) {
|
|
730
|
-
if (isFieldReference(value)) {
|
|
731
|
-
throw new JqlError(
|
|
732
|
-
`a {"$field": \u2026} reference compares with another field, which $eq, $ne and the ordering operators do; it is not a value that can be held here`,
|
|
733
|
-
at
|
|
734
|
-
);
|
|
735
|
-
}
|
|
736
|
-
if (isDateLiteral(value)) {
|
|
737
|
-
const date = value.$date;
|
|
738
|
-
if (Number.isNaN(resolveDate(date, 0))) {
|
|
739
|
-
const relative = isPlainObject(date) ? `; a relative date is {"$ago": "1h"} or {"$ahead": "1h"}, with a count and one of ${DURATION_UNITS.join(", ")}` : "";
|
|
740
|
-
throw new JqlError(`${JSON.stringify(date)} is not a date${relative}`, `${at}.$date`);
|
|
741
|
-
}
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
for (const key in value) checkLiteral(value[key], `${at}.${key}`, depth + 1);
|
|
745
|
-
return;
|
|
746
|
-
}
|
|
747
|
-
const hint = value instanceof RegExp ? '; write {"$regex": "\u2026"} instead' : value instanceof Date ? '; write {"$date": "\u2026"} instead' : "";
|
|
748
|
-
throw new JqlError(`${describe(value)} is not JSON, so a query holding it could not be stored or sent${hint}`, at);
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// src/vocabulary.ts
|
|
752
|
-
var BAD_NAME = /^\$|\./;
|
|
753
|
-
function defineVocabulary() {
|
|
754
|
-
return (definition) => build(definition);
|
|
755
|
-
}
|
|
756
|
-
function checkVocabulary(value, at = "vocabulary") {
|
|
757
|
-
if (value === void 0 || value !== null && typeof value === "object" && value.lookup instanceof Map) return value;
|
|
758
|
-
throw new JqlError(
|
|
759
|
-
`is not a vocabulary, but ${describe(value)}: build one with defineVocabulary()({ fields: \u2026 }) \u2014 the empty parentheses first \u2014 and pass what that returns`,
|
|
760
|
-
at
|
|
761
|
-
);
|
|
762
|
-
}
|
|
763
|
-
function build(definition) {
|
|
764
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
765
|
-
const fields = [];
|
|
766
|
-
const claim = (name, field) => {
|
|
767
|
-
const key = name.toLowerCase();
|
|
768
|
-
if (name === "" || BAD_NAME.test(name)) throw new JqlError(`"${name}" cannot name a field: a field name is not empty, does not start with "$" and has no "."`, "vocabulary");
|
|
769
|
-
const holder = lookup.get(key);
|
|
770
|
-
if (holder !== void 0) {
|
|
771
|
-
throw new JqlError(`"${name}" names both "${holder.name}" and "${field.name}", so a query using it could mean either`, "vocabulary");
|
|
772
|
-
}
|
|
773
|
-
lookup.set(key, field);
|
|
774
|
-
};
|
|
775
|
-
for (const [name, spec] of Object.entries(definition.fields)) {
|
|
776
|
-
if (spec.path !== void 0 && spec.get !== void 0) {
|
|
777
|
-
throw new JqlError(`"${name}" has both a path and a getter; one of them would be ignored, so say which`, `vocabulary.${name}`);
|
|
778
|
-
}
|
|
779
|
-
if (spec.path === "") throw new JqlError(`"${name}" has an empty path, which reaches nothing`, `vocabulary.${name}`);
|
|
780
|
-
const field = {
|
|
781
|
-
name,
|
|
782
|
-
kind: spec.kind ?? "text",
|
|
783
|
-
path: spec.path ?? name,
|
|
784
|
-
get: spec.get,
|
|
785
|
-
aliases: spec.aliases ?? [],
|
|
786
|
-
values: spec.values
|
|
787
|
-
};
|
|
788
|
-
fields.push(field);
|
|
789
|
-
claim(name, field);
|
|
790
|
-
for (const alias of field.aliases) claim(alias, field);
|
|
791
|
-
}
|
|
792
|
-
if (definition.text !== void 0) {
|
|
793
|
-
for (const name of definition.text) {
|
|
794
|
-
if (!lookup.has(name.toLowerCase())) throw new JqlError(`the text field "${name}" is not a field of this vocabulary, so a bare word would never search it`, "vocabulary.text");
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
return {
|
|
798
|
-
lookup,
|
|
799
|
-
fields,
|
|
800
|
-
names: [...lookup.keys()].sort(),
|
|
801
|
-
text: definition.text,
|
|
802
|
-
strict: definition.strict ?? false
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
// src/core.ts
|
|
807
|
-
var EXTENSION_NAME = /^\$x[A-Z][A-Za-z0-9]*$/;
|
|
808
|
-
var ALWAYS = { test: () => true, cost: 0 };
|
|
809
|
-
var NOTHING = { test: () => false, cost: 0 };
|
|
810
|
-
var QUERY_OPERATORS = ["$and", "$or", "$nor", "$not", "$text", "$comment"];
|
|
811
|
-
var FIELD_OPERATORS = [
|
|
812
|
-
"$eq",
|
|
813
|
-
"$ne",
|
|
814
|
-
"$gt",
|
|
815
|
-
"$gte",
|
|
816
|
-
"$lt",
|
|
817
|
-
"$lte",
|
|
818
|
-
"$in",
|
|
819
|
-
"$nin",
|
|
820
|
-
"$exists",
|
|
821
|
-
"$type",
|
|
822
|
-
"$contains",
|
|
823
|
-
"$startsWith",
|
|
824
|
-
"$endsWith",
|
|
825
|
-
"$word",
|
|
826
|
-
"$glob",
|
|
827
|
-
"$regex",
|
|
828
|
-
"$options",
|
|
829
|
-
"$mod",
|
|
830
|
-
"$size",
|
|
831
|
-
"$length",
|
|
832
|
-
"$all",
|
|
833
|
-
"$elemMatch",
|
|
834
|
-
"$not"
|
|
835
|
-
];
|
|
836
|
-
var FIELD_OPERATOR_SET = new Set(FIELD_OPERATORS);
|
|
837
|
-
var EVERY_OPERATOR = [.../* @__PURE__ */ new Set([...QUERY_OPERATORS, ...FIELD_OPERATORS])];
|
|
838
|
-
var CASE_AWARE = /* @__PURE__ */ new Set(["$eq", "$ne", "$in", "$nin", "$all", "$contains", "$startsWith", "$endsWith", "$word", "$glob", "$regex"]);
|
|
839
|
-
function compile(query, options = {}) {
|
|
840
|
-
if (typeof query === "function") return query;
|
|
841
|
-
const limits = options.limits === void 0 ? DEFAULT_LIMITS : { ...DEFAULT_LIMITS, ...options.limits };
|
|
842
|
-
const added = extensions(options.operators);
|
|
843
|
-
const context = {
|
|
844
|
-
vocabulary: checkVocabulary(options.vocabulary),
|
|
845
|
-
limits,
|
|
846
|
-
now: options.now === void 0 ? Date.now() : options.now(),
|
|
847
|
-
operators: added,
|
|
848
|
-
allowed: allowlist(limits.allowOperators, added),
|
|
849
|
-
nodes: 0
|
|
850
|
-
};
|
|
851
|
-
const { test } = compileQuery(query, context, "", 0);
|
|
852
|
-
if (test === ALWAYS.test) return () => true;
|
|
853
|
-
if (test === NOTHING.test) return () => false;
|
|
854
|
-
return test;
|
|
855
|
-
}
|
|
856
|
-
function matches(value, query, options) {
|
|
857
|
-
return compile(query, options)(value);
|
|
858
|
-
}
|
|
859
|
-
function validate(query, options) {
|
|
860
|
-
try {
|
|
861
|
-
return { valid: true, test: compile(query, options) };
|
|
862
|
-
} catch (error) {
|
|
863
|
-
if (error instanceof JqlError) return { valid: false, error };
|
|
864
|
-
throw error;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
function untyped(query) {
|
|
868
|
-
return query;
|
|
869
|
-
}
|
|
870
|
-
function reachField(name, vocabulary, at) {
|
|
871
|
-
return resolveField(name, { vocabulary}, at).reach;
|
|
872
|
-
}
|
|
873
|
-
var ALWAYS_ALLOWED = /* @__PURE__ */ new Set(["$options", "$comment"]);
|
|
874
|
-
var GATEABLE = /* @__PURE__ */ new Set([...FIELD_OPERATORS, ...QUERY_OPERATORS, "$field"]);
|
|
875
|
-
function allowlist(names, added) {
|
|
876
|
-
if (names === "all") return void 0;
|
|
877
|
-
if (!Array.isArray(names)) throw new JqlError(`is a list of operator names or "all", not ${describe(names)}`, "limits.allowOperators");
|
|
878
|
-
const out = /* @__PURE__ */ new Set();
|
|
879
|
-
for (const name of names) {
|
|
880
|
-
if (typeof name !== "string" || !GATEABLE.has(name) && !added.has(name)) {
|
|
881
|
-
throw new JqlError(`"${String(name)}" is not an operator, so allowing it allows nothing${typeof name === "string" ? didYouMean(name, [...GATEABLE]) : ""}`, "limits.allowOperators");
|
|
882
|
-
}
|
|
883
|
-
out.add(name);
|
|
884
|
-
}
|
|
885
|
-
return out;
|
|
886
|
-
}
|
|
887
|
-
function permit(key, context, at) {
|
|
888
|
-
const allowed = context.allowed;
|
|
889
|
-
if (allowed === void 0 || ALWAYS_ALLOWED.has(key) || allowed.has(key)) return;
|
|
890
|
-
const listed = [...allowed];
|
|
891
|
-
const shown = listed.length > 8 ? `${listed.slice(0, 8).join(", ")}, \u2026` : listed.join(", ");
|
|
892
|
-
throw new JqlError(`"${key}" is not an operator this query may use (${shown === "" ? "none" : shown})`, at);
|
|
893
|
-
}
|
|
894
|
-
var NO_EXTENSIONS = /* @__PURE__ */ new Map();
|
|
895
|
-
function extensions(given) {
|
|
896
|
-
if (given === void 0 || given.length === 0) return NO_EXTENSIONS;
|
|
897
|
-
const out = /* @__PURE__ */ new Map();
|
|
898
|
-
for (const definition of given) {
|
|
899
|
-
if (!EXTENSION_NAME.test(definition.name)) {
|
|
900
|
-
throw new JqlError(`"${definition.name}" cannot name an added operator: the name is $x and a capital, such as "$xCidr", so a query that needs more than standard JQL says so`, "operators");
|
|
901
|
-
}
|
|
902
|
-
if (out.has(definition.name)) throw new JqlError(`"${definition.name}" is given twice, and the two could not both be it`, "operators");
|
|
903
|
-
if (typeof definition.compile !== "function") throw new JqlError(`"${definition.name}" has no compile function, so there is nothing for it to do`, "operators");
|
|
904
|
-
out.set(definition.name, definition);
|
|
905
|
-
}
|
|
906
|
-
return out;
|
|
907
|
-
}
|
|
908
|
-
function count(context, at) {
|
|
909
|
-
context.nodes++;
|
|
910
|
-
if (context.nodes > context.limits.maxNodes) throw new JqlError(`the query holds more than ${context.limits.maxNodes} fields and operators`, at);
|
|
911
|
-
}
|
|
912
|
-
function join(at, key) {
|
|
913
|
-
return at === "" ? key : `${at}.${key}`;
|
|
914
|
-
}
|
|
915
|
-
function compileQuery(query, context, at, depth) {
|
|
916
|
-
if (depth > context.limits.maxDepth) throw new JqlError(`the query nests deeper than ${context.limits.maxDepth} levels`, at);
|
|
917
|
-
if (!isPlainObject(query)) throw new JqlError(`a query is an object, not ${describe(query)}`, at);
|
|
918
|
-
const parts = [];
|
|
919
|
-
let self;
|
|
920
|
-
for (const key in query) {
|
|
921
|
-
const value = query[key];
|
|
922
|
-
const here = join(at, key);
|
|
923
|
-
if (value === void 0) {
|
|
924
|
-
throw new JqlError("the value is undefined; JSON has no undefined, and a condition on nothing would match everything", here);
|
|
925
|
-
}
|
|
926
|
-
count(context, here);
|
|
927
|
-
if (!key.startsWith("$")) {
|
|
928
|
-
parts.push(compileField(resolveField(key, context, here), value, context, here, depth));
|
|
929
|
-
continue;
|
|
930
|
-
}
|
|
931
|
-
permit(key, context, here);
|
|
932
|
-
switch (key) {
|
|
933
|
-
case "$and":
|
|
934
|
-
parts.push(allOf(queryList(value, context, here, depth)));
|
|
935
|
-
break;
|
|
936
|
-
case "$or":
|
|
937
|
-
parts.push(anyOf(queryList(value, context, here, depth)));
|
|
938
|
-
break;
|
|
939
|
-
case "$nor":
|
|
940
|
-
parts.push(negate(anyOf(queryList(value, context, here, depth))));
|
|
941
|
-
break;
|
|
942
|
-
case "$not":
|
|
943
|
-
parts.push(negate(compileQuery(value, context, here, depth + 1)));
|
|
944
|
-
break;
|
|
945
|
-
case "$text":
|
|
946
|
-
parts.push(compileText(value, context, here));
|
|
947
|
-
break;
|
|
948
|
-
case "$comment":
|
|
949
|
-
if (typeof value !== "string") throw new JqlError(`a comment is a string, not ${describe(value)}`, here);
|
|
950
|
-
break;
|
|
951
|
-
default:
|
|
952
|
-
if (!FIELD_OPERATOR_SET.has(key)) throw new JqlError(`"${key}" is not an operator${didYouMean(key, EVERY_OPERATOR)}`, here);
|
|
953
|
-
self ??= {};
|
|
954
|
-
self[key] = value;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
if (self !== void 0) parts.push(compileCondition(SELF, self, context, at, depth));
|
|
958
|
-
return allOf(parts);
|
|
959
|
-
}
|
|
960
|
-
function queryList(value, context, at, depth) {
|
|
961
|
-
if (!Array.isArray(value)) throw new JqlError(`takes a list of queries, not ${describe(value)}`, at);
|
|
962
|
-
return value.map((item, index) => compileQuery(item, context, `${at}[${index}]`, depth + 1));
|
|
963
|
-
}
|
|
964
|
-
var SELF = { read: readSelf, probe: void 0, reach: (document, test) => test(document), key: void 0, cost: 0 };
|
|
965
|
-
function resolveField(name, context, at) {
|
|
966
|
-
const vocabulary = context.vocabulary;
|
|
967
|
-
if (vocabulary !== void 0) {
|
|
968
|
-
const direct = vocabulary.lookup.get(name.toLowerCase());
|
|
969
|
-
if (direct !== void 0) return fieldOf(direct, [], at);
|
|
970
|
-
const dot = name.indexOf(".");
|
|
971
|
-
if (dot > 0) {
|
|
972
|
-
const head = vocabulary.lookup.get(name.slice(0, dot).toLowerCase());
|
|
973
|
-
if (head !== void 0) {
|
|
974
|
-
const rest = splitPath(name.slice(dot + 1));
|
|
975
|
-
if (typeof rest === "string") throw new JqlError(rest, at);
|
|
976
|
-
return fieldOf(head, rest, at);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
if (vocabulary.strict) throw new JqlError(`"${name}" is not a field here${didYouMean(name, vocabulary.names)}`, at);
|
|
980
|
-
}
|
|
981
|
-
const keys = splitPath(name);
|
|
982
|
-
if (typeof keys === "string") throw new JqlError(keys, at);
|
|
983
|
-
return pathField(keys);
|
|
984
|
-
}
|
|
985
|
-
function fieldOf(field, rest, at) {
|
|
986
|
-
if (field.get !== void 0) {
|
|
987
|
-
const get = field.get;
|
|
988
|
-
if (rest.length === 0) return { read: get, probe: void 0, reach: (document, test) => test(get(document)), key: void 0, cost: 3 };
|
|
989
|
-
return { read: void 0, probe: probeFrom(get, rest), reach: reachFrom(get, rest), key: void 0, cost: 3 + rest.length };
|
|
990
|
-
}
|
|
991
|
-
const keys = splitPath(field.path);
|
|
992
|
-
if (typeof keys === "string") throw new JqlError(keys, at);
|
|
993
|
-
return pathField([...keys, ...rest]);
|
|
994
|
-
}
|
|
995
|
-
function pathField(keys) {
|
|
996
|
-
if (keys.length === 1) {
|
|
997
|
-
const key = keys[0];
|
|
998
|
-
return { read: void 0, probe: probePath(keys), reach: reachPath(keys), key, cost: 0 };
|
|
999
|
-
}
|
|
1000
|
-
return { read: void 0, probe: probePath(keys), reach: reachPath(keys), key: void 0, cost: keys.length };
|
|
1001
|
-
}
|
|
1002
|
-
function compileField(field, value, context, at, depth) {
|
|
1003
|
-
if (isFieldReference(value)) {
|
|
1004
|
-
permit("$field", context, at);
|
|
1005
|
-
permit("$eq", context, at);
|
|
1006
|
-
return compareFields(field, "$eq", value.$field, false, context, at);
|
|
1007
|
-
}
|
|
1008
|
-
if (isPlainObject(value) && !isDateLiteral(value)) {
|
|
1009
|
-
let operators = 0;
|
|
1010
|
-
let names = 0;
|
|
1011
|
-
for (const key in value) {
|
|
1012
|
-
if (key.startsWith("$")) operators++;
|
|
1013
|
-
else names++;
|
|
1014
|
-
}
|
|
1015
|
-
if (operators > 0 && names > 0) {
|
|
1016
|
-
throw new JqlError("mixes operators with field names; an object here is either a condition ({ $gt: 1 }) or a value to compare with ({ a: 1 }), not both", at);
|
|
1017
|
-
}
|
|
1018
|
-
if (operators > 0) return compileCondition(field, value, context, at, depth + 1);
|
|
1019
|
-
}
|
|
1020
|
-
permit("$eq", context, at);
|
|
1021
|
-
return equality(field, value, false, at, context.now);
|
|
1022
|
-
}
|
|
1023
|
-
function compileCondition(field, condition2, context, at, depth) {
|
|
1024
|
-
const { values: values2, whole } = conditionParts(field, condition2, context, at, depth);
|
|
1025
|
-
return combine(field, values2, whole);
|
|
1026
|
-
}
|
|
1027
|
-
function combine(field, values2, whole) {
|
|
1028
|
-
const parts = [...whole];
|
|
1029
|
-
if (values2.length > 0) {
|
|
1030
|
-
const cost = values2.reduce((sum, value) => sum + value.cost, 0);
|
|
1031
|
-
if (field.read !== void 0) {
|
|
1032
|
-
const only = values2.length === 1 ? values2[0] : void 0;
|
|
1033
|
-
parts.push(only !== void 0 && only.any !== void 0 ? holdsAny(field, only.any, only.negated, cost) : holds(field, allOfValues(values2), cost));
|
|
1034
|
-
} else {
|
|
1035
|
-
const separate = allOf(values2.map((value) => value.negated ? negate(holds(field, value.test, value.cost)) : holds(field, value.test, value.cost)));
|
|
1036
|
-
const probe = field.probe;
|
|
1037
|
-
if (probe === void 0) parts.push(separate);
|
|
1038
|
-
else {
|
|
1039
|
-
const fused = allOfValues(values2);
|
|
1040
|
-
const fallback = separate.test;
|
|
1041
|
-
parts.push({ test: (document) => {
|
|
1042
|
-
const value = probe(document);
|
|
1043
|
-
return value === FANOUT ? fallback(document) : fused(value);
|
|
1044
|
-
}, cost: separate.cost });
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
return allOf(parts);
|
|
1049
|
-
}
|
|
1050
|
-
function conditionParts(field, condition2, context, at, depth) {
|
|
1051
|
-
if (depth > context.limits.maxDepth) throw new JqlError(`the query nests deeper than ${context.limits.maxDepth} levels`, at);
|
|
1052
|
-
let flags = "";
|
|
1053
|
-
if (condition2.$options !== void 0) {
|
|
1054
|
-
flags = parseOptions(condition2.$options, join(at, "$options"));
|
|
1055
|
-
const usesCase = Object.keys(condition2).some((key) => CASE_AWARE.has(key));
|
|
1056
|
-
if (!usesCase) throw new JqlError("$options has nothing to apply to: it changes $regex and the equality and string operators beside it", join(at, "$options"));
|
|
1057
|
-
if (/[msu]/.test(flags) && condition2.$regex === void 0) throw new JqlError(`the flags "${flags.replace("i", "")}" only mean something to $regex, and there is none here`, join(at, "$options"));
|
|
1058
|
-
}
|
|
1059
|
-
const ignoreCase = flags.includes("i");
|
|
1060
|
-
const values2 = [];
|
|
1061
|
-
const whole = [];
|
|
1062
|
-
const add = (test, cost, negated = false) => {
|
|
1063
|
-
values2.push({ test, cost, negated, any: void 0 });
|
|
1064
|
-
};
|
|
1065
|
-
const addAny = (test, cost, negated = false) => {
|
|
1066
|
-
values2.push({ test: elementwise(test), cost, negated, any: test });
|
|
1067
|
-
};
|
|
1068
|
-
for (const key in condition2) {
|
|
1069
|
-
const operand2 = condition2[key];
|
|
1070
|
-
const here = join(at, key);
|
|
1071
|
-
if (operand2 === void 0) throw new JqlError("the value is undefined; JSON has no undefined, and a condition on nothing would match everything", here);
|
|
1072
|
-
count(context, here);
|
|
1073
|
-
permit(key, context, here);
|
|
1074
|
-
switch (key) {
|
|
1075
|
-
case "$options":
|
|
1076
|
-
break;
|
|
1077
|
-
case "$eq":
|
|
1078
|
-
case "$ne": {
|
|
1079
|
-
const negated = key === "$ne";
|
|
1080
|
-
const reference = referencePath(operand2, here);
|
|
1081
|
-
if (reference !== void 0) {
|
|
1082
|
-
permit("$field", context, here);
|
|
1083
|
-
whole.push(compareFields(field, "$eq", reference, negated, context, here));
|
|
1084
|
-
break;
|
|
1085
|
-
}
|
|
1086
|
-
add(equalsValue(operand2, ignoreCase, here, context.now), operand2 !== null && typeof operand2 === "object" ? 3 : 0, negated);
|
|
1087
|
-
break;
|
|
1088
|
-
}
|
|
1089
|
-
case "$gt":
|
|
1090
|
-
case "$gte":
|
|
1091
|
-
case "$lt":
|
|
1092
|
-
case "$lte":
|
|
1093
|
-
{
|
|
1094
|
-
const reference = referencePath(operand2, here);
|
|
1095
|
-
if (reference !== void 0) {
|
|
1096
|
-
permit("$field", context, here);
|
|
1097
|
-
whole.push(compareFields(field, key, reference, false, context, here));
|
|
1098
|
-
break;
|
|
1099
|
-
}
|
|
1100
|
-
addAny(orderTest(key, operand2, here, context.now), 1);
|
|
1101
|
-
}
|
|
1102
|
-
break;
|
|
1103
|
-
case "$in":
|
|
1104
|
-
addAny(inTest(operand2, ignoreCase, here, context.now), 1);
|
|
1105
|
-
break;
|
|
1106
|
-
case "$nin":
|
|
1107
|
-
addAny(inTest(operand2, ignoreCase, here, context.now), 1, true);
|
|
1108
|
-
break;
|
|
1109
|
-
case "$exists":
|
|
1110
|
-
if (typeof operand2 !== "boolean") throw new JqlError(`takes true or false, not ${describe(operand2)}`, here);
|
|
1111
|
-
add(isPresent, 0, !operand2);
|
|
1112
|
-
break;
|
|
1113
|
-
case "$type":
|
|
1114
|
-
addAny(typeTest(operand2, here), 1);
|
|
1115
|
-
break;
|
|
1116
|
-
case "$contains":
|
|
1117
|
-
case "$startsWith":
|
|
1118
|
-
case "$endsWith":
|
|
1119
|
-
case "$word":
|
|
1120
|
-
case "$glob":
|
|
1121
|
-
addAny(stringTest(key, operand2, ignoreCase, here, context.limits.maxGlobLength), key === "$word" || key === "$glob" ? 4 : 2);
|
|
1122
|
-
break;
|
|
1123
|
-
case "$regex":
|
|
1124
|
-
addAny(regexTest(operand2, flags, context.limits, here), 5);
|
|
1125
|
-
break;
|
|
1126
|
-
case "$mod":
|
|
1127
|
-
addAny(modTest(operand2, here), 1);
|
|
1128
|
-
break;
|
|
1129
|
-
case "$size":
|
|
1130
|
-
add(sizeTest(operand2, context, here, depth, "array"), 1);
|
|
1131
|
-
break;
|
|
1132
|
-
case "$length":
|
|
1133
|
-
add(sizeTest(operand2, context, here, depth, "anything with a length"), 1);
|
|
1134
|
-
break;
|
|
1135
|
-
case "$all":
|
|
1136
|
-
add(allTest(operand2, ignoreCase, here, context.now), 4);
|
|
1137
|
-
break;
|
|
1138
|
-
case "$elemMatch": {
|
|
1139
|
-
if (!isPlainObject(operand2)) throw new JqlError(`takes a query for one element, not ${describe(operand2)}`, here);
|
|
1140
|
-
const element = compileQuery(operand2, context, here, depth + 1);
|
|
1141
|
-
const test = element.test;
|
|
1142
|
-
add((value) => {
|
|
1143
|
-
if (!Array.isArray(value)) return false;
|
|
1144
|
-
for (let i = 0; i < value.length; i++) if (test(value[i])) return true;
|
|
1145
|
-
return false;
|
|
1146
|
-
}, 4 + element.cost);
|
|
1147
|
-
break;
|
|
1148
|
-
}
|
|
1149
|
-
case "$not": {
|
|
1150
|
-
if (!isPlainObject(operand2) || isDateLiteral(operand2) || !Object.keys(operand2).every((name) => name.startsWith("$"))) {
|
|
1151
|
-
throw new JqlError(`takes a condition such as { "$gt": 5 }, not ${describe(operand2)}; to negate a value, use $ne`, here);
|
|
1152
|
-
}
|
|
1153
|
-
const inner = conditionParts(field, operand2, context, here, depth + 1);
|
|
1154
|
-
if (field.read !== void 0 && inner.whole.length === 0) {
|
|
1155
|
-
add(allOfValues(inner.values), inner.values.reduce((sum, value) => sum + value.cost, 0), true);
|
|
1156
|
-
break;
|
|
1157
|
-
}
|
|
1158
|
-
whole.push(negate(combine(field, inner.values, inner.whole)));
|
|
1159
|
-
break;
|
|
1160
|
-
}
|
|
1161
|
-
default: {
|
|
1162
|
-
const extension = context.operators.get(key);
|
|
1163
|
-
if (extension !== void 0) {
|
|
1164
|
-
const test = extension.compile(operand2, here);
|
|
1165
|
-
if (typeof test !== "function") throw new JqlError(`"${key}" did not build a test, so there is nothing to run`, here);
|
|
1166
|
-
const cost = extension.cost ?? 4;
|
|
1167
|
-
if (extension.elementwise === false) add(test, cost);
|
|
1168
|
-
else addAny(test, cost);
|
|
1169
|
-
break;
|
|
1170
|
-
}
|
|
1171
|
-
const reason2 = QUERY_OPERATORS.includes(key) ? `"${key}" combines whole queries, so it belongs beside field names rather than inside a field's condition` : EXTENSION_NAME.test(key) ? `"${key}" is an added operator, and this query was compiled without it; pass it in \`operators\`` : `"${key}" is not an operator${didYouMean(key, [...FIELD_OPERATORS, ...context.operators.keys()])}`;
|
|
1172
|
-
throw new JqlError(reason2, here);
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
return { values: values2, whole };
|
|
1177
|
-
}
|
|
1178
|
-
function allOfValues(values2) {
|
|
1179
|
-
const tests = [...values2].sort((a, b) => a.cost - b.cost).map(({ test, negated }) => negated ? (value) => !test(value) : test);
|
|
1180
|
-
if (tests.length === 0) return () => true;
|
|
1181
|
-
if (tests.length === 1) return tests[0];
|
|
1182
|
-
if (tests.length === 2) {
|
|
1183
|
-
const [a, b] = tests;
|
|
1184
|
-
return (value) => a(value) && b(value);
|
|
1185
|
-
}
|
|
1186
|
-
return (value) => {
|
|
1187
|
-
for (let i = 0; i < tests.length; i++) if (!tests[i](value)) return false;
|
|
1188
|
-
return true;
|
|
1189
|
-
};
|
|
1190
|
-
}
|
|
1191
|
-
var isPresent = (value) => value !== void 0;
|
|
1192
|
-
function elementwise(test) {
|
|
1193
|
-
return (value) => {
|
|
1194
|
-
if (test(value)) return true;
|
|
1195
|
-
if (!Array.isArray(value)) return false;
|
|
1196
|
-
for (let i = 0; i < value.length; i++) if (test(value[i])) return true;
|
|
1197
|
-
return false;
|
|
1198
|
-
};
|
|
1199
|
-
}
|
|
1200
|
-
function holds(field, test, cost) {
|
|
1201
|
-
const key = field.key;
|
|
1202
|
-
if (key !== void 0) {
|
|
1203
|
-
const reach2 = field.reach;
|
|
1204
|
-
const plain = !needsGuard(key);
|
|
1205
|
-
return {
|
|
1206
|
-
test: (document) => {
|
|
1207
|
-
if (document === null || typeof document !== "object") return test(void 0);
|
|
1208
|
-
if (Array.isArray(document)) return reach2(document, test);
|
|
1209
|
-
return test(plain && document.__proto__ === PLAIN ? document[key] : readOwn(document, key));
|
|
1210
|
-
},
|
|
1211
|
-
cost: field.cost + cost
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
const read = field.read;
|
|
1215
|
-
if (read === readSelf) return { test, cost: field.cost + cost };
|
|
1216
|
-
if (read !== void 0) return { test: (document) => test(read(document)), cost: field.cost + cost };
|
|
1217
|
-
const reach = field.reach;
|
|
1218
|
-
const probe = field.probe;
|
|
1219
|
-
if (probe !== void 0) {
|
|
1220
|
-
return {
|
|
1221
|
-
test: (document) => {
|
|
1222
|
-
const value = probe(document);
|
|
1223
|
-
return value === FANOUT ? reach(document, test) : test(value);
|
|
1224
|
-
},
|
|
1225
|
-
cost: field.cost + cost
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
return { test: (document) => reach(document, test), cost: field.cost + cost };
|
|
1229
|
-
}
|
|
1230
|
-
function holdsAny(field, test, negated, cost) {
|
|
1231
|
-
const key = field.key;
|
|
1232
|
-
if (key === void 0) {
|
|
1233
|
-
const read = field.read;
|
|
1234
|
-
const single = (value) => {
|
|
1235
|
-
if (test(value)) return true;
|
|
1236
|
-
if (!Array.isArray(value)) return false;
|
|
1237
|
-
for (let i = 0; i < value.length; i++) if (test(value[i])) return true;
|
|
1238
|
-
return false;
|
|
1239
|
-
};
|
|
1240
|
-
return { test: negated ? (document) => !single(read(document)) : (document) => single(read(document)), cost: field.cost + cost };
|
|
1241
|
-
}
|
|
1242
|
-
const reach = field.reach;
|
|
1243
|
-
const plain = !needsGuard(key);
|
|
1244
|
-
const any = (value) => {
|
|
1245
|
-
if (test(value)) return true;
|
|
1246
|
-
if (!Array.isArray(value)) return false;
|
|
1247
|
-
for (let i = 0; i < value.length; i++) if (test(value[i])) return true;
|
|
1248
|
-
return false;
|
|
1249
|
-
};
|
|
1250
|
-
const hit = (document) => {
|
|
1251
|
-
if (document === null || typeof document !== "object") return test(void 0);
|
|
1252
|
-
if (Array.isArray(document)) return reach(document, any);
|
|
1253
|
-
return any(plain && document.__proto__ === PLAIN ? document[key] : readOwn(document, key));
|
|
1254
|
-
};
|
|
1255
|
-
return { test: negated ? (document) => !hit(document) : hit, cost: field.cost + cost };
|
|
1256
|
-
}
|
|
1257
|
-
function equalsValue(literal2, ignoreCase, at, now) {
|
|
1258
|
-
if (!ignoreCase && (typeof literal2 === "string" || typeof literal2 === "number" || typeof literal2 === "boolean")) {
|
|
1259
|
-
checkLiteral(literal2, at);
|
|
1260
|
-
const wanted = literal2;
|
|
1261
|
-
const big = alsoBig(literal2);
|
|
1262
|
-
if (big !== void 0) return (value) => value === wanted || value === big || Array.isArray(value) && (value.includes(wanted) || value.includes(big));
|
|
1263
|
-
return (value) => value === wanted || Array.isArray(value) && value.includes(wanted);
|
|
1264
|
-
}
|
|
1265
|
-
return elementwise(equalsTest(literal2, ignoreCase, at, now));
|
|
1266
|
-
}
|
|
1267
|
-
function equality(field, literal2, ignoreCase, at, now) {
|
|
1268
|
-
const key = field.key;
|
|
1269
|
-
if (key !== void 0 && !ignoreCase && (typeof literal2 === "string" || typeof literal2 === "number" || typeof literal2 === "boolean")) {
|
|
1270
|
-
checkLiteral(literal2, at);
|
|
1271
|
-
const wanted = literal2;
|
|
1272
|
-
const reach = field.reach;
|
|
1273
|
-
const plain = !needsGuard(key);
|
|
1274
|
-
const test = equalsValue(literal2, false, at, now);
|
|
1275
|
-
const big = alsoBig(literal2);
|
|
1276
|
-
if (big !== void 0) {
|
|
1277
|
-
return {
|
|
1278
|
-
test: (document) => {
|
|
1279
|
-
if (document === null || typeof document !== "object") return false;
|
|
1280
|
-
if (Array.isArray(document)) return reach(document, test);
|
|
1281
|
-
const value = plain && document.__proto__ === PLAIN ? document[key] : readOwn(document, key);
|
|
1282
|
-
return value === wanted || value === big || Array.isArray(value) && (value.includes(wanted) || value.includes(big));
|
|
1283
|
-
},
|
|
1284
|
-
cost: 0
|
|
1285
|
-
};
|
|
1286
|
-
}
|
|
1287
|
-
return {
|
|
1288
|
-
test: (document) => {
|
|
1289
|
-
if (document === null || typeof document !== "object") return false;
|
|
1290
|
-
if (Array.isArray(document)) return reach(document, test);
|
|
1291
|
-
const value = plain && document.__proto__ === PLAIN ? document[key] : readOwn(document, key);
|
|
1292
|
-
return value === wanted || Array.isArray(value) && value.includes(wanted);
|
|
1293
|
-
},
|
|
1294
|
-
cost: 0
|
|
1295
|
-
};
|
|
1296
|
-
}
|
|
1297
|
-
const probe = field.probe;
|
|
1298
|
-
if (probe !== void 0 && !ignoreCase && (typeof literal2 === "string" || typeof literal2 === "number" || typeof literal2 === "boolean")) {
|
|
1299
|
-
checkLiteral(literal2, at);
|
|
1300
|
-
const wanted = literal2;
|
|
1301
|
-
const test = equalsValue(literal2, false, at, now);
|
|
1302
|
-
const reach = field.reach;
|
|
1303
|
-
const big = alsoBig(literal2);
|
|
1304
|
-
if (big !== void 0) {
|
|
1305
|
-
return {
|
|
1306
|
-
test: (document) => {
|
|
1307
|
-
const value = probe(document);
|
|
1308
|
-
if (value === wanted || value === big) return true;
|
|
1309
|
-
if (value === FANOUT) return reach(document, test);
|
|
1310
|
-
return Array.isArray(value) && (value.includes(wanted) || value.includes(big));
|
|
1311
|
-
},
|
|
1312
|
-
cost: field.cost
|
|
1313
|
-
};
|
|
1314
|
-
}
|
|
1315
|
-
return {
|
|
1316
|
-
test: (document) => {
|
|
1317
|
-
const value = probe(document);
|
|
1318
|
-
if (value === wanted) return true;
|
|
1319
|
-
if (value === FANOUT) return reach(document, test);
|
|
1320
|
-
return Array.isArray(value) && value.includes(wanted);
|
|
1321
|
-
},
|
|
1322
|
-
cost: field.cost
|
|
1323
|
-
};
|
|
1324
|
-
}
|
|
1325
|
-
return holds(field, equalsValue(literal2, ignoreCase, at, now), literal2 !== null && typeof literal2 === "object" ? 3 : 0);
|
|
1326
|
-
}
|
|
1327
|
-
function sizeTest(operand2, context, at, depth, measures) {
|
|
1328
|
-
const strings = measures !== "array";
|
|
1329
|
-
let length;
|
|
1330
|
-
if (typeof operand2 === "number") {
|
|
1331
|
-
if (!Number.isInteger(operand2) || operand2 < 0) throw new JqlError(`a length is a whole number, not ${operand2}`, at);
|
|
1332
|
-
length = (size) => size === operand2;
|
|
1333
|
-
} else if (isPlainObject(operand2)) {
|
|
1334
|
-
length = compileCondition(SELF, operand2, context, at, depth + 1).test;
|
|
1335
|
-
} else throw new JqlError(`takes a number or a condition on one, not ${describe(operand2)}`, at);
|
|
1336
|
-
if (strings) return (value) => (typeof value === "string" || Array.isArray(value)) && length(value.length);
|
|
1337
|
-
return (value) => Array.isArray(value) && length(value.length);
|
|
1338
|
-
}
|
|
1339
|
-
function compareFields(field, operator, path, negated, context, at) {
|
|
1340
|
-
const other = resolveField(path, context, at);
|
|
1341
|
-
const compare = comparer(operator);
|
|
1342
|
-
const leftRead = field.read;
|
|
1343
|
-
const rightRead = other.read;
|
|
1344
|
-
let holdsPair;
|
|
1345
|
-
if (leftRead !== void 0 && rightRead !== void 0) {
|
|
1346
|
-
holdsPair = (document) => eachOf(leftRead(document), (one) => eachOf(rightRead(document), (two) => compare(one, two)));
|
|
1347
|
-
} else {
|
|
1348
|
-
const left = field.reach;
|
|
1349
|
-
const right = other.reach;
|
|
1350
|
-
holdsPair = (document) => left(document, (one) => eachOf(one, (a) => right(document, (two) => eachOf(two, (b) => compare(a, b)))));
|
|
1351
|
-
}
|
|
1352
|
-
return { test: negated ? (document) => !holdsPair(document) : holdsPair, cost: field.cost + other.cost + 4 };
|
|
1353
|
-
}
|
|
1354
|
-
function comparer(operator) {
|
|
1355
|
-
if (operator === "$eq") return (a, b) => a !== void 0 && b !== void 0 && valuesEqual(a, b);
|
|
1356
|
-
return (a, b) => {
|
|
1357
|
-
if (a === void 0 || b === void 0) return false;
|
|
1358
|
-
const order = orderOf(a, b);
|
|
1359
|
-
if (order === void 0) return false;
|
|
1360
|
-
switch (operator) {
|
|
1361
|
-
case "$gt":
|
|
1362
|
-
return order > 0;
|
|
1363
|
-
case "$gte":
|
|
1364
|
-
return order >= 0;
|
|
1365
|
-
case "$lt":
|
|
1366
|
-
return order < 0;
|
|
1367
|
-
default:
|
|
1368
|
-
return order <= 0;
|
|
1369
|
-
}
|
|
1370
|
-
};
|
|
1371
|
-
}
|
|
1372
|
-
function referencePath(operand2, at) {
|
|
1373
|
-
if (!isPlainObject(operand2) || !("$field" in operand2)) return void 0;
|
|
1374
|
-
if (typeof operand2.$field !== "string") throw new JqlError(`a {"$field": \u2026} reference takes the path as a string, not ${describe(operand2.$field)}`, at);
|
|
1375
|
-
const beside = Object.keys(operand2).filter((key) => key !== "$field");
|
|
1376
|
-
if (beside.length > 0) throw new JqlError(`a {"$field": \u2026} reference holds nothing but the path, and "${beside[0]}" is beside it`, at);
|
|
1377
|
-
return operand2.$field;
|
|
1378
|
-
}
|
|
1379
|
-
function eachOf(value, test) {
|
|
1380
|
-
if (test(value)) return true;
|
|
1381
|
-
if (!Array.isArray(value)) return false;
|
|
1382
|
-
for (let i = 0; i < value.length; i++) if (test(value[i])) return true;
|
|
1383
|
-
return false;
|
|
1384
|
-
}
|
|
1385
|
-
function compileText(value, context, at) {
|
|
1386
|
-
let search2;
|
|
1387
|
-
let fields;
|
|
1388
|
-
let caseSensitive = false;
|
|
1389
|
-
if (typeof value === "string") search2 = value;
|
|
1390
|
-
else if (isPlainObject(value)) {
|
|
1391
|
-
for (const key in value) {
|
|
1392
|
-
if (key !== "$search" && key !== "$fields" && key !== "$caseSensitive") {
|
|
1393
|
-
throw new JqlError(`"${key}" is not part of a text search ($search, $fields, $caseSensitive)${didYouMean(key, ["$search", "$fields", "$caseSensitive"])}`, join(at, key));
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
search2 = value.$search;
|
|
1397
|
-
fields = value.$fields;
|
|
1398
|
-
caseSensitive = "$caseSensitive" in value ? value.$caseSensitive : false;
|
|
1399
|
-
} else throw new JqlError(`takes a phrase or { "$search": \u2026 }, not ${describe(value)}`, at);
|
|
1400
|
-
if (typeof search2 !== "string") throw new JqlError(`the phrase is a string, not ${describe(search2)}`, join(at, "$search"));
|
|
1401
|
-
if (typeof caseSensitive !== "boolean") throw new JqlError(`takes true or false, not ${describe(caseSensitive)}`, join(at, "$caseSensitive"));
|
|
1402
|
-
const names = fields === void 0 ? context.vocabulary?.text : fields;
|
|
1403
|
-
const reaches = names === void 0 ? void 0 : textFields(names, context, at);
|
|
1404
|
-
const needle = caseSensitive ? search2 : search2.toLowerCase();
|
|
1405
|
-
if (needle === "") return ALWAYS;
|
|
1406
|
-
const found = caseSensitive ? (text2) => text2.includes(needle) : (text2) => text2.toLowerCase().includes(needle);
|
|
1407
|
-
const numeric = /\d/.test(needle);
|
|
1408
|
-
const maxDepth = context.limits.maxTextDepth;
|
|
1409
|
-
const inValue = (item) => containsText(item, found, numeric, maxDepth);
|
|
1410
|
-
if (reaches === void 0) return { test: inValue, cost: 20 };
|
|
1411
|
-
return {
|
|
1412
|
-
test: (document) => {
|
|
1413
|
-
for (let i = 0; i < reaches.length; i++) if (reaches[i](document, inValue)) return true;
|
|
1414
|
-
return false;
|
|
1415
|
-
},
|
|
1416
|
-
cost: 6 + reaches.length * 2
|
|
1417
|
-
};
|
|
1418
|
-
}
|
|
1419
|
-
function textFields(names, context, at) {
|
|
1420
|
-
if (!Array.isArray(names) || names.length === 0) throw new JqlError(`takes a non-empty list of field names, not ${describe(names)}`, join(at, "$fields"));
|
|
1421
|
-
return names.map((name, index) => {
|
|
1422
|
-
if (typeof name !== "string") throw new JqlError(`a field name is a string, not ${describe(name)}`, `${join(at, "$fields")}[${index}]`);
|
|
1423
|
-
return resolveField(name, context, `${join(at, "$fields")}[${index}]`).reach;
|
|
1424
|
-
});
|
|
1425
|
-
}
|
|
1426
|
-
function containsText(value, found, numeric, depth) {
|
|
1427
|
-
if (typeof value === "string") return found(value);
|
|
1428
|
-
if (typeof value === "number" || typeof value === "bigint") return numeric && found(String(value));
|
|
1429
|
-
if (value === null || typeof value !== "object" || depth <= 0 || value instanceof Date) return false;
|
|
1430
|
-
if (Array.isArray(value)) {
|
|
1431
|
-
for (let i = 0; i < value.length; i++) if (containsText(value[i], found, numeric, depth - 1)) return true;
|
|
1432
|
-
return false;
|
|
1433
|
-
}
|
|
1434
|
-
if (value instanceof Map || value instanceof Set) {
|
|
1435
|
-
for (const item of value.values()) if (containsText(item, found, numeric, depth - 1)) return true;
|
|
1436
|
-
return false;
|
|
1437
|
-
}
|
|
1438
|
-
const record = value;
|
|
1439
|
-
for (const key in record) if (Object.hasOwn(record, key) && containsText(record[key], found, numeric, depth - 1)) return true;
|
|
1440
|
-
return false;
|
|
1441
|
-
}
|
|
1442
|
-
function allOf(parts) {
|
|
1443
|
-
const real = parts.filter((part) => part !== ALWAYS);
|
|
1444
|
-
if (real.includes(NOTHING)) return NOTHING;
|
|
1445
|
-
if (real.length === 0) return ALWAYS;
|
|
1446
|
-
if (real.length === 1) return real[0];
|
|
1447
|
-
real.sort((a, b) => a.cost - b.cost);
|
|
1448
|
-
const cost = real.reduce((sum, part) => sum + part.cost, 0);
|
|
1449
|
-
const tests = real.map((part) => part.test);
|
|
1450
|
-
if (tests.length === 2) {
|
|
1451
|
-
const [a, b] = tests;
|
|
1452
|
-
return { test: (document) => a(document) && b(document), cost };
|
|
1453
|
-
}
|
|
1454
|
-
if (tests.length === 3) {
|
|
1455
|
-
const [a, b, c] = tests;
|
|
1456
|
-
return { test: (document) => a(document) && b(document) && c(document), cost };
|
|
1457
|
-
}
|
|
1458
|
-
return {
|
|
1459
|
-
test: (document) => {
|
|
1460
|
-
for (let i = 0; i < tests.length; i++) if (!tests[i](document)) return false;
|
|
1461
|
-
return true;
|
|
1462
|
-
},
|
|
1463
|
-
cost
|
|
1464
|
-
};
|
|
1465
|
-
}
|
|
1466
|
-
function anyOf(parts) {
|
|
1467
|
-
const real = parts.filter((part) => part !== NOTHING);
|
|
1468
|
-
if (real.includes(ALWAYS)) return ALWAYS;
|
|
1469
|
-
if (real.length === 0) return NOTHING;
|
|
1470
|
-
if (real.length === 1) return real[0];
|
|
1471
|
-
real.sort((a, b) => a.cost - b.cost);
|
|
1472
|
-
const cost = real.reduce((sum, part) => sum + part.cost, 0);
|
|
1473
|
-
const tests = real.map((part) => part.test);
|
|
1474
|
-
if (tests.length === 2) {
|
|
1475
|
-
const [a, b] = tests;
|
|
1476
|
-
return { test: (document) => a(document) || b(document), cost };
|
|
1477
|
-
}
|
|
1478
|
-
return {
|
|
1479
|
-
test: (document) => {
|
|
1480
|
-
for (let i = 0; i < tests.length; i++) if (tests[i](document)) return true;
|
|
1481
|
-
return false;
|
|
1482
|
-
},
|
|
1483
|
-
cost
|
|
1484
|
-
};
|
|
1485
|
-
}
|
|
1486
|
-
function negate(part) {
|
|
1487
|
-
if (part === ALWAYS) return NOTHING;
|
|
1488
|
-
if (part === NOTHING) return ALWAYS;
|
|
1489
|
-
const test = part.test;
|
|
1490
|
-
return { test: (document) => !test(document), cost: part.cost };
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
// src/internal/record.ts
|
|
1494
|
-
function setField(target, key, value) {
|
|
1495
|
-
if (key === "__proto__") {
|
|
1496
|
-
Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
|
|
1497
|
-
return;
|
|
1498
|
-
}
|
|
1499
|
-
target[key] = value;
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
// src/collections.ts
|
|
1503
|
-
function walk3(source, visit) {
|
|
1504
|
-
if (Array.isArray(source)) {
|
|
1505
|
-
for (let i = 0; i < source.length; i++) if (visit(source[i])) return i;
|
|
1506
|
-
return -1;
|
|
1507
|
-
}
|
|
1508
|
-
if (source instanceof Map) {
|
|
1509
|
-
let i = 0;
|
|
1510
|
-
for (const item of source.values()) {
|
|
1511
|
-
if (visit(item)) return i;
|
|
1512
|
-
i++;
|
|
1513
|
-
}
|
|
1514
|
-
return -1;
|
|
1515
|
-
}
|
|
1516
|
-
if (typeof source[Symbol.iterator] === "function") {
|
|
1517
|
-
let i = 0;
|
|
1518
|
-
for (const item of source) {
|
|
1519
|
-
if (visit(item)) return i;
|
|
1520
|
-
i++;
|
|
1521
|
-
}
|
|
1522
|
-
return -1;
|
|
1523
|
-
}
|
|
1524
|
-
const list = source;
|
|
1525
|
-
for (let i = 0; i < list.length; i++) if (visit(list[i])) return i;
|
|
1526
|
-
return -1;
|
|
1527
|
-
}
|
|
1528
|
-
function find(source, query, options) {
|
|
1529
|
-
const test = compile(query, options);
|
|
1530
|
-
let found;
|
|
1531
|
-
walk3(source, (item) => {
|
|
1532
|
-
if (!test(item)) return false;
|
|
1533
|
-
found = item;
|
|
1534
|
-
return true;
|
|
1535
|
-
});
|
|
1536
|
-
return found;
|
|
1537
|
-
}
|
|
1538
|
-
function findIndex(source, query, options) {
|
|
1539
|
-
return walk3(source, compile(query, options));
|
|
1540
|
-
}
|
|
1541
|
-
function filter(source, query, options) {
|
|
1542
|
-
const test = compile(query, options);
|
|
1543
|
-
const out = [];
|
|
1544
|
-
walk3(source, (item) => {
|
|
1545
|
-
if (test(item)) out.push(item);
|
|
1546
|
-
return false;
|
|
1547
|
-
});
|
|
1548
|
-
return out;
|
|
1549
|
-
}
|
|
1550
|
-
function count2(source, query, options) {
|
|
1551
|
-
const test = compile(query, options);
|
|
1552
|
-
let total = 0;
|
|
1553
|
-
walk3(source, (item) => {
|
|
1554
|
-
if (test(item)) total++;
|
|
1555
|
-
return false;
|
|
1556
|
-
});
|
|
1557
|
-
return total;
|
|
1558
|
-
}
|
|
1559
|
-
function some(source, query, options) {
|
|
1560
|
-
return walk3(source, compile(query, options)) !== -1;
|
|
1561
|
-
}
|
|
1562
|
-
function every(source, query, options) {
|
|
1563
|
-
const test = compile(query, options);
|
|
1564
|
-
return walk3(source, (item) => !test(item)) === -1;
|
|
1565
|
-
}
|
|
1566
|
-
function partition(source, query, options) {
|
|
1567
|
-
const test = compile(query, options);
|
|
1568
|
-
const yes = [];
|
|
1569
|
-
const no = [];
|
|
1570
|
-
walk3(source, (item) => {
|
|
1571
|
-
(test(item) ? yes : no).push(item);
|
|
1572
|
-
return false;
|
|
1573
|
-
});
|
|
1574
|
-
return [yes, no];
|
|
1575
|
-
}
|
|
1576
|
-
function filterMap(source, query, options) {
|
|
1577
|
-
const test = compile(query, options);
|
|
1578
|
-
const out = /* @__PURE__ */ new Map();
|
|
1579
|
-
for (const [key, value] of source) if (test(value)) out.set(key, value);
|
|
1580
|
-
return out;
|
|
1581
|
-
}
|
|
1582
|
-
function filterRecord(source, query, options) {
|
|
1583
|
-
const test = compile(query, options);
|
|
1584
|
-
const out = {};
|
|
1585
|
-
for (const key of Object.keys(source)) {
|
|
1586
|
-
const value = source[key];
|
|
1587
|
-
if (test(value)) setField(out, key, value);
|
|
1588
|
-
}
|
|
1589
|
-
return out;
|
|
1590
|
-
}
|
|
1591
|
-
function findEntry(source, query, options) {
|
|
1592
|
-
const test = compile(query, options);
|
|
1593
|
-
if (source instanceof Map) {
|
|
1594
|
-
for (const [key, value] of source) if (test(value)) return [key, value];
|
|
1595
|
-
return void 0;
|
|
1596
|
-
}
|
|
1597
|
-
const record = source;
|
|
1598
|
-
for (const key of Object.keys(record)) {
|
|
1599
|
-
const value = record[key];
|
|
1600
|
-
if (test(value)) return [key, value];
|
|
1601
|
-
}
|
|
1602
|
-
return void 0;
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
// src/internal/order.ts
|
|
1606
|
-
function rank(value) {
|
|
1607
|
-
if (value === void 0 || value === null) return 0;
|
|
1608
|
-
switch (typeof value) {
|
|
1609
|
-
case "number":
|
|
1610
|
-
case "bigint":
|
|
1611
|
-
return Number.isNaN(value) ? 0 : 1;
|
|
1612
|
-
case "string":
|
|
1613
|
-
return 2;
|
|
1614
|
-
case "boolean":
|
|
1615
|
-
return 4;
|
|
1616
|
-
default:
|
|
1617
|
-
return value instanceof Date ? 5 : 3;
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
function compareValues(a, b) {
|
|
1621
|
-
const ra = rank(a);
|
|
1622
|
-
const rb = rank(b);
|
|
1623
|
-
if (ra !== rb) return ra - rb;
|
|
1624
|
-
switch (ra) {
|
|
1625
|
-
case 1:
|
|
1626
|
-
case 2:
|
|
1627
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
1628
|
-
case 4:
|
|
1629
|
-
return a === b ? 0 : a ? 1 : -1;
|
|
1630
|
-
case 5:
|
|
1631
|
-
return a.getTime() - b.getTime();
|
|
1632
|
-
default:
|
|
1633
|
-
return 0;
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
function sortValue(values2, descending, depth = 0) {
|
|
1637
|
-
let best;
|
|
1638
|
-
let first = true;
|
|
1639
|
-
for (const value of values2) {
|
|
1640
|
-
if (Array.isArray(value)) {
|
|
1641
|
-
if (value.length === 0 || depth >= 16) continue;
|
|
1642
|
-
const inner = sortValue(value, descending, depth + 1);
|
|
1643
|
-
if (first || (descending ? compareValues(inner, best) > 0 : compareValues(inner, best) < 0)) best = inner;
|
|
1644
|
-
first = false;
|
|
1645
|
-
continue;
|
|
1646
|
-
}
|
|
1647
|
-
if (first || (descending ? compareValues(value, best) > 0 : compareValues(value, best) < 0)) best = value;
|
|
1648
|
-
first = false;
|
|
1649
|
-
}
|
|
1650
|
-
return best;
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
// src/search.ts
|
|
1654
|
-
var REQUEST_KEYS = ["where", "sort", "skip", "limit", "fields", "omit"];
|
|
1655
|
-
function search(source, request = {}, options = {}) {
|
|
1656
|
-
const plan2 = planRequest(request, options);
|
|
1657
|
-
const collect2 = plan2.collect();
|
|
1658
|
-
const test = plan2.test;
|
|
1659
|
-
each(source, (item, index) => {
|
|
1660
|
-
if (test !== void 0 && !test(item)) return false;
|
|
1661
|
-
return collect2.offer(item, index);
|
|
1662
|
-
});
|
|
1663
|
-
return plan2.shape(collect2.finish());
|
|
1664
|
-
}
|
|
1665
|
-
function planRequest(request, options) {
|
|
1666
|
-
if (!isPlainObject(request)) throw new JqlError(`a request is an object, not ${describe(request)}`);
|
|
1667
|
-
for (const key of Object.keys(request)) {
|
|
1668
|
-
if (!REQUEST_KEYS.includes(key)) throw new JqlError(`"${key}" is not part of a request (${REQUEST_KEYS.join(", ")})${didYouMean(key, REQUEST_KEYS)}`, key);
|
|
1669
|
-
}
|
|
1670
|
-
const vocabulary = checkVocabulary(options.vocabulary);
|
|
1671
|
-
const test = request.where === void 0 ? void 0 : compile(request.where, options);
|
|
1672
|
-
const skip = count3(request.skip, "skip") ?? 0;
|
|
1673
|
-
const limit = count3(request.limit, "limit");
|
|
1674
|
-
const keys = sortKeys(request.sort, vocabulary);
|
|
1675
|
-
const project = request.fields === void 0 ? void 0 : projector(request.fields, vocabulary);
|
|
1676
|
-
const drop = request.omit === void 0 ? void 0 : redactor(request.omit, vocabulary);
|
|
1677
|
-
return {
|
|
1678
|
-
collect: () => collector(keys, skip, limit),
|
|
1679
|
-
test,
|
|
1680
|
-
shape: (items) => {
|
|
1681
|
-
const projected = project === void 0 ? items : items.map(project);
|
|
1682
|
-
return drop === void 0 ? projected : projected.map(drop);
|
|
1683
|
-
}
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
function collector(keys, skip, limit) {
|
|
1687
|
-
return keys.length === 0 ? inOrder(skip, limit) : ranked(keys, skip, limit);
|
|
1688
|
-
}
|
|
1689
|
-
function count3(value, name) {
|
|
1690
|
-
if (value === void 0) return void 0;
|
|
1691
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
1692
|
-
throw new JqlError(`is a whole number of items, zero or more, not ${describe(value)}`, name);
|
|
1693
|
-
}
|
|
1694
|
-
return value;
|
|
1695
|
-
}
|
|
1696
|
-
function sortKeys(sort, vocabulary) {
|
|
1697
|
-
if (sort === void 0) return [];
|
|
1698
|
-
if (!isPlainObject(sort)) throw new JqlError(`is an object of field names to directions, not ${describe(sort)}`, "sort");
|
|
1699
|
-
return Object.keys(sort).map((name) => {
|
|
1700
|
-
const direction = sort[name];
|
|
1701
|
-
const at = `sort.${name}`;
|
|
1702
|
-
if (direction !== 1 && direction !== -1 && direction !== "asc" && direction !== "desc") {
|
|
1703
|
-
throw new JqlError(`a direction is 1, -1, "asc" or "desc", not ${describe(direction)}`, at);
|
|
1704
|
-
}
|
|
1705
|
-
return { reach: reachField(name, vocabulary, at), descending: direction === -1 || direction === "desc" };
|
|
1706
|
-
});
|
|
1707
|
-
}
|
|
1708
|
-
function each(source, visit) {
|
|
1709
|
-
if (Array.isArray(source)) {
|
|
1710
|
-
for (let i2 = 0; i2 < source.length; i2++) if (visit(source[i2], i2)) return;
|
|
1711
|
-
return;
|
|
1712
|
-
}
|
|
1713
|
-
const iterable = source instanceof Map ? source.values() : typeof source[Symbol.iterator] === "function" ? source : void 0;
|
|
1714
|
-
if (iterable === void 0) {
|
|
1715
|
-
const list = source;
|
|
1716
|
-
for (let i2 = 0; i2 < list.length; i2++) if (visit(list[i2], i2)) return;
|
|
1717
|
-
return;
|
|
1718
|
-
}
|
|
1719
|
-
let i = 0;
|
|
1720
|
-
for (const item of iterable) if (visit(item, i++)) return;
|
|
1721
|
-
}
|
|
1722
|
-
function inOrder(skip, limit) {
|
|
1723
|
-
const out = [];
|
|
1724
|
-
let passed = 0;
|
|
1725
|
-
return {
|
|
1726
|
-
offer(item) {
|
|
1727
|
-
if (limit === 0) return true;
|
|
1728
|
-
if (passed < skip) {
|
|
1729
|
-
passed++;
|
|
1730
|
-
return false;
|
|
1731
|
-
}
|
|
1732
|
-
out.push(item);
|
|
1733
|
-
return limit !== void 0 && out.length >= limit;
|
|
1734
|
-
},
|
|
1735
|
-
finish: () => out
|
|
1736
|
-
};
|
|
1737
|
-
}
|
|
1738
|
-
function ranked(keys, skip, limit) {
|
|
1739
|
-
const compare = (a, b) => {
|
|
1740
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1741
|
-
const order = compareValues(a.keys[i], b.keys[i]);
|
|
1742
|
-
if (order !== 0) return keys[i].descending ? -order : order;
|
|
1743
|
-
}
|
|
1744
|
-
return a.index - b.index;
|
|
1745
|
-
};
|
|
1746
|
-
const keep = limit === void 0 ? Number.POSITIVE_INFINITY : skip + limit;
|
|
1747
|
-
const heap = [];
|
|
1748
|
-
return {
|
|
1749
|
-
offer(item, index) {
|
|
1750
|
-
if (limit === 0) return true;
|
|
1751
|
-
const entry = { item, keys: keys.map((key) => keyOf(item, key)), index };
|
|
1752
|
-
if (heap.length < keep) {
|
|
1753
|
-
heap.push(entry);
|
|
1754
|
-
if (keep !== Number.POSITIVE_INFINITY) siftUp(heap, heap.length - 1, compare);
|
|
1755
|
-
} else if (compare(entry, heap[0]) < 0) {
|
|
1756
|
-
heap[0] = entry;
|
|
1757
|
-
siftDown(heap, 0, compare);
|
|
1758
|
-
}
|
|
1759
|
-
return false;
|
|
1760
|
-
},
|
|
1761
|
-
finish() {
|
|
1762
|
-
heap.sort(compare);
|
|
1763
|
-
return heap.slice(skip).map((entry) => entry.item);
|
|
1764
|
-
}
|
|
1765
|
-
};
|
|
1766
|
-
}
|
|
1767
|
-
function keyOf(item, key) {
|
|
1768
|
-
const values2 = [];
|
|
1769
|
-
key.reach(item, (value) => {
|
|
1770
|
-
values2.push(value);
|
|
1771
|
-
return false;
|
|
1772
|
-
});
|
|
1773
|
-
return sortValue(values2, key.descending);
|
|
1774
|
-
}
|
|
1775
|
-
function siftUp(heap, at, compare) {
|
|
1776
|
-
let child = at;
|
|
1777
|
-
while (child > 0) {
|
|
1778
|
-
const parent = child - 1 >> 1;
|
|
1779
|
-
if (compare(heap[child], heap[parent]) <= 0) return;
|
|
1780
|
-
[heap[child], heap[parent]] = [heap[parent], heap[child]];
|
|
1781
|
-
child = parent;
|
|
1782
|
-
}
|
|
1783
|
-
}
|
|
1784
|
-
function siftDown(heap, at, compare) {
|
|
1785
|
-
let parent = at;
|
|
1786
|
-
for (; ; ) {
|
|
1787
|
-
const left = parent * 2 + 1;
|
|
1788
|
-
const right = left + 1;
|
|
1789
|
-
let largest = parent;
|
|
1790
|
-
if (left < heap.length && compare(heap[left], heap[largest]) > 0) largest = left;
|
|
1791
|
-
if (right < heap.length && compare(heap[right], heap[largest]) > 0) largest = right;
|
|
1792
|
-
if (largest === parent) return;
|
|
1793
|
-
[heap[parent], heap[largest]] = [heap[largest], heap[parent]];
|
|
1794
|
-
parent = largest;
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
function projector(fields, vocabulary) {
|
|
1798
|
-
if (!Array.isArray(fields)) throw new JqlError(`is a list of field names, not ${describe(fields)}`, "fields");
|
|
1799
|
-
const tree = /* @__PURE__ */ new Map();
|
|
1800
|
-
const computed = [];
|
|
1801
|
-
fields.forEach((name, index) => {
|
|
1802
|
-
const at = `fields[${index}]`;
|
|
1803
|
-
if (typeof name !== "string") throw new JqlError(`a field name is a string, not ${describe(name)}`, at);
|
|
1804
|
-
const field = vocabulary?.lookup.get(name.toLowerCase());
|
|
1805
|
-
if (field?.get !== void 0) {
|
|
1806
|
-
computed.push([field.name, field.get]);
|
|
1807
|
-
return;
|
|
1808
|
-
}
|
|
1809
|
-
const keys = splitPath(field?.path ?? name);
|
|
1810
|
-
if (typeof keys === "string") throw new JqlError(keys, at);
|
|
1811
|
-
let node2 = tree;
|
|
1812
|
-
for (let position = 0; position < keys.length; position++) {
|
|
1813
|
-
const key = keys[position];
|
|
1814
|
-
const existing = node2.get(key);
|
|
1815
|
-
if (existing === true) break;
|
|
1816
|
-
if (position === keys.length - 1) {
|
|
1817
|
-
node2.set(key, true);
|
|
1818
|
-
break;
|
|
1819
|
-
}
|
|
1820
|
-
if (existing === void 0) {
|
|
1821
|
-
const child = /* @__PURE__ */ new Map();
|
|
1822
|
-
node2.set(key, child);
|
|
1823
|
-
node2 = child;
|
|
1824
|
-
} else node2 = existing;
|
|
1825
|
-
}
|
|
1826
|
-
});
|
|
1827
|
-
return (item) => {
|
|
1828
|
-
const out = pick(item, tree, 0) ?? {};
|
|
1829
|
-
for (const [name, get] of computed) setField(out, name, get(item));
|
|
1830
|
-
return out;
|
|
1831
|
-
};
|
|
1832
|
-
}
|
|
1833
|
-
function redactor(omit, vocabulary) {
|
|
1834
|
-
if (!Array.isArray(omit)) throw new JqlError(`is a list of field names, not ${describe(omit)}`, "omit");
|
|
1835
|
-
const tree = /* @__PURE__ */ new Map();
|
|
1836
|
-
omit.forEach((name, index) => {
|
|
1837
|
-
const at = `omit[${index}]`;
|
|
1838
|
-
if (typeof name !== "string") throw new JqlError(`a field name is a string, not ${describe(name)}`, at);
|
|
1839
|
-
const field = vocabulary?.lookup.get(name.toLowerCase());
|
|
1840
|
-
const keys = field?.get !== void 0 ? [field.name] : splitPath(field?.path ?? name);
|
|
1841
|
-
if (typeof keys === "string") throw new JqlError(keys, at);
|
|
1842
|
-
let node2 = tree;
|
|
1843
|
-
for (let position = 0; position < keys.length; position++) {
|
|
1844
|
-
const key = keys[position];
|
|
1845
|
-
if (position === keys.length - 1) {
|
|
1846
|
-
node2.set(key, true);
|
|
1847
|
-
break;
|
|
1848
|
-
}
|
|
1849
|
-
const existing = node2.get(key);
|
|
1850
|
-
if (existing === true) break;
|
|
1851
|
-
if (existing === void 0) {
|
|
1852
|
-
const child = /* @__PURE__ */ new Map();
|
|
1853
|
-
node2.set(key, child);
|
|
1854
|
-
node2 = child;
|
|
1855
|
-
} else node2 = existing;
|
|
1856
|
-
}
|
|
1857
|
-
});
|
|
1858
|
-
return (item) => without(item, tree, 0);
|
|
1859
|
-
}
|
|
1860
|
-
var MAX_REDACT_DEPTH = 512;
|
|
1861
|
-
function without(value, tree, depth) {
|
|
1862
|
-
if (depth > MAX_REDACT_DEPTH) {
|
|
1863
|
-
throw new JqlError(`an item nests deeper than ${MAX_REDACT_DEPTH} levels, so it cannot be redacted; nothing was dropped from it`, "omit");
|
|
1864
|
-
}
|
|
1865
|
-
if (value === null || typeof value !== "object") return value;
|
|
1866
|
-
if (Array.isArray(value)) {
|
|
1867
|
-
let changed2 = false;
|
|
1868
|
-
const copy = value.map((element) => {
|
|
1869
|
-
const kept = without(element, tree, depth + 1);
|
|
1870
|
-
if (kept !== element) changed2 = true;
|
|
1871
|
-
return kept;
|
|
1872
|
-
});
|
|
1873
|
-
return changed2 ? copy : value;
|
|
1874
|
-
}
|
|
1875
|
-
if (value instanceof Map) {
|
|
1876
|
-
let changed2 = false;
|
|
1877
|
-
const copy = /* @__PURE__ */ new Map();
|
|
1878
|
-
for (const [key, held] of value) {
|
|
1879
|
-
const sub = typeof key === "string" ? tree.get(key) : void 0;
|
|
1880
|
-
if (sub === true) {
|
|
1881
|
-
changed2 = true;
|
|
1882
|
-
continue;
|
|
1883
|
-
}
|
|
1884
|
-
const kept = sub === void 0 ? held : without(held, sub, depth + 1);
|
|
1885
|
-
if (kept !== held) changed2 = true;
|
|
1886
|
-
copy.set(key, kept);
|
|
1887
|
-
}
|
|
1888
|
-
return changed2 ? copy : value;
|
|
1889
|
-
}
|
|
1890
|
-
const record = value;
|
|
1891
|
-
const keys = Object.keys(record);
|
|
1892
|
-
if (!keys.some((key) => tree.has(key))) return value;
|
|
1893
|
-
const out = {};
|
|
1894
|
-
let changed = false;
|
|
1895
|
-
for (const key of keys) {
|
|
1896
|
-
const sub = tree.get(key);
|
|
1897
|
-
if (sub === true) {
|
|
1898
|
-
changed = true;
|
|
1899
|
-
continue;
|
|
1900
|
-
}
|
|
1901
|
-
const held = record[key];
|
|
1902
|
-
const kept = sub === void 0 ? held : without(held, sub, depth + 1);
|
|
1903
|
-
if (kept !== held) changed = true;
|
|
1904
|
-
setField(out, key, kept);
|
|
1905
|
-
}
|
|
1906
|
-
return changed ? out : value;
|
|
1907
|
-
}
|
|
1908
|
-
function pick(value, tree, depth) {
|
|
1909
|
-
if (value === null || typeof value !== "object" || depth > MAX_PATH_SEGMENTS) return void 0;
|
|
1910
|
-
const out = {};
|
|
1911
|
-
for (const [key, sub] of tree) {
|
|
1912
|
-
const found = readOwn(value, key);
|
|
1913
|
-
if (found === void 0) continue;
|
|
1914
|
-
if (sub === true) setField(out, key, found);
|
|
1915
|
-
else if (Array.isArray(found)) setField(out, key, found.map((element) => pick(element, sub, depth + 1)).filter((element) => element !== void 0));
|
|
1916
|
-
else {
|
|
1917
|
-
const inner = pick(found, sub, depth + 1);
|
|
1918
|
-
if (inner !== void 0) setField(out, key, inner);
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
return out;
|
|
1922
|
-
}
|
|
3
|
+
var chunk2ZMIVDES_cjs = require('./chunk-2ZMIVDES.cjs');
|
|
4
|
+
var chunkEJFHVGBC_cjs = require('./chunk-EJFHVGBC.cjs');
|
|
5
|
+
require('./chunk-ITPY6VTV.cjs');
|
|
6
|
+
var chunk74QKHM6Y_cjs = require('./chunk-74QKHM6Y.cjs');
|
|
1923
7
|
|
|
1924
8
|
// src/group.ts
|
|
1925
9
|
function group(source, by, options = {}) {
|
|
1926
|
-
if (typeof by !== "string") throw new JqlError(`a group is named by a field, not ${describe(by)}`, "by");
|
|
10
|
+
if (typeof by !== "string") throw new chunk74QKHM6Y_cjs.JqlError(`a group is named by a field, not ${chunk74QKHM6Y_cjs.describe(by)}`, "by");
|
|
1927
11
|
if (options.limit !== void 0 && (!Number.isInteger(options.limit) || options.limit < 0)) {
|
|
1928
|
-
throw new JqlError(`is a whole number of groups, zero or more, not ${describe(options.limit)}`, "limit");
|
|
12
|
+
throw new chunk74QKHM6Y_cjs.JqlError(`is a whole number of groups, zero or more, not ${chunk74QKHM6Y_cjs.describe(options.limit)}`, "limit");
|
|
1929
13
|
}
|
|
1930
14
|
if (options.items !== void 0 && typeof options.items !== "boolean" && (!Number.isInteger(options.items) || options.items < 0)) {
|
|
1931
|
-
throw new JqlError(`is true, false, or how many items to keep, not ${describe(options.items)}`, "items");
|
|
15
|
+
throw new chunk74QKHM6Y_cjs.JqlError(`is true, false, or how many items to keep, not ${chunk74QKHM6Y_cjs.describe(options.items)}`, "items");
|
|
1932
16
|
}
|
|
1933
|
-
const reach = reachField(by, checkVocabulary(options.vocabulary), "by");
|
|
1934
|
-
const test = options.where === void 0 ? void 0 : compile(options.where, options);
|
|
17
|
+
const reach = chunk2ZMIVDES_cjs.reachField(by, chunkEJFHVGBC_cjs.checkVocabulary(options.vocabulary), "by");
|
|
18
|
+
const test = options.where === void 0 ? void 0 : chunk2ZMIVDES_cjs.compile(options.where, options);
|
|
1935
19
|
const keep = options.items === true ? Number.POSITIVE_INFINITY : options.items === void 0 || options.items === false ? 0 : options.items;
|
|
1936
20
|
const groups = /* @__PURE__ */ new Map();
|
|
1937
21
|
const keys = [];
|
|
@@ -1960,7 +44,7 @@ function group(source, by, options = {}) {
|
|
|
1960
44
|
for (let i = 0; i < list.length; i++) visit(list[i]);
|
|
1961
45
|
}
|
|
1962
46
|
const byKey = options.sort === "key";
|
|
1963
|
-
const found = [...groups.values()].sort((a, b) => byKey ? compareValues(a.key, b.key) : b.count - a.count || compareValues(a.key, b.key));
|
|
47
|
+
const found = [...groups.values()].sort((a, b) => byKey ? chunk2ZMIVDES_cjs.compareValues(a.key, b.key) : b.count - a.count || chunk2ZMIVDES_cjs.compareValues(a.key, b.key));
|
|
1964
48
|
const limited = options.limit === void 0 ? found : found.slice(0, options.limit);
|
|
1965
49
|
return limited.map((held) => keep > 0 ? { key: held.key, count: held.count, items: held.items } : { key: held.key, count: held.count });
|
|
1966
50
|
}
|
|
@@ -1978,21 +62,21 @@ function collect(value, into) {
|
|
|
1978
62
|
}
|
|
1979
63
|
|
|
1980
64
|
// src/explain.ts
|
|
1981
|
-
var
|
|
65
|
+
var FIELD_OPERATOR_SET = new Set(chunk2ZMIVDES_cjs.FIELD_OPERATORS);
|
|
1982
66
|
function explain(query, item, options = {}) {
|
|
1983
67
|
return node(query, item, "", options);
|
|
1984
68
|
}
|
|
1985
69
|
function matchedBy(clause, item, options) {
|
|
1986
|
-
return compile(clause, options)(item);
|
|
70
|
+
return chunk2ZMIVDES_cjs.compile(clause, options)(item);
|
|
1987
71
|
}
|
|
1988
72
|
function node(clause, item, at, options) {
|
|
1989
|
-
if (typeof clause === "function" || !isPlainObject(clause)) {
|
|
73
|
+
if (typeof clause === "function" || !chunk74QKHM6Y_cjs.isPlainObject(clause)) {
|
|
1990
74
|
return leaf(clause, item, at, options, typeof clause === "function" ? "a predicate of your own" : "the whole query");
|
|
1991
75
|
}
|
|
1992
76
|
const keys = Object.keys(clause);
|
|
1993
77
|
if (keys.length === 0) return { matched: true, at, clause, because: "an empty query matches everything" };
|
|
1994
78
|
if (keys.length > 1) {
|
|
1995
|
-
const self = keys.filter((key2) => key2 !== "$not" &&
|
|
79
|
+
const self = keys.filter((key2) => key2 !== "$not" && FIELD_OPERATOR_SET.has(key2));
|
|
1996
80
|
const rest = keys.filter((key2) => !self.includes(key2));
|
|
1997
81
|
const parts = rest.map((key2) => node({ [key2]: clause[key2] }, item, at, options));
|
|
1998
82
|
if (self.length > 0) {
|
|
@@ -2004,7 +88,7 @@ function node(clause, item, at, options) {
|
|
|
2004
88
|
}
|
|
2005
89
|
const key = keys[0];
|
|
2006
90
|
const value = clause[key];
|
|
2007
|
-
const here =
|
|
91
|
+
const here = join(at, key);
|
|
2008
92
|
switch (key) {
|
|
2009
93
|
case "$and":
|
|
2010
94
|
case "$or":
|
|
@@ -2024,10 +108,10 @@ function node(clause, item, at, options) {
|
|
|
2024
108
|
};
|
|
2025
109
|
}
|
|
2026
110
|
}
|
|
2027
|
-
if (!key.startsWith("$") && isPlainObject(value) && !isFieldReference(value) && Object.keys(value).length > 1 && Object.keys(value).every((name) => name.startsWith("$"))) {
|
|
111
|
+
if (!key.startsWith("$") && chunk74QKHM6Y_cjs.isPlainObject(value) && !chunk74QKHM6Y_cjs.isFieldReference(value) && Object.keys(value).length > 1 && Object.keys(value).every((name) => name.startsWith("$"))) {
|
|
2028
112
|
const operators = Object.keys(value).filter((name) => name !== "$options");
|
|
2029
113
|
const flags = value.$options === void 0 ? {} : { $options: value.$options };
|
|
2030
|
-
const parts = operators.map((name) => leaf({ [key]: { [name]: value[name], ...CASE_AWARE.has(name) ? flags : {} } }, item,
|
|
114
|
+
const parts = operators.map((name) => leaf({ [key]: { [name]: value[name], ...chunk2ZMIVDES_cjs.CASE_AWARE.has(name) ? flags : {} } }, item, join(here, name), options, key));
|
|
2031
115
|
return branch(clause, here, parts, "and");
|
|
2032
116
|
}
|
|
2033
117
|
return leaf(clause, item, here, options, key);
|
|
@@ -2046,13 +130,13 @@ function leaf(clause, item, at, options, key) {
|
|
|
2046
130
|
function reason(clause, item, options, key) {
|
|
2047
131
|
if (key === "$text") return matchedBy(clause, item, options) ? "the item holds that text" : "no value of the item holds that text";
|
|
2048
132
|
if (key === "$comment") return "a comment decides nothing";
|
|
2049
|
-
if (key.startsWith("$") &&
|
|
2050
|
-
if (!isPlainObject(clause)) return "the clause was run as given";
|
|
133
|
+
if (key.startsWith("$") && FIELD_OPERATOR_SET.has(key)) return `the item itself is ${values(item === void 0 ? [] : [item])}`;
|
|
134
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(clause)) return "the clause was run as given";
|
|
2051
135
|
const path = Object.keys(clause)[0];
|
|
2052
136
|
if (path === void 0 || path.startsWith("$")) return "the clause was run as given";
|
|
2053
137
|
const found = [];
|
|
2054
138
|
try {
|
|
2055
|
-
reachField(path, options.vocabulary, path)(item, (value) => {
|
|
139
|
+
chunk2ZMIVDES_cjs.reachField(path, options.vocabulary, path)(item, (value) => {
|
|
2056
140
|
if (found.length < 4) found.push(value);
|
|
2057
141
|
return false;
|
|
2058
142
|
});
|
|
@@ -2076,7 +160,7 @@ function shorten(value) {
|
|
|
2076
160
|
}
|
|
2077
161
|
return text2.length > 60 ? `${text2.slice(0, 60)}\u2026` : text2;
|
|
2078
162
|
}
|
|
2079
|
-
function
|
|
163
|
+
function join(at, key) {
|
|
2080
164
|
return at === "" ? key : `${at}.${key}`;
|
|
2081
165
|
}
|
|
2082
166
|
|
|
@@ -2086,15 +170,15 @@ var QUERIES = /* @__PURE__ */ new Set(["$elemMatch"]);
|
|
|
2086
170
|
var LOGIC = /* @__PURE__ */ new Set(["$and", "$or", "$nor"]);
|
|
2087
171
|
function canonical(query, options) {
|
|
2088
172
|
if (typeof query === "function") throw new TypeError("a compiled predicate has no canonical form: it is code, not a query");
|
|
2089
|
-
compile(query, options);
|
|
173
|
+
chunk2ZMIVDES_cjs.compile(query, options);
|
|
2090
174
|
return rewrite(query);
|
|
2091
175
|
}
|
|
2092
176
|
function fingerprint(query, options) {
|
|
2093
177
|
return checksum(JSON.stringify(canonical(query, options)) ?? "");
|
|
2094
178
|
}
|
|
2095
179
|
function rewrite(value) {
|
|
2096
|
-
if (!isPlainObject(value)) return value;
|
|
2097
|
-
if (isDateLiteral(value) || isFieldReference(value)) return value;
|
|
180
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value)) return value;
|
|
181
|
+
if (chunk74QKHM6Y_cjs.isDateLiteral(value) || chunk74QKHM6Y_cjs.isFieldReference(value)) return value;
|
|
2098
182
|
const out = {};
|
|
2099
183
|
const keys = Object.keys(value).sort().filter((key) => key !== "$comment");
|
|
2100
184
|
const alone = keys.length === 1;
|
|
@@ -2129,7 +213,7 @@ function fold(out) {
|
|
|
2129
213
|
const lifted = {};
|
|
2130
214
|
const kept = [];
|
|
2131
215
|
for (const part of parts) {
|
|
2132
|
-
const keys = isPlainObject(part) ? Object.keys(part) : void 0;
|
|
216
|
+
const keys = chunk74QKHM6Y_cjs.isPlainObject(part) ? Object.keys(part) : void 0;
|
|
2133
217
|
if (keys === void 0 || keys.length === 0 || keys.some((key) => taken.has(key))) {
|
|
2134
218
|
kept.push(part);
|
|
2135
219
|
continue;
|
|
@@ -2148,7 +232,7 @@ function fold(out) {
|
|
|
2148
232
|
return sorted;
|
|
2149
233
|
}
|
|
2150
234
|
function condition(value) {
|
|
2151
|
-
if (isPlainObject(value) && !isDateLiteral(value) && !isFieldReference(value) && Object.keys(value).length > 0 && Object.keys(value).every((key) => key.startsWith("$"))) {
|
|
235
|
+
if (chunk74QKHM6Y_cjs.isPlainObject(value) && !chunk74QKHM6Y_cjs.isDateLiteral(value) && !chunk74QKHM6Y_cjs.isFieldReference(value) && Object.keys(value).length > 0 && Object.keys(value).every((key) => key.startsWith("$"))) {
|
|
2152
236
|
const out = {};
|
|
2153
237
|
for (const key of Object.keys(value).sort()) out[key] = key === "$not" ? condition(value[key]) : operand(key, value[key]);
|
|
2154
238
|
return out;
|
|
@@ -2163,18 +247,18 @@ function operand(key, value) {
|
|
|
2163
247
|
return types.length === 1 ? types[0] : types;
|
|
2164
248
|
}
|
|
2165
249
|
if (key === "$options" && typeof value === "string") return [...value].sort().join("");
|
|
2166
|
-
if ((key === "$size" || key === "$length") && isPlainObject(value)) return condition(value);
|
|
250
|
+
if ((key === "$size" || key === "$length") && chunk74QKHM6Y_cjs.isPlainObject(value)) return condition(value);
|
|
2167
251
|
return literal(value);
|
|
2168
252
|
}
|
|
2169
253
|
function literal(value) {
|
|
2170
254
|
if (Array.isArray(value)) return value.map(literal);
|
|
2171
|
-
if (!isPlainObject(value) || isDateLiteral(value) || isFieldReference(value)) return value;
|
|
255
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value) || chunk74QKHM6Y_cjs.isDateLiteral(value) || chunk74QKHM6Y_cjs.isFieldReference(value)) return value;
|
|
2172
256
|
const out = {};
|
|
2173
257
|
for (const key of Object.keys(value).sort()) out[key] = literal(value[key]);
|
|
2174
258
|
return out;
|
|
2175
259
|
}
|
|
2176
260
|
function text(value) {
|
|
2177
|
-
const search2 = typeof value === "string" ? { $search: value } : isPlainObject(value) ? value : void 0;
|
|
261
|
+
const search2 = typeof value === "string" ? { $search: value } : chunk74QKHM6Y_cjs.isPlainObject(value) ? value : void 0;
|
|
2178
262
|
if (search2 === void 0) return value;
|
|
2179
263
|
const out = { $search: search2.$search };
|
|
2180
264
|
if (Array.isArray(search2.$fields)) out.$fields = unique(search2.$fields);
|
|
@@ -2185,7 +269,7 @@ function flatten(key, parts) {
|
|
|
2185
269
|
if (key === "$nor") return [...parts];
|
|
2186
270
|
const out = [];
|
|
2187
271
|
for (const part of parts) {
|
|
2188
|
-
const inner = isPlainObject(part) && Object.keys(part).length === 1 ? part[key] : void 0;
|
|
272
|
+
const inner = chunk74QKHM6Y_cjs.isPlainObject(part) && Object.keys(part).length === 1 ? part[key] : void 0;
|
|
2189
273
|
if (Array.isArray(inner)) out.push(...flatten(key, inner));
|
|
2190
274
|
else out.push(part);
|
|
2191
275
|
}
|
|
@@ -2216,10 +300,10 @@ function checksum(text2) {
|
|
|
2216
300
|
}
|
|
2217
301
|
|
|
2218
302
|
// src/plan.ts
|
|
2219
|
-
var KNOWN = /* @__PURE__ */ new Set([...FIELD_OPERATORS, ...QUERY_OPERATORS, "$field"]);
|
|
303
|
+
var KNOWN = /* @__PURE__ */ new Set([...chunk2ZMIVDES_cjs.FIELD_OPERATORS, ...chunk2ZMIVDES_cjs.QUERY_OPERATORS, "$field"]);
|
|
2220
304
|
function plan(query, capabilities, options = {}) {
|
|
2221
305
|
if (typeof query === "function") throw new TypeError("a compiled predicate cannot be split: it is code, not a query");
|
|
2222
|
-
const verdict = validate(query, options);
|
|
306
|
+
const verdict = chunk2ZMIVDES_cjs.validate(query, options);
|
|
2223
307
|
if (!verdict.valid) throw verdict.error;
|
|
2224
308
|
const now = options.now === void 0 ? Date.now() : options.now();
|
|
2225
309
|
const vocabulary = options.vocabulary;
|
|
@@ -2246,8 +330,8 @@ function plan(query, capabilities, options = {}) {
|
|
|
2246
330
|
}
|
|
2247
331
|
}
|
|
2248
332
|
return {
|
|
2249
|
-
pushed:
|
|
2250
|
-
remaining:
|
|
333
|
+
pushed: join2(pushed),
|
|
334
|
+
remaining: join2(stays),
|
|
2251
335
|
complete: stays.length === 0,
|
|
2252
336
|
kept
|
|
2253
337
|
};
|
|
@@ -2259,7 +343,7 @@ function conjuncts(query, at) {
|
|
|
2259
343
|
if (key === "$comment") continue;
|
|
2260
344
|
if (key === "$and" && Array.isArray(value)) {
|
|
2261
345
|
value.forEach((part, index) => {
|
|
2262
|
-
if (isPlainObject(part)) out.push(...conjuncts(part, `${here}[${index}]`));
|
|
346
|
+
if (chunk74QKHM6Y_cjs.isPlainObject(part)) out.push(...conjuncts(part, `${here}[${index}]`));
|
|
2263
347
|
});
|
|
2264
348
|
continue;
|
|
2265
349
|
}
|
|
@@ -2267,7 +351,7 @@ function conjuncts(query, at) {
|
|
|
2267
351
|
}
|
|
2268
352
|
return out;
|
|
2269
353
|
}
|
|
2270
|
-
function
|
|
354
|
+
function join2(parts) {
|
|
2271
355
|
if (parts.length === 0) return void 0;
|
|
2272
356
|
const query = parts.length === 1 ? parts[0] : { $and: parts };
|
|
2273
357
|
return query;
|
|
@@ -2289,7 +373,7 @@ function unpushableOperator(key, value, context, at) {
|
|
|
2289
373
|
case "$and":
|
|
2290
374
|
if (!Array.isArray(value)) return "the clause is malformed";
|
|
2291
375
|
for (const part of value) {
|
|
2292
|
-
if (!isPlainObject(part)) return "the clause is malformed";
|
|
376
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(part)) return "the clause is malformed";
|
|
2293
377
|
const why = unpushable(part, context);
|
|
2294
378
|
if (why !== void 0) return why;
|
|
2295
379
|
}
|
|
@@ -2301,7 +385,7 @@ function unpushableOperator(key, value, context, at) {
|
|
|
2301
385
|
if (!context.or && key === "$nor") return "the store cannot answer an $or";
|
|
2302
386
|
if (!Array.isArray(value) || value.length === 0) return "the clause is malformed";
|
|
2303
387
|
for (const part of value) {
|
|
2304
|
-
if (!isPlainObject(part)) return "the clause is malformed";
|
|
388
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(part)) return "the clause is malformed";
|
|
2305
389
|
const why = unpushable(part, context);
|
|
2306
390
|
if (why !== void 0) return why;
|
|
2307
391
|
}
|
|
@@ -2309,7 +393,7 @@ function unpushableOperator(key, value, context, at) {
|
|
|
2309
393
|
}
|
|
2310
394
|
case "$not": {
|
|
2311
395
|
if (!context.not) return "the store cannot answer a negation";
|
|
2312
|
-
if (!isPlainObject(value)) return "the clause is malformed";
|
|
396
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value)) return "the clause is malformed";
|
|
2313
397
|
return unpushable(value, context);
|
|
2314
398
|
}
|
|
2315
399
|
case "$text":
|
|
@@ -2323,8 +407,8 @@ function unpushableField(name, value, context, at) {
|
|
|
2323
407
|
if (field?.get !== void 0) return `"${name}" is computed here, so the store has no such field`;
|
|
2324
408
|
const stored = storedName(name, context);
|
|
2325
409
|
if (context.fields !== "all" && !context.fields.has(stored)) return `the store cannot filter on "${stored}"`;
|
|
2326
|
-
if (isFieldReference(value)) return allows(context, "$field") ? void 0 : "the store cannot compare two fields";
|
|
2327
|
-
if (!isPlainObject(value) || isDateLiteral(value)) {
|
|
410
|
+
if (chunk74QKHM6Y_cjs.isFieldReference(value)) return allows(context, "$field") ? void 0 : "the store cannot compare two fields";
|
|
411
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value) || chunk74QKHM6Y_cjs.isDateLiteral(value)) {
|
|
2328
412
|
if (!allows(context, "$eq")) return 'the store cannot answer "$eq"';
|
|
2329
413
|
return accepted(context, stored, { $eq: value });
|
|
2330
414
|
}
|
|
@@ -2341,14 +425,14 @@ function unpushableField(name, value, context, at) {
|
|
|
2341
425
|
return "the store cannot answer a negation";
|
|
2342
426
|
}
|
|
2343
427
|
const operand2 = value[key];
|
|
2344
|
-
if (isFieldReference(operand2) && !allows(context, "$field")) return "the store cannot compare two fields";
|
|
428
|
+
if (chunk74QKHM6Y_cjs.isFieldReference(operand2) && !allows(context, "$field")) return "the store cannot compare two fields";
|
|
2345
429
|
if (key === "$elemMatch") {
|
|
2346
|
-
if (!isPlainObject(operand2)) return "the clause is malformed";
|
|
430
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(operand2)) return "the clause is malformed";
|
|
2347
431
|
const why = unpushable(operand2, context);
|
|
2348
432
|
if (why !== void 0) return why;
|
|
2349
433
|
}
|
|
2350
434
|
if (key === "$not") {
|
|
2351
|
-
if (!isPlainObject(operand2)) return "the clause is malformed";
|
|
435
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(operand2)) return "the clause is malformed";
|
|
2352
436
|
const why = unpushableField(name, operand2, context);
|
|
2353
437
|
if (why !== void 0) return why;
|
|
2354
438
|
}
|
|
@@ -2363,7 +447,7 @@ function allows(context, operator) {
|
|
|
2363
447
|
return context.operators === "all" || context.operators.has(operator);
|
|
2364
448
|
}
|
|
2365
449
|
function resolve(value, context) {
|
|
2366
|
-
if (!isPlainObject(value)) return value;
|
|
450
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value)) return value;
|
|
2367
451
|
const out = {};
|
|
2368
452
|
for (const [key, held] of Object.entries(value)) {
|
|
2369
453
|
switch (key) {
|
|
@@ -2387,8 +471,8 @@ function resolve(value, context) {
|
|
|
2387
471
|
return out;
|
|
2388
472
|
}
|
|
2389
473
|
function resolveCondition(value, context) {
|
|
2390
|
-
if (!isPlainObject(value)) return resolveLiteral(value, context);
|
|
2391
|
-
if (isDateLiteral(value) || isFieldReference(value)) return resolveOperand("$eq", value, context);
|
|
474
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value)) return resolveLiteral(value, context);
|
|
475
|
+
if (chunk74QKHM6Y_cjs.isDateLiteral(value) || chunk74QKHM6Y_cjs.isFieldReference(value)) return resolveOperand("$eq", value, context);
|
|
2392
476
|
const keys = Object.keys(value);
|
|
2393
477
|
if (keys.length === 0 || !keys.every((key) => key.startsWith("$"))) return resolveLiteral(value, context);
|
|
2394
478
|
const out = {};
|
|
@@ -2398,20 +482,20 @@ function resolveCondition(value, context) {
|
|
|
2398
482
|
function resolveOperand(key, operand2, context) {
|
|
2399
483
|
if (key === "$elemMatch") return resolve(operand2, context);
|
|
2400
484
|
if (key === "$not") return resolveCondition(operand2, context);
|
|
2401
|
-
if (isFieldReference(operand2)) return { $field: storedName(operand2.$field, context) };
|
|
2402
|
-
if (Array.isArray(operand2)) return operand2.map((item) => isFieldReference(item) ? { $field: storedName(item.$field, context) } : resolveLiteral(item, context));
|
|
485
|
+
if (chunk74QKHM6Y_cjs.isFieldReference(operand2)) return { $field: storedName(operand2.$field, context) };
|
|
486
|
+
if (Array.isArray(operand2)) return operand2.map((item) => chunk74QKHM6Y_cjs.isFieldReference(item) ? { $field: storedName(item.$field, context) } : resolveLiteral(item, context));
|
|
2403
487
|
return resolveLiteral(operand2, context);
|
|
2404
488
|
}
|
|
2405
489
|
function resolveText(value, context) {
|
|
2406
|
-
if (!isPlainObject(value) || !Array.isArray(value.$fields)) return value;
|
|
490
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value) || !Array.isArray(value.$fields)) return value;
|
|
2407
491
|
return { ...value, $fields: value.$fields.map((name) => typeof name === "string" ? storedName(name, context) : name) };
|
|
2408
492
|
}
|
|
2409
493
|
function resolveLiteral(value, context) {
|
|
2410
494
|
if (Array.isArray(value)) return value.map((item) => resolveLiteral(item, context));
|
|
2411
|
-
if (!isPlainObject(value)) return value;
|
|
2412
|
-
if (isDateLiteral(value)) {
|
|
2413
|
-
const time = resolveDate(value.$date, context.now);
|
|
2414
|
-
if (Number.isNaN(time)) throw new JqlError(`${JSON.stringify(value.$date)} is not a date`);
|
|
495
|
+
if (!chunk74QKHM6Y_cjs.isPlainObject(value)) return value;
|
|
496
|
+
if (chunk74QKHM6Y_cjs.isDateLiteral(value)) {
|
|
497
|
+
const time = chunk74QKHM6Y_cjs.resolveDate(value.$date, context.now);
|
|
498
|
+
if (Number.isNaN(time)) throw new chunk74QKHM6Y_cjs.JqlError(`${JSON.stringify(value.$date)} is not a date`);
|
|
2415
499
|
return { $date: time };
|
|
2416
500
|
}
|
|
2417
501
|
const out = {};
|
|
@@ -2452,7 +536,7 @@ async function* iterate(source) {
|
|
|
2452
536
|
for (let i = 0; i < list.length; i++) yield list[i];
|
|
2453
537
|
}
|
|
2454
538
|
async function* filterStream(source, query, options) {
|
|
2455
|
-
const test = compile(query, options);
|
|
539
|
+
const test = chunk2ZMIVDES_cjs.compile(query, options);
|
|
2456
540
|
for await (const item of iterate(source)) if (test(item)) yield item;
|
|
2457
541
|
}
|
|
2458
542
|
async function findAsync(source, query, options) {
|
|
@@ -2466,22 +550,22 @@ async function filterAsync(source, query, options) {
|
|
|
2466
550
|
}
|
|
2467
551
|
async function countAsync(source, query, options) {
|
|
2468
552
|
let total = 0;
|
|
2469
|
-
const test = compile(query, options);
|
|
553
|
+
const test = chunk2ZMIVDES_cjs.compile(query, options);
|
|
2470
554
|
for await (const item of iterate(source)) if (test(item)) total++;
|
|
2471
555
|
return total;
|
|
2472
556
|
}
|
|
2473
557
|
async function someAsync(source, query, options) {
|
|
2474
|
-
const test = compile(query, options);
|
|
558
|
+
const test = chunk2ZMIVDES_cjs.compile(query, options);
|
|
2475
559
|
for await (const item of iterate(source)) if (test(item)) return true;
|
|
2476
560
|
return false;
|
|
2477
561
|
}
|
|
2478
562
|
async function everyAsync(source, query, options) {
|
|
2479
|
-
const test = compile(query, options);
|
|
563
|
+
const test = chunk2ZMIVDES_cjs.compile(query, options);
|
|
2480
564
|
for await (const item of iterate(source)) if (!test(item)) return false;
|
|
2481
565
|
return true;
|
|
2482
566
|
}
|
|
2483
567
|
async function searchAsync(source, request = {}, options = {}) {
|
|
2484
|
-
const plan2 = planRequest(request, options);
|
|
568
|
+
const plan2 = chunk2ZMIVDES_cjs.planRequest(request, options);
|
|
2485
569
|
const collect2 = plan2.collect();
|
|
2486
570
|
let index = 0;
|
|
2487
571
|
for await (const item of iterate(source)) {
|
|
@@ -2492,38 +576,101 @@ async function searchAsync(source, request = {}, options = {}) {
|
|
|
2492
576
|
return plan2.shape(collect2.finish());
|
|
2493
577
|
}
|
|
2494
578
|
|
|
2495
|
-
exports
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
exports
|
|
579
|
+
Object.defineProperty(exports, "DEFAULT_LIMITS", {
|
|
580
|
+
enumerable: true,
|
|
581
|
+
get: function () { return chunk2ZMIVDES_cjs.DEFAULT_LIMITS; }
|
|
582
|
+
});
|
|
583
|
+
Object.defineProperty(exports, "FIELD_OPERATORS", {
|
|
584
|
+
enumerable: true,
|
|
585
|
+
get: function () { return chunk2ZMIVDES_cjs.FIELD_OPERATORS; }
|
|
586
|
+
});
|
|
587
|
+
Object.defineProperty(exports, "QUERY_OPERATORS", {
|
|
588
|
+
enumerable: true,
|
|
589
|
+
get: function () { return chunk2ZMIVDES_cjs.QUERY_OPERATORS; }
|
|
590
|
+
});
|
|
591
|
+
Object.defineProperty(exports, "UNTRUSTED_LIMITS", {
|
|
592
|
+
enumerable: true,
|
|
593
|
+
get: function () { return chunk2ZMIVDES_cjs.UNTRUSTED_LIMITS; }
|
|
594
|
+
});
|
|
595
|
+
Object.defineProperty(exports, "compile", {
|
|
596
|
+
enumerable: true,
|
|
597
|
+
get: function () { return chunk2ZMIVDES_cjs.compile; }
|
|
598
|
+
});
|
|
599
|
+
Object.defineProperty(exports, "count", {
|
|
600
|
+
enumerable: true,
|
|
601
|
+
get: function () { return chunk2ZMIVDES_cjs.count; }
|
|
602
|
+
});
|
|
603
|
+
Object.defineProperty(exports, "every", {
|
|
604
|
+
enumerable: true,
|
|
605
|
+
get: function () { return chunk2ZMIVDES_cjs.every; }
|
|
606
|
+
});
|
|
607
|
+
Object.defineProperty(exports, "filter", {
|
|
608
|
+
enumerable: true,
|
|
609
|
+
get: function () { return chunk2ZMIVDES_cjs.filter; }
|
|
610
|
+
});
|
|
611
|
+
Object.defineProperty(exports, "filterMap", {
|
|
612
|
+
enumerable: true,
|
|
613
|
+
get: function () { return chunk2ZMIVDES_cjs.filterMap; }
|
|
614
|
+
});
|
|
615
|
+
Object.defineProperty(exports, "filterRecord", {
|
|
616
|
+
enumerable: true,
|
|
617
|
+
get: function () { return chunk2ZMIVDES_cjs.filterRecord; }
|
|
618
|
+
});
|
|
619
|
+
Object.defineProperty(exports, "find", {
|
|
620
|
+
enumerable: true,
|
|
621
|
+
get: function () { return chunk2ZMIVDES_cjs.find; }
|
|
622
|
+
});
|
|
623
|
+
Object.defineProperty(exports, "findEntry", {
|
|
624
|
+
enumerable: true,
|
|
625
|
+
get: function () { return chunk2ZMIVDES_cjs.findEntry; }
|
|
626
|
+
});
|
|
627
|
+
Object.defineProperty(exports, "findIndex", {
|
|
628
|
+
enumerable: true,
|
|
629
|
+
get: function () { return chunk2ZMIVDES_cjs.findIndex; }
|
|
630
|
+
});
|
|
631
|
+
Object.defineProperty(exports, "matches", {
|
|
632
|
+
enumerable: true,
|
|
633
|
+
get: function () { return chunk2ZMIVDES_cjs.matches; }
|
|
634
|
+
});
|
|
635
|
+
Object.defineProperty(exports, "partition", {
|
|
636
|
+
enumerable: true,
|
|
637
|
+
get: function () { return chunk2ZMIVDES_cjs.partition; }
|
|
638
|
+
});
|
|
639
|
+
Object.defineProperty(exports, "search", {
|
|
640
|
+
enumerable: true,
|
|
641
|
+
get: function () { return chunk2ZMIVDES_cjs.search; }
|
|
642
|
+
});
|
|
643
|
+
Object.defineProperty(exports, "some", {
|
|
644
|
+
enumerable: true,
|
|
645
|
+
get: function () { return chunk2ZMIVDES_cjs.some; }
|
|
646
|
+
});
|
|
647
|
+
Object.defineProperty(exports, "untyped", {
|
|
648
|
+
enumerable: true,
|
|
649
|
+
get: function () { return chunk2ZMIVDES_cjs.untyped; }
|
|
650
|
+
});
|
|
651
|
+
Object.defineProperty(exports, "validate", {
|
|
652
|
+
enumerable: true,
|
|
653
|
+
get: function () { return chunk2ZMIVDES_cjs.validate; }
|
|
654
|
+
});
|
|
655
|
+
Object.defineProperty(exports, "defineVocabulary", {
|
|
656
|
+
enumerable: true,
|
|
657
|
+
get: function () { return chunkEJFHVGBC_cjs.defineVocabulary; }
|
|
658
|
+
});
|
|
659
|
+
Object.defineProperty(exports, "JqlError", {
|
|
660
|
+
enumerable: true,
|
|
661
|
+
get: function () { return chunk74QKHM6Y_cjs.JqlError; }
|
|
662
|
+
});
|
|
2500
663
|
exports.canonical = canonical;
|
|
2501
|
-
exports.compile = compile;
|
|
2502
|
-
exports.count = count2;
|
|
2503
664
|
exports.countAsync = countAsync;
|
|
2504
|
-
exports.defineVocabulary = defineVocabulary;
|
|
2505
|
-
exports.every = every;
|
|
2506
665
|
exports.everyAsync = everyAsync;
|
|
2507
666
|
exports.explain = explain;
|
|
2508
|
-
exports.filter = filter;
|
|
2509
667
|
exports.filterAsync = filterAsync;
|
|
2510
|
-
exports.filterMap = filterMap;
|
|
2511
|
-
exports.filterRecord = filterRecord;
|
|
2512
668
|
exports.filterStream = filterStream;
|
|
2513
|
-
exports.find = find;
|
|
2514
669
|
exports.findAsync = findAsync;
|
|
2515
|
-
exports.findEntry = findEntry;
|
|
2516
|
-
exports.findIndex = findIndex;
|
|
2517
670
|
exports.fingerprint = fingerprint;
|
|
2518
671
|
exports.group = group;
|
|
2519
|
-
exports.matches = matches;
|
|
2520
|
-
exports.partition = partition;
|
|
2521
672
|
exports.plan = plan;
|
|
2522
|
-
exports.search = search;
|
|
2523
673
|
exports.searchAsync = searchAsync;
|
|
2524
|
-
exports.some = some;
|
|
2525
674
|
exports.someAsync = someAsync;
|
|
2526
|
-
exports.untyped = untyped;
|
|
2527
|
-
exports.validate = validate;
|
|
2528
675
|
//# sourceMappingURL=index.cjs.map
|
|
2529
676
|
//# sourceMappingURL=index.cjs.map
|