@plumbus/core 0.2.9 → 0.3.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 (176) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ai/__tests__/ai-service.test.js +704 -1
  3. package/dist/ai/__tests__/ai-service.test.js.map +1 -1
  4. package/dist/ai/__tests__/chunking.test.js +34 -0
  5. package/dist/ai/__tests__/chunking.test.js.map +1 -1
  6. package/dist/ai/__tests__/provider.test.d.ts.map +1 -1
  7. package/dist/ai/__tests__/provider.test.js +425 -0
  8. package/dist/ai/__tests__/provider.test.js.map +1 -1
  9. package/dist/ai/__tests__/validation.test.js +200 -1
  10. package/dist/ai/__tests__/validation.test.js.map +1 -1
  11. package/dist/ai/__tests__/zod-to-provider-schema.test.d.ts +2 -0
  12. package/dist/ai/__tests__/zod-to-provider-schema.test.d.ts.map +1 -0
  13. package/dist/ai/__tests__/zod-to-provider-schema.test.js +60 -0
  14. package/dist/ai/__tests__/zod-to-provider-schema.test.js.map +1 -0
  15. package/dist/ai/ai-service.d.ts +19 -2
  16. package/dist/ai/ai-service.d.ts.map +1 -1
  17. package/dist/ai/ai-service.js +544 -110
  18. package/dist/ai/ai-service.js.map +1 -1
  19. package/dist/ai/cost-tracker.d.ts +26 -1
  20. package/dist/ai/cost-tracker.d.ts.map +1 -1
  21. package/dist/ai/cost-tracker.js +1 -0
  22. package/dist/ai/cost-tracker.js.map +1 -1
  23. package/dist/ai/index.d.ts +5 -3
  24. package/dist/ai/index.d.ts.map +1 -1
  25. package/dist/ai/index.js +5 -1
  26. package/dist/ai/index.js.map +1 -1
  27. package/dist/ai/provider.d.ts +45 -1
  28. package/dist/ai/provider.d.ts.map +1 -1
  29. package/dist/ai/provider.js +226 -32
  30. package/dist/ai/provider.js.map +1 -1
  31. package/dist/ai/rag/chunking.js +53 -3
  32. package/dist/ai/rag/chunking.js.map +1 -1
  33. package/dist/ai/refusal.d.ts +28 -0
  34. package/dist/ai/refusal.d.ts.map +1 -0
  35. package/dist/ai/refusal.js +36 -0
  36. package/dist/ai/refusal.js.map +1 -0
  37. package/dist/ai/validation.d.ts +40 -8
  38. package/dist/ai/validation.d.ts.map +1 -1
  39. package/dist/ai/validation.js +97 -6
  40. package/dist/ai/validation.js.map +1 -1
  41. package/dist/ai/zod-to-provider-schema.d.ts +15 -0
  42. package/dist/ai/zod-to-provider-schema.d.ts.map +1 -0
  43. package/dist/ai/zod-to-provider-schema.js +200 -0
  44. package/dist/ai/zod-to-provider-schema.js.map +1 -0
  45. package/dist/cli/__tests__/doctor.test.js +104 -2
  46. package/dist/cli/__tests__/doctor.test.js.map +1 -1
  47. package/dist/cli/__tests__/init.test.js +127 -7
  48. package/dist/cli/__tests__/init.test.js.map +1 -1
  49. package/dist/cli/__tests__/migrate.test.js +159 -2
  50. package/dist/cli/__tests__/migrate.test.js.map +1 -1
  51. package/dist/cli/commands/__tests__/commands.test.js +5 -0
  52. package/dist/cli/commands/__tests__/commands.test.js.map +1 -1
  53. package/dist/cli/commands/dev.d.ts.map +1 -1
  54. package/dist/cli/commands/dev.js +21 -1
  55. package/dist/cli/commands/dev.js.map +1 -1
  56. package/dist/cli/commands/doctor.d.ts +2 -0
  57. package/dist/cli/commands/doctor.d.ts.map +1 -1
  58. package/dist/cli/commands/doctor.js +78 -0
  59. package/dist/cli/commands/doctor.js.map +1 -1
  60. package/dist/cli/commands/generate.d.ts.map +1 -1
  61. package/dist/cli/commands/generate.js +7 -2
  62. package/dist/cli/commands/generate.js.map +1 -1
  63. package/dist/cli/commands/init.d.ts +16 -2
  64. package/dist/cli/commands/init.d.ts.map +1 -1
  65. package/dist/cli/commands/init.js +226 -25
  66. package/dist/cli/commands/init.js.map +1 -1
  67. package/dist/cli/commands/migrate.d.ts.map +1 -1
  68. package/dist/cli/commands/migrate.js +258 -8
  69. package/dist/cli/commands/migrate.js.map +1 -1
  70. package/dist/cli/commands/start.d.ts.map +1 -1
  71. package/dist/cli/commands/start.js +21 -1
  72. package/dist/cli/commands/start.js.map +1 -1
  73. package/dist/data/__tests__/drift-inspector.test.d.ts +2 -0
  74. package/dist/data/__tests__/drift-inspector.test.d.ts.map +1 -0
  75. package/dist/data/__tests__/drift-inspector.test.js +170 -0
  76. package/dist/data/__tests__/drift-inspector.test.js.map +1 -0
  77. package/dist/data/__tests__/framework-migration-rewriter.test.d.ts +2 -0
  78. package/dist/data/__tests__/framework-migration-rewriter.test.d.ts.map +1 -0
  79. package/dist/data/__tests__/framework-migration-rewriter.test.js +329 -0
  80. package/dist/data/__tests__/framework-migration-rewriter.test.js.map +1 -0
  81. package/dist/data/__tests__/migration.test.js +93 -2
  82. package/dist/data/__tests__/migration.test.js.map +1 -1
  83. package/dist/data/__tests__/repository.test.js +126 -0
  84. package/dist/data/__tests__/repository.test.js.map +1 -1
  85. package/dist/data/drift-inspector.d.ts +41 -0
  86. package/dist/data/drift-inspector.d.ts.map +1 -0
  87. package/dist/data/drift-inspector.js +197 -0
  88. package/dist/data/drift-inspector.js.map +1 -0
  89. package/dist/data/framework-migration-rewriter.d.ts +61 -0
  90. package/dist/data/framework-migration-rewriter.d.ts.map +1 -0
  91. package/dist/data/framework-migration-rewriter.js +357 -0
  92. package/dist/data/framework-migration-rewriter.js.map +1 -0
  93. package/dist/data/index.d.ts +2 -1
  94. package/dist/data/index.d.ts.map +1 -1
  95. package/dist/data/index.js +2 -1
  96. package/dist/data/index.js.map +1 -1
  97. package/dist/data/migration.d.ts +31 -1
  98. package/dist/data/migration.d.ts.map +1 -1
  99. package/dist/data/migration.js +113 -3
  100. package/dist/data/migration.js.map +1 -1
  101. package/dist/data/repository.d.ts.map +1 -1
  102. package/dist/data/repository.js +21 -0
  103. package/dist/data/repository.js.map +1 -1
  104. package/dist/define/__tests__/definePrompt.test.js +37 -0
  105. package/dist/define/__tests__/definePrompt.test.js.map +1 -1
  106. package/dist/define/definePrompt.d.ts +13 -0
  107. package/dist/define/definePrompt.d.ts.map +1 -1
  108. package/dist/define/definePrompt.js +3 -0
  109. package/dist/define/definePrompt.js.map +1 -1
  110. package/dist/errors/http.d.ts.map +1 -1
  111. package/dist/errors/http.js +2 -0
  112. package/dist/errors/http.js.map +1 -1
  113. package/dist/errors/index.d.ts +12 -0
  114. package/dist/errors/index.d.ts.map +1 -1
  115. package/dist/errors/index.js +21 -0
  116. package/dist/errors/index.js.map +1 -1
  117. package/dist/events/__tests__/event-emitter.test.js +72 -0
  118. package/dist/events/__tests__/event-emitter.test.js.map +1 -1
  119. package/dist/events/emitter.d.ts.map +1 -1
  120. package/dist/events/emitter.js +51 -0
  121. package/dist/events/emitter.js.map +1 -1
  122. package/dist/execution/__tests__/context-factory.test.js +1 -0
  123. package/dist/execution/__tests__/context-factory.test.js.map +1 -1
  124. package/dist/execution/context-factory.d.ts.map +1 -1
  125. package/dist/execution/context-factory.js +2 -0
  126. package/dist/execution/context-factory.js.map +1 -1
  127. package/dist/flows/__tests__/flow-engine.test.js +451 -4
  128. package/dist/flows/__tests__/flow-engine.test.js.map +1 -1
  129. package/dist/flows/__tests__/flow-service.test.js +8 -0
  130. package/dist/flows/__tests__/flow-service.test.js.map +1 -1
  131. package/dist/flows/__tests__/step-executor.test.js +8 -2
  132. package/dist/flows/__tests__/step-executor.test.js.map +1 -1
  133. package/dist/flows/engine.d.ts +50 -1
  134. package/dist/flows/engine.d.ts.map +1 -1
  135. package/dist/flows/engine.js +427 -23
  136. package/dist/flows/engine.js.map +1 -1
  137. package/dist/flows/flow-service.d.ts.map +1 -1
  138. package/dist/flows/flow-service.js +4 -0
  139. package/dist/flows/flow-service.js.map +1 -1
  140. package/dist/flows/index.d.ts +1 -1
  141. package/dist/flows/index.d.ts.map +1 -1
  142. package/dist/flows/index.js +1 -1
  143. package/dist/flows/index.js.map +1 -1
  144. package/dist/flows/schema.d.ts +34 -0
  145. package/dist/flows/schema.d.ts.map +1 -1
  146. package/dist/flows/schema.js +3 -0
  147. package/dist/flows/schema.js.map +1 -1
  148. package/dist/index.d.ts +4 -4
  149. package/dist/index.d.ts.map +1 -1
  150. package/dist/index.js +3 -3
  151. package/dist/index.js.map +1 -1
  152. package/dist/server/bootstrap.d.ts +14 -0
  153. package/dist/server/bootstrap.d.ts.map +1 -1
  154. package/dist/server/bootstrap.js +23 -4
  155. package/dist/server/bootstrap.js.map +1 -1
  156. package/dist/testing/context.d.ts.map +1 -1
  157. package/dist/testing/context.js +37 -1
  158. package/dist/testing/context.js.map +1 -1
  159. package/dist/types/context.d.ts +110 -0
  160. package/dist/types/context.d.ts.map +1 -1
  161. package/dist/types/enums.d.ts +2 -0
  162. package/dist/types/enums.d.ts.map +1 -1
  163. package/dist/types/enums.js +2 -0
  164. package/dist/types/enums.js.map +1 -1
  165. package/dist/types/prompt.d.ts +64 -0
  166. package/dist/types/prompt.d.ts.map +1 -1
  167. package/dist/worker/__tests__/bootstrap.test.js +36 -2
  168. package/dist/worker/__tests__/bootstrap.test.js.map +1 -1
  169. package/dist/worker/bootstrap.d.ts +7 -0
  170. package/dist/worker/bootstrap.d.ts.map +1 -1
  171. package/dist/worker/bootstrap.js +153 -12
  172. package/dist/worker/bootstrap.js.map +1 -1
  173. package/instructions/framework.md +7 -0
  174. package/instructions/guardrails.md +39 -0
  175. package/instructions/patterns.md +10 -0
  176. package/package.json +3 -2
@@ -0,0 +1,357 @@
1
+ // ── Framework Migration Rewriter ──
2
+ // Transforms drizzle-kit's raw migration SQL so that it can be safely applied
3
+ // against a database whose framework-managed tables (flow_executions, etc.)
4
+ // already exist but are missing newly-added framework columns.
5
+ //
6
+ // Why this exists:
7
+ // When a project upgrades `@plumbus/core`, the framework's own table schemas
8
+ // may have grown new columns (e.g. flow leasing added `lease_owner` and
9
+ // `lease_expires_at` to `flow_executions`). Drizzle-kit, which generates
10
+ // migrations purely from snapshot diffs, has no awareness of which tables
11
+ // are framework-managed and emits `CREATE TABLE` for the entire framework
12
+ // table — even when the table already exists in the live DB. That migration
13
+ // is then rejected by the `migrate apply` preflight ("framework table
14
+ // already exists"), leaving users with no clean upgrade path.
15
+ //
16
+ // What this does:
17
+ // Given the raw SQL drizzle-kit produced and a `DriftReport` from
18
+ // `inspectFrameworkDrift`, we rewrite the SQL so that:
19
+ // • CREATE TABLE statements for framework tables that already exist are
20
+ // replaced with one ALTER TABLE … ADD COLUMN per `missing_in_db`
21
+ // column reported by the drift inspector. Column type/null/default
22
+ // text is parsed verbatim out of the original CREATE TABLE body so we
23
+ // inherit drizzle-kit's exact serialization.
24
+ // • CREATE TABLE statements for framework tables whose columns already
25
+ // fully match the schema are dropped entirely.
26
+ // • CREATE INDEX / CREATE UNIQUE INDEX statements are wrapped with
27
+ // IF NOT EXISTS so re-running on a partially migrated DB doesn't trip
28
+ // on indexes that already exist (Postgres ≥ 9.5).
29
+ // • Everything else (entity tables, ALTERs to entity tables, constraints,
30
+ // etc.) passes through unchanged.
31
+ //
32
+ // Limitations (future work):
33
+ // • IF NOT EXISTS only suppresses the duplicate-name error on relations
34
+ // and indexes; it does NOT verify that the existing definition actually
35
+ // matches what the migration intends. Safe full reconciliation requires
36
+ // comparing columns, defaults, constraints, and indexes — see
37
+ // `inspectFrameworkDrift` for a starting point. We currently only act
38
+ // on `missing_in_db` columns; `type_mismatch`, `nullability_mismatch`,
39
+ // and `extra_in_db` are surfaced in the summary but not auto-rewritten,
40
+ // because resolving them safely usually needs human judgment.
41
+ // • CONSTRAINT clauses inside a rewrite-target CREATE TABLE (e.g. table-
42
+ // level UNIQUE / CHECK) are dropped with a warning — Postgres has no
43
+ // ADD CONSTRAINT IF NOT EXISTS, so we can't safely re-add idempotently.
44
+ import { FRAMEWORK_TABLE_NAMES, } from './drift-inspector.js';
45
+ const STATEMENT_BREAKPOINT = '--> statement-breakpoint';
46
+ const FRAMEWORK_TABLE_SET = new Set(FRAMEWORK_TABLE_NAMES);
47
+ /**
48
+ * Rewrite drizzle-kit migration statements to be safe against framework-table
49
+ * drift.
50
+ *
51
+ * Operates on the raw `string[]` that `drizzle-kit/api.generateMigration`
52
+ * returns — one element per SQL statement. Returns a new array of statements
53
+ * (some may be removed, some may expand into multiple ALTER TABLE …
54
+ * statements) along with a structured summary for logging.
55
+ *
56
+ * Pure function — no IO, no DB access.
57
+ *
58
+ * If the report contains no `existingFrameworkTables`, the input is returned
59
+ * unchanged apart from index IF NOT EXISTS wrapping, which is always safe.
60
+ */
61
+ export function rewriteFrameworkDriftMigration(inputStatements, driftReport, _schemas) {
62
+ const summary = {
63
+ alteredTables: [],
64
+ droppedCreateTables: [],
65
+ wrappedIndexes: [],
66
+ idempotentAddColumns: [],
67
+ warnings: [],
68
+ };
69
+ const driftByTable = new Map();
70
+ for (const table of driftReport.tables) {
71
+ driftByTable.set(table.tableName, table);
72
+ }
73
+ const existingFrameworkSet = new Set(driftReport.existingFrameworkTables);
74
+ const out = [];
75
+ for (const stmt of inputStatements) {
76
+ const trimmed = stmt.trim();
77
+ if (!trimmed)
78
+ continue;
79
+ const createTableName = matchCreateTableName(trimmed);
80
+ if (createTableName && existingFrameworkSet.has(createTableName)) {
81
+ const tableDrift = driftByTable.get(createTableName);
82
+ const missing = tableDrift?.columnDrifts.filter((d) => d.kind === 'missing_in_db') ?? [];
83
+ if (missing.length === 0) {
84
+ // Table already fully matches — drop the CREATE TABLE.
85
+ summary.droppedCreateTables.push(createTableName);
86
+ continue;
87
+ }
88
+ const parsed = parseCreateTableBody(trimmed);
89
+ if (!parsed) {
90
+ // Couldn't parse safely — leave as-is and warn. Apply preflight will
91
+ // still catch the conflict; better to fail loudly than to lose data.
92
+ summary.warnings.push(`Could not parse CREATE TABLE for "${createTableName}"; passing through unchanged.`);
93
+ out.push(stmt);
94
+ continue;
95
+ }
96
+ const columnLineByName = new Map(parsed.columnLines.map((c) => [c.name, c.line]));
97
+ const altered = [];
98
+ const alterStatements = [];
99
+ for (const col of missing) {
100
+ const line = columnLineByName.get(col.column);
101
+ if (!line) {
102
+ // Drift inspector reported a missing column but drizzle-kit didn't
103
+ // include a definition for it — schema desync. Warn and skip.
104
+ summary.warnings.push(`Drift reported missing column "${createTableName}.${col.column}" but the generated CREATE TABLE has no matching definition.`);
105
+ continue;
106
+ }
107
+ alterStatements.push(`ALTER TABLE "${createTableName}" ADD COLUMN ${line};`);
108
+ altered.push(col.column);
109
+ }
110
+ if (parsed.constraintLines.length > 0) {
111
+ summary.warnings.push(`Dropped ${parsed.constraintLines.length} table-level constraint clause(s) from CREATE TABLE for "${createTableName}" because Postgres does not support ADD CONSTRAINT IF NOT EXISTS. If a new framework constraint is required, add it manually.`);
112
+ }
113
+ if (alterStatements.length === 0) {
114
+ summary.droppedCreateTables.push(createTableName);
115
+ continue;
116
+ }
117
+ summary.alteredTables.push({
118
+ table: createTableName,
119
+ addedColumns: altered,
120
+ });
121
+ // Push each ALTER as its own array element so the caller can join with
122
+ // any separator (including a literal newline, which is what drizzle-kit
123
+ // already does for migration files).
124
+ for (const a of alterStatements)
125
+ out.push(a);
126
+ continue;
127
+ }
128
+ const indexWrapped = wrapCreateIndexIfNotExists(trimmed);
129
+ if (indexWrapped !== trimmed) {
130
+ summary.wrappedIndexes.push(extractIndexName(trimmed) ?? '<anonymous>');
131
+ out.push(indexWrapped);
132
+ continue;
133
+ }
134
+ const addColWrapped = wrapAlterAddColumnIfNotExists(trimmed);
135
+ if (addColWrapped !== trimmed) {
136
+ summary.idempotentAddColumns.push(extractAddColumnTarget(trimmed) ?? '<unknown>');
137
+ out.push(addColWrapped);
138
+ continue;
139
+ }
140
+ out.push(stmt);
141
+ }
142
+ return {
143
+ statements: out,
144
+ summary,
145
+ };
146
+ }
147
+ // ── Internals ──
148
+ /**
149
+ * Re-exported for callers that want to render rewritten statements with the
150
+ * same separator drizzle-kit uses internally for breakpoint-aware tooling.
151
+ */
152
+ export const STATEMENT_BREAKPOINT_MARKER = STATEMENT_BREAKPOINT;
153
+ const CREATE_TABLE_HEAD_RE = /^\s*CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"([^"]+)"|([a-zA-Z_]\w*))/i;
154
+ function matchCreateTableName(stmt) {
155
+ const m = stmt.match(CREATE_TABLE_HEAD_RE);
156
+ if (!m)
157
+ return null;
158
+ return m[1] ?? m[2] ?? null;
159
+ }
160
+ const TABLE_LEVEL_CONSTRAINT_KEYWORDS = [
161
+ 'CONSTRAINT',
162
+ 'PRIMARY KEY',
163
+ 'UNIQUE',
164
+ 'CHECK',
165
+ 'FOREIGN KEY',
166
+ 'EXCLUDE',
167
+ ];
168
+ /**
169
+ * Parse the parenthesized body of a CREATE TABLE statement into individual
170
+ * column definition lines. Drizzle-kit emits one column per line, separated
171
+ * by commas, with the column name as a quoted identifier at the start.
172
+ *
173
+ * Returns null if the body cannot be located (e.g. no opening paren).
174
+ */
175
+ function parseCreateTableBody(stmt) {
176
+ const openIdx = stmt.indexOf('(');
177
+ if (openIdx < 0)
178
+ return null;
179
+ // Find the matching closing paren. Drizzle-kit-generated bodies don't
180
+ // contain nested parens for our purposes (no inline CHECK constraints etc.
181
+ // — those would surface as constraintLines). We still scan with depth so we
182
+ // don't get fooled by anything embedded.
183
+ let depth = 0;
184
+ let closeIdx = -1;
185
+ let inSingleQuote = false;
186
+ for (let i = openIdx; i < stmt.length; i++) {
187
+ const ch = stmt[i];
188
+ if (ch === "'" && stmt[i - 1] !== '\\')
189
+ inSingleQuote = !inSingleQuote;
190
+ if (inSingleQuote)
191
+ continue;
192
+ if (ch === '(')
193
+ depth++;
194
+ else if (ch === ')') {
195
+ depth--;
196
+ if (depth === 0) {
197
+ closeIdx = i;
198
+ break;
199
+ }
200
+ }
201
+ }
202
+ if (closeIdx < 0)
203
+ return null;
204
+ const body = stmt.slice(openIdx + 1, closeIdx);
205
+ // Split by top-level commas (no nesting expected in column defs, but be
206
+ // defensive about quoted strings and parens just in case).
207
+ const segments = splitTopLevelCommas(body);
208
+ const columnLines = [];
209
+ const constraintLines = [];
210
+ for (const raw of segments) {
211
+ const line = raw.trim();
212
+ if (!line)
213
+ continue;
214
+ if (isConstraintLine(line)) {
215
+ constraintLines.push(line);
216
+ continue;
217
+ }
218
+ const nameMatch = line.match(/^"([^"]+)"\s+(.+)$/) ?? line.match(/^([a-zA-Z_]\w*)\s+(.+)$/);
219
+ if (!nameMatch) {
220
+ // Unrecognized — treat as constraint to be safe (will trigger warning).
221
+ constraintLines.push(line);
222
+ continue;
223
+ }
224
+ const colName = nameMatch[1];
225
+ columnLines.push({ name: colName, line });
226
+ }
227
+ return { columnLines, constraintLines };
228
+ }
229
+ function splitTopLevelCommas(body) {
230
+ const parts = [];
231
+ let depth = 0;
232
+ let inSingleQuote = false;
233
+ let start = 0;
234
+ for (let i = 0; i < body.length; i++) {
235
+ const ch = body[i];
236
+ if (ch === "'" && body[i - 1] !== '\\')
237
+ inSingleQuote = !inSingleQuote;
238
+ if (inSingleQuote)
239
+ continue;
240
+ if (ch === '(')
241
+ depth++;
242
+ else if (ch === ')')
243
+ depth--;
244
+ else if (ch === ',' && depth === 0) {
245
+ parts.push(body.slice(start, i));
246
+ start = i + 1;
247
+ }
248
+ }
249
+ parts.push(body.slice(start));
250
+ return parts;
251
+ }
252
+ function isConstraintLine(line) {
253
+ const upper = line.toUpperCase();
254
+ return TABLE_LEVEL_CONSTRAINT_KEYWORDS.some((kw) => upper.startsWith(kw));
255
+ }
256
+ const CREATE_INDEX_RE = /^(\s*)CREATE\s+(UNIQUE\s+)?INDEX(?!\s+IF\s+NOT\s+EXISTS\b)\s+/i;
257
+ function wrapCreateIndexIfNotExists(stmt) {
258
+ return stmt.replace(CREATE_INDEX_RE, (_match, leading, unique) => {
259
+ const u = unique ? unique : '';
260
+ return `${leading}CREATE ${u}INDEX IF NOT EXISTS `;
261
+ });
262
+ }
263
+ const INDEX_NAME_RE = /CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?"?([^"\s]+)"?/i;
264
+ function extractIndexName(stmt) {
265
+ const m = stmt.match(INDEX_NAME_RE);
266
+ return m?.[1] ?? null;
267
+ }
268
+ // Match `ALTER TABLE [IF EXISTS] <tbl> ADD COLUMN [IF NOT EXISTS]`. We only
269
+ // want to rewrite when IF NOT EXISTS is *not* already present. Multiple
270
+ // ADD COLUMN clauses can appear in one ALTER TABLE statement separated by
271
+ // commas; we wrap every one of them.
272
+ const ALTER_ADD_COLUMN_RE = /\bADD\s+COLUMN(?!\s+IF\s+NOT\s+EXISTS\b)\s+/gi;
273
+ function isAlterTableStatement(stmt) {
274
+ return /^\s*ALTER\s+TABLE\b/i.test(stmt);
275
+ }
276
+ /**
277
+ * Rewrite `ALTER TABLE … ADD COLUMN <name> …` to `ADD COLUMN IF NOT EXISTS
278
+ * <name> …`. We do not touch `ADD CONSTRAINT`, `ALTER COLUMN`, etc.
279
+ *
280
+ * Why universal idempotency:
281
+ * Drizzle-kit's diff-based generation depends on the snapshot in
282
+ * drizzle/meta accurately reflecting the live schema. Real projects
283
+ * accumulate snapshot drift (manually edited migrations, partial applies,
284
+ * prod hotfixes). Making framework-emitted ADD COLUMN idempotent removes a
285
+ * whole class of "column already exists" apply failures without changing
286
+ * semantics: a real type/default mismatch will still surface elsewhere
287
+ * (e.g. queries failing at runtime), and the apply path remains a no-op
288
+ * when the column is already there.
289
+ *
290
+ * Limitation (future work, mirrors the index case):
291
+ * Postgres' `IF NOT EXISTS` only suppresses the duplicate-name error; it
292
+ * does NOT verify that the existing column matches the requested type,
293
+ * nullability, or default. Comprehensive reconciliation requires
294
+ * `inspectFrameworkDrift`-style comparison across every column for every
295
+ * user-managed entity, not just the framework-managed tables.
296
+ */
297
+ function wrapAlterAddColumnIfNotExists(stmt) {
298
+ if (!isAlterTableStatement(stmt))
299
+ return stmt;
300
+ return stmt.replace(ALTER_ADD_COLUMN_RE, 'ADD COLUMN IF NOT EXISTS ');
301
+ }
302
+ const ALTER_TABLE_TARGET_RE = /^\s*ALTER\s+TABLE\s+(?:IF\s+EXISTS\s+)?(?:"([^"]+)"|([a-zA-Z_]\w*))/i;
303
+ const ADD_COLUMN_NAME_RE = /\bADD\s+COLUMN(?:\s+IF\s+NOT\s+EXISTS)?\s+(?:"([^"]+)"|([a-zA-Z_]\w*))/gi;
304
+ function extractAddColumnTarget(stmt) {
305
+ const tableMatch = stmt.match(ALTER_TABLE_TARGET_RE);
306
+ const table = tableMatch?.[1] ?? tableMatch?.[2] ?? null;
307
+ if (!table)
308
+ return null;
309
+ const columns = [];
310
+ for (const m of stmt.matchAll(ADD_COLUMN_NAME_RE)) {
311
+ columns.push(m[1] ?? m[2]);
312
+ }
313
+ if (columns.length === 0)
314
+ return `"${table}"`;
315
+ return `"${table}".${columns.map((c) => `"${c}"`).join(',')}`;
316
+ }
317
+ /**
318
+ * Convenience: format the rewriter summary for human-readable CLI output.
319
+ * Returns an array of lines (no trailing newlines), or an empty array if no
320
+ * meaningful rewriting happened.
321
+ */
322
+ export function formatRewriteSummary(summary) {
323
+ const lines = [];
324
+ if (summary.alteredTables.length > 0) {
325
+ lines.push('Framework drift rewrite: emitted ALTER TABLE ADD COLUMN for:');
326
+ for (const t of summary.alteredTables) {
327
+ lines.push(` ${t.table}: ${t.addedColumns.join(', ')}`);
328
+ }
329
+ }
330
+ if (summary.droppedCreateTables.length > 0) {
331
+ lines.push(`Framework drift rewrite: dropped redundant CREATE TABLE for: ${summary.droppedCreateTables.join(', ')}`);
332
+ }
333
+ if (summary.wrappedIndexes.length > 0) {
334
+ lines.push(`Framework drift rewrite: wrapped ${summary.wrappedIndexes.length} CREATE INDEX statement(s) with IF NOT EXISTS.`);
335
+ }
336
+ if (summary.idempotentAddColumns.length > 0) {
337
+ lines.push(`Framework drift rewrite: made ${summary.idempotentAddColumns.length} ALTER TABLE ADD COLUMN statement(s) idempotent.`);
338
+ }
339
+ for (const w of summary.warnings) {
340
+ lines.push(` warning: ${w}`);
341
+ }
342
+ return lines;
343
+ }
344
+ /**
345
+ * True if the rewriter actually changed anything beyond cosmetic whitespace.
346
+ * Useful for skipping noisy logs when the migration was clean already.
347
+ */
348
+ export function rewriteHadEffect(summary) {
349
+ return (summary.alteredTables.length > 0 ||
350
+ summary.droppedCreateTables.length > 0 ||
351
+ summary.wrappedIndexes.length > 0 ||
352
+ summary.idempotentAddColumns.length > 0 ||
353
+ summary.warnings.length > 0);
354
+ }
355
+ // Re-export so callers can keep a single import surface.
356
+ export { FRAMEWORK_TABLE_SET };
357
+ //# sourceMappingURL=framework-migration-rewriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-migration-rewriter.js","sourceRoot":"","sources":["../../src/data/framework-migration-rewriter.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export { gte, ilike, like, lte, sql } from 'drizzle-orm';
2
- export { applyMigrations, collectSchemas, rollbackLastMigration, type MigrationConfig, type MigrationRecord, } from './migration.js';
2
+ export { applyMigrations, collectSchemas, readPendingMigrations, rollbackLastMigration, type MigrationApplyResult, type MigrationConfig, type MigrationRecord, type PendingMigration, } from './migration.js';
3
+ export { extractCreateTableNames, formatDriftReport, FRAMEWORK_TABLE_NAMES, getExistingFrameworkTables, inspectFrameworkDrift, type ColumnDrift, type DriftReport, type FrameworkTableName, type TableDrift, } from './drift-inspector.js';
3
4
  export { EntityRegistry } from './registry.js';
4
5
  export { createRepository, type RepositoryOptions } from './repository.js';
5
6
  export { generateDrizzleSchema, generateSchemas } from './schema-generator.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -5,7 +5,8 @@
5
5
  // Key exports: createRepository, EntityRegistry, generateDrizzleSchema, applyMigrations
6
6
  // Re-export Drizzle operators for use in query conditions
7
7
  export { gte, ilike, like, lte, sql } from 'drizzle-orm';
8
- export { applyMigrations, collectSchemas, rollbackLastMigration, } from './migration.js';
8
+ export { applyMigrations, collectSchemas, readPendingMigrations, rollbackLastMigration, } from './migration.js';
9
+ export { extractCreateTableNames, formatDriftReport, FRAMEWORK_TABLE_NAMES, getExistingFrameworkTables, inspectFrameworkDrift, } from './drift-inspector.js';
9
10
  export { EntityRegistry } from './registry.js';
10
11
  export { createRepository } from './repository.js';
11
12
  export { generateDrizzleSchema, generateSchemas } from './schema-generator.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,+EAA+E;AAC/E,oEAAoE;AACpE,EAAE;AACF,wFAAwF;AAExF,0DAA0D;AAC1D,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,eAAe,EACf,cAAc,EACd,qBAAqB,GAGtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAA0B,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,+EAA+E;AAC/E,oEAAoE;AACpE,EAAE;AACF,wFAAwF;AAExF,0DAA0D;AAC1D,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,qBAAqB,GAKtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,GAKtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAA0B,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -5,10 +5,40 @@ export interface MigrationConfig {
5
5
  db: PostgresJsDatabase;
6
6
  migrationsFolder: string;
7
7
  }
8
+ export interface PendingMigration {
9
+ tag: string;
10
+ hash: string;
11
+ statements: string[];
12
+ rawSql: string;
13
+ folderMillis: number;
14
+ }
15
+ export interface MigrationApplyResult {
16
+ applied: number;
17
+ tags: string[];
18
+ }
19
+ export interface MigrationReconcileResult {
20
+ adopted: number;
21
+ alreadyApplied: number;
22
+ adoptedTags: string[];
23
+ }
24
+ /**
25
+ * Read the migration journal and determine which migrations are pending
26
+ * (not yet applied to the database).
27
+ */
28
+ export declare function readPendingMigrations(config: MigrationConfig): Promise<PendingMigration[]>;
8
29
  /**
9
30
  * Apply pending migrations from the migrations folder.
31
+ *
32
+ * Each migration runs inside a transaction. On failure, the error includes
33
+ * the migration tag, statement index, and a SQL preview for diagnostics.
34
+ */
35
+ export declare function applyMigrations(config: MigrationConfig): Promise<MigrationApplyResult>;
36
+ /**
37
+ * Reconcile migration history by marking journal migrations as applied
38
+ * without executing schema changes. Intended for adoption/recovery when
39
+ * the live database already matches the current Plumbus schema.
10
40
  */
11
- export declare function applyMigrations(config: MigrationConfig): Promise<void>;
41
+ export declare function reconcileMigrationHistory(config: MigrationConfig): Promise<MigrationReconcileResult>;
12
42
  /**
13
43
  * Collect all Drizzle table schemas from entity definitions,
14
44
  * plus framework-internal tables (e.g. audit_records).
@@ -1 +1 @@
1
- {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/data/migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAMlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,kBAAkB,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAmBzC;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,aAAa,GAAG,eAAe,CAAC;CACzC,CAAC,CA2BD"}
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/data/migration.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAKlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,kBAAkB,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAYD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AA4DD;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAShG;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+B5F;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,wBAAwB,CAAC,CA+BnC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAmBzC;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,aAAa,GAAG,eAAe,CAAC;CACzC,CAAC,CA2BD"}
@@ -1,16 +1,126 @@
1
- import { migrate } from 'drizzle-orm/postgres-js/migrator';
1
+ import * as crypto from 'node:crypto';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { sql } from 'drizzle-orm';
2
5
  import { documentChunksTable, documentsTable } from '../ai/rag/schema.js';
3
6
  import { auditRecords } from '../audit/schema.js';
4
7
  import { deadLetterTable, idempotencyTable, outboxTable } from '../events/outbox.js';
5
8
  import { flowDeadLetterTable, flowExecutionsTable, flowSchedulesTable } from '../flows/schema.js';
6
9
  import { generateDrizzleSchema } from './schema-generator.js';
10
+ function readMigrationJournalEntries(migrationsFolder) {
11
+ const journalPath = path.join(migrationsFolder, 'meta', '_journal.json');
12
+ if (!fs.existsSync(journalPath)) {
13
+ throw new Error(`Can't find meta/_journal.json in ${migrationsFolder}`);
14
+ }
15
+ const journal = JSON.parse(fs.readFileSync(journalPath, 'utf-8'));
16
+ return journal.entries;
17
+ }
18
+ function readJournalMigrations(migrationsFolder) {
19
+ const journalEntries = readMigrationJournalEntries(migrationsFolder);
20
+ return journalEntries.map((entry) => {
21
+ const sqlPath = path.join(migrationsFolder, `${entry.tag}.sql`);
22
+ if (!fs.existsSync(sqlPath)) {
23
+ throw new Error(`Missing migration file: ${sqlPath}`);
24
+ }
25
+ const rawSql = fs.readFileSync(sqlPath, 'utf-8');
26
+ const hash = crypto.createHash('sha256').update(rawSql).digest('hex');
27
+ const statements = entry.breakpoints
28
+ ? rawSql
29
+ .split('--> statement-breakpoint')
30
+ .map((statement) => statement.trim())
31
+ .filter(Boolean)
32
+ : [rawSql];
33
+ return {
34
+ tag: entry.tag,
35
+ hash,
36
+ statements,
37
+ rawSql,
38
+ folderMillis: entry.when,
39
+ };
40
+ });
41
+ }
42
+ async function ensureMigrationsTable(db) {
43
+ await db.execute(sql `CREATE TABLE IF NOT EXISTS "__drizzle_migrations" (
44
+ id SERIAL PRIMARY KEY,
45
+ hash TEXT NOT NULL,
46
+ created_at BIGINT
47
+ )`);
48
+ }
49
+ async function getAppliedMigrationHashes(db) {
50
+ const appliedRows = (await db.execute(sql `SELECT hash FROM "__drizzle_migrations"`));
51
+ return new Set(appliedRows.map((row) => row.hash));
52
+ }
53
+ /**
54
+ * Read the migration journal and determine which migrations are pending
55
+ * (not yet applied to the database).
56
+ */
57
+ export async function readPendingMigrations(config) {
58
+ const { db, migrationsFolder } = config;
59
+ await ensureMigrationsTable(db);
60
+ const appliedHashes = await getAppliedMigrationHashes(db);
61
+ const journalMigrations = readJournalMigrations(migrationsFolder);
62
+ return journalMigrations.filter((migration) => !appliedHashes.has(migration.hash));
63
+ }
7
64
  /**
8
65
  * Apply pending migrations from the migrations folder.
66
+ *
67
+ * Each migration runs inside a transaction. On failure, the error includes
68
+ * the migration tag, statement index, and a SQL preview for diagnostics.
9
69
  */
10
70
  export async function applyMigrations(config) {
11
- await migrate(config.db, {
12
- migrationsFolder: config.migrationsFolder,
71
+ const pending = await readPendingMigrations(config);
72
+ if (pending.length === 0) {
73
+ return { applied: 0, tags: [] };
74
+ }
75
+ const appliedTags = [];
76
+ for (const migration of pending) {
77
+ await config.db.transaction(async (tx) => {
78
+ for (let i = 0; i < migration.statements.length; i++) {
79
+ const stmt = migration.statements[i] ?? '';
80
+ try {
81
+ await tx.execute(sql.raw(stmt));
82
+ }
83
+ catch (stmtErr) {
84
+ const preview = stmt.length > 200 ? `${stmt.slice(0, 200)}...` : stmt;
85
+ throw new Error(`Migration "${migration.tag}" failed at statement ${i + 1}/${migration.statements.length}:\n` +
86
+ ` SQL: ${preview}\n` +
87
+ ` Error: ${stmtErr instanceof Error ? stmtErr.message : String(stmtErr)}`);
88
+ }
89
+ }
90
+ await tx.execute(sql `INSERT INTO "__drizzle_migrations" (hash, created_at) VALUES (${migration.hash}, ${migration.folderMillis})`);
91
+ });
92
+ appliedTags.push(migration.tag);
93
+ }
94
+ return { applied: appliedTags.length, tags: appliedTags };
95
+ }
96
+ /**
97
+ * Reconcile migration history by marking journal migrations as applied
98
+ * without executing schema changes. Intended for adoption/recovery when
99
+ * the live database already matches the current Plumbus schema.
100
+ */
101
+ export async function reconcileMigrationHistory(config) {
102
+ const journalMigrations = readJournalMigrations(config.migrationsFolder);
103
+ await ensureMigrationsTable(config.db);
104
+ const appliedHashes = await getAppliedMigrationHashes(config.db);
105
+ const missingMigrations = journalMigrations.filter((migration) => !appliedHashes.has(migration.hash));
106
+ if (missingMigrations.length === 0) {
107
+ return {
108
+ adopted: 0,
109
+ alreadyApplied: journalMigrations.length,
110
+ adoptedTags: [],
111
+ };
112
+ }
113
+ await config.db.transaction(async (tx) => {
114
+ for (const migration of missingMigrations) {
115
+ await tx.execute(sql `INSERT INTO "__drizzle_migrations" (hash, created_at)
116
+ VALUES (${migration.hash}, ${migration.folderMillis})`);
117
+ }
13
118
  });
119
+ return {
120
+ adopted: missingMigrations.length,
121
+ alreadyApplied: journalMigrations.length - missingMigrations.length,
122
+ adoptedTags: missingMigrations.map((migration) => migration.tag),
123
+ };
14
124
  }
15
125
  /**
16
126
  * Collect all Drizzle table schemas from entity definitions,
@@ -1 +1 @@
1
- {"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/data/migration.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAElG,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAO9D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAuB;IAC3D,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE;QACvB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;KAC1C,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,QAA4B;IAE5B,MAAM,OAAO,GAA4C,EAAE,CAAC;IAC5D,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;IACD,4BAA4B;IAC5B,OAAO,CAAC,eAAe,GAAG,YAAkD,CAAC;IAC7E,sBAAsB;IACtB,OAAO,CAAC,cAAc,GAAG,WAAiD,CAAC;IAC3E,OAAO,CAAC,mBAAmB,GAAG,gBAAsD,CAAC;IACrF,OAAO,CAAC,mBAAmB,GAAG,eAAqD,CAAC;IACpF,cAAc;IACd,OAAO,CAAC,iBAAiB,GAAG,mBAAyD,CAAC;IACtF,OAAO,CAAC,kBAAkB,GAAG,mBAAyD,CAAC;IACvF,OAAO,CAAC,gBAAgB,GAAG,kBAAwD,CAAC;IACpF,aAAa;IACb,OAAO,CAAC,WAAW,GAAG,cAAoD,CAAC;IAC3E,OAAO,CAAC,iBAAiB,GAAG,mBAAyD,CAAC;IACtF,OAAO,OAAO,CAAC;AACjB,CAAC;AAWD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAuB;IAIjE,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IAErB,sEAAsE;IACtE,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC;QAC7B,GAAG,EAAE,oFAAoF;QACzF,MAAM,EAAE,EAAE;KACJ,CAAC,CAA2D,CAAC;IAErE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC;IAEzC,sDAAsD;IACtD,MAAM,EAAE,CAAC,OAAO,CAAC;QACf,GAAG,EAAE,kDAAkD;QACvD,MAAM,EAAE,CAAC,aAAa,CAAC;KACjB,CAAC,CAAC;IAEV,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/data/migration.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/data/repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC/B,EAAE,EAAE,kBAAkB,CAAC;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAgO7D"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/data/repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC/B,EAAE,EAAE,kBAAkB,CAAC;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAyP7D"}
@@ -76,6 +76,27 @@ export function createRepository(options) {
76
76
  await auditMutation('create', record);
77
77
  return created;
78
78
  },
79
+ async createMany(records) {
80
+ if (records.length === 0)
81
+ return [];
82
+ const prepared = records.map((data) => {
83
+ const record = { ...data };
84
+ if (isTenantScoped && !bypassTenantScope) {
85
+ if (!auth.tenantId) {
86
+ throw new Error(`Tenant-scoped entity "${entity.name}" requires auth.tenantId`);
87
+ }
88
+ record.tenantId = auth.tenantId;
89
+ }
90
+ return record;
91
+ });
92
+ const rows = await db.insert(table).values(prepared).returning();
93
+ // One summary audit row per batch instead of N per-row audits.
94
+ await auditMutation('createMany', {
95
+ count: prepared.length,
96
+ sample: maskData(prepared[0] ?? {}),
97
+ });
98
+ return rows;
99
+ },
79
100
  async update(id, updates) {
80
101
  const conditions = [];
81
102
  const idCol = table.id;