litedbmodel 1.2.10 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +1 -1
  2. package/dist/DBModel.d.ts.map +1 -1
  3. package/dist/DBModel.js +6 -0
  4. package/dist/DBModel.js.map +1 -1
  5. package/dist/scp/authoring-sql.d.ts +134 -0
  6. package/dist/scp/authoring-sql.d.ts.map +1 -0
  7. package/dist/scp/authoring-sql.js +191 -0
  8. package/dist/scp/authoring-sql.js.map +1 -0
  9. package/dist/scp/authoring.d.ts +155 -0
  10. package/dist/scp/authoring.d.ts.map +1 -0
  11. package/dist/scp/authoring.js +162 -0
  12. package/dist/scp/authoring.js.map +1 -0
  13. package/dist/scp/catalog.d.ts +91 -0
  14. package/dist/scp/catalog.d.ts.map +1 -0
  15. package/dist/scp/catalog.js +230 -0
  16. package/dist/scp/catalog.js.map +1 -0
  17. package/dist/scp/codegen.d.ts +95 -0
  18. package/dist/scp/codegen.d.ts.map +1 -0
  19. package/dist/scp/codegen.js +94 -0
  20. package/dist/scp/codegen.js.map +1 -0
  21. package/dist/scp/dialect.d.ts +141 -0
  22. package/dist/scp/dialect.d.ts.map +1 -0
  23. package/dist/scp/dialect.js +194 -0
  24. package/dist/scp/dialect.js.map +1 -0
  25. package/dist/scp/errors.d.ts +36 -0
  26. package/dist/scp/errors.d.ts.map +1 -0
  27. package/dist/scp/errors.js +72 -0
  28. package/dist/scp/errors.js.map +1 -0
  29. package/dist/scp/find-filter-guard.d.ts +68 -0
  30. package/dist/scp/find-filter-guard.d.ts.map +1 -0
  31. package/dist/scp/find-filter-guard.js +88 -0
  32. package/dist/scp/find-filter-guard.js.map +1 -0
  33. package/dist/scp/fragment/assemble.d.ts +61 -0
  34. package/dist/scp/fragment/assemble.d.ts.map +1 -0
  35. package/dist/scp/fragment/assemble.js +148 -0
  36. package/dist/scp/fragment/assemble.js.map +1 -0
  37. package/dist/scp/fragment/compile-pg.d.ts +107 -0
  38. package/dist/scp/fragment/compile-pg.d.ts.map +1 -0
  39. package/dist/scp/fragment/compile-pg.js +142 -0
  40. package/dist/scp/fragment/compile-pg.js.map +1 -0
  41. package/dist/scp/fragment/index.d.ts +16 -0
  42. package/dist/scp/fragment/index.d.ts.map +1 -0
  43. package/dist/scp/fragment/index.js +34 -0
  44. package/dist/scp/fragment/index.js.map +1 -0
  45. package/dist/scp/fragment/model.d.ts +119 -0
  46. package/dist/scp/fragment/model.d.ts.map +1 -0
  47. package/dist/scp/fragment/model.js +66 -0
  48. package/dist/scp/fragment/model.js.map +1 -0
  49. package/dist/scp/fragment/pg-array-type.d.ts +13 -0
  50. package/dist/scp/fragment/pg-array-type.d.ts.map +1 -0
  51. package/dist/scp/fragment/pg-array-type.js +34 -0
  52. package/dist/scp/fragment/pg-array-type.js.map +1 -0
  53. package/dist/scp/guard.d.ts +43 -0
  54. package/dist/scp/guard.d.ts.map +1 -0
  55. package/dist/scp/guard.js +134 -0
  56. package/dist/scp/guard.js.map +1 -0
  57. package/dist/scp/index.cjs +12202 -0
  58. package/dist/scp/index.d.ts +64 -0
  59. package/dist/scp/index.d.ts.map +1 -0
  60. package/dist/scp/index.js +238 -0
  61. package/dist/scp/index.js.map +1 -0
  62. package/dist/scp/index.mjs +4819 -0
  63. package/dist/scp/makesql/authoring-compile.d.ts +90 -0
  64. package/dist/scp/makesql/authoring-compile.d.ts.map +1 -0
  65. package/dist/scp/makesql/authoring-compile.js +494 -0
  66. package/dist/scp/makesql/authoring-compile.js.map +1 -0
  67. package/dist/scp/makesql/compile-crud.d.ts +133 -0
  68. package/dist/scp/makesql/compile-crud.d.ts.map +1 -0
  69. package/dist/scp/makesql/compile-crud.js +288 -0
  70. package/dist/scp/makesql/compile-crud.js.map +1 -0
  71. package/dist/scp/makesql/compile-relation.d.ts +157 -0
  72. package/dist/scp/makesql/compile-relation.d.ts.map +1 -0
  73. package/dist/scp/makesql/compile-relation.js +425 -0
  74. package/dist/scp/makesql/compile-relation.js.map +1 -0
  75. package/dist/scp/makesql/compile-select.d.ts +45 -0
  76. package/dist/scp/makesql/compile-select.d.ts.map +1 -0
  77. package/dist/scp/makesql/compile-select.js +58 -0
  78. package/dist/scp/makesql/compile-select.js.map +1 -0
  79. package/dist/scp/makesql/compile.d.ts +63 -0
  80. package/dist/scp/makesql/compile.d.ts.map +1 -0
  81. package/dist/scp/makesql/compile.js +99 -0
  82. package/dist/scp/makesql/compile.js.map +1 -0
  83. package/dist/scp/makesql/handler.d.ts +58 -0
  84. package/dist/scp/makesql/handler.d.ts.map +1 -0
  85. package/dist/scp/makesql/handler.js +113 -0
  86. package/dist/scp/makesql/handler.js.map +1 -0
  87. package/dist/scp/makesql/index.d.ts +33 -0
  88. package/dist/scp/makesql/index.d.ts.map +1 -0
  89. package/dist/scp/makesql/index.js +114 -0
  90. package/dist/scp/makesql/index.js.map +1 -0
  91. package/dist/scp/makesql/ir.d.ts +42 -0
  92. package/dist/scp/makesql/ir.d.ts.map +1 -0
  93. package/dist/scp/makesql/ir.js +66 -0
  94. package/dist/scp/makesql/ir.js.map +1 -0
  95. package/dist/scp/makesql/json-array.d.ts +84 -0
  96. package/dist/scp/makesql/json-array.d.ts.map +1 -0
  97. package/dist/scp/makesql/json-array.js +118 -0
  98. package/dist/scp/makesql/json-array.js.map +1 -0
  99. package/dist/scp/makesql/json-batch.d.ts +102 -0
  100. package/dist/scp/makesql/json-batch.d.ts.map +1 -0
  101. package/dist/scp/makesql/json-batch.js +269 -0
  102. package/dist/scp/makesql/json-batch.js.map +1 -0
  103. package/dist/scp/makesql/makesql.d.ts +99 -0
  104. package/dist/scp/makesql/makesql.d.ts.map +1 -0
  105. package/dist/scp/makesql/makesql.js +122 -0
  106. package/dist/scp/makesql/makesql.js.map +1 -0
  107. package/dist/scp/makesql/pool-executor.d.ts +47 -0
  108. package/dist/scp/makesql/pool-executor.d.ts.map +1 -0
  109. package/dist/scp/makesql/pool-executor.js +50 -0
  110. package/dist/scp/makesql/pool-executor.js.map +1 -0
  111. package/dist/scp/makesql/static-bundle.d.ts +185 -0
  112. package/dist/scp/makesql/static-bundle.d.ts.map +1 -0
  113. package/dist/scp/makesql/static-bundle.js +1024 -0
  114. package/dist/scp/makesql/static-bundle.js.map +1 -0
  115. package/dist/scp/makesql/tx.d.ts +216 -0
  116. package/dist/scp/makesql/tx.d.ts.map +1 -0
  117. package/dist/scp/makesql/tx.js +743 -0
  118. package/dist/scp/makesql/tx.js.map +1 -0
  119. package/dist/scp/relation.d.ts +148 -0
  120. package/dist/scp/relation.d.ts.map +1 -0
  121. package/dist/scp/relation.js +257 -0
  122. package/dist/scp/relation.js.map +1 -0
  123. package/dist/scp/runtime.d.ts +231 -0
  124. package/dist/scp/runtime.d.ts.map +1 -0
  125. package/dist/scp/runtime.js +381 -0
  126. package/dist/scp/runtime.js.map +1 -0
  127. package/dist/scp/typed-object.d.ts +99 -0
  128. package/dist/scp/typed-object.d.ts.map +1 -0
  129. package/dist/scp/typed-object.js +184 -0
  130. package/dist/scp/typed-object.js.map +1 -0
  131. package/dist/scp/writes.d.ts +251 -0
  132. package/dist/scp/writes.d.ts.map +1 -0
  133. package/dist/scp/writes.js +176 -0
  134. package/dist/scp/writes.js.map +1 -0
  135. package/docs/proposal/contracts-architecture-feasibility.md +328 -0
  136. package/docs/proposal/contracts-architecture.md +579 -0
  137. package/docs/proposal/litedbmodel-v2-scp-architecture.md +382 -0
  138. package/docs/proposal/sql-dynamic-expansion-spec.md +175 -0
  139. package/docs/proposal/v0-coverage-matrix.md +157 -0
  140. package/docs/proposal/v2-completeness-plan.md +90 -0
  141. package/docs/proposal/v2-sql-parity-checklist.md +162 -0
  142. package/package.json +27 -5
  143. package/docs/README_REVIEW.md +0 -23
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP catalog — WS1 (#21).
4
+ *
5
+ * `LITEDBMODEL_CATALOG` is the behavior-contracts–typed `Catalog` that IS the whole
6
+ * per-DSL difference litedbmodel supplies as a SQL-backend consumer (bc C2: "the only
7
+ * per-DSL difference is the catalog"). It mirrors the SHAPE of graphddb's
8
+ * `GRAPHDDB_CATALOG` (`src/spec/catalog.ts`) exactly: compact `PortSchema` constructors,
9
+ * an `entry()` helper, per-primitive `inputPorts`, an `output.shape`, and a
10
+ * `portableToIR` flag. The effect implementation (SQL execution + row→model assembly) is
11
+ * bound separately in the handler registry (WS3, C4 — catalog declares, registry binds).
12
+ *
13
+ * ## Catalog names (spec §1 / §11 item 1)
14
+ *
15
+ * `Select` / `Insert` / `Update` / `Delete` are the CRUD leaf components. `Fragment` is
16
+ * the dynamic WHERE/SET fragment-tree component (SKIP → fragment existence rules, §8);
17
+ * `Tx` is the multi-statement transaction envelope. As in graphddb, the transaction
18
+ * envelope (`Tx`) is `portableToIR: false` — a transaction is emitted as a Component
19
+ * whose body references the per-statement CRUD primitives; the atomic BEGIN/COMMIT
20
+ * envelope is the runtime's execution concern (WS3), never a portable-IR node.
21
+ *
22
+ * ## Port schema conventions
23
+ *
24
+ * A `CatalogEntry.inputPorts` names the STATIC ports of the emitted wiring. Two families
25
+ * are dynamic by construction and are validated by {@link assertComponentsInCatalog}
26
+ * against documented patterns instead of being statically enumerable:
27
+ *
28
+ * - **`where`/`set`/`values` records**: one port per model field, flattened one-port-
29
+ * per-field under a `<group>.<field>` key ({@link WRITE_PORT_FAMILIES}). These carry
30
+ * Expression IR (the field's value/condition), from the closed operator set only.
31
+ *
32
+ * The CRUD entries carry `additionalPorts: true` (bc#26) so bc's shared port check
33
+ * (`checkPortNames` / `buildComponentDefinition`) accepts the dynamic families; every
34
+ * DECLARED port keeps bc's required/type checks regardless of the opt-in. `Tx`'s single
35
+ * port is static, so it keeps bc's fail-closed default.
36
+ */
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.WRITE_PORT_FAMILIES = exports.WRITE_CATALOG_NAMES = exports.CATALOG_NAMES = exports.LITEDBMODEL_CATALOG = void 0;
39
+ exports.catalogEntry = catalogEntry;
40
+ exports.assertComponentsInCatalog = assertComponentsInCatalog;
41
+ exports.deriveContractEffect = deriveContractEffect;
42
+ const behavior_contracts_1 = require("behavior-contracts");
43
+ // Compact schema constructors (the IR bundle is size-budgeted — graphddb convention).
44
+ const P = (type, required) => (required ? { type, required } : { type });
45
+ /**
46
+ * The shared read-port surface for `Select`: `table` always; the optional
47
+ * `where` (a fragment-tree reference — see `Fragment`), `order`, `limit`, `offset`,
48
+ * `group` wiring, and the always-emitted `select` projection.
49
+ *
50
+ * `where` is typed `fragment` (not `expr`): a Select's dynamic WHERE is a fragment tree
51
+ * (§8), NOT a single Expression — the SKIP existence rules live on the tree, outside the
52
+ * Expression IR vocabulary (bc `expression-ir.md` §4: SKIP is OUTSIDE Expression IR).
53
+ * `limit` / `offset` are `expr` (they may be an input-ref or a `coalesce` default, §8).
54
+ */
55
+ const SELECT_PORTS = {
56
+ table: P('string', true),
57
+ select: P('string[]', true),
58
+ where: P('fragment'),
59
+ order: P('string'),
60
+ limit: P('expr'),
61
+ offset: P('expr'),
62
+ group: P('string'),
63
+ // Additive read-tail/head ports (V0 R3/R4/R5/R6). SQL is v1-sourced from the matching
64
+ // `SelectDesc` fields via `compileSelect` (`_buildSelectSQL`), wired in `compileSelectNode`:
65
+ // - `forUpdate` (R3): a literal `'true'` string toggles the ` FOR UPDATE` tail.
66
+ // - `join`/`joinParams` (R5): a literal JOIN clause text (`JOIN t ON …`) + its bound
67
+ // value-specs (`expr[]`), spliced after `FROM <t>` (v1 `_buildSelectSQL` JOIN position).
68
+ // - `cte`/`cteParams` (R4): a WITH-CTE `{name, sql}` literal + its bound value-specs,
69
+ // prefixed as `WITH <name> AS (<sql>) ` (v1 WITH-wrap). `cteParams` bind FIRST (v1 param
70
+ // order: CTE → JOIN → WHERE).
71
+ // - `append` (R6): a raw trailing clause text (e.g. `HAVING …`) appended verbatim.
72
+ forUpdate: P('string'),
73
+ join: P('string'),
74
+ joinParams: P('expr[]'),
75
+ cte: P('map'),
76
+ cteParams: P('expr[]'),
77
+ append: P('string'),
78
+ };
79
+ /**
80
+ * The shared write-port surface for `Insert`/`Update`/`Delete`: `table` always;
81
+ * `where` (fragment tree — required existence enforced by the compiler, not here, since a
82
+ * Select may legitimately omit it); `returning` projection; `onConflict` wiring for
83
+ * Insert. The per-field value/set ports (`values.<field>` / `set.<field>`) are dynamic
84
+ * ({@link WRITE_PORT_FAMILIES}) and each carries an Expression IR value.
85
+ */
86
+ const WRITE_PORTS = {
87
+ table: P('string', true),
88
+ where: P('fragment'),
89
+ returning: P('string'),
90
+ onConflict: P('string'),
91
+ onConflictAction: P('string'),
92
+ // PRIMARY KEY descriptor for the MySQL RETURNING emulation (INSERT…RETURNING): `pk` is a
93
+ // comma-separated PK column list, `autoInc` names the single AUTO_INCREMENT column (absent for a
94
+ // client-supplied PK). Consumed by compileWriteNode → mysqlPkHint so the emulation re-selects by
95
+ // the REAL PK. Inert on PG/SQLite (native RETURNING).
96
+ pk: P('string'),
97
+ autoInc: P('string'),
98
+ };
99
+ const entry = (name, inputPorts, shape, portableToIR) => ({
100
+ name,
101
+ inputPorts,
102
+ output: { shape },
103
+ portableToIR,
104
+ // Dynamic port families (where/set/values record ports) are validated by
105
+ // assertComponentsInCatalog, not statically enumerable. Tx overrides back to
106
+ // fail-closed (its one port is static).
107
+ additionalPorts: true,
108
+ });
109
+ /**
110
+ * litedbmodel's specific-component catalog (spec §11 item 1) — the behavior-contracts
111
+ * `Catalog`-typed source of truth. Each entry declares the Port schema of one SQL
112
+ * primitive AS THE BACKEND COMPILE WIRES IT; the effect implementation is bound
113
+ * separately in the handler registry (WS3, C4). All entries except `Tx` may appear in
114
+ * the portable IR.
115
+ */
116
+ exports.LITEDBMODEL_CATALOG = {
117
+ // Read: `items` (a Select root yields a row list; per-row collapse to `item` is the
118
+ // consumer's cardinality concern, mirrored from graphddb Query's `cardinality` port).
119
+ Select: entry('Select', { ...SELECT_PORTS, cardinality: P('string') }, 'items', true),
120
+ // COUNT(*) aggregate read (v1 `DBModel._count`): `SELECT COUNT(*) as count FROM t[ WHERE …]`.
121
+ // Only `table` (required) + the optional `where` fragment tree — v1's count carries no
122
+ // projection/order/limit/offset (it counts the filtered rows). Output is a one-row `[{count}]`
123
+ // list (the `items` shape, like every read); the consumer reads `count` — v1's `parseInt(count)`.
124
+ Count: entry('Count', { table: P('string', true), where: P('fragment') }, 'items', true),
125
+ // Writes yield the RETURNING row list (`items`); a single-row write collapses at the
126
+ // consumer boundary, same as reads.
127
+ Insert: entry('Insert', WRITE_PORTS, 'items', true),
128
+ Update: entry('Update', WRITE_PORTS, 'items', true),
129
+ Delete: entry('Delete', WRITE_PORTS, 'items', true),
130
+ // The dynamic WHERE/SET fragment-tree component (§8). Its ports carry the fragment
131
+ // tree; the compiler resolves SKIP/AND-OR structure to fragment existence rules.
132
+ Fragment: entry('Fragment', { tree: P('fragment', true) }, 'item', true),
133
+ // The runtime-side atomic envelope: never referenced by the portable IR (a transaction
134
+ // IS a component over the CRUD primitives) — runtime-only. Its single port is static,
135
+ // so it keeps bc's fail-closed default (no additionalPorts opt-in).
136
+ Tx: {
137
+ ...entry('Tx', { statements: P('map[]', true) }, 'item', false),
138
+ additionalPorts: false,
139
+ },
140
+ };
141
+ /** Look up a catalog entry by name (undefined for an unknown primitive). */
142
+ function catalogEntry(name) {
143
+ return exports.LITEDBMODEL_CATALOG[name];
144
+ }
145
+ /** The catalog names litedbmodel declares (the C2 per-DSL surface). */
146
+ exports.CATALOG_NAMES = [
147
+ 'Select',
148
+ 'Count',
149
+ 'Insert',
150
+ 'Update',
151
+ 'Delete',
152
+ 'Fragment',
153
+ 'Tx',
154
+ ];
155
+ /**
156
+ * The CQRS write catalog: the names whose presence in a component body makes the
157
+ * component a COMMAND (spec §2.4 — effect is derived from the graph, not authored).
158
+ * `Select`/`Fragment` are read-side; `Insert`/`Update`/`Delete`/`Tx` are write-side.
159
+ */
160
+ exports.WRITE_CATALOG_NAMES = [
161
+ 'Insert',
162
+ 'Update',
163
+ 'Delete',
164
+ 'Tx',
165
+ ];
166
+ const WRITE_SET = new Set(exports.WRITE_CATALOG_NAMES);
167
+ /**
168
+ * The dynamic per-field write-port families (`<group>.<field>` — the flattened record
169
+ * convention; longest-prefix wins). A `values.<field>` (Insert) or `set.<field>`
170
+ * (Update) port carries the field's Expression IR value.
171
+ */
172
+ exports.WRITE_PORT_FAMILIES = [
173
+ 'values.',
174
+ 'set.',
175
+ ];
176
+ /**
177
+ * The emitter's catalog validation (loud; a violation is a BUILD error), mirrored from
178
+ * graphddb's `assertComponentsInCatalog`. Every `componentRef` / `map` body node of every
179
+ * emitted component must:
180
+ *
181
+ * 1. reference a declared catalog name;
182
+ * 2. wire every `required` port of that entry;
183
+ * 3. wire ONLY declared ports — a port is declared if it is a static `inputPorts` name or
184
+ * a write record-family port ({@link WRITE_PORT_FAMILIES}, write entries only).
185
+ *
186
+ * All violations are collected and thrown as one error. `cond` nodes carry no component
187
+ * reference and are skipped.
188
+ */
189
+ function assertComponentsInCatalog(components) {
190
+ const errs = [];
191
+ for (const c of components) {
192
+ for (const n of c.body) {
193
+ if ('cond' in n)
194
+ continue;
195
+ const ref = 'map' in n ? n.map : n;
196
+ const entryDef = exports.LITEDBMODEL_CATALOG[ref.component];
197
+ if (entryDef === undefined) {
198
+ errs.push(`${c.name}/${n.id}: references '${ref.component}', not a LITEDBMODEL_CATALOG entry (known: ${exports.CATALOG_NAMES.join(', ')})`);
199
+ continue;
200
+ }
201
+ const ports = ref.ports;
202
+ for (const [p, s] of Object.entries(entryDef.inputPorts)) {
203
+ if (s.required === true && !(p in ports)) {
204
+ errs.push(`${c.name}/${n.id} (${ref.component}): required port '${p}' is not wired`);
205
+ }
206
+ }
207
+ const isWriteItem = WRITE_SET.has(ref.component);
208
+ for (const p of Object.keys(ports)) {
209
+ if (p in entryDef.inputPorts)
210
+ continue;
211
+ if (isWriteItem && exports.WRITE_PORT_FAMILIES.some((f) => p.startsWith(f)))
212
+ continue;
213
+ errs.push(`${c.name}/${n.id} (${ref.component}): port '${p}' is not declared by the catalog entry (nor a write record-family port)`);
214
+ }
215
+ }
216
+ }
217
+ if (errs.length > 0) {
218
+ throw new Error(`litedbmodel catalog validation failed (${errs.length} violation${errs.length === 1 ? '' : 's'}):\n - ${errs.join('\n - ')}`);
219
+ }
220
+ }
221
+ /**
222
+ * Derive one component's Query/Command classification FROM THE GRAPH: behavior-contracts'
223
+ * `classifyBehaviorEffect` over {@link WRITE_CATALOG_NAMES} — a component is a `'command'`
224
+ * iff its body references a write-catalog primitive, else a `'query'` (spec §2.4: effect
225
+ * is derived, never authored).
226
+ */
227
+ function deriveContractEffect(component) {
228
+ return (0, behavior_contracts_1.classifyBehaviorEffect)(component, exports.WRITE_CATALOG_NAMES) === 'writing' ? 'command' : 'query';
229
+ }
230
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/scp/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * litedbmodel v2 SCP — mode-3 codegen (WS7f, #35; spec §9 exec-mode 3 / §10 / §11; makeSQL flip,
3
+ * epic #43/#45 Phase B).
4
+ *
5
+ * The static-codegen execution mode ("Codegen・静的(全言語)— IR → 各言語ソース生成 runtime≈0,
6
+ * 入力は可搬IRのみ, bc#13 共有 generator に SQL catalog を供給" — spec §9). It takes a §8 STATIC
7
+ * makeSQL {@link SqlBundle} and, per target language, emits:
8
+ *
9
+ * 1. **Behavior module** — bc's SHARED generator (`generateModule`, bc#13) run over the bundle's
10
+ * portable IR (a read bundle's surrogate `ComponentGraphIR`, or the `makeSQL` component IR for
11
+ * a write), baked as a language-native LITERAL with a `bind(handlers)` accessor delegating to
12
+ * `runBehavior`. litedbmodel writes NO execution logic here — codegen is upstream-owned (bc).
13
+ * 2. **SQL catalog companion** — the pure-JSON STATIC makeSQL catalog (per-node statement
14
+ * templates / relations / transaction). A codegen consumer's thin SQL layer reads it to
15
+ * evaluate skip + value-specs → assemble → render → execute (identically to the mode-2 runtime).
16
+ *
17
+ * ## Byte-identical to the thin-runtime (mode-2), by construction
18
+ *
19
+ * The companion IS the bundle, so a codegen runtime that evaluates it drives the IDENTICAL
20
+ * static-makeSQL render/execute path {@link executeBundle} uses — SQL text (all dialects) and
21
+ * results are identical, not approximately equal. The TS leg PROVES this by executing via the
22
+ * artifact and asserting exact equality vs {@link executeBundle} (see {@link codegenExecuteBundleForTest}).
23
+ */
24
+ import { type ComponentGraphIR, type GeneratedModule, type Scope, type Value } from 'behavior-contracts';
25
+ import type { SqlBundle, SqliteDb } from './runtime';
26
+ import type { DialectName } from './dialect';
27
+ import type { RelationOp } from './relation';
28
+ import type { ReadGraph } from './makesql/static-bundle';
29
+ import type { TransactionPlan } from './makesql/tx';
30
+ /**
31
+ * The languages litedbmodel mode-3 codegen supports — exactly the set bc's shared generator
32
+ * registers (bc#13 SP1 typescript/python + SP2 go/rust/php). {@link assertLanguageSupported}
33
+ * verifies against the LIVE registry so a bc capability drift is caught loudly.
34
+ */
35
+ export declare const CODEGEN_LANGUAGES: readonly ["typescript", "python", "go", "rust", "php"];
36
+ export type CodegenLanguage = (typeof CODEGEN_LANGUAGES)[number];
37
+ /**
38
+ * The SQL catalog companion (spec §9): the STATIC makeSQL bundle fields the codegen consumer's
39
+ * thin SQL layer reads to evaluate + render + execute. Pure JSON — round-trips losslessly.
40
+ */
41
+ export interface SqlCatalogCompanion {
42
+ /** Target SQL dialect (`sqlite`/`postgres`/`mysql`) — compiled once, TS-side (spec §10). */
43
+ readonly dialect: DialectName;
44
+ /** READ bundles: the portable read graph (surrogate IR + per-node makeSQL statements). */
45
+ readonly readGraph?: ReadGraph;
46
+ /** WRITE bundles: the single base-write makeSQL statement template. */
47
+ readonly statement?: {
48
+ readonly sql: string;
49
+ readonly params: readonly unknown[];
50
+ readonly skip?: unknown;
51
+ };
52
+ /** Input heads normalized to present-as-null (absent-key SKIP) — mirrors the bundle. */
53
+ readonly optionalHeads: readonly string[];
54
+ /** Pre-compiled STATIC read-relation batch ops (spec §5/§8), keyed by relation name. */
55
+ readonly relations: Record<string, RelationOp>;
56
+ /** Derived gate-first write-time-relations transaction plan (spec §6/§8), for a Command bundle. */
57
+ readonly transaction?: TransactionPlan;
58
+ }
59
+ /** The full codegen artifact for one bundle × one language. */
60
+ export interface CodegenArtifact {
61
+ /** The target language. */
62
+ readonly language: CodegenLanguage;
63
+ /** The generated behavior module (bc's shared generator output — IR baked as a native literal). */
64
+ readonly module: GeneratedModule;
65
+ /** The SQL catalog companion sidecar (the STATIC makeSQL execution catalog). */
66
+ readonly companion: SqlCatalogCompanion;
67
+ /** The portable IR baked into {@link module}. */
68
+ readonly ir: ComponentGraphIR;
69
+ /** The originating bundle (so the equivalence leg re-executes the SAME static bundle). */
70
+ readonly bundle: SqlBundle;
71
+ }
72
+ /**
73
+ * The portable {@link ComponentGraphIR} view of a §8 bundle: a read bundle's surrogate IR (each
74
+ * SQL node → a `makeSQL` node), or the single `makeSQL` component IR for a write. Baking THIS is
75
+ * what makes the generated module a genuine bc artifact; the static SQL catalog rides the companion.
76
+ */
77
+ export declare function bundleToPortableIR(bundle: SqlBundle): ComponentGraphIR;
78
+ /**
79
+ * Assert the requested language is one bc's shared generator can emit — checked against the LIVE
80
+ * registry, not just the {@link CODEGEN_LANGUAGES} constant, so a bc capability drift fails LOUDLY.
81
+ */
82
+ export declare function assertLanguageSupported(language: string, registered: readonly string[]): asserts language is CodegenLanguage;
83
+ /**
84
+ * Generate the mode-3 codegen artifact for ONE §8 bundle in ONE target language: bc's SHARED
85
+ * generator bakes the IR literal + emits `bind(handlers)`, and we attach the STATIC SQL catalog
86
+ * companion. litedbmodel supplies the input (IR + catalog); bc owns the emitter.
87
+ */
88
+ export declare function generateCodegenArtifact(bundle: SqlBundle, language: string, registeredLanguages: readonly string[], runtimeImport?: string): CodegenArtifact;
89
+ /**
90
+ * The TS codegen EXECUTION path used to PROVE byte-identity: a codegen runtime reads the SQL
91
+ * catalog companion (the STATIC makeSQL bundle) and evaluates skip + value-specs → assemble →
92
+ * render → execute — which is EXACTLY {@link executeBundle} over the SAME bundle.
93
+ */
94
+ export declare function codegenExecuteBundleForTest(artifact: CodegenArtifact, input: Scope, db: SqliteDb): Value;
95
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/scp/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAkB,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACzH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,wDAAyD,CAAC;AACxF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5G,wFAAwF;IACxF,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,mGAAmG;IACnG,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;CACxC;AAED,+DAA+D;AAC/D,MAAM,WAAW,eAAe;IAC9B,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,mGAAmG;IACnG,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IACxC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC;IAC9B,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAGtE;AAcD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,CAa5H;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,aAAa,CAAC,EAAE,MAAM,GACrB,eAAe,CAKjB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,GAAG,KAAK,CAExG"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — mode-3 codegen (WS7f, #35; spec §9 exec-mode 3 / §10 / §11; makeSQL flip,
4
+ * epic #43/#45 Phase B).
5
+ *
6
+ * The static-codegen execution mode ("Codegen・静的(全言語)— IR → 各言語ソース生成 runtime≈0,
7
+ * 入力は可搬IRのみ, bc#13 共有 generator に SQL catalog を供給" — spec §9). It takes a §8 STATIC
8
+ * makeSQL {@link SqlBundle} and, per target language, emits:
9
+ *
10
+ * 1. **Behavior module** — bc's SHARED generator (`generateModule`, bc#13) run over the bundle's
11
+ * portable IR (a read bundle's surrogate `ComponentGraphIR`, or the `makeSQL` component IR for
12
+ * a write), baked as a language-native LITERAL with a `bind(handlers)` accessor delegating to
13
+ * `runBehavior`. litedbmodel writes NO execution logic here — codegen is upstream-owned (bc).
14
+ * 2. **SQL catalog companion** — the pure-JSON STATIC makeSQL catalog (per-node statement
15
+ * templates / relations / transaction). A codegen consumer's thin SQL layer reads it to
16
+ * evaluate skip + value-specs → assemble → render → execute (identically to the mode-2 runtime).
17
+ *
18
+ * ## Byte-identical to the thin-runtime (mode-2), by construction
19
+ *
20
+ * The companion IS the bundle, so a codegen runtime that evaluates it drives the IDENTICAL
21
+ * static-makeSQL render/execute path {@link executeBundle} uses — SQL text (all dialects) and
22
+ * results are identical, not approximately equal. The TS leg PROVES this by executing via the
23
+ * artifact and asserting exact equality vs {@link executeBundle} (see {@link codegenExecuteBundleForTest}).
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.CODEGEN_LANGUAGES = void 0;
27
+ exports.bundleToPortableIR = bundleToPortableIR;
28
+ exports.assertLanguageSupported = assertLanguageSupported;
29
+ exports.generateCodegenArtifact = generateCodegenArtifact;
30
+ exports.codegenExecuteBundleForTest = codegenExecuteBundleForTest;
31
+ const behavior_contracts_1 = require("behavior-contracts");
32
+ const runtime_1 = require("./runtime");
33
+ const ir_1 = require("./makesql/ir");
34
+ /**
35
+ * The languages litedbmodel mode-3 codegen supports — exactly the set bc's shared generator
36
+ * registers (bc#13 SP1 typescript/python + SP2 go/rust/php). {@link assertLanguageSupported}
37
+ * verifies against the LIVE registry so a bc capability drift is caught loudly.
38
+ */
39
+ exports.CODEGEN_LANGUAGES = ['typescript', 'python', 'go', 'rust', 'php'];
40
+ /**
41
+ * The portable {@link ComponentGraphIR} view of a §8 bundle: a read bundle's surrogate IR (each
42
+ * SQL node → a `makeSQL` node), or the single `makeSQL` component IR for a write. Baking THIS is
43
+ * what makes the generated module a genuine bc artifact; the static SQL catalog rides the companion.
44
+ */
45
+ function bundleToPortableIR(bundle) {
46
+ if (bundle.readGraph !== undefined)
47
+ return bundle.readGraph.ir;
48
+ return (0, ir_1.makeSqlComponentIR)(bundle.name);
49
+ }
50
+ /** The STATIC makeSQL execution catalog carried alongside the (baked) portable IR. */
51
+ function companionOf(bundle) {
52
+ const base = {
53
+ dialect: bundle.dialect,
54
+ optionalHeads: bundle.optionalHeads,
55
+ relations: bundle.relations,
56
+ ...(bundle.readGraph !== undefined ? { readGraph: bundle.readGraph } : {}),
57
+ ...(bundle.statement !== undefined ? { statement: bundle.statement } : {}),
58
+ };
59
+ return bundle.transaction === undefined ? base : { ...base, transaction: bundle.transaction };
60
+ }
61
+ /**
62
+ * Assert the requested language is one bc's shared generator can emit — checked against the LIVE
63
+ * registry, not just the {@link CODEGEN_LANGUAGES} constant, so a bc capability drift fails LOUDLY.
64
+ */
65
+ function assertLanguageSupported(language, registered) {
66
+ if (!exports.CODEGEN_LANGUAGES.includes(language)) {
67
+ throw new Error(`litedbmodel codegen: language '${language}' is not a supported target (supported: ${exports.CODEGEN_LANGUAGES.join(', ')})`);
68
+ }
69
+ if (!registered.includes(language)) {
70
+ throw new Error(`litedbmodel codegen: bc's shared generator does not register an emitter for '${language}' ` +
71
+ `(bc registered: ${[...registered].sort().join(', ')}). This is a bc#13 capability limit — ESCALATE to bc (bc#22 pattern), ` +
72
+ `never fork a litedbmodel-local generator (codegen は上流所有, spec §9).`);
73
+ }
74
+ }
75
+ /**
76
+ * Generate the mode-3 codegen artifact for ONE §8 bundle in ONE target language: bc's SHARED
77
+ * generator bakes the IR literal + emits `bind(handlers)`, and we attach the STATIC SQL catalog
78
+ * companion. litedbmodel supplies the input (IR + catalog); bc owns the emitter.
79
+ */
80
+ function generateCodegenArtifact(bundle, language, registeredLanguages, runtimeImport) {
81
+ assertLanguageSupported(language, registeredLanguages);
82
+ const ir = bundleToPortableIR(bundle);
83
+ const module = (0, behavior_contracts_1.generateModule)(ir, runtimeImport === undefined ? { language } : { language, runtimeImport });
84
+ return { language, module, companion: companionOf(bundle), ir, bundle };
85
+ }
86
+ /**
87
+ * The TS codegen EXECUTION path used to PROVE byte-identity: a codegen runtime reads the SQL
88
+ * catalog companion (the STATIC makeSQL bundle) and evaluates skip + value-specs → assemble →
89
+ * render → execute — which is EXACTLY {@link executeBundle} over the SAME bundle.
90
+ */
91
+ function codegenExecuteBundleForTest(artifact, input, db) {
92
+ return (0, runtime_1.executeBundle)(artifact.bundle, input, { db });
93
+ }
94
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../src/scp/codegen.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;AAyDH,gDAGC;AAkBD,0DAaC;AAOD,0DAUC;AAOD,kEAEC;AAnHD,2DAAyH;AAEzH,uCAA0C;AAC1C,qCAAkD;AAMlD;;;;GAIG;AACU,QAAA,iBAAiB,GAAG,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAU,CAAC;AAoCxF;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,MAAiB;IAClD,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;IAC/D,OAAO,IAAA,uBAAkB,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,sFAAsF;AACtF,SAAS,WAAW,CAAC,MAAiB;IACpC,MAAM,IAAI,GAAwB;QAChC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC;IACF,OAAO,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;AAChG,CAAC;AAED;;;GAGG;AACH,SAAgB,uBAAuB,CAAC,QAAgB,EAAE,UAA6B;IACrF,IAAI,CAAE,yBAAuC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CACb,kCAAkC,QAAQ,2CAA2C,yBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACrH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,gFAAgF,QAAQ,IAAI;YAC1F,mBAAmB,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,wEAAwE;YAC5H,oEAAoE,CACvE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,uBAAuB,CACrC,MAAiB,EACjB,QAAgB,EAChB,mBAAsC,EACtC,aAAsB;IAEtB,uBAAuB,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAA,mCAAc,EAAC,EAAE,EAAE,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;IAC5G,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,SAAgB,2BAA2B,CAAC,QAAyB,EAAE,KAAY,EAAE,EAAY;IAC/F,OAAO,IAAA,uBAAa,EAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * litedbmodel v2 SCP — dialect strategy table (WS6, #26; spec §4/§5/§8/§10).
3
+ *
4
+ * The SINGLE SOURCE OF TRUTH for every SQL-dialect difference the Backend Compile + render
5
+ * pipeline needs. The dialect axis is compiled ONCE, TS-side (spec §10: "方言軸はコンパイル時
6
+ * に TS 側で1回検証"). This module encodes the differences as a closed strategy record — NO
7
+ * scattered `?:` in the engine code (the hard rule). A backend compile / renderer asks the
8
+ * {@link Dialect} for the dialect-specific text and never branches on the dialect name inline.
9
+ *
10
+ * ## What actually differs (verified against the v1 SqlBuilders — the golden bar)
11
+ *
12
+ * For the CRUD + write-tx + relation SQL the SCP Backend Compile emits (single-row VALUES,
13
+ * `?` placeholders, `col = ?` WHERE, `col IN (?, …)`), the dialect surface is small and
14
+ * closed:
15
+ *
16
+ * - **INSERT conflict clause**: SQLite `INSERT OR IGNORE … ` / `… ON CONFLICT (cols) DO
17
+ * UPDATE SET c = excluded.c`; Postgres `… ON CONFLICT (cols) DO NOTHING` / `… DO UPDATE
18
+ * SET c = EXCLUDED.c`; MySQL `INSERT IGNORE …` / `… ON DUPLICATE KEY UPDATE c = VALUES(c)`.
19
+ * These are byte-identical to `SqliteSqlBuilder` / `PostgresSqlBuilder` / `MysqlSqlBuilder`
20
+ * `buildInsert` for the single-record case (see the WS6 dialect-golden test).
21
+ * - **Bare `ON CONFLICT DO NOTHING`** (no column list — the gate-first idempotency/unique
22
+ * guard INSERTs of the write-tx plan, spec §6): SQLite/Postgres emit `ON CONFLICT DO
23
+ * NOTHING`; MySQL emits `INSERT IGNORE`.
24
+ * - **Placeholder style**: all dialects author with `?`; Postgres converts `?`→`$1,$2,…` in a
25
+ * final left-to-right one-pass AFTER the SQL text is fully assembled (spec §8 — the
26
+ * number-reassignment problem is designed out because the pass runs once over the final
27
+ * flat text). SQLite/MySQL keep `?`.
28
+ *
29
+ * Everything else (SELECT/UPDATE/DELETE skeletons, `col = ?`, `col IN (?, …)` expansion, the
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 live here.
32
+ *
33
+ * ## DB behavior differences beyond SQL text (spec §13) — closeable-by-convention line
34
+ *
35
+ * SQL-text identity does not guarantee identical DB behavior (NULL ordering, collation,
36
+ * timezone). Per spec §13, those are closed "by dialect-compile-time convention" only within
37
+ * the closeable line. WS6 encodes the ONE convention that is mechanically closeable in the
38
+ * compiled SQL text: deterministic NULL ordering for an `ORDER BY … NULLS` requirement
39
+ * ({@link Dialect.orderByNulls}). Collation / timezone / float semantics are OUT OF SCOPE
40
+ * (documented, not silently defaulted).
41
+ */
42
+ /** The SQL dialects the Backend Compile targets (spec §4 breadth: PG/MySQL/SQLite). */
43
+ export type DialectName = 'sqlite' | 'postgres' | 'mysql';
44
+ /** An INSERT conflict action (dialect-neutral intent; the dialect renders the clause). */
45
+ export type ConflictAction = 'ignore' | {
46
+ readonly updateColumns: readonly string[];
47
+ };
48
+ /**
49
+ * A dialect strategy: the closed set of dialect-specific renderings the Backend Compile +
50
+ * render pipeline consumes. One frozen record per dialect (the SSoT). Every method is a pure
51
+ * text producer — no side effects, no hidden fallback.
52
+ */
53
+ export interface Dialect {
54
+ readonly name: DialectName;
55
+ /**
56
+ * Render an INSERT's optional conflict clause, appended after `… VALUES (…)`.
57
+ *
58
+ * @param conflictColumns the conflict-target columns (`ON CONFLICT (a, b)`), or an empty
59
+ * array for a bare conflict target (the write-tx guard INSERTs — spec §6).
60
+ * @param action `'ignore'` (do-nothing) or an upsert with the update-column list.
61
+ * @param insertColumns the INSERT's column list (needed for the `VALUES(col)` / `EXCLUDED.col`
62
+ * SET-clause rendering when `updateColumns` is `'all'` at the call site — the caller passes
63
+ * the resolved list, so this only needs the resolved update columns).
64
+ */
65
+ insertConflictClause(conflictColumns: readonly string[], action: ConflictAction): string;
66
+ /**
67
+ * For MySQL, an `ignore` conflict is expressed on the INSERT VERB (`INSERT IGNORE INTO`),
68
+ * not as a trailing clause; SQLite uses `INSERT OR IGNORE INTO`; Postgres uses a plain
69
+ * `INSERT INTO` + a trailing `ON CONFLICT … DO NOTHING`. This returns the INSERT verb+prefix
70
+ * up to and including `INTO` for the `ignore` case, and the plain `INSERT INTO` otherwise.
71
+ */
72
+ insertVerb(action: ConflictAction | undefined): string;
73
+ /**
74
+ * Whether this dialect's conflict `ignore` is a trailing clause (Postgres) rather than an
75
+ * INSERT-verb modifier (SQLite `OR IGNORE`, MySQL `IGNORE`). Drives whether
76
+ * {@link insertConflictClause} emits text for the `ignore` case.
77
+ */
78
+ readonly ignoreIsTrailingClause: boolean;
79
+ /**
80
+ * Render a bare do-nothing GUARD INSERT — the gate-first idempotency/unique guard of the
81
+ * write-tx plan (spec §6): `INSERT INTO <t> (<cols>) VALUES (<ph>)` + a do-nothing conflict
82
+ * on ANY unique constraint (no column target). SQLite/Postgres emit a trailing
83
+ * `… ON CONFLICT DO NOTHING`; MySQL emits `INSERT IGNORE INTO … VALUES (…)`.
84
+ *
85
+ * This is DISTINCT from the CRUD `ignore` path ({@link insertVerb} + {@link insertConflictClause}),
86
+ * which mirrors the v1 SqlBuilders (SQLite uses the `INSERT OR IGNORE` verb there). The guard
87
+ * form is SCP-internal and its SQLite golden is the trailing `ON CONFLICT DO NOTHING` (WS5),
88
+ * so the two contexts render differently ON SQLITE and are kept as separate strategy methods
89
+ * rather than one branch.
90
+ *
91
+ * @param table the guard table.
92
+ * @param columns the guard row's columns (in order).
93
+ * @param placeholders the pre-joined placeholder list (`"?, ?, ?"`).
94
+ */
95
+ guardInsert(table: string, columns: readonly string[], placeholders: string): string;
96
+ /**
97
+ * Convert the fully-assembled, param-flattened SQL text's `?` placeholders to this dialect's
98
+ * final placeholder style. SQLite/MySQL: identity (keep `?`). Postgres: a single left-to-right
99
+ * pass replacing the Nth `?` with `$N` (spec §8 final one-pass). This runs ONCE over the final
100
+ * text, so there is no number-reassignment problem.
101
+ */
102
+ finalizePlaceholders(sql: string): string;
103
+ /**
104
+ * Deterministic NULL ordering for an `ORDER BY <expr> <dir>` term when the model requires it
105
+ * (spec §13 "`ORDER BY … NULLS` 強制"). Postgres supports `NULLS FIRST/LAST` natively; SQLite
106
+ * (3.30+) also supports it; MySQL does NOT, so the convention is emulated with a leading
107
+ * `<expr> IS NULL` sort key. Returns the full ORDER BY term text.
108
+ */
109
+ orderByNulls(expr: string, dir: 'ASC' | 'DESC', nulls: 'FIRST' | 'LAST'): string;
110
+ }
111
+ /**
112
+ * Replace each `?` placeholder in a fully-assembled SQL string with `$1, $2, …` left-to-right
113
+ * (Postgres). This is the spec §8 "最終1パス" conversion: it runs ONCE over the final flat SQL
114
+ * text, so placeholder numbering is a plain running counter — the number-reassignment problem
115
+ * cannot reappear (there is no per-fragment renumbering). Every `?` is a bound param position
116
+ * (the render pipeline never emits a literal `?` inside a string literal — values are always
117
+ * parameterized), so a naive scan is correct for the compiled surface.
118
+ */
119
+ export declare function toDollarPlaceholders(sql: string): string;
120
+ /**
121
+ * SQLite. `ignore` is an INSERT-verb modifier (`INSERT OR IGNORE INTO`); upsert uses
122
+ * `ON CONFLICT (cols) DO UPDATE SET c = excluded.c`. Placeholders stay `?`. NULL ordering uses
123
+ * the native `NULLS FIRST/LAST` (SQLite 3.30+).
124
+ */
125
+ export declare const SQLITE: Dialect;
126
+ /**
127
+ * Postgres. `ignore` is a TRAILING clause (`… ON CONFLICT (cols) DO NOTHING`); upsert uses
128
+ * `ON CONFLICT (cols) DO UPDATE SET c = EXCLUDED.c`. Placeholders are converted `?`→`$N` in the
129
+ * final one-pass. NULL ordering uses native `NULLS FIRST/LAST`.
130
+ */
131
+ export declare const POSTGRES: Dialect;
132
+ /**
133
+ * MySQL. `ignore` is an INSERT-verb modifier (`INSERT IGNORE INTO`); upsert uses
134
+ * `… ON DUPLICATE KEY UPDATE c = VALUES(c)` (no conflict-column target — MySQL keys off any
135
+ * unique index). Placeholders stay `?`. NULL ordering is emulated with a leading
136
+ * `<expr> IS NULL` sort key (MySQL has no `NULLS FIRST/LAST`).
137
+ */
138
+ export declare const MYSQL: Dialect;
139
+ /** Look up a dialect strategy by name (throws on an unknown dialect — no silent default). */
140
+ export declare function dialectFor(name: DialectName): Dialect;
141
+ //# sourceMappingURL=dialect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../../src/scp/dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;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"}