litedbmodel 2.0.1 → 2.1.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 (97) hide show
  1. package/dist/decorators.d.ts.map +1 -1
  2. package/dist/decorators.js +44 -24
  3. package/dist/decorators.js.map +1 -1
  4. package/dist/drivers/mysql.d.ts.map +1 -1
  5. package/dist/drivers/mysql.js +6 -0
  6. package/dist/drivers/mysql.js.map +1 -1
  7. package/dist/drivers/postgres.d.ts.map +1 -1
  8. package/dist/drivers/postgres.js +7 -0
  9. package/dist/drivers/postgres.js.map +1 -1
  10. package/dist/drivers/sqlite.d.ts +2 -0
  11. package/dist/drivers/sqlite.d.ts.map +1 -1
  12. package/dist/drivers/sqlite.js +37 -2
  13. package/dist/drivers/sqlite.js.map +1 -1
  14. package/dist/scp/authoring.d.ts +66 -3
  15. package/dist/scp/authoring.d.ts.map +1 -1
  16. package/dist/scp/authoring.js +194 -5
  17. package/dist/scp/authoring.js.map +1 -1
  18. package/dist/scp/catalog.d.ts +6 -2
  19. package/dist/scp/catalog.d.ts.map +1 -1
  20. package/dist/scp/catalog.js +17 -2
  21. package/dist/scp/catalog.js.map +1 -1
  22. package/dist/scp/codegen.d.ts +132 -26
  23. package/dist/scp/codegen.d.ts.map +1 -1
  24. package/dist/scp/codegen.js +546 -35
  25. package/dist/scp/codegen.js.map +1 -1
  26. package/dist/scp/coltype.d.ts +124 -0
  27. package/dist/scp/coltype.d.ts.map +1 -0
  28. package/dist/scp/coltype.js +408 -0
  29. package/dist/scp/coltype.js.map +1 -0
  30. package/dist/scp/dialect.d.ts +12 -3
  31. package/dist/scp/dialect.d.ts.map +1 -1
  32. package/dist/scp/dialect.js +12 -3
  33. package/dist/scp/dialect.js.map +1 -1
  34. package/dist/scp/fragment/assemble.d.ts.map +1 -1
  35. package/dist/scp/fragment/assemble.js +10 -2
  36. package/dist/scp/fragment/assemble.js.map +1 -1
  37. package/dist/scp/fragment/compile-pg.js +4 -4
  38. package/dist/scp/guard.d.ts +1 -1
  39. package/dist/scp/guard.d.ts.map +1 -1
  40. package/dist/scp/guard.js +6 -0
  41. package/dist/scp/guard.js.map +1 -1
  42. package/dist/scp/index.cjs +10003 -4917
  43. package/dist/scp/index.d.ts +8 -5
  44. package/dist/scp/index.d.ts.map +1 -1
  45. package/dist/scp/index.js +35 -9
  46. package/dist/scp/index.js.map +1 -1
  47. package/dist/scp/index.mjs +1343 -213
  48. package/dist/scp/makesql/authoring-compile.d.ts.map +1 -1
  49. package/dist/scp/makesql/authoring-compile.js +11 -0
  50. package/dist/scp/makesql/authoring-compile.js.map +1 -1
  51. package/dist/scp/makesql/compile-select.d.ts +8 -1
  52. package/dist/scp/makesql/compile-select.d.ts.map +1 -1
  53. package/dist/scp/makesql/compile-select.js +1 -1
  54. package/dist/scp/makesql/compile-select.js.map +1 -1
  55. package/dist/scp/makesql/index.d.ts +2 -3
  56. package/dist/scp/makesql/index.d.ts.map +1 -1
  57. package/dist/scp/makesql/index.js +6 -6
  58. package/dist/scp/makesql/index.js.map +1 -1
  59. package/dist/scp/makesql/json-batch.d.ts.map +1 -1
  60. package/dist/scp/makesql/json-batch.js +6 -1
  61. package/dist/scp/makesql/json-batch.js.map +1 -1
  62. package/dist/scp/makesql/outtype.d.ts +99 -0
  63. package/dist/scp/makesql/outtype.d.ts.map +1 -0
  64. package/dist/scp/makesql/outtype.js +328 -0
  65. package/dist/scp/makesql/outtype.js.map +1 -0
  66. package/dist/scp/makesql/pool-executor.d.ts +70 -0
  67. package/dist/scp/makesql/pool-executor.d.ts.map +1 -1
  68. package/dist/scp/makesql/pool-executor.js +73 -5
  69. package/dist/scp/makesql/pool-executor.js.map +1 -1
  70. package/dist/scp/makesql/static-bundle.d.ts +41 -30
  71. package/dist/scp/makesql/static-bundle.d.ts.map +1 -1
  72. package/dist/scp/makesql/static-bundle.js +351 -131
  73. package/dist/scp/makesql/static-bundle.js.map +1 -1
  74. package/dist/scp/makesql/tx.d.ts +1 -1
  75. package/dist/scp/makesql/tx.d.ts.map +1 -1
  76. package/dist/scp/makesql/tx.js +48 -3
  77. package/dist/scp/makesql/tx.js.map +1 -1
  78. package/dist/scp/makesql/writeouttype.d.ts +65 -0
  79. package/dist/scp/makesql/writeouttype.d.ts.map +1 -0
  80. package/dist/scp/makesql/writeouttype.js +194 -0
  81. package/dist/scp/makesql/writeouttype.js.map +1 -0
  82. package/dist/scp/relation.d.ts +15 -1
  83. package/dist/scp/relation.d.ts.map +1 -1
  84. package/dist/scp/relation.js +61 -2
  85. package/dist/scp/relation.js.map +1 -1
  86. package/dist/scp/runtime.d.ts +17 -5
  87. package/dist/scp/runtime.d.ts.map +1 -1
  88. package/dist/scp/runtime.js +55 -14
  89. package/dist/scp/runtime.js.map +1 -1
  90. package/docs/BENCHMARK.md +58 -56
  91. package/docs/benchmark-chart.svg +166 -166
  92. package/docs/proposal/litedbmodel-v2-scp-architecture.md +51 -0
  93. package/package.json +8 -2
  94. package/dist/scp/makesql/ir.d.ts +0 -42
  95. package/dist/scp/makesql/ir.d.ts.map +0 -1
  96. package/dist/scp/makesql/ir.js +0 -66
  97. package/dist/scp/makesql/ir.js.map +0 -1
@@ -0,0 +1,328 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — codegen `outType` derivation (spec §4.1; issues #58/#56).
4
+ *
5
+ * bc's TYPED-RAW de-box emitters (`rust-typed-raw` / `go-typed-raw` / `typescript-typed`) require
6
+ * each read node to carry an `outType` and the component an `outputType` (bc portable type
7
+ * notation). WITHOUT them the emitter hard-fails ("nothing to de-box") — the correct fail-closed
8
+ * behavior. This module derives those annotations for a READ component from:
9
+ *
10
+ * 1. the per-node SELECT projection (`table` + `select` ports) → a row `obj` type, each column's
11
+ * bc scalar resolved from its SQL type (the schema/DDL SoT) via {@link sqlTypeToBcScalar};
12
+ * 2. the node cardinality (a Select node returns a row LIST → `{arr:rowObj}`; a Count → `int`; a
13
+ * `.map` node wraps its per-element handler result → `{arr:<elem>}`);
14
+ * 3. the component `output` Φ-expression, walked to compose the `outputType` from the node types
15
+ * (`{ref:[nodeId]}` → that node's outType; `{obj:{…}}`/`{arr:…}`/`{opt:…}` recurse).
16
+ *
17
+ * Spec §4.1 discipline: an ambiguous/unmappable projection is a HARD ERROR (no-assume,
18
+ * no-fallback) — a `*` projection, a computed/aliased column, or a column with no schema type
19
+ * THROWS. It is NEVER degraded to a boxed/untyped output; that would silently defeat the de-box.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.parseProjectionColumn = parseProjectionColumn;
23
+ exports.nodeOutType = nodeOutType;
24
+ exports.crudNodeAsType = crudNodeAsType;
25
+ exports.deriveReadOutTypes = deriveReadOutTypes;
26
+ const coltype_1 = require("../coltype");
27
+ const tx_1 = require("./tx");
28
+ /**
29
+ * Narrow a {@link BcScalar} to a bc {@link PortableScalarType}. `BcScalar`'s members
30
+ * (`string|int|float|bool|null`) are exactly bc 0.3.0's portable scalar notation, so this is an
31
+ * identity narrow. DATE/TIMESTAMP columns map to `string` at the `sqlTypeToBcScalar` layer (spec
32
+ * §4.1 owner decision; bc has no `date` scalar — behavior-contracts#84 deferred), so no `date`
33
+ * scalar ever reaches here.
34
+ */
35
+ function toPortableScalar(scalar, _table, _column) {
36
+ return scalar;
37
+ }
38
+ function isMap(n) {
39
+ return 'map' in n;
40
+ }
41
+ /** The `{component, ports}` of a body node (unwrapping a `.map`). */
42
+ function nodeRef(n) {
43
+ return isMap(n) ? { component: n.map.component, ports: n.map.ports } : { component: n.component, ports: n.ports };
44
+ }
45
+ function opKey(node) {
46
+ if (node === null || typeof node !== 'object' || Array.isArray(node))
47
+ return undefined;
48
+ const keys = Object.keys(node);
49
+ return keys.length === 1 ? keys[0] : undefined;
50
+ }
51
+ /** Read a required literal string port, or throw (the projection SoT must be a literal in the IR). */
52
+ function stringPort(ports, name) {
53
+ const v = ports[name];
54
+ if (v === undefined)
55
+ return undefined;
56
+ if (typeof v !== 'string') {
57
+ throw new Error(`outtype: port '${name}' must be a literal string in the IR (got ${JSON.stringify(v)})`);
58
+ }
59
+ return v;
60
+ }
61
+ /** Read a literal `{arr:[str,…]}` string-list port (the SELECT projection). */
62
+ function stringArrayPort(ports, name) {
63
+ const v = ports[name];
64
+ if (v === undefined)
65
+ return undefined;
66
+ if (typeof v === 'object' && v !== null && 'arr' in v && Array.isArray(v.arr)) {
67
+ return v.arr.map((e) => {
68
+ if (typeof e !== 'string')
69
+ throw new Error(`outtype: '${name}' entries must be literal strings (got ${JSON.stringify(e)})`);
70
+ return e;
71
+ });
72
+ }
73
+ throw new Error(`outtype: port '${name}' must be an {arr:[…]} literal in the IR (got ${JSON.stringify(v)})`);
74
+ }
75
+ /**
76
+ * The SINGLE projection-column parser (issue #59) — shared by BOTH the codegen `outType` derivation
77
+ * and the TS read-path materializer derivation so the two CANNOT diverge (the recurring source of
78
+ * silent-rounding leaks). Classifies ONE `select`-list entry:
79
+ * - bare `col` → `{ kind:'column', underlying:'col', outputKey:'col' }`.
80
+ * - qualified `t.col` → strip qualifier → `underlying:'col', outputKey:'col'`.
81
+ * - aliased `col AS b` / `t.col AS b` → `underlying:'col', outputKey:'b'` (the driver row key).
82
+ * - computed `COUNT(*)`, `NOW()`, `x::uuid`, `x+1`, aliased or not → `{ kind:'computed', text }`.
83
+ * - `*` / `t.*` → HARD ERROR (the concrete column list is unknown).
84
+ * A SCHEMA-column entry MUST be typed against the declaration (a caller resolves + fail-closes on an
85
+ * undeclared column → never a silent rounded-i64 leak). A COMPUTED entry has no schema column to
86
+ * round: the read path leaves it raw; the codegen path (which needs every struct field typed) rejects
87
+ * it. This ONE parser guarantees every shape is classified identically for both paths.
88
+ */
89
+ function parseProjectionColumn(col, table, at) {
90
+ const raw = col.trim();
91
+ if (raw === '*' || raw.endsWith('.*')) {
92
+ throw new Error(`outtype: ${at}: SELECT on '${table}' projects '${raw}' (a wildcard). A typed de-box needs the ` +
93
+ `concrete column list to build the row struct + type each column — spec §4.1 is column-typed. ` +
94
+ `Project explicit columns (no-assume, no-fallback).`);
95
+ }
96
+ // Split off an `AS <alias>` (case-insensitive; alias must be a bare identifier).
97
+ let expr = raw;
98
+ let alias;
99
+ const asMatch = /^(.*?)\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i.exec(raw);
100
+ if (asMatch !== null) {
101
+ expr = asMatch[1].trim();
102
+ alias = asMatch[2];
103
+ }
104
+ // A bare or qualified column reference — `col` or `qual.col` (identifiers only) — is a SCHEMA
105
+ // column. The qualifier (if present) names the column's OWNER table (a JOIN column), against which
106
+ // its type resolves; without a qualifier the column belongs to the node's base table.
107
+ const refMatch = /^(?:([A-Za-z_][A-Za-z0-9_]*)\.)?([A-Za-z_][A-Za-z0-9_]*)$/.exec(expr);
108
+ if (refMatch !== null) {
109
+ const qualifier = refMatch[1];
110
+ const underlying = refMatch[2];
111
+ return { kind: 'column', underlying, outputKey: alias ?? underlying, ...(qualifier !== undefined ? { qualifier } : {}) };
112
+ }
113
+ // Anything else (a function call `f(x)`, an aggregate `COUNT(*)`, a cast `x::uuid`, arithmetic, a
114
+ // literal) is a COMPUTED expression — no underlying schema column, so it cannot round an i64. The
115
+ // read path leaves it raw; the codegen path rejects it (it needs a concrete field type).
116
+ return { kind: 'computed', text: raw };
117
+ }
118
+ /**
119
+ * The row `obj` type of a SELECT projection: `{obj:{outputKey: <bcScalar>, …}}`. Each column is
120
+ * resolved ONCE via the SHARED {@link parseProjectionColumn} (bare / qualified / aliased) and its SQL
121
+ * type (from the schema SoT) yields BOTH the bc scalar (this outType, for codegen) AND — written into
122
+ * the `materializers` accumulator — the TS read-path {@link MaterializeClass} (INT32/INT64/date/bool).
123
+ * This is the SINGLE column-type resolution the whole read pipeline consumes: codegen reads the
124
+ * `obj`; the runtime read path reads `materializers`. They cannot diverge — they are two projections
125
+ * of the ONE resolution. A `*` / absent projection, a computed column, a duplicate OUTPUT key, or an
126
+ * undeclared underlying column is a HARD ERROR (no-assume, no-fallback) — for BOTH consumers.
127
+ */
128
+ function rowObjType(table, projection, resolveColumnType, at, materializers) {
129
+ if (projection === undefined || projection.length === 0) {
130
+ throw new Error(`outtype: ${at}: SELECT on '${table}' has no explicit column projection ('*' / empty). A typed ` +
131
+ `de-box needs the concrete column list to build the row struct — spec §4.1 is column-typed. ` +
132
+ `Project explicit columns (no-assume, no-fallback).`);
133
+ }
134
+ const obj = {};
135
+ for (const col of projection) {
136
+ const entry = parseProjectionColumn(col, table, at);
137
+ // A computed expression has no concrete struct field type — HARD ERROR (spec §4.1 no-assume).
138
+ // The read path never reaches a separate lenient pass now; `*`/computed fail here for BOTH.
139
+ if (entry.kind === 'computed') {
140
+ throw new Error(`outtype: ${at}: projected expression '${entry.text}' on '${table}' is computed (function / ` +
141
+ `aggregate / cast / literal) and cannot be typed into a concrete row struct field. Typed ` +
142
+ `de-box (spec §4.1) requires bare/qualified/aliased schema columns. No-assume, no-fallback.`);
143
+ }
144
+ const { underlying, outputKey, qualifier } = entry;
145
+ if (outputKey in obj)
146
+ throw new Error(`outtype: ${at}: duplicate projected column key '${outputKey}' on '${table}'`);
147
+ // Resolve against the qualifier's table (a JOIN column) if present, else the node's base table.
148
+ const owner = qualifier ?? table;
149
+ // ONE resolution of the SQL type → both the bc scalar AND the materialize class. resolveColumnType
150
+ // throws on an undeclared column, sqlType* throw on an unknown SQL type — fail-closed by
151
+ // construction on the UNDERLYING column, keyed by the OUTPUT column (the driver's row key).
152
+ const sqlType = resolveColumnType(owner, underlying);
153
+ obj[outputKey] = toPortableScalar((0, coltype_1.sqlTypeToBcScalar)(sqlType), owner, underlying);
154
+ const klass = (0, coltype_1.sqlTypeToMaterializeClass)(sqlType);
155
+ if (klass !== 'passthrough')
156
+ materializers[outputKey] = klass; // omit passthrough (no-op coercion)
157
+ }
158
+ return { obj };
159
+ }
160
+ /**
161
+ * The outType + read-path materializers of ONE read body node — derived from the SINGLE column-type
162
+ * resolution ({@link rowObjType}). A `Select` returns a ROW LIST → `{arr:rowObj}`; a `Count` a single
163
+ * `int` (a scalar, no per-column map). A `.map` node wraps its per-element Select result. An
164
+ * unrecognized component throws (typed read de-box covers only the SQL read catalog).
165
+ */
166
+ function nodeTypes(node, resolveColumnType) {
167
+ const { component, ports } = nodeRef(node);
168
+ const at = `node '${node.id}'`;
169
+ if (component === 'Count')
170
+ return { outType: 'int', materializers: {} };
171
+ if (component === 'Select') {
172
+ const table = stringPort(ports, 'table');
173
+ if (table === undefined)
174
+ throw new Error(`outtype: ${at}: Select node requires a literal 'table' port`);
175
+ const projection = stringArrayPort(ports, 'select');
176
+ const materializers = {};
177
+ const row = rowObjType(table, projection, resolveColumnType, at, materializers);
178
+ // A `.map` node iterates a list and invokes the inner component per element (row LIST per element
179
+ // → `{arr:{arr:rowObj}}`); a plain Select node returns the row list `{arr:rowObj}`.
180
+ const outType = isMap(node) ? { arr: { arr: row } } : { arr: row };
181
+ return { outType, materializers };
182
+ }
183
+ throw new Error(`outtype: ${at}: component '${component}' has no typed outType (typed read de-box covers Select/Count only). ` +
184
+ `A write / unknown node cannot be de-boxed here — no-assume, no-fallback.`);
185
+ }
186
+ /** The outType of ONE read body node (thin wrapper over {@link nodeTypes} for external callers). */
187
+ function nodeOutType(node, resolveColumnType) {
188
+ return nodeTypes(node, resolveColumnType).outType;
189
+ }
190
+ /**
191
+ * Derive the component `outputType` by walking the `output` Φ-expression against a `nodeId →
192
+ * outType` map. `{ref:[id]}` resolves to that node's outType; `{obj:{k:expr,…}}` /
193
+ * `{arr:expr}` / `{opt:expr}` recurse structurally. A `ref` to an unknown id, or an operator the
194
+ * typed output path does not cover, is a HARD ERROR (no-assume, no-fallback) — the output must be
195
+ * a pure composition of typed node results, never a boxed dynamic tree.
196
+ */
197
+ function outputType(output, byNode, at) {
198
+ const op = opKey(output);
199
+ if (op === 'ref' || op === 'refOpt') {
200
+ const path = output[op];
201
+ if (!Array.isArray(path) || path.length === 0 || typeof path[0] !== 'string') {
202
+ throw new Error(`outtype: ${at}: a '${op}' output must reference a node id`);
203
+ }
204
+ // A node-result ref is a single-segment path `[nodeId]`. A deeper path (field access on a node
205
+ // result) cannot be typed here without walking into the row struct — out of the bench's scope.
206
+ if (path.length !== 1 || path[0].startsWith('$') || path[0] === tx_1.IN_SENTINEL) {
207
+ throw new Error(`outtype: ${at}: output ref path ${JSON.stringify(path)} is not a bare node-result reference; ` +
208
+ `field access / input refs at the output position are not supported by the typed de-box path. No-assume, no-fallback.`);
209
+ }
210
+ const t = byNode.get(path[0]);
211
+ if (t === undefined)
212
+ throw new Error(`outtype: ${at}: output references node '${path[0]}' which has no derived outType`);
213
+ return t;
214
+ }
215
+ if (op === 'obj') {
216
+ const obj = output.obj;
217
+ if (obj === null || typeof obj !== 'object' || Array.isArray(obj))
218
+ throw new Error(`outtype: ${at}: 'obj' output must be a record`);
219
+ const out = {};
220
+ for (const [k, expr] of Object.entries(obj)) {
221
+ if (k === '__proto__')
222
+ throw new Error(`outtype: ${at}: '__proto__' key forbidden in output obj`);
223
+ out[k] = outputType(expr, byNode, `${at}.obj.${k}`);
224
+ }
225
+ return { obj: out };
226
+ }
227
+ if (op === 'arr') {
228
+ const arr = output.arr;
229
+ // An `{arr:<expr>}` output whose single element expr types the element (the typed corpus uses
230
+ // homogeneous arrays). An `{arr:[…]}` literal list is not a typed homogeneous array here.
231
+ if (Array.isArray(arr))
232
+ throw new Error(`outtype: ${at}: an '{arr:[…]}' literal list output cannot be typed as a homogeneous array. No-assume, no-fallback.`);
233
+ return { arr: outputType(arr, byNode, `${at}.arr`) };
234
+ }
235
+ if (op === 'opt') {
236
+ const inner = output.opt;
237
+ return { opt: outputType(inner, byNode, `${at}.opt`) };
238
+ }
239
+ throw new Error(`outtype: ${at}: output expression ${JSON.stringify(output)} is not a typed composition ` +
240
+ `(ref / obj / arr / opt of node results). The typed de-box path does not build a dynamic ` +
241
+ `Value output tree — no-assume, no-fallback.`);
242
+ }
243
+ /**
244
+ * PRE-COMPILE node-output type (bc 0.8.0 SA5 / #12): the determined `PortableType` a litedbmodel CRUD
245
+ * leaf annotates its authored node with, via bc's `.as(t)` recording API, so `compileBehaviors`'
246
+ * all-nodes-typed gate (`UNTYPED_NODE`) passes. Computed from the RAW authored ports (a plain `table`
247
+ * string + a plain `select` / `returning` column list — the same projection SoT `deriveReadOutTypes`
248
+ * reads post-compile, just moved to authoring time) + the model's inline `static columns` resolver.
249
+ *
250
+ * - `Select` → the row LIST `{arr:{obj:{outKey:<scalar>,…}}}` from the `select` projection. This is
251
+ * the value `.as` takes in BOTH positions: a top-level Select node's `outType` is this list; a
252
+ * mapped Select's `.as` records it as the map ELEMENT type (bc convention — the per-parent row list).
253
+ * - `Count` → NOT handled here: its output is the static `int` catalog `elemType` (no `.as`).
254
+ * - `Insert`/`Update`/`Delete` → the RETURNING row list `{arr:{obj:…}}` from the `returning` port
255
+ * (bare-column list). No `returning` → an EMPTY row list `{arr:{obj:{}}}` (the write surfaces rows
256
+ * only via RETURNING; a no-RETURNING write yields empty rows — mirrors `writeouttype.ts`).
257
+ *
258
+ * Schema columns are parsed by the SAME {@link parseProjectionColumn} the read/codegen paths use and
259
+ * typed via the resolver (an undeclared column fails closed here at authoring — earlier than the
260
+ * post-compile derivation). A COMPUTED projected column (`COUNT(*) as n`, a cast, a literal) is OMITTED
261
+ * from the typed row struct — the read path leaves a computed column RAW (#59: "the read path leaves it
262
+ * raw; the codegen path rejects it"), so its field is absent from the de-box row type. This keeps the
263
+ * node's outType DETERMINED (gate passes) while preserving #59's raw-computed read behavior; the typed
264
+ * codegen path independently rejects a computed projection later (it needs every field typed). The
265
+ * value is the OUTPUT-row type only; SQL stays opaque text on the makeSQL leaf (types the node OUTPUT,
266
+ * never the SQL).
267
+ */
268
+ function crudNodeAsType(component, ports, resolveColumnType, at) {
269
+ const table = ports['table'];
270
+ if (typeof table !== 'string') {
271
+ throw new Error(`outtype: ${at}: ${component} node requires a literal 'table' string port to type its output (got ${JSON.stringify(table)})`);
272
+ }
273
+ if (component === 'Select') {
274
+ const select = ports['select'];
275
+ if (!Array.isArray(select) || select.length === 0) {
276
+ throw new Error(`outtype: ${at}: Select has no explicit column projection ('*' / empty). A typed de-box needs the ` +
277
+ `concrete column list to build the row struct — spec §4.1 is column-typed. Project explicit columns.`);
278
+ }
279
+ const obj = {};
280
+ for (const raw of select) {
281
+ if (typeof raw !== 'string')
282
+ throw new Error(`outtype: ${at}: Select 'select' entries must be literal strings (got ${JSON.stringify(raw)})`);
283
+ const parsed = parseProjectionColumn(raw, table, at);
284
+ if (parsed.kind === 'computed')
285
+ continue; // computed column: read raw, omitted from the typed row (SA5-determined without it)
286
+ const { underlying, outputKey, qualifier } = parsed;
287
+ if (outputKey in obj)
288
+ throw new Error(`outtype: ${at}: duplicate projected column key '${outputKey}' on '${table}'`);
289
+ obj[outputKey] = toPortableScalar((0, coltype_1.sqlTypeToBcScalar)(resolveColumnType(qualifier ?? table, underlying)), qualifier ?? table, underlying);
290
+ }
291
+ return { arr: { obj } };
292
+ }
293
+ if (component === 'Insert' || component === 'Update' || component === 'Delete') {
294
+ // The RETURNING port is a single comma-separated bare-column string (`'id, author_id'`) or absent.
295
+ const returning = ports['returning'];
296
+ if (returning === undefined)
297
+ return { arr: { obj: {} } };
298
+ if (typeof returning !== 'string') {
299
+ throw new Error(`outtype: ${at}: ${component} 'returning' port must be a literal string (got ${JSON.stringify(returning)})`);
300
+ }
301
+ const cols = returning.split(',').map((c) => c.trim()).filter((c) => c.length > 0);
302
+ if (cols.length === 0)
303
+ return { arr: { obj: {} } };
304
+ return { arr: rowObjType(table, cols, resolveColumnType, at, {}) };
305
+ }
306
+ throw new Error(`outtype: ${at}: no pre-compile output type for component '${component}' (typed CRUD covers Select/Insert/Update/Delete; Count is static via catalog elemType).`);
307
+ }
308
+ /**
309
+ * Per-node `outType` (keyed by body node id) + the component `outputType`, derived for a READ
310
+ * component (spec §4.1). `cond` nodes are skipped for the per-node map but a `cond` at the OUTPUT
311
+ * position (a shared-branch merge) would be handled by {@link outputType} if reached — the bench's
312
+ * read outputs are ref / obj compositions of Select nodes. Any ambiguity throws (fail-closed).
313
+ */
314
+ function deriveReadOutTypes(component, resolveColumnType) {
315
+ const byNode = new Map();
316
+ const materializersByNode = new Map();
317
+ for (const n of component.body) {
318
+ if ('cond' in n)
319
+ continue; // a cond node carries no SELECT projection; it is typed by its branch
320
+ // ONE resolution per node → the outType (codegen) AND the read-path materializers (runtime).
321
+ const t = nodeTypes(n, resolveColumnType);
322
+ byNode.set(n.id, t.outType);
323
+ if (Object.keys(t.materializers).length > 0)
324
+ materializersByNode.set(n.id, t.materializers);
325
+ }
326
+ return { byNode, outputType: outputType(component.output, byNode, `component '${component.name}' output`), materializersByNode };
327
+ }
328
+ //# sourceMappingURL=outtype.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outtype.js","sourceRoot":"","sources":["../../../src/scp/makesql/outtype.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,38 @@
17
17
  * force either into a consumer that only uses the sync better-sqlite3 conformance path.
18
18
  */
19
19
  import type { SqlExecutorAsync } from './static-bundle';
20
+ /** The minimal `pg.types` surface: register a per-OID text parser. */
21
+ export interface PgTypesLike {
22
+ setTypeParser(oid: number, parser: (value: string) => unknown): void;
23
+ }
24
+ /**
25
+ * Register `pg` type parsers so the read-path de-box (issue #59) gets coercible values: the
26
+ * DATE/TIMESTAMP/TIMESTAMPTZ/TIME family is returned as its NATIVE TEXTUAL string (NOT a JS Date),
27
+ * honoring the `date→string` outType and carrying the TZ for timestamptz. int8 already arrives as a
28
+ * string (pg default), so it needs no parser. Idempotent. Call ONCE, before building the pool, from
29
+ * the consumer that owns the `pg` module (`import { types } from 'pg'; configurePgDeboxTypeParsers(types)`).
30
+ *
31
+ * WHY the GLOBAL parser (a documented, deliberate exception): `pg`'s default DATE parser builds a JS
32
+ * `Date` at LOCAL midnight, which shifts the UTC CALENDAR DAY (e.g. `2026-07-14` → a Date whose UTC
33
+ * day is `2026-07-13`). That loss happens INSIDE the driver, BEFORE the materializer sees the value —
34
+ * so materializer-side coercion CANNOT recover the correct calendar day from the already-shifted
35
+ * Date. Reading the native text (this parser) is the only lossless option, and `pg` exposes type
36
+ * parsers only at module (process-global) scope. It is set ONCE at pool creation, not per read. The
37
+ * materializer's `Date → ISO string` path remains as a defensive fallback for any driver/config that
38
+ * still slips a Date through, but the correct-day guarantee for pg DATE comes from this parser.
39
+ */
40
+ export declare function configurePgDeboxTypeParsers(types: PgTypesLike): void;
41
+ /**
42
+ * The `mysql2` pool options the read-path de-box (issue #59) requires: `supportBigNumbers` +
43
+ * `bigNumberStrings` so BIGINT arrives as an EXACT string (→ bigint; a plain number would already
44
+ * have rounded it), and `dateStrings` so the DATE/TIMESTAMP/DATETIME family arrives as its native
45
+ * textual string (→ the `date→string` outType, NOT a JS Date). Spread into `mysql.createPool(...)`.
46
+ */
47
+ export declare const mysqlDeboxPoolOptions: {
48
+ readonly supportBigNumbers: true;
49
+ readonly bigNumberStrings: true;
50
+ readonly dateStrings: true;
51
+ };
20
52
  /** The minimal `pg.Pool` surface we need: `query(text, values)` resolving `{ rows }`. */
21
53
  export interface PgPoolLike {
22
54
  query(text: string, values?: unknown[]): Promise<{
@@ -43,5 +75,43 @@ export declare function pgPoolExecutor(pool: PgPoolLike): SqlExecutorAsync;
43
75
  *
44
76
  * Recommend `connectionLimit` ≥ the plan's `concurrency` (default 16).
45
77
  */
78
+ /** Minimal `pg` module surface: a `Pool` ctor + the global `types.setTypeParser`. */
79
+ export interface PgModuleLike {
80
+ Pool: new (config: Record<string, unknown>) => PgPoolLike & {
81
+ end?: () => Promise<void>;
82
+ };
83
+ types: PgTypesLike;
84
+ }
85
+ /** Minimal `mysql2/promise` module surface: `createPool`. */
86
+ export interface Mysql2ModuleLike {
87
+ createPool(config: Record<string, unknown>): MysqlPoolLike & {
88
+ end?: () => Promise<void>;
89
+ };
90
+ }
91
+ /**
92
+ * Build a PG pool + executor with the read-path de-box wired IN (issue #59): registers the pg date
93
+ * type parsers (DATE/TIMESTAMP family → native textual string) globally, then builds the pool.
94
+ * int8 already arrives as a string on pg. Returns `{ pool, exec }` — pass `exec` to
95
+ * `executeBehaviorAsync`. This is the production async path's de-box-correct entry (no hand-spread
96
+ * options).
97
+ */
98
+ export declare function pgDeboxExecutor(pg: PgModuleLike, config: Record<string, unknown>): {
99
+ pool: PgPoolLike & {
100
+ end?: () => Promise<void>;
101
+ };
102
+ exec: SqlExecutorAsync;
103
+ };
104
+ /**
105
+ * Build a MySQL pool + executor with the read-path de-box wired IN (issue #59): the pool carries
106
+ * {@link mysqlDeboxPoolOptions} (`supportBigNumbers + bigNumberStrings` so BIGINT → exact string,
107
+ * `dateStrings` so the date family → string) — options that MUST be set at pool construction (a
108
+ * rounded BIGINT cannot be un-rounded post-hoc). Returns `{ pool, exec }` for `executeBehaviorAsync`.
109
+ */
110
+ export declare function mysqlDeboxExecutor(mysql2: Mysql2ModuleLike, config: Record<string, unknown>): {
111
+ pool: MysqlPoolLike & {
112
+ end?: () => Promise<void>;
113
+ };
114
+ exec: SqlExecutorAsync;
115
+ };
46
116
  export declare function mysqlPoolExecutor(pool: MysqlPoolLike): SqlExecutorAsync;
47
117
  //# sourceMappingURL=pool-executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pool-executor.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/pool-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CACvF;AAED,kGAAkG;AAClG,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;CACvF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,CAKjE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,CAKvE"}
1
+ {"version":3,"file":"pool-executor.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/pool-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAkBxD,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;CACtE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAOpE;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;CAIxB,CAAC;AAEX,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CACvF;AAED,kGAAkG;AAClG,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;CACvF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,CAKjE;AAED;;;;;;GAMG;AAQH,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IAC1F,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;CAC5F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,UAAU,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAI/J;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,aAAa,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAG7K;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,CAKvE"}
@@ -18,8 +18,61 @@
18
18
  * force either into a consumer that only uses the sync better-sqlite3 conformance path.
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.mysqlDeboxPoolOptions = void 0;
22
+ exports.configurePgDeboxTypeParsers = configurePgDeboxTypeParsers;
21
23
  exports.pgPoolExecutor = pgPoolExecutor;
24
+ exports.pgDeboxExecutor = pgDeboxExecutor;
25
+ exports.mysqlDeboxExecutor = mysqlDeboxExecutor;
22
26
  exports.mysqlPoolExecutor = mysqlPoolExecutor;
27
+ // ── TS read-path driver de-box config (issue #59) ─────────────────────────────
28
+ // The read-path materializer (`materializeCell`) coerces each driver cell to the JS form its SQL
29
+ // column type declares (BIGINT→bigint, DATE→string, …). For that to be LOSSLESS the driver must
30
+ // hand the value over in a coercible form:
31
+ // - PG: int8 (OID 20) already arrives as a STRING; DATE/TIMESTAMP/TIMESTAMPTZ arrive as a JS
32
+ // Date by default (TZ-shifted). `configurePgDeboxTypeParsers` registers `pg` type parsers so
33
+ // the date family arrives as its NATIVE TEXTUAL form (carrying TZ for timestamptz) — the
34
+ // value-preserving string the materializer expects. This is a GLOBAL `pg` setting (pg has no
35
+ // per-pool parser), applied once by the consumer that owns the pg import.
36
+ // - MySQL: BIGINT arrives as a rounded JS number by default (LOSSY). The pool MUST be built with
37
+ // `mysqlDeboxPoolOptions` (`supportBigNumbers + bigNumberStrings` so BIGINT→string, and
38
+ // `dateStrings` so the date family→string). `mysqlDeboxPoolOptions` is those options.
39
+ /** PG type OIDs for the date/time family + int8 (bigint). */
40
+ const PG_OID = { INT8: 20, DATE: 1082, TIMESTAMP: 1114, TIMESTAMPTZ: 1184, TIME: 1083, TIMETZ: 1266 };
41
+ /**
42
+ * Register `pg` type parsers so the read-path de-box (issue #59) gets coercible values: the
43
+ * DATE/TIMESTAMP/TIMESTAMPTZ/TIME family is returned as its NATIVE TEXTUAL string (NOT a JS Date),
44
+ * honoring the `date→string` outType and carrying the TZ for timestamptz. int8 already arrives as a
45
+ * string (pg default), so it needs no parser. Idempotent. Call ONCE, before building the pool, from
46
+ * the consumer that owns the `pg` module (`import { types } from 'pg'; configurePgDeboxTypeParsers(types)`).
47
+ *
48
+ * WHY the GLOBAL parser (a documented, deliberate exception): `pg`'s default DATE parser builds a JS
49
+ * `Date` at LOCAL midnight, which shifts the UTC CALENDAR DAY (e.g. `2026-07-14` → a Date whose UTC
50
+ * day is `2026-07-13`). That loss happens INSIDE the driver, BEFORE the materializer sees the value —
51
+ * so materializer-side coercion CANNOT recover the correct calendar day from the already-shifted
52
+ * Date. Reading the native text (this parser) is the only lossless option, and `pg` exposes type
53
+ * parsers only at module (process-global) scope. It is set ONCE at pool creation, not per read. The
54
+ * materializer's `Date → ISO string` path remains as a defensive fallback for any driver/config that
55
+ * still slips a Date through, but the correct-day guarantee for pg DATE comes from this parser.
56
+ */
57
+ function configurePgDeboxTypeParsers(types) {
58
+ const asString = (v) => v; // identity: keep the driver's native textual form
59
+ types.setTypeParser(PG_OID.DATE, asString);
60
+ types.setTypeParser(PG_OID.TIMESTAMP, asString);
61
+ types.setTypeParser(PG_OID.TIMESTAMPTZ, asString);
62
+ types.setTypeParser(PG_OID.TIME, asString);
63
+ types.setTypeParser(PG_OID.TIMETZ, asString);
64
+ }
65
+ /**
66
+ * The `mysql2` pool options the read-path de-box (issue #59) requires: `supportBigNumbers` +
67
+ * `bigNumberStrings` so BIGINT arrives as an EXACT string (→ bigint; a plain number would already
68
+ * have rounded it), and `dateStrings` so the DATE/TIMESTAMP/DATETIME family arrives as its native
69
+ * textual string (→ the `date→string` outType, NOT a JS Date). Spread into `mysql.createPool(...)`.
70
+ */
71
+ exports.mysqlDeboxPoolOptions = {
72
+ supportBigNumbers: true,
73
+ bigNumberStrings: true,
74
+ dateStrings: true,
75
+ };
23
76
  /**
24
77
  * Adapt a `pg.Pool` to the async executor seam. Each `exec` runs `pool.query`, which acquires a
25
78
  * pooled connection, runs the query, and releases it — so N concurrent siblings run on N pooled
@@ -35,12 +88,27 @@ function pgPoolExecutor(pool) {
35
88
  };
36
89
  }
37
90
  /**
38
- * Adapt a `mysql2/promise` pool to the async executor seam. `pool.query` acquires + releases a
39
- * pooled connection per call, so concurrent siblings run in parallel. The graph renders `?`
40
- * placeholders for the `mysql` dialect — `mysql2`'s native form.
41
- *
42
- * Recommend `connectionLimit` ≥ the plan's `concurrency` (default 16).
91
+ * Build a PG pool + executor with the read-path de-box wired IN (issue #59): registers the pg date
92
+ * type parsers (DATE/TIMESTAMP family → native textual string) globally, then builds the pool.
93
+ * int8 already arrives as a string on pg. Returns `{ pool, exec }` — pass `exec` to
94
+ * `executeBehaviorAsync`. This is the production async path's de-box-correct entry (no hand-spread
95
+ * options).
43
96
  */
97
+ function pgDeboxExecutor(pg, config) {
98
+ configurePgDeboxTypeParsers(pg.types);
99
+ const pool = new pg.Pool(config);
100
+ return { pool, exec: pgPoolExecutor(pool) };
101
+ }
102
+ /**
103
+ * Build a MySQL pool + executor with the read-path de-box wired IN (issue #59): the pool carries
104
+ * {@link mysqlDeboxPoolOptions} (`supportBigNumbers + bigNumberStrings` so BIGINT → exact string,
105
+ * `dateStrings` so the date family → string) — options that MUST be set at pool construction (a
106
+ * rounded BIGINT cannot be un-rounded post-hoc). Returns `{ pool, exec }` for `executeBehaviorAsync`.
107
+ */
108
+ function mysqlDeboxExecutor(mysql2, config) {
109
+ const pool = mysql2.createPool({ ...config, ...exports.mysqlDeboxPoolOptions });
110
+ return { pool, exec: mysqlPoolExecutor(pool) };
111
+ }
44
112
  function mysqlPoolExecutor(pool) {
45
113
  return async (sql, params) => {
46
114
  const [rows] = await pool.query(sql, params);
@@ -1 +1 @@
1
- {"version":3,"file":"pool-executor.js","sourceRoot":"","sources":["../../../src/scp/makesql/pool-executor.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;AAsBH,wCAKC;AASD,8CAKC;AA3BD;;;;;;;GAOG;AACH,SAAgB,cAAc,CAAC,IAAgB;IAC7C,OAAO,KAAK,EAAE,GAAW,EAAE,MAAiB,EAAsC,EAAE;QAClF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,IAAmB;IACnD,OAAO,KAAK,EAAE,GAAW,EAAE,MAAiB,EAAsC,EAAE;QAClF,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"pool-executor.js","sourceRoot":"","sources":["../../../src/scp/makesql/pool-executor.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAyCH,kEAOC;AAgCD,wCAKC;AAkCD,0CAIC;AAQD,gDAGC;AAED,8CAKC;AAzID,iFAAiF;AACjF,iGAAiG;AACjG,gGAAgG;AAChG,2CAA2C;AAC3C,+FAA+F;AAC/F,iGAAiG;AACjG,6FAA6F;AAC7F,iGAAiG;AACjG,8EAA8E;AAC9E,mGAAmG;AACnG,4FAA4F;AAC5F,0FAA0F;AAE1F,6DAA6D;AAC7D,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAW,CAAC;AAO/G;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,2BAA2B,CAAC,KAAkB;IAC5D,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,kDAAkD;IAC7F,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChD,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAClD,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACU,QAAA,qBAAqB,GAAG;IACnC,iBAAiB,EAAE,IAAI;IACvB,gBAAgB,EAAE,IAAI;IACtB,WAAW,EAAE,IAAI;CACT,CAAC;AAYX;;;;;;;GAOG;AACH,SAAgB,cAAc,CAAC,IAAgB;IAC7C,OAAO,KAAK,EAAE,GAAW,EAAE,MAAiB,EAAsC,EAAE;QAClF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC;AA2BD;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,EAAgB,EAAE,MAA+B;IAC/E,2BAA2B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,MAAwB,EAAE,MAA+B;IAC1F,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,6BAAqB,EAAE,CAAC,CAAC;IACxE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;AACjD,CAAC;AAED,SAAgB,iBAAiB,CAAC,IAAmB;IACnD,OAAO,KAAK,EAAE,GAAW,EAAE,MAAiB,EAAsC,EAAE;QAClF,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}