@routier/core 0.7.0 → 0.8.0

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 (47) hide show
  1. package/dist/codegen/blocks.d.ts +17 -1
  2. package/dist/codegen/handlers/types.d.ts +13 -5
  3. package/dist/codegen/index.cjs +28 -0
  4. package/dist/codegen/index.cjs.map +1 -1
  5. package/dist/codegen/index.js +28 -0
  6. package/dist/codegen/index.js.map +1 -1
  7. package/dist/collections/MemoryDataCollection.d.ts +2 -4
  8. package/dist/collections/index.cjs +127 -15
  9. package/dist/collections/index.cjs.map +1 -1
  10. package/dist/collections/index.js +127 -15
  11. package/dist/collections/index.js.map +1 -1
  12. package/dist/expressions/index.cjs +226 -4
  13. package/dist/expressions/index.cjs.map +1 -1
  14. package/dist/expressions/index.js +228 -5
  15. package/dist/expressions/index.js.map +1 -1
  16. package/dist/expressions/parser.d.ts +42 -1
  17. package/dist/index.cjs +753 -345
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.js +756 -345
  20. package/dist/index.js.map +1 -1
  21. package/dist/plugins/EphemeralDataPlugin.d.ts +8 -0
  22. package/dist/plugins/index.cjs +566 -49
  23. package/dist/plugins/index.cjs.map +1 -1
  24. package/dist/plugins/index.js +566 -48
  25. package/dist/plugins/index.js.map +1 -1
  26. package/dist/plugins/query/QueryOptionsCollection.d.ts +15 -5
  27. package/dist/plugins/query/index.d.ts +1 -0
  28. package/dist/plugins/query/renames.d.ts +27 -0
  29. package/dist/plugins/query/types.d.ts +15 -1
  30. package/dist/plugins/translators/SqlTranslator.d.ts +15 -0
  31. package/dist/schema/SchemaDefinition.d.ts +8 -0
  32. package/dist/schema/changeTracker.d.ts +10 -0
  33. package/dist/schema/index.cjs +291 -274
  34. package/dist/schema/index.cjs.map +1 -1
  35. package/dist/schema/index.d.ts +1 -0
  36. package/dist/schema/index.js +294 -276
  37. package/dist/schema/index.js.map +1 -1
  38. package/dist/schema/types.d.ts +8 -7
  39. package/dist/schema/utils/storageDates.d.ts +25 -0
  40. package/dist/transfer/index.cjs.map +1 -1
  41. package/dist/transfer/index.js.map +1 -1
  42. package/dist/utilities/index.cjs +74 -29
  43. package/dist/utilities/index.cjs.map +1 -1
  44. package/dist/utilities/index.js +74 -29
  45. package/dist/utilities/index.js.map +1 -1
  46. package/package.json +2 -2
  47. package/dist/codegen/utils.d.ts +0 -22
@@ -215,6 +215,30 @@ const mismatchWarning = (expression)=>{
215
215
  const outcome = expression.negated ? "every row matches" : "no row matches";
216
216
  return `Routier: '${side.property.property.getAssignmentPath()}' is a ${side.expected}, and this filter ` + `compares it against ${describeLiteral(side.value.value)}, which is a ${typeof side.value.value}. ` + `A strict comparison between them is the same answer for every row, so ${outcome} and the filter ` + `runs in memory. https://routier.dev/guides/strict-comparison-types`;
217
217
  };
218
+ /**
219
+ * An item as one dispatch receives it: a new object, so a report written on it stays with that dispatch.
220
+ *
221
+ * A database option starts `executed` again, because a report is only an answer from the plugin that
222
+ * made it. A memory option keeps the reason core planned it with. A join's inner options are copied the
223
+ * same way, since a plugin can report on them too.
224
+ */ const toDispatchItem = (item)=>{
225
+ const option = item.option;
226
+ const value = option.name === "join" ? {
227
+ ...option.value,
228
+ innerOptions: option.value.innerOptions.forDispatch()
229
+ } : option.value;
230
+ return {
231
+ index: item.index,
232
+ option: option.target === "database" ? {
233
+ ...option,
234
+ value,
235
+ reason: "executed"
236
+ } : {
237
+ ...option,
238
+ value
239
+ }
240
+ };
241
+ };
218
242
  class QueryOptionsCollection {
219
243
  options = new Map();
220
244
  nextExecutionTarget = "database";
@@ -253,7 +277,7 @@ class QueryOptionsCollection {
253
277
  }
254
278
  }
255
279
  if (name === "filter") {
256
- // Need to check for unmapped and renamed properties
280
+ // Need to check for unmapped properties
257
281
  const filterValue = value;
258
282
  // A tautology (`x => true`) filters nothing — skip it entirely so
259
283
  // plugins never see it
@@ -270,14 +294,10 @@ class QueryOptionsCollection {
270
294
  this.cutOverToMemory("unmapped-property");
271
295
  return false;
272
296
  }
273
- if ((0,_assertions__rspack_import_1/* .isPropertyExpression */.e3)(expression) && expression.property.hasRenamedSegments) {
274
- // Cut over to memory execution: the plugin stores data under the
275
- // `from` (storage) names, but filter selectors reference the
276
- // in-memory names. Memory execution runs after deserialization,
277
- // where the in-memory names exist
278
- this.cutOverToMemory("renamed-property");
279
- return false;
280
- }
297
+ // A renamed property stays with the database. Whether the backend can read a
298
+ // `from` name is the plugin's to know, not this collection's: the property
299
+ // travels with the option, and a plugin that cannot resolve it reports it
300
+ // back see `reportRenamedProperties`
281
301
  if (comparesTypesThatCannotMatch(expression)) {
282
302
  _utilities__rspack_import_3/* .logger.warn */.vF.warn(mismatchWarning(expression));
283
303
  this.cutOverToMemory("predicate-error");
@@ -289,26 +309,19 @@ class QueryOptionsCollection {
289
309
  }
290
310
  if (name === "sort") {
291
311
  const sortValue = value;
292
- // Same rule as filters: sort selectors reference in-memory names, which
293
- // only exist after deserialization when the property is renamed or unmapped
312
+ // Same rule as filters: an unmapped property only exists after deserialization. A
313
+ // renamed one stays with the database, for the plugin to resolve or report
294
314
  if (sortValue.property != null && sortValue.property.isUnmapped) {
295
315
  this.cutOverToMemory("unmapped-property");
296
- } else if (sortValue.property != null && sortValue.property.hasRenamedSegments) {
297
- this.cutOverToMemory("renamed-property");
298
316
  }
299
317
  }
300
318
  if (name === "nearest") {
301
319
  const nearestValue = value;
302
- // Same rule as sort, and for the same reason: the plugin stores the vector under
303
- // the `from` name, and an unmapped property is not stored at all. Both are only
304
- // readable after deserialization, which is where memory execution runs.
305
- //
306
- // This is also what lets every translator's in-memory fallback read the column by
307
- // its resolved name — anything whose storage name differs never reaches them.
320
+ // Same rule as sort, and for the same reason: an unmapped property is not stored at
321
+ // all, so it is only readable after deserialization, which is where memory execution
322
+ // runs. A vector stored under a `from` name is the plugin's to resolve or report.
308
323
  if (nearestValue.property != null && nearestValue.property.isUnmapped) {
309
324
  this.cutOverToMemory("unmapped-property");
310
- } else if (nearestValue.property != null && nearestValue.property.hasRenamedSegments) {
311
- this.cutOverToMemory("renamed-property");
312
325
  }
313
326
  }
314
327
  if ((name === "filter" || name === "sort") && (this.options.has("skip") || this.options.has("take"))) {
@@ -415,6 +428,9 @@ class QueryOptionsCollection {
415
428
  * the shared collection before executing. Without restoring, a re-executed terminal —
416
429
  * the whole point of a subscribed queryable — stacks its option a second time and
417
430
  * runs it over the first execution's scalar result.
431
+ *
432
+ * The item objects are shared with the snapshot. Nothing reports on them, because every
433
+ * dispatch sends a `forDispatch` copy, so a restore brings back no reports.
418
434
  */ snapshot() {
419
435
  const options = new Map([
420
436
  ...this.options.entries()
@@ -492,19 +508,48 @@ class QueryOptionsCollection {
492
508
  }
493
509
  }
494
510
  /**
495
- * Forgets what any previous dispatch reported.
511
+ * A copy of the collection for one dispatch to a plugin, with nothing reported on it.
496
512
  *
497
513
  * Capability is answered per dispatch, so a report is only an answer for the execution that
498
- * produced it. The items are shared with any snapshot, so a report mutated in place otherwise
499
- * survives a restore and a second terminal on the same queryable replays options the plugin
500
- * did run a `skip` applied twice, over rows already windowed.
501
- */ forgetReports() {
514
+ * produced it. Reports are written onto items, and the items of a queryable's collection
515
+ * outlive any one execution: a snapshot shares them, and a subscription dispatches the same
516
+ * query on every change. A report left on them replays options the plugin did run on the
517
+ * next execution, such as a `skip` applied twice over rows already windowed, or hands a
518
+ * renamed filter to memory that the engine could have run.
519
+ *
520
+ * Each item keeps its index, name, value and target. A half from `split`/`splitAt` is copied
521
+ * with a copy of its origin, and its items are that copy's items, so a report on the half still
522
+ * cascades over the whole dispatch without reaching the collection it was copied from.
523
+ */ forDispatch() {
524
+ if (this.origin == null) {
525
+ return this.copyForDispatch().copy;
526
+ }
527
+ const { copy: root, copies } = this.origin.copyForDispatch();
528
+ const half = new QueryOptionsCollection();
502
529
  this.resolveEnumeration();
503
530
  for (const item of this.enumeratedItems){
504
- if (item.option.target === "database") {
505
- item.option.reason = "executed";
506
- }
531
+ // An item added to the half after it was split has no counterpart in the origin
532
+ half.adopt(copies.get(item) ?? toDispatchItem(item));
507
533
  }
534
+ half.origin = root;
535
+ return half;
536
+ }
537
+ copyForDispatch() {
538
+ const copy = new QueryOptionsCollection();
539
+ const copies = new Map();
540
+ this.resolveEnumeration();
541
+ for (const item of this.enumeratedItems){
542
+ const copied = toDispatchItem(item);
543
+ copies.set(item, copied);
544
+ copy.adopt(copied);
545
+ }
546
+ copy.nextExecutionTarget = this.nextExecutionTarget;
547
+ copy.nextExecutionReason = this.nextExecutionReason;
548
+ copy.nextIndex = this.nextIndex;
549
+ return {
550
+ copy,
551
+ copies
552
+ };
508
553
  }
509
554
  /** The options the database did not run, in the order they were written. */ notExecuted() {
510
555
  this.resolveEnumeration();