@routier/core 0.5.0 → 0.7.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 (65) hide show
  1. package/README.md +1 -1
  2. package/dist/assertions/index.cjs +19 -8
  3. package/dist/assertions/index.cjs.map +1 -1
  4. package/dist/assertions/index.d.ts +5 -1
  5. package/dist/assertions/index.js +21 -9
  6. package/dist/assertions/index.js.map +1 -1
  7. package/dist/collections/MemoryDataCollection.d.ts +10 -0
  8. package/dist/collections/index.cjs +29 -4
  9. package/dist/collections/index.cjs.map +1 -1
  10. package/dist/collections/index.js +29 -4
  11. package/dist/collections/index.js.map +1 -1
  12. package/dist/expressions/callSource.d.ts +41 -0
  13. package/dist/expressions/evaluate.d.ts +3 -0
  14. package/dist/expressions/fold.d.ts +7 -0
  15. package/dist/expressions/index.cjs +1754 -233
  16. package/dist/expressions/index.cjs.map +1 -1
  17. package/dist/expressions/index.d.ts +2 -0
  18. package/dist/expressions/index.js +1765 -234
  19. package/dist/expressions/index.js.map +1 -1
  20. package/dist/expressions/types.d.ts +45 -26
  21. package/dist/expressions/utils.d.ts +19 -1
  22. package/dist/index.cjs +2429 -363
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.js +2769 -682
  25. package/dist/index.js.map +1 -1
  26. package/dist/performance/index.cjs +6 -4
  27. package/dist/performance/index.cjs.map +1 -1
  28. package/dist/performance/index.js +6 -4
  29. package/dist/performance/index.js.map +1 -1
  30. package/dist/pipeline/index.cjs +6 -4
  31. package/dist/pipeline/index.cjs.map +1 -1
  32. package/dist/pipeline/index.js +6 -4
  33. package/dist/pipeline/index.js.map +1 -1
  34. package/dist/plugins/index.cjs +2323 -316
  35. package/dist/plugins/index.cjs.map +1 -1
  36. package/dist/plugins/index.d.ts +1 -0
  37. package/dist/plugins/index.js +2328 -311
  38. package/dist/plugins/index.js.map +1 -1
  39. package/dist/plugins/query/QueryOptionsCollection.d.ts +38 -10
  40. package/dist/plugins/query/describeFilter.d.ts +83 -0
  41. package/dist/plugins/query/explain.d.ts +71 -9
  42. package/dist/plugins/query/index.d.ts +1 -0
  43. package/dist/plugins/query/join.d.ts +4 -1
  44. package/dist/plugins/query/types.d.ts +36 -4
  45. package/dist/plugins/resultShape.d.ts +35 -0
  46. package/dist/schema/PropertyInfo.d.ts +0 -1
  47. package/dist/schema/index.cjs +7 -14
  48. package/dist/schema/index.cjs.map +1 -1
  49. package/dist/schema/index.js +7 -14
  50. package/dist/schema/index.js.map +1 -1
  51. package/dist/transfer/ChunkEncoder.d.ts +60 -0
  52. package/dist/transfer/decoder.d.ts +29 -0
  53. package/dist/transfer/fillers.d.ts +36 -0
  54. package/dist/transfer/index.cjs +873 -0
  55. package/dist/transfer/index.cjs.map +1 -0
  56. package/dist/transfer/index.d.ts +47 -0
  57. package/dist/transfer/index.js +872 -0
  58. package/dist/transfer/index.js.map +1 -0
  59. package/dist/transfer/plan.d.ts +94 -0
  60. package/dist/transfer/types.d.ts +138 -0
  61. package/dist/utilities/index.cjs +242 -49
  62. package/dist/utilities/index.cjs.map +1 -1
  63. package/dist/utilities/index.js +242 -49
  64. package/dist/utilities/index.js.map +1 -1
  65. package/package.json +9 -1
@@ -9,18 +9,11 @@ export declare class QueryOptionsCollection<T> {
9
9
  private nextExecutionReason;
10
10
  private nextIndex;
11
11
  private enumeratedItems;
12
+ private dirty;
13
+ /** The collection a `splitAt`/`split` half came from. A capability report belongs to it. */
14
+ private origin;
12
15
  /** Cuts over to memory execution, keeping the first cause. See `MemoryExecutionReason`. */
13
16
  private cutOverToMemory;
14
- /**
15
- * True when `split()` or `splitAt()` produced this collection.
16
- *
17
- * Those rebuild each half by re-adding its options, which re-derives execution targets
18
- * without the options that caused them — a post-join filter alone in the memory half
19
- * derives back to `"database"`. Anything reading `target` as a report of where work runs
20
- * has to reject a derived collection; see `explainQuery`.
21
- */
22
- private derived;
23
- get isDerived(): boolean;
24
17
  get items(): Map<keyof QueryOptionValueMap<unknown>, QueryCollectionItem<any, any>[]>;
25
18
  get isEmpty(): boolean;
26
19
  static EMPTY<R>(): QueryOptionsCollection<R>;
@@ -47,6 +40,41 @@ export declare class QueryOptionsCollection<T> {
47
40
  * runs it over the first execution's scalar result.
48
41
  */
49
42
  snapshot(): () => void;
43
+ /** Takes an item as it stands — same object, same index, same target and reason. */
44
+ private adopt;
45
+ /**
46
+ * A plugin reporting that its engine cannot express one option.
47
+ *
48
+ * Core marks the rest of the database phase `not-reached`, because the database has to stop
49
+ * there — a window applied in front of a filter that was not applied returns the wrong rows.
50
+ * Passing the cascade through core is what makes it impossible for a plugin to mark a
51
+ * non-contiguous cut.
52
+ *
53
+ * A report names a culprit and never un-names one, so reports commute.
54
+ *
55
+ * The option is not moved to the memory arm. It stays where it was planned, which is what keeps
56
+ * a redirect distinguishable from something core sent to memory in the first place.
57
+ */
58
+ reportMissingCapability(item: QueryCollectionItem<any, any>): void;
59
+ /**
60
+ * A plugin reporting that its engine would answer one option differently from JavaScript.
61
+ *
62
+ * Same cascade as `reportMissingCapability`, and a separate reason because the caller can act on
63
+ * one and not the other. See `DatabaseExecutionReason`.
64
+ */
65
+ reportEngineDivergence(item: QueryCollectionItem<any, any>): void;
66
+ private report;
67
+ /**
68
+ * Forgets what any previous dispatch reported.
69
+ *
70
+ * Capability is answered per dispatch, so a report is only an answer for the execution that
71
+ * produced it. The items are shared with any snapshot, so a report mutated in place otherwise
72
+ * survives a restore and a second terminal on the same queryable replays options the plugin
73
+ * did run — a `skip` applied twice, over rows already windowed.
74
+ */
75
+ forgetReports(): void;
76
+ /** The options the database did not run, in the order they were written. */
77
+ notExecuted(): QueryCollectionItem<any, any>[];
50
78
  split(): {
51
79
  memory: QueryOptionsCollection<T>;
52
80
  database: QueryOptionsCollection<T>;
@@ -0,0 +1,83 @@
1
+ import type { Expression } from "../../expressions";
2
+ /**
3
+ * Saying what a backend was asked to do, with the values pulled out.
4
+ *
5
+ * `explain` already carries `{ text, parameters }` per executed query, and the SQL plugins fill
6
+ * both in — a statement with `?` and the values bound to it. Every other backend reported a
7
+ * placeholder: Dexie said `filter(<predicate>)`, which names nothing, and a key-value store said
8
+ * only that it scanned. The predicate was the one thing a reader wanted and the one thing missing.
9
+ *
10
+ * Two renderings live here, and neither knows about a specific engine:
11
+ *
12
+ * - `describeFilterAsJs` — the predicate as JavaScript, for a backend with no query language of
13
+ * its own. It reads like what the caller wrote, which is what they are looking for.
14
+ * - `parameteriseDocument` — for a backend whose query IS a document. Values become `?` and are
15
+ * collected in order, so a Mango selector and an MQL filter both come out in their own shape
16
+ * with the values listed beside them.
17
+ *
18
+ * Pulling values out is not decoration. It is what makes two runs of one query comparable, and
19
+ * what keeps a value out of the text when that text is logged.
20
+ */
21
+ export type ParameterisedQuery = {
22
+ /** The query in its own language, with each value replaced by `?`. */
23
+ text: string;
24
+ /** The values, in the order their placeholders appear. */
25
+ parameters: unknown[];
26
+ };
27
+ /**
28
+ * The predicate as JavaScript, with every value replaced by `?`.
29
+ *
30
+ * Rendered from the parsed tree rather than from the function's source. The tree is what the
31
+ * backend was actually given, so this cannot drift from what ran; and a value reaching the tree
32
+ * as a literal is indistinguishable from one arriving through a params object, which is what
33
+ * makes both come out as `?` the way SQL treats them.
34
+ */
35
+ export declare const describeFilterAsJs: (expression: Expression) => ParameterisedQuery;
36
+ /**
37
+ * Marks a value inside a query document so it is replaced by `?` rather than printed.
38
+ *
39
+ * A document language carries its values inline, so there is nothing in the shape itself to say
40
+ * which parts are operators and which are data. A dialect wraps the data as it builds the
41
+ * document, and `parameteriseDocument` reads the wrapper.
42
+ */
43
+ declare const PARAMETER: unique symbol;
44
+ export type ParameterHolder = {
45
+ readonly [PARAMETER]: unknown;
46
+ };
47
+ export declare const parameter: (value: unknown) => ParameterHolder;
48
+ /**
49
+ * Renders a query DOCUMENT with its values replaced by `?`.
50
+ *
51
+ * Language-agnostic on purpose: an MQL filter and a Mango selector are both plain objects, and so
52
+ * is whatever a future document store wants reported. The dialect decides the shape; this only
53
+ * decides how it is written down.
54
+ *
55
+ * A value not wrapped by `parameter` is structural — an operator name, a field path, a nesting
56
+ * level — and is printed as it is. That is the whole distinction, and it has to be made where the
57
+ * document is built, because by the time it is an object the two are the same kind of thing.
58
+ */
59
+ export declare const parameteriseDocument: (document: unknown) => ParameterisedQuery;
60
+ /**
61
+ * Every filter on a query, as one description.
62
+ *
63
+ * Filters accumulate — `.where(a).where(b)` is `a && b` — so they are reported as one predicate
64
+ * rather than several, which is how the caller thinks of them and how a SQL plugin renders them
65
+ * into one `WHERE`. Parameters run left to right across the whole thing, matching the text.
66
+ *
67
+ * A filter that could not be parsed falls back to its source. Mixing the two is deliberate: one
68
+ * unparsable filter does not make the others unreadable, and seeing which one it was is the
69
+ * point.
70
+ */
71
+ export declare const describeFilters: (filters: readonly {
72
+ expression: Expression;
73
+ filter?: unknown;
74
+ }[]) => ParameterisedQuery;
75
+ /**
76
+ * A predicate core could not parse, shown as the caller wrote it.
77
+ *
78
+ * This is the case where the source matters most: an unparsable filter is why the query did not
79
+ * push down, and the reason codes say that it happened without showing what it was. There are no
80
+ * parameters — nothing was extracted, because nothing was understood.
81
+ */
82
+ export declare const describeUnparsableFilter: (filter: unknown, reason?: string) => ParameterisedQuery;
83
+ export {};
@@ -1,4 +1,4 @@
1
- import { MemoryExecutionReason, QueryOptionExecutionTarget, QueryOptionName } from "./types";
1
+ import { DatabaseExecutionReason, MemoryExecutionReason, QueryOptionName } from "./types";
2
2
  import { QueryOptionsCollection } from "./QueryOptionsCollection";
3
3
  /**
4
4
  * One sentence per reason code, written for someone meeting pushdown for the first time.
@@ -24,25 +24,68 @@ export type ExplainedOption = {
24
24
  detail?: Record<string, unknown>;
25
25
  };
26
26
  export declare const EXECUTED_QUERIES_UNSUPPORTED = "This plugin did not report what it executed. It may not support explain.";
27
+ /**
28
+ * Why an option planned for the database did not run there. `executed` has no sentence: it needs no
29
+ * explaining, and a step made of executed options is a database step like any other.
30
+ */
31
+ export declare const DATABASE_EXECUTION_EXPLANATIONS: Record<Exclude<DatabaseExecutionReason, "executed">, string>;
32
+ /**
33
+ * Where a step ran.
34
+ *
35
+ * A database step names WHICH database, because a cross-plugin join reads from more than one — and a
36
+ * name alone does not say whether the second was PostgreSQL or PouchDB, which is the difference
37
+ * between a statement a reader recognises and one they cannot place.
38
+ */
39
+ export type ExecutedIn = {
40
+ kind: "database";
41
+ database: string;
42
+ plugin: string;
43
+ } | {
44
+ kind: "memory";
45
+ };
46
+ /** Why a step is not in the database. `executed` never appears: those steps ARE in the database. */
47
+ export type StepReason = MemoryExecutionReason | Exclude<DatabaseExecutionReason, "executed">;
48
+ /**
49
+ * One run of options in one place.
50
+ *
51
+ * A union, so a memory step cannot carry statements it could not have run and a database step cannot
52
+ * carry a reason for not being in the database.
53
+ */
27
54
  export type ExecutionStep = {
28
55
  step: number;
29
56
  of: number;
30
- executedIn: QueryOptionExecutionTarget;
31
- description: string;
57
+ executedIn: Extract<ExecutedIn, {
58
+ kind: "database";
59
+ }>;
32
60
  options: ExplainedOption[];
33
- /** Set on database steps once the plugin has reported. */
34
- executedQueries?: ExecutedQuery[];
35
- /** Set on the first database step instead, when the plugin reported nothing. */
61
+ /** What the plugin reported running. Empty when it reported nothing. */
62
+ executedQueries: ExecutedQuery[];
63
+ /** Set instead, when this plugin does not report what it executed. */
36
64
  executedQueriesUnsupported?: string;
37
- /** Set on memory steps only. */
38
- reason?: MemoryExecutionReason;
65
+ } | {
66
+ step: number;
67
+ of: number;
68
+ executedIn: Extract<ExecutedIn, {
69
+ kind: "memory";
70
+ }>;
71
+ options: ExplainedOption[];
72
+ reason?: StepReason;
39
73
  explanation?: string;
40
74
  };
75
+ export type DatabaseStep = Extract<ExecutionStep, {
76
+ executedQueries: ExecutedQuery[];
77
+ }>;
78
+ export type MemoryStep = Exclude<ExecutionStep, DatabaseStep>;
79
+ /**
80
+ * TypeScript does not narrow a union from a discriminant nested inside a property, so the two kinds
81
+ * of step need a guard rather than an inline check.
82
+ */
83
+ export declare const isDatabaseStep: (step: ExecutionStep) => step is DatabaseStep;
41
84
  export type QueryExplanationSummary = {
42
85
  database: number;
43
86
  memory: number;
44
87
  /** Deduped, in first-seen order. Empty when the whole query pushed down. */
45
- reasons: MemoryExecutionReason[];
88
+ reasons: StepReason[];
46
89
  explanation: string;
47
90
  };
48
91
  export type QueryExplanation = {
@@ -80,3 +123,22 @@ export declare const explainQuery: (options: QueryOptionsCollection<any>, contex
80
123
  * original — nothing mutates them, and copying deeper would only look safer than it is.
81
124
  */
82
125
  export declare const withExecutedQueries: (explanation: QueryExplanation, executedQueries: ExecutedQuery[]) => QueryExplanation;
126
+ /**
127
+ * Adds the step for a cross-plugin join's inner side.
128
+ *
129
+ * Appended by the executor rather than derived from the options, because the inner side's options
130
+ * live on the join, in its own collection, and were never part of this query's chain. It goes before
131
+ * the memory steps that consume it — the join cannot run until both sides are read.
132
+ */
133
+ /**
134
+ * Every statement the query ran, across every database it touched, in execution order.
135
+ *
136
+ * A step is a place, so the statements live on the steps — this is for a caller that wants them all
137
+ * without caring which plugin ran which.
138
+ */
139
+ export declare const executedQueriesOf: (explanation: QueryExplanation) => ExecutedQuery[];
140
+ export declare const withInnerSide: (explanation: QueryExplanation, innerSide: {
141
+ database: string;
142
+ plugin: string;
143
+ executedQueries: ExecutedQuery[];
144
+ }) => QueryExplanation;
@@ -1,3 +1,4 @@
1
+ export * from './describeFilter';
1
2
  export * from './explain';
2
3
  export * from './formatExplanation';
3
4
  export * from './join';
@@ -5,6 +5,7 @@ import type { DbPluginQueryEvent } from "../types";
5
5
  import type { ITranslatedValue } from "../translators/types";
6
6
  import { QueryOptionsCollection } from "./QueryOptionsCollection";
7
7
  import { QueryOptionValueMap } from "./types";
8
+ import { ExecutedQuery } from "./explain";
8
9
  export type JoinKind = "inner" | "left";
9
10
  /**
10
11
  * One side's join key, as a property path plus the resolved property.
@@ -165,7 +166,9 @@ export declare const loadJoinInnerSide: <TRoot extends {}, TShape>(event: DbPlug
165
166
  * before anything else — so it is optional, and its absence costs a wider inner read rather
166
167
  * than a wrong one.
167
168
  */
168
- outerKeys?: ReadonlySet<unknown> | null) => void;
169
+ outerKeys?: ReadonlySet<unknown> | null,
170
+ /** Where the inner read reports what it executed. Defaults to the outer read's own list. */
171
+ innerExecutedQueries?: ExecutedQuery[]) => void;
169
172
  /**
170
173
  * Interprets a join by running TWO ordinary queries through the plugin's own read path.
171
174
  *
@@ -27,13 +27,45 @@ export type QueryOptionName = keyof QueryOptionValueMap<unknown>;
27
27
  * never returns to `"database"`, so the code recorded is the FIRST cause and it stays on every
28
28
  * option after it. Reporting a later one would name a symptom of this one.
29
29
  */
30
- export type MemoryExecutionReason = "not-parsable" | "unmapped-property" | "renamed-property" | "map-rename" | "after-nearest" | "after-join" | "cross-plugin-join";
30
+ /** Why core planned an option for memory, decided when the option is added. */
31
+ export type MemoryExecutionReason = "not-parsable" | "unmapped-property" | "renamed-property" | "map-rename" | "after-nearest" | "after-join" | "cross-plugin-join" | "predicate-error" | "after-window";
32
+ /**
33
+ * What became of an option planned for the database.
34
+ *
35
+ * `missing-capability` and `engine-divergence` are the only values a plugin writes, and the only
36
+ * ones core cannot derive: an engine's capabilities are not knowable from here. SQLite's `REGEXP`
37
+ * exists if the host registered the function and not otherwise, so two instances in one process can
38
+ * differ.
39
+ *
40
+ * They are separate because a developer can act on one and not the other: no way to say it at all,
41
+ * versus an engine that would answer, and answer differently from JavaScript.
42
+ *
43
+ * `not-reached` is the rest of the database phase after either. The database stops there rather than
44
+ * carrying on: a window applied in front of a filter that was not applied returns the wrong rows.
45
+ * Core writes it, so a plugin cannot mark a cascade it does not own.
46
+ */
47
+ export type DatabaseExecutionReason = "executed" | "missing-capability" | "engine-divergence" | "not-reached";
48
+ /**
49
+ * One option, and where it runs.
50
+ *
51
+ * `target` narrows what `reason` can say, so an option cannot carry a reason that does not belong to
52
+ * the half it was planned for. An option is never moved between arms — the database arm records what
53
+ * became of it, which is what makes a redirect readable:
54
+ *
55
+ * ```ts
56
+ * option.target === "database" && option.reason === "missing-capability"
57
+ * ```
58
+ */
31
59
  export type QueryOption<T, K extends QueryOptionName> = {
32
60
  name: QueryOptionName;
33
61
  value: QueryOptionValueMap<T>[K];
34
- target: QueryOptionExecutionTarget;
35
- /** Set only when `target` is `"memory"`. */
36
- reason?: MemoryExecutionReason;
62
+ target: "database";
63
+ reason: DatabaseExecutionReason;
64
+ } | {
65
+ name: QueryOptionName;
66
+ value: QueryOptionValueMap<T>[K];
67
+ target: "memory";
68
+ reason: MemoryExecutionReason;
37
69
  };
38
70
  export type QueryOptionValueMap<T extends {}> = {
39
71
  skip: number;
@@ -0,0 +1,35 @@
1
+ import type { PropertyInfo } from '../schema/PropertyInfo';
2
+ import type { QueryField } from './query/types';
3
+ /**
4
+ * What a statement or command RETURNS, described before it runs.
5
+ *
6
+ * A plugin's builder knows this and nothing else knows it: the shape of a result comes from the
7
+ * projection, the join aliases, or the `RETURNING` list, none of which survive into the SQL as
8
+ * anything a reader could recover. So the builder states it, once, beside the statement it built.
9
+ *
10
+ * Deliberately says nothing about what anyone does with the result. It is a description, not an
11
+ * instruction — the same description serves a driver that transfers rows across a worker
12
+ * boundary, one that hands them straight back, and one that only wants to know the column order.
13
+ * A consumer that needs more turns this into whatever it needs: `buildTransferPlan` in
14
+ * `@routier/core/transfer` is one such consumer, and it is not privileged.
15
+ */
16
+ export type ResultColumn = {
17
+ /** Exact name the engine will return, including any projection or join alias. */
18
+ readonly name: string;
19
+ /**
20
+ * The schema property behind the column, or `null`.
21
+ *
22
+ * `null` for an expression — a computed value, an aggregate, anything with no declared type
23
+ * to reason from. A consumer that wants to treat the value specially needs the property; one
24
+ * that only wants names does not.
25
+ */
26
+ readonly property: PropertyInfo<any> | null;
27
+ };
28
+ /**
29
+ * The columns a `map` projection selects.
30
+ *
31
+ * Named by `sourceName`, which is what the statement actually emits; the rename to
32
+ * `destinationName` happens in the translator, after the rows come back. A field with no
33
+ * `property` is an expression.
34
+ */
35
+ export declare const mappedResultColumns: (fields: readonly QueryField[]) => ResultColumn[];
@@ -89,7 +89,6 @@ export declare class PropertyInfo<T extends {}> {
89
89
  */
90
90
  get level(): number;
91
91
  get isRenamed(): boolean;
92
- get supportsDeserialization(): boolean;
93
92
  private _getPropertyChain;
94
93
  private _needsOptionalChaining;
95
94
  private _resolvePathArray;
@@ -618,12 +618,14 @@ const isLogLevel = (value)=>typeof value === 'string' && LOG_LEVELS.includes(val
618
618
  const debug = process.env.DEBUG;
619
619
  if (debug === 'routier' || debug === '*') return 'debug';
620
620
  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
621
  if (env === 'dev' || env === 'development') return 'debug';
625
622
  }
626
- return 'silent';
623
+ // Warnings are on unless something turns them off.
624
+ //
625
+ // Routier warns when a query returns correct rows a slower way than it could, or when a filter
626
+ // compares types that can never match. Both are the caller's to act on, and a default of
627
+ // `silent` meant the only people who ever saw them were the ones who already knew to look.
628
+ return 'warn';
627
629
  };
628
630
  let level = resolveLevel();
629
631
  let rank = RANK[level];
@@ -1779,12 +1781,6 @@ class SchemaComputed extends SchemaBase {
1779
1781
  ;// CONCATENATED MODULE: ./src/schema/PropertyInfo.ts
1780
1782
 
1781
1783
 
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
1784
  /**
1789
1785
  * Represents metadata and utilities for a property in a schema, including its type, name, parent, children, and serialization details.
1790
1786
  */ class PropertyInfo {
@@ -1904,9 +1900,6 @@ const SUPPORTED_DESERIALIZATION_TYPES = new Set([
1904
1900
  get isRenamed() {
1905
1901
  return !!this.from;
1906
1902
  }
1907
- get supportsDeserialization() {
1908
- return this.valueDeserializer != null || SUPPORTED_DESERIALIZATION_TYPES.has(this.type);
1909
- }
1910
1903
  _getPropertyChain() {
1911
1904
  if (this._propertyChainCache) {
1912
1905
  return this._propertyChainCache;
@@ -2159,7 +2152,7 @@ const SUPPORTED_DESERIALIZATION_TYPES = new Set([
2159
2152
  if (this.type === types/* .SchemaTypes.Boolean */.L.Boolean) {
2160
2153
  return Boolean(value);
2161
2154
  }
2162
- throw new Error(`Unsupported deserialization for type. Type: ${this.type}`);
2155
+ return value;
2163
2156
  }
2164
2157
  }
2165
2158