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.
- package/README.md +7 -0
- package/dist/DBConditions.d.ts.map +1 -1
- package/dist/DBConditions.js +16 -1
- package/dist/DBConditions.js.map +1 -1
- package/dist/DBHandler.d.ts.map +1 -1
- package/dist/DBHandler.js +6 -0
- package/dist/DBHandler.js.map +1 -1
- package/dist/DBModel.d.ts +84 -2
- package/dist/DBModel.d.ts.map +1 -1
- package/dist/DBModel.js +312 -29
- package/dist/DBModel.js.map +1 -1
- package/dist/decorators.d.ts +52 -0
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +127 -24
- package/dist/decorators.js.map +1 -1
- package/dist/drivers/mysql.d.ts.map +1 -1
- package/dist/drivers/mysql.js +12 -2
- package/dist/drivers/mysql.js.map +1 -1
- package/dist/drivers/postgres.d.ts.map +1 -1
- package/dist/drivers/postgres.js +13 -2
- package/dist/drivers/postgres.js.map +1 -1
- package/dist/drivers/sqlite.d.ts +2 -0
- package/dist/drivers/sqlite.d.ts.map +1 -1
- package/dist/drivers/sqlite.js +49 -4
- package/dist/drivers/sqlite.js.map +1 -1
- package/dist/index.cjs +10741 -0
- package/dist/index.d.cts +1 -0
- package/dist/scp/coltype.d.ts +108 -0
- package/dist/scp/coltype.d.ts.map +1 -1
- package/dist/scp/coltype.js +293 -6
- package/dist/scp/coltype.js.map +1 -1
- package/dist/scp/connection-routing.d.ts +312 -0
- package/dist/scp/connection-routing.d.ts.map +1 -0
- package/dist/scp/connection-routing.js +394 -0
- package/dist/scp/connection-routing.js.map +1 -0
- package/dist/scp/dbmodel-runtime.d.ts +101 -0
- package/dist/scp/dbmodel-runtime.d.ts.map +1 -0
- package/dist/scp/dbmodel-runtime.js +174 -0
- package/dist/scp/dbmodel-runtime.js.map +1 -0
- package/dist/scp/decorator-adapter.d.ts +196 -0
- package/dist/scp/decorator-adapter.d.ts.map +1 -0
- package/dist/scp/decorator-adapter.js +286 -0
- package/dist/scp/decorator-adapter.js.map +1 -0
- package/dist/scp/emit/emitter.d.ts +108 -0
- package/dist/scp/emit/emitter.d.ts.map +1 -0
- package/dist/scp/emit/emitter.js +782 -0
- package/dist/scp/emit/emitter.js.map +1 -0
- package/dist/scp/emit/endpoint.d.ts +248 -0
- package/dist/scp/emit/endpoint.d.ts.map +1 -0
- package/dist/scp/emit/endpoint.js +20 -0
- package/dist/scp/emit/endpoint.js.map +1 -0
- package/dist/scp/emit/index.d.ts +11 -0
- package/dist/scp/emit/index.d.ts.map +1 -0
- package/dist/scp/emit/index.js +13 -0
- package/dist/scp/emit/index.js.map +1 -0
- package/dist/scp/errors.d.ts +45 -1
- package/dist/scp/errors.d.ts.map +1 -1
- package/dist/scp/errors.js +47 -1
- package/dist/scp/errors.js.map +1 -1
- package/dist/scp/exec-context.d.ts +390 -0
- package/dist/scp/exec-context.d.ts.map +1 -0
- package/dist/scp/exec-context.js +540 -0
- package/dist/scp/exec-context.js.map +1 -0
- package/dist/scp/grouping.d.ts +32 -0
- package/dist/scp/grouping.d.ts.map +1 -0
- package/dist/scp/grouping.js +0 -0
- package/dist/scp/grouping.js.map +1 -0
- package/dist/scp/index.cjs +6432 -17579
- package/dist/scp/index.d.cts +1 -0
- package/dist/scp/index.d.mts +1 -0
- package/dist/scp/index.d.ts +51 -52
- package/dist/scp/index.d.ts.map +1 -1
- package/dist/scp/index.js +189 -152
- package/dist/scp/index.js.map +1 -1
- package/dist/scp/index.mjs +6067 -3659
- package/dist/scp/leaf-transport.d.ts +50 -0
- package/dist/scp/leaf-transport.d.ts.map +1 -0
- package/dist/scp/leaf-transport.js +92 -0
- package/dist/scp/leaf-transport.js.map +1 -0
- package/dist/scp/leaves.d.ts +174 -0
- package/dist/scp/leaves.d.ts.map +1 -0
- package/dist/scp/leaves.js +287 -0
- package/dist/scp/leaves.js.map +1 -0
- package/dist/scp/limit-config.d.ts +118 -0
- package/dist/scp/limit-config.d.ts.map +1 -0
- package/dist/scp/limit-config.js +126 -0
- package/dist/scp/limit-config.js.map +1 -0
- package/dist/scp/makesql/compile-relation.d.ts +49 -23
- package/dist/scp/makesql/compile-relation.d.ts.map +1 -1
- package/dist/scp/makesql/compile-relation.js +101 -76
- package/dist/scp/makesql/compile-relation.js.map +1 -1
- package/dist/scp/makesql/compile-select.d.ts +45 -10
- package/dist/scp/makesql/compile-select.d.ts.map +1 -1
- package/dist/scp/makesql/compile-select.js +50 -10
- package/dist/scp/makesql/compile-select.js.map +1 -1
- package/dist/scp/makesql/handler.d.ts +1 -1
- package/dist/scp/makesql/handler.d.ts.map +1 -1
- package/dist/scp/makesql/index.d.ts +7 -10
- package/dist/scp/makesql/index.d.ts.map +1 -1
- package/dist/scp/makesql/index.js +19 -30
- package/dist/scp/makesql/index.js.map +1 -1
- package/dist/scp/makesql/json-array.d.ts +65 -0
- package/dist/scp/makesql/json-array.d.ts.map +1 -1
- package/dist/scp/makesql/json-array.js +99 -10
- package/dist/scp/makesql/json-array.js.map +1 -1
- package/dist/scp/makesql/json-batch.d.ts.map +1 -1
- package/dist/scp/makesql/json-batch.js +21 -19
- package/dist/scp/makesql/json-batch.js.map +1 -1
- package/dist/scp/makesql/makesql.d.ts +1 -1
- package/dist/scp/makesql/makesql.d.ts.map +1 -1
- package/dist/scp/makesql/mysql-returning.d.ts +93 -0
- package/dist/scp/makesql/mysql-returning.d.ts.map +1 -0
- package/dist/scp/makesql/mysql-returning.js +215 -0
- package/dist/scp/makesql/mysql-returning.js.map +1 -0
- package/dist/scp/makesql/outtype.d.ts +75 -34
- package/dist/scp/makesql/outtype.d.ts.map +1 -1
- package/dist/scp/makesql/outtype.js +91 -118
- package/dist/scp/makesql/outtype.js.map +1 -1
- package/dist/scp/makesql/pool-executor.d.ts +135 -13
- package/dist/scp/makesql/pool-executor.d.ts.map +1 -1
- package/dist/scp/makesql/pool-executor.js +229 -21
- package/dist/scp/makesql/pool-executor.js.map +1 -1
- package/dist/scp/makesql/tx.d.ts +107 -22
- package/dist/scp/makesql/tx.d.ts.map +1 -1
- package/dist/scp/makesql/tx.js +451 -97
- package/dist/scp/makesql/tx.js.map +1 -1
- package/dist/scp/makesql/writeouttype.d.ts +7 -8
- package/dist/scp/makesql/writeouttype.d.ts.map +1 -1
- package/dist/scp/makesql/writeouttype.js +8 -7
- package/dist/scp/makesql/writeouttype.js.map +1 -1
- package/dist/scp/middleware.d.ts +287 -0
- package/dist/scp/middleware.d.ts.map +1 -0
- package/dist/scp/middleware.js +358 -0
- package/dist/scp/middleware.js.map +1 -0
- package/dist/scp/relation.d.ts +80 -9
- package/dist/scp/relation.d.ts.map +1 -1
- package/dist/scp/relation.js +198 -78
- package/dist/scp/relation.js.map +1 -1
- package/dist/scp/tx-options.d.ts +136 -0
- package/dist/scp/tx-options.d.ts.map +1 -0
- package/dist/scp/tx-options.js +184 -0
- package/dist/scp/tx-options.js.map +1 -0
- package/dist/scp/write-bundle.d.ts +131 -0
- package/dist/scp/write-bundle.d.ts.map +1 -0
- package/dist/scp/write-bundle.js +160 -0
- package/dist/scp/write-bundle.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/BENCHMARK.md +58 -56
- package/docs/benchmark-chart.svg +166 -166
- package/docs/design/phase-a-execution-context.md +139 -0
- package/package.json +16 -9
- package/dist/scp/authoring-sql.d.ts +0 -134
- package/dist/scp/authoring-sql.d.ts.map +0 -1
- package/dist/scp/authoring-sql.js +0 -191
- package/dist/scp/authoring-sql.js.map +0 -1
- package/dist/scp/authoring.d.ts +0 -155
- package/dist/scp/authoring.d.ts.map +0 -1
- package/dist/scp/authoring.js +0 -162
- package/dist/scp/authoring.js.map +0 -1
- package/dist/scp/catalog.d.ts +0 -94
- package/dist/scp/catalog.d.ts.map +0 -1
- package/dist/scp/catalog.js +0 -234
- package/dist/scp/catalog.js.map +0 -1
- package/dist/scp/codegen.d.ts +0 -189
- package/dist/scp/codegen.d.ts.map +0 -1
- package/dist/scp/codegen.js +0 -421
- package/dist/scp/codegen.js.map +0 -1
- package/dist/scp/find-filter-guard.d.ts +0 -68
- package/dist/scp/find-filter-guard.d.ts.map +0 -1
- package/dist/scp/find-filter-guard.js +0 -88
- package/dist/scp/find-filter-guard.js.map +0 -1
- package/dist/scp/guard.d.ts +0 -43
- package/dist/scp/guard.d.ts.map +0 -1
- package/dist/scp/guard.js +0 -134
- package/dist/scp/guard.js.map +0 -1
- package/dist/scp/makesql/authoring-compile.d.ts +0 -90
- package/dist/scp/makesql/authoring-compile.d.ts.map +0 -1
- package/dist/scp/makesql/authoring-compile.js +0 -494
- package/dist/scp/makesql/authoring-compile.js.map +0 -1
- package/dist/scp/makesql/ir.d.ts +0 -42
- package/dist/scp/makesql/ir.d.ts.map +0 -1
- package/dist/scp/makesql/ir.js +0 -66
- package/dist/scp/makesql/ir.js.map +0 -1
- package/dist/scp/makesql/static-bundle.d.ts +0 -187
- package/dist/scp/makesql/static-bundle.d.ts.map +0 -1
- package/dist/scp/makesql/static-bundle.js +0 -1113
- package/dist/scp/makesql/static-bundle.js.map +0 -1
- package/dist/scp/runtime.d.ts +0 -242
- package/dist/scp/runtime.d.ts.map +0 -1
- package/dist/scp/runtime.js +0 -400
- 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 (
|
|
77
|
-
*
|
|
78
|
-
* (`
|
|
79
|
-
*
|
|
80
|
-
* IN-list and the batch UPDATE composite already use —
|
|
81
|
-
*
|
|
82
|
-
* `(
|
|
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:
|
|
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 (
|
|
135
|
-
*
|
|
136
|
-
*
|
|
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
|
|
140
|
-
* `batchLoadWithLateralComposite`
|
|
141
|
-
*
|
|
142
|
-
*
|
|
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 ((?,?),…)`.
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
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:
|
|
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
|
|
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"}
|