@dxos/echo-query 0.10.0 → 0.11.1

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.
@@ -1,4 +1,14 @@
1
- //#region ../../../common/invariant/dist/lib/browser/index.mjs
1
+ //#region ../../../common/invariant/dist/lib/index.mjs
2
+ /**
3
+ * Use this to assert the arguments of a function.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * function foo(arg: string) {
8
+ * assertArgument(typeof arg === 'string', 'arg must be a string');
9
+ * }
10
+ * ```
11
+ */
2
12
  var assertArgument = (condition, argumentName, message) => {
3
13
  if (!condition) {
4
14
  const error = /* @__PURE__ */ new TypeError(`Invalid argument \`${argumentName}\`` + (message ? `: ${message}` : ""));
@@ -9,19 +19,27 @@ var assertArgument = (condition, argumentName, message) => {
9
19
 
10
20
  //#endregion
11
21
  //#region src/query-lite/query-lite.ts
22
+ const OrderTypeId = "~@dxos/echo/Order";
23
+ const FilterTypeId = "~@dxos/echo/Filter";
24
+ const QueryTypeId = "~@dxos/echo/Query";
25
+ const ProjectionTypeId = "~@dxos/echo/Query.Projection";
12
26
  var OrderClass = class OrderClass {
13
27
  static "variance" = {};
14
- static "is"(value) {
15
- return typeof value === "object" && value !== null && "~Order" in value;
28
+ static is(value) {
29
+ return typeof value === "object" && value !== null && OrderTypeId in value;
16
30
  }
17
- "constructor"(ast) {
31
+ constructor(ast) {
18
32
  this.ast = ast;
19
33
  }
20
- "~Order" = OrderClass.variance;
34
+ [OrderTypeId] = OrderClass.variance;
21
35
  };
22
36
  let Order1;
23
37
  (function(_Order) {
24
- _Order.natural = new OrderClass({ kind: "natural" });
38
+ _Order.OrderTypeId = "~@dxos/echo/Order";
39
+ _Order.natural = (direction = "asc") => new OrderClass({
40
+ kind: "natural",
41
+ direction
42
+ });
25
43
  _Order.property = (property, direction) => new OrderClass({
26
44
  kind: "property",
27
45
  property,
@@ -61,6 +79,7 @@ const _filterMatchValueLocal = (filter, value) => {
61
79
  }
62
80
  return true;
63
81
  case "in": return filter.values.includes(value);
82
+ case "in-query": throw new Error("in-query filters are not supported in the sandboxed toPredicate matcher.");
64
83
  case "range": return value >= filter.from && value <= filter.to;
65
84
  case "not": return !_filterMatchValueLocal(filter.filter, value);
66
85
  case "and": return filter.filters.every((f) => _filterMatchValueLocal(f, value));
@@ -88,21 +107,22 @@ const _filterMatchEntityLocal = (filter, entity) => {
88
107
  }
89
108
  };
90
109
  var FilterClass = class FilterClass {
110
+ static "FilterTypeId" = FilterTypeId;
91
111
  static "variance" = {};
92
- static "is"(value) {
93
- return typeof value === "object" && value !== null && "~Filter" in value;
112
+ static is(value) {
113
+ return typeof value === "object" && value !== null && FilterTypeId in value;
94
114
  }
95
- static "fromAst"(ast) {
115
+ static fromAst(ast) {
96
116
  return new FilterClass(ast);
97
117
  }
98
- static "everything"() {
118
+ static everything() {
99
119
  return new FilterClass({
100
120
  type: "object",
101
121
  typename: null,
102
122
  props: {}
103
123
  });
104
124
  }
105
- static "nothing"() {
125
+ static nothing() {
106
126
  return new FilterClass({
107
127
  type: "not",
108
128
  filter: {
@@ -112,14 +132,14 @@ var FilterClass = class FilterClass {
112
132
  }
113
133
  });
114
134
  }
115
- static "relation"() {
135
+ static relation() {
116
136
  return new FilterClass({
117
137
  type: "object",
118
138
  typename: null,
119
139
  props: {}
120
140
  });
121
141
  }
122
- static "id"(...ids) {
142
+ static id(...ids) {
123
143
  if (ids.length === 0) return FilterClass.nothing();
124
144
  return new FilterClass({
125
145
  type: "object",
@@ -128,7 +148,7 @@ var FilterClass = class FilterClass {
128
148
  props: {}
129
149
  });
130
150
  }
131
- static "type"(schema, props) {
151
+ static type(schema, props) {
132
152
  if (typeof schema !== "string") throw new TypeError("expected typename as the first paramter");
133
153
  return new FilterClass({
134
154
  type: "object",
@@ -136,27 +156,27 @@ var FilterClass = class FilterClass {
136
156
  ...propsFilterToAst(props ?? {})
137
157
  });
138
158
  }
139
- static "typename"(typename) {
159
+ static typename(typename) {
140
160
  return new FilterClass({
141
161
  type: "object",
142
162
  typename: makeTypeDxn(typename),
143
163
  props: {}
144
164
  });
145
165
  }
146
- static "typeURI"(uri) {
166
+ static typeURI(uri) {
147
167
  return new FilterClass({
148
168
  type: "object",
149
169
  typename: uri,
150
170
  props: {}
151
171
  });
152
172
  }
153
- static "tag"(tag) {
173
+ static tag(tag) {
154
174
  return new FilterClass({
155
175
  type: "tag",
156
176
  tag
157
177
  });
158
178
  }
159
- static "key"(key, options) {
179
+ static key(key, options) {
160
180
  return new FilterClass({
161
181
  type: "object",
162
182
  typename: null,
@@ -165,21 +185,21 @@ var FilterClass = class FilterClass {
165
185
  metaVersion: options?.version
166
186
  });
167
187
  }
168
- static "props"(props) {
188
+ static props(props) {
169
189
  return new FilterClass({
170
190
  type: "object",
171
191
  typename: null,
172
192
  ...propsFilterToAst(props)
173
193
  });
174
194
  }
175
- static "text"(text, options) {
195
+ static text(text, options) {
176
196
  return new FilterClass({
177
197
  type: "text-search",
178
198
  text,
179
199
  searchKind: options?.type
180
200
  });
181
201
  }
182
- static "foreignKeys"(schema, keys) {
202
+ static foreignKeys(schema, keys) {
183
203
  assertArgument(typeof schema === "string", "schema");
184
204
  assertArgument(!schema.startsWith("dxn:"), "schema");
185
205
  return new FilterClass({
@@ -189,7 +209,7 @@ var FilterClass = class FilterClass {
189
209
  foreignKeys: keys
190
210
  });
191
211
  }
192
- static "eq"(value) {
212
+ static eq(value) {
193
213
  if (!isRef(value) && typeof value === "object" && value !== null) throw new TypeError("Cannot use object as a value for eq filter");
194
214
  return new FilterClass({
195
215
  type: "compare",
@@ -197,67 +217,67 @@ var FilterClass = class FilterClass {
197
217
  value: isRef(value) ? value.noInline().encode() : value
198
218
  });
199
219
  }
200
- static "neq"(value) {
220
+ static neq(value) {
201
221
  return new FilterClass({
202
222
  type: "compare",
203
223
  operator: "neq",
204
224
  value
205
225
  });
206
226
  }
207
- static "gt"(value) {
227
+ static gt(value) {
208
228
  return new FilterClass({
209
229
  type: "compare",
210
230
  operator: "gt",
211
231
  value
212
232
  });
213
233
  }
214
- static "gte"(value) {
234
+ static gte(value) {
215
235
  return new FilterClass({
216
236
  type: "compare",
217
237
  operator: "gte",
218
238
  value
219
239
  });
220
240
  }
221
- static "lt"(value) {
241
+ static lt(value) {
222
242
  return new FilterClass({
223
243
  type: "compare",
224
244
  operator: "lt",
225
245
  value
226
246
  });
227
247
  }
228
- static "lte"(value) {
248
+ static lte(value) {
229
249
  return new FilterClass({
230
250
  type: "compare",
231
251
  operator: "lte",
232
252
  value
233
253
  });
234
254
  }
235
- static "in"(...values) {
255
+ static in(...values) {
236
256
  return new FilterClass({
237
257
  type: "in",
238
258
  values
239
259
  });
240
260
  }
241
- static "contains"(value) {
261
+ static contains(value) {
242
262
  return new FilterClass({
243
263
  type: "contains",
244
264
  value
245
265
  });
246
266
  }
247
- static "between"(from, to) {
267
+ static between(from, to) {
248
268
  return new FilterClass({
249
269
  type: "range",
250
270
  from,
251
271
  to
252
272
  });
253
273
  }
254
- static "updated"(range) {
274
+ static updated(range) {
255
275
  return FilterClass._timeRangeFilter("updatedAt", range);
256
276
  }
257
- static "created"(range) {
277
+ static created(range) {
258
278
  return FilterClass._timeRangeFilter("createdAt", range);
259
279
  }
260
- static "childOf"(parents, options) {
280
+ static childOf(parents, options) {
261
281
  return new FilterClass({
262
282
  type: "child-of",
263
283
  parents: (Array.isArray(parents) ? parents : [parents]).map((item) => {
@@ -267,7 +287,7 @@ var FilterClass = class FilterClass {
267
287
  transitive: options?.transitive ?? true
268
288
  });
269
289
  }
270
- static "_timeRangeFilter"(field, range) {
290
+ static _timeRangeFilter(field, range) {
271
291
  const toMs = (d) => typeof d === "number" ? d : d.getTime();
272
292
  const filters = [];
273
293
  if (range.after != null) filters.push(new FilterClass({
@@ -285,26 +305,26 @@ var FilterClass = class FilterClass {
285
305
  if (filters.length === 0) return FilterClass.everything();
286
306
  return filters.length === 1 ? filters[0] : FilterClass.and(...filters);
287
307
  }
288
- static "not"(filter) {
308
+ static not(filter) {
289
309
  return new FilterClass({
290
310
  type: "not",
291
311
  filter: filter.ast
292
312
  });
293
313
  }
294
- static "and"(...filters) {
314
+ static and(...filters) {
295
315
  return new FilterClass({
296
316
  type: "and",
297
- filters: filters.map((f) => f.ast)
317
+ filters: filters.map((filter) => filter.ast)
298
318
  });
299
319
  }
300
- static "or"(...filters) {
320
+ static or(...filters) {
301
321
  return new FilterClass({
302
322
  type: "or",
303
- filters: filters.map((f) => f.ast)
323
+ filters: filters.map((filter) => filter.ast)
304
324
  });
305
325
  }
306
326
  /** Returns a human-readable string representation of a Filter AST. */
307
- static "pretty"(filter) {
327
+ static pretty(filter) {
308
328
  return prettyFilter(filter.ast);
309
329
  }
310
330
  /** Create a predicate from a filter. */
@@ -312,10 +332,10 @@ var FilterClass = class FilterClass {
312
332
  if (filter === void 0) return (entity) => _filterMatchEntityLocal(entityOrFilter.ast, entity);
313
333
  return _filterMatchEntityLocal(filter.ast, entityOrFilter);
314
334
  });
315
- "constructor"(ast) {
335
+ constructor(ast) {
316
336
  this.ast = ast;
317
337
  }
318
- "~Filter" = FilterClass.variance;
338
+ [FilterTypeId] = FilterClass.variance;
319
339
  };
320
340
  const Filter1 = FilterClass;
321
341
  const propsFilterToAst = (predicates) => {
@@ -340,20 +360,22 @@ const processPredicate = (predicate) => {
340
360
  return FilterClass.eq(predicate).ast;
341
361
  };
342
362
  var QueryClass = class QueryClass {
363
+ static "QueryTypeId" = QueryTypeId;
343
364
  static "variance" = {};
344
- static "is"(value) {
345
- return typeof value === "object" && value !== null && "~Query" in value;
365
+ static "projectionVariance" = {};
366
+ static is(value) {
367
+ return typeof value === "object" && value !== null && QueryTypeId in value;
346
368
  }
347
- static "fromAst"(ast) {
369
+ static fromAst(ast) {
348
370
  return new QueryClass(ast);
349
371
  }
350
- static "select"(filter) {
372
+ static select(filter) {
351
373
  return new QueryClass({
352
374
  type: "select",
353
375
  filter: filter.ast
354
376
  });
355
377
  }
356
- "select"(filter) {
378
+ select(filter) {
357
379
  if (FilterClass.is(filter)) return new QueryClass({
358
380
  type: "filter",
359
381
  selection: this.ast,
@@ -365,34 +387,48 @@ var QueryClass = class QueryClass {
365
387
  filter: FilterClass.props(filter).ast
366
388
  });
367
389
  }
368
- static "type"(schema, predicates) {
390
+ project(property) {
391
+ return {
392
+ [ProjectionTypeId]: QueryClass.projectionVariance,
393
+ query: this.ast,
394
+ property
395
+ };
396
+ }
397
+ static type(schema, predicates) {
369
398
  if (typeof schema !== "string") throw new TypeError("expected typename as the first paramter");
370
399
  return new QueryClass({
371
400
  type: "select",
372
401
  filter: FilterClass.type(schema, predicates).ast
373
402
  });
374
403
  }
375
- static "all"(...queries) {
404
+ static all(...queries) {
376
405
  if (queries.length === 0) throw new TypeError("Query.all combines results of multiple queries, to query all objects use Query.select(Filter.everything())");
377
406
  return new QueryClass({
378
407
  type: "union",
379
408
  queries: queries.map((q) => q.ast)
380
409
  });
381
410
  }
382
- static "without"(source, exclude) {
411
+ static without(source, exclude) {
383
412
  return new QueryClass({
384
413
  type: "set-difference",
385
414
  source: source.ast,
386
415
  exclude: exclude.ast
387
416
  });
388
417
  }
389
- static "from"(...args) {
418
+ static project(query, property) {
419
+ return {
420
+ [ProjectionTypeId]: QueryClass.projectionVariance,
421
+ query: query.ast,
422
+ property
423
+ };
424
+ }
425
+ static from(...args) {
390
426
  return new QueryClass({
391
427
  type: "select",
392
428
  filter: FilterClass.everything().ast
393
429
  }).from(...args);
394
430
  }
395
- "from"(...args) {
431
+ from(...args) {
396
432
  if (args.length > 1 && args.every((arg$1) => _isScopeLike(arg$1))) return new QueryClass({
397
433
  type: "from",
398
434
  query: this.ast,
@@ -421,21 +457,21 @@ var QueryClass = class QueryClass {
421
457
  throw new TypeError("Database and Feed objects are not supported in query-lite sandbox");
422
458
  }
423
459
  /** Returns a human-readable string representation of a Query AST. */
424
- static "pretty"(query) {
460
+ static pretty(query) {
425
461
  return prettyQuery(query.ast);
426
462
  }
427
- "constructor"(ast) {
463
+ constructor(ast) {
428
464
  this.ast = ast;
429
465
  }
430
- "~Query" = QueryClass.variance;
431
- "reference"(key) {
466
+ [QueryTypeId] = QueryClass.variance;
467
+ reference(key) {
432
468
  return new QueryClass({
433
469
  type: "reference-traversal",
434
470
  anchor: this.ast,
435
471
  property: key
436
472
  });
437
473
  }
438
- "referencedBy"(target, key) {
474
+ referencedBy(target, key) {
439
475
  if (target !== void 0 && typeof target !== "string") throw new TypeError("referencedBy requires a typename string in query-lite");
440
476
  const typename = target !== void 0 ? makeTypeDxn(target) : null;
441
477
  return new QueryClass({
@@ -445,7 +481,7 @@ var QueryClass = class QueryClass {
445
481
  typename
446
482
  });
447
483
  }
448
- "sourceOf"(relation, predicates) {
484
+ sourceOf(relation, predicates) {
449
485
  return new QueryClass({
450
486
  type: "relation",
451
487
  anchor: this.ast,
@@ -453,7 +489,7 @@ var QueryClass = class QueryClass {
453
489
  filter: relation === void 0 ? void 0 : typeof relation === "string" ? FilterClass.type(relation, predicates).ast : FilterClass.type(relation, predicates).ast
454
490
  });
455
491
  }
456
- "targetOf"(relation, predicates) {
492
+ targetOf(relation, predicates) {
457
493
  return new QueryClass({
458
494
  type: "relation",
459
495
  anchor: this.ast,
@@ -461,56 +497,73 @@ var QueryClass = class QueryClass {
461
497
  filter: relation === void 0 ? void 0 : typeof relation === "string" ? FilterClass.type(relation, predicates).ast : FilterClass.type(relation, predicates).ast
462
498
  });
463
499
  }
464
- "source"() {
500
+ source() {
465
501
  return new QueryClass({
466
502
  type: "relation-traversal",
467
503
  anchor: this.ast,
468
504
  direction: "source"
469
505
  });
470
506
  }
471
- "target"() {
507
+ target() {
472
508
  return new QueryClass({
473
509
  type: "relation-traversal",
474
510
  anchor: this.ast,
475
511
  direction: "target"
476
512
  });
477
513
  }
478
- "parent"() {
514
+ parent() {
479
515
  return new QueryClass({
480
516
  type: "hierarchy-traversal",
481
517
  anchor: this.ast,
482
518
  direction: "to-parent"
483
519
  });
484
520
  }
485
- "children"() {
521
+ children() {
486
522
  return new QueryClass({
487
523
  type: "hierarchy-traversal",
488
524
  anchor: this.ast,
489
525
  direction: "to-children"
490
526
  });
491
527
  }
492
- "orderBy"(...order) {
528
+ orderBy(...order) {
493
529
  return new QueryClass({
494
530
  type: "order",
495
531
  query: this.ast,
496
- order: order.map((o) => o.ast)
532
+ order: order.map((orderItem) => orderItem.ast)
497
533
  });
498
534
  }
499
- "limit"(limit) {
535
+ limit(limit) {
500
536
  return new QueryClass({
501
537
  type: "limit",
502
538
  query: this.ast,
503
539
  limit
504
540
  });
505
541
  }
506
- "options"(options) {
542
+ skip(skip) {
543
+ return new QueryClass({
544
+ type: "skip",
545
+ query: this.ast,
546
+ skip
547
+ });
548
+ }
549
+ aggregate(aggregates) {
550
+ return new QueryClass({
551
+ type: "aggregate",
552
+ query: this.ast,
553
+ aggregates: Object.entries(aggregates).map(([name, aggregate]) => ({
554
+ name,
555
+ ...aggregate.spec
556
+ }))
557
+ });
558
+ }
559
+ options(options) {
507
560
  return new QueryClass({
508
561
  type: "options",
509
562
  query: this.ast,
510
563
  options
511
564
  });
512
565
  }
513
- "debugLabel"(label) {
566
+ debugLabel(label) {
514
567
  if (this.ast.type === "options") return new QueryClass({
515
568
  type: "options",
516
569
  query: this.ast.query,
@@ -567,6 +620,7 @@ const prettyFilter = (filter) => {
567
620
  }
568
621
  case "compare": return `Filter.${filter.operator}(${JSON.stringify(filter.value)})`;
569
622
  case "in": return `Filter.in(${filter.values.map((v) => JSON.stringify(v)).join(", ")})`;
623
+ case "in-query": return `Filter.in(${prettyQuery(filter.subquery)}.project(${JSON.stringify(filter.property)}))`;
570
624
  case "contains": return `Filter.contains(${JSON.stringify(filter.value)})`;
571
625
  case "range": return `Filter.between(${JSON.stringify(filter.from)}, ${JSON.stringify(filter.to)})`;
572
626
  case "text-search": return `Filter.text(${JSON.stringify(filter.text)})`;
@@ -600,7 +654,7 @@ const prettyQuery = (query) => {
600
654
  case "set-difference": return `Query.without(${prettyQuery(query.source)}, ${prettyQuery(query.exclude)})`;
601
655
  case "order": {
602
656
  const orders = query.order.map((o) => {
603
- if (o.kind === "natural") return "Order.natural";
657
+ if (o.kind === "natural") return `Order.natural(${JSON.stringify(o.direction)})`;
604
658
  if (o.kind === "rank") return `Order.rank(${JSON.stringify(o.direction)})`;
605
659
  if (o.kind === "timestamp") return `Order.${o.field === "updatedAt" ? "updated" : "created"}(${JSON.stringify(o.direction)})`;
606
660
  return `Order.property(${JSON.stringify(o.property)}, ${JSON.stringify(o.direction)})`;
@@ -625,6 +679,14 @@ const prettyQuery = (query) => {
625
679
  }
626
680
  return `${prettyQuery(query.query)}.from(${prettyQuery(query.from.query)})`;
627
681
  case "limit": return `${prettyQuery(query.query)}.limit(${query.limit})`;
682
+ case "skip": return `${prettyQuery(query.query)}.skip(${query.skip})`;
683
+ case "aggregate": {
684
+ const aggregates = query.aggregates.map((aggregate) => {
685
+ const arg = aggregate.kind === "items" ? aggregate.limit !== void 0 ? `{ limit: ${aggregate.limit} }` : "" : aggregate.kind === "count" ? "" : JSON.stringify(aggregate.property);
686
+ return `${JSON.stringify(aggregate.name)}: Aggregate.${aggregate.kind}(${arg})`;
687
+ });
688
+ return `${prettyQuery(query.query)}.aggregate({ ${aggregates.join(", ")} })`;
689
+ }
628
690
  }
629
691
  };
630
692