litedbmodel 2.1.0 → 2.2.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 (186) hide show
  1. package/README.md +7 -0
  2. package/dist/DBConditions.d.ts.map +1 -1
  3. package/dist/DBConditions.js +16 -1
  4. package/dist/DBConditions.js.map +1 -1
  5. package/dist/DBHandler.d.ts.map +1 -1
  6. package/dist/DBHandler.js +6 -0
  7. package/dist/DBHandler.js.map +1 -1
  8. package/dist/DBModel.d.ts +84 -2
  9. package/dist/DBModel.d.ts.map +1 -1
  10. package/dist/DBModel.js +312 -29
  11. package/dist/DBModel.js.map +1 -1
  12. package/dist/decorators.d.ts +52 -0
  13. package/dist/decorators.d.ts.map +1 -1
  14. package/dist/decorators.js +83 -0
  15. package/dist/decorators.js.map +1 -1
  16. package/dist/drivers/mysql.d.ts.map +1 -1
  17. package/dist/drivers/mysql.js +6 -2
  18. package/dist/drivers/mysql.js.map +1 -1
  19. package/dist/drivers/postgres.d.ts.map +1 -1
  20. package/dist/drivers/postgres.js +6 -2
  21. package/dist/drivers/postgres.js.map +1 -1
  22. package/dist/drivers/sqlite.d.ts.map +1 -1
  23. package/dist/drivers/sqlite.js +12 -2
  24. package/dist/drivers/sqlite.js.map +1 -1
  25. package/dist/index.cjs +10741 -0
  26. package/dist/index.d.cts +1 -0
  27. package/dist/scp/coltype.d.ts +26 -1
  28. package/dist/scp/coltype.d.ts.map +1 -1
  29. package/dist/scp/coltype.js +82 -15
  30. package/dist/scp/coltype.js.map +1 -1
  31. package/dist/scp/connection-routing.d.ts +312 -0
  32. package/dist/scp/connection-routing.d.ts.map +1 -0
  33. package/dist/scp/connection-routing.js +394 -0
  34. package/dist/scp/connection-routing.js.map +1 -0
  35. package/dist/scp/dbmodel-runtime.d.ts +101 -0
  36. package/dist/scp/dbmodel-runtime.d.ts.map +1 -0
  37. package/dist/scp/dbmodel-runtime.js +174 -0
  38. package/dist/scp/dbmodel-runtime.js.map +1 -0
  39. package/dist/scp/decorator-adapter.d.ts +196 -0
  40. package/dist/scp/decorator-adapter.d.ts.map +1 -0
  41. package/dist/scp/decorator-adapter.js +286 -0
  42. package/dist/scp/decorator-adapter.js.map +1 -0
  43. package/dist/scp/emit/emitter.d.ts +108 -0
  44. package/dist/scp/emit/emitter.d.ts.map +1 -0
  45. package/dist/scp/emit/emitter.js +782 -0
  46. package/dist/scp/emit/emitter.js.map +1 -0
  47. package/dist/scp/emit/endpoint.d.ts +248 -0
  48. package/dist/scp/emit/endpoint.d.ts.map +1 -0
  49. package/dist/scp/emit/endpoint.js +20 -0
  50. package/dist/scp/emit/endpoint.js.map +1 -0
  51. package/dist/scp/emit/index.d.ts +11 -0
  52. package/dist/scp/emit/index.d.ts.map +1 -0
  53. package/dist/scp/emit/index.js +13 -0
  54. package/dist/scp/emit/index.js.map +1 -0
  55. package/dist/scp/errors.d.ts +45 -1
  56. package/dist/scp/errors.d.ts.map +1 -1
  57. package/dist/scp/errors.js +47 -1
  58. package/dist/scp/errors.js.map +1 -1
  59. package/dist/scp/exec-context.d.ts +390 -0
  60. package/dist/scp/exec-context.d.ts.map +1 -0
  61. package/dist/scp/exec-context.js +540 -0
  62. package/dist/scp/exec-context.js.map +1 -0
  63. package/dist/scp/grouping.d.ts +32 -0
  64. package/dist/scp/grouping.d.ts.map +1 -0
  65. package/dist/scp/grouping.js +0 -0
  66. package/dist/scp/grouping.js.map +1 -0
  67. package/dist/scp/index.cjs +6814 -15731
  68. package/dist/scp/index.d.cts +1 -0
  69. package/dist/scp/index.d.mts +1 -0
  70. package/dist/scp/index.d.ts +47 -49
  71. package/dist/scp/index.d.ts.map +1 -1
  72. package/dist/scp/index.js +174 -152
  73. package/dist/scp/index.js.map +1 -1
  74. package/dist/scp/index.mjs +5561 -3704
  75. package/dist/scp/leaf-transport.d.ts +50 -0
  76. package/dist/scp/leaf-transport.d.ts.map +1 -0
  77. package/dist/scp/leaf-transport.js +92 -0
  78. package/dist/scp/leaf-transport.js.map +1 -0
  79. package/dist/scp/leaves.d.ts +174 -0
  80. package/dist/scp/leaves.d.ts.map +1 -0
  81. package/dist/scp/leaves.js +287 -0
  82. package/dist/scp/leaves.js.map +1 -0
  83. package/dist/scp/limit-config.d.ts +118 -0
  84. package/dist/scp/limit-config.d.ts.map +1 -0
  85. package/dist/scp/limit-config.js +126 -0
  86. package/dist/scp/limit-config.js.map +1 -0
  87. package/dist/scp/makesql/compile-relation.d.ts +49 -23
  88. package/dist/scp/makesql/compile-relation.d.ts.map +1 -1
  89. package/dist/scp/makesql/compile-relation.js +101 -76
  90. package/dist/scp/makesql/compile-relation.js.map +1 -1
  91. package/dist/scp/makesql/compile-select.d.ts +45 -10
  92. package/dist/scp/makesql/compile-select.d.ts.map +1 -1
  93. package/dist/scp/makesql/compile-select.js +50 -10
  94. package/dist/scp/makesql/compile-select.js.map +1 -1
  95. package/dist/scp/makesql/handler.d.ts +1 -1
  96. package/dist/scp/makesql/handler.d.ts.map +1 -1
  97. package/dist/scp/makesql/index.d.ts +7 -9
  98. package/dist/scp/makesql/index.d.ts.map +1 -1
  99. package/dist/scp/makesql/index.js +17 -28
  100. package/dist/scp/makesql/index.js.map +1 -1
  101. package/dist/scp/makesql/json-array.d.ts +65 -0
  102. package/dist/scp/makesql/json-array.d.ts.map +1 -1
  103. package/dist/scp/makesql/json-array.js +99 -10
  104. package/dist/scp/makesql/json-array.js.map +1 -1
  105. package/dist/scp/makesql/json-batch.d.ts.map +1 -1
  106. package/dist/scp/makesql/json-batch.js +15 -18
  107. package/dist/scp/makesql/json-batch.js.map +1 -1
  108. package/dist/scp/makesql/makesql.d.ts +1 -1
  109. package/dist/scp/makesql/makesql.d.ts.map +1 -1
  110. package/dist/scp/makesql/mysql-returning.d.ts +93 -0
  111. package/dist/scp/makesql/mysql-returning.d.ts.map +1 -0
  112. package/dist/scp/makesql/mysql-returning.js +215 -0
  113. package/dist/scp/makesql/mysql-returning.js.map +1 -0
  114. package/dist/scp/makesql/outtype.d.ts +40 -54
  115. package/dist/scp/makesql/outtype.d.ts.map +1 -1
  116. package/dist/scp/makesql/outtype.js +46 -204
  117. package/dist/scp/makesql/outtype.js.map +1 -1
  118. package/dist/scp/makesql/pool-executor.d.ts +86 -34
  119. package/dist/scp/makesql/pool-executor.d.ts.map +1 -1
  120. package/dist/scp/makesql/pool-executor.js +179 -39
  121. package/dist/scp/makesql/pool-executor.js.map +1 -1
  122. package/dist/scp/makesql/tx.d.ts +107 -22
  123. package/dist/scp/makesql/tx.d.ts.map +1 -1
  124. package/dist/scp/makesql/tx.js +451 -97
  125. package/dist/scp/makesql/tx.js.map +1 -1
  126. package/dist/scp/makesql/writeouttype.d.ts +4 -4
  127. package/dist/scp/makesql/writeouttype.d.ts.map +1 -1
  128. package/dist/scp/makesql/writeouttype.js +5 -3
  129. package/dist/scp/makesql/writeouttype.js.map +1 -1
  130. package/dist/scp/middleware.d.ts +287 -0
  131. package/dist/scp/middleware.d.ts.map +1 -0
  132. package/dist/scp/middleware.js +358 -0
  133. package/dist/scp/middleware.js.map +1 -0
  134. package/dist/scp/relation.d.ts +65 -8
  135. package/dist/scp/relation.d.ts.map +1 -1
  136. package/dist/scp/relation.js +154 -93
  137. package/dist/scp/relation.js.map +1 -1
  138. package/dist/scp/tx-options.d.ts +136 -0
  139. package/dist/scp/tx-options.d.ts.map +1 -0
  140. package/dist/scp/tx-options.js +184 -0
  141. package/dist/scp/tx-options.js.map +1 -0
  142. package/dist/scp/write-bundle.d.ts +131 -0
  143. package/dist/scp/write-bundle.d.ts.map +1 -0
  144. package/dist/scp/write-bundle.js +160 -0
  145. package/dist/scp/write-bundle.js.map +1 -0
  146. package/dist/types.d.ts +7 -0
  147. package/dist/types.d.ts.map +1 -1
  148. package/dist/types.js.map +1 -1
  149. package/docs/design/phase-a-execution-context.md +139 -0
  150. package/package.json +14 -13
  151. package/dist/scp/authoring-sql.d.ts +0 -134
  152. package/dist/scp/authoring-sql.d.ts.map +0 -1
  153. package/dist/scp/authoring-sql.js +0 -191
  154. package/dist/scp/authoring-sql.js.map +0 -1
  155. package/dist/scp/authoring.d.ts +0 -218
  156. package/dist/scp/authoring.d.ts.map +0 -1
  157. package/dist/scp/authoring.js +0 -351
  158. package/dist/scp/authoring.js.map +0 -1
  159. package/dist/scp/catalog.d.ts +0 -95
  160. package/dist/scp/catalog.d.ts.map +0 -1
  161. package/dist/scp/catalog.js +0 -245
  162. package/dist/scp/catalog.js.map +0 -1
  163. package/dist/scp/codegen.d.ts +0 -201
  164. package/dist/scp/codegen.d.ts.map +0 -1
  165. package/dist/scp/codegen.js +0 -605
  166. package/dist/scp/codegen.js.map +0 -1
  167. package/dist/scp/find-filter-guard.d.ts +0 -68
  168. package/dist/scp/find-filter-guard.d.ts.map +0 -1
  169. package/dist/scp/find-filter-guard.js +0 -88
  170. package/dist/scp/find-filter-guard.js.map +0 -1
  171. package/dist/scp/guard.d.ts +0 -43
  172. package/dist/scp/guard.d.ts.map +0 -1
  173. package/dist/scp/guard.js +0 -140
  174. package/dist/scp/guard.js.map +0 -1
  175. package/dist/scp/makesql/authoring-compile.d.ts +0 -90
  176. package/dist/scp/makesql/authoring-compile.d.ts.map +0 -1
  177. package/dist/scp/makesql/authoring-compile.js +0 -505
  178. package/dist/scp/makesql/authoring-compile.js.map +0 -1
  179. package/dist/scp/makesql/static-bundle.d.ts +0 -196
  180. package/dist/scp/makesql/static-bundle.d.ts.map +0 -1
  181. package/dist/scp/makesql/static-bundle.js +0 -1244
  182. package/dist/scp/makesql/static-bundle.js.map +0 -1
  183. package/dist/scp/runtime.d.ts +0 -243
  184. package/dist/scp/runtime.d.ts.map +0 -1
  185. package/dist/scp/runtime.js +0 -422
  186. package/dist/scp/runtime.js.map +0 -1
@@ -29,13 +29,21 @@
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.RELATION_KEYS_HEAD = void 0;
31
31
  exports.compileRelationOp = compileRelationOp;
32
+ exports.parentKeyCols = parentKeyCols;
33
+ exports.targetKeyCols = targetKeyCols;
34
+ exports.relationGuard = relationGuard;
32
35
  exports.runRelationOp = runRelationOp;
33
36
  exports.distributeToParent = distributeToParent;
34
37
  const makesql_1 = require("./makesql/makesql");
35
38
  const handler_1 = require("./makesql/handler");
39
+ const exec_context_1 = require("./exec-context");
36
40
  const coltype_1 = require("./coltype");
37
41
  const outtype_1 = require("./makesql/outtype");
42
+ const limit_config_1 = require("./limit-config");
43
+ const grouping_1 = require("./grouping");
44
+ const json_array_1 = require("./makesql/json-array");
38
45
  const compile_relation_1 = require("./makesql/compile-relation");
46
+ const tx_1 = require("./makesql/tx");
39
47
  /** The reserved input head the relation batch query binds its deduped key array to. */
40
48
  exports.RELATION_KEYS_HEAD = '__keys';
41
49
  /**
@@ -58,7 +66,7 @@ function compileRelationOp(decl, resolveColumnType) {
58
66
  }
59
67
  const dialect = decl.dialect ?? 'sqlite';
60
68
  const composite = isCompositeDecl(decl);
61
- const sql = compiledBatchSql(decl, dialect);
69
+ const sql = compiledBatchSql(decl, dialect, resolveColumnType);
62
70
  // CROSS-DB (V0 R1): carry the target connection tag ONLY when set (a same-DB relation stays
63
71
  // untagged, so existing bundles are byte-unchanged — the field is additive/optional).
64
72
  const conn = decl.connection !== undefined ? { connection: decl.connection } : {};
@@ -80,11 +88,26 @@ function compileRelationOp(decl, resolveColumnType) {
80
88
  materializers[entry.outputKey] = klass;
81
89
  }
82
90
  }
91
+ // CHAINED relations (nested `with`): compile each grandchild relation recursively, inheriting THIS
92
+ // relation's dialect. The SAME single compiler — a child is just another RelationDecl whose parent is
93
+ // this relation's target rows; no separate nested-relation path. Absent ⇒ a leaf (byte-unchanged).
94
+ const childRelations = decl.childRelations !== undefined && decl.childRelations.length > 0
95
+ ? decl.childRelations.map((c) => compileRelationOp({ ...c, dialect: c.dialect ?? dialect }, resolveColumnType))
96
+ : undefined;
83
97
  const target = {
84
98
  targetTable: decl.targetTable,
85
99
  select: [...decl.select],
86
100
  ...(Object.keys(materializers).length > 0 ? { materializers } : {}),
101
+ ...(childRelations !== undefined ? { childRelations } : {}),
87
102
  };
103
+ // Hard-limit runaway cap (Phase E-2, epic #74; v1 `_selectForRelation`): resolve the effective
104
+ // batch-total cap ONCE at compile (per-relation override → global) and bake it onto the op as a
105
+ // plain number the native ports read. Only a `hasMany` is capped (single-cardinality fetches ≤1
106
+ // child per parent). A relation with an INTRINSIC per-parent `limit` window SKIPS the check — its
107
+ // fanout is already bounded per parent (v1 raw-SQL-with-LIMIT skip). `null` (per-relation or global)
108
+ // ⇒ disabled ⇒ the field is omitted (op stays byte-unchanged for the uncapped path).
109
+ const effectiveHardLimit = decl.kind === 'hasMany' && decl.limit === undefined ? (0, limit_config_1.resolveHasManyHardLimit)(decl.hardLimit) : null;
110
+ const guard = effectiveHardLimit !== null ? { hardLimit: effectiveHardLimit } : {};
88
111
  if (composite) {
89
112
  return {
90
113
  name: decl.name,
@@ -95,6 +118,7 @@ function compileRelationOp(decl, resolveColumnType) {
95
118
  ...conn,
96
119
  sql,
97
120
  ...target,
121
+ ...guard,
98
122
  };
99
123
  }
100
124
  return {
@@ -106,6 +130,7 @@ function compileRelationOp(decl, resolveColumnType) {
106
130
  ...conn,
107
131
  sql,
108
132
  ...target,
133
+ ...guard,
109
134
  };
110
135
  }
111
136
  /**
@@ -132,25 +157,43 @@ function isCompositeDecl(decl) {
132
157
  }
133
158
  return true;
134
159
  }
160
+ /**
161
+ * The PG element type of each COMPOSITE key column, from the CHILD column's DECLARED type — the same
162
+ * schema-derived derivation the composite `tupleIn` predicate uses (`pgTypeSpecimen` →
163
+ * `inferPgElementType`), so the two composite PG forms cast identically. The child column is the one
164
+ * the key row is compared against, so its declared type is the type the key must carry.
165
+ *
166
+ * A composite PG batch cannot be compiled without them (the key rows come out of JSON as `text` and
167
+ * `int = text` fails at plan time), so a missing resolver is a LOUD compile error, never a silent
168
+ * `text` fallback.
169
+ */
170
+ function pgKeyTypesOf(decl, targetKeys, resolveColumnType) {
171
+ if (resolveColumnType === undefined) {
172
+ throw new Error(`relation '${decl.name}': a COMPOSITE-key relation on postgres needs the target model's column types ` +
173
+ `(keys ${targetKeys.join(', ')} on '${decl.targetTable}') — pass a ColumnTypeResolver to compileRelationOp`);
174
+ }
175
+ return targetKeys.map((k) => (0, compile_relation_1.inferPgElementType)([(0, tx_1.pgTypeSpecimen)(resolveColumnType(decl.targetTable, k))]));
176
+ }
135
177
  /**
136
178
  * Compile the STATIC batch SELECT text: the makeSQL relation builder emits complete tuned SQL
137
179
  * whose deduped-key array is ONE param. We compile against a single placeholder key array so
138
180
  * the text is fixed; the runtime re-binds the real deduped keys against the SAME text (the
139
181
  * single-JSON / `= ANY` forms are length-independent, so the text is stable).
140
182
  */
141
- function compiledBatchSql(decl, dialect) {
142
- // A COMPOSITE decl compiles to the STATIC composite form (PG: one array param per key column;
143
- // MySQL/SQLite: one JSON array-of-tuples param) — length-independent, so the text is fixed. A
144
- // per-parent `limit` selects the STATIC composite-LIMITED builder (PG LATERAL / MySQL·SQLite
145
- // ROW_NUMBER window over the SAME static key-set predicate — #47 last completeness gap).
183
+ function compiledBatchSql(decl, dialect, resolveColumnType) {
184
+ // A COMPOSITE decl compiles to the STATIC composite form — ONE JSON array-of-tuples param on every
185
+ // dialect, length-independent, so the text is fixed. A per-parent `limit` selects the STATIC
186
+ // composite-LIMITED builder (PG LATERAL / MySQL·SQLite ROW_NUMBER window over the SAME static
187
+ // key-set predicate — #47 last completeness gap).
146
188
  if (decl.parentKeys !== undefined) {
189
+ const targetKeys = [...decl.targetKeys];
147
190
  const compositeBase = {
148
191
  dialect,
149
192
  tableName: decl.targetTable,
150
193
  select: decl.select.join(', '),
151
194
  order: decl.order,
152
- targetKeys: [...decl.targetKeys],
153
- deferPgArrayCast: true,
195
+ targetKeys,
196
+ ...(dialect === 'postgres' ? { pgKeyTypes: pgKeyTypesOf(decl, targetKeys, resolveColumnType) } : {}),
154
197
  };
155
198
  const node = decl.limit !== undefined
156
199
  ? (0, compile_relation_1.compileCompositeKeyStaticLimited)({ ...compositeBase, limit: decl.limit })
@@ -160,6 +203,15 @@ function compiledBatchSql(decl, dialect) {
160
203
  // A one-element placeholder key set fixes the SQL text (single-JSON-param / `= ANY` forms are
161
204
  // value-length-independent). The concrete keys are bound at execute time.
162
205
  const placeholderKeys = [null];
206
+ // The PG `= ANY(?::<T>[])` element type comes from the target key COLUMN's DECLARED type — the same
207
+ // schema-derived derivation the composite path uses (`pgKeyTypesOf`). It must NOT be inferred at
208
+ // render from a bound value: the value's type differs by language (a bc int is a BigInt on the TS
209
+ // plane → `bigint[]`, a native int in python/php → `int[]`), which broke cross-language byte-identity.
210
+ // The column is the authority (an int column → `int[]`, byte-identical to v1's live-correct cast, and
211
+ // never the #43 `text[]`). Only fall back to render-time inference when no resolver is available.
212
+ const pgKeyCast = dialect === 'postgres' && resolveColumnType !== undefined
213
+ ? (0, compile_relation_1.inferPgElementType)([(0, tx_1.pgTypeSpecimen)(resolveColumnType(decl.targetTable, decl.targetKey))])
214
+ : undefined;
163
215
  const base = {
164
216
  dialect,
165
217
  tableName: decl.targetTable,
@@ -167,11 +219,9 @@ function compiledBatchSql(decl, dialect) {
167
219
  order: decl.order,
168
220
  targetKey: decl.targetKey,
169
221
  values: placeholderKeys,
170
- // The keys are UNKNOWN at symbolic compile (placeholder set), so the PG `= ANY(?::<T>[])`
171
- // element type is DEFERRED to render (#46) — resolved from the real deduped keys via
172
- // `inferPgArrayType`, reproducing v1's live-correct cast (`::int[]` for int keys). Baking a
173
- // compile-time `text[]` here was the #43 regression (`integer = text` on real PG).
174
- deferPgArrayCast: true,
222
+ ...(pgKeyCast !== undefined
223
+ ? { sqlCastMap: new Map([[decl.targetKey, pgKeyCast]]) }
224
+ : { deferPgArrayCast: true }),
175
225
  };
176
226
  const node = decl.limit !== undefined
177
227
  ? (0, compile_relation_1.compileSingleKeyLimited)({ ...base, limit: decl.limit })
@@ -179,6 +229,30 @@ function compiledBatchSql(decl, dialect) {
179
229
  // The builder emits the SQL with ONE `?` (the whole key array). Assemble to the flat text.
180
230
  return (0, makesql_1.assembleMakeSQL)(node).sql;
181
231
  }
232
+ /**
233
+ * Coerce a relation target to an {@link ExecutionContext}. A raw {@link RelationDriver} (read-only
234
+ * `prepare`) is adapted to a full sync driver (its `run` is never reached on the read-only relation
235
+ * path) and wrapped via {@link contextForDriver} — the backward-compat seam. So the relation batch
236
+ * ALSO funnels through the central seam (middleware → connectionFor → execute), no direct driver.
237
+ */
238
+ function relationContext(target) {
239
+ if ('connectionFor' in target)
240
+ return target;
241
+ const driver = {
242
+ prepare(sql) {
243
+ const s = target.prepare(sql);
244
+ return {
245
+ all: (...p) => s.all(...p),
246
+ // The read-only relation path never runs a write; a defensive stub keeps the driver shape total.
247
+ run: () => {
248
+ throw new Error('relation batch: unexpected write on a read-only relation driver');
249
+ },
250
+ safeIntegers: s.safeIntegers?.bind(s),
251
+ };
252
+ },
253
+ };
254
+ return (0, exec_context_1.contextForDriver)(driver);
255
+ }
182
256
  /** The ordered PARENT key columns of an op (single-key → 1-element list; composite → the tuple). */
183
257
  function parentKeyCols(op) {
184
258
  return op.parentKeys ?? [op.parentKey];
@@ -187,28 +261,39 @@ function parentKeyCols(op) {
187
261
  function targetKeyCols(op) {
188
262
  return op.targetKeys ?? [op.targetKey];
189
263
  }
190
- /** The stringified key identity for dedupe/grouping. Single scalar → `String(v)`; tuple → joined. */
191
- function keyIdentity(values) {
192
- // A NUL separator no scalar `String(v)` contains, so distinct tuples never collide.
193
- return values.map((v) => String(v)).join('');
264
+ /**
265
+ * The op's RELATION RUNAWAY GUARD, or `null` when it baked none (disabled, or an intrinsic per-parent
266
+ * `limit` window whose fanout is already bounded). The ONE projection of a compiled op onto the
267
+ * {@link RelationGuard} record — read by BOTH consumers of the cap: {@link runRelationOp} (the
268
+ * typed-object / lazy batch) and the emitter, which bakes this record into the generated child fetch's
269
+ * `guard` port so the leaf enforces the SAME resolved cap. Nothing downstream re-derives it.
270
+ */
271
+ function relationGuard(op) {
272
+ if (op.hardLimit === undefined)
273
+ return null;
274
+ return {
275
+ limit: op.hardLimit,
276
+ ...(op.targetTable !== undefined ? { model: op.targetTable } : {}),
277
+ relation: op.name,
278
+ };
194
279
  }
195
280
  /**
196
- * Bind the deduped keys to the batch op's params per dialect + arity. Single-key: PG binds the
197
- * scalar array verbatim (`= ANY(?::t[])`); MySQL/SQLite bind the JSON-encoded array. Composite: PG
198
- * binds ONE array param PER key column (transposed tuples → `unnest(?::t1[], ?::t2[])`);
199
- * MySQL/SQLite bind ONE JSON array-of-tuples string. Returns the positional param list.
281
+ * Bind the deduped keys to the batch op's params — ONE param, every dialect and arity. A COMPOSITE
282
+ * key set is the JSON array-of-tuples every dialect expands server-side (PG `json_array_elements`,
283
+ * MySQL `JSON_TABLE`, SQLite `json_each`), so the key binding is dialect-INDEPENDENT: no key-tuple
284
+ * transpose anywhere. A SINGLE-key set is the scalar array — bound raw on PG (`= ANY(?::t[])` takes a
285
+ * native array) and JSON-encoded on MySQL/SQLite.
286
+ *
287
+ * The JSON encoding goes through {@link encodeJsonParam}, the one serializer every JSON param uses.
288
+ * These keys came OFF a read, so an `int` key is a `BigInt` — a bare `JSON.stringify` here does not
289
+ * "diverge subtly", it THROWS `Do not know how to serialize a BigInt` and takes every relation read
290
+ * with an integer parent key down with it.
200
291
  */
201
292
  function bindKeys(op, tuples) {
202
- const composite = op.parentKeys !== undefined;
203
- if (op.dialect === 'postgres') {
204
- if (!composite)
205
- return [tuples.map((t) => t[0])]; // ONE scalar array param
206
- // Transpose tuples → per-column arrays: `[[1,a],[2,b]] → [[1,2],[a,b]]` — one array param each.
207
- return parentKeyCols(op).map((_, col) => tuples.map((t) => t[col]));
208
- }
209
- // MySQL/SQLite: single-key → JSON scalar array; composite → JSON array-of-tuples. ONE param.
210
- const payload = composite ? tuples.map((t) => [...t]) : tuples.map((t) => t[0]);
211
- return [JSON.stringify(payload)];
293
+ if (op.parentKeys !== undefined)
294
+ return [(0, json_array_1.encodeJsonParam)(op.dialect, tuples.map((t) => [...t]))];
295
+ const keys = tuples.map((t) => t[0]);
296
+ return [op.dialect === 'postgres' ? keys : (0, json_array_1.encodeJsonParam)(op.dialect, keys)];
212
297
  }
213
298
  /**
214
299
  * Run ONE {@link RelationOp} for a set of parent rows: dedup the parent-key tuples, render the
@@ -221,49 +306,47 @@ function bindKeys(op, tuples) {
221
306
  * NO query (the correct empty-set behavior — the membership over no keys selects nothing).
222
307
  */
223
308
  function runRelationOp(op, parents, db) {
309
+ const ctx = relationContext(db);
224
310
  const pCols = parentKeyCols(op);
225
- const keys = dedupeKeys(parents, pCols);
311
+ const keys = (0, grouping_1.dedupeKeyTuples)(parents, pCols);
226
312
  const batch = new Map();
227
- // Resolve the deferred PG array cast(s) (#46) from the REAL keys BEFORE the `?`→`$N` render. A
228
- // single-key op has ONE cast; a composite PG op has ONE cast PER key column — resolve each from
229
- // its own column's key values, left-to-right (resolvePgArrayCast resolves the first token each
230
- // call). MySQL/SQLite carry no cast token.
231
- let cast = op.sql;
232
- if (op.dialect === 'postgres') {
233
- for (let col = 0; col < pCols.length; col++)
234
- cast = (0, compile_relation_1.resolvePgArrayCast)(cast, keys.map((t) => t[col]));
235
- }
313
+ // Resolve the deferred PG array cast (#46) from the REAL keys BEFORE the `?`→`$N` render: the
314
+ // SINGLE-key `= ANY(?::<T>[])` is the only cast whose element type is value-derived. A composite
315
+ // batch carries no token (its key rows are cast from the DECLARED column types at compile) and
316
+ // MySQL/SQLite carry none at all.
317
+ const cast = op.dialect === 'postgres' && op.parentKeys === undefined
318
+ ? (0, compile_relation_1.resolvePgArrayCast)(op.sql, keys.map((t) => t[0]))
319
+ : op.sql;
236
320
  const sql = (0, handler_1.renderPlaceholders)(cast, op.dialect);
237
321
  if (keys.length === 0)
238
322
  return { sql, keys, batch };
239
323
  const tCols = targetKeyCols(op);
240
324
  // Materialize the child rows (issue #59) exactly like the primary read, using the STATIC
241
325
  // materializers baked onto the op at compile (from the model's DDL — ZERO per-read introspection).
242
- // Enable safeIntegers when the child projects a BIGINT so int8 arrives exact. A BIGINT/DATE/BOOL
243
- // child column de-boxes identically to a top-level read (INT→number / BIGINT→string / DATE→string
244
- // / bool). SQLite-shaped driver; the async PG/MySQL relation path materializes at its own seam.
326
+ // A BIGINT/DATE/BOOL child column de-boxes identically to a top-level read (INT→number /
327
+ // BIGINT→string / DATE→string / bool).
245
328
  const childCols = op.materializers;
246
- const int64Child = childCols !== undefined && Object.values(childCols).includes('int64');
247
- const stmt = db.prepare(sql);
248
- if (int64Child && typeof stmt.safeIntegers === 'function') {
249
- stmt.safeIntegers(true);
250
- }
251
- const rawRows = stmt.all(...bindKeys(op, keys));
252
- const rows = materializeChildRows(rawRows, childCols, int64Child);
253
- for (const row of rows) {
254
- const k = keyIdentity(tCols.map((c) => row[c]));
255
- const list = batch.get(k);
256
- if (list === undefined)
257
- batch.set(k, [row]);
258
- else
259
- list.push(row);
260
- }
261
- return { sql, keys, batch };
329
+ // The EXACT-integer seam, unconditionally — the same one the `executeSQL` leaf reads through. This
330
+ // used to switch to the inexact seam unless a child column was declared `int64`, which made ONE
331
+ // column read back as two different JS types depending on which surface fetched it: `1n` through
332
+ // codegen, `1` through the lazy path. Exactness is not a per-endpoint choice; the DECLARED type
333
+ // decides the consumer-facing shape, and that narrowing is `materializeCell`'s job below.
334
+ const boundParams = bindKeys(op, keys);
335
+ const rawRows = (0, exec_context_1.executeSafe)(ctx, sql, boundParams);
336
+ // Hard-limit runaway guard (Phase E-2, epic #74; v1 `_selectForRelation`): POST-fetch, if the batch
337
+ // TOTAL exceeds the baked cap, throw with the EXACT count (the batch is fetched in full, no N+1).
338
+ // The check itself is the SHARED relation primitive (`assertRelationHardLimit`) over the op's own
339
+ // guard — the SAME two functions the codegen path runs in the `executeSQL` leaf, so the two read
340
+ // surfaces cannot drift on the cap, the count or the error identity. Runs BEFORE grouping/hydration
341
+ // so an over-cap read never assembles an unbounded result set.
342
+ (0, limit_config_1.assertRelationHardLimit)(rawRows, relationGuard(op));
343
+ const rows = materializeChildRows(rawRows, childCols);
344
+ // Group the child rows by their target-key identity — the shared grouping SSoT ({@link groupByKey}),
345
+ // the SAME core the eager `group` leaf uses (no duplicated grouping).
346
+ return { sql, keys, batch: (0, grouping_1.groupByKey)(rows, tCols) };
262
347
  }
263
348
  /** Materialize relation child rows (issue #59): same coercion as the primary read. */
264
- function materializeChildRows(rows, cols, safeIntegersOn) {
265
- if (cols === undefined && !safeIntegersOn)
266
- return rows;
349
+ function materializeChildRows(rows, cols) {
267
350
  for (const row of rows) {
268
351
  for (const key of Object.keys(row)) {
269
352
  const klass = cols?.[key];
@@ -271,8 +354,9 @@ function materializeChildRows(rows, cols, safeIntegersOn) {
271
354
  row[key] = (0, coltype_1.materializeCell)(row[key], klass);
272
355
  continue;
273
356
  }
274
- // Defensive: under safeIntegers, an untyped int child column arrives as bigint — narrow it.
275
- if (safeIntegersOn && typeof row[key] === 'bigint') {
357
+ // An UNDECLARED integer column arrives as bigint from the exact seam — narrow it here. There is
358
+ // no longer a mode in which it does not, so this is the normal path, not a defensive one.
359
+ if (typeof row[key] === 'bigint') {
276
360
  const v = row[key];
277
361
  row[key] = v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(v) : v.toString();
278
362
  }
@@ -280,37 +364,14 @@ function materializeChildRows(rows, cols, safeIntegersOn) {
280
364
  }
281
365
  return rows;
282
366
  }
283
- /**
284
- * The deduped, non-null parent-key TUPLES (insertion order preserved — deterministic). A tuple is
285
- * dropped if ANY of its key columns is null/undefined (no partial keys). Deduped on the stringified
286
- * tuple identity (so `1` and `"1"` collapse exactly as `String(v)`).
287
- */
288
- function dedupeKeys(parents, keyCols) {
289
- const seen = new Set();
290
- const out = [];
291
- for (const p of parents) {
292
- const tuple = keyCols.map((c) => p[c]);
293
- if (tuple.some((v) => v === undefined || v === null))
294
- continue;
295
- const s = keyIdentity(tuple);
296
- if (seen.has(s))
297
- continue;
298
- seen.add(s);
299
- out.push(tuple);
300
- }
301
- return out;
302
- }
303
367
  /**
304
368
  * Distribute a resolved {@link RelationBatch} onto ONE parent per the relation cardinality:
305
- * `hasMany` → the child list (`[]` when none); `belongsTo`/`hasOne` → the single child (or
306
- * `null`). Keyed by the parent's key-tuple identity. `null`/`[]` is the declared cardinality's
307
- * empty representation, not an ad-hoc default.
369
+ * `hasMany` → the child list (`[]` when none); `belongsTo`/`hasOne` → the single child (or `null`).
370
+ * A thin consumer over the shared grouping SSoT ({@link attachToParent}) — the SAME core the eager
371
+ * `group` leaf uses (no duplicated grouping). `null`/`[]` is the declared cardinality's empty
372
+ * representation, not an ad-hoc default.
308
373
  */
309
374
  function distributeToParent(op, parent, batch) {
310
- const tuple = parentKeyCols(op).map((c) => parent[c]);
311
- const rows = tuple.some((v) => v === undefined || v === null) ? undefined : batch.get(keyIdentity(tuple));
312
- if (op.kind === 'hasMany')
313
- return rows ?? [];
314
- return rows !== undefined && rows.length > 0 ? rows[0] : null;
375
+ return (0, grouping_1.attachToParent)(parent, parentKeyCols(op), batch, op.kind !== 'hasMany');
315
376
  }
316
377
  //# sourceMappingURL=relation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"relation.js","sourceRoot":"","sources":["../../src/scp/relation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relation.js","sourceRoot":"","sources":["../../src/scp/relation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * litedbmodel v2 SCP — the **tx-completeness contract** (Phase B-1 / #81): the TransactionOptions
3
+ * shape, the guard errors, the per-dialect isolation-level SQL, and the retryable-error classifier.
4
+ *
5
+ * This module is the **API REFERENCE** for Phase B — the 4 native ports (rust #82 / go #83 / py #84
6
+ * / php #85) mirror THIS contract exactly (option field names + defaults, guard-error semantics,
7
+ * isolation-level→SQL mapping per dialect, retryable-error classification, retry-loop policy). It is
8
+ * dialect-neutral and driver-agnostic on purpose: `withTransactionAsync` (exec-context.ts) consumes
9
+ * it; nothing here touches a connection.
10
+ *
11
+ * It builds ON the Phase A {@link import('./exec-context').ExecutionContext} + owned-connection
12
+ * ownership (`withTransactionAsync`); it does NOT re-implement connection ownership — it layers the
13
+ * options/guards/retry/isolation on top of that seam. It mirrors v1 `src/DBModel.ts`
14
+ * (`transaction` :2787, `checkWriteAllowed` :886, `isRetryableError` :2865) but on the SCP seam.
15
+ */
16
+ import { WriteOutsideTransactionError, WriteInReadOnlyContextError } from '../types';
17
+ import type { Dialect } from './makesql/handler';
18
+ export { WriteOutsideTransactionError, WriteInReadOnlyContextError };
19
+ /**
20
+ * The three portable SQL isolation levels the tx API exposes (lowercased, matching the v2 public
21
+ * surface). READ UNCOMMITTED is deliberately NOT offered — neither PG (which silently upgrades it to
22
+ * READ COMMITTED) nor a correctness-minded default wants it, and omitting it keeps the 4 ports' enum
23
+ * identical. The value maps to the canonical SQL phrase via {@link isolationSql}.
24
+ */
25
+ export type IsolationLevel = 'read committed' | 'repeatable read' | 'serializable';
26
+ /** The canonical SQL phrase for an {@link IsolationLevel} (e.g. `SERIALIZABLE`). */
27
+ export declare function isolationPhrase(level: IsolationLevel): string;
28
+ /**
29
+ * The tx-start statements for `dialect` at `isolation` (in issue order). Per-dialect because the
30
+ * three engines express per-transaction isolation DIFFERENTLY:
31
+ *
32
+ * - **postgres**: `BEGIN ISOLATION LEVEL <phrase>` — one statement, the level rides the BEGIN.
33
+ * - **mysql**: `SET TRANSACTION ISOLATION LEVEL <phrase>` MUST precede `BEGIN` (it scopes the very
34
+ * NEXT transaction only), so this returns TWO statements: the SET, then a bare `BEGIN`.
35
+ * - **sqlite**: SQLite has NO per-transaction isolation-level knob. Its isolation is a
36
+ * process/PRAGMA-level property (`journal_mode=WAL` gives snapshot reads; the default rollback
37
+ * journal serializes writers), NOT something a `BEGIN` clause selects. So an isolation request on
38
+ * SQLite is a HARD ERROR here — we do NOT silently drop it (that would fake honoring the level).
39
+ * The conformance/bench SQLite path never passes `isolation`, so it always emits a bare `BEGIN`.
40
+ *
41
+ * With no `isolation`, every dialect emits a single bare `BEGIN` (the Phase A behavior, byte-identical).
42
+ */
43
+ export declare function beginStatements(dialect: Dialect, isolation?: IsolationLevel): readonly string[];
44
+ /**
45
+ * Options for a transaction (the Phase B contract; mirrors v1 `TransactionOptions` in `src/types.ts`
46
+ * plus the new `isolation`). Every field is optional with a stable default; the 4 native ports MUST
47
+ * expose the SAME field names + defaults.
48
+ */
49
+ export interface TransactionOptions {
50
+ /**
51
+ * Per-transaction isolation level. Issued via {@link beginStatements} on the tx-owned connection
52
+ * (PG: on BEGIN; MySQL: a preceding SET). Omit for the engine default (PG/MySQL: READ COMMITTED /
53
+ * REPEATABLE READ respectively). SQLite has no per-tx level ⇒ passing this on SQLite is an error.
54
+ */
55
+ readonly isolation?: IsolationLevel;
56
+ /** Retry the whole tx on a retryable error (deadlock / serialization / connection). @default true */
57
+ readonly retryOnError?: boolean;
58
+ /** Max attempts before giving up (the FIRST try counts as attempt 1). @default 3 */
59
+ readonly retryLimit?: number;
60
+ /** Backoff base in ms; attempt k waits `retryDuration * 2^(k-1)` (exponential). @default 200 */
61
+ readonly retryDuration?: number;
62
+ /**
63
+ * ROLLBACK instead of COMMIT at the end of a SUCCESSFUL body (dry-run / preview): the body runs and
64
+ * its result is returned, but NO change is committed. A body error still ROLLBACKs + re-raises as
65
+ * usual. @default false
66
+ */
67
+ readonly rollbackOnly?: boolean;
68
+ /**
69
+ * Override the GLOBAL writer-after-transaction setting FOR THIS TRANSACTION (v1 parity —
70
+ * `TransactionOptions.useWriterAfterTransaction`, honored at `DBModel.transaction` :3103).
71
+ *
72
+ * `false` means this transaction's COMMIT does NOT arm writer-stickiness: the reads that follow it
73
+ * go back to the reader pool immediately instead of being pinned to the writer for
74
+ * `writerStickyDuration`. Use it for a transaction whose writes nobody needs to read back (a
75
+ * bookkeeping / audit / fire-and-forget write), so it does not cost every following read its
76
+ * replica.
77
+ *
78
+ * Omitted (or `true`) ⇒ the GLOBAL setting decides, exactly as before: the arming call lands on the
79
+ * ctx's {@link import('./connection-routing').WriterStickyClock}, which is itself disabled when the
80
+ * deployment configured `useWriterAfterTransaction: false`. This mirrors v1, where a per-tx `true`
81
+ * likewise cannot switch stickiness ON against a global `false` (`_shouldUseWriterSticky` :487
82
+ * re-checks the global). @default true
83
+ */
84
+ readonly useWriterAfterTransaction?: boolean;
85
+ }
86
+ /** The resolved (defaults-applied) options the tx runtime uses — no `undefined` holes. */
87
+ export interface ResolvedTxOptions {
88
+ readonly isolation?: IsolationLevel;
89
+ readonly retryOnError: boolean;
90
+ readonly retryLimit: number;
91
+ readonly retryDuration: number;
92
+ readonly rollbackOnly: boolean;
93
+ readonly useWriterAfterTransaction: boolean;
94
+ }
95
+ /** Apply the Phase B defaults (v1-parity: retryOnError=true, retryLimit=3, retryDuration=200). */
96
+ export declare function resolveTxOptions(opts?: TransactionOptions): ResolvedTxOptions;
97
+ /**
98
+ * Is `error` a RETRYABLE transaction failure — a deadlock, a serialization failure, or a broken
99
+ * connection — for which re-running the whole transaction can succeed? Classification is by the
100
+ * driver's stable error CODE first (PG `SQLSTATE`, MySQL `errno`), with the v1 message substrings as
101
+ * a fallback (mirrors v1 `DBModel.isRetryableError` :2865). A data conflict (unique/FK/check) is NOT
102
+ * retryable — re-running would fail identically.
103
+ *
104
+ * Codes (per dialect):
105
+ * - **postgres** SQLSTATE: `40001` serialization_failure, `40P01` deadlock_detected.
106
+ * - **mysql** errno: `1213` ER_LOCK_DEADLOCK, `1205` ER_LOCK_WAIT_TIMEOUT.
107
+ * - **connection errors** (either dialect): via {@link isConnectionError} — a dropped/reset/refused
108
+ * connection is retryable (reconnect on the next attempt).
109
+ */
110
+ export declare function isRetryableTxError(error: unknown, isConnectionError: (e: Error) => boolean): boolean;
111
+ /** Sleep `ms` (the retry backoff). */
112
+ export declare function sleep(ms: number): Promise<void>;
113
+ /** Run `fn` with the "inside a transaction" marker set (called by the tx runtime around the body). */
114
+ export declare function runInTransactionScope<R>(fn: () => R): R;
115
+ /**
116
+ * Run `fn` in a READ-ONLY context (mirror v1 `DBModel.withWriter`): reads are allowed, but ANY write
117
+ * inside `fn` throws {@link WriteInReadOnlyContextError}. Use for a read-your-writes / writer-pinned
118
+ * read scope that must never accidentally mutate.
119
+ */
120
+ export declare function withReadOnly<R>(fn: () => R): R;
121
+ /** True if the current async scope is inside an active transaction (guard/nested detection). */
122
+ export declare function isInTransaction(): boolean;
123
+ /** True if the current async scope is a read-only context ({@link withReadOnly}). */
124
+ export declare function isReadOnly(): boolean;
125
+ /**
126
+ * Enforce the write=tx guard (mirror v1 `DBModel._checkWriteAllowed`, DBModel.ts:886-896): a write
127
+ * inside a {@link withReadOnly} scope throws {@link WriteInReadOnlyContextError}; a write with NO
128
+ * active transaction throws {@link WriteOutsideTransactionError}. Called at every write ENTRY
129
+ * (create/update/delete/upsert/batch) BEFORE any SQL is issued. The order matches v1: read-only is
130
+ * checked first (a read-only scope is the more specific rejection).
131
+ *
132
+ * @param operation the write op name (INSERT/UPDATE/DELETE/UPSERT/BATCH) — carried in the error.
133
+ * @param modelName optional model/table name — carried in the error for diagnosis.
134
+ */
135
+ export declare function checkWriteAllowed(operation: string, modelName?: string): void;
136
+ //# sourceMappingURL=tx-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx-options.d.ts","sourceRoot":"","sources":["../../src/scp/tx-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,CAAC;AAIrE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAEnF,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAe7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,SAAS,MAAM,EAAE,CAoB/F;AAID;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,qGAAqG;IACrG,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,oFAAoF;IACpF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,gGAAgG;IAChG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CAC9C;AAED,0FAA0F;AAC1F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAC;CAC7C;AAED,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,kBAAuB,GAAG,iBAAiB,CASjF;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,OAAO,GAAG,OAAO,CAsBpG;AAED,sCAAsC;AACtC,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAkBD,sGAAsG;AACtG,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE9C;AAED,gGAAgG;AAChG,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,qFAAqF;AACrF,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAG7E"}