litedbmodel 2.0.0 → 2.0.2
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/dist/scp/authoring-sql.d.ts +78 -0
- package/dist/scp/authoring-sql.d.ts.map +1 -1
- package/dist/scp/authoring-sql.js +110 -2
- package/dist/scp/authoring-sql.js.map +1 -1
- package/dist/scp/catalog.d.ts +5 -2
- package/dist/scp/catalog.d.ts.map +1 -1
- package/dist/scp/catalog.js +32 -1
- package/dist/scp/catalog.js.map +1 -1
- package/dist/scp/codegen.d.ts +143 -85
- package/dist/scp/codegen.d.ts.map +1 -1
- package/dist/scp/codegen.js +374 -90
- package/dist/scp/codegen.js.map +1 -1
- package/dist/scp/coltype.d.ts +41 -0
- package/dist/scp/coltype.d.ts.map +1 -0
- package/dist/scp/coltype.js +188 -0
- package/dist/scp/coltype.js.map +1 -0
- package/dist/scp/dialect.d.ts +12 -3
- package/dist/scp/dialect.d.ts.map +1 -1
- package/dist/scp/dialect.js +12 -3
- package/dist/scp/dialect.js.map +1 -1
- package/dist/scp/find-filter-guard.d.ts +68 -0
- package/dist/scp/find-filter-guard.d.ts.map +1 -0
- package/dist/scp/find-filter-guard.js +88 -0
- package/dist/scp/find-filter-guard.js.map +1 -0
- package/dist/scp/fragment/assemble.d.ts +61 -0
- package/dist/scp/fragment/assemble.d.ts.map +1 -0
- package/dist/scp/fragment/assemble.js +156 -0
- package/dist/scp/fragment/assemble.js.map +1 -0
- package/dist/scp/fragment/compile-pg.d.ts +107 -0
- package/dist/scp/fragment/compile-pg.d.ts.map +1 -0
- package/dist/scp/fragment/compile-pg.js +142 -0
- package/dist/scp/fragment/compile-pg.js.map +1 -0
- package/dist/scp/fragment/index.d.ts +16 -0
- package/dist/scp/fragment/index.d.ts.map +1 -0
- package/dist/scp/fragment/index.js +34 -0
- package/dist/scp/fragment/index.js.map +1 -0
- package/dist/scp/fragment/model.d.ts +119 -0
- package/dist/scp/fragment/model.d.ts.map +1 -0
- package/dist/scp/fragment/model.js +66 -0
- package/dist/scp/fragment/model.js.map +1 -0
- package/dist/scp/fragment/pg-array-type.d.ts +13 -0
- package/dist/scp/fragment/pg-array-type.d.ts.map +1 -0
- package/dist/scp/fragment/pg-array-type.js +34 -0
- package/dist/scp/fragment/pg-array-type.js.map +1 -0
- package/dist/scp/guard.d.ts +2 -6
- package/dist/scp/guard.d.ts.map +1 -1
- package/dist/scp/guard.js +19 -22
- package/dist/scp/guard.js.map +1 -1
- package/dist/scp/index.cjs +18695 -3921
- package/dist/scp/index.d.ts +41 -24
- package/dist/scp/index.d.ts.map +1 -1
- package/dist/scp/index.js +134 -49
- package/dist/scp/index.js.map +1 -1
- package/dist/scp/index.mjs +4830 -1432
- package/dist/scp/makesql/authoring-compile.d.ts +90 -0
- package/dist/scp/makesql/authoring-compile.d.ts.map +1 -0
- package/dist/scp/makesql/authoring-compile.js +494 -0
- package/dist/scp/makesql/authoring-compile.js.map +1 -0
- package/dist/scp/makesql/compile-crud.d.ts +133 -0
- package/dist/scp/makesql/compile-crud.d.ts.map +1 -0
- package/dist/scp/makesql/compile-crud.js +288 -0
- package/dist/scp/makesql/compile-crud.js.map +1 -0
- package/dist/scp/makesql/compile-relation.d.ts +157 -0
- package/dist/scp/makesql/compile-relation.d.ts.map +1 -0
- package/dist/scp/makesql/compile-relation.js +425 -0
- package/dist/scp/makesql/compile-relation.js.map +1 -0
- package/dist/scp/makesql/compile-select.d.ts +52 -0
- package/dist/scp/makesql/compile-select.d.ts.map +1 -0
- package/dist/scp/makesql/compile-select.js +58 -0
- package/dist/scp/makesql/compile-select.js.map +1 -0
- package/dist/scp/makesql/compile.d.ts +63 -0
- package/dist/scp/makesql/compile.d.ts.map +1 -0
- package/dist/scp/makesql/compile.js +99 -0
- package/dist/scp/makesql/compile.js.map +1 -0
- package/dist/scp/makesql/handler.d.ts +58 -0
- package/dist/scp/makesql/handler.d.ts.map +1 -0
- package/dist/scp/makesql/handler.js +113 -0
- package/dist/scp/makesql/handler.js.map +1 -0
- package/dist/scp/makesql/index.d.ts +33 -0
- package/dist/scp/makesql/index.d.ts.map +1 -0
- package/dist/scp/makesql/index.js +114 -0
- package/dist/scp/makesql/index.js.map +1 -0
- package/dist/scp/makesql/ir.d.ts +42 -0
- package/dist/scp/makesql/ir.d.ts.map +1 -0
- package/dist/scp/makesql/ir.js +66 -0
- package/dist/scp/makesql/ir.js.map +1 -0
- package/dist/scp/makesql/json-array.d.ts +84 -0
- package/dist/scp/makesql/json-array.d.ts.map +1 -0
- package/dist/scp/makesql/json-array.js +118 -0
- package/dist/scp/makesql/json-array.js.map +1 -0
- package/dist/scp/makesql/json-batch.d.ts +102 -0
- package/dist/scp/makesql/json-batch.d.ts.map +1 -0
- package/dist/scp/makesql/json-batch.js +269 -0
- package/dist/scp/makesql/json-batch.js.map +1 -0
- package/dist/scp/makesql/makesql.d.ts +99 -0
- package/dist/scp/makesql/makesql.d.ts.map +1 -0
- package/dist/scp/makesql/makesql.js +122 -0
- package/dist/scp/makesql/makesql.js.map +1 -0
- package/dist/scp/makesql/outtype.d.ts +44 -0
- package/dist/scp/makesql/outtype.d.ts.map +1 -0
- package/dist/scp/makesql/outtype.js +197 -0
- package/dist/scp/makesql/outtype.js.map +1 -0
- package/dist/scp/makesql/pool-executor.d.ts +47 -0
- package/dist/scp/makesql/pool-executor.d.ts.map +1 -0
- package/dist/scp/makesql/pool-executor.js +50 -0
- package/dist/scp/makesql/pool-executor.js.map +1 -0
- package/dist/scp/makesql/static-bundle.d.ts +187 -0
- package/dist/scp/makesql/static-bundle.d.ts.map +1 -0
- package/dist/scp/makesql/static-bundle.js +1113 -0
- package/dist/scp/makesql/static-bundle.js.map +1 -0
- package/dist/scp/makesql/tx.d.ts +216 -0
- package/dist/scp/makesql/tx.d.ts.map +1 -0
- package/dist/scp/makesql/tx.js +788 -0
- package/dist/scp/makesql/tx.js.map +1 -0
- package/dist/scp/makesql/writeouttype.d.ts +66 -0
- package/dist/scp/makesql/writeouttype.d.ts.map +1 -0
- package/dist/scp/makesql/writeouttype.js +195 -0
- package/dist/scp/makesql/writeouttype.js.map +1 -0
- package/dist/scp/relation.d.ts +86 -74
- package/dist/scp/relation.d.ts.map +1 -1
- package/dist/scp/relation.js +186 -120
- package/dist/scp/relation.js.map +1 -1
- package/dist/scp/runtime.d.ts +158 -211
- package/dist/scp/runtime.d.ts.map +1 -1
- package/dist/scp/runtime.js +250 -515
- package/dist/scp/runtime.js.map +1 -1
- package/dist/scp/typed-object.d.ts +12 -1
- package/dist/scp/typed-object.d.ts.map +1 -1
- package/dist/scp/typed-object.js +25 -4
- package/dist/scp/typed-object.js.map +1 -1
- package/docs/proposal/litedbmodel-v2-scp-architecture.md +51 -0
- package/docs/proposal/v0-coverage-matrix.md +157 -0
- package/docs/proposal/v2-completeness-plan.md +90 -0
- package/docs/proposal/v2-sql-parity-checklist.md +162 -0
- package/package.json +3 -3
- package/dist/scp/bridge.d.ts +0 -64
- package/dist/scp/bridge.d.ts.map +0 -1
- package/dist/scp/bridge.js +0 -329
- package/dist/scp/bridge.js.map +0 -1
- package/dist/scp/compile-dialect.d.ts +0 -39
- package/dist/scp/compile-dialect.d.ts.map +0 -1
- package/dist/scp/compile-dialect.js +0 -62
- package/dist/scp/compile-dialect.js.map +0 -1
- package/dist/scp/compile-sqlite.d.ts +0 -114
- package/dist/scp/compile-sqlite.d.ts.map +0 -1
- package/dist/scp/compile-sqlite.js +0 -149
- package/dist/scp/compile-sqlite.js.map +0 -1
- package/dist/scp/ir.d.ts +0 -92
- package/dist/scp/ir.d.ts.map +0 -1
- package/dist/scp/ir.js +0 -28
- package/dist/scp/ir.js.map +0 -1
- package/dist/scp/render.d.ts +0 -40
- package/dist/scp/render.d.ts.map +0 -1
- package/dist/scp/render.js +0 -170
- package/dist/scp/render.js.map +0 -1
- package/dist/scp/write-plan.d.ts +0 -161
- package/dist/scp/write-plan.d.ts.map +0 -1
- package/dist/scp/write-plan.js +0 -528
- package/dist/scp/write-plan.js.map +0 -1
- package/dist/scp/write-runtime.d.ts +0 -80
- package/dist/scp/write-runtime.d.ts.map +0 -1
- package/dist/scp/write-runtime.js +0 -167
- package/dist/scp/write-runtime.js.map +0 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* litedbmodel v2 型システム(SCP アーキ spec §4.1): SQL 型 → bc outType スカラの正規変換。
|
|
4
|
+
*
|
|
5
|
+
* litedbmodel は SQL バックエンド consumer なので **SQL 型を型の SoT** とする(TS の `number` は
|
|
6
|
+
* INTEGER/REAL を区別できないため型の権威にしない)。typed codegen(bc typed-raw 脱box)の `outType`
|
|
7
|
+
* 注記はこの変換で決まる。**曖昧/未知は error(no-assume・no-fallback)** — 既定値へ潰さない。
|
|
8
|
+
*
|
|
9
|
+
* 返すのは bc の scalar 型名(`typed.ts` の scalar union `"string"|"int"|"float"|"bool"|"null"`)。
|
|
10
|
+
* 行/リレーションの構造型(`obj`/`arr`/`opt`)は列型ではなくクエリ由来なので本変換の対象外。
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.sqlTypeToBcScalar = sqlTypeToBcScalar;
|
|
14
|
+
exports.parseSchemaColumnTypes = parseSchemaColumnTypes;
|
|
15
|
+
exports.schemaColumnTypeResolver = schemaColumnTypeResolver;
|
|
16
|
+
/**
|
|
17
|
+
* SQL 型(DDL のトークン。`DECIMAL(10,2)` 等の括弧やサイズは無視)→ bc outType スカラ。
|
|
18
|
+
* spec §4.1 の正規表に一致。未知/曖昧は throw(fail-closed)。
|
|
19
|
+
*/
|
|
20
|
+
function sqlTypeToBcScalar(sqlType) {
|
|
21
|
+
// 括弧のサイズ/精度・`UNSIGNED` 等の修飾を落として基底型名で判定。
|
|
22
|
+
const t = sqlType
|
|
23
|
+
.trim()
|
|
24
|
+
.toUpperCase()
|
|
25
|
+
.replace(/\(.*\)/, '')
|
|
26
|
+
.replace(/\b(UNSIGNED|ZEROFILL|PRECISION)\b/g, '')
|
|
27
|
+
.replace(/\s+/g, ' ')
|
|
28
|
+
.trim();
|
|
29
|
+
switch (t) {
|
|
30
|
+
// int は既定 64bit(i64)。INTEGER も BIGINT も int(bigint を別型にしない — サイズ制限は列制約で表現)。
|
|
31
|
+
case 'INTEGER':
|
|
32
|
+
case 'INT':
|
|
33
|
+
case 'BIGINT':
|
|
34
|
+
case 'SMALLINT':
|
|
35
|
+
case 'TINYINT':
|
|
36
|
+
case 'MEDIUMINT':
|
|
37
|
+
case 'INT2':
|
|
38
|
+
case 'INT4':
|
|
39
|
+
case 'INT8':
|
|
40
|
+
return 'int';
|
|
41
|
+
// int と real は明確に分離。
|
|
42
|
+
case 'REAL':
|
|
43
|
+
case 'FLOAT':
|
|
44
|
+
case 'DOUBLE':
|
|
45
|
+
case 'FLOAT4':
|
|
46
|
+
case 'FLOAT8':
|
|
47
|
+
return 'float';
|
|
48
|
+
// decimal は精度保持のため文字列表現。
|
|
49
|
+
case 'DECIMAL':
|
|
50
|
+
case 'NUMERIC':
|
|
51
|
+
case 'MONEY':
|
|
52
|
+
return 'string';
|
|
53
|
+
case 'TEXT':
|
|
54
|
+
case 'VARCHAR':
|
|
55
|
+
case 'CHAR':
|
|
56
|
+
case 'CHARACTER':
|
|
57
|
+
case 'CHARACTER VARYING':
|
|
58
|
+
case 'CLOB':
|
|
59
|
+
case 'UUID':
|
|
60
|
+
return 'string';
|
|
61
|
+
case 'BOOLEAN':
|
|
62
|
+
case 'BOOL':
|
|
63
|
+
return 'bool';
|
|
64
|
+
// date/timestamp は一旦 string(spec §4.1 owner 決定)。bc に date scalar が無く(behavior-contracts#84
|
|
65
|
+
// は defer)、DB は行ごとに別 TZ を保存しないので、文字列表現で往復させる。将来 bc date 型導入時に最適化。
|
|
66
|
+
case 'DATE':
|
|
67
|
+
case 'TIMESTAMP':
|
|
68
|
+
case 'TIMESTAMPTZ':
|
|
69
|
+
case 'DATETIME':
|
|
70
|
+
case 'TIME':
|
|
71
|
+
return 'string';
|
|
72
|
+
// JSON 列の表現は JSON テキスト=文字列(TS のみ利便で object へ de/serialize。列を typed obj 化しない)。
|
|
73
|
+
case 'JSON':
|
|
74
|
+
case 'JSONB':
|
|
75
|
+
return 'string';
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`litedbmodel type system (spec §4.1): no bc outType mapping for SQL type '${sqlType}' ` +
|
|
78
|
+
`(normalized '${t}'). Add it to the §4.1 table or fix the column — ambiguous/unknown types ` +
|
|
79
|
+
`are a hard error (no-assume, no-fallback), never defaulted.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parse a list of `CREATE TABLE` DDL statements into a `table → (column → SQL type)` map. This is
|
|
84
|
+
* the spec §4.1 SoT: the physical SQL type of each column, from which `sqlTypeToBcScalar` derives
|
|
85
|
+
* the bc `outType` scalar for typed codegen. Only the base column definitions are read; table-level
|
|
86
|
+
* constraints (`PRIMARY KEY (…)`, `FOREIGN KEY …`, `UNIQUE (…)`, `CHECK …`) are skipped. A column's
|
|
87
|
+
* type is its first token after the name (e.g. `id INTEGER PRIMARY KEY` → `INTEGER`). Column names
|
|
88
|
+
* quoted with `"`/`` ` ``/`[]` are unquoted. Non-`CREATE TABLE` statements (INSERT seed rows, etc.)
|
|
89
|
+
* are ignored, so a mixed schema+seed list is accepted as-is.
|
|
90
|
+
*/
|
|
91
|
+
function parseSchemaColumnTypes(ddl) {
|
|
92
|
+
const tables = new Map();
|
|
93
|
+
const CREATE = /^\s*CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([A-Za-z0-9_."`[\]]+)\s*\(([\s\S]*)\)\s*;?\s*$/i;
|
|
94
|
+
const unquote = (s) => s.replace(/^["`[]|["`\]]$/g, '');
|
|
95
|
+
// Column/constraint list keywords that start a TABLE-LEVEL constraint (not a column definition).
|
|
96
|
+
const TABLE_CONSTRAINT = /^(PRIMARY|FOREIGN|UNIQUE|CHECK|CONSTRAINT|KEY|INDEX)\b/i;
|
|
97
|
+
for (const stmt of ddl) {
|
|
98
|
+
const m = CREATE.exec(stmt);
|
|
99
|
+
if (m === null)
|
|
100
|
+
continue; // not a CREATE TABLE (seed INSERT / pragma / etc.) — skip
|
|
101
|
+
const table = unquote(m[1].trim());
|
|
102
|
+
const cols = new Map();
|
|
103
|
+
for (const entry of splitTopLevel(m[2])) {
|
|
104
|
+
const line = entry.trim();
|
|
105
|
+
if (line.length === 0)
|
|
106
|
+
continue;
|
|
107
|
+
if (TABLE_CONSTRAINT.test(line))
|
|
108
|
+
continue; // table-level constraint, not a column
|
|
109
|
+
// `<name> <TYPE...> [constraints]` — the type is the token(s) up to the first constraint
|
|
110
|
+
// keyword or the end. `parseColumnDef` returns `{ name, sqlType }` or undefined (unparseable).
|
|
111
|
+
const parsed = parseColumnDef(line);
|
|
112
|
+
if (parsed === undefined)
|
|
113
|
+
continue;
|
|
114
|
+
cols.set(parsed.name, parsed.sqlType);
|
|
115
|
+
}
|
|
116
|
+
tables.set(table, cols);
|
|
117
|
+
}
|
|
118
|
+
return tables;
|
|
119
|
+
}
|
|
120
|
+
/** Split a CREATE TABLE column list on TOP-LEVEL commas (commas inside `(…)`, e.g. `DECIMAL(10,2)`, stay). */
|
|
121
|
+
function splitTopLevel(body) {
|
|
122
|
+
const parts = [];
|
|
123
|
+
let depth = 0;
|
|
124
|
+
let cur = '';
|
|
125
|
+
for (const ch of body) {
|
|
126
|
+
if (ch === '(')
|
|
127
|
+
depth++;
|
|
128
|
+
else if (ch === ')')
|
|
129
|
+
depth--;
|
|
130
|
+
if (ch === ',' && depth === 0) {
|
|
131
|
+
parts.push(cur);
|
|
132
|
+
cur = '';
|
|
133
|
+
}
|
|
134
|
+
else
|
|
135
|
+
cur += ch;
|
|
136
|
+
}
|
|
137
|
+
if (cur.trim().length > 0)
|
|
138
|
+
parts.push(cur);
|
|
139
|
+
return parts;
|
|
140
|
+
}
|
|
141
|
+
/** The SQL-type keywords that may form a multi-word type (so `CHARACTER VARYING`, `DOUBLE PRECISION` stay whole). */
|
|
142
|
+
const TYPE_CONTINUATION = /^(VARYING|PRECISION)$/i;
|
|
143
|
+
/** Parse one `<name> <TYPE...>` column definition into `{ name, sqlType }`. Undefined when unparseable. */
|
|
144
|
+
function parseColumnDef(line) {
|
|
145
|
+
const unquote = (s) => s.replace(/^["`[]|["`\]]$/g, '');
|
|
146
|
+
const nameMatch = /^([A-Za-z0-9_."`[\]]+)\s+(.*)$/.exec(line);
|
|
147
|
+
if (nameMatch === null)
|
|
148
|
+
return undefined;
|
|
149
|
+
const name = unquote(nameMatch[1]);
|
|
150
|
+
const rest = nameMatch[2].trim();
|
|
151
|
+
// The type is the leading token plus any `(...)` size/precision, plus a continuation word
|
|
152
|
+
// (`CHARACTER VARYING`, `DOUBLE PRECISION`). Everything after is column constraints.
|
|
153
|
+
const typeMatch = /^([A-Za-z0-9_]+(?:\s*\([^)]*\))?)\s*(.*)$/.exec(rest);
|
|
154
|
+
if (typeMatch === null)
|
|
155
|
+
return undefined;
|
|
156
|
+
let sqlType = typeMatch[1].trim();
|
|
157
|
+
const after = typeMatch[2].trim();
|
|
158
|
+
const nextWord = /^([A-Za-z]+)/.exec(after);
|
|
159
|
+
if (nextWord !== null && TYPE_CONTINUATION.test(nextWord[1]))
|
|
160
|
+
sqlType = `${sqlType} ${nextWord[1]}`;
|
|
161
|
+
if (sqlType.length === 0)
|
|
162
|
+
return undefined;
|
|
163
|
+
return { name, sqlType };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Build a {@link ColumnTypeResolver} from CREATE TABLE DDL (spec §4.1 SoT). The resolver throws
|
|
167
|
+
* (no default) for any `table.column` the DDL does not declare — an unknown column is a hard error
|
|
168
|
+
* (no-assume, no-fallback), so a codegen `outType` derivation can never silently box an untyped row.
|
|
169
|
+
*/
|
|
170
|
+
function schemaColumnTypeResolver(ddl) {
|
|
171
|
+
const tables = parseSchemaColumnTypes(ddl);
|
|
172
|
+
return (table, column) => {
|
|
173
|
+
const cols = tables.get(table);
|
|
174
|
+
if (cols === undefined) {
|
|
175
|
+
throw new Error(`litedbmodel type system (spec §4.1): no schema for table '${table}' — cannot type its ` +
|
|
176
|
+
`SELECT projection for typed codegen. The DDL (schema.sql SoT) must declare the table ` +
|
|
177
|
+
`(known: ${[...tables.keys()].join(', ') || '<none>'}). No-assume, no-fallback.`);
|
|
178
|
+
}
|
|
179
|
+
const sqlType = cols.get(column);
|
|
180
|
+
if (sqlType === undefined) {
|
|
181
|
+
throw new Error(`litedbmodel type system (spec §4.1): column '${column}' not declared on table '${table}' ` +
|
|
182
|
+
`(known columns: ${[...cols.keys()].join(', ')}). A projected column with no schema type ` +
|
|
183
|
+
`cannot be typed for de-boxed codegen. No-assume, no-fallback.`);
|
|
184
|
+
}
|
|
185
|
+
return sqlType;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=coltype.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coltype.js","sourceRoot":"","sources":["../../src/scp/coltype.ts"],"names":[],"mappings":"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"}
|
package/dist/scp/dialect.d.ts
CHANGED
|
@@ -25,10 +25,19 @@
|
|
|
25
25
|
* final left-to-right one-pass AFTER the SQL text is fully assembled (spec §8 — the
|
|
26
26
|
* number-reassignment problem is designed out because the pass runs once over the final
|
|
27
27
|
* flat text). SQLite/MySQL keep `?`.
|
|
28
|
+
* - **Per-column value cast (PG)**: a written column with a declared `sqlCast` type emits
|
|
29
|
+
* `?::<sqlCast>` on Postgres — in an INSERT `VALUES (…)` tuple (`PostgresSqlBuilder`:289-296)
|
|
30
|
+
* AND an UPDATE `SET c = ?::<sqlCast>` (`DBModel._update`:1058-1063) — via the dialect cast
|
|
31
|
+
* formatter (`formatterFor`), skipping `timestamp`/`date`. MySQL/SQLite emit a bare `?` (the
|
|
32
|
+
* cast formatter is identity there). This is resolved at compile (the write path targets a
|
|
33
|
+
* single dialect), applied in `compile-crud.compileUpdateSingle` and `tx.compileWriteNode`.
|
|
28
34
|
*
|
|
29
|
-
* Everything else (SELECT/UPDATE/DELETE skeletons, `col = ?`, `col IN (?, …)` expansion,
|
|
30
|
-
* fragment tree, RETURNING for SQLite/Postgres) is identical text across dialects, so it is
|
|
31
|
-
* NOT part of the strategy — only the genuine divergences
|
|
35
|
+
* Everything else (SELECT/UPDATE/DELETE skeletons, a NON-cast `col = ?`, `col IN (?, …)` expansion,
|
|
36
|
+
* the fragment tree, RETURNING for SQLite/Postgres) is identical text across dialects, so it is
|
|
37
|
+
* NOT part of the strategy — only the genuine divergences (including the PG per-column cast above)
|
|
38
|
+
* live here. NB: `col = ?` / `VALUES (?)` is identical across dialects ONLY for a column with no
|
|
39
|
+
* `sqlCast`; a PG cast column is the `?::<sqlCast>` divergence just described (this was previously
|
|
40
|
+
* mis-documented as unconditionally identical).
|
|
32
41
|
*
|
|
33
42
|
* ## DB behavior differences beyond SQL text (spec §13) — closeable-by-convention line
|
|
34
43
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../../src/scp/dialect.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../../src/scp/dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAE1D,0FAA0F;AAC1F,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG;IAAE,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAEtF;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAE3B;;;;;;;;;OASG;IACH,oBAAoB,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;IAEzF;;;;;OAKG;IACH,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;IAEvD;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IAEzC;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IAErF;;;;;OAKG;IACH,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAE1C;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;CAClF;AAID;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYxD;AAwCD;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,OAoBnB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,OAkBrB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,OA0BlB,CAAC;AASH,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAMrD"}
|
package/dist/scp/dialect.js
CHANGED
|
@@ -26,10 +26,19 @@
|
|
|
26
26
|
* final left-to-right one-pass AFTER the SQL text is fully assembled (spec §8 — the
|
|
27
27
|
* number-reassignment problem is designed out because the pass runs once over the final
|
|
28
28
|
* flat text). SQLite/MySQL keep `?`.
|
|
29
|
+
* - **Per-column value cast (PG)**: a written column with a declared `sqlCast` type emits
|
|
30
|
+
* `?::<sqlCast>` on Postgres — in an INSERT `VALUES (…)` tuple (`PostgresSqlBuilder`:289-296)
|
|
31
|
+
* AND an UPDATE `SET c = ?::<sqlCast>` (`DBModel._update`:1058-1063) — via the dialect cast
|
|
32
|
+
* formatter (`formatterFor`), skipping `timestamp`/`date`. MySQL/SQLite emit a bare `?` (the
|
|
33
|
+
* cast formatter is identity there). This is resolved at compile (the write path targets a
|
|
34
|
+
* single dialect), applied in `compile-crud.compileUpdateSingle` and `tx.compileWriteNode`.
|
|
29
35
|
*
|
|
30
|
-
* Everything else (SELECT/UPDATE/DELETE skeletons, `col = ?`, `col IN (?, …)` expansion,
|
|
31
|
-
* fragment tree, RETURNING for SQLite/Postgres) is identical text across dialects, so it is
|
|
32
|
-
* NOT part of the strategy — only the genuine divergences
|
|
36
|
+
* Everything else (SELECT/UPDATE/DELETE skeletons, a NON-cast `col = ?`, `col IN (?, …)` expansion,
|
|
37
|
+
* the fragment tree, RETURNING for SQLite/Postgres) is identical text across dialects, so it is
|
|
38
|
+
* NOT part of the strategy — only the genuine divergences (including the PG per-column cast above)
|
|
39
|
+
* live here. NB: `col = ?` / `VALUES (?)` is identical across dialects ONLY for a column with no
|
|
40
|
+
* `sqlCast`; a PG cast column is the `?::<sqlCast>` divergence just described (this was previously
|
|
41
|
+
* mis-documented as unconditionally identical).
|
|
33
42
|
*
|
|
34
43
|
* ## DB behavior differences beyond SQL text (spec §13) — closeable-by-convention line
|
|
35
44
|
*
|
package/dist/scp/dialect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialect.js","sourceRoot":"","sources":["../../src/scp/dialect.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"dialect.js","sourceRoot":"","sources":["../../src/scp/dialect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* litedbmodel v2 SCP — FIND_FILTER fail-closed authoring guard (#47 Finding B / plan R8).
|
|
3
|
+
*
|
|
4
|
+
* `FIND_FILTER` is a v1 PER-MODEL implicit predicate (a soft-delete / tenant scope) that
|
|
5
|
+
* v1 MERGES into the WHERE of every internal `find()`/`count()` before compiling
|
|
6
|
+
* (`DBModel._buildSelectSQL` / `_count`: `normalizedCond.add(condsToRecord(FIND_FILTER))`).
|
|
7
|
+
* It is not a distinct SQL construct — it manifests purely as extra WHERE fragments.
|
|
8
|
+
*
|
|
9
|
+
* The SCP compile path (`L.Select({ where })` → `compileReadGraph` → `renderReadPrimary`)
|
|
10
|
+
* is AUTHORED from an explicit `where`; it has NO `DBModel` class context, so it CANNOT
|
|
11
|
+
* auto-apply a model's `FIND_FILTER` (there is no model reference at compile time, and no
|
|
12
|
+
* production seam routes a `DBModel` into the SCP compile — grep: `FIND_FILTER` appears only
|
|
13
|
+
* in `DBModel`/`decorators`/`types`, never under `src/scp/`). Auto-apply is therefore
|
|
14
|
+
* impossible without model context the SCP compile does not have.
|
|
15
|
+
*
|
|
16
|
+
* Resolution = the plan's variant chosen fail-closed: a model that DECLARES a `FIND_FILTER`
|
|
17
|
+
* MUST have its scope predicates folded into the authored `L.Select({ where })`; if the
|
|
18
|
+
* author routes such a model through SCP WITHOUT the scope keys, this guard throws loudly
|
|
19
|
+
* ({@link FindFilterLeakError}) rather than silently dropping the filter (which would leak
|
|
20
|
+
* soft-deleted / cross-tenant rows — a correctness bug, not a cosmetic one). When the scope
|
|
21
|
+
* keys ARE present the guard is a no-op (byte-identical to v1's merged WHERE — proven in
|
|
22
|
+
* `test/scp/find-filter-noop.test.ts`).
|
|
23
|
+
*/
|
|
24
|
+
import { type Conds } from '../Column';
|
|
25
|
+
/** A `DBModel`-shaped source: the only field this guard reads is the optional `FIND_FILTER`. */
|
|
26
|
+
export interface FindFilterSource {
|
|
27
|
+
/** The per-model implicit scope predicate (v1 `DBModel.FIND_FILTER`), or null/undefined. */
|
|
28
|
+
readonly FIND_FILTER?: Conds | null;
|
|
29
|
+
/** Class name for diagnostics (present on every `DBModel` subclass). */
|
|
30
|
+
readonly name?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A model declaring a `FIND_FILTER` was compiled via the SCP path without its scope
|
|
34
|
+
* predicates present in the authored WHERE — the filter would silently leak. Thrown
|
|
35
|
+
* fail-closed at compile time; never swallowed.
|
|
36
|
+
*/
|
|
37
|
+
export declare class FindFilterLeakError extends Error {
|
|
38
|
+
/** The declaring model's class name (diagnostics). */
|
|
39
|
+
readonly modelName: string;
|
|
40
|
+
/** The FIND_FILTER scope keys that are MISSING from the authored WHERE. */
|
|
41
|
+
readonly missingKeys: readonly string[];
|
|
42
|
+
constructor(
|
|
43
|
+
/** The declaring model's class name (diagnostics). */
|
|
44
|
+
modelName: string,
|
|
45
|
+
/** The FIND_FILTER scope keys that are MISSING from the authored WHERE. */
|
|
46
|
+
missingKeys: readonly string[]);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract the top-level predicate KEYS a `FIND_FILTER` folds into a WHERE. Uses the SAME
|
|
50
|
+
* `condsToRecord` v1 runs when merging (`DBModel._buildSelectSQL`:597) so the key set is
|
|
51
|
+
* exactly what v1 would add to `normalizedCond`. `__or__` (grouped OR) is kept as a key so a
|
|
52
|
+
* scoped OR-group also demands explicit authoring (fail-closed; never silently satisfied).
|
|
53
|
+
*/
|
|
54
|
+
export declare function findFilterKeys(filter: Conds | null | undefined): string[];
|
|
55
|
+
/**
|
|
56
|
+
* Fail-closed guard: assert a model's `FIND_FILTER` scope keys are all present in the
|
|
57
|
+
* authored WHERE key set BEFORE an SCP compile of that model. No FIND_FILTER → no-op. When
|
|
58
|
+
* present, EVERY scope key must appear in `authoredWhereKeys`; any missing key throws
|
|
59
|
+
* {@link FindFilterLeakError}. The caller passes the top-level keys of the object it hands to
|
|
60
|
+
* `L.Select({ where })` (the same shape `condsToRecord` yields), so the check compares
|
|
61
|
+
* like-for-like against v1's merged predicate.
|
|
62
|
+
*
|
|
63
|
+
* @param model a `DBModel`-shaped source that MAY declare `FIND_FILTER`.
|
|
64
|
+
* @param authoredWhereKeys the top-level WHERE keys the SCP author expressed for this model.
|
|
65
|
+
* @throws FindFilterLeakError when a declared scope key is absent from the authored WHERE.
|
|
66
|
+
*/
|
|
67
|
+
export declare function assertFindFilterFolded(model: FindFilterSource, authoredWhereKeys: Iterable<string>): void;
|
|
68
|
+
//# sourceMappingURL=find-filter-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-filter-guard.d.ts","sourceRoot":"","sources":["../../src/scp/find-filter-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,WAAW,CAAC;AAEtD,gGAAgG;AAChG,MAAM,WAAW,gBAAgB;IAC/B,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAE1C,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE;;IAHvC,sDAAsD;IAC7C,SAAS,EAAE,MAAM;IAC1B,2EAA2E;IAClE,WAAW,EAAE,SAAS,MAAM,EAAE;CAY1C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAGzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,gBAAgB,EACvB,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,GAClC,IAAI,CAQN"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* litedbmodel v2 SCP — FIND_FILTER fail-closed authoring guard (#47 Finding B / plan R8).
|
|
4
|
+
*
|
|
5
|
+
* `FIND_FILTER` is a v1 PER-MODEL implicit predicate (a soft-delete / tenant scope) that
|
|
6
|
+
* v1 MERGES into the WHERE of every internal `find()`/`count()` before compiling
|
|
7
|
+
* (`DBModel._buildSelectSQL` / `_count`: `normalizedCond.add(condsToRecord(FIND_FILTER))`).
|
|
8
|
+
* It is not a distinct SQL construct — it manifests purely as extra WHERE fragments.
|
|
9
|
+
*
|
|
10
|
+
* The SCP compile path (`L.Select({ where })` → `compileReadGraph` → `renderReadPrimary`)
|
|
11
|
+
* is AUTHORED from an explicit `where`; it has NO `DBModel` class context, so it CANNOT
|
|
12
|
+
* auto-apply a model's `FIND_FILTER` (there is no model reference at compile time, and no
|
|
13
|
+
* production seam routes a `DBModel` into the SCP compile — grep: `FIND_FILTER` appears only
|
|
14
|
+
* in `DBModel`/`decorators`/`types`, never under `src/scp/`). Auto-apply is therefore
|
|
15
|
+
* impossible without model context the SCP compile does not have.
|
|
16
|
+
*
|
|
17
|
+
* Resolution = the plan's variant chosen fail-closed: a model that DECLARES a `FIND_FILTER`
|
|
18
|
+
* MUST have its scope predicates folded into the authored `L.Select({ where })`; if the
|
|
19
|
+
* author routes such a model through SCP WITHOUT the scope keys, this guard throws loudly
|
|
20
|
+
* ({@link FindFilterLeakError}) rather than silently dropping the filter (which would leak
|
|
21
|
+
* soft-deleted / cross-tenant rows — a correctness bug, not a cosmetic one). When the scope
|
|
22
|
+
* keys ARE present the guard is a no-op (byte-identical to v1's merged WHERE — proven in
|
|
23
|
+
* `test/scp/find-filter-noop.test.ts`).
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.FindFilterLeakError = void 0;
|
|
27
|
+
exports.findFilterKeys = findFilterKeys;
|
|
28
|
+
exports.assertFindFilterFolded = assertFindFilterFolded;
|
|
29
|
+
const Column_1 = require("../Column");
|
|
30
|
+
/**
|
|
31
|
+
* A model declaring a `FIND_FILTER` was compiled via the SCP path without its scope
|
|
32
|
+
* predicates present in the authored WHERE — the filter would silently leak. Thrown
|
|
33
|
+
* fail-closed at compile time; never swallowed.
|
|
34
|
+
*/
|
|
35
|
+
class FindFilterLeakError extends Error {
|
|
36
|
+
modelName;
|
|
37
|
+
missingKeys;
|
|
38
|
+
constructor(
|
|
39
|
+
/** The declaring model's class name (diagnostics). */
|
|
40
|
+
modelName,
|
|
41
|
+
/** The FIND_FILTER scope keys that are MISSING from the authored WHERE. */
|
|
42
|
+
missingKeys) {
|
|
43
|
+
super(`FIND_FILTER leak: model '${modelName}' declares an implicit scope predicate on ` +
|
|
44
|
+
`[${missingKeys.join(', ')}] that is NOT present in the SCP-authored WHERE. The SCP ` +
|
|
45
|
+
`compile cannot auto-apply FIND_FILTER (no model context at compile time), so the ` +
|
|
46
|
+
`scope predicate would be silently dropped (soft-delete / tenant scope leak). Fold ` +
|
|
47
|
+
`the FIND_FILTER predicates into the authored L.Select({ where }) explicitly ` +
|
|
48
|
+
`(e.g. whereEq/whereIsNull on ${missingKeys.join(', ')}).`);
|
|
49
|
+
this.modelName = modelName;
|
|
50
|
+
this.missingKeys = missingKeys;
|
|
51
|
+
this.name = 'FindFilterLeakError';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.FindFilterLeakError = FindFilterLeakError;
|
|
55
|
+
/**
|
|
56
|
+
* Extract the top-level predicate KEYS a `FIND_FILTER` folds into a WHERE. Uses the SAME
|
|
57
|
+
* `condsToRecord` v1 runs when merging (`DBModel._buildSelectSQL`:597) so the key set is
|
|
58
|
+
* exactly what v1 would add to `normalizedCond`. `__or__` (grouped OR) is kept as a key so a
|
|
59
|
+
* scoped OR-group also demands explicit authoring (fail-closed; never silently satisfied).
|
|
60
|
+
*/
|
|
61
|
+
function findFilterKeys(filter) {
|
|
62
|
+
if (!filter || filter.length === 0)
|
|
63
|
+
return [];
|
|
64
|
+
return Object.keys((0, Column_1.condsToRecord)(filter));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Fail-closed guard: assert a model's `FIND_FILTER` scope keys are all present in the
|
|
68
|
+
* authored WHERE key set BEFORE an SCP compile of that model. No FIND_FILTER → no-op. When
|
|
69
|
+
* present, EVERY scope key must appear in `authoredWhereKeys`; any missing key throws
|
|
70
|
+
* {@link FindFilterLeakError}. The caller passes the top-level keys of the object it hands to
|
|
71
|
+
* `L.Select({ where })` (the same shape `condsToRecord` yields), so the check compares
|
|
72
|
+
* like-for-like against v1's merged predicate.
|
|
73
|
+
*
|
|
74
|
+
* @param model a `DBModel`-shaped source that MAY declare `FIND_FILTER`.
|
|
75
|
+
* @param authoredWhereKeys the top-level WHERE keys the SCP author expressed for this model.
|
|
76
|
+
* @throws FindFilterLeakError when a declared scope key is absent from the authored WHERE.
|
|
77
|
+
*/
|
|
78
|
+
function assertFindFilterFolded(model, authoredWhereKeys) {
|
|
79
|
+
const required = findFilterKeys(model.FIND_FILTER);
|
|
80
|
+
if (required.length === 0)
|
|
81
|
+
return; // No implicit scope → nothing to fold → no-op.
|
|
82
|
+
const present = new Set(authoredWhereKeys);
|
|
83
|
+
const missing = required.filter((k) => !present.has(k));
|
|
84
|
+
if (missing.length > 0) {
|
|
85
|
+
throw new FindFilterLeakError(model.name ?? '<anonymous model>', missing);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=find-filter-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-filter-guard.js","sourceRoot":"","sources":["../../src/scp/find-filter-guard.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;AA0CH,wCAGC;AAcD,wDAWC;AApED,sCAAsD;AAUtD;;;;GAIG;AACH,MAAa,mBAAoB,SAAQ,KAAK;IAGjC;IAEA;IAJX;IACE,sDAAsD;IAC7C,SAAiB;IAC1B,2EAA2E;IAClE,WAA8B;QAEvC,KAAK,CACH,4BAA4B,SAAS,4CAA4C;YAC/E,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,2DAA2D;YACrF,mFAAmF;YACnF,oFAAoF;YACpF,8EAA8E;YAC9E,gCAAgC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAC7D,CAAC;QAXO,cAAS,GAAT,SAAS,CAAQ;QAEjB,gBAAW,GAAX,WAAW,CAAmB;QAUvC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAjBD,kDAiBC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,MAAgC;IAC7D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,MAAM,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,sBAAsB,CACpC,KAAuB,EACvB,iBAAmC;IAEnC,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,+CAA+C;IAClF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,mBAAmB,CAAC,KAAK,CAAC,IAAI,IAAI,mBAAmB,EAAE,OAAO,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* litedbmodel v2 SCP — fragment RUNTIME (assemble + bind).
|
|
3
|
+
*
|
|
4
|
+
* This is the thin runtime a bundle drives. It does exactly three things:
|
|
5
|
+
*
|
|
6
|
+
* 1. ASSEMBLE — walk the ordered fragment list; drop any fragment whose `skip`
|
|
7
|
+
* is satisfied; concatenate the present fragments' `sql`, and their `params`
|
|
8
|
+
* in order. Nested-fragment params splice their own `sql` at the `?` and
|
|
9
|
+
* contribute their own params in order.
|
|
10
|
+
* 2. EVALUATE — turn each value-spec param into a concrete bound value using the
|
|
11
|
+
* runtime `input` (and upstream `wire` results).
|
|
12
|
+
* 3. RENDER — the produced `{ sql, params }` uses `?`; a dialect step turns `?`
|
|
13
|
+
* into `$N` for PostgreSQL (identical to the original driver's naive replace).
|
|
14
|
+
*
|
|
15
|
+
* NO SQL structure is generated here. The `sql` text is already complete; the
|
|
16
|
+
* runtime only splices nested-fragment text and fills `?`.
|
|
17
|
+
*/
|
|
18
|
+
import { type Fragment, type Node, type WhereGroup, type ValueSpec, type PresenceCondition } from './model';
|
|
19
|
+
/** Runtime binding scope: FLAT — input keys and wire results are top-level roots. */
|
|
20
|
+
export interface Scope {
|
|
21
|
+
input: Record<string, unknown>;
|
|
22
|
+
wire?: Record<string, Record<string, unknown>>;
|
|
23
|
+
}
|
|
24
|
+
/** Is a fragment's `skip` satisfied (⇒ omit the fragment)? */
|
|
25
|
+
export declare function isSkipped(cond: PresenceCondition | undefined, scope: Scope): boolean;
|
|
26
|
+
/** Evaluate a value-spec to its bound value against the runtime scope. */
|
|
27
|
+
export declare function evalValueSpec(spec: ValueSpec, scope: Scope): unknown;
|
|
28
|
+
/**
|
|
29
|
+
* Assemble a single fragment: interleave its literal `sql` (split on `?`) with the
|
|
30
|
+
* rendered text of each param, concatenating params in order.
|
|
31
|
+
*/
|
|
32
|
+
export declare function assembleFragment(frag: Fragment, scope: Scope): {
|
|
33
|
+
sql: string;
|
|
34
|
+
params: unknown[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Assemble a WHERE group: join present members with `" AND "`, prefix `" WHERE "`.
|
|
38
|
+
* If no member is present, produce the empty string (identical to the ORIGINAL
|
|
39
|
+
* `DBConditions.compile` → `parts.length === 0 ? '' : parts.join(' AND ')`, with the
|
|
40
|
+
* `" WHERE "` prefix owned by the caller/select in the original — here folded in).
|
|
41
|
+
*/
|
|
42
|
+
export declare function assembleWhereGroup(group: WhereGroup, scope: Scope): {
|
|
43
|
+
sql: string;
|
|
44
|
+
params: unknown[];
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Assemble an ordered fragment/WHERE-group list into a single `{ sql, params }`
|
|
48
|
+
* (with `?`). Fragments whose `skip` is satisfied are omitted entirely (sql AND
|
|
49
|
+
* params). A WHERE group joins its present members with the original's text glue.
|
|
50
|
+
*/
|
|
51
|
+
export declare function assemble(nodes: Node[], scope: Scope): {
|
|
52
|
+
sql: string;
|
|
53
|
+
params: unknown[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* PostgreSQL dialect render: `?` → `$1, $2, …`. Byte-identical to the original
|
|
57
|
+
* driver's `convertPlaceholders` (naive left-to-right replace; see
|
|
58
|
+
* `src/drivers/postgres.ts`).
|
|
59
|
+
*/
|
|
60
|
+
export declare function toPostgres(sql: string): string;
|
|
61
|
+
//# sourceMappingURL=assemble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../../../src/scp/fragment/assemble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,IAAI,EACT,KAAK,UAAU,EAEf,KAAK,SAAS,EACd,KAAK,iBAAiB,EAOvB,MAAM,SAAS,CAAC;AAEjB,qFAAqF;AACrF,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChD;AAWD,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,IAAI,EAAE,iBAAiB,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAIpF;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CA+BpE;AAYD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAejG;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAWtG;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAgBxF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9C"}
|