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
package/dist/scp/relation.js
CHANGED
|
@@ -29,11 +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");
|
|
40
|
+
const coltype_1 = require("./coltype");
|
|
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");
|
|
36
45
|
const compile_relation_1 = require("./makesql/compile-relation");
|
|
46
|
+
const tx_1 = require("./makesql/tx");
|
|
37
47
|
/** The reserved input head the relation batch query binds its deduped key array to. */
|
|
38
48
|
exports.RELATION_KEYS_HEAD = '__keys';
|
|
39
49
|
/**
|
|
@@ -44,7 +54,7 @@ exports.RELATION_KEYS_HEAD = '__keys';
|
|
|
44
54
|
* LATERAL (PG) / ROW_NUMBER (MySQL·SQLite) form. The SQL text is FIXED (the array binds as one
|
|
45
55
|
* param regardless of length), so it needs no per-input recompile.
|
|
46
56
|
*/
|
|
47
|
-
function compileRelationOp(decl) {
|
|
57
|
+
function compileRelationOp(decl, resolveColumnType) {
|
|
48
58
|
if (decl.kind !== 'hasMany' && decl.limit !== undefined) {
|
|
49
59
|
throw new Error(`relation '${decl.name}': a per-parent 'limit' is only valid for hasMany (got ${decl.kind})`);
|
|
50
60
|
}
|
|
@@ -56,10 +66,48 @@ function compileRelationOp(decl) {
|
|
|
56
66
|
}
|
|
57
67
|
const dialect = decl.dialect ?? 'sqlite';
|
|
58
68
|
const composite = isCompositeDecl(decl);
|
|
59
|
-
const sql = compiledBatchSql(decl, dialect);
|
|
69
|
+
const sql = compiledBatchSql(decl, dialect, resolveColumnType);
|
|
60
70
|
// CROSS-DB (V0 R1): carry the target connection tag ONLY when set (a same-DB relation stays
|
|
61
71
|
// untagged, so existing bundles are byte-unchanged — the field is additive/optional).
|
|
62
72
|
const conn = decl.connection !== undefined ? { connection: decl.connection } : {};
|
|
73
|
+
// Carry the child table + projection AND bake the STATIC child materializers (issue #59) using the
|
|
74
|
+
// SHARED `parseProjectionColumn` + the SINGLE column-type resolver — the SAME resolution the primary
|
|
75
|
+
// read uses (no separate bare-regex pass). Every projection shape (bare / qualified `t.col` /
|
|
76
|
+
// aliased `col AS b`) resolves + fail-closes identically; a `*` / computed / undeclared column
|
|
77
|
+
// THROWS. The batch's child rows then de-box with ZERO per-read introspection.
|
|
78
|
+
const materializers = {};
|
|
79
|
+
if (resolveColumnType !== undefined) {
|
|
80
|
+
const at = `relation '${decl.name}'`;
|
|
81
|
+
for (const c of decl.select) {
|
|
82
|
+
const entry = (0, outtype_1.parseProjectionColumn)(c, decl.targetTable, at); // `*`/computed → throw
|
|
83
|
+
if (entry.kind === 'computed')
|
|
84
|
+
continue; // a relation child rarely projects computed; leave raw
|
|
85
|
+
const sqlType = resolveColumnType(entry.qualifier ?? decl.targetTable, entry.underlying); // undeclared → throw
|
|
86
|
+
const klass = (0, coltype_1.sqlTypeToMaterializeClass)(sqlType);
|
|
87
|
+
if (klass !== 'passthrough')
|
|
88
|
+
materializers[entry.outputKey] = klass;
|
|
89
|
+
}
|
|
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;
|
|
97
|
+
const target = {
|
|
98
|
+
targetTable: decl.targetTable,
|
|
99
|
+
select: [...decl.select],
|
|
100
|
+
...(Object.keys(materializers).length > 0 ? { materializers } : {}),
|
|
101
|
+
...(childRelations !== undefined ? { childRelations } : {}),
|
|
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 } : {};
|
|
63
111
|
if (composite) {
|
|
64
112
|
return {
|
|
65
113
|
name: decl.name,
|
|
@@ -69,6 +117,8 @@ function compileRelationOp(decl) {
|
|
|
69
117
|
dialect,
|
|
70
118
|
...conn,
|
|
71
119
|
sql,
|
|
120
|
+
...target,
|
|
121
|
+
...guard,
|
|
72
122
|
};
|
|
73
123
|
}
|
|
74
124
|
return {
|
|
@@ -79,6 +129,8 @@ function compileRelationOp(decl) {
|
|
|
79
129
|
dialect,
|
|
80
130
|
...conn,
|
|
81
131
|
sql,
|
|
132
|
+
...target,
|
|
133
|
+
...guard,
|
|
82
134
|
};
|
|
83
135
|
}
|
|
84
136
|
/**
|
|
@@ -105,25 +157,43 @@ function isCompositeDecl(decl) {
|
|
|
105
157
|
}
|
|
106
158
|
return true;
|
|
107
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
|
+
}
|
|
108
177
|
/**
|
|
109
178
|
* Compile the STATIC batch SELECT text: the makeSQL relation builder emits complete tuned SQL
|
|
110
179
|
* whose deduped-key array is ONE param. We compile against a single placeholder key array so
|
|
111
180
|
* the text is fixed; the runtime re-binds the real deduped keys against the SAME text (the
|
|
112
181
|
* single-JSON / `= ANY` forms are length-independent, so the text is stable).
|
|
113
182
|
*/
|
|
114
|
-
function compiledBatchSql(decl, dialect) {
|
|
115
|
-
// A COMPOSITE decl compiles to the STATIC composite form
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
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).
|
|
119
188
|
if (decl.parentKeys !== undefined) {
|
|
189
|
+
const targetKeys = [...decl.targetKeys];
|
|
120
190
|
const compositeBase = {
|
|
121
191
|
dialect,
|
|
122
192
|
tableName: decl.targetTable,
|
|
123
193
|
select: decl.select.join(', '),
|
|
124
194
|
order: decl.order,
|
|
125
|
-
targetKeys
|
|
126
|
-
|
|
195
|
+
targetKeys,
|
|
196
|
+
...(dialect === 'postgres' ? { pgKeyTypes: pgKeyTypesOf(decl, targetKeys, resolveColumnType) } : {}),
|
|
127
197
|
};
|
|
128
198
|
const node = decl.limit !== undefined
|
|
129
199
|
? (0, compile_relation_1.compileCompositeKeyStaticLimited)({ ...compositeBase, limit: decl.limit })
|
|
@@ -133,6 +203,15 @@ function compiledBatchSql(decl, dialect) {
|
|
|
133
203
|
// A one-element placeholder key set fixes the SQL text (single-JSON-param / `= ANY` forms are
|
|
134
204
|
// value-length-independent). The concrete keys are bound at execute time.
|
|
135
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;
|
|
136
215
|
const base = {
|
|
137
216
|
dialect,
|
|
138
217
|
tableName: decl.targetTable,
|
|
@@ -140,11 +219,9 @@ function compiledBatchSql(decl, dialect) {
|
|
|
140
219
|
order: decl.order,
|
|
141
220
|
targetKey: decl.targetKey,
|
|
142
221
|
values: placeholderKeys,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// compile-time `text[]` here was the #43 regression (`integer = text` on real PG).
|
|
147
|
-
deferPgArrayCast: true,
|
|
222
|
+
...(pgKeyCast !== undefined
|
|
223
|
+
? { sqlCastMap: new Map([[decl.targetKey, pgKeyCast]]) }
|
|
224
|
+
: { deferPgArrayCast: true }),
|
|
148
225
|
};
|
|
149
226
|
const node = decl.limit !== undefined
|
|
150
227
|
? (0, compile_relation_1.compileSingleKeyLimited)({ ...base, limit: decl.limit })
|
|
@@ -152,6 +229,30 @@ function compiledBatchSql(decl, dialect) {
|
|
|
152
229
|
// The builder emits the SQL with ONE `?` (the whole key array). Assemble to the flat text.
|
|
153
230
|
return (0, makesql_1.assembleMakeSQL)(node).sql;
|
|
154
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
|
+
}
|
|
155
256
|
/** The ordered PARENT key columns of an op (single-key → 1-element list; composite → the tuple). */
|
|
156
257
|
function parentKeyCols(op) {
|
|
157
258
|
return op.parentKeys ?? [op.parentKey];
|
|
@@ -160,28 +261,39 @@ function parentKeyCols(op) {
|
|
|
160
261
|
function targetKeyCols(op) {
|
|
161
262
|
return op.targetKeys ?? [op.targetKey];
|
|
162
263
|
}
|
|
163
|
-
/**
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
+
};
|
|
167
279
|
}
|
|
168
280
|
/**
|
|
169
|
-
* Bind the deduped keys to the batch op's params
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
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.
|
|
173
291
|
*/
|
|
174
292
|
function bindKeys(op, tuples) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
// Transpose tuples → per-column arrays: `[[1,a],[2,b]] → [[1,2],[a,b]]` — one array param each.
|
|
180
|
-
return parentKeyCols(op).map((_, col) => tuples.map((t) => t[col]));
|
|
181
|
-
}
|
|
182
|
-
// MySQL/SQLite: single-key → JSON scalar array; composite → JSON array-of-tuples. ONE param.
|
|
183
|
-
const payload = composite ? tuples.map((t) => [...t]) : tuples.map((t) => t[0]);
|
|
184
|
-
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)];
|
|
185
297
|
}
|
|
186
298
|
/**
|
|
187
299
|
* Run ONE {@link RelationOp} for a set of parent rows: dedup the parent-key tuples, render the
|
|
@@ -194,64 +306,72 @@ function bindKeys(op, tuples) {
|
|
|
194
306
|
* NO query (the correct empty-set behavior — the membership over no keys selects nothing).
|
|
195
307
|
*/
|
|
196
308
|
function runRelationOp(op, parents, db) {
|
|
309
|
+
const ctx = relationContext(db);
|
|
197
310
|
const pCols = parentKeyCols(op);
|
|
198
|
-
const keys =
|
|
311
|
+
const keys = (0, grouping_1.dedupeKeyTuples)(parents, pCols);
|
|
199
312
|
const batch = new Map();
|
|
200
|
-
// Resolve the deferred PG array cast
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
cast = (0, compile_relation_1.resolvePgArrayCast)(cast, keys.map((t) => t[col]));
|
|
208
|
-
}
|
|
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;
|
|
209
320
|
const sql = (0, handler_1.renderPlaceholders)(cast, op.dialect);
|
|
210
321
|
if (keys.length === 0)
|
|
211
322
|
return { sql, keys, batch };
|
|
212
323
|
const tCols = targetKeyCols(op);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
324
|
+
// Materialize the child rows (issue #59) exactly like the primary read, using the STATIC
|
|
325
|
+
// materializers baked onto the op at compile (from the model's DDL — ZERO per-read introspection).
|
|
326
|
+
// A BIGINT/DATE/BOOL child column de-boxes identically to a top-level read (INT→number /
|
|
327
|
+
// BIGINT→string / DATE→string / bool).
|
|
328
|
+
const childCols = op.materializers;
|
|
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) };
|
|
223
347
|
}
|
|
224
|
-
/**
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
out.push(tuple);
|
|
348
|
+
/** Materialize relation child rows (issue #59): same coercion as the primary read. */
|
|
349
|
+
function materializeChildRows(rows, cols) {
|
|
350
|
+
for (const row of rows) {
|
|
351
|
+
for (const key of Object.keys(row)) {
|
|
352
|
+
const klass = cols?.[key];
|
|
353
|
+
if (klass !== undefined) {
|
|
354
|
+
row[key] = (0, coltype_1.materializeCell)(row[key], klass);
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
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') {
|
|
360
|
+
const v = row[key];
|
|
361
|
+
row[key] = v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(v) : v.toString();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
241
364
|
}
|
|
242
|
-
return
|
|
365
|
+
return rows;
|
|
243
366
|
}
|
|
244
367
|
/**
|
|
245
368
|
* Distribute a resolved {@link RelationBatch} onto ONE parent per the relation cardinality:
|
|
246
|
-
* `hasMany` → the child list (`[]` when none); `belongsTo`/`hasOne` → the single child (or
|
|
247
|
-
*
|
|
248
|
-
*
|
|
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.
|
|
249
373
|
*/
|
|
250
374
|
function distributeToParent(op, parent, batch) {
|
|
251
|
-
|
|
252
|
-
const rows = tuple.some((v) => v === undefined || v === null) ? undefined : batch.get(keyIdentity(tuple));
|
|
253
|
-
if (op.kind === 'hasMany')
|
|
254
|
-
return rows ?? [];
|
|
255
|
-
return rows !== undefined && rows.length > 0 ? rows[0] : null;
|
|
375
|
+
return (0, grouping_1.attachToParent)(parent, parentKeyCols(op), batch, op.kind !== 'hasMany');
|
|
256
376
|
}
|
|
257
377
|
//# sourceMappingURL=relation.js.map
|
package/dist/scp/relation.js.map
CHANGED
|
@@ -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"}
|