litedbmodel 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +7 -0
  2. package/dist/DBConditions.d.ts.map +1 -1
  3. package/dist/DBConditions.js +16 -1
  4. package/dist/DBConditions.js.map +1 -1
  5. package/dist/DBHandler.d.ts.map +1 -1
  6. package/dist/DBHandler.js +6 -0
  7. package/dist/DBHandler.js.map +1 -1
  8. package/dist/DBModel.d.ts +84 -2
  9. package/dist/DBModel.d.ts.map +1 -1
  10. package/dist/DBModel.js +312 -29
  11. package/dist/DBModel.js.map +1 -1
  12. package/dist/decorators.d.ts +52 -0
  13. package/dist/decorators.d.ts.map +1 -1
  14. package/dist/decorators.js +83 -0
  15. package/dist/decorators.js.map +1 -1
  16. package/dist/drivers/mysql.d.ts.map +1 -1
  17. package/dist/drivers/mysql.js +6 -2
  18. package/dist/drivers/mysql.js.map +1 -1
  19. package/dist/drivers/postgres.d.ts.map +1 -1
  20. package/dist/drivers/postgres.js +6 -2
  21. package/dist/drivers/postgres.js.map +1 -1
  22. package/dist/drivers/sqlite.d.ts.map +1 -1
  23. package/dist/drivers/sqlite.js +12 -2
  24. package/dist/drivers/sqlite.js.map +1 -1
  25. package/dist/index.cjs +10741 -0
  26. package/dist/index.d.cts +1 -0
  27. package/dist/scp/coltype.d.ts +26 -1
  28. package/dist/scp/coltype.d.ts.map +1 -1
  29. package/dist/scp/coltype.js +82 -15
  30. package/dist/scp/coltype.js.map +1 -1
  31. package/dist/scp/connection-routing.d.ts +312 -0
  32. package/dist/scp/connection-routing.d.ts.map +1 -0
  33. package/dist/scp/connection-routing.js +394 -0
  34. package/dist/scp/connection-routing.js.map +1 -0
  35. package/dist/scp/dbmodel-runtime.d.ts +101 -0
  36. package/dist/scp/dbmodel-runtime.d.ts.map +1 -0
  37. package/dist/scp/dbmodel-runtime.js +174 -0
  38. package/dist/scp/dbmodel-runtime.js.map +1 -0
  39. package/dist/scp/decorator-adapter.d.ts +196 -0
  40. package/dist/scp/decorator-adapter.d.ts.map +1 -0
  41. package/dist/scp/decorator-adapter.js +286 -0
  42. package/dist/scp/decorator-adapter.js.map +1 -0
  43. package/dist/scp/emit/emitter.d.ts +108 -0
  44. package/dist/scp/emit/emitter.d.ts.map +1 -0
  45. package/dist/scp/emit/emitter.js +782 -0
  46. package/dist/scp/emit/emitter.js.map +1 -0
  47. package/dist/scp/emit/endpoint.d.ts +248 -0
  48. package/dist/scp/emit/endpoint.d.ts.map +1 -0
  49. package/dist/scp/emit/endpoint.js +20 -0
  50. package/dist/scp/emit/endpoint.js.map +1 -0
  51. package/dist/scp/emit/index.d.ts +11 -0
  52. package/dist/scp/emit/index.d.ts.map +1 -0
  53. package/dist/scp/emit/index.js +13 -0
  54. package/dist/scp/emit/index.js.map +1 -0
  55. package/dist/scp/errors.d.ts +45 -1
  56. package/dist/scp/errors.d.ts.map +1 -1
  57. package/dist/scp/errors.js +47 -1
  58. package/dist/scp/errors.js.map +1 -1
  59. package/dist/scp/exec-context.d.ts +390 -0
  60. package/dist/scp/exec-context.d.ts.map +1 -0
  61. package/dist/scp/exec-context.js +540 -0
  62. package/dist/scp/exec-context.js.map +1 -0
  63. package/dist/scp/grouping.d.ts +32 -0
  64. package/dist/scp/grouping.d.ts.map +1 -0
  65. package/dist/scp/grouping.js +0 -0
  66. package/dist/scp/grouping.js.map +1 -0
  67. package/dist/scp/index.cjs +6814 -15731
  68. package/dist/scp/index.d.cts +1 -0
  69. package/dist/scp/index.d.mts +1 -0
  70. package/dist/scp/index.d.ts +47 -49
  71. package/dist/scp/index.d.ts.map +1 -1
  72. package/dist/scp/index.js +174 -152
  73. package/dist/scp/index.js.map +1 -1
  74. package/dist/scp/index.mjs +5561 -3704
  75. package/dist/scp/leaf-transport.d.ts +50 -0
  76. package/dist/scp/leaf-transport.d.ts.map +1 -0
  77. package/dist/scp/leaf-transport.js +92 -0
  78. package/dist/scp/leaf-transport.js.map +1 -0
  79. package/dist/scp/leaves.d.ts +174 -0
  80. package/dist/scp/leaves.d.ts.map +1 -0
  81. package/dist/scp/leaves.js +287 -0
  82. package/dist/scp/leaves.js.map +1 -0
  83. package/dist/scp/limit-config.d.ts +118 -0
  84. package/dist/scp/limit-config.d.ts.map +1 -0
  85. package/dist/scp/limit-config.js +126 -0
  86. package/dist/scp/limit-config.js.map +1 -0
  87. package/dist/scp/makesql/compile-relation.d.ts +49 -23
  88. package/dist/scp/makesql/compile-relation.d.ts.map +1 -1
  89. package/dist/scp/makesql/compile-relation.js +101 -76
  90. package/dist/scp/makesql/compile-relation.js.map +1 -1
  91. package/dist/scp/makesql/compile-select.d.ts +45 -10
  92. package/dist/scp/makesql/compile-select.d.ts.map +1 -1
  93. package/dist/scp/makesql/compile-select.js +50 -10
  94. package/dist/scp/makesql/compile-select.js.map +1 -1
  95. package/dist/scp/makesql/handler.d.ts +1 -1
  96. package/dist/scp/makesql/handler.d.ts.map +1 -1
  97. package/dist/scp/makesql/index.d.ts +7 -9
  98. package/dist/scp/makesql/index.d.ts.map +1 -1
  99. package/dist/scp/makesql/index.js +17 -28
  100. package/dist/scp/makesql/index.js.map +1 -1
  101. package/dist/scp/makesql/json-array.d.ts +65 -0
  102. package/dist/scp/makesql/json-array.d.ts.map +1 -1
  103. package/dist/scp/makesql/json-array.js +99 -10
  104. package/dist/scp/makesql/json-array.js.map +1 -1
  105. package/dist/scp/makesql/json-batch.d.ts.map +1 -1
  106. package/dist/scp/makesql/json-batch.js +15 -18
  107. package/dist/scp/makesql/json-batch.js.map +1 -1
  108. package/dist/scp/makesql/makesql.d.ts +1 -1
  109. package/dist/scp/makesql/makesql.d.ts.map +1 -1
  110. package/dist/scp/makesql/mysql-returning.d.ts +93 -0
  111. package/dist/scp/makesql/mysql-returning.d.ts.map +1 -0
  112. package/dist/scp/makesql/mysql-returning.js +215 -0
  113. package/dist/scp/makesql/mysql-returning.js.map +1 -0
  114. package/dist/scp/makesql/outtype.d.ts +40 -54
  115. package/dist/scp/makesql/outtype.d.ts.map +1 -1
  116. package/dist/scp/makesql/outtype.js +46 -204
  117. package/dist/scp/makesql/outtype.js.map +1 -1
  118. package/dist/scp/makesql/pool-executor.d.ts +86 -34
  119. package/dist/scp/makesql/pool-executor.d.ts.map +1 -1
  120. package/dist/scp/makesql/pool-executor.js +179 -39
  121. package/dist/scp/makesql/pool-executor.js.map +1 -1
  122. package/dist/scp/makesql/tx.d.ts +107 -22
  123. package/dist/scp/makesql/tx.d.ts.map +1 -1
  124. package/dist/scp/makesql/tx.js +451 -97
  125. package/dist/scp/makesql/tx.js.map +1 -1
  126. package/dist/scp/makesql/writeouttype.d.ts +4 -4
  127. package/dist/scp/makesql/writeouttype.d.ts.map +1 -1
  128. package/dist/scp/makesql/writeouttype.js +5 -3
  129. package/dist/scp/makesql/writeouttype.js.map +1 -1
  130. package/dist/scp/middleware.d.ts +287 -0
  131. package/dist/scp/middleware.d.ts.map +1 -0
  132. package/dist/scp/middleware.js +358 -0
  133. package/dist/scp/middleware.js.map +1 -0
  134. package/dist/scp/relation.d.ts +65 -8
  135. package/dist/scp/relation.d.ts.map +1 -1
  136. package/dist/scp/relation.js +154 -93
  137. package/dist/scp/relation.js.map +1 -1
  138. package/dist/scp/tx-options.d.ts +136 -0
  139. package/dist/scp/tx-options.d.ts.map +1 -0
  140. package/dist/scp/tx-options.js +184 -0
  141. package/dist/scp/tx-options.js.map +1 -0
  142. package/dist/scp/write-bundle.d.ts +131 -0
  143. package/dist/scp/write-bundle.d.ts.map +1 -0
  144. package/dist/scp/write-bundle.js +160 -0
  145. package/dist/scp/write-bundle.js.map +1 -0
  146. package/dist/types.d.ts +7 -0
  147. package/dist/types.d.ts.map +1 -1
  148. package/dist/types.js.map +1 -1
  149. package/docs/design/phase-a-execution-context.md +139 -0
  150. package/package.json +14 -13
  151. package/dist/scp/authoring-sql.d.ts +0 -134
  152. package/dist/scp/authoring-sql.d.ts.map +0 -1
  153. package/dist/scp/authoring-sql.js +0 -191
  154. package/dist/scp/authoring-sql.js.map +0 -1
  155. package/dist/scp/authoring.d.ts +0 -218
  156. package/dist/scp/authoring.d.ts.map +0 -1
  157. package/dist/scp/authoring.js +0 -351
  158. package/dist/scp/authoring.js.map +0 -1
  159. package/dist/scp/catalog.d.ts +0 -95
  160. package/dist/scp/catalog.d.ts.map +0 -1
  161. package/dist/scp/catalog.js +0 -245
  162. package/dist/scp/catalog.js.map +0 -1
  163. package/dist/scp/codegen.d.ts +0 -201
  164. package/dist/scp/codegen.d.ts.map +0 -1
  165. package/dist/scp/codegen.js +0 -605
  166. package/dist/scp/codegen.js.map +0 -1
  167. package/dist/scp/find-filter-guard.d.ts +0 -68
  168. package/dist/scp/find-filter-guard.d.ts.map +0 -1
  169. package/dist/scp/find-filter-guard.js +0 -88
  170. package/dist/scp/find-filter-guard.js.map +0 -1
  171. package/dist/scp/guard.d.ts +0 -43
  172. package/dist/scp/guard.d.ts.map +0 -1
  173. package/dist/scp/guard.js +0 -140
  174. package/dist/scp/guard.js.map +0 -1
  175. package/dist/scp/makesql/authoring-compile.d.ts +0 -90
  176. package/dist/scp/makesql/authoring-compile.d.ts.map +0 -1
  177. package/dist/scp/makesql/authoring-compile.js +0 -505
  178. package/dist/scp/makesql/authoring-compile.js.map +0 -1
  179. package/dist/scp/makesql/static-bundle.d.ts +0 -196
  180. package/dist/scp/makesql/static-bundle.d.ts.map +0 -1
  181. package/dist/scp/makesql/static-bundle.js +0 -1244
  182. package/dist/scp/makesql/static-bundle.js.map +0 -1
  183. package/dist/scp/runtime.d.ts +0 -243
  184. package/dist/scp/runtime.d.ts.map +0 -1
  185. package/dist/scp/runtime.js +0 -422
  186. package/dist/scp/runtime.js.map +0 -1
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — the decorator METADATA adapter (Phase F-1, epic #74, issue #104).
4
+ *
5
+ * litedbmodel's decorators are metadata-only COLLECTORS: `@column` / `@hasMany` / … record
6
+ * `ColumnMeta` / `RelationMeta` / `TABLE_NAME` on the class (`src/decorators.ts`, via `reflect-metadata`
7
+ * + `_columnMeta` / `_relationMeta`). This module READS that registry and translates it into the SCP-level
8
+ * facts the rest of the stack consumes, plus the write bundles a decorated model compiles to. It builds
9
+ * NO SQL structure of its own and holds NO authoring vocabulary — the decorator never emits IR, and the
10
+ * adapter never re-implements composition.
11
+ *
12
+ * ## What the adapter translates
13
+ *
14
+ * 1. **Columns** (the one real translation): `@column.*` `ColumnMeta` (the decorator already knows the
15
+ * type family — bigint / date / boolean / uuid / json / array / …) → the SCP column SoT
16
+ * ({@link ModelColumns}: the SQL-type token per column, validated by `coltype.ts`). See
17
+ * {@link deriveModelColumns} + {@link COLUMN_FAMILY_SQL_TYPE}. The typed-read `outType` and the
18
+ * relation key-array element type both resolve against exactly this SoT.
19
+ * 2. **Relations**: `@hasMany` / `@belongsTo` / `@hasOne` `RelationMeta` → {@link RelationDecl} →
20
+ * `compileRelationOp` (single + composite keys, per-parent `limit` window + `hardLimit`).
21
+ * 3. **Write bundles**: `createMany` (and a `create` WITH `onConflict`) / `updateMany` / `deleteMany` →
22
+ * `compileCreateManyBundle` / `compileUpdateManyBundle` / `compileDeleteManyBundle`, with the
23
+ * model's column SoT threaded as the write de-box resolver.
24
+ *
25
+ * READS are NOT compiled here. A read endpoint is DECLARED on the `@behavior` / `@leaf` authoring
26
+ * surface and lowered by `bc generate`; an ad-hoc runtime-shaped query runs the v1 imperative path.
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.DEFAULT_UNCAST_SQL_TYPE = exports.COLUMN_FAMILY_SQL_TYPE = void 0;
30
+ exports.columnSqlType = columnSqlType;
31
+ exports.deriveModelColumns = deriveModelColumns;
32
+ exports.tableNameOf = tableNameOf;
33
+ exports.compileCreateBundle = compileCreateBundle;
34
+ exports.compileUpdateBundle = compileUpdateBundle;
35
+ exports.compileDeleteBundle = compileDeleteBundle;
36
+ exports.relationKeyTypeResolver = relationKeyTypeResolver;
37
+ exports.modelColumnResolver = modelColumnResolver;
38
+ exports.deriveRelationDecls = deriveRelationDecls;
39
+ exports.relationDeclOf = relationDeclOf;
40
+ exports.compileRelationOps = compileRelationOps;
41
+ const write_bundle_1 = require("./write-bundle");
42
+ const relation_1 = require("./relation");
43
+ const coltype_1 = require("./coltype");
44
+ const decorators_1 = require("../decorators");
45
+ const Column_1 = require("../Column");
46
+ // ── 1. Column-type mapping (decorator ColumnMeta → the SCP column SQL type) ─────────────────────
47
+ /**
48
+ * The decorator's `ColumnMeta.sqlCast` type-family token → the canonical §4.1 SQL-type token the SCP
49
+ * `static columns` SoT carries (validated by `coltype.ts`). The decorator ALREADY knows the family
50
+ * (it set `sqlCast` from the `@column.*` variant / the `design:type` inference — `src/decorators.ts`),
51
+ * so this is a pure token normalization, no inference. `coltype.ts` accepts every RHS here:
52
+ * BOOLEAN/BIGINT/TIMESTAMP/DATE/UUID/JSONB are scalar; the array tokens de-box as `passthrough`
53
+ * (`sqlTypeToMaterializeClass`).
54
+ *
55
+ * The RHS matches the decorator families 1:1:
56
+ * - `boolean` → `BOOLEAN` (`@column.boolean()` / auto `Boolean`)
57
+ * - `bigint` → `BIGINT` (`@column.bigint()` / auto `BigInt` — read de-box: exact string)
58
+ * - `timestamp` → `TIMESTAMP` (`@column.datetime()` / auto `Date` — read de-box: TZ string)
59
+ * - `date` → `DATE` (`@column.date()` — read de-box: YYYY-MM-DD string)
60
+ * - `uuid` → `UUID` (`@column.uuid()`)
61
+ * - `jsonb` → `JSONB` (`@column.json()`)
62
+ * - `text[]` / `int[]` / `numeric[]` / `boolean[]` → the array token (`@column.*Array()`)
63
+ */
64
+ exports.COLUMN_FAMILY_SQL_TYPE = {
65
+ boolean: 'BOOLEAN',
66
+ bigint: 'BIGINT',
67
+ timestamp: 'TIMESTAMP',
68
+ date: 'DATE',
69
+ uuid: 'UUID',
70
+ jsonb: 'JSONB',
71
+ 'text[]': 'TEXT[]',
72
+ 'int[]': 'INT[]',
73
+ 'numeric[]': 'NUMERIC[]',
74
+ 'boolean[]': 'BOOLEAN[]',
75
+ };
76
+ /**
77
+ * The LAST-RESORT SQL type for a column that carries NO `sqlCast` family, NO `baseSqlType` (its
78
+ * `design:type` is absent — no `emitDecoratorMetadata` — or is an Array/Object family), and NO
79
+ * `columnTypes` override. Phase F-2 (#105 option B) made {@link columnSqlType} consult the decorator's
80
+ * `baseSqlType` (derived from the field's TS `design:type`: String→TEXT / Number→INTEGER / Boolean→
81
+ * BOOLEAN / Date→TIMESTAMP / BigInt→BIGINT) BEFORE this default, so a bare `@column() name: string`
82
+ * types as `TEXT` (not `INTEGER`) — the fix for F1's blanket-INTEGER read-de-box defect (it threw
83
+ * `materialize int32` on a live string column). This default now only applies when `design:type` is
84
+ * genuinely unavailable; a REAL/DECIMAL column (a `Number` that is not INT) is pinned via
85
+ * {@link DeriveColumnsOptions.columnTypes} (the escape hatch, unchanged from F1).
86
+ */
87
+ exports.DEFAULT_UNCAST_SQL_TYPE = 'INTEGER';
88
+ /**
89
+ * Translate ONE column's {@link ColumnMeta} to its §4.1 SQL-type token. Precedence (Phase F-2 / #105
90
+ * option B):
91
+ * 1. an explicit `columnTypes` override (the REAL/DECIMAL/width escape hatch) wins;
92
+ * 2. else the family token from {@link COLUMN_FAMILY_SQL_TYPE} (an explicit `@column.*` `sqlCast`);
93
+ * 3. else the decorator's `baseSqlType` — derived from the field's TS `design:type` (String→TEXT /
94
+ * Number→INTEGER / Boolean→BOOLEAN / Date→TIMESTAMP / BigInt→BIGINT), so a bare `@column()` types
95
+ * correctly for the SCP typed-read de-box (the fix for F1's blanket-INTEGER default);
96
+ * 4. else {@link DEFAULT_UNCAST_SQL_TYPE} (only when `design:type` is unavailable).
97
+ * Fail-closed: a family token the mapping does not know, or a produced token `coltype.ts` rejects,
98
+ * THROWS (naming the column) — never a silent skip (no-assume, no-fallback).
99
+ */
100
+ function columnSqlType(propKey, meta, override) {
101
+ const sqlType = override ??
102
+ (meta.sqlCast !== undefined ? exports.COLUMN_FAMILY_SQL_TYPE[meta.sqlCast] : undefined) ??
103
+ meta.baseSqlType ??
104
+ exports.DEFAULT_UNCAST_SQL_TYPE;
105
+ if (meta.sqlCast !== undefined && override === undefined && exports.COLUMN_FAMILY_SQL_TYPE[meta.sqlCast] === undefined) {
106
+ throw new Error(`decorator-adapter: column '${propKey}' has decorator sqlCast family '${meta.sqlCast}' with no ` +
107
+ `SCP SQL-type mapping. Add it to COLUMN_FAMILY_SQL_TYPE or pin the column via ` +
108
+ `options.columnTypes['${propKey}']. No-assume, no-fallback.`);
109
+ }
110
+ // Validate the produced token is in the §4.1 vocabulary (throws for an unknown/ambiguous type).
111
+ (0, coltype_1.sqlTypeToMaterializeClass)(sqlType);
112
+ return sqlType;
113
+ }
114
+ /**
115
+ * Derive the SCP `static columns` ({@link ModelColumns}) for a decorated model class from its
116
+ * `@column` `ColumnMeta` registry (the decorator IS the type SoT for v1/v2's decorator surface). The
117
+ * table is the model's `TABLE_NAME` (or the model-name lowercased, matching the decorator's
118
+ * `effectiveTableName`). Each column keys by its DB `columnName` (what a SELECT projects), mapping to
119
+ * its §4.1 SQL type. A model with no `@column` declarations yields no table entry.
120
+ *
121
+ * This is the ONE real translation in the adapter — the read-path de-box (INT→number / BIGINT→string /
122
+ * DATE→string / BOOLEAN→boolean) and the codegen `outType` both consult exactly this SoT.
123
+ */
124
+ function deriveModelColumns(modelClass, options = {}) {
125
+ const meta = (0, decorators_1.getColumnMeta)(modelClass);
126
+ if (meta === undefined || meta.size === 0)
127
+ return {};
128
+ const table = tableNameOf(modelClass);
129
+ const cols = {};
130
+ for (const [propKey, m] of meta) {
131
+ cols[m.columnName] = columnSqlType(propKey, m, options.columnTypes?.[propKey]);
132
+ }
133
+ return { [table]: cols };
134
+ }
135
+ /** The effective table name (v1 `@model` rule): explicit `TABLE_NAME`, else the model name lowercased. */
136
+ function tableNameOf(modelClass) {
137
+ return modelClass.TABLE_NAME ?? modelClass.name.toLowerCase();
138
+ }
139
+ // ── 2. Write bundles (createMany / updateMany / deleteMany) ─────────────────────────────────────
140
+ /**
141
+ * Compile a decorated model's `createMany` — and a `create` WITH `onConflict` (upsert) — into a batch
142
+ * write {@link SqlBundle} via `compileCreateManyBundle`. This is the UPSERT carry: `onConflict` /
143
+ * `onConflictUpdate` / `onConflictIgnore` are `compileInsertMany` BUILD options (not authored ports),
144
+ * so they carry end-to-end here with NO SCP authoring addition — exactly as v1's `create` and
145
+ * `createMany` share the ONE `DBModel._insert` grouping path (`buildInsert` handles ON CONFLICT for
146
+ * both a single record and a batch). A single-record `records` array is a one-group createMany that
147
+ * emits the SAME statement `_insert` does for a single upsert.
148
+ *
149
+ * Parity scope (the v1/v2 SQL-parity rule, per dialect — NOT a blanket "byte-identical to v1"): on
150
+ * **Postgres** the emitted upsert INSERT is byte-identical to v1 (`compileInsertMany` copies the v1
151
+ * `buildInsert` verbatim; PG stays base-class tuple/placeholder form). On **MySQL / SQLite** the v2
152
+ * form is the JSON-array single-param shape (`json_each` / `JSON_TABLE`), which is DELIBERATELY NOT
153
+ * byte-identical to v1's per-row placeholder expansion — it is the established v2 shape the conformance
154
+ * corpus freezes (#64/#65), executing to the same rows. So: pg = v1-byte-identical; mysql/sqlite = the
155
+ * v2 JSON-array form (equivalent result, distinct text).
156
+ *
157
+ * @param options the `compileCreateManyBundle` options (records / rawRecords / sqlCastMap / onConflict /
158
+ * onConflictUpdate / onConflictIgnore / returning / pk) — already serialized as `DBModel._insert`
159
+ * holds them.
160
+ */
161
+ function compileCreateBundle(modelClass, name, options, dialect = 'sqlite', columnsOptions) {
162
+ const resolveColumnType = modelColumnResolver(modelClass, columnsOptions);
163
+ return (0, write_bundle_1.compileCreateManyBundle)(name, options, dialect, resolveColumnType);
164
+ }
165
+ /** Compile a decorated model's `updateMany` into a batch write {@link SqlBundle} (`compileUpdateManyBundle`). */
166
+ function compileUpdateBundle(name, options, dialect = 'sqlite') {
167
+ return (0, write_bundle_1.compileUpdateManyBundle)(name, options, dialect);
168
+ }
169
+ /**
170
+ * Compile a decorated model's `deleteMany` into a batch write {@link SqlBundle} (`compileDeleteManyBundle`):
171
+ * a PK-set IN-list DELETE (single key) or one DELETE per composite-key group. `keyColumns` +
172
+ * `returning` carry straight through.
173
+ */
174
+ function compileDeleteBundle(name, options, dialect = 'sqlite') {
175
+ return (0, write_bundle_1.compileDeleteManyBundle)(name, options, dialect);
176
+ }
177
+ /**
178
+ * Build a {@link KeyTypeResolver} from a decorated model's `static columns` SoT — `(table, column) →`
179
+ * the de-box bc scalar of that key column ({@link import('./coltype').keyArrayElemScalar}). Threaded into
180
+ * {@link relationReadAuthoring} so each relation's `pluck` key array is stamped with the type its
181
+ * READ-materialized key value carries. Returns `undefined` when the model declares no columns.
182
+ */
183
+ function relationKeyTypeResolver(modelClass, columnsOptions) {
184
+ const columns = deriveModelColumns(modelClass, columnsOptions);
185
+ if (Object.keys(columns).length === 0)
186
+ return undefined;
187
+ return (table, column) => {
188
+ const sqlType = columns[table]?.[column];
189
+ if (sqlType === undefined) {
190
+ throw new Error(`decorator-adapter: relation key column '${table}.${column}' has no declared type in the model's ` +
191
+ `static columns — cannot stamp the key array's de-box element type (no-assume, no-fallback).`);
192
+ }
193
+ return (0, coltype_1.keyArrayElemScalar)(sqlType);
194
+ };
195
+ }
196
+ /** The fail-closed column-type resolver for a decorated model (its `static columns` SoT), or `undefined` if it has no columns. */
197
+ function modelColumnResolver(modelClass, columnsOptions) {
198
+ const columns = deriveModelColumns(modelClass, columnsOptions);
199
+ const tables = Object.keys(columns);
200
+ if (tables.length === 0)
201
+ return undefined;
202
+ const map = new Map();
203
+ for (const [t, cols] of Object.entries(columns))
204
+ map.set(t, new Map(Object.entries(cols)));
205
+ return (0, coltype_1.columnTypeResolverFromColumnMap)(map);
206
+ }
207
+ // ── 4. Relation authoring generation (@hasMany / @belongsTo / @hasOne → RelationDecl → RelationOp) ──
208
+ /**
209
+ * Translate a decorated model's `@hasMany` / `@belongsTo` / `@hasOne` {@link RelationMeta} registry
210
+ * into SCP {@link RelationDecl}s. Single AND composite keys are supported: the decorator's
211
+ * `keysFactory` resolves lazily (forward refs) to `[srcCol, tgtCol]` (single) or `[[…],[…]]`
212
+ * (composite); the target table + projection come from the target model's `@column` metadata (the
213
+ * relation projects the child's OWN columns). Per-parent `order` / `limit` (hasMany window) and
214
+ * `hardLimit` carry from the decorator `options`.
215
+ *
216
+ * @param modelClass the parent (source) `@model` class.
217
+ * @param resolveTargetModel model NAME → the target `@model` class (the decorator records the target
218
+ * model NAME on the key column; the caller supplies the registry — same lazy-resolution shape v1's
219
+ * `_loadRelation` uses).
220
+ */
221
+ function deriveRelationDecls(modelClass, resolveTargetModel, dialect = 'sqlite') {
222
+ return (0, decorators_1.getRelationMeta)(modelClass).map((rel) => relationDeclOf(rel, resolveTargetModel, dialect).decl);
223
+ }
224
+ /**
225
+ * Translate ONE {@link RelationMeta} → a {@link RelationDecl} (single or composite key) AND the
226
+ * resolved target model (so a caller can bake the child's de-box materializers from the TARGET
227
+ * model's `static columns` — the relation projects the child's own columns).
228
+ */
229
+ function relationDeclOf(rel, resolveTargetModel, dialect = 'sqlite') {
230
+ const parsed = parseKeys(rel.keysFactory());
231
+ const targetModel = resolveTargetModel(parsed.targetModelName);
232
+ const targetTable = tableNameOf(targetModel);
233
+ const select = targetProjection(targetModel);
234
+ const order = rel.options?.order ? (0, Column_1.orderToString)(rel.options.order()) : undefined;
235
+ const base = {
236
+ name: rel.propertyKey,
237
+ kind: rel.type,
238
+ targetTable,
239
+ select,
240
+ dialect,
241
+ ...(order !== undefined ? { order } : {}),
242
+ ...(rel.options?.limit !== undefined ? { limit: rel.options.limit } : {}),
243
+ ...(rel.options?.hardLimit !== undefined ? { hardLimit: rel.options.hardLimit } : {}),
244
+ };
245
+ const decl = parsed.composite
246
+ ? { ...base, parentKeys: parsed.sourceKeys, targetKeys: parsed.targetKeys }
247
+ : { ...base, parentKey: parsed.sourceKeys[0], targetKey: parsed.targetKeys[0] };
248
+ return { decl, targetModel };
249
+ }
250
+ /**
251
+ * Compile a decorated model's relation registry into ready {@link RelationOp}s (one per relation). Each
252
+ * op's child-column de-box materializers are baked from the TARGET model's `static columns` (the same
253
+ * resolution the primary read uses) — ZERO per-read introspection.
254
+ */
255
+ function compileRelationOps(modelClass, resolveTargetModel, dialect = 'sqlite', columnsOptions) {
256
+ const ops = {};
257
+ for (const rel of (0, decorators_1.getRelationMeta)(modelClass)) {
258
+ const { decl, targetModel } = relationDeclOf(rel, resolveTargetModel, dialect);
259
+ ops[decl.name] = (0, relation_1.compileRelationOp)(decl, modelColumnResolver(targetModel, columnsOptions));
260
+ }
261
+ return ops;
262
+ }
263
+ /** Parse the decorator `keysFactory()` result (single pair or composite) into src/target column lists. */
264
+ function parseKeys(keys) {
265
+ const arr = keys;
266
+ const composite = Array.isArray(arr[0]);
267
+ if (composite) {
268
+ const pairs = arr;
269
+ return {
270
+ composite: true,
271
+ sourceKeys: pairs.map((p) => p[0].columnName),
272
+ targetKeys: pairs.map((p) => p[1].columnName),
273
+ targetModelName: pairs[0][1].modelName,
274
+ };
275
+ }
276
+ const [src, tgt] = arr;
277
+ return { composite: false, sourceKeys: [src.columnName], targetKeys: [tgt.columnName], targetModelName: tgt.modelName };
278
+ }
279
+ /** The target model's projected columns (its own `@column` DB column names — the relation child props). */
280
+ function targetProjection(targetModel) {
281
+ const meta = (0, decorators_1.getColumnMeta)(targetModel);
282
+ if (meta === undefined)
283
+ return [];
284
+ return Array.from(meta.values()).map((m) => m.columnName);
285
+ }
286
+ //# sourceMappingURL=decorator-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorator-adapter.js","sourceRoot":"","sources":["../../src/scp/decorator-adapter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;AAmGH,sCAgBC;AAYD,gDASC;AASD,kCAEC;AAwBD,kDASC;AAGD,kDAMC;AAOD,kDAMC;AAQD,0DAgBC;AAGD,kDAUC;AAiBD,kDAMC;AAOD,wCAyBC;AAOD,gDAYC;AAvTD,iDAKwB;AACxB,yCAAsG;AACtG,uCAAmJ;AAInJ,8CAAmG;AACnG,sCAA0D;AAiB1D,mGAAmG;AAEnG;;;;;;;;;;;;;;;;GAgBG;AACU,QAAA,sBAAsB,GAAqC;IACtE,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IACtB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,WAAW;IACxB,WAAW,EAAE,WAAW;CACzB,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,uBAAuB,GAAG,SAAS,CAAC;AAajD;;;;;;;;;;;GAWG;AACH,SAAgB,aAAa,CAAC,OAAe,EAAE,IAAgB,EAAE,QAAiB;IAChF,MAAM,OAAO,GACX,QAAQ;QACR,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,8BAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,IAAI,CAAC,WAAW;QAChB,+BAAuB,CAAC;IAC1B,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,8BAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;QAC/G,MAAM,IAAI,KAAK,CACb,8BAA8B,OAAO,mCAAmC,IAAI,CAAC,OAAO,YAAY;YAC9F,+EAA+E;YAC/E,wBAAwB,OAAO,6BAA6B,CAC/D,CAAC;IACJ,CAAC;IACD,gGAAgG;IAChG,IAAA,mCAAyB,EAAC,OAAO,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAAC,UAA0B,EAAE,UAAgC,EAAE;IAC/F,MAAM,IAAI,GAAG,IAAA,0BAAa,EAAC,UAAU,CAAC,CAAC;IACvC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAQD,0GAA0G;AAC1G,SAAgB,WAAW,CAAC,UAA0B;IACpD,OAAO,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;AAChE,CAAC;AAED,mGAAmG;AACnG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,mBAAmB,CACjC,UAA0B,EAC1B,IAAY,EACZ,OAAiG,EACjG,UAAuB,QAAQ,EAC/B,cAAqC;IAErC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC1E,OAAO,IAAA,sCAAuB,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAC5E,CAAC;AAED,iHAAiH;AACjH,SAAgB,mBAAmB,CACjC,IAAY,EACZ,OAA+B,EAC/B,UAAuB,QAAQ;IAE/B,OAAO,IAAA,sCAAuB,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CACjC,IAAY,EACZ,OAAyG,EACzG,UAAuB,QAAQ;IAE/B,OAAO,IAAA,sCAAuB,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CACrC,UAA0B,EAC1B,cAAqC;IAErC,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC/D,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxD,OAAO,CAAC,KAAa,EAAE,MAAc,EAAE,EAAE;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,2CAA2C,KAAK,IAAI,MAAM,wCAAwC;gBAChG,6FAA6F,CAChG,CAAC;QACJ,CAAC;QACD,OAAO,IAAA,4BAAkB,EAAC,OAAO,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED,kIAAkI;AAClI,SAAgB,mBAAmB,CACjC,UAA0B,EAC1B,cAAqC;IAErC,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,EAA+B,CAAC;IACnD,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3F,OAAO,IAAA,yCAA+B,EAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,uGAAuG;AAEvG;;;;;;;;;;;;GAYG;AACH,SAAgB,mBAAmB,CACjC,UAA0B,EAC1B,kBAAyD,EACzD,UAAuB,QAAQ;IAE/B,OAAO,IAAA,4BAAe,EAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;AACzG,CAAC;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAC5B,GAAiB,EACjB,kBAAyD,EACzD,UAAuB,QAAQ;IAE/B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAA,sBAAa,EAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE/F,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,GAAG,CAAC,WAAW;QACrB,IAAI,EAAE,GAAG,CAAC,IAAoB;QAC9B,WAAW;QACX,MAAM;QACN,OAAO;QACP,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtF,CAAC;IACF,MAAM,IAAI,GAAiB,MAAM,CAAC,SAAS;QACzC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;QAC3E,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAChC,UAA0B,EAC1B,kBAAyD,EACzD,UAAuB,QAAQ,EAC/B,cAAqC;IAErC,MAAM,GAAG,GAA+B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,IAAA,4BAAe,EAAC,UAAU,CAAC,EAAE,CAAC;QAC9C,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAC/E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAA,4BAAiB,EAAC,IAAI,EAAE,mBAAmB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAWD,0GAA0G;AAC1G,SAAS,SAAS,CAAC,IAAa;IAM9B,MAAM,GAAG,GAAG,IAA0B,CAAC;IACvC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,GAA4B,CAAC;QAC3C,OAAO;YACL,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;YAC7C,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;YAC7C,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SACvC,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,GAA4B,CAAC;IAChD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;AAC1H,CAAC;AAED,2GAA2G;AAC3G,SAAS,gBAAgB,CAAC,WAA2B;IACnD,MAAM,IAAI,GAAG,IAAA,0BAAa,EAAC,WAAW,CAAC,CAAC;IACxC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * litedbmodel v2 SCP — the decorator/metadata → SCP-restricted TS LOWERING EMITTER.
3
+ *
4
+ * This is the middle of the settled model (CLAUDE.md §1):
5
+ *
6
+ * ```
7
+ * ORM user: decorated models + DECLARED endpoints (no SQL) ← src/decorators.ts + ./endpoint
8
+ * ↓ emitBehaviorModule — THIS module
9
+ * SCP-restricted TS: `@behavior static` methods calling the ONE `@leaf` catalog (`Db`), with the
10
+ * dialect SQL already baked in by `makesql`
11
+ * ↓ bc generate --from
12
+ * go / rust / py / php / ts native modules — bc wires the leaves automatically
13
+ * ```
14
+ *
15
+ * ## It compiles nothing of its own
16
+ *
17
+ * Every artifact the emitter puts in the emitted source comes from an EXISTING aggregation point —
18
+ * the emitter only RENDERS them as TypeScript:
19
+ *
20
+ * | emitted thing | comes from |
21
+ * |------------------------------|-----------------------------------------------------------------|
22
+ * | read SQL + param order | `makesql/compile-select.compileSelect` |
23
+ * | WHERE text (whole / fragment)| `makesql/compile.compileWhere` → `DBConditions` |
24
+ * | static IN-list membership | `makesql/json-array.inListPredicate` (PG `= ANY(?)`, #46) |
25
+ * | write SQL + param order | `makesql/tx.compileWriteNode` (INSERT/UPDATE/DELETE + batch) |
26
+ * | relation batch SQL + keys | `relation.compileRelationOp` (+ `parentKeyCols`/`targetKeyCols`) |
27
+ * | relation hard-limit guard | `relation.relationGuard` (the compiled op's resolved cap) |
28
+ * | row types | `makesql/outtype.deriveReadRow` over the model's `@column` SoT |
29
+ * | column SQL types | `decorator-adapter.deriveModelColumns` / `modelColumnResolver` |
30
+ * | relation declarations | `decorator-adapter.relationDeclOf` |
31
+ * | find hard-limit cap | `limit-config.resolveFindHardLimit` |
32
+ * | the leaf catalog | `leaf-transport.Db` (imported by the emitted module) |
33
+ *
34
+ * ## How a parameter reaches the SQL
35
+ *
36
+ * The builders bind VALUES: they push whatever value a condition/port carried into `params` in the
37
+ * exact order the `?`s appear. The emitter therefore hands them a {@link ParamRef} SENTINEL instead
38
+ * of a value and reads the sentinels back out of `params` — so the emitted `params` array is the
39
+ * builders' own binding order, with each slot rendered as the method parameter it stands for. A slot
40
+ * that came back as a plain value (a QUERY view's own fragment params) renders as a literal.
41
+ *
42
+ * ## SKIP / dynamic WHERE (CLAUDE.md §2 — settled)
43
+ *
44
+ * A predicate declared `optional` is present-or-absent PER CALL, so the final SQL can only be
45
+ * determined at execution time. The emitter therefore does NOT bake it: it passes the WHERE as
46
+ * FRAGMENTS — SQL text + params, and a skipped fragment is simply omitted — and the `executeSQL`
47
+ * leaf assembles the survivors when it runs ({@link import('../leaves').assembleDynamicWhere}); the
48
+ * `?`→`$N` render happens after that, on the final SQL. There is no intermediate IR vocabulary: a
49
+ * fragment is `{sql, params}` and nothing else, and a skipped one evaluates to `null` (bc's `cond` is
50
+ * lazy, so a dropped fragment's params are never evaluated).
51
+ *
52
+ * A statement with NO optional predicate carries no plan at all — its WHERE is lowered into the
53
+ * static `sql` at emit time (native-clean). One path, chosen per statement.
54
+ */
55
+ import { type DeriveColumnsOptions, type ModelClassLike } from '../decorator-adapter';
56
+ import type { DialectName } from '../dialect';
57
+ import type { EndpointSet } from './endpoint';
58
+ /** What to emit. */
59
+ export interface EmitSpec {
60
+ /** The emitted class name — the `bc generate --behavior` argument. */
61
+ readonly behavior: string;
62
+ /** The dialect whose SQL is baked into the emitted source. */
63
+ readonly dialect: DialectName;
64
+ /**
65
+ * The module specifier the emitted source imports `Db` from — the ONE `@leaf` catalog
66
+ * (`src/scp/leaf-transport`). It must resolve FROM the emitted file's own location, because
67
+ * `bc generate --from` type-checks the emitted source.
68
+ */
69
+ readonly leafImport: string;
70
+ /** The declared endpoints — one `@behavior static` method each, in declaration order. */
71
+ readonly endpoints: EndpointSet;
72
+ /** Model NAME → model class, for resolving a relation's target model (as `deriveRelationDecls` takes). */
73
+ readonly models?: (modelName: string) => ModelClassLike;
74
+ /** Per-column SQL-type overrides passed through to {@link deriveModelColumns}. */
75
+ readonly columnOptions?: DeriveColumnsOptions;
76
+ }
77
+ /** One emitted endpoint's call contract — what a caller passes and what it gets back. */
78
+ export interface EmittedEndpoint {
79
+ readonly name: string;
80
+ /** The emitted method's parameters, in signature order (the generated module's input scope keys). */
81
+ readonly params: readonly {
82
+ readonly name: string;
83
+ readonly type: string;
84
+ }[];
85
+ /** The emitted method's declared return type. */
86
+ readonly returnType: string;
87
+ /**
88
+ * The `findHardLimit` cap baked into this read's `LIMIT cap + 1` bounded fetch, when one was
89
+ * configured and the endpoint declared no explicit limit. SCP has no throw, so the read boundary
90
+ * enforces it post-fetch with {@link import('../limit-config').assertFindHardLimit} — the same
91
+ * split the relation twin uses (`runRelationOp` throws off the op's baked `hardLimit`).
92
+ */
93
+ readonly findHardLimit?: number;
94
+ }
95
+ /** The emitter's output. */
96
+ export interface EmitResult {
97
+ /** The SCP-restricted TypeScript source (what `bc generate --from` reads). */
98
+ readonly source: string;
99
+ /** Per-endpoint call contracts, in emission order. */
100
+ readonly endpoints: readonly EmittedEndpoint[];
101
+ }
102
+ /**
103
+ * Lower a set of declared endpoints to SCP-restricted TypeScript. The result's `source` is ordinary
104
+ * `tsc --strict` TypeScript (that is bc's authoring requirement) whose only imports are bc's
105
+ * authoring markers and the library's ONE leaf catalog.
106
+ */
107
+ export declare function emitBehaviorModule(spec: EmitSpec): EmitResult;
108
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../../src/scp/emit/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAcH,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAQV,WAAW,EAYZ,MAAM,YAAY,CAAC;AAIpB,oBAAoB;AACpB,MAAM,WAAW,QAAQ;IACvB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC,0GAA0G;IAC1G,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,cAAc,CAAC;IACxD,kFAAkF;IAClF,QAAQ,CAAC,aAAa,CAAC,EAAE,oBAAoB,CAAC;CAC/C;AAED,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qGAAqG;IACrG,QAAQ,CAAC,MAAM,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7E,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,4BAA4B;AAC5B,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;CAChD;AAsBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAM7D"}