litedbmodel 2.0.2 → 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 (193) 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 +127 -24
  15. package/dist/decorators.js.map +1 -1
  16. package/dist/drivers/mysql.d.ts.map +1 -1
  17. package/dist/drivers/mysql.js +12 -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 +13 -2
  21. package/dist/drivers/postgres.js.map +1 -1
  22. package/dist/drivers/sqlite.d.ts +2 -0
  23. package/dist/drivers/sqlite.d.ts.map +1 -1
  24. package/dist/drivers/sqlite.js +49 -4
  25. package/dist/drivers/sqlite.js.map +1 -1
  26. package/dist/index.cjs +10741 -0
  27. package/dist/index.d.cts +1 -0
  28. package/dist/scp/coltype.d.ts +108 -0
  29. package/dist/scp/coltype.d.ts.map +1 -1
  30. package/dist/scp/coltype.js +293 -6
  31. package/dist/scp/coltype.js.map +1 -1
  32. package/dist/scp/connection-routing.d.ts +312 -0
  33. package/dist/scp/connection-routing.d.ts.map +1 -0
  34. package/dist/scp/connection-routing.js +394 -0
  35. package/dist/scp/connection-routing.js.map +1 -0
  36. package/dist/scp/dbmodel-runtime.d.ts +101 -0
  37. package/dist/scp/dbmodel-runtime.d.ts.map +1 -0
  38. package/dist/scp/dbmodel-runtime.js +174 -0
  39. package/dist/scp/dbmodel-runtime.js.map +1 -0
  40. package/dist/scp/decorator-adapter.d.ts +196 -0
  41. package/dist/scp/decorator-adapter.d.ts.map +1 -0
  42. package/dist/scp/decorator-adapter.js +286 -0
  43. package/dist/scp/decorator-adapter.js.map +1 -0
  44. package/dist/scp/emit/emitter.d.ts +108 -0
  45. package/dist/scp/emit/emitter.d.ts.map +1 -0
  46. package/dist/scp/emit/emitter.js +782 -0
  47. package/dist/scp/emit/emitter.js.map +1 -0
  48. package/dist/scp/emit/endpoint.d.ts +248 -0
  49. package/dist/scp/emit/endpoint.d.ts.map +1 -0
  50. package/dist/scp/emit/endpoint.js +20 -0
  51. package/dist/scp/emit/endpoint.js.map +1 -0
  52. package/dist/scp/emit/index.d.ts +11 -0
  53. package/dist/scp/emit/index.d.ts.map +1 -0
  54. package/dist/scp/emit/index.js +13 -0
  55. package/dist/scp/emit/index.js.map +1 -0
  56. package/dist/scp/errors.d.ts +45 -1
  57. package/dist/scp/errors.d.ts.map +1 -1
  58. package/dist/scp/errors.js +47 -1
  59. package/dist/scp/errors.js.map +1 -1
  60. package/dist/scp/exec-context.d.ts +390 -0
  61. package/dist/scp/exec-context.d.ts.map +1 -0
  62. package/dist/scp/exec-context.js +540 -0
  63. package/dist/scp/exec-context.js.map +1 -0
  64. package/dist/scp/grouping.d.ts +32 -0
  65. package/dist/scp/grouping.d.ts.map +1 -0
  66. package/dist/scp/grouping.js +0 -0
  67. package/dist/scp/grouping.js.map +1 -0
  68. package/dist/scp/index.cjs +6432 -17579
  69. package/dist/scp/index.d.cts +1 -0
  70. package/dist/scp/index.d.mts +1 -0
  71. package/dist/scp/index.d.ts +51 -52
  72. package/dist/scp/index.d.ts.map +1 -1
  73. package/dist/scp/index.js +189 -152
  74. package/dist/scp/index.js.map +1 -1
  75. package/dist/scp/index.mjs +6067 -3659
  76. package/dist/scp/leaf-transport.d.ts +50 -0
  77. package/dist/scp/leaf-transport.d.ts.map +1 -0
  78. package/dist/scp/leaf-transport.js +92 -0
  79. package/dist/scp/leaf-transport.js.map +1 -0
  80. package/dist/scp/leaves.d.ts +174 -0
  81. package/dist/scp/leaves.d.ts.map +1 -0
  82. package/dist/scp/leaves.js +287 -0
  83. package/dist/scp/leaves.js.map +1 -0
  84. package/dist/scp/limit-config.d.ts +118 -0
  85. package/dist/scp/limit-config.d.ts.map +1 -0
  86. package/dist/scp/limit-config.js +126 -0
  87. package/dist/scp/limit-config.js.map +1 -0
  88. package/dist/scp/makesql/compile-relation.d.ts +49 -23
  89. package/dist/scp/makesql/compile-relation.d.ts.map +1 -1
  90. package/dist/scp/makesql/compile-relation.js +101 -76
  91. package/dist/scp/makesql/compile-relation.js.map +1 -1
  92. package/dist/scp/makesql/compile-select.d.ts +45 -10
  93. package/dist/scp/makesql/compile-select.d.ts.map +1 -1
  94. package/dist/scp/makesql/compile-select.js +50 -10
  95. package/dist/scp/makesql/compile-select.js.map +1 -1
  96. package/dist/scp/makesql/handler.d.ts +1 -1
  97. package/dist/scp/makesql/handler.d.ts.map +1 -1
  98. package/dist/scp/makesql/index.d.ts +7 -10
  99. package/dist/scp/makesql/index.d.ts.map +1 -1
  100. package/dist/scp/makesql/index.js +19 -30
  101. package/dist/scp/makesql/index.js.map +1 -1
  102. package/dist/scp/makesql/json-array.d.ts +65 -0
  103. package/dist/scp/makesql/json-array.d.ts.map +1 -1
  104. package/dist/scp/makesql/json-array.js +99 -10
  105. package/dist/scp/makesql/json-array.js.map +1 -1
  106. package/dist/scp/makesql/json-batch.d.ts.map +1 -1
  107. package/dist/scp/makesql/json-batch.js +21 -19
  108. package/dist/scp/makesql/json-batch.js.map +1 -1
  109. package/dist/scp/makesql/makesql.d.ts +1 -1
  110. package/dist/scp/makesql/makesql.d.ts.map +1 -1
  111. package/dist/scp/makesql/mysql-returning.d.ts +93 -0
  112. package/dist/scp/makesql/mysql-returning.d.ts.map +1 -0
  113. package/dist/scp/makesql/mysql-returning.js +215 -0
  114. package/dist/scp/makesql/mysql-returning.js.map +1 -0
  115. package/dist/scp/makesql/outtype.d.ts +75 -34
  116. package/dist/scp/makesql/outtype.d.ts.map +1 -1
  117. package/dist/scp/makesql/outtype.js +91 -118
  118. package/dist/scp/makesql/outtype.js.map +1 -1
  119. package/dist/scp/makesql/pool-executor.d.ts +135 -13
  120. package/dist/scp/makesql/pool-executor.d.ts.map +1 -1
  121. package/dist/scp/makesql/pool-executor.js +229 -21
  122. package/dist/scp/makesql/pool-executor.js.map +1 -1
  123. package/dist/scp/makesql/tx.d.ts +107 -22
  124. package/dist/scp/makesql/tx.d.ts.map +1 -1
  125. package/dist/scp/makesql/tx.js +451 -97
  126. package/dist/scp/makesql/tx.js.map +1 -1
  127. package/dist/scp/makesql/writeouttype.d.ts +7 -8
  128. package/dist/scp/makesql/writeouttype.d.ts.map +1 -1
  129. package/dist/scp/makesql/writeouttype.js +8 -7
  130. package/dist/scp/makesql/writeouttype.js.map +1 -1
  131. package/dist/scp/middleware.d.ts +287 -0
  132. package/dist/scp/middleware.d.ts.map +1 -0
  133. package/dist/scp/middleware.js +358 -0
  134. package/dist/scp/middleware.js.map +1 -0
  135. package/dist/scp/relation.d.ts +80 -9
  136. package/dist/scp/relation.d.ts.map +1 -1
  137. package/dist/scp/relation.js +198 -78
  138. package/dist/scp/relation.js.map +1 -1
  139. package/dist/scp/tx-options.d.ts +136 -0
  140. package/dist/scp/tx-options.d.ts.map +1 -0
  141. package/dist/scp/tx-options.js +184 -0
  142. package/dist/scp/tx-options.js.map +1 -0
  143. package/dist/scp/write-bundle.d.ts +131 -0
  144. package/dist/scp/write-bundle.d.ts.map +1 -0
  145. package/dist/scp/write-bundle.js +160 -0
  146. package/dist/scp/write-bundle.js.map +1 -0
  147. package/dist/types.d.ts +7 -0
  148. package/dist/types.d.ts.map +1 -1
  149. package/dist/types.js.map +1 -1
  150. package/docs/BENCHMARK.md +58 -56
  151. package/docs/benchmark-chart.svg +166 -166
  152. package/docs/design/phase-a-execution-context.md +139 -0
  153. package/package.json +16 -9
  154. package/dist/scp/authoring-sql.d.ts +0 -134
  155. package/dist/scp/authoring-sql.d.ts.map +0 -1
  156. package/dist/scp/authoring-sql.js +0 -191
  157. package/dist/scp/authoring-sql.js.map +0 -1
  158. package/dist/scp/authoring.d.ts +0 -155
  159. package/dist/scp/authoring.d.ts.map +0 -1
  160. package/dist/scp/authoring.js +0 -162
  161. package/dist/scp/authoring.js.map +0 -1
  162. package/dist/scp/catalog.d.ts +0 -94
  163. package/dist/scp/catalog.d.ts.map +0 -1
  164. package/dist/scp/catalog.js +0 -234
  165. package/dist/scp/catalog.js.map +0 -1
  166. package/dist/scp/codegen.d.ts +0 -189
  167. package/dist/scp/codegen.d.ts.map +0 -1
  168. package/dist/scp/codegen.js +0 -421
  169. package/dist/scp/codegen.js.map +0 -1
  170. package/dist/scp/find-filter-guard.d.ts +0 -68
  171. package/dist/scp/find-filter-guard.d.ts.map +0 -1
  172. package/dist/scp/find-filter-guard.js +0 -88
  173. package/dist/scp/find-filter-guard.js.map +0 -1
  174. package/dist/scp/guard.d.ts +0 -43
  175. package/dist/scp/guard.d.ts.map +0 -1
  176. package/dist/scp/guard.js +0 -134
  177. package/dist/scp/guard.js.map +0 -1
  178. package/dist/scp/makesql/authoring-compile.d.ts +0 -90
  179. package/dist/scp/makesql/authoring-compile.d.ts.map +0 -1
  180. package/dist/scp/makesql/authoring-compile.js +0 -494
  181. package/dist/scp/makesql/authoring-compile.js.map +0 -1
  182. package/dist/scp/makesql/ir.d.ts +0 -42
  183. package/dist/scp/makesql/ir.d.ts.map +0 -1
  184. package/dist/scp/makesql/ir.js +0 -66
  185. package/dist/scp/makesql/ir.js.map +0 -1
  186. package/dist/scp/makesql/static-bundle.d.ts +0 -187
  187. package/dist/scp/makesql/static-bundle.d.ts.map +0 -1
  188. package/dist/scp/makesql/static-bundle.js +0 -1113
  189. package/dist/scp/makesql/static-bundle.js.map +0 -1
  190. package/dist/scp/runtime.d.ts +0 -242
  191. package/dist/scp/runtime.d.ts.map +0 -1
  192. package/dist/scp/runtime.js +0 -400
  193. package/dist/scp/runtime.js.map +0 -1
@@ -0,0 +1,118 @@
1
+ /**
2
+ * litedbmodel v2 SCP — hard-limit runaway prevention config (Phase E-2, epic #74; v1 parity —
3
+ * `DBModel.setLimitConfig` / `_limitConfig`).
4
+ *
5
+ * A read that forgot its WHERE clause, or a hasMany relation batch fanning out over an accidental
6
+ * cross-join, can load an unbounded result set. v1 guarded this with a global `findHardLimit` /
7
+ * `hasManyHardLimit` (plus a per-relation override); this module is the v2 SCP equivalent — the
8
+ * SHARED config surface the TS runtime reads at COMPILE time to bake the effective caps onto the
9
+ * portable artifacts (the {@link import('./makesql/static-bundle').ReadGraph} find-guard and each
10
+ * {@link import('./relation').RelationOp}). Because the caps are baked at compile, the native ports
11
+ * (#100-103) need NO config surface of their own: they read the resolved `hardLimit` off the JSON
12
+ * artifact and run the SAME post-fetch throw.
13
+ *
14
+ * ## Semantics (v1 parity — match precisely)
15
+ *
16
+ * - `findHardLimit` — a top-level read (find/read) exceeding this THROWS {@link
17
+ * import('./errors').LimitExceededError} (`context: 'find'`). The read injects `LIMIT hardLimit +
18
+ * 1` when the author set no explicit limit, so the throw only asserts the total EXCEEDS the cap.
19
+ * - `hasManyHardLimit` — a hasMany relation batch whose TOTAL fetched rows exceed this THROWS
20
+ * (`context: 'relation'`, EXACT count). A per-relation `hardLimit` override wins over the global.
21
+ * - `null` DISABLES the check (a per-relation `hardLimit: null` disables it for that relation even
22
+ * when the global is set); `undefined` on a relation means "use the global".
23
+ * - A raw-SQL relation with an INTRINSIC per-parent `LIMIT` (a `hasMany` `RelationDecl.limit`) skips
24
+ * the batch-total check — its fanout is already bounded per parent by the window.
25
+ *
26
+ * The config is a process-global singleton (v1 `DBModel._limitConfig`). `setLimitConfig` MERGES
27
+ * (v1 parity), `resetLimitConfig` clears it (test isolation). The defaults are BOTH disabled
28
+ * (`undefined` ⇒ no cap) so nothing changes for a caller who never opts in.
29
+ */
30
+ /**
31
+ * Global hard-limit config (spec §E-2; v1 `LimitConfig`). Both caps default to disabled.
32
+ * This is the AUTHORING/config surface — the resolved caps are baked onto the compiled artifacts.
33
+ */
34
+ export interface LimitConfig {
35
+ /**
36
+ * Hard cap for a top-level read (find/read). A read returning more than this THROWS
37
+ * {@link import('./errors').LimitExceededError}. `null` / `undefined` ⇒ disabled (no cap).
38
+ */
39
+ readonly findHardLimit?: number | null;
40
+ /**
41
+ * Hard cap for a hasMany relation batch TOTAL. A batch fetching more than this THROWS. A
42
+ * per-relation `hardLimit` override wins. `null` / `undefined` ⇒ disabled (no cap).
43
+ */
44
+ readonly hasManyHardLimit?: number | null;
45
+ }
46
+ /**
47
+ * MERGE `config` into the global hard-limit config (v1 `DBModel.setLimitConfig` parity — a partial
48
+ * update, not a replace). Call once at app start:
49
+ * `setLimitConfig({ findHardLimit: 5000, hasManyHardLimit: 500 })`.
50
+ * Pass `null` for a key to explicitly DISABLE that check.
51
+ */
52
+ export declare function setLimitConfig(config: LimitConfig): void;
53
+ /** Read a shallow copy of the current global hard-limit config. */
54
+ export declare function getLimitConfig(): LimitConfig;
55
+ /** Clear the global hard-limit config back to the disabled default (test isolation). */
56
+ export declare function resetLimitConfig(): void;
57
+ /**
58
+ * Resolve the effective `findHardLimit`: the value passed in `override` (when the caller supplies a
59
+ * config explicitly, e.g. at compile) else the global. Returns `null` (disabled) or a non-negative
60
+ * integer cap. `undefined` normalizes to the global; an explicit `null` disables.
61
+ */
62
+ export declare function resolveFindHardLimit(override?: number | null): number | null;
63
+ /**
64
+ * Resolve the effective hasMany cap for ONE relation (v1 `_selectForRelation` precedence):
65
+ * per-relation `perRelation` (`null` disables, a number overrides) wins over the `global`
66
+ * `hasManyHardLimit`; `undefined` on the relation falls through to the global. Returns `null`
67
+ * (disabled) or a non-negative integer cap.
68
+ */
69
+ export declare function resolveHasManyHardLimit(perRelation?: number | null, global?: number | null): number | null;
70
+ /**
71
+ * The find hard-limit READ-BOUNDARY check — the twin of {@link assertRelationHardLimit}. The emitter
72
+ * bakes `LIMIT cap + 1` into the capped read's static SQL (a BOUNDED fetch: at most `cap + 1` rows
73
+ * ever leave the DB), and this asserts the result: `cap + 1` rows means the true total EXCEEDS the
74
+ * cap, so it throws {@link LimitExceededError} with `context:'find'` and `count = rows.length` (the
75
+ * fetch size — the total is only known to exceed).
76
+ *
77
+ * It lives at the boundary because SCP has no throw: a generated module returns rows, and the caller
78
+ * that asked for the capped endpoint enforces the policy. `cap === undefined` ⇒ the endpoint baked no
79
+ * guard ⇒ no check.
80
+ */
81
+ export declare function assertFindHardLimit(rows: readonly unknown[], cap: number | undefined, model: string): void;
82
+ /**
83
+ * The RELATION runaway guard, resolved at compile onto a {@link import('./relation').RelationOp} and
84
+ * carried verbatim to whoever fetches that relation's child rows: the effective batch-total `limit`
85
+ * plus the identity the error reports (`model` = the child TABLE, `relation` = the relation name).
86
+ *
87
+ * It is a PLAIN JSON record on purpose. The compiled op is the SSoT, and the same record is what the
88
+ * emitter bakes into the generated relation child fetch (`leaf-transport.Db.executeSQL`'s `guard`
89
+ * port), so the codegen path and the typed-object/lazy path enforce ONE resolved cap — there is no
90
+ * second config surface anywhere downstream, in any language.
91
+ */
92
+ export interface RelationGuard {
93
+ /** The effective batch-total row cap (per-relation override → global, resolved at compile). */
94
+ readonly limit: number;
95
+ /**
96
+ * The child (target) TABLE — what {@link LimitExceededError.model} reports in the relation context.
97
+ * Optional exactly as the error's own field is: an op compiled without a target table reports
98
+ * `unknown` rather than inventing a name.
99
+ */
100
+ readonly model?: string;
101
+ /** The relation NAME — what {@link LimitExceededError.relation} reports. */
102
+ readonly relation: string;
103
+ }
104
+ /**
105
+ * The relation hard-limit POST-FETCH check — the ONE `count > cap ⇒ throw` primitive for the relation
106
+ * context, shared by BOTH v2 read surfaces: the typed-object / lazy batch
107
+ * ({@link import('./relation').runRelationOp}) and the CODEGEN path, where the `executeSQL` leaf runs
108
+ * it on the raw child rows of a guarded relation fetch — the only place the raw child rows exist
109
+ * (past `group` the graph is nested, and SCP itself has no throw).
110
+ *
111
+ * Unlike the find twin the batch is fetched IN FULL (v1 `_selectForRelation` parity — no `LIMIT
112
+ * cap + 1` on a relation batch), so `count` is the EXACT batch total, exactly as
113
+ * {@link import('./errors').LimitExceededContext} declares and as the rust/go/python/php ports mirror.
114
+ * `guard == null` ⇒ the relation baked no cap (disabled, or an intrinsic per-parent `limit` window
115
+ * whose fanout is already bounded) ⇒ no check.
116
+ */
117
+ export declare function assertRelationHardLimit(rows: readonly unknown[], guard: RelationGuard | null | undefined): void;
118
+ //# sourceMappingURL=limit-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-config.d.ts","sourceRoot":"","sources":["../../src/scp/limit-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAKD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAExD;AAED,mEAAmE;AACnE,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG5E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK1G;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAG1G;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,+FAA+F;IAC/F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAK/G"}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — hard-limit runaway prevention config (Phase E-2, epic #74; v1 parity —
4
+ * `DBModel.setLimitConfig` / `_limitConfig`).
5
+ *
6
+ * A read that forgot its WHERE clause, or a hasMany relation batch fanning out over an accidental
7
+ * cross-join, can load an unbounded result set. v1 guarded this with a global `findHardLimit` /
8
+ * `hasManyHardLimit` (plus a per-relation override); this module is the v2 SCP equivalent — the
9
+ * SHARED config surface the TS runtime reads at COMPILE time to bake the effective caps onto the
10
+ * portable artifacts (the {@link import('./makesql/static-bundle').ReadGraph} find-guard and each
11
+ * {@link import('./relation').RelationOp}). Because the caps are baked at compile, the native ports
12
+ * (#100-103) need NO config surface of their own: they read the resolved `hardLimit` off the JSON
13
+ * artifact and run the SAME post-fetch throw.
14
+ *
15
+ * ## Semantics (v1 parity — match precisely)
16
+ *
17
+ * - `findHardLimit` — a top-level read (find/read) exceeding this THROWS {@link
18
+ * import('./errors').LimitExceededError} (`context: 'find'`). The read injects `LIMIT hardLimit +
19
+ * 1` when the author set no explicit limit, so the throw only asserts the total EXCEEDS the cap.
20
+ * - `hasManyHardLimit` — a hasMany relation batch whose TOTAL fetched rows exceed this THROWS
21
+ * (`context: 'relation'`, EXACT count). A per-relation `hardLimit` override wins over the global.
22
+ * - `null` DISABLES the check (a per-relation `hardLimit: null` disables it for that relation even
23
+ * when the global is set); `undefined` on a relation means "use the global".
24
+ * - A raw-SQL relation with an INTRINSIC per-parent `LIMIT` (a `hasMany` `RelationDecl.limit`) skips
25
+ * the batch-total check — its fanout is already bounded per parent by the window.
26
+ *
27
+ * The config is a process-global singleton (v1 `DBModel._limitConfig`). `setLimitConfig` MERGES
28
+ * (v1 parity), `resetLimitConfig` clears it (test isolation). The defaults are BOTH disabled
29
+ * (`undefined` ⇒ no cap) so nothing changes for a caller who never opts in.
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.setLimitConfig = setLimitConfig;
33
+ exports.getLimitConfig = getLimitConfig;
34
+ exports.resetLimitConfig = resetLimitConfig;
35
+ exports.resolveFindHardLimit = resolveFindHardLimit;
36
+ exports.resolveHasManyHardLimit = resolveHasManyHardLimit;
37
+ exports.assertFindHardLimit = assertFindHardLimit;
38
+ exports.assertRelationHardLimit = assertRelationHardLimit;
39
+ const errors_1 = require("./errors");
40
+ /** The process-global config singleton (v1 `DBModel._limitConfig`). Both caps disabled by default. */
41
+ let globalLimitConfig = {};
42
+ /**
43
+ * MERGE `config` into the global hard-limit config (v1 `DBModel.setLimitConfig` parity — a partial
44
+ * update, not a replace). Call once at app start:
45
+ * `setLimitConfig({ findHardLimit: 5000, hasManyHardLimit: 500 })`.
46
+ * Pass `null` for a key to explicitly DISABLE that check.
47
+ */
48
+ function setLimitConfig(config) {
49
+ globalLimitConfig = { ...globalLimitConfig, ...config };
50
+ }
51
+ /** Read a shallow copy of the current global hard-limit config. */
52
+ function getLimitConfig() {
53
+ return { ...globalLimitConfig };
54
+ }
55
+ /** Clear the global hard-limit config back to the disabled default (test isolation). */
56
+ function resetLimitConfig() {
57
+ globalLimitConfig = {};
58
+ }
59
+ /**
60
+ * Resolve the effective `findHardLimit`: the value passed in `override` (when the caller supplies a
61
+ * config explicitly, e.g. at compile) else the global. Returns `null` (disabled) or a non-negative
62
+ * integer cap. `undefined` normalizes to the global; an explicit `null` disables.
63
+ */
64
+ function resolveFindHardLimit(override) {
65
+ const v = override !== undefined ? override : globalLimitConfig.findHardLimit;
66
+ return normalizeCap(v, 'findHardLimit');
67
+ }
68
+ /**
69
+ * Resolve the effective hasMany cap for ONE relation (v1 `_selectForRelation` precedence):
70
+ * per-relation `perRelation` (`null` disables, a number overrides) wins over the `global`
71
+ * `hasManyHardLimit`; `undefined` on the relation falls through to the global. Returns `null`
72
+ * (disabled) or a non-negative integer cap.
73
+ */
74
+ function resolveHasManyHardLimit(perRelation, global) {
75
+ // v1: `perRelationHardLimit === null ? null : perRelationHardLimit ?? globalHasManyHardLimit`.
76
+ const g = global !== undefined ? global : globalLimitConfig.hasManyHardLimit;
77
+ const raw = perRelation === null ? null : perRelation !== undefined ? perRelation : g;
78
+ return normalizeCap(raw, 'hasManyHardLimit');
79
+ }
80
+ /**
81
+ * The find hard-limit READ-BOUNDARY check — the twin of {@link assertRelationHardLimit}. The emitter
82
+ * bakes `LIMIT cap + 1` into the capped read's static SQL (a BOUNDED fetch: at most `cap + 1` rows
83
+ * ever leave the DB), and this asserts the result: `cap + 1` rows means the true total EXCEEDS the
84
+ * cap, so it throws {@link LimitExceededError} with `context:'find'` and `count = rows.length` (the
85
+ * fetch size — the total is only known to exceed).
86
+ *
87
+ * It lives at the boundary because SCP has no throw: a generated module returns rows, and the caller
88
+ * that asked for the capped endpoint enforces the policy. `cap === undefined` ⇒ the endpoint baked no
89
+ * guard ⇒ no check.
90
+ */
91
+ function assertFindHardLimit(rows, cap, model) {
92
+ if (cap === undefined)
93
+ return;
94
+ if (rows.length > cap)
95
+ throw new errors_1.LimitExceededError(cap, rows.length, 'find', model);
96
+ }
97
+ /**
98
+ * The relation hard-limit POST-FETCH check — the ONE `count > cap ⇒ throw` primitive for the relation
99
+ * context, shared by BOTH v2 read surfaces: the typed-object / lazy batch
100
+ * ({@link import('./relation').runRelationOp}) and the CODEGEN path, where the `executeSQL` leaf runs
101
+ * it on the raw child rows of a guarded relation fetch — the only place the raw child rows exist
102
+ * (past `group` the graph is nested, and SCP itself has no throw).
103
+ *
104
+ * Unlike the find twin the batch is fetched IN FULL (v1 `_selectForRelation` parity — no `LIMIT
105
+ * cap + 1` on a relation batch), so `count` is the EXACT batch total, exactly as
106
+ * {@link import('./errors').LimitExceededContext} declares and as the rust/go/python/php ports mirror.
107
+ * `guard == null` ⇒ the relation baked no cap (disabled, or an intrinsic per-parent `limit` window
108
+ * whose fanout is already bounded) ⇒ no check.
109
+ */
110
+ function assertRelationHardLimit(rows, guard) {
111
+ if (guard === null || guard === undefined)
112
+ return;
113
+ if (rows.length > guard.limit) {
114
+ throw new errors_1.LimitExceededError(guard.limit, rows.length, 'relation', guard.model, guard.relation);
115
+ }
116
+ }
117
+ /** Validate + normalize a cap: `null`/`undefined` ⇒ null (disabled); else a non-negative integer. */
118
+ function normalizeCap(v, field) {
119
+ if (v === null || v === undefined)
120
+ return null;
121
+ if (!Number.isInteger(v) || v < 0) {
122
+ throw new Error(`limit-config: ${field} must be a non-negative integer or null (got ${String(v)})`);
123
+ }
124
+ return v;
125
+ }
126
+ //# sourceMappingURL=limit-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limit-config.js","sourceRoot":"","sources":["../../src/scp/limit-config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;AA8BH,wCAEC;AAGD,wCAEC;AAGD,4CAEC;AAOD,oDAGC;AAQD,0DAKC;AAaD,kDAGC;AAsCD,0DAKC;AA1HD,qCAA8C;AAmB9C,sGAAsG;AACtG,IAAI,iBAAiB,GAAgB,EAAE,CAAC;AAExC;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,MAAmB;IAChD,iBAAiB,GAAG,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAAC;AAC1D,CAAC;AAED,mEAAmE;AACnE,SAAgB,cAAc;IAC5B,OAAO,EAAE,GAAG,iBAAiB,EAAE,CAAC;AAClC,CAAC;AAED,wFAAwF;AACxF,SAAgB,gBAAgB;IAC9B,iBAAiB,GAAG,EAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,QAAwB;IAC3D,MAAM,CAAC,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,aAAa,CAAC;IAC9E,OAAO,YAAY,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CAAC,WAA2B,EAAE,MAAsB;IACzF,+FAA+F;IAC/F,MAAM,CAAC,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,gBAAgB,CAAC;IAC7E,MAAM,GAAG,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,OAAO,YAAY,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAAC,IAAwB,EAAE,GAAuB,EAAE,KAAa;IAClG,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO;IAC9B,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,2BAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACvF,CAAC;AAyBD;;;;;;;;;;;;GAYG;AACH,SAAgB,uBAAuB,CAAC,IAAwB,EAAE,KAAuC;IACvG,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAClD,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,IAAI,2BAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,CAA4B,EAAE,KAAa;IAC/D,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,gDAAgD,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -15,6 +15,12 @@
15
15
  * MySQL/SQLite `SELECT … FROM t WHERE (k1, k2) IN ((?, ?), …)`
16
16
  * composite-key, per-parent limit: PG LATERAL composite / others ROW_NUMBER composite.
17
17
  *
18
+ * The STATIC composite forms ({@link compileCompositeKeyStaticUnlimited} /
19
+ * {@link compileCompositeKeyStaticLimited}) deviate from those v1 texts on EVERY dialect: they bind
20
+ * the key set as ONE array-of-tuples param (RESULT parity, not byte-identity) so a composite batch
21
+ * rides the same three-leaf transport as everything else. The v1 texts stay proven by the
22
+ * value-expanding builders below.
23
+ *
18
24
  * The PG type text (`?::type[]`) comes from the ORIGINAL `inferPgArrayType` (sqlCast
19
25
  * wins, else element-type inference). The .rs regressions are NOT reproduced: PG
20
26
  * per-parent-limit is LATERAL (not ROW_NUMBER), and PG types are sqlCast-driven (not
@@ -26,6 +32,13 @@
26
32
  import { type ConditionObject } from '../../DBConditions';
27
33
  import type { MakeSQL } from './makesql';
28
34
  import type { Dialect } from './handler';
35
+ /**
36
+ * The PG ELEMENT type of a value set — the ONE type inference every PG cast in this module is built
37
+ * on ({@link inferPgArrayType} appends `[]`; the composite key-row expansion casts each key column
38
+ * with it). Reproduces the ORIGINAL `LazyRelation.inferPgArrayType`'s element decision (the PG
39
+ * anchor — NOT the .rs coarse text-folding).
40
+ */
41
+ export declare function inferPgElementType(values: unknown[]): string;
29
42
  /**
30
43
  * Reproduce the ORIGINAL `LazyRelation.inferPgArrayType`: sqlCast wins (`<cast>[]`);
31
44
  * otherwise infer the element type from the sample values. Byte-identical to the
@@ -71,20 +84,32 @@ export interface RelationCompileBase {
71
84
  */
72
85
  deferPgArrayCast?: boolean;
73
86
  }
87
+ /** The STATIC composite-key builders' options: {@link RelationCompileBase} + the PG key-column types. */
88
+ export interface CompositeStaticBase extends RelationCompileBase {
89
+ /**
90
+ * PostgreSQL only: the PG ELEMENT type of each key column, positional with `targetKeys`, derived
91
+ * from the model's DECLARED column type (the schema SoT — never from the values, which are unknown
92
+ * at compile and empty at call time often enough to matter; the SAME rule the composite `tupleIn`
93
+ * predicate follows, `json-array.ts` `pgElementTypes`). The key rows carry these types so the JOIN
94
+ * compares `int = int` / `bigint = bigint` against the child key columns instead of `… = text`.
95
+ */
96
+ readonly pgKeyTypes?: readonly string[];
97
+ }
74
98
  /**
75
99
  * The STATIC composite-key batch forms (#47 item 1) — length-INDEPENDENT so the compiled `op.sql`
76
- * is fixed (one param per column on PG; ONE JSON param on MySQL/SQLite), the SAME static-op
77
- * property the single-key relation forms have. PG stays byte-identical to v1's `unnest`-JOIN
78
- * (`batchLoadWithUnnestJoin`), with the element-type cast DEFERRED (#46) to render from the real
79
- * keys. MySQL/SQLite use the single-JSON tuple form (the owner-approved deviation the single-key
80
- * IN-list and the batch UPDATE composite already use — RESULT parity, NOT byte-identity): a
81
- * `JSON_TABLE`/`json_each` subquery over one JSON array-of-tuples param. The v1 literal
82
- * `(k1,k2) IN ((?,?),…)` byte-form stays proven by the golden `compileCompositeKeyUnlimited`.
100
+ * is fixed (ONE JSON array-of-tuples param on EVERY dialect), the SAME static-op property the
101
+ * single-key relation forms have. Every dialect now consumes the SAME single key param the relation
102
+ * key set is produced as (`pluck` — one array of key TUPLES): MySQL/SQLite expand it with
103
+ * `JSON_TABLE`/`json_each`, PostgreSQL with {@link pgCompositeKeyRows} (#159). This is the
104
+ * owner-approved deviation the single-key IN-list and the batch UPDATE composite already use —
105
+ * RESULT parity, NOT byte-identity with v1; the v1 literal `(k1,k2) IN ((?,?),…)` /
106
+ * `unnest(?::t1[], ?::t2[])` byte-forms stay proven by the goldens
107
+ * {@link compileCompositeKeyUnlimited} / {@link compileCompositeKeyLimited}.
83
108
  *
84
109
  * The JSON tuple param is `[[k1a,k2a],[k1b,k2b],…]` (positional element arrays), read back by
85
110
  * ordinal path (`$[0]`, `$[1]`, …) so no per-column JSON key names are needed.
86
111
  */
87
- export declare function compileCompositeKeyStaticUnlimited(opts: RelationCompileBase & {
112
+ export declare function compileCompositeKeyStaticUnlimited(opts: CompositeStaticBase & {
88
113
  targetKeys: string[];
89
114
  }): MakeSQL;
90
115
  /**
@@ -131,26 +156,27 @@ export declare function compileCompositeKeyLimited(opts: RelationCompileBase & {
131
156
  /**
132
157
  * The STATIC composite-key per-parent-LIMIT batch form (#47 last completeness gap) — the
133
158
  * length-INDEPENDENT sibling of {@link compileCompositeKeyLimited}, so the compiled `op.sql` is
134
- * FIXED (one array param per key column on PG; ONE JSON array-of-tuples param on MySQL/SQLite) and
135
- * can be a STATIC bundle op — exactly the property {@link compileSingleKeyLimited} and
136
- * {@link compileCompositeKeyStaticUnlimited} already have.
159
+ * FIXED (ONE JSON array-of-tuples param on every dialect) and can be a STATIC bundle op — exactly
160
+ * the property {@link compileSingleKeyLimited} and {@link compileCompositeKeyStaticUnlimited}
161
+ * already have.
137
162
  *
138
- * The per-parent window is IDENTICAL to the single-key-limited path:
139
- * - **PG**: `CROSS JOIN LATERAL` over `unnest(?::t1[], ?::t2[])` — BYTE-identical to v1's
140
- * `batchLoadWithLateralComposite` (the composite LATERAL is already structurally
141
- * length-independent; only the element-type cast was value-derived, and that is DEFERRED (#46)
142
- * to render from the real keys via {@link PG_ARRAY_CAST_TOKEN}). No deviation on PG.
163
+ * The per-parent window is IDENTICAL to the single-key-limited path, over the SAME single key param:
164
+ * - **PG**: `CROSS JOIN LATERAL` over the typed key rows of {@link pgCompositeKeyRows} — v1's
165
+ * `batchLoadWithLateralComposite` window verbatim, with its per-column `unnest(?::t1[], ?::t2[])`
166
+ * key source replaced by the single-JSON-tuple expansion (#159), so the key set binds as the ONE
167
+ * array `pluck` yields.
143
168
  * - **MySQL/SQLite**: the SAME `ROW_NUMBER() OVER (PARTITION BY <keys> ORDER BY <order>)` CTE +
144
169
  * `_rn <= limit` filter v1's `batchLoadWithRowNumberComposite` emits — but the CTE membership
145
170
  * WHERE is the STATIC JSON-tuple predicate ({@link compositeJsonMembership}) instead of v1's
146
- * value-dependent `(k1,k2) IN ((?,?),…)`. This is the owner-sanctioned static deviation the
147
- * composite UNLIMITED form ({@link compileCompositeKeyStaticUnlimited}) and the single-key
148
- * IN-list already use: the JSON subquery selects the SAME child rows the tuple-IN would, the
149
- * window partitions/orders identically, so it is RESULT-parity to v1 (proven live). The v1
150
- * literal `(k1,k2) IN ((?,?),…)` byte-form stays proven by the golden
151
- * {@link compileCompositeKeyLimited}.
171
+ * value-dependent `(k1,k2) IN ((?,?),…)`.
172
+ *
173
+ * Both are the owner-sanctioned static deviation the composite UNLIMITED form
174
+ * ({@link compileCompositeKeyStaticUnlimited}) and the single-key IN-list already use: the key rows
175
+ * select the SAME child rows the value-expanded form would and the window partitions/orders
176
+ * identically, so it is RESULT-parity to v1 (proven live). The v1 byte-forms stay proven by the
177
+ * golden {@link compileCompositeKeyLimited}.
152
178
  */
153
- export declare function compileCompositeKeyStaticLimited(opts: RelationCompileBase & {
179
+ export declare function compileCompositeKeyStaticLimited(opts: CompositeStaticBase & {
154
180
  targetKeys: string[];
155
181
  limit: number;
156
182
  }): MakeSQL;
@@ -1 +1 @@
1
- {"version":3,"file":"compile-relation.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/compile-relation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAY5E;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAIzE;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GACnD,OAAO,CAmCT;AA4BD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,GACnE,OAAO,CAyBT;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClF,OAAO,CAoCT;AAWD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAA;CAAE,GACxE,OAAO,CAuCT;AAMD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvF,OAAO,CA+CT;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE,OAAO,CA6CT"}
1
+ {"version":3,"file":"compile-relation.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/compile-relation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAW5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAIzE;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAuBD,yGAAyG;AACzG,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AA+BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GACnD,OAAO,CA0BT;AAeD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,GACnE,OAAO,CAyBT;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClF,OAAO,CAoCT;AAWD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAA;CAAE,GACxE,OAAO,CAuCT;AAMD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvF,OAAO,CA+CT;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE,OAAO,CAuCT"}