@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
@@ -1019,6 +1019,7 @@ __webpack_require__.d(__webpack_exports__, {
1019
1019
 
1020
1020
 
1021
1021
 
1022
+
1022
1023
  // Error message constants
1023
1024
  const ERROR_MESSAGES = {
1024
1025
  PROPERTY_NOT_FOUND: (path)=>`Error parsing query, could not find PropertyInfo for path: ${path}`,
@@ -1626,6 +1627,9 @@ const COALESCE_OPERATORS = sourceKeyed({
1626
1627
  // A comparison always names a schema property, so the condition alone settles it
1627
1628
  return true;
1628
1629
  }
1630
+ if (operand.kind === "opaque") {
1631
+ return operand.reads.some(containsProperty);
1632
+ }
1629
1633
  return operand.kind === "arithmetic" && (containsProperty(operand.left) || containsProperty(operand.right) || operand.extra != null && containsProperty(operand.extra));
1630
1634
  };
1631
1635
  const DECLARATION_KEYWORDS = new Set([
@@ -1803,13 +1807,18 @@ const resolveParamPath = (paramsName, path, data)=>{
1803
1807
  scope;
1804
1808
  paramsName;
1805
1809
  params;
1810
+ /**
1811
+ * Whether this parses a value selector rather than a filter, and so reads a call it has no node for
1812
+ * as an `OpaqueOperand` instead of refusing it.
1813
+ */ readsValues;
1806
1814
  /** Set when a param value shaped the tree itself (e.g. x[p.name]) — such templates cannot be cached. */ structurallyDependsOnParams = false;
1807
- constructor(schema, stream, scope, paramsName, params){
1815
+ constructor(schema, stream, scope, paramsName, params, readsValues = false){
1808
1816
  this.schema = schema;
1809
1817
  this.stream = stream;
1810
1818
  this.scope = scope;
1811
1819
  this.paramsName = paramsName;
1812
1820
  this.params = params;
1821
+ this.readsValues = readsValues;
1813
1822
  }
1814
1823
  parse() {
1815
1824
  const expression = this.parseOr();
@@ -1831,6 +1840,71 @@ const resolveParamPath = (paramsName, path, data)=>{
1831
1840
  }
1832
1841
  return answer;
1833
1842
  }
1843
+ /**
1844
+ * What a value selector returns: one value, or the fields of an object literal.
1845
+ *
1846
+ * A block body is read only when it does nothing but return, which is what a transpiler makes of an
1847
+ * arrow function. Anything more is refused, and the caller falls back to running the function.
1848
+ */ parseSelector() {
1849
+ const block = this.stream.matchPunctuation("{");
1850
+ if (block) {
1851
+ const keyword = this.stream.next();
1852
+ if (keyword.kind !== "identifier" || keyword.value !== "return") {
1853
+ throw new Error(ERROR_MESSAGES.UNSUPPORTED("a selector block that does more than return"));
1854
+ }
1855
+ }
1856
+ const selected = this.stream.isPunctuation("{") ? this.parseObjectLiteral() : this.stream.isPunctuation("(") && this.stream.isPunctuation("{", 1) ? this.parseBracketedObjectLiteral() : this.parseInterpolation();
1857
+ if (block) {
1858
+ this.stream.matchPunctuation(";");
1859
+ this.stream.expectPunctuation("}");
1860
+ }
1861
+ if (!this.stream.isAtEnd) {
1862
+ throw new Error(ERROR_MESSAGES.UNSUPPORTED(`unexpected token '${this.stream.peek()?.value}'`));
1863
+ }
1864
+ return selected;
1865
+ }
1866
+ /** `({ … })`, the arrow body that returns an object. */ parseBracketedObjectLiteral() {
1867
+ this.stream.expectPunctuation("(");
1868
+ const fields = this.parseObjectLiteral();
1869
+ this.stream.expectPunctuation(")");
1870
+ return fields;
1871
+ }
1872
+ /**
1873
+ * The fields of an object literal, each one value.
1874
+ *
1875
+ * A field's value is read without a top-level conditional, which needs brackets here: the look-ahead
1876
+ * for a `?` does not stop at the comma that ends the field.
1877
+ */ parseObjectLiteral() {
1878
+ this.stream.expectPunctuation("{");
1879
+ const fields = [];
1880
+ while(!this.stream.matchPunctuation("}")){
1881
+ const key = this.stream.next();
1882
+ if (key.kind !== "identifier" && key.kind !== "string") {
1883
+ throw new Error(ERROR_MESSAGES.UNSUPPORTED(`the object key '${key.value}'`));
1884
+ }
1885
+ fields.push({
1886
+ name: key.value,
1887
+ operand: this.stream.matchPunctuation(":") ? this.parseValue() : this.parseShorthand(key)
1888
+ });
1889
+ if (!this.stream.matchPunctuation(",")) {
1890
+ this.stream.expectPunctuation("}");
1891
+ break;
1892
+ }
1893
+ }
1894
+ return fields;
1895
+ }
1896
+ /** `{ name }`, which reads what the parameter list bound `name` to. */ parseShorthand(key) {
1897
+ const binding = key.kind === "identifier" ? this.scope.get(key.value) : undefined;
1898
+ if (binding == null || binding.kind === "inlined") {
1899
+ throw new Error(ERROR_MESSAGES.VARIABLE_VALUE(key.value));
1900
+ }
1901
+ return this.parseChain({
1902
+ kind: binding.kind,
1903
+ path: [
1904
+ ...binding.path
1905
+ ]
1906
+ });
1907
+ }
1834
1908
  /** The expression a `{ … }` block answers with. */ parseBlock() {
1835
1909
  this.stream.expectPunctuation("{");
1836
1910
  const answer = this.parseStatements();
@@ -2094,7 +2168,7 @@ const resolveParamPath = (paramsName, path, data)=>{
2094
2168
  * A structural dependence found inside propagates outward: the template it belongs to cannot be
2095
2169
  * cached either.
2096
2170
  */ parseNested(source) {
2097
- const nested = new ExpressionParser(this.schema, new TokenStream(tokenize(source)), this.scope, this.paramsName, this.params);
2171
+ const nested = new ExpressionParser(this.schema, new TokenStream(tokenize(source)), this.scope, this.paramsName, this.params, this.readsValues);
2098
2172
  const operand = nested.parseInterpolation();
2099
2173
  // Leftover tokens mean the interpolation held something this reads only part of. Silently
2100
2174
  // keeping the part it understood is the worst outcome available: `${x.age > 5 ? "a" : "b"}`
@@ -2386,7 +2460,7 @@ const resolveParamPath = (paramsName, path, data)=>{
2386
2460
  if (argument.kind === "method-call") {
2387
2461
  throw new Error(ERROR_MESSAGES.UNSUPPORTED("nested method call inside .includes()"));
2388
2462
  }
2389
- if (argument.kind === "arithmetic" || argument.kind === "conditional") {
2463
+ if (argument.kind === "arithmetic" || argument.kind === "conditional" || argument.kind === "opaque") {
2390
2464
  throw new Error(ERROR_MESSAGES.UNSUPPORTED("arithmetic inside .includes()"));
2391
2465
  }
2392
2466
  return {
@@ -2480,7 +2554,7 @@ const resolveParamPath = (paramsName, path, data)=>{
2480
2554
  if (argument.kind === "method-call") {
2481
2555
  throw new Error(ERROR_MESSAGES.UNSUPPORTED(`nested method call inside .${method}()`));
2482
2556
  }
2483
- if (argument.kind === "arithmetic" || argument.kind === "conditional") {
2557
+ if (argument.kind === "arithmetic" || argument.kind === "conditional" || argument.kind === "opaque") {
2484
2558
  throw new Error(ERROR_MESSAGES.UNSUPPORTED(`arithmetic inside .${method}()`));
2485
2559
  }
2486
2560
  return {
@@ -2490,9 +2564,20 @@ const resolveParamPath = (paramsName, path, data)=>{
2490
2564
  argument
2491
2565
  };
2492
2566
  }
2567
+ if (this.readsValues) {
2568
+ return this.withGroupCall(this.opaqueCall(this.resolveChain(options.kind, path, transformer, locale)));
2569
+ }
2493
2570
  throw new Error(ERROR_MESSAGES.UNSUPPORTED(`method '.${method}()'`));
2494
2571
  }
2495
2572
  if (transformer != null) {
2573
+ if (this.readsValues) {
2574
+ return this.withGroupCall({
2575
+ kind: "opaque",
2576
+ reads: [
2577
+ this.resolveChain(options.kind, path, transformer, locale)
2578
+ ]
2579
+ });
2580
+ }
2496
2581
  throw new Error(ERROR_MESSAGES.UNSUPPORTED("property access after a transform method"));
2497
2582
  }
2498
2583
  path.push(segment.value);
@@ -2637,10 +2722,39 @@ const resolveParamPath = (paramsName, path, data)=>{
2637
2722
  argument
2638
2723
  };
2639
2724
  }
2725
+ // Any other member or call of a value, which a selector reads through
2726
+ if (this.readsValues) {
2727
+ this.stream.next();
2728
+ this.stream.next();
2729
+ receiver = this.stream.isPunctuation("(") ? this.opaqueCall(receiver) : {
2730
+ kind: "opaque",
2731
+ reads: [
2732
+ receiver
2733
+ ]
2734
+ };
2735
+ continue;
2736
+ }
2640
2737
  break;
2641
2738
  }
2642
2739
  return receiver;
2643
2740
  }
2741
+ /** A call with no node of its own, from its `(`, kept for what its receiver and arguments read. */ opaqueCall(receiver) {
2742
+ const reads = [
2743
+ receiver
2744
+ ];
2745
+ this.stream.expectPunctuation("(");
2746
+ while(!this.stream.matchPunctuation(")")){
2747
+ reads.push(this.parseValue());
2748
+ if (!this.stream.matchPunctuation(",")) {
2749
+ this.stream.expectPunctuation(")");
2750
+ break;
2751
+ }
2752
+ }
2753
+ return {
2754
+ kind: "opaque",
2755
+ reads
2756
+ };
2757
+ }
2644
2758
  withValueTransformer(operand) {
2645
2759
  if (this.stream.isPunctuation(".")) {
2646
2760
  const method = this.stream.peek(1);
@@ -2674,6 +2788,10 @@ const resolveParamPath = (paramsName, path, data)=>{
2674
2788
  if (right.kind === "method-call") {
2675
2789
  throw new Error(ERROR_MESSAGES.UNSUPPORTED("method call on the right side of a comparison"));
2676
2790
  }
2791
+ // A comparison is a tree a backend renders, and this operand has no node in one
2792
+ if (left.kind === "opaque" || right.kind === "opaque") {
2793
+ throw new Error(ERROR_MESSAGES.UNSUPPORTED("a call with no expression form inside a comparison"));
2794
+ }
2677
2795
  if (needsBrackets(left) || needsBrackets(right)) {
2678
2796
  throw new Error(ERROR_MESSAGES.UNSUPPORTED("a bitwise or nullish operator compared without brackets, which JavaScript reads the other way round"));
2679
2797
  }
@@ -2887,6 +3005,9 @@ const resolveParamPath = (paramsName, path, data)=>{
2887
3005
  if (operand.kind === "method-call") {
2888
3006
  throw new Error(ERROR_MESSAGES.UNSUPPORTED("a method call inside arithmetic"));
2889
3007
  }
3008
+ if (operand.kind === "opaque") {
3009
+ throw new Error(ERROR_MESSAGES.UNSUPPORTED("a call with no expression form inside arithmetic"));
3010
+ }
2890
3011
  return this.createValueExpression(operand, null, /* applyConverter */ false);
2891
3012
  }
2892
3013
  createPropertyExpression(operand) {
@@ -3222,6 +3343,104 @@ const toExpression = (schema, fn, params)=>{
3222
3343
  return _types__rspack_import_1/* .Expression.notParsable */.r4.notParsable(refusalOf(error));
3223
3344
  }
3224
3345
  };
3346
+ const collectReads = (operand, into)=>{
3347
+ switch(operand.kind){
3348
+ case "property":
3349
+ into.add(operand.property);
3350
+ return;
3351
+ case "method-call":
3352
+ collectReads(operand.target, into);
3353
+ collectReads(operand.argument, into);
3354
+ return;
3355
+ case "arithmetic":
3356
+ collectReads(operand.left, into);
3357
+ collectReads(operand.right, into);
3358
+ if (operand.extra != null) {
3359
+ collectReads(operand.extra, into);
3360
+ }
3361
+ return;
3362
+ case "conditional":
3363
+ for (const property of getProperties(operand.condition)){
3364
+ into.add(property);
3365
+ }
3366
+ collectReads(operand.whenTrue, into);
3367
+ collectReads(operand.whenFalse, into);
3368
+ return;
3369
+ case "opaque":
3370
+ for (const read of operand.reads){
3371
+ collectReads(read, into);
3372
+ }
3373
+ return;
3374
+ }
3375
+ };
3376
+ const selectedValue = (operand)=>{
3377
+ const found = new Set();
3378
+ collectReads(operand, found);
3379
+ const reads = [
3380
+ ...found
3381
+ ];
3382
+ return {
3383
+ property: reads.length === 1 ? reads[0] : null,
3384
+ reads,
3385
+ isDirectProperty: operand.kind === "property" && operand.transformer == null
3386
+ };
3387
+ };
3388
+ // Keyed like the template cache. A selector takes no params, so every result is cacheable
3389
+ const selectorCache = new WeakMap();
3390
+ /**
3391
+ * Reads a sort, map, group or `nearest` selector with the grammar filters use, for what its value is
3392
+ * read from.
3393
+ *
3394
+ * Not for evaluating it: the caller's function stays the value, and nothing here renders one. A plugin
3395
+ * decides from the result whether it can run the option. One that orders or projects by column cannot
3396
+ * run a value that is not the property itself, and one that runs the function over stored rows cannot
3397
+ * run it over a renamed property.
3398
+ *
3399
+ * So the grammar is wider here than for a filter. A call it has no node for, such as `getFullYear()`,
3400
+ * is kept for the operands it reads rather than refused, since the function it came from still runs.
3401
+ *
3402
+ * `not-parsable` is not logged. The option runs as it did before the selector was parsed.
3403
+ *
3404
+ * Cached by function source per schema, like `toExpression`. The result is shared, so it is read-only.
3405
+ */ const parseSelector = (schema, selector)=>{
3406
+ const source = selector.toString();
3407
+ let bySource = selectorCache.get(schema);
3408
+ const cached = bySource?.get(source);
3409
+ if (cached != null) {
3410
+ return cached;
3411
+ }
3412
+ let parsed;
3413
+ try {
3414
+ const shape = resolveFunctionShape(source, false);
3415
+ const parser = new ExpressionParser(schema, new TokenStream(tokenize(shape.body)), shape.scope, null, undefined, true);
3416
+ const selected = parser.parseSelector();
3417
+ parsed = Array.isArray(selected) ? {
3418
+ kind: "object",
3419
+ fields: selected.map((field)=>({
3420
+ name: field.name,
3421
+ ...selectedValue(field.operand)
3422
+ }))
3423
+ } : {
3424
+ kind: "value",
3425
+ value: selectedValue(selected)
3426
+ };
3427
+ } catch (error) {
3428
+ parsed = {
3429
+ kind: "not-parsable",
3430
+ reason: refusalOf(error)
3431
+ };
3432
+ }
3433
+ if (bySource == null) {
3434
+ bySource = new Map();
3435
+ selectorCache.set(schema, bySource);
3436
+ }
3437
+ // Stryker disable next-line all: the same resource bound as the template cache's
3438
+ if (bySource.size >= MAX_CACHED_TEMPLATES_PER_SCHEMA) {
3439
+ bySource.clear();
3440
+ }
3441
+ bySource.set(source, parsed);
3442
+ return parsed;
3443
+ }; // #endregion
3225
3444
 
3226
3445
 
3227
3446
  },
@@ -3929,6 +4148,30 @@ const mismatchWarning = (expression)=>{
3929
4148
  const outcome = expression.negated ? "every row matches" : "no row matches";
3930
4149
  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`;
3931
4150
  };
4151
+ /**
4152
+ * An item as one dispatch receives it: a new object, so a report written on it stays with that dispatch.
4153
+ *
4154
+ * A database option starts `executed` again, because a report is only an answer from the plugin that
4155
+ * made it. A memory option keeps the reason core planned it with. A join's inner options are copied the
4156
+ * same way, since a plugin can report on them too.
4157
+ */ const toDispatchItem = (item)=>{
4158
+ const option = item.option;
4159
+ const value = option.name === "join" ? {
4160
+ ...option.value,
4161
+ innerOptions: option.value.innerOptions.forDispatch()
4162
+ } : option.value;
4163
+ return {
4164
+ index: item.index,
4165
+ option: option.target === "database" ? {
4166
+ ...option,
4167
+ value,
4168
+ reason: "executed"
4169
+ } : {
4170
+ ...option,
4171
+ value
4172
+ }
4173
+ };
4174
+ };
3932
4175
  class QueryOptionsCollection {
3933
4176
  options = new Map();
3934
4177
  nextExecutionTarget = "database";
@@ -3967,7 +4210,7 @@ class QueryOptionsCollection {
3967
4210
  }
3968
4211
  }
3969
4212
  if (name === "filter") {
3970
- // Need to check for unmapped and renamed properties
4213
+ // Need to check for unmapped properties
3971
4214
  const filterValue = value;
3972
4215
  // A tautology (`x => true`) filters nothing — skip it entirely so
3973
4216
  // plugins never see it
@@ -3984,14 +4227,10 @@ class QueryOptionsCollection {
3984
4227
  this.cutOverToMemory("unmapped-property");
3985
4228
  return false;
3986
4229
  }
3987
- if ((0,_assertions__rspack_import_1/* .isPropertyExpression */.e3)(expression) && expression.property.hasRenamedSegments) {
3988
- // Cut over to memory execution: the plugin stores data under the
3989
- // `from` (storage) names, but filter selectors reference the
3990
- // in-memory names. Memory execution runs after deserialization,
3991
- // where the in-memory names exist
3992
- this.cutOverToMemory("renamed-property");
3993
- return false;
3994
- }
4230
+ // A renamed property stays with the database. Whether the backend can read a
4231
+ // `from` name is the plugin's to know, not this collection's: the property
4232
+ // travels with the option, and a plugin that cannot resolve it reports it
4233
+ // back see `reportRenamedProperties`
3995
4234
  if (comparesTypesThatCannotMatch(expression)) {
3996
4235
  _utilities__rspack_import_3/* .logger.warn */.vF.warn(mismatchWarning(expression));
3997
4236
  this.cutOverToMemory("predicate-error");
@@ -4003,26 +4242,19 @@ class QueryOptionsCollection {
4003
4242
  }
4004
4243
  if (name === "sort") {
4005
4244
  const sortValue = value;
4006
- // Same rule as filters: sort selectors reference in-memory names, which
4007
- // only exist after deserialization when the property is renamed or unmapped
4245
+ // Same rule as filters: an unmapped property only exists after deserialization. A
4246
+ // renamed one stays with the database, for the plugin to resolve or report
4008
4247
  if (sortValue.property != null && sortValue.property.isUnmapped) {
4009
4248
  this.cutOverToMemory("unmapped-property");
4010
- } else if (sortValue.property != null && sortValue.property.hasRenamedSegments) {
4011
- this.cutOverToMemory("renamed-property");
4012
4249
  }
4013
4250
  }
4014
4251
  if (name === "nearest") {
4015
4252
  const nearestValue = value;
4016
- // Same rule as sort, and for the same reason: the plugin stores the vector under
4017
- // the `from` name, and an unmapped property is not stored at all. Both are only
4018
- // readable after deserialization, which is where memory execution runs.
4019
- //
4020
- // This is also what lets every translator's in-memory fallback read the column by
4021
- // its resolved name — anything whose storage name differs never reaches them.
4253
+ // Same rule as sort, and for the same reason: an unmapped property is not stored at
4254
+ // all, so it is only readable after deserialization, which is where memory execution
4255
+ // runs. A vector stored under a `from` name is the plugin's to resolve or report.
4022
4256
  if (nearestValue.property != null && nearestValue.property.isUnmapped) {
4023
4257
  this.cutOverToMemory("unmapped-property");
4024
- } else if (nearestValue.property != null && nearestValue.property.hasRenamedSegments) {
4025
- this.cutOverToMemory("renamed-property");
4026
4258
  }
4027
4259
  }
4028
4260
  if ((name === "filter" || name === "sort") && (this.options.has("skip") || this.options.has("take"))) {
@@ -4129,6 +4361,9 @@ class QueryOptionsCollection {
4129
4361
  * the shared collection before executing. Without restoring, a re-executed terminal —
4130
4362
  * the whole point of a subscribed queryable — stacks its option a second time and
4131
4363
  * runs it over the first execution's scalar result.
4364
+ *
4365
+ * The item objects are shared with the snapshot. Nothing reports on them, because every
4366
+ * dispatch sends a `forDispatch` copy, so a restore brings back no reports.
4132
4367
  */ snapshot() {
4133
4368
  const options = new Map([
4134
4369
  ...this.options.entries()
@@ -4206,19 +4441,48 @@ class QueryOptionsCollection {
4206
4441
  }
4207
4442
  }
4208
4443
  /**
4209
- * Forgets what any previous dispatch reported.
4444
+ * A copy of the collection for one dispatch to a plugin, with nothing reported on it.
4210
4445
  *
4211
4446
  * Capability is answered per dispatch, so a report is only an answer for the execution that
4212
- * produced it. The items are shared with any snapshot, so a report mutated in place otherwise
4213
- * survives a restore and a second terminal on the same queryable replays options the plugin
4214
- * did run a `skip` applied twice, over rows already windowed.
4215
- */ forgetReports() {
4447
+ * produced it. Reports are written onto items, and the items of a queryable's collection
4448
+ * outlive any one execution: a snapshot shares them, and a subscription dispatches the same
4449
+ * query on every change. A report left on them replays options the plugin did run on the
4450
+ * next execution, such as a `skip` applied twice over rows already windowed, or hands a
4451
+ * renamed filter to memory that the engine could have run.
4452
+ *
4453
+ * Each item keeps its index, name, value and target. A half from `split`/`splitAt` is copied
4454
+ * with a copy of its origin, and its items are that copy's items, so a report on the half still
4455
+ * cascades over the whole dispatch without reaching the collection it was copied from.
4456
+ */ forDispatch() {
4457
+ if (this.origin == null) {
4458
+ return this.copyForDispatch().copy;
4459
+ }
4460
+ const { copy: root, copies } = this.origin.copyForDispatch();
4461
+ const half = new QueryOptionsCollection();
4216
4462
  this.resolveEnumeration();
4217
4463
  for (const item of this.enumeratedItems){
4218
- if (item.option.target === "database") {
4219
- item.option.reason = "executed";
4220
- }
4464
+ // An item added to the half after it was split has no counterpart in the origin
4465
+ half.adopt(copies.get(item) ?? toDispatchItem(item));
4221
4466
  }
4467
+ half.origin = root;
4468
+ return half;
4469
+ }
4470
+ copyForDispatch() {
4471
+ const copy = new QueryOptionsCollection();
4472
+ const copies = new Map();
4473
+ this.resolveEnumeration();
4474
+ for (const item of this.enumeratedItems){
4475
+ const copied = toDispatchItem(item);
4476
+ copies.set(item, copied);
4477
+ copy.adopt(copied);
4478
+ }
4479
+ copy.nextExecutionTarget = this.nextExecutionTarget;
4480
+ copy.nextExecutionReason = this.nextExecutionReason;
4481
+ copy.nextIndex = this.nextIndex;
4482
+ return {
4483
+ copy,
4484
+ copies
4485
+ };
4222
4486
  }
4223
4487
  /** The options the database did not run, in the order they were written. */ notExecuted() {
4224
4488
  this.resolveEnumeration();
@@ -4418,6 +4682,128 @@ var HashType = /*#__PURE__*/ (/* unused pure expression or super */ null && (fun
4418
4682
  }({})));
4419
4683
 
4420
4684
 
4685
+ },
4686
+ 575(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
4687
+ __webpack_require__.d(__webpack_exports__, {
4688
+ l: () => (isArrayValued)
4689
+ });
4690
+ /* import */ var _types__rspack_import_0 = __webpack_require__(537);
4691
+
4692
+ /**
4693
+ * Types whose runtime value is a JS array.
4694
+ *
4695
+ * `Array` and `Vector` are the same thing to every layer that copies, compares, hashes or
4696
+ * freezes a value — a vector is a list of numbers and nothing more. They differ only where a
4697
+ * backend chooses storage, which is the one place that should ask for `SchemaTypes.Vector` by
4698
+ * name.
4699
+ *
4700
+ * This exists so adding a third array-shaped type is one edit rather than a hunt through
4701
+ * twelve handlers. Missing one of those is silent in the worst way: a vector that clones by
4702
+ * reference is shared with the change tracker's copy, so overwriting an embedding produces no
4703
+ * diff and the save reports nothing to do.
4704
+ */ const ARRAY_VALUED_TYPES = new Set([
4705
+ _types__rspack_import_0/* .SchemaTypes.Array */.L.Array,
4706
+ _types__rspack_import_0/* .SchemaTypes.Vector */.L.Vector
4707
+ ]);
4708
+ /** True when the property's value is a JS array and needs value rather than reference semantics. */ const isArrayValued = (type)=>ARRAY_VALUED_TYPES.has(type);
4709
+ /**
4710
+ * True when the property's elements are primitives, so a spread is a sufficient copy.
4711
+ *
4712
+ * A vector is always numbers, so it never needs the per-element deep copy an array of objects
4713
+ * or dates does.
4714
+ */ const PRIMITIVE_ELEMENT_TYPES = new Set([
4715
+ _types__rspack_import_0/* .SchemaTypes.String */.L.String,
4716
+ _types__rspack_import_0/* .SchemaTypes.Number */.L.Number,
4717
+ _types__rspack_import_0/* .SchemaTypes.Boolean */.L.Boolean
4718
+ ]);
4719
+ const hasPrimitiveElements = (type, elementType)=>type === SchemaTypes.Vector || PRIMITIVE_ELEMENT_TYPES.has(elementType);
4720
+
4721
+
4722
+ },
4723
+ 894(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
4724
+ __webpack_require__.d(__webpack_exports__, {
4725
+ T: () => (getStorageDateReviver)
4726
+ });
4727
+ /* import */ var _types__rspack_import_0 = __webpack_require__(537);
4728
+ /* import */ var _propertyKind__rspack_import_1 = __webpack_require__(575);
4729
+
4730
+
4731
+ const collectDatePaths = (properties, paths)=>{
4732
+ for (const property of properties){
4733
+ // The stored value belongs to whoever wrote it: a custom serializer, deserializer or
4734
+ // transform reads it back, and would be handed a Date it did not expect. Unmapped
4735
+ // properties are never stored.
4736
+ if (property.valueSerializer != null || property.valueDeserializer != null || property.transform != null || property.isUnmapped) {
4737
+ continue;
4738
+ }
4739
+ if (property.type === _types__rspack_import_0/* .SchemaTypes.Object */.L.Object) {
4740
+ collectDatePaths(property.children, paths);
4741
+ continue;
4742
+ }
4743
+ const isArray = (0,_propertyKind__rspack_import_1/* .isArrayValued */.l)(property.type) && property.innerSchema?.type === _types__rspack_import_0/* .SchemaTypes.Date */.L.Date;
4744
+ if (property.type !== _types__rspack_import_0/* .SchemaTypes.Date */.L.Date && isArray === false) {
4745
+ continue;
4746
+ }
4747
+ paths.push({
4748
+ segments: [
4749
+ ...property.getParentPathArray({
4750
+ useFromPropertyName: true
4751
+ }),
4752
+ property.getResolvedName()
4753
+ ],
4754
+ isArray
4755
+ });
4756
+ }
4757
+ };
4758
+ const reviveAt = (record, path)=>{
4759
+ const { segments } = path;
4760
+ let parent = record;
4761
+ for(let i = 0, length = segments.length - 1; i < length; i++){
4762
+ parent = parent[segments[i]];
4763
+ // An absent or null parent holds no date
4764
+ if (parent == null || typeof parent !== "object") {
4765
+ return;
4766
+ }
4767
+ }
4768
+ const key = segments[segments.length - 1];
4769
+ const value = parent[key];
4770
+ if (path.isArray === false) {
4771
+ if (typeof value === "string") {
4772
+ parent[key] = new Date(value);
4773
+ }
4774
+ return;
4775
+ }
4776
+ if (Array.isArray(value)) {
4777
+ for(let i = 0, length = value.length; i < length; i++){
4778
+ if (typeof value[i] === "string") {
4779
+ value[i] = new Date(value[i]);
4780
+ }
4781
+ }
4782
+ }
4783
+ };
4784
+ /** Per schema: `null` for a schema with no dates, so a caller can skip the pass. */ const revivers = new WeakMap();
4785
+ /**
4786
+ * The reviver for `schema`'s records, or `null` when it declares no dates.
4787
+ *
4788
+ * Built once per compiled schema. A read revives every row it returns, so the paths are resolved
4789
+ * here rather than per row.
4790
+ */ const getStorageDateReviver = (schema)=>{
4791
+ const cached = revivers.get(schema);
4792
+ if (cached !== undefined) {
4793
+ return cached;
4794
+ }
4795
+ const paths = [];
4796
+ collectDatePaths(schema.properties, paths);
4797
+ const reviver = paths.length === 0 ? null : (record)=>{
4798
+ for(let i = 0, length = paths.length; i < length; i++){
4799
+ reviveAt(record, paths[i]);
4800
+ }
4801
+ };
4802
+ revivers.set(schema, reviver);
4803
+ return reviver;
4804
+ };
4805
+
4806
+
4421
4807
  },
4422
4808
  76(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
4423
4809
  __webpack_require__.d(__webpack_exports__, {
@@ -4692,9 +5078,10 @@ __webpack_require__.d(__webpack_exports__, {
4692
5078
  QB: () => (/* reexport */ RetryDbPlugin),
4693
5079
  m6: () => (/* reexport */ executeJoin),
4694
5080
  i1: () => (/* reexport */ parameteriseDocument),
4695
- __: () => (/* reexport */ toEntityShape),
5081
+ wk: () => (/* reexport */ reportRenamedProperties),
4696
5082
  VW: () => (/* reexport */ applyInnerOptions),
4697
5083
  B2: () => (/* reexport */ describeUnparsableFilter),
5084
+ __: () => (/* reexport */ toEntityShape),
4698
5085
  Jd: () => (/* reexport */ EphemeralDataPlugin),
4699
5086
  Pl: () => (/* reexport */ deserializePersistResult),
4700
5087
  JF: () => (/* reexport */ DataTranslator),
@@ -5685,9 +6072,12 @@ class JsonTranslator extends DataTranslator {
5685
6072
  }
5686
6073
  }
5687
6074
 
6075
+ // EXTERNAL MODULE: ./src/schema/utils/storageDates.ts
6076
+ var storageDates = __webpack_require__(894);
5688
6077
  ;// CONCATENATED MODULE: ./src/plugins/translators/SqlTranslator.ts
5689
6078
 
5690
6079
 
6080
+
5691
6081
  /**
5692
6082
  * A stored vector as a list of numbers, whatever the driver handed back.
5693
6083
  *
@@ -5716,6 +6106,31 @@ class SqlTranslator extends DataTranslator {
5716
6106
  super(query);
5717
6107
  this.pushedDown = pushedDown;
5718
6108
  }
6109
+ /**
6110
+ * Dates back as Dates, before the caller's selectors run over the rows.
6111
+ *
6112
+ * A `group` key and a `map` are the caller's lambdas, run here over rows as the engine returned them.
6113
+ * SQLite, D1 and libSQL hand a date back as the TEXT it was stored as, which has no `getFullYear()`
6114
+ * and groups apart from the Date the entity holds. Revived at storage paths and in place, which the
6115
+ * datastore's deserialization still reads, and after `decodeJsonColumns`, so a date inside a JSON
6116
+ * column is revived too. Only a string is converted, so an engine that returns a Date (PostgreSQL,
6117
+ * PGlite, MySQL) is left alone, and so is a row already revived.
6118
+ *
6119
+ * Not a joined statement's rows, which are tuples, each half already deserialized. Nor rows whose
6120
+ * `group` or `map` was handed back, which the datastore runs after deserializing them.
6121
+ */ translate(data) {
6122
+ const runsHere = (name)=>this.query.options.get(name).some((item)=>item.option.target === "database" && item.option.reason === "executed");
6123
+ if (this.pushedDown.join !== true && this.query.schema != null && Array.isArray(data) && (runsHere("group") || runsHere("map"))) {
6124
+ const reviveDates = (0,storageDates/* .getStorageDateReviver */.T)(this.query.schema);
6125
+ for(let i = 0, length = reviveDates == null ? 0 : data.length; i < length; i++){
6126
+ const row = data[i];
6127
+ if (row != null && typeof row === "object") {
6128
+ reviveDates(row);
6129
+ }
6130
+ }
6131
+ }
6132
+ return super.translate(data);
6133
+ }
5719
6134
  count(data, _) {
5720
6135
  if (Array.isArray(data) && data.length > 0) {
5721
6136
  // Count is returned as the property alias on the query.
@@ -6167,7 +6582,6 @@ const isParameter = (value)=>typeof value === "object" && value !== null && PARA
6167
6582
  */ const MEMORY_EXECUTION_EXPLANATIONS = {
6168
6583
  "not-parsable": "A filter could not be parsed into an expression tree, so it and every option after it run in memory.",
6169
6584
  "unmapped-property": "The property is not stored in the database, so it can only be read after deserialization.",
6170
- "renamed-property": "The property is stored under a different name, and selectors use the in-memory name, so it can only be read after deserialization.",
6171
6585
  "map-rename": "A map renames or drops properties, so every option after it refers to names the database does not have.",
6172
6586
  "after-nearest": "A similarity search orders and limits rows, and the plugin cannot report whether it performed the search, so every option after it runs in memory.",
6173
6587
  "after-join": "A join produces [outer, inner] tuples rather than entities, and the plugin cannot report how it joined, so every option after it runs in memory.",
@@ -6669,6 +7083,80 @@ const formatStep = (step, lines)=>{
6669
7083
  return lines.join("\n");
6670
7084
  };
6671
7085
 
7086
+ // EXTERNAL MODULE: ./src/expressions/utils.ts
7087
+ var utils = __webpack_require__(63);
7088
+ ;// CONCATENATED MODULE: ./src/plugins/query/renames.ts
7089
+
7090
+
7091
+ const PROPERTY_READING_OPTIONS = [
7092
+ "filter",
7093
+ "sort",
7094
+ "nearest",
7095
+ "map",
7096
+ "group"
7097
+ ];
7098
+ const namesRenamedProperty = (expression)=>{
7099
+ let found = false;
7100
+ if (expression == null) {
7101
+ return found;
7102
+ }
7103
+ (0,utils/* .forEach */.jJ)(expression, (node)=>{
7104
+ if ((0,assertions/* .isPropertyExpression */.e3)(node) && node.property.hasRenamedSegments) {
7105
+ found = true;
7106
+ return false;
7107
+ }
7108
+ return true;
7109
+ });
7110
+ return found;
7111
+ };
7112
+ const isRenamed = (property)=>property != null && property.hasRenamedSegments;
7113
+ /**
7114
+ * Whether a selector's value is read from a renamed property, whether it is that property or computed
7115
+ * from it: `r => r.dueDate.getTime()` reads `dueDate` all the same. Every property it reads when the
7116
+ * selector was parsed, and otherwise the property recorded for it.
7117
+ */ const readsRenamedValue = (value)=>value != null && (value.reads != null ? value.reads.some(isRenamed) : isRenamed(value.property));
7118
+ const readsRenamedField = (fields)=>fields != null && fields.some(readsRenamedValue);
7119
+ const readsRenamedProperty = (name, value)=>{
7120
+ switch(name){
7121
+ case "filter":
7122
+ return namesRenamedProperty(value.expression);
7123
+ case "map":
7124
+ // A projection reads each field it selects
7125
+ return readsRenamedField(value.fields);
7126
+ case "group":
7127
+ // A group reads its key, then copies every field of the row into its members: every schema
7128
+ // property, or what a `map` before it selected
7129
+ return readsRenamedValue(value.key) || readsRenamedField(value.fields);
7130
+ default:
7131
+ return readsRenamedValue(value);
7132
+ }
7133
+ };
7134
+ /**
7135
+ * Hands back every option over a property stored under a `.from()` name, for the datastore to run
7136
+ * in memory.
7137
+ *
7138
+ * Core keeps such an option with the database, because only the plugin knows whether its backend
7139
+ * reads storage names. One that translates the option — SQL renders the column from
7140
+ * `getResolvedName()` — needs nothing from here. One that runs the caller's lambda over rows as it
7141
+ * stores them reads a key the row does not have, and answers wrongly without an error: that plugin
7142
+ * calls this before it reads anything, and the datastore finishes the query after deserialization,
7143
+ * where the in-memory names exist.
7144
+ *
7145
+ * Reported as `missing-capability`: the backend cannot express the option as written, and like
7146
+ * every capability, that is only knowable by the plugin.
7147
+ *
7148
+ * @param names Which options to check, for a plugin that resolves some of them itself — Mongo renders
7149
+ * filters and sorts through the stored path, and runs `nearest`, `map` and `group` in JavaScript.
7150
+ */ const reportRenamedProperties = (options, names = PROPERTY_READING_OPTIONS)=>{
7151
+ for (const name of names){
7152
+ for (const item of options.get(name)){
7153
+ if (readsRenamedProperty(name, item.option.value)) {
7154
+ options.reportMissingCapability(item);
7155
+ }
7156
+ }
7157
+ }
7158
+ };
7159
+
6672
7160
  ;// CONCATENATED MODULE: ./src/plugins/query/types.ts
6673
7161
  var types_QueryOrdering = /*#__PURE__*/ function(QueryOrdering) {
6674
7162
  QueryOrdering["Descending"] = "desc";
@@ -6686,6 +7174,7 @@ var types_QueryOrdering = /*#__PURE__*/ function(QueryOrdering) {
6686
7174
 
6687
7175
 
6688
7176
 
7177
+
6689
7178
  // EXTERNAL MODULE: ./src/expressions/evaluate.ts
6690
7179
  var evaluate = __webpack_require__(379);
6691
7180
  // EXTERNAL MODULE: ./src/expressions/fold.ts
@@ -6699,6 +7188,9 @@ var fold = __webpack_require__(43);
6699
7188
  * Everything except `map` and `group`. Those two are defined BY a closure — the projection is the
6700
7189
  * option — and no data form of them exists to send. Nothing else needs its closure: a sort is a
6701
7190
  * property and a direction, a filter is an expression tree, `nearest` is a vector and a count.
7191
+ *
7192
+ * Except a sort or `nearest` whose selector computes its value, such as `x => x.name.length`. It is sent
7193
+ * as the property it reads, and the receiver would order by that instead. See `isSendable`.
6702
7194
  */ const SENDABLE = new Set([
6703
7195
  "skip",
6704
7196
  "take",
@@ -6712,6 +7204,7 @@ var fold = __webpack_require__(43);
6712
7204
  "sum",
6713
7205
  "distinct"
6714
7206
  ]);
7207
+ const isSendable = (name, value)=>SENDABLE.has(name) && (name !== "sort" && name !== "nearest" || value.isDirectProperty !== false);
6715
7208
  /**
6716
7209
  * Splits options into the PREFIX that can be sent and the remainder that cannot.
6717
7210
  *
@@ -6727,7 +7220,12 @@ var fold = __webpack_require__(43);
6727
7220
  const local = new QueryOptionsCollection/* .QueryOptionsCollection */.H();
6728
7221
  let stopped = false;
6729
7222
  options.forEach((option)=>{
6730
- if (stopped === false && SENDABLE.has(option.name) === false) {
7223
+ // Reported by the plugin, so it belongs to the datastore, and so does everything after it —
7224
+ // a report cascades to the end of the database phase, which keeps what is left a prefix
7225
+ if (option.target === "database" && option.reason !== "executed") {
7226
+ return;
7227
+ }
7228
+ if (stopped === false && isSendable(option.name, option.value) === false) {
6731
7229
  stopped = true;
6732
7230
  }
6733
7231
  (stopped ? local : sendable).add(option.name, option.value);
@@ -7594,6 +8092,15 @@ class EphemeralDataPlugin {
7594
8092
  */ get databaseName() {
7595
8093
  return this._databaseName;
7596
8094
  }
8095
+ /**
8096
+ * Whether the records this plugin holds are in storage shape, keyed by `from` names.
8097
+ *
8098
+ * True for every store of what the datastore serialized, which is why a renamed property is
8099
+ * reported and records are cloned and keyed by their storage names. The datastore's change probe
8100
+ * holds rows the broadcast has already deserialized, so it reads them by in-memory names instead.
8101
+ */ get holdsStorageShape() {
8102
+ return true;
8103
+ }
7597
8104
  /**
7598
8105
  * All-or-nothing across every collection in the save.
7599
8106
  *
@@ -7801,7 +8308,9 @@ class EphemeralDataPlugin {
7801
8308
  * join discards the surplus. Same pairs either way.
7802
8309
  */ resolveJoinInnerSide(event, outerKeys, done) {
7803
8310
  const joinOption = event.operation.options.getLast("join");
7804
- if (joinOption == null) {
8311
+ // Not reached when an option before it was reported: the datastore's own join branch pairs
8312
+ // the rows this read returns.
8313
+ if (joinOption == null || joinOption.reason !== "executed") {
7805
8314
  done({
7806
8315
  ok: "success"
7807
8316
  });
@@ -7828,7 +8337,7 @@ class EphemeralDataPlugin {
7828
8337
  const innerRows = [];
7829
8338
  // Records are held in STORAGE shape, so the key is read by its resolved column name.
7830
8339
  const innerKey = joinOption.value.innerKey;
7831
- const keyColumn = innerKey.property?.getResolvedName() ?? innerKey.propertyName;
8340
+ const keyColumn = this.holdsStorageShape ? innerKey.property?.getResolvedName() ?? innerKey.propertyName : innerKey.propertyName;
7832
8341
  for (const record of innerCollection.values()){
7833
8342
  if (outerKeys != null && outerKeys.has(record[keyColumn]) === false) {
7834
8343
  continue;
@@ -7857,7 +8366,7 @@ class EphemeralDataPlugin {
7857
8366
  * to fall back to `structuredClone`, which is roughly an order of magnitude slower and was paid
7858
8367
  * on EVERY read of EVERY schema that renames a property.
7859
8368
  */ recordCloner(schema) {
7860
- const hasRenamedProperties = schema.properties.some((property)=>property.from != null);
8369
+ const hasRenamedProperties = this.holdsStorageShape && schema.properties.some((property)=>property.from != null);
7861
8370
  return hasRenamedProperties ? schema.cloneStorage : schema.clone;
7862
8371
  }
7863
8372
  query(event, done) {
@@ -7869,6 +8378,12 @@ class EphemeralDataPlugin {
7869
8378
  const schema = operation.schema;
7870
8379
  const collection = this.resolveCollection(schema);
7871
8380
  const cloneRecord = this.recordCloner(schema);
8381
+ // Records are held in storage shape and every option below runs the caller's lambda
8382
+ // over them, so a `from` property is read by a name the record does not have. Handed
8383
+ // back, and the datastore runs it after deserialization.
8384
+ if (this.holdsStorageShape) {
8385
+ reportRenamedProperties(operation.options);
8386
+ }
7872
8387
  collection.load((r)=>{
7873
8388
  if (r.ok === Result/* .Result.ERROR */.Q.ERROR) {
7874
8389
  done(Result/* .PluginEventResult.error */.D.error(event.id, r.error));
@@ -7877,7 +8392,9 @@ class EphemeralDataPlugin {
7877
8392
  const orderedOptions = [];
7878
8393
  operation.options.forEach((o)=>orderedOptions.push(o));
7879
8394
  let leadingFilterCount = 0;
7880
- while(leadingFilterCount < orderedOptions.length && orderedOptions[leadingFilterCount].name === "filter"){
8395
+ // Stops at a reported filter too: the database phase ends there, and the datastore
8396
+ // runs it and everything after it.
8397
+ while(leadingFilterCount < orderedOptions.length && orderedOptions[leadingFilterCount].name === "filter" && orderedOptions[leadingFilterCount].reason === "executed"){
7881
8398
  leadingFilterCount++;
7882
8399
  }
7883
8400
  // Key-equality fast path: when a leading filter's parsed expression pins
@@ -7955,14 +8472,14 @@ class EphemeralDataPlugin {
7955
8472
  * that was never applied.
7956
8473
  *
7957
8474
  * Before the inner side, to match execution order.
7958
- */ const described = describeFilters(operation.options.get("filter").map((entry)=>entry.option.value));
8475
+ */ const described = describeFilters(operation.options.get("filter").filter((entry)=>entry.option.reason === "executed").map((entry)=>entry.option.value));
7959
8476
  event.executedQueries.push({
7960
8477
  text: `${operation.schema.collectionName}: scanned ${cloned.length} in-memory ` + `${cloned.length === 1 ? "record" : "records"}, filter ${described.text}`,
7961
8478
  parameters: described.parameters.length > 0 ? described.parameters : undefined
7962
8479
  });
7963
8480
  const joinOption = operation.options.getLast("join");
7964
- const outerKeys = joinOption == null ? null : distinctJoinKeys(cloned, joinOption.value.outerKey, joinOption.value.semiJoinKeyThreshold, {
7965
- storageShape: true
8481
+ const outerKeys = joinOption == null || joinOption.reason !== "executed" ? null : distinctJoinKeys(cloned, joinOption.value.outerKey, joinOption.value.semiJoinKeyThreshold, {
8482
+ storageShape: this.holdsStorageShape
7966
8483
  });
7967
8484
  this.resolveJoinInnerSide(event, outerKeys, (joinResult)=>{
7968
8485
  if (joinResult.ok === "error") {
@@ -8138,7 +8655,7 @@ class TelemetryDbPlugin {
8138
8655
  *
8139
8656
  * The clone is a real date and fails `instanceof Date`, which is what a caller checks. Mutated in
8140
8657
  * place because the clone is already private to this call.
8141
- */ const reviveDates = (value)=>{
8658
+ */ const CacheDbPlugin_reviveDates = (value)=>{
8142
8659
  if (value == null || typeof value !== "object") {
8143
8660
  return value;
8144
8661
  }
@@ -8147,12 +8664,12 @@ class TelemetryDbPlugin {
8147
8664
  }
8148
8665
  if (Array.isArray(value)) {
8149
8666
  for(let i = 0, length = value.length; i < length; i++){
8150
- value[i] = reviveDates(value[i]);
8667
+ value[i] = CacheDbPlugin_reviveDates(value[i]);
8151
8668
  }
8152
8669
  return value;
8153
8670
  }
8154
8671
  for (const key of Object.keys(value)){
8155
- value[key] = reviveDates(value[key]);
8672
+ value[key] = CacheDbPlugin_reviveDates(value[key]);
8156
8673
  }
8157
8674
  return value;
8158
8675
  };
@@ -8194,7 +8711,7 @@ class CacheDbPlugin {
8194
8711
  * the next update would be written UNCHECKED with no error anywhere.
8195
8712
  * Pinned by `datastore/src/collections/wrapperStacking.test.ts`.
8196
8713
  */ rebuild(entry) {
8197
- return new entry.construct(reviveDates(structuredClone(entry.value)), entry.isTransformed);
8714
+ return new entry.construct(CacheDbPlugin_reviveDates(structuredClone(entry.value)), entry.isTransformed);
8198
8715
  }
8199
8716
  query(event, done) {
8200
8717
  const key = this.keyFor(event);
@@ -8650,6 +9167,7 @@ var __webpack_exports__nearestBy = __webpack_exports__.iG;
8650
9167
  var __webpack_exports__parameter = __webpack_exports__.Wi;
8651
9168
  var __webpack_exports__parameteriseDocument = __webpack_exports__.i1;
8652
9169
  var __webpack_exports__readJoinKey = __webpack_exports__.qy;
9170
+ var __webpack_exports__reportRenamedProperties = __webpack_exports__.wk;
8653
9171
  var __webpack_exports__semiJoinFilter = __webpack_exports__.lA;
8654
9172
  var __webpack_exports__serializeBulkPersist = __webpack_exports__.n;
8655
9173
  var __webpack_exports__serializePersistResult = __webpack_exports__.yR;
@@ -8658,6 +9176,6 @@ var __webpack_exports__splitSendableOptions = __webpack_exports__.PP;
8658
9176
  var __webpack_exports__toEntityShape = __webpack_exports__.__;
8659
9177
  var __webpack_exports__withExecutedQueries = __webpack_exports__.Kg;
8660
9178
  var __webpack_exports__withInnerSide = __webpack_exports__.oJ;
8661
- export { __webpack_exports__BatchingDbPlugin as BatchingDbPlugin, __webpack_exports__CacheDbPlugin as CacheDbPlugin, __webpack_exports__ConcurrencyDbPlugin as ConcurrencyDbPlugin, __webpack_exports__DATABASE_EXECUTION_EXPLANATIONS as DATABASE_EXECUTION_EXPLANATIONS, __webpack_exports__DEFAULT_SEMI_JOIN_KEY_THRESHOLD as DEFAULT_SEMI_JOIN_KEY_THRESHOLD, __webpack_exports__DataTranslator as DataTranslator, __webpack_exports__EXECUTED_QUERIES_UNSUPPORTED as EXECUTED_QUERIES_UNSUPPORTED, __webpack_exports__EphemeralDataPlugin as EphemeralDataPlugin, __webpack_exports__JsonTranslator as JsonTranslator, __webpack_exports__MEMORY_EXECUTION_EXPLANATIONS as MEMORY_EXECUTION_EXPLANATIONS, __webpack_exports__Query as Query, __webpack_exports__QueryOptionsCollection as QueryOptionsCollection, __webpack_exports__QueryOrdering as QueryOrdering, __webpack_exports__RetryDbPlugin as RetryDbPlugin, __webpack_exports__SqlTranslator as SqlTranslator, __webpack_exports__TelemetryDbPlugin as TelemetryDbPlugin, __webpack_exports__TranslatedArrayValue as TranslatedArrayValue, __webpack_exports__TranslatedGroupValue as TranslatedGroupValue, __webpack_exports__TranslatedSingleValue as TranslatedSingleValue, __webpack_exports__TupleTranslator as TupleTranslator, __webpack_exports__applyInnerOptions as applyInnerOptions, __webpack_exports__collectingSink as collectingSink, __webpack_exports__cosineDistance as cosineDistance, __webpack_exports__createRequestHandler as createRequestHandler, __webpack_exports__describeFilterAsJs as describeFilterAsJs, __webpack_exports__describeFilters as describeFilters, __webpack_exports__describeUnparsableFilter as describeUnparsableFilter, __webpack_exports__deserializeBulkPersist as deserializeBulkPersist, __webpack_exports__deserializePersistResult as deserializePersistResult, __webpack_exports__deserializeQueryOptions as deserializeQueryOptions, __webpack_exports__distinctJoinKeys as distinctJoinKeys, __webpack_exports__executeJoin as executeJoin, __webpack_exports__executedQueriesOf as executedQueriesOf, __webpack_exports__explainQuery as explainQuery, __webpack_exports__formatExplanation as formatExplanation, __webpack_exports__hashJoin as hashJoin, __webpack_exports__isDatabaseStep as isDatabaseStep, __webpack_exports__joinInPlugin as joinInPlugin, __webpack_exports__loadJoinInnerSide as loadJoinInnerSide, __webpack_exports__loggerSink as loggerSink, __webpack_exports__mappedResultColumns as mappedResultColumns, __webpack_exports__nearestBy as nearestBy, __webpack_exports__parameter as parameter, __webpack_exports__parameteriseDocument as parameteriseDocument, __webpack_exports__readJoinKey as readJoinKey, __webpack_exports__semiJoinFilter as semiJoinFilter, __webpack_exports__serializeBulkPersist as serializeBulkPersist, __webpack_exports__serializePersistResult as serializePersistResult, __webpack_exports__serializeQueryOptions as serializeQueryOptions, __webpack_exports__splitSendableOptions as splitSendableOptions, __webpack_exports__toEntityShape as toEntityShape, __webpack_exports__withExecutedQueries as withExecutedQueries, __webpack_exports__withInnerSide as withInnerSide };
9179
+ export { __webpack_exports__BatchingDbPlugin as BatchingDbPlugin, __webpack_exports__CacheDbPlugin as CacheDbPlugin, __webpack_exports__ConcurrencyDbPlugin as ConcurrencyDbPlugin, __webpack_exports__DATABASE_EXECUTION_EXPLANATIONS as DATABASE_EXECUTION_EXPLANATIONS, __webpack_exports__DEFAULT_SEMI_JOIN_KEY_THRESHOLD as DEFAULT_SEMI_JOIN_KEY_THRESHOLD, __webpack_exports__DataTranslator as DataTranslator, __webpack_exports__EXECUTED_QUERIES_UNSUPPORTED as EXECUTED_QUERIES_UNSUPPORTED, __webpack_exports__EphemeralDataPlugin as EphemeralDataPlugin, __webpack_exports__JsonTranslator as JsonTranslator, __webpack_exports__MEMORY_EXECUTION_EXPLANATIONS as MEMORY_EXECUTION_EXPLANATIONS, __webpack_exports__Query as Query, __webpack_exports__QueryOptionsCollection as QueryOptionsCollection, __webpack_exports__QueryOrdering as QueryOrdering, __webpack_exports__RetryDbPlugin as RetryDbPlugin, __webpack_exports__SqlTranslator as SqlTranslator, __webpack_exports__TelemetryDbPlugin as TelemetryDbPlugin, __webpack_exports__TranslatedArrayValue as TranslatedArrayValue, __webpack_exports__TranslatedGroupValue as TranslatedGroupValue, __webpack_exports__TranslatedSingleValue as TranslatedSingleValue, __webpack_exports__TupleTranslator as TupleTranslator, __webpack_exports__applyInnerOptions as applyInnerOptions, __webpack_exports__collectingSink as collectingSink, __webpack_exports__cosineDistance as cosineDistance, __webpack_exports__createRequestHandler as createRequestHandler, __webpack_exports__describeFilterAsJs as describeFilterAsJs, __webpack_exports__describeFilters as describeFilters, __webpack_exports__describeUnparsableFilter as describeUnparsableFilter, __webpack_exports__deserializeBulkPersist as deserializeBulkPersist, __webpack_exports__deserializePersistResult as deserializePersistResult, __webpack_exports__deserializeQueryOptions as deserializeQueryOptions, __webpack_exports__distinctJoinKeys as distinctJoinKeys, __webpack_exports__executeJoin as executeJoin, __webpack_exports__executedQueriesOf as executedQueriesOf, __webpack_exports__explainQuery as explainQuery, __webpack_exports__formatExplanation as formatExplanation, __webpack_exports__hashJoin as hashJoin, __webpack_exports__isDatabaseStep as isDatabaseStep, __webpack_exports__joinInPlugin as joinInPlugin, __webpack_exports__loadJoinInnerSide as loadJoinInnerSide, __webpack_exports__loggerSink as loggerSink, __webpack_exports__mappedResultColumns as mappedResultColumns, __webpack_exports__nearestBy as nearestBy, __webpack_exports__parameter as parameter, __webpack_exports__parameteriseDocument as parameteriseDocument, __webpack_exports__readJoinKey as readJoinKey, __webpack_exports__reportRenamedProperties as reportRenamedProperties, __webpack_exports__semiJoinFilter as semiJoinFilter, __webpack_exports__serializeBulkPersist as serializeBulkPersist, __webpack_exports__serializePersistResult as serializePersistResult, __webpack_exports__serializeQueryOptions as serializeQueryOptions, __webpack_exports__splitSendableOptions as splitSendableOptions, __webpack_exports__toEntityShape as toEntityShape, __webpack_exports__withExecutedQueries as withExecutedQueries, __webpack_exports__withInnerSide as withInnerSide };
8662
9180
 
8663
9181
  //# sourceMappingURL=index.js.map