@dxos/echo-query 0.8.3 → 0.8.4-main.1068cf700f

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.
Files changed (66) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/neutral/index.mjs +719 -0
  3. package/dist/lib/neutral/index.mjs.map +7 -0
  4. package/dist/lib/neutral/meta.json +1 -0
  5. package/dist/query-lite/index.d.ts +8799 -0
  6. package/dist/query-lite/index.d.ts.map +1 -0
  7. package/dist/query-lite/index.js +381 -0
  8. package/dist/query-lite/index.js.map +1 -0
  9. package/dist/types/src/index.d.ts +2 -0
  10. package/dist/types/src/index.d.ts.map +1 -1
  11. package/dist/types/src/parser/gen/index.d.ts +8 -0
  12. package/dist/types/src/parser/gen/index.d.ts.map +1 -0
  13. package/dist/types/src/parser/gen/query.d.ts +3 -0
  14. package/dist/types/src/parser/gen/query.d.ts.map +1 -0
  15. package/dist/types/src/parser/gen/query.terms.d.ts +2 -0
  16. package/dist/types/src/parser/gen/query.terms.d.ts.map +1 -0
  17. package/dist/types/src/parser/index.d.ts +3 -0
  18. package/dist/types/src/parser/index.d.ts.map +1 -0
  19. package/dist/types/src/parser/query-builder.d.ts +82 -0
  20. package/dist/types/src/parser/query-builder.d.ts.map +1 -0
  21. package/dist/types/src/parser/query.test.d.ts +2 -0
  22. package/dist/types/src/parser/query.test.d.ts.map +1 -0
  23. package/dist/types/src/query-lite/index.d.ts +2 -0
  24. package/dist/types/src/query-lite/index.d.ts.map +1 -0
  25. package/dist/types/src/query-lite/query-lite.d.ts +8 -0
  26. package/dist/types/src/query-lite/query-lite.d.ts.map +1 -0
  27. package/dist/types/src/sandbox/index.d.ts +2 -0
  28. package/dist/types/src/sandbox/index.d.ts.map +1 -0
  29. package/dist/types/src/sandbox/query-sandbox.d.ts +21 -0
  30. package/dist/types/src/sandbox/query-sandbox.d.ts.map +1 -0
  31. package/dist/types/src/sandbox/query-sandbox.test.d.ts +2 -0
  32. package/dist/types/src/sandbox/query-sandbox.test.d.ts.map +1 -0
  33. package/dist/types/src/sandbox/quickjs.d.ts +8 -0
  34. package/dist/types/src/sandbox/quickjs.d.ts.map +1 -0
  35. package/dist/types/src/sandbox/quickjs.test.d.ts +2 -0
  36. package/dist/types/src/sandbox/quickjs.test.d.ts.map +1 -0
  37. package/dist/types/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +30 -10
  39. package/src/env.d.ts +8 -0
  40. package/src/index.ts +3 -0
  41. package/src/parser/gen/index.ts +13 -0
  42. package/src/parser/gen/query.terms.ts +27 -0
  43. package/src/parser/gen/query.ts +18 -0
  44. package/src/parser/index.ts +6 -0
  45. package/src/parser/query-builder.ts +539 -0
  46. package/src/parser/query.grammar +130 -0
  47. package/src/parser/query.test.ts +416 -0
  48. package/src/query-lite/index.ts +5 -0
  49. package/src/query-lite/query-lite.ts +505 -0
  50. package/src/sandbox/index.ts +5 -0
  51. package/src/sandbox/query-sandbox.test.ts +53 -0
  52. package/src/sandbox/query-sandbox.ts +72 -0
  53. package/src/sandbox/quickjs.test.ts +67 -0
  54. package/src/sandbox/quickjs.ts +33 -0
  55. package/dist/lib/browser/index.mjs +0 -2
  56. package/dist/lib/browser/index.mjs.map +0 -7
  57. package/dist/lib/browser/meta.json +0 -1
  58. package/dist/lib/node/index.cjs +0 -2
  59. package/dist/lib/node/index.cjs.map +0 -7
  60. package/dist/lib/node/meta.json +0 -1
  61. package/dist/lib/node-esm/index.mjs +0 -2
  62. package/dist/lib/node-esm/index.mjs.map +0 -7
  63. package/dist/lib/node-esm/meta.json +0 -1
  64. package/dist/types/src/search.test.d.ts +0 -2
  65. package/dist/types/src/search.test.d.ts.map +0 -1
  66. package/src/search.test.ts +0 -49
@@ -0,0 +1,719 @@
1
+ import "@dxos/node-std/globals";
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+
8
+ // src/parser/gen/query.ts
9
+ import { LRParser } from "@lezer/lr";
10
+ var spec_Identifier = {
11
+ __proto__: null,
12
+ type: 26,
13
+ NOT: 86,
14
+ not: 86,
15
+ "!": 86,
16
+ AND: 88,
17
+ and: 88,
18
+ OR: 90,
19
+ or: 90
20
+ };
21
+ var parser = LRParser.deserialize({
22
+ version: 14,
23
+ states: "(jOVQPOOOnQPO'#ClOOQO'#Cd'#CdOOQO'#Cf'#CfOyQPO'#ChO!OQPO'#CrO!WQPO'#CkOOQO'#Cc'#CcOOQO'#Cz'#CzOOQO'#DW'#DWOVQPO'#DWQ!]QPOOOVQPO'#DWO!mQPO,58xO!rQPO'#DQO!wQPO,59WO#PQPO,59SO#UQPO'#CtOOQO,59^,59^O#ZQPO,59^O#cQQO,59VO#wQPO,59rOOQO'#C{'#C{OOQO'#C|'#C|OOQO'#C}'#C}OVQPO,59rOVQPO,59rOVQPO,59rO$rQPO,59rOVQPO1G.dOOQO,59l,59lOOQO-E7O-E7OOOQO1G.n1G.nO#cQQO,59`O%VQPO'#DRO%[QPO1G.xOOQO1G.x1G.xO%dQQO'#CwOOQO'#Cn'#CnOOQO1G.q1G.qO%kQPO1G/^O&RQPO1G/^O&iQPO1G/^OOQO1G/^1G/^O'PQPO7+$OOOQO1G.z1G.zOOQO,59m,59mOOQO-E7P-E7POOQO7+$d7+$dOOQO,59c,59cO'dQPO,59cOOQO<<Gj<<GjO#cQQO'#DSO'lQPO1G.}OOQO1G.}1G.}OOQO,59n,59nOOQO-E7Q-E7QOOQO7+$i7+$i",
24
+ stateData: "'t~OyOS~ORPOT[OXQOZRO]SOgTO{WO~OS]Oa^O^`X~O^`O~ORaOjbO~O^dO~OrhOshO|fO}gO~PVOTmO~ORnO~Oa^O^`a~ORpO~O^qO~OirOjtO~OZvOcvOdvOevOgTOluO~O{WORzaTzaXzaZza]zagzarzaszawza|za}zaUza~OU{OrhOshO|fO}gO~PVORaO~OirOj!QO~Om!RO~P#cOrzisziwzi|zi}ziUzi~PVO|fOrzisziwzi}ziUzi~PVO|fO}gOrzisziwziUzi~PVOU!TOrhOshO|fO}gO~PVOi!UOm!WO~Oi!UOm!ZO~O",
25
+ goto: "%h{PP|PPPP|!]P!]P!]PP!]!lP!{PPP#XP#nPP#hPP#t$U$]$cPP$h$n$tPPP$zkXOYZ[ijklmxyz|kVOYZ[ijklmxyz|kUOYZ[ijklmxyz|QwdQ}qQ!SuR!X!UjVOYZ[ijklmxyz|Xvdqu!UQcTR!OrmYOYZ[eijklmxyz|ZiZlyz|XjZlz|VkZl|Q_PRo_QscR!PsQ!V!SR!Y!VQZO`eYZelxyz|Ql[QxiQyjQzkR|m",
26
+ nodeNames: "\u26A0 Query Assignment Identifier = ( ) Filter TagFilter Tag TextFilter String TypeFilter TypeKeyword : PropertyFilter PropertyPath . Value Number Boolean Null ObjectLiteral { ObjectProperty , } ArrayLiteral [ ] Not And Or Relation ArrowRight ArrowLeft",
27
+ maxTerm: 45,
28
+ skippedNodes: [
29
+ 0
30
+ ],
31
+ repeatNodeCount: 3,
32
+ tokenData: "3P~RsX^#`pq#`rs$Tst%qwx&ixy(Qyz(V|}([}!O(a!O!P*Q!Q![(j![!]*V!^!_*[!_!`*g!c!}*l!}#O+W#P#Q+]#R#S*l#T#Y*l#Y#Z+b#Z#b*l#b#c.q#c#h*l#h#i1c#i#o*l#o#p2u#q#r2z#y#z#`$f$g#`#BY#BZ#`$IS$I_#`$I|$JO#`$JT$JU#`$KV$KW#`&FU&FV#`~#eYy~X^#`pq#`#y#z#`$f$g#`#BY#BZ#`$IS$I_#`$I|$JO#`$JT$JU#`$KV$KW#`&FU&FV#`~$WVOr$Trs$ms#O$T#O#P$r#P;'S$T;'S;=`%k<%lO$T~$rOZ~~$uRO;'S$T;'S;=`%O;=`O$T~%RWOr$Trs$ms#O$T#O#P$r#P;'S$T;'S;=`%k;=`<%l$T<%lO$T~%nP;=`<%l$T~%tT}!O&T!Q![&T!c!}&T#R#S&T#T#o&T~&YTX~}!O&T!Q![&T!c!}&T#R#S&T#T#o&T~&lVOw&iwx$mx#O&i#O#P'R#P;'S&i;'S;=`'z<%lO&i~'URO;'S&i;'S;=`'_;=`O&i~'bWOw&iwx$mx#O&i#O#P'R#P;'S&i;'S;=`'z;=`<%l&i<%lO&i~'}P;=`<%l&i~(VOT~~([OU~~(aOi~~(dQ!Q![(j!`!a){~(oSc~!O!P({!Q![(j!g!h)a#X#Y)a~)OP!Q![)R~)WRc~!Q![)R!g!h)a#X#Y)a~)dR{|)m}!O)m!Q![)s~)pP!Q![)s~)xPc~!Q![)s~*QOr~~*VOa~~*[O^~~*_P}!O*b~*gOs~~*lOS~P*qVRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#o*l~+]Ol~~+bOm~R+gWRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#U,P#U#o*lR,UXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#`*l#`#a,q#a#o*lR,vXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#g*l#g#h-c#h#o*lR-hXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#X*l#X#Y.T#Y#o*lR.[VdQRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#o*lR.vXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#i*l#i#j/c#j#o*lR/hXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#`*l#`#a0T#a#o*lR0YXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#`*l#`#a0u#a#o*lR0|VRPeQ}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#o*lR1hXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#f*l#f#g2T#g#o*lR2YXRP}!O*l!O!P*l!P!Q*l!Q![*l!c!}*l#R#S*l#T#i*l#i#j-c#j#o*l~2zOg~~3POj~",
33
+ tokenizers: [
34
+ 0,
35
+ 1
36
+ ],
37
+ topRules: {
38
+ "Query": [
39
+ 0,
40
+ 1
41
+ ]
42
+ },
43
+ specialized: [
44
+ {
45
+ term: 3,
46
+ get: (value) => spec_Identifier[value] || -1
47
+ }
48
+ ],
49
+ tokenPrec: 0
50
+ });
51
+
52
+ // src/parser/gen/query.terms.ts
53
+ var query_terms_exports = {};
54
+ __export(query_terms_exports, {
55
+ And: () => And,
56
+ ArrayLiteral: () => ArrayLiteral,
57
+ ArrowLeft: () => ArrowLeft,
58
+ ArrowRight: () => ArrowRight,
59
+ Assignment: () => Assignment,
60
+ Boolean: () => Boolean,
61
+ Filter: () => Filter,
62
+ Identifier: () => Identifier,
63
+ Not: () => Not,
64
+ Null: () => Null,
65
+ Number: () => Number2,
66
+ ObjectLiteral: () => ObjectLiteral,
67
+ ObjectProperty: () => ObjectProperty,
68
+ Or: () => Or,
69
+ PropertyFilter: () => PropertyFilter,
70
+ PropertyPath: () => PropertyPath,
71
+ Query: () => Query,
72
+ Relation: () => Relation,
73
+ String: () => String2,
74
+ Tag: () => Tag,
75
+ TagFilter: () => TagFilter,
76
+ TextFilter: () => TextFilter,
77
+ TypeFilter: () => TypeFilter,
78
+ TypeKeyword: () => TypeKeyword,
79
+ Value: () => Value
80
+ });
81
+ var Query = 1;
82
+ var Assignment = 2;
83
+ var Identifier = 3;
84
+ var Filter = 7;
85
+ var TagFilter = 8;
86
+ var Tag = 9;
87
+ var TextFilter = 10;
88
+ var String2 = 11;
89
+ var TypeFilter = 12;
90
+ var TypeKeyword = 13;
91
+ var PropertyFilter = 15;
92
+ var PropertyPath = 16;
93
+ var Value = 18;
94
+ var Number2 = 19;
95
+ var Boolean = 20;
96
+ var Null = 21;
97
+ var ObjectLiteral = 22;
98
+ var ObjectProperty = 24;
99
+ var ArrayLiteral = 27;
100
+ var Not = 30;
101
+ var And = 31;
102
+ var Or = 32;
103
+ var Relation = 33;
104
+ var ArrowRight = 34;
105
+ var ArrowLeft = 35;
106
+
107
+ // src/parser/gen/index.ts
108
+ (function(QueryDSL2) {
109
+ QueryDSL2.Parser = parser;
110
+ QueryDSL2.Node = query_terms_exports;
111
+ QueryDSL2.Tokens = [
112
+ "type:",
113
+ "AND",
114
+ "OR",
115
+ "NOT"
116
+ ];
117
+ })(QueryDSL || (QueryDSL = {}));
118
+ var QueryDSL;
119
+
120
+ // src/parser/query-builder.ts
121
+ import { Filter as Filter2 } from "@dxos/echo";
122
+ import { invariant } from "@dxos/invariant";
123
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/echo/echo-query/src/parser/query-builder.ts";
124
+ var QueryBuilder = class {
125
+ _tags;
126
+ _parser = QueryDSL.Parser.configure({
127
+ strict: true
128
+ });
129
+ constructor(_tags) {
130
+ this._tags = _tags;
131
+ }
132
+ /**
133
+ * Check valid input.
134
+ */
135
+ validate(input) {
136
+ try {
137
+ const tree = this._parser.parse(input);
138
+ return tree.cursor().node.name === "Query";
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
143
+ /**
144
+ * Build a query from the input string.
145
+ */
146
+ build(input) {
147
+ try {
148
+ const tree = this._parser.parse(input);
149
+ return this.buildQuery(tree, input);
150
+ } catch {
151
+ return {};
152
+ }
153
+ }
154
+ /**
155
+ * Build a query from a parsed DSL tree.
156
+ */
157
+ buildQuery(tree, input) {
158
+ const cursor = tree.cursor();
159
+ if (cursor.node.name !== "Query") {
160
+ return {};
161
+ }
162
+ const children = [];
163
+ if (cursor.firstChild()) {
164
+ do {
165
+ children.push({
166
+ name: cursor.node.name,
167
+ from: cursor.from,
168
+ to: cursor.to
169
+ });
170
+ } while (cursor.nextSibling());
171
+ cursor.parent();
172
+ }
173
+ const hasAssignment = children.some((child) => child.name === "Assignment");
174
+ if (hasAssignment) {
175
+ return this._parseAssignment(cursor, input);
176
+ }
177
+ const hasOperator = children.some((child) => child.name === "And" || child.name === "Or");
178
+ const hasMultipleExpressions = children.filter((child) => child.name === "Filter" || child.name === "Not" || child.name === "(").length > 1;
179
+ if (hasOperator || hasMultipleExpressions) {
180
+ const filter2 = this._parseBinaryExpression(cursor, input);
181
+ return {
182
+ filter: filter2
183
+ };
184
+ }
185
+ if (!cursor.firstChild()) {
186
+ return {
187
+ filter: Filter2.nothing()
188
+ };
189
+ }
190
+ const filter = this._parseExpression(cursor, input);
191
+ return {
192
+ filter
193
+ };
194
+ }
195
+ /**
196
+ * Parse an assignment node.
197
+ */
198
+ _parseAssignment(cursor, input) {
199
+ if (!cursor.firstChild()) {
200
+ return {};
201
+ }
202
+ let name;
203
+ let filter;
204
+ do {
205
+ if (cursor.node.name === "Assignment") {
206
+ const assignmentText = this._getNodeText(cursor, input);
207
+ if (cursor.firstChild()) {
208
+ name = this._getNodeText(cursor, input);
209
+ const openParenIndex = assignmentText.indexOf("(");
210
+ const closeParenIndex = assignmentText.lastIndexOf(")");
211
+ if (openParenIndex !== -1 && closeParenIndex !== -1 && closeParenIndex > openParenIndex) {
212
+ const subInput = assignmentText.slice(openParenIndex + 1, closeParenIndex).trim();
213
+ const subTree = this._parser.parse(subInput);
214
+ const subResult = this.buildQuery(subTree, subInput);
215
+ filter = subResult.filter;
216
+ }
217
+ cursor.parent();
218
+ }
219
+ break;
220
+ }
221
+ } while (cursor.nextSibling());
222
+ cursor.parent();
223
+ return {
224
+ filter,
225
+ name
226
+ };
227
+ }
228
+ /**
229
+ * Parse an expression node.
230
+ */
231
+ _parseExpression(cursor, input) {
232
+ const nodeName = cursor.node.name;
233
+ switch (nodeName) {
234
+ case "Filter":
235
+ return this._parseFilter(cursor, input);
236
+ case "Not": {
237
+ cursor.nextSibling();
238
+ const notFilter = this._parseExpression(cursor, input);
239
+ return notFilter ? Filter2.not(notFilter) : void 0;
240
+ }
241
+ case "And":
242
+ case "Or":
243
+ cursor.parent();
244
+ return this._parseBinaryExpression(cursor, input);
245
+ case "(": {
246
+ cursor.nextSibling();
247
+ const parenFilter = this._parseExpression(cursor, input);
248
+ cursor.nextSibling();
249
+ return parenFilter;
250
+ }
251
+ default: {
252
+ const savedPos = cursor.from;
253
+ if (cursor.firstChild()) {
254
+ let hasOperator = false;
255
+ let expressionCount = 0;
256
+ do {
257
+ if (cursor.node.name === "And" || cursor.node.name === "Or") {
258
+ hasOperator = true;
259
+ break;
260
+ }
261
+ if (cursor.node.name === "Filter" || cursor.node.name === "Not" || cursor.node.name === "(") {
262
+ expressionCount++;
263
+ }
264
+ } while (cursor.nextSibling());
265
+ hasOperator = hasOperator || expressionCount > 1;
266
+ cursor.parent();
267
+ cursor.firstChild();
268
+ while (cursor.from !== savedPos && cursor.nextSibling()) {
269
+ }
270
+ if (hasOperator) {
271
+ cursor.parent();
272
+ return this._parseBinaryExpression(cursor, input);
273
+ } else {
274
+ const result = this._parseExpression(cursor, input);
275
+ cursor.parent();
276
+ return result;
277
+ }
278
+ }
279
+ return Filter2.nothing();
280
+ }
281
+ }
282
+ }
283
+ /**
284
+ * Parse a binary expression (AND/OR).
285
+ */
286
+ _parseBinaryExpression(cursor, input) {
287
+ const filters = [];
288
+ let operator = null;
289
+ if (cursor.firstChild()) {
290
+ do {
291
+ const nodeName = cursor.node.name;
292
+ if (nodeName === "And" || nodeName === "Or") {
293
+ operator = nodeName.toLowerCase();
294
+ } else if (nodeName === "(") {
295
+ const savedPos = cursor.from;
296
+ cursor.nextSibling();
297
+ let hasBinaryOp = false;
298
+ do {
299
+ if (cursor.node.name === "And" || cursor.node.name === "Or") {
300
+ hasBinaryOp = true;
301
+ break;
302
+ }
303
+ } while (cursor.nextSibling() && cursor.node.name !== ")");
304
+ cursor.parent();
305
+ cursor.firstChild();
306
+ while (cursor.from !== savedPos && cursor.nextSibling()) {
307
+ }
308
+ cursor.nextSibling();
309
+ if (hasBinaryOp) {
310
+ let depth = 1;
311
+ const exprStart = cursor.from;
312
+ let exprEnd = cursor.to;
313
+ while (cursor.nextSibling() && depth > 0) {
314
+ if (cursor.node.name === "(") depth++;
315
+ else if (cursor.node.name === ")") {
316
+ depth--;
317
+ if (depth === 0) {
318
+ exprEnd = cursor.from;
319
+ }
320
+ }
321
+ }
322
+ const subInput = input.slice(exprStart, exprEnd);
323
+ const subTree = this._parser.parse(subInput);
324
+ const subResult = this.buildQuery(subTree, subInput);
325
+ if (subResult.filter) {
326
+ filters.push(subResult.filter);
327
+ }
328
+ } else {
329
+ const subFilter = this._parseExpression(cursor, input);
330
+ if (subFilter) {
331
+ filters.push(subFilter);
332
+ }
333
+ while (cursor.nextSibling() && cursor.node.name !== ")") {
334
+ }
335
+ }
336
+ } else if (nodeName !== ")") {
337
+ const subFilter = this._parseExpression(cursor, input);
338
+ if (subFilter) {
339
+ filters.push(subFilter);
340
+ }
341
+ }
342
+ } while (cursor.nextSibling());
343
+ cursor.parent();
344
+ }
345
+ if (filters.length === 0) {
346
+ return Filter2.nothing();
347
+ }
348
+ if (filters.length === 1) {
349
+ return filters[0];
350
+ }
351
+ return operator === "or" ? Filter2.or(...filters) : Filter2.and(...filters);
352
+ }
353
+ /**
354
+ * Parse a Filter node.
355
+ */
356
+ _parseFilter(cursor, input) {
357
+ if (!cursor.firstChild()) {
358
+ return Filter2.nothing();
359
+ }
360
+ let result = void 0;
361
+ const filterType = cursor.node.name;
362
+ switch (filterType) {
363
+ case "TagFilter":
364
+ if (this._tags) {
365
+ result = this._parseTagFilter(cursor, input);
366
+ }
367
+ break;
368
+ case "TextFilter":
369
+ result = this._parseTextFilter(cursor, input);
370
+ break;
371
+ case "TypeFilter":
372
+ result = this._parseTypeFilter(cursor, input);
373
+ break;
374
+ case "ObjectLiteral":
375
+ result = this._parseObjectLiteral(cursor, input);
376
+ break;
377
+ case "PropertyFilter":
378
+ result = this._parsePropertyFilter(cursor, input);
379
+ break;
380
+ default:
381
+ result = Filter2.nothing();
382
+ }
383
+ cursor.parent();
384
+ return result;
385
+ }
386
+ /**
387
+ * Parse a TypeFilter node (type:typename).
388
+ */
389
+ _parseTypeFilter(cursor, input) {
390
+ cursor.firstChild();
391
+ cursor.nextSibling();
392
+ cursor.nextSibling();
393
+ const typename = this._getNodeText(cursor, input);
394
+ cursor.parent();
395
+ return Filter2.typename(typename);
396
+ }
397
+ /**
398
+ * Parse a TextFilter node (quoted string).
399
+ */
400
+ _parseTextFilter(cursor, input) {
401
+ cursor.firstChild();
402
+ const text = this._getNodeText(cursor, input);
403
+ cursor.parent();
404
+ return Filter2.text(text.slice(1, -1));
405
+ }
406
+ /**
407
+ * Parse an ObjectLiteral node.
408
+ */
409
+ _parseObjectLiteral(cursor, input) {
410
+ const props = {};
411
+ if (cursor.firstChild()) {
412
+ do {
413
+ if (cursor.node.name === "ObjectProperty") {
414
+ const { key, value } = this._parseObjectProperty(cursor, input);
415
+ if (key) {
416
+ props[key] = Filter2.eq(value);
417
+ }
418
+ }
419
+ } while (cursor.nextSibling());
420
+ cursor.parent();
421
+ }
422
+ return Filter2.props(props);
423
+ }
424
+ /**
425
+ * Parse an ObjectProperty node.
426
+ */
427
+ _parseObjectProperty(cursor, input) {
428
+ let key = null;
429
+ let value = null;
430
+ if (cursor.firstChild()) {
431
+ if (cursor.node.name === "Identifier") {
432
+ key = this._getNodeText(cursor, input);
433
+ }
434
+ cursor.nextSibling();
435
+ cursor.nextSibling();
436
+ if (cursor.node.name === "Value" && cursor.firstChild()) {
437
+ value = this._parseValue(cursor, input);
438
+ cursor.parent();
439
+ }
440
+ cursor.parent();
441
+ }
442
+ return {
443
+ key,
444
+ value
445
+ };
446
+ }
447
+ /**
448
+ * Parse a PropertyFilter node (property:value).
449
+ */
450
+ _parsePropertyFilter(cursor, input) {
451
+ let path = null;
452
+ let value = null;
453
+ if (cursor.firstChild()) {
454
+ if (cursor.node.name === "PropertyPath") {
455
+ path = this._parsePropertyPath(cursor, input);
456
+ }
457
+ cursor.nextSibling();
458
+ cursor.nextSibling();
459
+ if (cursor.node.name === "Value" && cursor.firstChild()) {
460
+ value = this._parseValue(cursor, input);
461
+ cursor.parent();
462
+ }
463
+ cursor.parent();
464
+ }
465
+ if (!path) {
466
+ return Filter2.nothing();
467
+ }
468
+ return Filter2.props({
469
+ [path]: value
470
+ });
471
+ }
472
+ /**
473
+ * Parse a PropertyPath node (supports dot notation).
474
+ */
475
+ _parsePropertyPath(cursor, input) {
476
+ const parts = [];
477
+ if (cursor.firstChild()) {
478
+ do {
479
+ if (cursor.node.name === "Identifier") {
480
+ parts.push(this._getNodeText(cursor, input));
481
+ }
482
+ } while (cursor.nextSibling());
483
+ cursor.parent();
484
+ }
485
+ return parts.join(".");
486
+ }
487
+ /**
488
+ * Parse a TagFilter node (#tag).
489
+ */
490
+ _parseTagFilter(cursor, input) {
491
+ invariant(this._tags, void 0, {
492
+ F: __dxlog_file,
493
+ L: 468,
494
+ S: this,
495
+ A: [
496
+ "this._tags",
497
+ ""
498
+ ]
499
+ });
500
+ const str = this._getNodeText(cursor, input).slice(1).toLowerCase();
501
+ const [key] = Object.entries(this._tags).find(([, value]) => value.label.toLowerCase() === str) ?? [];
502
+ return key ? Filter2.tag(key) : void 0;
503
+ }
504
+ /**
505
+ * Parse a Value node.
506
+ */
507
+ _parseValue(cursor, input) {
508
+ const valueType = cursor.node.name;
509
+ switch (valueType) {
510
+ case "String": {
511
+ const str = this._getNodeText(cursor, input);
512
+ return str.slice(1, -1);
513
+ }
514
+ case "Number":
515
+ return Number(this._getNodeText(cursor, input));
516
+ case "Boolean":
517
+ return this._getNodeText(cursor, input) === "true";
518
+ case "Null":
519
+ return null;
520
+ case "ObjectLiteral": {
521
+ const props = {};
522
+ if (cursor.firstChild()) {
523
+ do {
524
+ if (cursor.node.name === "ObjectProperty") {
525
+ const { key, value } = this._parseObjectProperty(cursor, input);
526
+ if (key) {
527
+ props[key] = value;
528
+ }
529
+ }
530
+ } while (cursor.nextSibling());
531
+ cursor.parent();
532
+ }
533
+ return props;
534
+ }
535
+ case "ArrayLiteral": {
536
+ const array = [];
537
+ if (cursor.firstChild()) {
538
+ do {
539
+ if (cursor.node.name === "Value" && cursor.firstChild()) {
540
+ array.push(this._parseValue(cursor, input));
541
+ cursor.parent();
542
+ }
543
+ } while (cursor.nextSibling());
544
+ cursor.parent();
545
+ }
546
+ return array;
547
+ }
548
+ default:
549
+ return null;
550
+ }
551
+ }
552
+ /**
553
+ * Get the text content of the current node.
554
+ */
555
+ _getNodeText(cursor, input) {
556
+ return input.slice(cursor.from, cursor.to);
557
+ }
558
+ };
559
+
560
+ // src/sandbox/query-sandbox.ts
561
+ import { Resource } from "@dxos/context";
562
+ import { Query as Query2 } from "@dxos/echo";
563
+ import { trim } from "@dxos/util";
564
+ import { createQuickJS } from "@dxos/vendor-quickjs";
565
+ import envCode from "#query-lite?raw";
566
+
567
+ // src/sandbox/quickjs.ts
568
+ var unwrapResult = (context, result) => {
569
+ if (result.error) {
570
+ const contextError = context.dump(result.error);
571
+ result.error.dispose();
572
+ if (typeof contextError === "object" && typeof contextError.name === "string" && typeof contextError.message === "string") {
573
+ const error = new Error(contextError.message);
574
+ Object.defineProperty(error, "name", {
575
+ value: contextError.name
576
+ });
577
+ const originalStack = error.stack;
578
+ error.stack = `${contextError.name}: ${contextError.message}
579
+ ${contextError.stack}${originalStack?.split("\n").slice(1).join("\n") ?? ""}`;
580
+ throw error;
581
+ } else {
582
+ throw new Error(String(contextError));
583
+ }
584
+ }
585
+ return result.value;
586
+ };
587
+
588
+ // src/sandbox/query-sandbox.ts
589
+ function _ts_add_disposable_resource(env, value, async) {
590
+ if (value !== null && value !== void 0) {
591
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
592
+ var dispose, inner;
593
+ if (async) {
594
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
595
+ dispose = value[Symbol.asyncDispose];
596
+ }
597
+ if (dispose === void 0) {
598
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
599
+ dispose = value[Symbol.dispose];
600
+ if (async) inner = dispose;
601
+ }
602
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
603
+ if (inner) dispose = function() {
604
+ try {
605
+ inner.call(this);
606
+ } catch (e) {
607
+ return Promise.reject(e);
608
+ }
609
+ };
610
+ env.stack.push({
611
+ value,
612
+ dispose,
613
+ async
614
+ });
615
+ } else if (async) {
616
+ env.stack.push({
617
+ async: true
618
+ });
619
+ }
620
+ return value;
621
+ }
622
+ function _ts_dispose_resources(env) {
623
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
624
+ var e = new Error(message);
625
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
626
+ };
627
+ return (_ts_dispose_resources = function _ts_dispose_resources2(env2) {
628
+ function fail(e) {
629
+ env2.error = env2.hasError ? new _SuppressedError(e, env2.error, "An error was suppressed during disposal.") : e;
630
+ env2.hasError = true;
631
+ }
632
+ var r, s = 0;
633
+ function next() {
634
+ while (r = env2.stack.pop()) {
635
+ try {
636
+ if (!r.async && s === 1) return s = 0, env2.stack.push(r), Promise.resolve().then(next);
637
+ if (r.dispose) {
638
+ var result = r.dispose.call(r.value);
639
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
640
+ fail(e);
641
+ return next();
642
+ });
643
+ } else s |= 1;
644
+ } catch (e) {
645
+ fail(e);
646
+ }
647
+ }
648
+ if (s === 1) return env2.hasError ? Promise.reject(env2.error) : Promise.resolve();
649
+ if (env2.hasError) throw env2.error;
650
+ }
651
+ return next();
652
+ })(env);
653
+ }
654
+ var QuerySandbox = class _QuerySandbox extends Resource {
655
+ // Caching the wasm module.
656
+ static quickJS = null;
657
+ static getQuickJS() {
658
+ if (!_QuerySandbox.quickJS) {
659
+ _QuerySandbox.quickJS = createQuickJS();
660
+ }
661
+ return _QuerySandbox.quickJS;
662
+ }
663
+ #runtime;
664
+ async _open() {
665
+ const quickJS = await _QuerySandbox.getQuickJS();
666
+ this.#runtime = quickJS.newRuntime({
667
+ moduleLoader: (moduleName, _context) => {
668
+ switch (moduleName) {
669
+ case "dxos:query-lite":
670
+ return envCode;
671
+ default:
672
+ throw new Error(`Module not found: ${moduleName}`);
673
+ }
674
+ }
675
+ });
676
+ }
677
+ async _close() {
678
+ this.#runtime.dispose();
679
+ }
680
+ /**
681
+ * Evaluates the query code.
682
+ * @param queryCode Example: `Query.select(Filter.typename('dxos.org/type/Person'))`
683
+ */
684
+ eval(queryCode) {
685
+ const env = {
686
+ stack: [],
687
+ error: void 0,
688
+ hasError: false
689
+ };
690
+ try {
691
+ const context = _ts_add_disposable_resource(env, this.#runtime.newContext(), false);
692
+ const globals = trim`
693
+ import { Filter, Order, Query } from 'dxos:query-lite';
694
+ globalThis.Filter = Filter;
695
+ globalThis.Order = Order;
696
+ globalThis.Query = Query;
697
+ `;
698
+ unwrapResult(context, context.evalCode(globals)).dispose();
699
+ const query = _ts_add_disposable_resource(env, unwrapResult(context, context.evalCode(queryCode)), false);
700
+ const result = context.dump(query);
701
+ if ("~Filter" in result) {
702
+ return Query2.select(result).ast;
703
+ } else {
704
+ return result.ast;
705
+ }
706
+ } catch (e) {
707
+ env.error = e;
708
+ env.hasError = true;
709
+ } finally {
710
+ _ts_dispose_resources(env);
711
+ }
712
+ }
713
+ };
714
+ export {
715
+ QueryBuilder,
716
+ QueryDSL,
717
+ QuerySandbox
718
+ };
719
+ //# sourceMappingURL=index.mjs.map