@schemalens/cli 0.1.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 (50) hide show
  1. package/README.md +154 -0
  2. package/dist/commands/ci.d.ts +15 -0
  3. package/dist/commands/ci.js +78 -0
  4. package/dist/commands/ci.js.map +1 -0
  5. package/dist/commands/deploy.d.ts +8 -0
  6. package/dist/commands/deploy.js +212 -0
  7. package/dist/commands/deploy.js.map +1 -0
  8. package/dist/commands/diff.d.ts +1 -0
  9. package/dist/commands/diff.js +96 -0
  10. package/dist/commands/diff.js.map +1 -0
  11. package/dist/commands/init.d.ts +1 -0
  12. package/dist/commands/init.js +197 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/migrate.d.ts +1 -0
  15. package/dist/commands/migrate.js +50 -0
  16. package/dist/commands/migrate.js.map +1 -0
  17. package/dist/commands/pull.d.ts +1 -0
  18. package/dist/commands/pull.js +80 -0
  19. package/dist/commands/pull.js.map +1 -0
  20. package/dist/commands/status.d.ts +1 -0
  21. package/dist/commands/status.js +59 -0
  22. package/dist/commands/status.js.map +1 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +133 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/lib/config.d.ts +34 -0
  27. package/dist/lib/config.js +150 -0
  28. package/dist/lib/config.js.map +1 -0
  29. package/dist/lib/differ.d.ts +13 -0
  30. package/dist/lib/differ.js +130 -0
  31. package/dist/lib/differ.js.map +1 -0
  32. package/dist/lib/git.d.ts +16 -0
  33. package/dist/lib/git.js +65 -0
  34. package/dist/lib/git.js.map +1 -0
  35. package/dist/lib/introspector.d.ts +2 -0
  36. package/dist/lib/introspector.js +7 -0
  37. package/dist/lib/introspector.js.map +1 -0
  38. package/dist/lib/planner.d.ts +26 -0
  39. package/dist/lib/planner.js +501 -0
  40. package/dist/lib/planner.js.map +1 -0
  41. package/dist/lib/reader.d.ts +19 -0
  42. package/dist/lib/reader.js +106 -0
  43. package/dist/lib/reader.js.map +1 -0
  44. package/dist/lib/sync.d.ts +13 -0
  45. package/dist/lib/sync.js +46 -0
  46. package/dist/lib/sync.js.map +1 -0
  47. package/dist/lib/writer.d.ts +7 -0
  48. package/dist/lib/writer.js +191 -0
  49. package/dist/lib/writer.js.map +1 -0
  50. package/package.json +37 -0
@@ -0,0 +1,501 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildDeployPlan = buildDeployPlan;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ // ---------------------------------------------------------------------------
9
+ // Helpers
10
+ // ---------------------------------------------------------------------------
11
+ function md5(content) {
12
+ return crypto_1.default.createHash('md5').update(content).digest('hex');
13
+ }
14
+ function stripHeader(content) {
15
+ return content.split('\n').slice(2).join('\n');
16
+ }
17
+ function bodyHash(content) {
18
+ return md5(stripHeader(content));
19
+ }
20
+ /**
21
+ * Normalize SQL body for comparison: trim, strip trailing semicolons/newlines.
22
+ * This prevents false diffs caused by the writer appending semicolons.
23
+ */
24
+ function normalizeForComparison(body) {
25
+ return body.trim().replace(/;\s*$/, '').trim();
26
+ }
27
+ // Languages that indicate extension-owned objects — cannot be deployed via SQL
28
+ const EXTENSION_LANGUAGES = new Set(['c', 'internal']);
29
+ /**
30
+ * Parse a CREATE TABLE definition.sql to extract column info.
31
+ * Returns a map of column_name -> { type, nullable, defaultVal }.
32
+ */
33
+ function parseColumnsFromDisk(content) {
34
+ const cols = new Map();
35
+ const body = stripHeader(content);
36
+ // Match lines inside CREATE TABLE (...) that look like column defs
37
+ const tableBodyMatch = body.match(/CREATE TABLE[^(]*\(([\s\S]*)\);/);
38
+ if (!tableBodyMatch)
39
+ return cols;
40
+ const lines = tableBodyMatch[1].split('\n');
41
+ for (const line of lines) {
42
+ const trimmed = line.trim().replace(/,$/, '');
43
+ // Skip constraints (CONSTRAINT keyword or lines starting with PRIMARY/FOREIGN/UNIQUE/CHECK)
44
+ if (/^\s*(CONSTRAINT|PRIMARY|FOREIGN|UNIQUE|CHECK|EXCLUDE)\b/i.test(trimmed))
45
+ continue;
46
+ if (!trimmed || trimmed.startsWith('--'))
47
+ continue;
48
+ // Pattern: "col_name" type [NOT NULL] [DEFAULT ...]
49
+ const colMatch = trimmed.match(/^"([^"]+)"\s+(\S+)(.*)/);
50
+ if (!colMatch)
51
+ continue;
52
+ const name = colMatch[1];
53
+ const type = colMatch[2];
54
+ const rest = colMatch[3] || '';
55
+ const nullable = !rest.includes('NOT NULL');
56
+ const defaultMatch = rest.match(/DEFAULT\s+(.*?)(?:\s*$)/i);
57
+ const defaultVal = defaultMatch ? defaultMatch[1].replace(/,$/, '').trim() : null;
58
+ cols.set(name, { type, nullable, defaultVal });
59
+ }
60
+ return cols;
61
+ }
62
+ /**
63
+ * Parse enum values from a disk enum file.
64
+ */
65
+ function parseEnumValuesFromDisk(content) {
66
+ const body = stripHeader(content);
67
+ const values = [];
68
+ const matches = body.matchAll(/'([^']+)'/g);
69
+ for (const m of matches) {
70
+ values.push(m[1]);
71
+ }
72
+ return values;
73
+ }
74
+ /**
75
+ * Parse index names from a disk indexes.sql file.
76
+ */
77
+ function parseIndexNamesFromDisk(content) {
78
+ const body = stripHeader(content);
79
+ const indexes = new Map();
80
+ const regex = /CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF NOT EXISTS\s+)?(?:"([^"]+)"|(\S+))/gi;
81
+ let m;
82
+ while ((m = regex.exec(body)) !== null) {
83
+ const name = m[1] || m[2];
84
+ const startIdx = m.index;
85
+ const endIdx = body.indexOf(';', startIdx);
86
+ const stmt = body.substring(startIdx, endIdx >= 0 ? endIdx + 1 : undefined).trim();
87
+ indexes.set(name, stmt);
88
+ }
89
+ return indexes;
90
+ }
91
+ /**
92
+ * Parse policy names from a disk policies.sql file.
93
+ */
94
+ function parsePolicyNamesFromDisk(content) {
95
+ const body = stripHeader(content);
96
+ const policies = new Set();
97
+ const regex = /CREATE POLICY\s+"([^"]+)"/gi;
98
+ let m;
99
+ while ((m = regex.exec(body)) !== null) {
100
+ policies.add(m[1]);
101
+ }
102
+ return policies;
103
+ }
104
+ /**
105
+ * Detect if two types are compatible for rename detection.
106
+ */
107
+ function typesCompatible(a, b) {
108
+ const normalize = (t) => t.toLowerCase().replace(/\s+/g, '');
109
+ return normalize(a) === normalize(b);
110
+ }
111
+ // ---------------------------------------------------------------------------
112
+ // Dependency ordering
113
+ // ---------------------------------------------------------------------------
114
+ const CATEGORY_ORDER = {
115
+ 'extension': 0,
116
+ 'enum': 1,
117
+ 'table-def': 2,
118
+ 'table-indexes': 3,
119
+ 'view': 4,
120
+ 'function': 5,
121
+ 'table-triggers': 6,
122
+ 'table-policies': 7,
123
+ };
124
+ // Supabase-managed schemas — never deploy into these
125
+ const MANAGED_SCHEMAS = new Set([
126
+ 'auth', 'storage', 'realtime', 'vault', 'pgsodium',
127
+ 'pgsodium_masks', 'graphql', 'graphql_public', 'supabase_functions',
128
+ 'supabase_migrations', 'net', 'cron', '_realtime', '_analytics',
129
+ ]);
130
+ // ---------------------------------------------------------------------------
131
+ // Core planner
132
+ // ---------------------------------------------------------------------------
133
+ function buildDeployPlan(diskFiles, liveSnapshot, renames) {
134
+ const steps = [];
135
+ const renameCandidates = [];
136
+ let stepNum = 0;
137
+ // Filter out Supabase-managed schemas, then sort by dependency order
138
+ const userFiles = diskFiles.filter(f => {
139
+ if (f.category === 'extension')
140
+ return true; // extensions are global
141
+ return !MANAGED_SCHEMAS.has(f.schemaName);
142
+ });
143
+ const sorted = [...userFiles].sort((a, b) => {
144
+ return (CATEGORY_ORDER[a.category] ?? 99) - (CATEGORY_ORDER[b.category] ?? 99);
145
+ });
146
+ // Build lookup maps from live snapshot
147
+ const liveTables = new Map(liveSnapshot.tables.map(t => [`${t.schema}.${t.name}`, t]));
148
+ const liveViews = new Map(liveSnapshot.views.map(v => [`${v.schema}.${v.name}`, v]));
149
+ const liveFunctions = new Map(liveSnapshot.functions.map(f => [`${f.schema}.${f.name}`, f]));
150
+ const liveEnums = new Map(liveSnapshot.enums.map(e => [`${e.schema}.${e.name}`, e]));
151
+ const liveExtNames = new Set(liveSnapshot.extensions.map(e => e.name));
152
+ for (const file of sorted) {
153
+ const key = `${file.schemaName}.${file.objectName}`;
154
+ switch (file.category) {
155
+ case 'extension': {
156
+ const sql = stripHeader(file.content).trim();
157
+ if (!sql || sql.startsWith('-- No')) {
158
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
159
+ }
160
+ else {
161
+ // Check if all extensions in the file already exist
162
+ const extNames = [...sql.matchAll(/CREATE EXTENSION[^"]*"([^"]+)"/gi)].map(m => m[1]);
163
+ const newExts = extNames.filter(name => !liveExtNames.has(name));
164
+ if (newExts.length === 0) {
165
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
166
+ }
167
+ else {
168
+ // Only CREATE the missing extensions
169
+ const newSql = newExts
170
+ .map(name => `CREATE EXTENSION IF NOT EXISTS "${name}";`)
171
+ .join('\n');
172
+ steps.push(makeStep(++stepNum, file, 'CREATE', newSql, false, []));
173
+ }
174
+ }
175
+ break;
176
+ }
177
+ case 'enum': {
178
+ const liveEnum = liveEnums.get(key);
179
+ const diskValues = parseEnumValuesFromDisk(file.content);
180
+ if (!liveEnum) {
181
+ steps.push(makeStep(++stepNum, file, 'CREATE', stripHeader(file.content).trim(), false, []));
182
+ }
183
+ else {
184
+ // Existing enum: add new values only (PG cannot remove enum values)
185
+ const newValues = diskValues.filter(v => !liveEnum.values.includes(v));
186
+ if (newValues.length === 0) {
187
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
188
+ }
189
+ else {
190
+ const sql = newValues
191
+ .map(v => `ALTER TYPE "${file.schemaName}"."${file.objectName}" ADD VALUE IF NOT EXISTS '${v}';`)
192
+ .join('\n');
193
+ steps.push(makeStep(++stepNum, file, 'ALTER', sql, false, []));
194
+ }
195
+ }
196
+ break;
197
+ }
198
+ case 'table-def': {
199
+ const liveTable = liveTables.get(key);
200
+ if (!liveTable) {
201
+ steps.push(makeStep(++stepNum, file, 'CREATE', stripHeader(file.content).trim(), false, []));
202
+ }
203
+ else {
204
+ const result = diffTableColumns(file, liveTable, renames);
205
+ renameCandidates.push(...result.renames);
206
+ if (result.sql.trim()) {
207
+ steps.push(makeStep(++stepNum, file, 'ALTER', result.sql, result.destructive, result.warnings));
208
+ }
209
+ else {
210
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
211
+ }
212
+ }
213
+ break;
214
+ }
215
+ case 'table-indexes': {
216
+ const liveTable = liveTables.get(key);
217
+ if (!liveTable) {
218
+ const sql = stripHeader(file.content).trim();
219
+ if (sql && !sql.startsWith('-- No')) {
220
+ steps.push(makeStep(++stepNum, file, 'CREATE', sql, false, []));
221
+ }
222
+ else {
223
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
224
+ }
225
+ }
226
+ else {
227
+ const result = diffIndexes(file, liveSnapshot.indexes, file.schemaName, file.objectName);
228
+ if (result.sql.trim()) {
229
+ steps.push(makeStep(++stepNum, file, result.operation, result.sql, result.destructive, result.warnings));
230
+ }
231
+ else {
232
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
233
+ }
234
+ }
235
+ break;
236
+ }
237
+ case 'view': {
238
+ const liveView = liveViews.get(key);
239
+ if (!liveView) {
240
+ steps.push(makeStep(++stepNum, file, 'CREATE', stripHeader(file.content).trim(), false, []));
241
+ }
242
+ else {
243
+ const liveNorm = normalizeForComparison(liveView.definition);
244
+ const diskBody = stripHeader(file.content).trim();
245
+ const diskDefMatch = diskBody.match(/AS\s+([\s\S]+)/i);
246
+ const diskDef = diskDefMatch ? diskDefMatch[1].trim() : diskBody;
247
+ const diskNorm = normalizeForComparison(diskDef);
248
+ if (md5(liveNorm) === md5(diskNorm)) {
249
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
250
+ }
251
+ else {
252
+ steps.push(makeStep(++stepNum, file, 'REPLACE', diskBody, false, []));
253
+ }
254
+ }
255
+ break;
256
+ }
257
+ case 'function': {
258
+ const liveFunc = liveFunctions.get(key);
259
+ const diskBody = stripHeader(file.content).trim();
260
+ // Skip extension-owned functions (C/internal) — cannot be deployed via SQL
261
+ if (liveFunc && EXTENSION_LANGUAGES.has(liveFunc.language)) {
262
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
263
+ break;
264
+ }
265
+ if (!liveFunc) {
266
+ steps.push(makeStep(++stepNum, file, 'CREATE', diskBody, false, []));
267
+ }
268
+ else {
269
+ const liveNorm = liveFunc.body ? normalizeForComparison(liveFunc.body) : '';
270
+ const diskNorm = normalizeForComparison(diskBody);
271
+ if (md5(liveNorm) === md5(diskNorm)) {
272
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
273
+ }
274
+ else {
275
+ steps.push(makeStep(++stepNum, file, 'REPLACE', diskBody, false, []));
276
+ }
277
+ }
278
+ break;
279
+ }
280
+ case 'table-triggers': {
281
+ const body = stripHeader(file.content).trim();
282
+ if (!body || body.startsWith('-- No')) {
283
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
284
+ break;
285
+ }
286
+ const liveTable = liveTables.get(key);
287
+ if (!liveTable) {
288
+ steps.push(makeStep(++stepNum, file, 'CREATE', body, false, []));
289
+ }
290
+ else {
291
+ // Extract CREATE TRIGGER statements from disk and compare against live
292
+ const liveTriggers = liveSnapshot.triggers.filter(t => t.schema === file.schemaName && t.table === file.objectName);
293
+ const liveSet = new Set(liveTriggers.map(t => normalizeForComparison(t.body)));
294
+ const diskTrigDefs = body.match(/CREATE TRIGGER[\s\S]*?(?=DROP TRIGGER|CREATE TRIGGER|$)/gi) || [];
295
+ const diskSet = new Set(diskTrigDefs.map(d => normalizeForComparison(d)));
296
+ // Compare: same triggers if same set of normalized CREATE TRIGGER statements
297
+ const setsEqual = liveSet.size === diskSet.size && [...liveSet].every(t => diskSet.has(t));
298
+ if (setsEqual) {
299
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
300
+ }
301
+ else {
302
+ steps.push(makeStep(++stepNum, file, 'REPLACE', body, false, []));
303
+ }
304
+ }
305
+ break;
306
+ }
307
+ case 'table-policies': {
308
+ const liveTable = liveTables.get(key);
309
+ if (!liveTable) {
310
+ const body = stripHeader(file.content).trim();
311
+ if (body && !body.startsWith('-- No')) {
312
+ steps.push(makeStep(++stepNum, file, 'CREATE', body, false, []));
313
+ }
314
+ else {
315
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
316
+ }
317
+ }
318
+ else {
319
+ const result = diffPolicies(file, liveSnapshot.policies, file.schemaName, file.objectName);
320
+ if (result.sql.trim()) {
321
+ steps.push(makeStep(++stepNum, file, result.operation, result.sql, result.destructive, result.warnings));
322
+ }
323
+ else {
324
+ steps.push(makeStep(++stepNum, file, 'SKIP', '', false, []));
325
+ }
326
+ }
327
+ break;
328
+ }
329
+ }
330
+ }
331
+ return {
332
+ steps,
333
+ renames: renameCandidates,
334
+ hasDestructive: steps.some(s => s.destructive),
335
+ };
336
+ }
337
+ function diffTableColumns(file, liveTable, confirmedRenames) {
338
+ const diskCols = parseColumnsFromDisk(file.content);
339
+ const liveCols = new Map(liveTable.columns.map(c => [c.name, c]));
340
+ const sqls = [];
341
+ const warnings = [];
342
+ const renames = [];
343
+ let destructive = false;
344
+ const tbl = `"${file.schemaName}"."${file.objectName}"`;
345
+ // Columns on disk but not live: ADD COLUMN
346
+ const added = [];
347
+ for (const [colName, col] of diskCols) {
348
+ if (!liveCols.has(colName)) {
349
+ // Check if this is a confirmed rename
350
+ let isRename = false;
351
+ for (const [rk, newName] of confirmedRenames) {
352
+ if (newName === colName && rk.startsWith(`${file.objectName}.`)) {
353
+ const oldCol = rk.split('.')[1];
354
+ sqls.push(`ALTER TABLE ${tbl} RENAME COLUMN "${oldCol}" TO "${colName}";`);
355
+ isRename = true;
356
+ break;
357
+ }
358
+ }
359
+ if (!isRename) {
360
+ added.push(colName);
361
+ const parts = [`ALTER TABLE ${tbl} ADD COLUMN "${colName}" ${col.type}`];
362
+ if (!col.nullable)
363
+ parts.push('NOT NULL');
364
+ if (col.defaultVal)
365
+ parts.push(`DEFAULT ${col.defaultVal}`);
366
+ sqls.push(parts.join(' ') + ';');
367
+ }
368
+ }
369
+ }
370
+ // Columns live but not on disk: DROP COLUMN
371
+ const removed = [];
372
+ for (const [colName] of liveCols) {
373
+ if (!diskCols.has(colName)) {
374
+ const renameKey = `${file.objectName}.${colName}`;
375
+ if (confirmedRenames.has(renameKey))
376
+ continue;
377
+ removed.push(colName);
378
+ sqls.push(`ALTER TABLE ${tbl} DROP COLUMN "${colName}";`);
379
+ warnings.push(`DROP COLUMN "${colName}" on ${tbl}`);
380
+ destructive = true;
381
+ }
382
+ }
383
+ // Detect possible renames (removed + added with compatible types)
384
+ for (const oldCol of removed) {
385
+ const liveCol = liveCols.get(oldCol);
386
+ if (!liveCol)
387
+ continue;
388
+ for (const newCol of added) {
389
+ const diskCol = diskCols.get(newCol);
390
+ if (!diskCol)
391
+ continue;
392
+ if (typesCompatible(liveCol.type, diskCol.type)) {
393
+ renames.push({
394
+ table: file.objectName,
395
+ schema: file.schemaName,
396
+ oldColumn: oldCol,
397
+ newColumn: newCol,
398
+ type: liveCol.type,
399
+ });
400
+ }
401
+ }
402
+ }
403
+ // Columns in both: check for type or nullability changes
404
+ for (const [colName, diskCol] of diskCols) {
405
+ const liveCol = liveCols.get(colName);
406
+ if (!liveCol)
407
+ continue;
408
+ if (liveCol.type !== diskCol.type) {
409
+ sqls.push(`ALTER TABLE ${tbl} ALTER COLUMN "${colName}" TYPE ${diskCol.type};`);
410
+ }
411
+ if (liveCol.nullable && !diskCol.nullable) {
412
+ sqls.push(`ALTER TABLE ${tbl} ALTER COLUMN "${colName}" SET NOT NULL;`);
413
+ }
414
+ else if (!liveCol.nullable && diskCol.nullable) {
415
+ sqls.push(`ALTER TABLE ${tbl} ALTER COLUMN "${colName}" DROP NOT NULL;`);
416
+ }
417
+ if (diskCol.defaultVal && diskCol.defaultVal !== liveCol.default) {
418
+ sqls.push(`ALTER TABLE ${tbl} ALTER COLUMN "${colName}" SET DEFAULT ${diskCol.defaultVal};`);
419
+ }
420
+ else if (!diskCol.defaultVal && liveCol.default) {
421
+ sqls.push(`ALTER TABLE ${tbl} ALTER COLUMN "${colName}" DROP DEFAULT;`);
422
+ }
423
+ }
424
+ return { sql: sqls.join('\n'), destructive, warnings, renames };
425
+ }
426
+ function diffIndexes(file, liveIndexes, schemaName, tableName) {
427
+ const diskIndexes = parseIndexNamesFromDisk(file.content);
428
+ const liveTableIndexes = liveIndexes.filter(i => i.schema === schemaName && i.table === tableName && !i.isPrimary);
429
+ const liveNames = new Set(liveTableIndexes.map(i => i.name));
430
+ const sqls = [];
431
+ const warnings = [];
432
+ let destructive = false;
433
+ for (const [name, stmt] of diskIndexes) {
434
+ if (!liveNames.has(name)) {
435
+ sqls.push(stmt.endsWith(';') ? stmt : stmt + ';');
436
+ }
437
+ }
438
+ for (const idx of liveTableIndexes) {
439
+ if (!diskIndexes.has(idx.name)) {
440
+ sqls.push(`DROP INDEX IF EXISTS "${schemaName}"."${idx.name}";`);
441
+ warnings.push(`DROP INDEX "${idx.name}" on ${schemaName}.${tableName}`);
442
+ destructive = true;
443
+ }
444
+ }
445
+ return {
446
+ sql: sqls.join('\n'),
447
+ operation: sqls.length > 0 ? 'ALTER' : 'SKIP',
448
+ destructive,
449
+ warnings,
450
+ };
451
+ }
452
+ // ---------------------------------------------------------------------------
453
+ // Policy diff
454
+ // ---------------------------------------------------------------------------
455
+ function diffPolicies(file, livePolicies, schemaName, tableName) {
456
+ const diskPolicies = parsePolicyNamesFromDisk(file.content);
457
+ const liveTablePolicies = livePolicies.filter(p => p.schema === schemaName && p.table === tableName);
458
+ const liveNames = new Set(liveTablePolicies.map(p => p.name));
459
+ const sqls = [];
460
+ const warnings = [];
461
+ let destructive = false;
462
+ const addedPolicies = [...diskPolicies].filter(n => !liveNames.has(n));
463
+ const removedPolicies = [...liveNames].filter(n => !diskPolicies.has(n));
464
+ if (addedPolicies.length > 0 || removedPolicies.length > 0) {
465
+ const body = stripHeader(file.content).trim();
466
+ sqls.push(body);
467
+ for (const name of removedPolicies) {
468
+ sqls.unshift(`DROP POLICY IF EXISTS "${name}" ON "${schemaName}"."${tableName}";`);
469
+ warnings.push(`DROP POLICY "${name}" on ${schemaName}.${tableName}`);
470
+ destructive = true;
471
+ }
472
+ }
473
+ else {
474
+ // Same policy names — if the policy set is identical, skip.
475
+ // Since we can't reliably parse policy bodies from the SQL file,
476
+ // and the file was generated by `pull` from the same DB, if the
477
+ // policy names match we consider them unchanged.
478
+ }
479
+ return {
480
+ sql: sqls.join('\n'),
481
+ operation: sqls.length > 0 ? 'REPLACE' : 'SKIP',
482
+ destructive,
483
+ warnings,
484
+ };
485
+ }
486
+ // ---------------------------------------------------------------------------
487
+ // Step builder
488
+ // ---------------------------------------------------------------------------
489
+ function makeStep(step, file, operation, sql, destructive, warnings) {
490
+ return {
491
+ step,
492
+ filePath: file.filePath,
493
+ objectType: file.category,
494
+ objectName: `${file.schemaName}.${file.objectName}`,
495
+ operation,
496
+ sql,
497
+ destructive,
498
+ warnings,
499
+ };
500
+ }
501
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/lib/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface DiskFile {
2
+ /** Relative path from project root, e.g. schema/tables/users/definition.sql */
3
+ filePath: string;
4
+ /** Category derived from path: extension | enum | table-def | table-indexes | table-policies | table-triggers | view | function */
5
+ category: DiskFileCategory;
6
+ /** Object name (table name, function name, etc.) */
7
+ objectName: string;
8
+ /** Schema name parsed from header, defaults to 'public' */
9
+ schemaName: string;
10
+ /** Raw file content */
11
+ content: string;
12
+ /** MD5 hash of content body (excluding the 2-line header) */
13
+ bodyHash: string;
14
+ }
15
+ export type DiskFileCategory = 'extension' | 'enum' | 'table-def' | 'table-indexes' | 'table-policies' | 'table-triggers' | 'view' | 'function';
16
+ /**
17
+ * Read all schema SQL files from disk into structured DiskFile objects.
18
+ */
19
+ export declare function readSchemaFiles(env: string): DiskFile[];
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readSchemaFiles = readSchemaFiles;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const SCHEMA_DIR = 'schema';
11
+ function md5(content) {
12
+ return crypto_1.default.createHash('md5').update(content).digest('hex');
13
+ }
14
+ function stripHeader(content) {
15
+ return content.split('\n').slice(2).join('\n');
16
+ }
17
+ function parseHeader(content) {
18
+ // Header format: -- object: <type> · <schema>.<name>
19
+ const firstLine = content.split('\n')[0] || '';
20
+ const match = firstLine.match(/--\s*object:\s*\S+\s*·\s*(\S+)\.(\S+)/);
21
+ if (match) {
22
+ return { schemaName: match[1], objectName: match[2] };
23
+ }
24
+ return { schemaName: 'public', objectName: '' };
25
+ }
26
+ function categorizeFile(relPath) {
27
+ const parts = relPath.split(path_1.default.sep);
28
+ // schema/<env>/extensions/enabled.sql
29
+ if (parts[2] === 'extensions') {
30
+ return { category: 'extension', fallbackName: 'enabled' };
31
+ }
32
+ // schema/<env>/enums/<name>.sql
33
+ if (parts[2] === 'enums' && parts[3]) {
34
+ return { category: 'enum', fallbackName: parts[3].replace(/\.sql$/, '') };
35
+ }
36
+ // schema/<env>/tables/<name>/definition.sql | indexes.sql | policies.sql | triggers.sql
37
+ if (parts[2] === 'tables' && parts[3] && parts[4]) {
38
+ const tableName = parts[3];
39
+ const fileName = parts[4].replace(/\.sql$/, '');
40
+ const categoryMap = {
41
+ definition: 'table-def',
42
+ indexes: 'table-indexes',
43
+ policies: 'table-policies',
44
+ triggers: 'table-triggers',
45
+ };
46
+ const cat = categoryMap[fileName];
47
+ if (cat)
48
+ return { category: cat, fallbackName: tableName };
49
+ }
50
+ // schema/<env>/views/<name>.sql
51
+ if (parts[2] === 'views' && parts[3]) {
52
+ return { category: 'view', fallbackName: parts[3].replace(/\.sql$/, '') };
53
+ }
54
+ // schema/<env>/functions/<name>.sql
55
+ if (parts[2] === 'functions' && parts[3]) {
56
+ return { category: 'function', fallbackName: parts[3].replace(/\.sql$/, '') };
57
+ }
58
+ return null;
59
+ }
60
+ /**
61
+ * Recursively collect all .sql files under a directory.
62
+ */
63
+ function collectSqlFiles(dir, base) {
64
+ const absDir = path_1.default.resolve(dir);
65
+ if (!fs_1.default.existsSync(absDir))
66
+ return [];
67
+ const results = [];
68
+ for (const entry of fs_1.default.readdirSync(absDir, { withFileTypes: true })) {
69
+ if (entry.name.startsWith('.'))
70
+ continue;
71
+ const fullPath = path_1.default.join(dir, entry.name);
72
+ if (entry.isDirectory()) {
73
+ results.push(...collectSqlFiles(fullPath, base));
74
+ }
75
+ else if (entry.name.endsWith('.sql')) {
76
+ results.push(fullPath);
77
+ }
78
+ }
79
+ return results;
80
+ }
81
+ /**
82
+ * Read all schema SQL files from disk into structured DiskFile objects.
83
+ */
84
+ function readSchemaFiles(env) {
85
+ const envDir = path_1.default.join(SCHEMA_DIR, env);
86
+ const files = collectSqlFiles(envDir, envDir);
87
+ const result = [];
88
+ for (const filePath of files) {
89
+ const relPath = path_1.default.relative('.', filePath);
90
+ const info = categorizeFile(relPath);
91
+ if (!info)
92
+ continue;
93
+ const content = fs_1.default.readFileSync(filePath, 'utf-8');
94
+ const header = parseHeader(content);
95
+ result.push({
96
+ filePath: relPath,
97
+ category: info.category,
98
+ objectName: header.objectName || info.fallbackName,
99
+ schemaName: header.schemaName,
100
+ content,
101
+ bodyHash: md5(stripHeader(content)),
102
+ });
103
+ }
104
+ return result;
105
+ }
106
+ //# sourceMappingURL=reader.js.map