@routier/core 0.6.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.
- package/dist/assertions/index.cjs +19 -8
- package/dist/assertions/index.cjs.map +1 -1
- package/dist/assertions/index.d.ts +5 -1
- package/dist/assertions/index.js +21 -9
- package/dist/assertions/index.js.map +1 -1
- package/dist/codegen/blocks.d.ts +17 -1
- package/dist/codegen/handlers/types.d.ts +13 -5
- package/dist/codegen/index.cjs +28 -0
- package/dist/codegen/index.cjs.map +1 -1
- package/dist/codegen/index.js +28 -0
- package/dist/codegen/index.js.map +1 -1
- package/dist/collections/MemoryDataCollection.d.ts +8 -0
- package/dist/collections/index.cjs +141 -4
- package/dist/collections/index.cjs.map +1 -1
- package/dist/collections/index.js +141 -4
- package/dist/collections/index.js.map +1 -1
- package/dist/expressions/callSource.d.ts +41 -0
- package/dist/expressions/evaluate.d.ts +3 -0
- package/dist/expressions/fold.d.ts +7 -0
- package/dist/expressions/index.cjs +1985 -242
- package/dist/expressions/index.cjs.map +1 -1
- package/dist/expressions/index.d.ts +2 -0
- package/dist/expressions/index.js +1997 -243
- package/dist/expressions/index.js.map +1 -1
- package/dist/expressions/parser.d.ts +42 -1
- package/dist/expressions/types.d.ts +45 -26
- package/dist/expressions/utils.d.ts +19 -1
- package/dist/index.cjs +3139 -680
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3479 -997
- package/dist/index.js.map +1 -1
- package/dist/performance/index.cjs +6 -4
- package/dist/performance/index.cjs.map +1 -1
- package/dist/performance/index.js +6 -4
- package/dist/performance/index.js.map +1 -1
- package/dist/pipeline/index.cjs +6 -4
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.js +6 -4
- package/dist/pipeline/index.js.map +1 -1
- package/dist/plugins/EphemeralDataPlugin.d.ts +8 -0
- package/dist/plugins/index.cjs +2921 -411
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.js +2863 -343
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/query/QueryOptionsCollection.d.ts +48 -10
- package/dist/plugins/query/describeFilter.d.ts +83 -0
- package/dist/plugins/query/explain.d.ts +71 -9
- package/dist/plugins/query/index.d.ts +2 -0
- package/dist/plugins/query/join.d.ts +4 -1
- package/dist/plugins/query/renames.d.ts +27 -0
- package/dist/plugins/query/types.d.ts +50 -4
- package/dist/plugins/translators/SqlTranslator.d.ts +15 -0
- package/dist/schema/PropertyInfo.d.ts +0 -1
- package/dist/schema/SchemaDefinition.d.ts +8 -0
- package/dist/schema/changeTracker.d.ts +10 -0
- package/dist/schema/index.cjs +298 -288
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +301 -290
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/types.d.ts +8 -7
- package/dist/schema/utils/storageDates.d.ts +25 -0
- package/dist/transfer/index.cjs.map +1 -1
- package/dist/transfer/index.js.map +1 -1
- package/dist/utilities/index.cjs +306 -68
- package/dist/utilities/index.cjs.map +1 -1
- package/dist/utilities/index.js +306 -68
- package/dist/utilities/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/codegen/utils.d.ts +0 -22
package/dist/schema/index.cjs
CHANGED
|
@@ -346,6 +346,14 @@ class FunctionFactoryBuilder extends ContainerBlock {
|
|
|
346
346
|
this._params.push(...params);
|
|
347
347
|
return this;
|
|
348
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* Adds a factory parameter carrying `value` and returns its name, for generated code to
|
|
351
|
+
* refer to. See `CodeBuilder.bind` for why values travel this way.
|
|
352
|
+
*/ bind(value) {
|
|
353
|
+
const parameter = this.createParameter(value);
|
|
354
|
+
this._params.push(parameter);
|
|
355
|
+
return parameter.name;
|
|
356
|
+
}
|
|
349
357
|
return() {
|
|
350
358
|
this._return = true;
|
|
351
359
|
return this;
|
|
@@ -461,6 +469,26 @@ class IfBuilder extends ContainerBlock {
|
|
|
461
469
|
}
|
|
462
470
|
}
|
|
463
471
|
class CodeBuilder extends ContainerBlock {
|
|
472
|
+
_bindings = [];
|
|
473
|
+
/**
|
|
474
|
+
* Makes `value` available to the generated function under the returned name.
|
|
475
|
+
*
|
|
476
|
+
* Generated code must never reach a runtime value by its source name or by pasting its
|
|
477
|
+
* source text: a minifier renames the declaration and cannot see inside the generated
|
|
478
|
+
* string, and pasted source loses the scope it closed over (#40, #46). A binding is passed
|
|
479
|
+
* in as a real value when the function is compiled, so it survives any bundler.
|
|
480
|
+
*/ bind(value, name = `binding${this._bindings.length}`) {
|
|
481
|
+
this._bindings.push({
|
|
482
|
+
name,
|
|
483
|
+
value
|
|
484
|
+
});
|
|
485
|
+
return name;
|
|
486
|
+
}
|
|
487
|
+
getBindings() {
|
|
488
|
+
return [
|
|
489
|
+
...this._bindings
|
|
490
|
+
];
|
|
491
|
+
}
|
|
464
492
|
toString() {
|
|
465
493
|
return this._lines.map((line)=>typeof line === 'string' ? this.indent(line) : line.toString()).join('\n\n');
|
|
466
494
|
}
|
|
@@ -543,6 +571,129 @@ var HashType = /*#__PURE__*/ function(HashType) {
|
|
|
543
571
|
}({});
|
|
544
572
|
|
|
545
573
|
|
|
574
|
+
},
|
|
575
|
+
575(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
576
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
577
|
+
L: () => (hasPrimitiveElements),
|
|
578
|
+
l: () => (isArrayValued)
|
|
579
|
+
});
|
|
580
|
+
/* import */ var _types__rspack_import_0 = __webpack_require__(537);
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Types whose runtime value is a JS array.
|
|
584
|
+
*
|
|
585
|
+
* `Array` and `Vector` are the same thing to every layer that copies, compares, hashes or
|
|
586
|
+
* freezes a value — a vector is a list of numbers and nothing more. They differ only where a
|
|
587
|
+
* backend chooses storage, which is the one place that should ask for `SchemaTypes.Vector` by
|
|
588
|
+
* name.
|
|
589
|
+
*
|
|
590
|
+
* This exists so adding a third array-shaped type is one edit rather than a hunt through
|
|
591
|
+
* twelve handlers. Missing one of those is silent in the worst way: a vector that clones by
|
|
592
|
+
* reference is shared with the change tracker's copy, so overwriting an embedding produces no
|
|
593
|
+
* diff and the save reports nothing to do.
|
|
594
|
+
*/ const ARRAY_VALUED_TYPES = new Set([
|
|
595
|
+
_types__rspack_import_0/* .SchemaTypes.Array */.L.Array,
|
|
596
|
+
_types__rspack_import_0/* .SchemaTypes.Vector */.L.Vector
|
|
597
|
+
]);
|
|
598
|
+
/** 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);
|
|
599
|
+
/**
|
|
600
|
+
* True when the property's elements are primitives, so a spread is a sufficient copy.
|
|
601
|
+
*
|
|
602
|
+
* A vector is always numbers, so it never needs the per-element deep copy an array of objects
|
|
603
|
+
* or dates does.
|
|
604
|
+
*/ const PRIMITIVE_ELEMENT_TYPES = new Set([
|
|
605
|
+
_types__rspack_import_0/* .SchemaTypes.String */.L.String,
|
|
606
|
+
_types__rspack_import_0/* .SchemaTypes.Number */.L.Number,
|
|
607
|
+
_types__rspack_import_0/* .SchemaTypes.Boolean */.L.Boolean
|
|
608
|
+
]);
|
|
609
|
+
const hasPrimitiveElements = (type, elementType)=>type === _types__rspack_import_0/* .SchemaTypes.Vector */.L.Vector || PRIMITIVE_ELEMENT_TYPES.has(elementType);
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
},
|
|
613
|
+
894(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
614
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
615
|
+
T: () => (getStorageDateReviver)
|
|
616
|
+
});
|
|
617
|
+
/* import */ var _types__rspack_import_0 = __webpack_require__(537);
|
|
618
|
+
/* import */ var _propertyKind__rspack_import_1 = __webpack_require__(575);
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
const collectDatePaths = (properties, paths)=>{
|
|
622
|
+
for (const property of properties){
|
|
623
|
+
// The stored value belongs to whoever wrote it: a custom serializer, deserializer or
|
|
624
|
+
// transform reads it back, and would be handed a Date it did not expect. Unmapped
|
|
625
|
+
// properties are never stored.
|
|
626
|
+
if (property.valueSerializer != null || property.valueDeserializer != null || property.transform != null || property.isUnmapped) {
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
if (property.type === _types__rspack_import_0/* .SchemaTypes.Object */.L.Object) {
|
|
630
|
+
collectDatePaths(property.children, paths);
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
const isArray = (0,_propertyKind__rspack_import_1/* .isArrayValued */.l)(property.type) && property.innerSchema?.type === _types__rspack_import_0/* .SchemaTypes.Date */.L.Date;
|
|
634
|
+
if (property.type !== _types__rspack_import_0/* .SchemaTypes.Date */.L.Date && isArray === false) {
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
637
|
+
paths.push({
|
|
638
|
+
segments: [
|
|
639
|
+
...property.getParentPathArray({
|
|
640
|
+
useFromPropertyName: true
|
|
641
|
+
}),
|
|
642
|
+
property.getResolvedName()
|
|
643
|
+
],
|
|
644
|
+
isArray
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
const reviveAt = (record, path)=>{
|
|
649
|
+
const { segments } = path;
|
|
650
|
+
let parent = record;
|
|
651
|
+
for(let i = 0, length = segments.length - 1; i < length; i++){
|
|
652
|
+
parent = parent[segments[i]];
|
|
653
|
+
// An absent or null parent holds no date
|
|
654
|
+
if (parent == null || typeof parent !== "object") {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
const key = segments[segments.length - 1];
|
|
659
|
+
const value = parent[key];
|
|
660
|
+
if (path.isArray === false) {
|
|
661
|
+
if (typeof value === "string") {
|
|
662
|
+
parent[key] = new Date(value);
|
|
663
|
+
}
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
if (Array.isArray(value)) {
|
|
667
|
+
for(let i = 0, length = value.length; i < length; i++){
|
|
668
|
+
if (typeof value[i] === "string") {
|
|
669
|
+
value[i] = new Date(value[i]);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
/** Per schema: `null` for a schema with no dates, so a caller can skip the pass. */ const revivers = new WeakMap();
|
|
675
|
+
/**
|
|
676
|
+
* The reviver for `schema`'s records, or `null` when it declares no dates.
|
|
677
|
+
*
|
|
678
|
+
* Built once per compiled schema. A read revives every row it returns, so the paths are resolved
|
|
679
|
+
* here rather than per row.
|
|
680
|
+
*/ const getStorageDateReviver = (schema)=>{
|
|
681
|
+
const cached = revivers.get(schema);
|
|
682
|
+
if (cached !== undefined) {
|
|
683
|
+
return cached;
|
|
684
|
+
}
|
|
685
|
+
const paths = [];
|
|
686
|
+
collectDatePaths(schema.properties, paths);
|
|
687
|
+
const reviver = paths.length === 0 ? null : (record)=>{
|
|
688
|
+
for(let i = 0, length = paths.length; i < length; i++){
|
|
689
|
+
reviveAt(record, paths[i]);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
revivers.set(schema, reviver);
|
|
693
|
+
return reviver;
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
|
|
546
697
|
},
|
|
547
698
|
581(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
548
699
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -618,12 +769,14 @@ const isLogLevel = (value)=>typeof value === 'string' && LOG_LEVELS.includes(val
|
|
|
618
769
|
const debug = process.env.DEBUG;
|
|
619
770
|
if (debug === 'routier' || debug === '*') return 'debug';
|
|
620
771
|
const env = "production"?.toLowerCase();
|
|
621
|
-
// `test` is deliberately absent. It used to be here, which meant no test suite anywhere
|
|
622
|
-
// could run Routier quietly. Opt in with DEBUG=routier or ROUTIER_LOG_LEVEL when a test
|
|
623
|
-
// needs the output.
|
|
624
772
|
if (env === 'dev' || env === 'development') return 'debug';
|
|
625
773
|
}
|
|
626
|
-
|
|
774
|
+
// Warnings are on unless something turns them off.
|
|
775
|
+
//
|
|
776
|
+
// Routier warns when a query returns correct rows a slower way than it could, or when a filter
|
|
777
|
+
// compares types that can never match. Both are the caller's to act on, and a default of
|
|
778
|
+
// `silent` meant the only people who ever saw them were the ones who already knew to look.
|
|
779
|
+
return 'warn';
|
|
627
780
|
};
|
|
628
781
|
let level = resolveLevel();
|
|
629
782
|
let rank = RANK[level];
|
|
@@ -935,6 +1088,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
935
1088
|
SchemaTransform: () => (/* reexport */ SchemaTransform),
|
|
936
1089
|
SchemaComputed: () => (/* reexport */ SchemaComputed),
|
|
937
1090
|
extractTypeInfo: () => (/* reexport */ extractTypeInfo),
|
|
1091
|
+
getStorageDateReviver: () => (/* reexport */ storageDates/* .getStorageDateReviver */.T),
|
|
938
1092
|
SchemaTracked: () => (/* reexport */ SchemaTracked),
|
|
939
1093
|
SchemaFile: () => (/* reexport */ SchemaFile),
|
|
940
1094
|
SchemaNumber: () => (/* reexport */ SchemaNumber),
|
|
@@ -951,12 +1105,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
951
1105
|
SchemaArray: () => (/* reexport */ SchemaArray),
|
|
952
1106
|
SchemaKey: () => (/* reexport */ SchemaKey),
|
|
953
1107
|
SchemaOptional: () => (/* reexport */ SchemaOptional),
|
|
954
|
-
hasPrimitiveElements: () => (/* reexport */ hasPrimitiveElements),
|
|
1108
|
+
hasPrimitiveElements: () => (/* reexport */ propertyKind/* .hasPrimitiveElements */.L),
|
|
955
1109
|
SchemaDefault: () => (/* reexport */ SchemaDefault),
|
|
956
1110
|
SchemaIndex: () => (/* reexport */ SchemaIndex),
|
|
957
1111
|
SchemaVector: () => (/* reexport */ SchemaVector),
|
|
958
1112
|
HashType: () => (/* reexport */ types/* .HashType */.$),
|
|
959
|
-
isArrayValued: () => (/* reexport */ isArrayValued),
|
|
1113
|
+
isArrayValued: () => (/* reexport */ propertyKind/* .isArrayValued */.l),
|
|
960
1114
|
SchemaBase: () => (/* reexport */ SchemaBase),
|
|
961
1115
|
createStandardJsonSchemaProps: () => (/* reexport */ createStandardJsonSchemaProps),
|
|
962
1116
|
propertyInfoToJsonSchema: () => (/* reexport */ propertyInfoToJsonSchema),
|
|
@@ -1779,12 +1933,6 @@ class SchemaComputed extends SchemaBase {
|
|
|
1779
1933
|
;// CONCATENATED MODULE: ./src/schema/PropertyInfo.ts
|
|
1780
1934
|
|
|
1781
1935
|
|
|
1782
|
-
const SUPPORTED_DESERIALIZATION_TYPES = new Set([
|
|
1783
|
-
types/* .SchemaTypes.Boolean */.L.Boolean,
|
|
1784
|
-
types/* .SchemaTypes.Date */.L.Date,
|
|
1785
|
-
types/* .SchemaTypes.Number */.L.Number,
|
|
1786
|
-
types/* .SchemaTypes.String */.L.String
|
|
1787
|
-
]);
|
|
1788
1936
|
/**
|
|
1789
1937
|
* Represents metadata and utilities for a property in a schema, including its type, name, parent, children, and serialization details.
|
|
1790
1938
|
*/ class PropertyInfo {
|
|
@@ -1904,9 +2052,6 @@ const SUPPORTED_DESERIALIZATION_TYPES = new Set([
|
|
|
1904
2052
|
get isRenamed() {
|
|
1905
2053
|
return !!this.from;
|
|
1906
2054
|
}
|
|
1907
|
-
get supportsDeserialization() {
|
|
1908
|
-
return this.valueDeserializer != null || SUPPORTED_DESERIALIZATION_TYPES.has(this.type);
|
|
1909
|
-
}
|
|
1910
2055
|
_getPropertyChain() {
|
|
1911
2056
|
if (this._propertyChainCache) {
|
|
1912
2057
|
return this._propertyChainCache;
|
|
@@ -2159,7 +2304,7 @@ const SUPPORTED_DESERIALIZATION_TYPES = new Set([
|
|
|
2159
2304
|
if (this.type === types/* .SchemaTypes.Boolean */.L.Boolean) {
|
|
2160
2305
|
return Boolean(value);
|
|
2161
2306
|
}
|
|
2162
|
-
|
|
2307
|
+
return value;
|
|
2163
2308
|
}
|
|
2164
2309
|
}
|
|
2165
2310
|
|
|
@@ -2186,78 +2331,9 @@ class SlotPath {
|
|
|
2186
2331
|
|
|
2187
2332
|
// EXTERNAL MODULE: ./src/errors/SchemaError.ts
|
|
2188
2333
|
var SchemaError = __webpack_require__(131);
|
|
2189
|
-
;// CONCATENATED MODULE: ./src/codegen/utils.ts
|
|
2190
|
-
/**
|
|
2191
|
-
* Counts non-overlapping occurrences of a term in text.
|
|
2192
|
-
*
|
|
2193
|
-
* Behavior:
|
|
2194
|
-
* - Case-sensitive matching
|
|
2195
|
-
* - If the search term is composed entirely of word characters (A–Z, a–z, 0–9, _),
|
|
2196
|
-
* enforce whole-word boundaries so "red" does not match inside "redder".
|
|
2197
|
-
* - If the search term contains any non-word character (e.g. "=>", "()", "::"),
|
|
2198
|
-
* match anywhere without boundary checks (useful for symbols).
|
|
2199
|
-
* - Non-overlapping matches (after a hit, advances by term length)
|
|
2200
|
-
* - Optimized single-character fast path; otherwise uses indexOf loop
|
|
2201
|
-
*
|
|
2202
|
-
* Examples:
|
|
2203
|
-
* - countWordOccurance("red redder red", "red") => 2
|
|
2204
|
-
* - countWordOccurance("()=>{}", "=>") => 1
|
|
2205
|
-
* - countWordOccurance("aaaa", "aa") => 2 (non-overlapping)
|
|
2206
|
-
*
|
|
2207
|
-
* @param text The source text to scan
|
|
2208
|
-
* @param word The term to match (must be non-empty)
|
|
2209
|
-
* @returns The number of occurrences found
|
|
2210
|
-
*/ const countWordOccurance = (text, word)=>{
|
|
2211
|
-
const wl = word.length;
|
|
2212
|
-
const tl = text.length;
|
|
2213
|
-
if (wl === 0 || wl > tl) return 0;
|
|
2214
|
-
// Fast path for single-character words
|
|
2215
|
-
if (wl === 1) {
|
|
2216
|
-
let c = 0;
|
|
2217
|
-
const code = word.charCodeAt(0);
|
|
2218
|
-
for(let i = 0; i < tl; i++)if (text.charCodeAt(i) === code) c++;
|
|
2219
|
-
return c;
|
|
2220
|
-
}
|
|
2221
|
-
let count = 0;
|
|
2222
|
-
let i = 0;
|
|
2223
|
-
function isWordCharCode(c) {
|
|
2224
|
-
return c >= 48 && c <= 57 // 0-9
|
|
2225
|
-
|| c >= 65 && c <= 90 // A-Z
|
|
2226
|
-
|| c >= 97 && c <= 122 // a-z
|
|
2227
|
-
|| c === 95; // _
|
|
2228
|
-
}
|
|
2229
|
-
// Decide whether to enforce word boundaries based on the search term
|
|
2230
|
-
let enforceWordBoundaries = true;
|
|
2231
|
-
for(let k = 0; k < wl; k++){
|
|
2232
|
-
const cc = word.charCodeAt(k);
|
|
2233
|
-
if (!isWordCharCode(cc)) {
|
|
2234
|
-
enforceWordBoundaries = false;
|
|
2235
|
-
break;
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
while(true){
|
|
2239
|
-
i = text.indexOf(word, i);
|
|
2240
|
-
if (i === -1) break;
|
|
2241
|
-
if (enforceWordBoundaries) {
|
|
2242
|
-
const left = i - 1;
|
|
2243
|
-
const right = i + wl;
|
|
2244
|
-
const leftOk = left < 0 || !isWordCharCode(text.charCodeAt(left));
|
|
2245
|
-
const rightOk = right >= tl || !isWordCharCode(text.charCodeAt(right));
|
|
2246
|
-
if (leftOk && rightOk) count++;
|
|
2247
|
-
} else {
|
|
2248
|
-
// No boundary enforcement for symbol-containing terms
|
|
2249
|
-
count++;
|
|
2250
|
-
}
|
|
2251
|
-
i += wl; // non-overlapping word matches
|
|
2252
|
-
}
|
|
2253
|
-
return count;
|
|
2254
|
-
};
|
|
2255
|
-
|
|
2256
2334
|
;// CONCATENATED MODULE: ./src/codegen/handlers/types.ts
|
|
2257
2335
|
|
|
2258
2336
|
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
2337
|
/**
|
|
2262
2338
|
* Terminal link for chains that apply only to a subset of properties (keys,
|
|
2263
2339
|
* identities). Returning the builder marks every other property as
|
|
@@ -2433,34 +2509,16 @@ class PropertyInfoHandler {
|
|
|
2433
2509
|
}
|
|
2434
2510
|
enriched.property(`${property.name}: ${entitySelectorPath}`);
|
|
2435
2511
|
}
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
const index = stringifiedFunction.indexOf("=>");
|
|
2447
|
-
body = stringifiedFunction.slice(index + 2, stringifiedFunction.length);
|
|
2448
|
-
}
|
|
2449
|
-
if (body.startsWith("{") === true && body.endsWith("}")) {
|
|
2450
|
-
// Remove brackets, wrapping function will have them
|
|
2451
|
-
builder.appendBody(body.slice(1, body.length - 1));
|
|
2452
|
-
return {
|
|
2453
|
-
builder,
|
|
2454
|
-
parameters
|
|
2455
|
-
};
|
|
2456
|
-
}
|
|
2457
|
-
builder.appendBody(`return ${body};`);
|
|
2458
|
-
return {
|
|
2459
|
-
builder,
|
|
2460
|
-
parameters
|
|
2461
|
-
};
|
|
2462
|
-
}
|
|
2463
|
-
throw new Error("Only arrow functions are allowed in the schema definition: function () {} ---> () => {}");
|
|
2512
|
+
/**
|
|
2513
|
+
* Binds a function the schema author supplied (a default, a computed, a serializer) into
|
|
2514
|
+
* the generated code and returns the expression that calls it with `args`.
|
|
2515
|
+
*
|
|
2516
|
+
* The function is passed in by value rather than pasted in as source text. Pasted source
|
|
2517
|
+
* loses the scope it was written in, so a default that called an imported helper threw, and
|
|
2518
|
+
* it had to be parsed back apart, which only worked for arrows: a bundler that lowers arrows
|
|
2519
|
+
* to `function` expressions, or renames what they refer to, broke every schema (#46).
|
|
2520
|
+
*/ emitBoundCall(target, fn, args) {
|
|
2521
|
+
return `${target.bind(fn)}(${args.join(", ")})`;
|
|
2464
2522
|
}
|
|
2465
2523
|
}
|
|
2466
2524
|
|
|
@@ -2620,28 +2678,21 @@ class EnrichmentPrimitiveHandler extends PropertyInfoHandler {
|
|
|
2620
2678
|
class EnrichmentFunctionHandler extends PropertyInfoHandler {
|
|
2621
2679
|
handle(property, builder) {
|
|
2622
2680
|
if (property.functionBody != null && property.type === types/* .SchemaTypes.Function */.L.Function) {
|
|
2623
|
-
const
|
|
2681
|
+
const factory = builder.get("factory");
|
|
2682
|
+
const args = [
|
|
2624
2683
|
"enriched",
|
|
2625
2684
|
"collectionName"
|
|
2626
2685
|
];
|
|
2627
2686
|
if (property.injected != null) {
|
|
2628
|
-
|
|
2629
|
-
const parameter = factory.createParameter(property.injected);
|
|
2630
|
-
factory.parameters(parameter);
|
|
2631
|
-
parameterNames.push(parameter.name);
|
|
2687
|
+
args.push(factory.bind(property.injected));
|
|
2632
2688
|
}
|
|
2633
|
-
const declarationsSlot = builder.get("factory.function.declarations");
|
|
2634
|
-
// Unwrap the functions to removing currying
|
|
2635
|
-
const defaultFunctionWithParameters = this.toNamedFunction(property.functionBody.toString(), declarationsSlot);
|
|
2636
|
-
defaultFunctionWithParameters.builder.parameters(...parameterNames.map((w, i)=>({
|
|
2637
|
-
name: defaultFunctionWithParameters.parameters[i],
|
|
2638
|
-
callName: w
|
|
2639
|
-
})));
|
|
2640
2689
|
const slot = builder.get("factory.function.assignment");
|
|
2641
2690
|
const enrichedAssignmentPath = property.getAssignmentPath({
|
|
2642
2691
|
parent: "enriched"
|
|
2643
2692
|
});
|
|
2644
|
-
|
|
2693
|
+
// The definition is curried: calling it with the entity returns the function the
|
|
2694
|
+
// property holds
|
|
2695
|
+
slot.assign(enrichedAssignmentPath).value(this.emitBoundCall(factory, property.functionBody, args));
|
|
2645
2696
|
return builder;
|
|
2646
2697
|
}
|
|
2647
2698
|
return super.handle(property, builder);
|
|
@@ -2696,34 +2747,17 @@ class EnrichmentDefaultFunctionHandler extends PropertyInfoHandler {
|
|
|
2696
2747
|
handle(property, builder) {
|
|
2697
2748
|
if (property.defaultValue != null && typeof property.defaultValue === "function") {
|
|
2698
2749
|
this.setEnrichedProperty(property, builder);
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
}
|
|
2706
|
-
const parameter = factory.createParameter(property.injected);
|
|
2707
|
-
factory.parameters(parameter);
|
|
2708
|
-
const defaultFunctionWithParameters = this.toNamedFunction(property.defaultValue.toString(), declarationsSlot);
|
|
2709
|
-
// This is ok, defaults can only inject one parameter anyways
|
|
2710
|
-
defaultFunctionWithParameters.builder.parameters(...defaultFunctionWithParameters.parameters.map((w)=>({
|
|
2711
|
-
name: w,
|
|
2712
|
-
callName: parameter.name
|
|
2713
|
-
})));
|
|
2714
|
-
const ifsSlot = builder.get("factory.function.ifs");
|
|
2715
|
-
const enrichedAssignmentPath = property.getAssignmentPath({
|
|
2716
|
-
parent: "enriched"
|
|
2717
|
-
});
|
|
2718
|
-
ifsSlot.if(`${enrichedAssignmentPath} == null`).appendBody(`${enrichedAssignmentPath} = ${defaultFunctionWithParameters.builder.toCallable()}`);
|
|
2719
|
-
return builder;
|
|
2720
|
-
}
|
|
2721
|
-
const defaultFunction = this.toNamedFunction(property.defaultValue.toString(), declarationsSlot);
|
|
2750
|
+
const factory = builder.get("factory");
|
|
2751
|
+
// Defaults take at most one argument: the injected value, when there is one
|
|
2752
|
+
const args = property.injected != null ? [
|
|
2753
|
+
factory.bind(property.injected)
|
|
2754
|
+
] : [];
|
|
2755
|
+
const call = this.emitBoundCall(factory, property.defaultValue, args);
|
|
2722
2756
|
const ifsSlot = builder.get("factory.function.ifs");
|
|
2723
2757
|
const enrichedAssignmentPath = property.getAssignmentPath({
|
|
2724
2758
|
parent: "enriched"
|
|
2725
2759
|
});
|
|
2726
|
-
ifsSlot.if(`${enrichedAssignmentPath} == null`).appendBody(`${enrichedAssignmentPath} = ${
|
|
2760
|
+
ifsSlot.if(`${enrichedAssignmentPath} == null`).appendBody(`${enrichedAssignmentPath} = ${call}`);
|
|
2727
2761
|
return builder;
|
|
2728
2762
|
}
|
|
2729
2763
|
return super.handle(property, builder);
|
|
@@ -2736,22 +2770,15 @@ class EnrichmentDefaultFunctionHandler extends PropertyInfoHandler {
|
|
|
2736
2770
|
class EnrichmentComputedValueHandler extends PropertyInfoHandler {
|
|
2737
2771
|
handle(property, builder) {
|
|
2738
2772
|
if (property.functionBody != null && property.type === types/* .SchemaTypes.Computed */.L.Computed) {
|
|
2739
|
-
const
|
|
2773
|
+
const factory = builder.get("factory");
|
|
2774
|
+
const args = [
|
|
2740
2775
|
"enriched",
|
|
2741
2776
|
"collectionName"
|
|
2742
2777
|
];
|
|
2743
2778
|
if (property.injected != null) {
|
|
2744
|
-
|
|
2745
|
-
const parameter = factory.createParameter(property.injected);
|
|
2746
|
-
factory.parameters(parameter);
|
|
2747
|
-
parameterNames.push(parameter.name);
|
|
2779
|
+
args.push(factory.bind(property.injected));
|
|
2748
2780
|
}
|
|
2749
|
-
const
|
|
2750
|
-
const defaultFunctionWithParameters = this.toNamedFunction(property.functionBody.toString(), declarationsSlot);
|
|
2751
|
-
defaultFunctionWithParameters.builder.parameters(...parameterNames.map((w, i)=>({
|
|
2752
|
-
name: defaultFunctionWithParameters.parameters[i],
|
|
2753
|
-
callName: w
|
|
2754
|
-
})));
|
|
2781
|
+
const call = this.emitBoundCall(factory, property.functionBody, args);
|
|
2755
2782
|
// Compute-once semantics for computed keys/identities: an existing value is
|
|
2756
2783
|
// carried into the enriched literal and never recomputed — a key must stay
|
|
2757
2784
|
// stable once assigned (content-hash ids would otherwise churn as the
|
|
@@ -2764,44 +2791,15 @@ class EnrichmentComputedValueHandler extends PropertyInfoHandler {
|
|
|
2764
2791
|
const enrichedAssignmentPath = property.getAssignmentPath({
|
|
2765
2792
|
parent: "enriched"
|
|
2766
2793
|
});
|
|
2767
|
-
ifsSlot.if(`${enrichedAssignmentPath} == null`).appendBody(`${enrichedAssignmentPath} = ${
|
|
2794
|
+
ifsSlot.if(`${enrichedAssignmentPath} == null`).appendBody(`${enrichedAssignmentPath} = ${call}`);
|
|
2768
2795
|
return builder;
|
|
2769
2796
|
}
|
|
2770
2797
|
return super.handle(property, builder);
|
|
2771
2798
|
}
|
|
2772
2799
|
}
|
|
2773
2800
|
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
/**
|
|
2777
|
-
* Types whose runtime value is a JS array.
|
|
2778
|
-
*
|
|
2779
|
-
* `Array` and `Vector` are the same thing to every layer that copies, compares, hashes or
|
|
2780
|
-
* freezes a value — a vector is a list of numbers and nothing more. They differ only where a
|
|
2781
|
-
* backend chooses storage, which is the one place that should ask for `SchemaTypes.Vector` by
|
|
2782
|
-
* name.
|
|
2783
|
-
*
|
|
2784
|
-
* This exists so adding a third array-shaped type is one edit rather than a hunt through
|
|
2785
|
-
* twelve handlers. Missing one of those is silent in the worst way: a vector that clones by
|
|
2786
|
-
* reference is shared with the change tracker's copy, so overwriting an embedding produces no
|
|
2787
|
-
* diff and the save reports nothing to do.
|
|
2788
|
-
*/ const ARRAY_VALUED_TYPES = new Set([
|
|
2789
|
-
types/* .SchemaTypes.Array */.L.Array,
|
|
2790
|
-
types/* .SchemaTypes.Vector */.L.Vector
|
|
2791
|
-
]);
|
|
2792
|
-
/** 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);
|
|
2793
|
-
/**
|
|
2794
|
-
* True when the property's elements are primitives, so a spread is a sufficient copy.
|
|
2795
|
-
*
|
|
2796
|
-
* A vector is always numbers, so it never needs the per-element deep copy an array of objects
|
|
2797
|
-
* or dates does.
|
|
2798
|
-
*/ const PRIMITIVE_ELEMENT_TYPES = new Set([
|
|
2799
|
-
types/* .SchemaTypes.String */.L.String,
|
|
2800
|
-
types/* .SchemaTypes.Number */.L.Number,
|
|
2801
|
-
types/* .SchemaTypes.Boolean */.L.Boolean
|
|
2802
|
-
]);
|
|
2803
|
-
const hasPrimitiveElements = (type, elementType)=>type === types/* .SchemaTypes.Vector */.L.Vector || PRIMITIVE_ELEMENT_TYPES.has(elementType);
|
|
2804
|
-
|
|
2801
|
+
// EXTERNAL MODULE: ./src/schema/utils/propertyKind.ts
|
|
2802
|
+
var propertyKind = __webpack_require__(575);
|
|
2805
2803
|
;// CONCATENATED MODULE: ./src/codegen/handlers/enrichment/EnrichmentArrayHandler.ts
|
|
2806
2804
|
|
|
2807
2805
|
|
|
@@ -2811,7 +2809,7 @@ const hasPrimitiveElements = (type, elementType)=>type === types/* .SchemaTypes.
|
|
|
2811
2809
|
* mark the root entity dirty instead of being silently lost on save.
|
|
2812
2810
|
*/ class EnrichmentArrayHandler extends PropertyInfoHandler {
|
|
2813
2811
|
handle(property, builder) {
|
|
2814
|
-
if (isArrayValued(property.type)) {
|
|
2812
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
2815
2813
|
// Place the property in the enriched literal like any other leaf
|
|
2816
2814
|
this.setEnrichedProperty(property, builder);
|
|
2817
2815
|
const enrichedPath = property.getAssignmentPath({
|
|
@@ -2853,13 +2851,10 @@ class MergeDefaultFunctionHandler extends PropertyInfoHandler {
|
|
|
2853
2851
|
// we are changing merge to be more like enrich so we can handle injections
|
|
2854
2852
|
// we may need to change more. Need to move towards factories
|
|
2855
2853
|
if (property.defaultValue != null && typeof property.defaultValue === "function") {
|
|
2856
|
-
const
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
factory.parameters(parameter);
|
|
2861
|
-
defaultFunctionParameters.push(parameter.name);
|
|
2862
|
-
}
|
|
2854
|
+
const factory = builder.get("factory");
|
|
2855
|
+
const args = property.injected != null ? [
|
|
2856
|
+
factory.bind(property.injected)
|
|
2857
|
+
] : [];
|
|
2863
2858
|
// A defaulted property still merges from the source; the default only fills
|
|
2864
2859
|
// the gap when neither side has a value
|
|
2865
2860
|
this.emitMergeCopy(property, builder, {
|
|
@@ -2875,15 +2870,9 @@ class MergeDefaultFunctionHandler extends PropertyInfoHandler {
|
|
|
2875
2870
|
const assignmentPath = property.getAssignmentPath({
|
|
2876
2871
|
parent: "destination"
|
|
2877
2872
|
});
|
|
2878
|
-
const declarationsSlot = builder.get("factory.function.header");
|
|
2879
|
-
const defaultFunctionWithParameters = this.toNamedFunction(property.defaultValue.toString(), declarationsSlot);
|
|
2880
|
-
defaultFunctionWithParameters.builder.parameters(...defaultFunctionParameters.map((w, i)=>({
|
|
2881
|
-
name: defaultFunctionWithParameters.parameters[i],
|
|
2882
|
-
callName: w
|
|
2883
|
-
})));
|
|
2884
2873
|
const defaultIf = ifsSlot.if(`${selectorPath} == null`);
|
|
2885
2874
|
this.emitDestinationAncestorGuards(property, defaultIf);
|
|
2886
|
-
defaultIf.appendBody(`${assignmentPath} = ${
|
|
2875
|
+
defaultIf.appendBody(`${assignmentPath} = ${this.emitBoundCall(factory, property.defaultValue, args)}`);
|
|
2887
2876
|
return builder;
|
|
2888
2877
|
}
|
|
2889
2878
|
return super.handle(property, builder);
|
|
@@ -2924,28 +2913,20 @@ class MergePrimitiveHandler extends PropertyInfoHandler {
|
|
|
2924
2913
|
class MergeComputedValueHandler extends PropertyInfoHandler {
|
|
2925
2914
|
handle(property, builder) {
|
|
2926
2915
|
if (property.functionBody != null && property.type === types/* .SchemaTypes.Computed */.L.Computed) {
|
|
2927
|
-
const
|
|
2916
|
+
const factory = builder.get("factory");
|
|
2917
|
+
const args = [
|
|
2928
2918
|
"source",
|
|
2929
2919
|
"collectionName"
|
|
2930
2920
|
];
|
|
2931
2921
|
if (property.injected != null) {
|
|
2932
|
-
|
|
2933
|
-
const parameter = factory.createParameter(property.injected);
|
|
2934
|
-
factory.parameters(parameter);
|
|
2935
|
-
parameterNames.push(parameter.name);
|
|
2922
|
+
args.push(factory.bind(property.injected));
|
|
2936
2923
|
}
|
|
2937
|
-
const declarationsSlot = builder.get("factory.function.header");
|
|
2938
|
-
const defaultFunctionWithParameters = this.toNamedFunction(property.functionBody.toString(), declarationsSlot);
|
|
2939
|
-
defaultFunctionWithParameters.builder.parameters(...parameterNames.map((w, i)=>({
|
|
2940
|
-
name: defaultFunctionWithParameters.parameters[i],
|
|
2941
|
-
callName: w
|
|
2942
|
-
})));
|
|
2943
2924
|
const slot = builder.get("factory.function.assignments");
|
|
2944
2925
|
const enrichedAssignmentPath = property.getAssignmentPath({
|
|
2945
2926
|
parent: "destination"
|
|
2946
2927
|
});
|
|
2947
2928
|
// We want to recompute the value always in case there are changes
|
|
2948
|
-
slot.assign(enrichedAssignmentPath).value(
|
|
2929
|
+
slot.assign(enrichedAssignmentPath).value(this.emitBoundCall(factory, property.functionBody, args));
|
|
2949
2930
|
return builder;
|
|
2950
2931
|
}
|
|
2951
2932
|
return super.handle(property, builder);
|
|
@@ -3018,7 +2999,7 @@ class MergeFunctionHandler extends PropertyInfoHandler {
|
|
|
3018
2999
|
* reference is adopted as-is — same as the primitive copy this replaces.
|
|
3019
3000
|
*/ class MergeArrayHandler extends PropertyInfoHandler {
|
|
3020
3001
|
handle(property, builder) {
|
|
3021
|
-
if (isArrayValued(property.type)) {
|
|
3002
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
3022
3003
|
const selectorPath = property.getSelectrorPath({
|
|
3023
3004
|
parent: "source",
|
|
3024
3005
|
assignmentType: "FORCE_NULLABLE_OR_OPTIONAL"
|
|
@@ -3355,7 +3336,7 @@ class CloneArrayHandler extends PropertyInfoHandler {
|
|
|
3355
3336
|
super(), this.useFromPropertyName = useFromPropertyName;
|
|
3356
3337
|
}
|
|
3357
3338
|
handle(property, builder) {
|
|
3358
|
-
if (isArrayValued(property.type)) {
|
|
3339
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
3359
3340
|
// Arrays are leaf properties — they have no child PropertyInfos, so the
|
|
3360
3341
|
// copy must happen here for every array, including nullable/optional ones.
|
|
3361
3342
|
// The `!== undefined` guard below covers absent values; an explicit null is copied as
|
|
@@ -3381,7 +3362,7 @@ class CloneArrayHandler extends PropertyInfoHandler {
|
|
|
3381
3362
|
// across merges), and a Proxy cannot pass a structured-clone boundary.
|
|
3382
3363
|
const elementType = property.innerSchema?.type;
|
|
3383
3364
|
let copyExpression;
|
|
3384
|
-
if (hasPrimitiveElements(property.type, elementType)) {
|
|
3365
|
+
if ((0,propertyKind/* .hasPrimitiveElements */.L)(property.type, elementType)) {
|
|
3385
3366
|
copyExpression = `[...${entitySelectorPath}]`;
|
|
3386
3367
|
} else if (elementType === types/* .SchemaTypes.Date */.L.Date) {
|
|
3387
3368
|
copyExpression = `${entitySelectorPath}.map(function (v) { return v == null ? v : new Date(v); })`;
|
|
@@ -3500,7 +3481,7 @@ class CloneObjectHandler extends PropertyInfoHandler {
|
|
|
3500
3481
|
// Anything that copies by assignment. An array-valued property must not land here:
|
|
3501
3482
|
// assigning the reference shares it with the source, which is the whole point of
|
|
3502
3483
|
// CloneArrayHandler.
|
|
3503
|
-
if (property.type != types/* .SchemaTypes.Object */.L.Object && isArrayValued(property.type) === false) {
|
|
3484
|
+
if (property.type != types/* .SchemaTypes.Object */.L.Object && (0,propertyKind/* .isArrayValued */.l)(property.type) === false) {
|
|
3504
3485
|
const slot = builder.get("if");
|
|
3505
3486
|
const useFromPropertyName = this.useFromPropertyName;
|
|
3506
3487
|
const entitySelectorPath = property.getSelectrorPath({
|
|
@@ -3563,7 +3544,7 @@ class CloneHandlerBuilder {
|
|
|
3563
3544
|
|
|
3564
3545
|
class CompareArrayHandler extends PropertyInfoHandler {
|
|
3565
3546
|
handle(property, builder) {
|
|
3566
|
-
if (isArrayValued(property.type)) {
|
|
3547
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
3567
3548
|
let compare = builder.getOrDefault("result.variable.compare");
|
|
3568
3549
|
const leftCompare = property.getSelectrorPath({
|
|
3569
3550
|
parent: "a"
|
|
@@ -3858,7 +3839,6 @@ class DeserializeDeserializerHandler extends PropertyInfoHandler {
|
|
|
3858
3839
|
handle(property, builder) {
|
|
3859
3840
|
if (property.valueDeserializer != null) {
|
|
3860
3841
|
let objectBuilder = builder.getOrDefault("result.variable.object");
|
|
3861
|
-
const assignmentBuilder = builder.getOrDefault("functions");
|
|
3862
3842
|
// Read the incoming record by `from` (storage) name
|
|
3863
3843
|
const entitySelectorPath = property.getSelectrorPath({
|
|
3864
3844
|
parent: "unserialized",
|
|
@@ -3871,18 +3851,16 @@ class DeserializeDeserializerHandler extends PropertyInfoHandler {
|
|
|
3871
3851
|
name: "object"
|
|
3872
3852
|
});
|
|
3873
3853
|
}
|
|
3874
|
-
const
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
callName: entitySelectorPath
|
|
3878
|
-
})));
|
|
3854
|
+
const call = this.emitBoundCall(builder, property.valueDeserializer, [
|
|
3855
|
+
entitySelectorPath
|
|
3856
|
+
]);
|
|
3879
3857
|
if (property.parent == null) {
|
|
3880
|
-
objectBuilder.property(`${property.name}: ${
|
|
3858
|
+
objectBuilder.property(`${property.name}: ${call}`);
|
|
3881
3859
|
return builder;
|
|
3882
3860
|
}
|
|
3883
3861
|
const slotPath = new SlotPath(...property.getParentPathArray());
|
|
3884
3862
|
objectBuilder = objectBuilder.get(slotPath.get());
|
|
3885
|
-
objectBuilder.property(`${property.name}: ${
|
|
3863
|
+
objectBuilder.property(`${property.name}: ${call}`);
|
|
3886
3864
|
return builder;
|
|
3887
3865
|
}
|
|
3888
3866
|
return super.handle(property, builder);
|
|
@@ -3908,7 +3886,7 @@ class DeserializeDeserializerHandler extends PropertyInfoHandler {
|
|
|
3908
3886
|
return `[...${selector}]`;
|
|
3909
3887
|
}
|
|
3910
3888
|
handle(property, builder) {
|
|
3911
|
-
if (isArrayValued(property.type)) {
|
|
3889
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
3912
3890
|
const slotPath = new SlotPath("result.variable.object");
|
|
3913
3891
|
// Create the result object when this is the first property iterated —
|
|
3914
3892
|
// handler output cannot depend on schema property order
|
|
@@ -4149,7 +4127,7 @@ class HashComputedValueHandler extends PropertyInfoHandler {
|
|
|
4149
4127
|
* objects would collapse every value to "[object Object]" and collide.
|
|
4150
4128
|
*/ class HashArrayHandler extends PropertyInfoHandler {
|
|
4151
4129
|
handle(property, builder) {
|
|
4152
|
-
if (isArrayValued(property.type)) {
|
|
4130
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
4153
4131
|
let stringBuilder = builder.getOrDefault("hash-object-return.variable.string");
|
|
4154
4132
|
const entitySelectorPath = property.getSelectrorPath({
|
|
4155
4133
|
parent: "entity"
|
|
@@ -4314,7 +4292,7 @@ class EnableChangeTrackingObjectHandler extends PropertyInfoHandler {
|
|
|
4314
4292
|
* mark the root entity dirty instead of being silently lost on save.
|
|
4315
4293
|
*/ class EnableChangeTrackingArrayHandler extends PropertyInfoHandler {
|
|
4316
4294
|
handle(property, builder) {
|
|
4317
|
-
if (isArrayValued(property.type)) {
|
|
4295
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
4318
4296
|
const assignmentSlot = builder.get("assignment");
|
|
4319
4297
|
const childSelectorPath = property.getSelectrorPath({
|
|
4320
4298
|
parent: "entity"
|
|
@@ -4391,7 +4369,7 @@ class FreezeObjectHandler extends PropertyInfoHandler {
|
|
|
4391
4369
|
|
|
4392
4370
|
class FreezeArrayHandler extends PropertyInfoHandler {
|
|
4393
4371
|
handle(property, builder) {
|
|
4394
|
-
if (isArrayValued(property.type)) {
|
|
4372
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
4395
4373
|
const assignmentSlot = builder.get("assignment");
|
|
4396
4374
|
const childSelectorPath = property.getSelectrorPath({
|
|
4397
4375
|
parent: "entity"
|
|
@@ -4527,7 +4505,6 @@ class SerializeSerializerHandler extends PropertyInfoHandler {
|
|
|
4527
4505
|
handle(property, builder) {
|
|
4528
4506
|
if (property.valueSerializer != null) {
|
|
4529
4507
|
const slot = builder.getOrDefault("if");
|
|
4530
|
-
const assignmentBuilder = builder.getOrDefault("functions");
|
|
4531
4508
|
// Serialize maps in-memory shape -> storage shape: read the entity by
|
|
4532
4509
|
// property name, write the result by `from` (storage) name
|
|
4533
4510
|
const entitySelectorPath = property.getSelectrorPath({
|
|
@@ -4537,17 +4514,15 @@ class SerializeSerializerHandler extends PropertyInfoHandler {
|
|
|
4537
4514
|
parent: "result",
|
|
4538
4515
|
useFromPropertyName: true
|
|
4539
4516
|
});
|
|
4540
|
-
const
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
callName: entitySelectorPath
|
|
4544
|
-
})));
|
|
4517
|
+
const call = this.emitBoundCall(builder, property.valueSerializer, [
|
|
4518
|
+
entitySelectorPath
|
|
4519
|
+
]);
|
|
4545
4520
|
if (property.parent == null) {
|
|
4546
|
-
slot.if(`Object.hasOwn(entity, "${property.name}")`).appendBody(`${resultSelectorPath} = ${
|
|
4521
|
+
slot.if(`Object.hasOwn(entity, "${property.name}")`).appendBody(`${resultSelectorPath} = ${call}`);
|
|
4547
4522
|
return builder;
|
|
4548
4523
|
}
|
|
4549
4524
|
// Nested serializer: same pattern as SerializeValueHandler — if block for parent existence, then assign via serializer
|
|
4550
|
-
this.emitSerializeNestedAssignment(property, slot,
|
|
4525
|
+
this.emitSerializeNestedAssignment(property, slot, call);
|
|
4551
4526
|
return builder;
|
|
4552
4527
|
}
|
|
4553
4528
|
return super.handle(property, builder);
|
|
@@ -4606,7 +4581,7 @@ class SerializeComputedHandler extends PropertyInfoHandler {
|
|
|
4606
4581
|
return `[...${selector}]`;
|
|
4607
4582
|
}
|
|
4608
4583
|
handle(property, builder) {
|
|
4609
|
-
if (isArrayValued(property.type)) {
|
|
4584
|
+
if ((0,propertyKind/* .isArrayValued */.l)(property.type)) {
|
|
4610
4585
|
const slot = builder.get("if");
|
|
4611
4586
|
// Serialize maps in-memory shape -> storage shape: read the entity by
|
|
4612
4587
|
// property name, write the result by `from` (storage) name
|
|
@@ -5510,8 +5485,8 @@ const arrayConverter = (property, context)=>{
|
|
|
5510
5485
|
// Create the function using new Function()
|
|
5511
5486
|
// If no parameters, call with just the body; otherwise spread the params
|
|
5512
5487
|
const fn = params.length > 0 ? new Function(...params, functionBody) : new Function(functionBody);
|
|
5513
|
-
// Wrap it so toString() returns the original arrow function string
|
|
5514
|
-
//
|
|
5488
|
+
// Wrap it so toString() returns the original arrow function string, so
|
|
5489
|
+
// serializing the rehydrated schema writes the same functionSource again
|
|
5515
5490
|
recreatedFn = Object.assign(fn, {
|
|
5516
5491
|
toString: ()=>functionSource
|
|
5517
5492
|
});
|
|
@@ -5520,7 +5495,7 @@ const arrayConverter = (property, context)=>{
|
|
|
5520
5495
|
recreatedFn = ()=>{
|
|
5521
5496
|
throw new Error(`Cannot recreate computed property ${computedProp.name}: ${e instanceof Error ? e.message : 'unknown error'}`);
|
|
5522
5497
|
};
|
|
5523
|
-
//
|
|
5498
|
+
// Keep functionSource re-parseable if this schema is serialized again
|
|
5524
5499
|
Object.assign(recreatedFn, {
|
|
5525
5500
|
toString: ()=>`() => { throw new Error("Cannot recreate computed property ${computedProp.name}"); }`
|
|
5526
5501
|
});
|
|
@@ -5657,39 +5632,16 @@ class SetHandlerBuilder {
|
|
|
5657
5632
|
}
|
|
5658
5633
|
}
|
|
5659
5634
|
|
|
5660
|
-
;// CONCATENATED MODULE: ./src/schema/
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
function assertPropertyHandled(generatorName, property, result) {
|
|
5688
|
-
if (result == null) {
|
|
5689
|
-
throw new Error(`Schema compilation failed: no '${generatorName}' code generator handles property '${property.getAssignmentPath()}' (type: ${property.type}). Add a handler for this property shape or mark it not applicable in the ${generatorName} chain.`);
|
|
5690
|
-
}
|
|
5691
|
-
}
|
|
5692
|
-
function createChangeTracker() {
|
|
5635
|
+
;// CONCATENATED MODULE: ./src/schema/changeTracker.ts
|
|
5636
|
+
/**
|
|
5637
|
+
* Builds the proxy factory that change-tracks an entity.
|
|
5638
|
+
*
|
|
5639
|
+
* Generated schema code receives the result as a bound value — a parameter of the generated
|
|
5640
|
+
* factory — and never refers to this module by name. Name references do not survive a minifier,
|
|
5641
|
+
* which renames the declaration but cannot see inside generated source text (#40, #46). The
|
|
5642
|
+
* returned function holds no per-entity state, so one per compiled schema is shared by every
|
|
5643
|
+
* entity it tracks.
|
|
5644
|
+
*/ function createChangeTracker() {
|
|
5693
5645
|
const DIRTY_ENTITY_MARKER = "isDirty";
|
|
5694
5646
|
const CHANGES_ENTITY_KEY = "changes";
|
|
5695
5647
|
const ORIGINAL_ENTITY_KEY = "original";
|
|
@@ -5788,6 +5740,40 @@ function createChangeTracker() {
|
|
|
5788
5740
|
return new Proxy(entity, proxyHandler);
|
|
5789
5741
|
};
|
|
5790
5742
|
}
|
|
5743
|
+
|
|
5744
|
+
;// CONCATENATED MODULE: ./src/schema/SchemaDefinition.ts
|
|
5745
|
+
|
|
5746
|
+
|
|
5747
|
+
|
|
5748
|
+
|
|
5749
|
+
|
|
5750
|
+
|
|
5751
|
+
|
|
5752
|
+
|
|
5753
|
+
|
|
5754
|
+
|
|
5755
|
+
|
|
5756
|
+
|
|
5757
|
+
|
|
5758
|
+
|
|
5759
|
+
|
|
5760
|
+
|
|
5761
|
+
|
|
5762
|
+
|
|
5763
|
+
|
|
5764
|
+
|
|
5765
|
+
|
|
5766
|
+
|
|
5767
|
+
|
|
5768
|
+
|
|
5769
|
+
|
|
5770
|
+
|
|
5771
|
+
|
|
5772
|
+
function assertPropertyHandled(generatorName, property, result) {
|
|
5773
|
+
if (result == null) {
|
|
5774
|
+
throw new Error(`Schema compilation failed: no '${generatorName}' code generator handles property '${property.getAssignmentPath()}' (type: ${property.type}). Add a handler for this property shape or mark it not applicable in the ${generatorName} chain.`);
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5791
5777
|
class SchemaDefinition extends SchemaBase {
|
|
5792
5778
|
instance;
|
|
5793
5779
|
type = types/* .SchemaTypes.Definition */.L.Definition;
|
|
@@ -5838,10 +5824,22 @@ class SchemaDefinition extends SchemaBase {
|
|
|
5838
5824
|
throw e;
|
|
5839
5825
|
}
|
|
5840
5826
|
}
|
|
5841
|
-
|
|
5827
|
+
/**
|
|
5828
|
+
* Compiles `builder` into a function taking `fnArgs`.
|
|
5829
|
+
*
|
|
5830
|
+
* A builder with bindings is compiled one level out: an outer function whose parameters are
|
|
5831
|
+
* the bindings, called once here with their values, returns the function that is kept. The
|
|
5832
|
+
* bound values become closure variables of that function, so the per-call cost is a context
|
|
5833
|
+
* read rather than anything resolved by name.
|
|
5834
|
+
*/ createFunction(builder, ...fnArgs) {
|
|
5842
5835
|
const body = builder.toString();
|
|
5836
|
+
const bindings = builder.getBindings();
|
|
5843
5837
|
try {
|
|
5844
|
-
|
|
5838
|
+
if (bindings.length === 0) {
|
|
5839
|
+
return Function(...fnArgs, body);
|
|
5840
|
+
}
|
|
5841
|
+
const outer = Function(...bindings.map((w)=>w.name), `return function(${fnArgs.join(", ")}) {\n${body}\n}`);
|
|
5842
|
+
return outer(...bindings.map((w)=>w.value));
|
|
5845
5843
|
} catch (e) {
|
|
5846
5844
|
logger/* .logger.error */.vF.error(`Error compiling schema function. Function Body: ${body}`);
|
|
5847
5845
|
throw e;
|
|
@@ -5974,9 +5972,11 @@ class SchemaDefinition extends SchemaBase {
|
|
|
5974
5972
|
const serializeHandler = serializeHandlerBuilder.build();
|
|
5975
5973
|
const compareIdsHandler = compareIdsHandlerBuilder.build();
|
|
5976
5974
|
const setHandlerHanlder = setHandlerBuilder.build();
|
|
5975
|
+
// Handed to the generated functions as a value, never embedded as source and called
|
|
5976
|
+
// by name — a minifier renames the declaration and breaks every schema (#40).
|
|
5977
|
+
const changeTracker = createChangeTracker();
|
|
5977
5978
|
const changeTrackingCodeBuilder = new blocks/* .CodeBuilder */.Nl();
|
|
5978
|
-
changeTrackingCodeBuilder.
|
|
5979
|
-
changeTrackingCodeBuilder.slot("declarations").variable("enableChangeTracking").value('createChangeTracker()');
|
|
5979
|
+
changeTrackingCodeBuilder.bind(changeTracker, "enableChangeTracking");
|
|
5980
5980
|
// Nested proxies are installed by assigning through already-proxied parents;
|
|
5981
5981
|
// pause tracking during setup so those writes don't register as changes
|
|
5982
5982
|
changeTrackingCodeBuilder.slot("pause").raw('\tconst hadTracking = entity.__tracking__ != null;\n\tif (!hadTracking) { Object.defineProperty(entity, "__tracking__", { value: { changes: {}, isDirty: false, original: {}, isPaused: false }, configurable: true, writable: true, enumerable: false }); }\n\tconst wasPaused = entity.__tracking__.isPaused;\n\tentity.__tracking__.isPaused = true;');
|
|
@@ -6005,9 +6005,10 @@ class SchemaDefinition extends SchemaBase {
|
|
|
6005
6005
|
}).parameters({
|
|
6006
6006
|
name: "collectionName",
|
|
6007
6007
|
value: this.collectionName
|
|
6008
|
+
}, {
|
|
6009
|
+
name: "changeTracker",
|
|
6010
|
+
value: changeTracker
|
|
6008
6011
|
});
|
|
6009
|
-
enricherFunctionRoot.slot("changeTracker").raw(`${createChangeTracker.toString()}`);
|
|
6010
|
-
enricherFunctionRoot.slot("changeTrackerFunction").raw(`\tconst changeTracker = createChangeTracker();`);
|
|
6011
6012
|
const enricherFunctionBody = enricherFunctionRoot.function(undefined, {
|
|
6012
6013
|
name: "function"
|
|
6013
6014
|
}).parameters("entity", "changeTrackingType").return();
|
|
@@ -6242,6 +6243,8 @@ class SchemaDefinition extends SchemaBase {
|
|
|
6242
6243
|
enricherFunctionBody.get("append").insert(deserializeCodeBuilder.get("result"));
|
|
6243
6244
|
enricherFunctionBody.get("append").insert(deserializeCodeBuilder.get("if"));
|
|
6244
6245
|
enricherFunctionRoot.replace("function", new blocks/* .FunctionBuilder */.kF(undefined).parameters("unserialized", "changeTrackingType").return());
|
|
6246
|
+
// The deserialize slots moved in above call the deserializers bound on their own builder
|
|
6247
|
+
enricherFunctionRoot.parameters(...deserializeCodeBuilder.getBindings());
|
|
6245
6248
|
const postProcessGenerator = this.createReturnFunction(enricherCodeBuilder);
|
|
6246
6249
|
const postProcessParams = enricherFunctionRoot.getParameters();
|
|
6247
6250
|
// Combine prepare and serialize
|
|
@@ -6250,6 +6253,10 @@ class SchemaDefinition extends SchemaBase {
|
|
|
6250
6253
|
preprocessCodeBuilder.get("main").insert(serializeCodeBuilder.get("assignments"));
|
|
6251
6254
|
preprocessCodeBuilder.get("main").insert(serializeCodeBuilder.get("functions"));
|
|
6252
6255
|
preprocessCodeBuilder.get("main").insert(serializeCodeBuilder.get("if"));
|
|
6256
|
+
// Likewise the serialize slots call the serializers bound on the serialize builder
|
|
6257
|
+
for (const binding of serializeCodeBuilder.getBindings()){
|
|
6258
|
+
preprocessCodeBuilder.bind(binding.value, binding.name);
|
|
6259
|
+
}
|
|
6253
6260
|
const getIdsFunction = this.createFunction(idSelectorCodeBuilder, "entity");
|
|
6254
6261
|
const getHashTypeFunction = this.createFunction(hashTypeCodeBuilder, "entity");
|
|
6255
6262
|
const prepareFunction = this.createFunction(prepareCodeBuilder, "entity");
|
|
@@ -6891,6 +6898,8 @@ const s = {
|
|
|
6891
6898
|
|
|
6892
6899
|
|
|
6893
6900
|
|
|
6901
|
+
// EXTERNAL MODULE: ./src/schema/utils/storageDates.ts
|
|
6902
|
+
var storageDates = __webpack_require__(894);
|
|
6894
6903
|
;// CONCATENATED MODULE: ./src/schema/index.ts
|
|
6895
6904
|
|
|
6896
6905
|
|
|
@@ -6903,6 +6912,7 @@ const s = {
|
|
|
6903
6912
|
|
|
6904
6913
|
|
|
6905
6914
|
|
|
6915
|
+
|
|
6906
6916
|
})();
|
|
6907
6917
|
|
|
6908
6918
|
module.exports = __webpack_exports__;
|