relq 1.0.25 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/commands/commit.cjs +80 -0
- package/dist/cjs/cli/commands/import.cjs +1 -0
- package/dist/cjs/cli/commands/pull.cjs +108 -34
- package/dist/cjs/cli/commands/push.cjs +48 -8
- package/dist/cjs/cli/commands/rollback.cjs +205 -84
- package/dist/cjs/cli/commands/schema-ast.cjs +219 -0
- package/dist/cjs/cli/index.cjs +6 -0
- package/dist/cjs/cli/utils/ast-codegen.cjs +95 -3
- package/dist/cjs/cli/utils/ast-transformer.cjs +12 -0
- package/dist/cjs/cli/utils/change-tracker.cjs +135 -0
- package/dist/cjs/cli/utils/commit-manager.cjs +54 -0
- package/dist/cjs/cli/utils/migration-generator.cjs +319 -0
- package/dist/cjs/cli/utils/repo-manager.cjs +99 -3
- package/dist/cjs/cli/utils/schema-diff.cjs +390 -0
- package/dist/cjs/cli/utils/schema-hash.cjs +4 -0
- package/dist/cjs/cli/utils/schema-to-ast.cjs +477 -0
- package/dist/cjs/schema-definition/column-types.cjs +50 -4
- package/dist/cjs/schema-definition/pg-enum.cjs +10 -0
- package/dist/cjs/schema-definition/pg-function.cjs +19 -0
- package/dist/cjs/schema-definition/pg-sequence.cjs +22 -1
- package/dist/cjs/schema-definition/pg-trigger.cjs +39 -0
- package/dist/cjs/schema-definition/pg-view.cjs +17 -0
- package/dist/cjs/schema-definition/sql-expressions.cjs +3 -0
- package/dist/cjs/schema-definition/table-definition.cjs +4 -0
- package/dist/config.d.ts +98 -0
- package/dist/esm/cli/commands/commit.js +83 -3
- package/dist/esm/cli/commands/import.js +1 -0
- package/dist/esm/cli/commands/pull.js +109 -35
- package/dist/esm/cli/commands/push.js +49 -9
- package/dist/esm/cli/commands/rollback.js +206 -85
- package/dist/esm/cli/commands/schema-ast.js +183 -0
- package/dist/esm/cli/index.js +6 -0
- package/dist/esm/cli/utils/ast-codegen.js +93 -3
- package/dist/esm/cli/utils/ast-transformer.js +12 -0
- package/dist/esm/cli/utils/change-tracker.js +134 -0
- package/dist/esm/cli/utils/commit-manager.js +51 -0
- package/dist/esm/cli/utils/migration-generator.js +318 -0
- package/dist/esm/cli/utils/repo-manager.js +96 -3
- package/dist/esm/cli/utils/schema-diff.js +389 -0
- package/dist/esm/cli/utils/schema-hash.js +4 -0
- package/dist/esm/cli/utils/schema-to-ast.js +447 -0
- package/dist/esm/schema-definition/column-types.js +50 -4
- package/dist/esm/schema-definition/pg-enum.js +10 -0
- package/dist/esm/schema-definition/pg-function.js +19 -0
- package/dist/esm/schema-definition/pg-sequence.js +22 -1
- package/dist/esm/schema-definition/pg-trigger.js +39 -0
- package/dist/esm/schema-definition/pg-view.js +17 -0
- package/dist/esm/schema-definition/sql-expressions.js +3 -0
- package/dist/esm/schema-definition/table-definition.js +4 -0
- package/dist/index.d.ts +98 -0
- package/dist/schema-builder.d.ts +223 -24
- package/package.json +1 -1
|
@@ -40,8 +40,11 @@ const repo_manager_1 = require("../utils/repo-manager.cjs");
|
|
|
40
40
|
const config_1 = require("../../config/config.cjs");
|
|
41
41
|
const config_loader_1 = require("../utils/config-loader.cjs");
|
|
42
42
|
const change_tracker_1 = require("../utils/change-tracker.cjs");
|
|
43
|
+
const commit_manager_1 = require("../utils/commit-manager.cjs");
|
|
44
|
+
const schema_to_ast_1 = require("../utils/schema-to-ast.cjs");
|
|
43
45
|
const fs = __importStar(require("fs"));
|
|
44
46
|
const path = __importStar(require("path"));
|
|
47
|
+
const jiti_1 = require("jiti");
|
|
45
48
|
async function commitCommand(context) {
|
|
46
49
|
const { config, flags, args, projectRoot } = context;
|
|
47
50
|
const author = config?.author || 'Developer <dev@example.com>';
|
|
@@ -52,6 +55,9 @@ async function commitCommand(context) {
|
|
|
52
55
|
const schemaPath = path.resolve(projectRoot, (0, config_loader_1.getSchemaPath)(config ?? undefined));
|
|
53
56
|
const { requireValidSchema } = await Promise.resolve().then(() => __importStar(require("../utils/config-loader.cjs")));
|
|
54
57
|
await requireValidSchema(schemaPath, flags);
|
|
58
|
+
if (flags['from-schema']) {
|
|
59
|
+
return commitFromSchema(context, schemaPath, author);
|
|
60
|
+
}
|
|
55
61
|
const staged = (0, repo_manager_1.getStagedChanges)(projectRoot);
|
|
56
62
|
if (staged.length === 0) {
|
|
57
63
|
console.log('nothing to commit, working tree clean');
|
|
@@ -76,6 +82,8 @@ async function commitCommand(context) {
|
|
|
76
82
|
}
|
|
77
83
|
const sortedChanges = (0, change_tracker_1.sortChangesByDependency)(staged);
|
|
78
84
|
const sql = (0, change_tracker_1.generateCombinedSQL)(sortedChanges);
|
|
85
|
+
const downSQL = (0, change_tracker_1.generateDownSQL)(sortedChanges);
|
|
86
|
+
const snapshot = (0, repo_manager_1.loadSnapshot)(projectRoot);
|
|
79
87
|
const creates = staged.filter(c => c.type === 'CREATE').length;
|
|
80
88
|
const alters = staged.filter(c => c.type === 'ALTER').length;
|
|
81
89
|
const drops = staged.filter(c => c.type === 'DROP').length;
|
|
@@ -96,6 +104,8 @@ async function commitCommand(context) {
|
|
|
96
104
|
timestamp: new Date().toISOString(),
|
|
97
105
|
changes: sortedChanges,
|
|
98
106
|
sql,
|
|
107
|
+
downSQL,
|
|
108
|
+
schema: snapshot,
|
|
99
109
|
snapshotHash: hash.substring(0, 12),
|
|
100
110
|
stats: {
|
|
101
111
|
creates,
|
|
@@ -149,4 +159,74 @@ async function commitCommand(context) {
|
|
|
149
159
|
(0, cli_utils_1.hint)("run 'relq export' to export as SQL file");
|
|
150
160
|
console.log('');
|
|
151
161
|
}
|
|
162
|
+
async function commitFromSchema(context, schemaPath, author) {
|
|
163
|
+
const { config, flags, args, projectRoot } = context;
|
|
164
|
+
const spinner = (0, cli_utils_1.createSpinner)();
|
|
165
|
+
let message = flags['m'] || flags['message'];
|
|
166
|
+
if (!message) {
|
|
167
|
+
if (args.length > 0) {
|
|
168
|
+
message = args.join(' ');
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
(0, cli_utils_1.fatal)('commit message required', "usage: relq commit --from-schema -m '<message>'");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
spinner.start('Loading schema file');
|
|
175
|
+
let schemaModule;
|
|
176
|
+
try {
|
|
177
|
+
const jiti = (0, jiti_1.createJiti)(path.dirname(schemaPath), { interopDefault: true });
|
|
178
|
+
const module = await jiti.import(schemaPath);
|
|
179
|
+
if (module && module.default && typeof module.default === 'object') {
|
|
180
|
+
schemaModule = module.default;
|
|
181
|
+
}
|
|
182
|
+
else if (module && typeof module === 'object') {
|
|
183
|
+
schemaModule = module;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
throw new Error('Schema file must export an object with table/enum definitions');
|
|
187
|
+
}
|
|
188
|
+
spinner.succeed('Loaded schema file');
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
spinner.fail('Failed to load schema');
|
|
192
|
+
(0, cli_utils_1.fatal)(`Could not load schema: ${err instanceof Error ? err.message : String(err)}`);
|
|
193
|
+
}
|
|
194
|
+
spinner.start('Converting schema to AST');
|
|
195
|
+
const ast = (0, schema_to_ast_1.schemaToAST)(schemaModule);
|
|
196
|
+
spinner.succeed('Converted schema to AST');
|
|
197
|
+
const schemaHash = (0, commit_manager_1.generateASTHash)(ast);
|
|
198
|
+
spinner.start('Creating commit');
|
|
199
|
+
try {
|
|
200
|
+
const commit = (0, commit_manager_1.createCommitFromSchema)(schemaModule, author, message, config?.commitLimit ?? 1000, projectRoot);
|
|
201
|
+
spinner.succeed('Created commit');
|
|
202
|
+
const tableCount = ast.tables.length;
|
|
203
|
+
const enumCount = ast.enums.length;
|
|
204
|
+
const functionCount = ast.functions.length;
|
|
205
|
+
const viewCount = ast.views.length;
|
|
206
|
+
const triggerCount = ast.triggers.length;
|
|
207
|
+
console.log('');
|
|
208
|
+
console.log(`[${(0, repo_manager_1.shortHash)(commit.hash)}] ${message}`);
|
|
209
|
+
const statsParts = [];
|
|
210
|
+
if (tableCount > 0)
|
|
211
|
+
statsParts.push(`${tableCount} table(s)`);
|
|
212
|
+
if (enumCount > 0)
|
|
213
|
+
statsParts.push(`${enumCount} enum(s)`);
|
|
214
|
+
if (functionCount > 0)
|
|
215
|
+
statsParts.push(`${functionCount} function(s)`);
|
|
216
|
+
if (viewCount > 0)
|
|
217
|
+
statsParts.push(`${viewCount} view(s)`);
|
|
218
|
+
if (triggerCount > 0)
|
|
219
|
+
statsParts.push(`${triggerCount} trigger(s)`);
|
|
220
|
+
console.log(` ${statsParts.length > 0 ? statsParts.join(', ') : 'empty schema'}`);
|
|
221
|
+
console.log('');
|
|
222
|
+
console.log(cli_utils_1.colors.muted(`Schema hash: ${schemaHash.substring(0, 12)}`));
|
|
223
|
+
console.log('');
|
|
224
|
+
(0, cli_utils_1.hint)("run 'relq push' to apply changes to database");
|
|
225
|
+
(0, cli_utils_1.hint)("run 'relq log' to view commit history");
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
spinner.fail('Failed to create commit');
|
|
229
|
+
(0, cli_utils_1.fatal)(`Could not create commit: ${err instanceof Error ? err.message : String(err)}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
152
232
|
exports.default = commitCommand;
|
|
@@ -211,6 +211,7 @@ async function importCommand(sqlFilePath, options = {}, projectRoot = process.cw
|
|
|
211
211
|
tables: filteredTables,
|
|
212
212
|
enums: filteredEnums,
|
|
213
213
|
domains: filteredDomains,
|
|
214
|
+
compositeTypes: parsedSchema.compositeTypes || [],
|
|
214
215
|
sequences: filteredSequences,
|
|
215
216
|
views: parsedSchema.views,
|
|
216
217
|
functions: parsedSchema.functions,
|
|
@@ -375,10 +375,92 @@ async function pullCommand(context) {
|
|
|
375
375
|
(0, cli_utils_1.fatal)('You have unresolved merge conflicts', `Use ${cli_utils_1.colors.cyan('relq resolve')} to see and resolve conflicts\nOr use ${cli_utils_1.colors.cyan('relq pull --force')} to overwrite local`);
|
|
376
376
|
}
|
|
377
377
|
if (schemaExists && localSnapshot && !force) {
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
378
|
+
const localForCompare = {
|
|
379
|
+
extensions: localSnapshot.extensions?.map(e => e.name) || [],
|
|
380
|
+
enums: localSnapshot.enums || [],
|
|
381
|
+
domains: localSnapshot.domains?.map(d => ({
|
|
382
|
+
name: d.name,
|
|
383
|
+
baseType: d.baseType,
|
|
384
|
+
isNotNull: d.notNull,
|
|
385
|
+
defaultValue: d.default,
|
|
386
|
+
checkExpression: d.check,
|
|
387
|
+
})) || [],
|
|
388
|
+
compositeTypes: localSnapshot.compositeTypes || [],
|
|
389
|
+
sequences: localSnapshot.sequences || [],
|
|
390
|
+
tables: localSnapshot.tables.map(t => ({
|
|
391
|
+
name: t.name,
|
|
392
|
+
schema: t.schema,
|
|
393
|
+
columns: t.columns.map(c => ({
|
|
394
|
+
name: c.name,
|
|
395
|
+
dataType: c.type,
|
|
396
|
+
isNullable: c.nullable,
|
|
397
|
+
defaultValue: c.default,
|
|
398
|
+
isPrimaryKey: c.primaryKey,
|
|
399
|
+
isUnique: c.unique,
|
|
400
|
+
comment: c.comment,
|
|
401
|
+
})),
|
|
402
|
+
indexes: t.indexes.map(i => ({
|
|
403
|
+
name: i.name,
|
|
404
|
+
columns: i.columns,
|
|
405
|
+
isUnique: i.unique,
|
|
406
|
+
type: i.type,
|
|
407
|
+
comment: i.comment,
|
|
408
|
+
})),
|
|
409
|
+
constraints: t.constraints || [],
|
|
410
|
+
isPartitioned: t.isPartitioned,
|
|
411
|
+
partitionType: t.partitionType,
|
|
412
|
+
partitionKey: t.partitionKey,
|
|
413
|
+
comment: t.comment,
|
|
414
|
+
})),
|
|
415
|
+
functions: localSnapshot.functions || [],
|
|
416
|
+
triggers: localSnapshot.triggers || [],
|
|
417
|
+
};
|
|
418
|
+
const remoteForCompare = {
|
|
419
|
+
extensions: dbSchema.extensions || [],
|
|
420
|
+
enums: filteredEnums || [],
|
|
421
|
+
domains: filteredDomains?.map(d => ({
|
|
422
|
+
name: d.name,
|
|
423
|
+
baseType: d.baseType,
|
|
424
|
+
isNotNull: d.isNotNull,
|
|
425
|
+
defaultValue: d.defaultValue,
|
|
426
|
+
checkExpression: d.checkExpression,
|
|
427
|
+
})) || [],
|
|
428
|
+
compositeTypes: filteredCompositeTypes || [],
|
|
429
|
+
sequences: [],
|
|
430
|
+
tables: filteredTables.map(t => ({
|
|
431
|
+
name: t.name,
|
|
432
|
+
schema: t.schema,
|
|
433
|
+
columns: t.columns.map(c => ({
|
|
434
|
+
name: c.name,
|
|
435
|
+
dataType: c.dataType,
|
|
436
|
+
isNullable: c.isNullable,
|
|
437
|
+
defaultValue: c.defaultValue,
|
|
438
|
+
isPrimaryKey: c.isPrimaryKey,
|
|
439
|
+
isUnique: c.isUnique,
|
|
440
|
+
comment: c.comment,
|
|
441
|
+
})),
|
|
442
|
+
indexes: t.indexes.map(i => ({
|
|
443
|
+
name: i.name,
|
|
444
|
+
columns: i.columns,
|
|
445
|
+
isUnique: i.isUnique,
|
|
446
|
+
type: i.type,
|
|
447
|
+
comment: i.comment,
|
|
448
|
+
})),
|
|
449
|
+
constraints: t.constraints || [],
|
|
450
|
+
isPartitioned: t.isPartitioned,
|
|
451
|
+
partitionType: t.partitionType,
|
|
452
|
+
partitionKey: t.partitionKey,
|
|
453
|
+
comment: t.comment,
|
|
454
|
+
})),
|
|
455
|
+
functions: filteredFunctions || [],
|
|
456
|
+
triggers: filteredTriggers || [],
|
|
457
|
+
};
|
|
458
|
+
const allChanges = (0, schema_comparator_1.compareSchemas)(localForCompare, remoteForCompare);
|
|
459
|
+
const tablesAdded = allChanges.filter(c => c.type === 'CREATE' && c.objectType === 'TABLE').length;
|
|
460
|
+
const tablesRemoved = allChanges.filter(c => c.type === 'DROP' && c.objectType === 'TABLE').length;
|
|
461
|
+
const columnsChanged = allChanges.filter(c => c.objectType === 'COLUMN').length;
|
|
462
|
+
const indexesChanged = allChanges.filter(c => c.objectType === 'INDEX').length;
|
|
463
|
+
const otherChanges = allChanges.filter(c => c.objectType !== 'TABLE' && c.objectType !== 'COLUMN' && c.objectType !== 'INDEX').length;
|
|
382
464
|
const conflicts = detectObjectConflicts(localSnapshot, currentSchema);
|
|
383
465
|
if (conflicts.length > 0 && !force) {
|
|
384
466
|
const mergeState = {
|
|
@@ -400,26 +482,40 @@ async function pullCommand(context) {
|
|
|
400
482
|
}
|
|
401
483
|
(0, cli_utils_1.fatal)('Automatic merge failed; fix conflicts and then commit', `${cli_utils_1.colors.cyan('relq resolve --theirs <name>')} Take remote version\n${cli_utils_1.colors.cyan('relq resolve --all-theirs')} Take all remote\n${cli_utils_1.colors.cyan('relq pull --force')} Force overwrite local`);
|
|
402
484
|
}
|
|
403
|
-
if (
|
|
485
|
+
if (allChanges.length === 0) {
|
|
404
486
|
console.log('Already up to date with remote');
|
|
405
487
|
console.log('');
|
|
406
488
|
return;
|
|
407
489
|
}
|
|
408
490
|
console.log(`${cli_utils_1.colors.yellow('Remote has changes:')}`);
|
|
409
|
-
if (
|
|
410
|
-
console.log(` ${cli_utils_1.colors.green(`+${
|
|
491
|
+
if (tablesAdded > 0) {
|
|
492
|
+
console.log(` ${cli_utils_1.colors.green(`+${tablesAdded}`)} table(s) added`);
|
|
493
|
+
}
|
|
494
|
+
if (tablesRemoved > 0) {
|
|
495
|
+
console.log(` ${cli_utils_1.colors.red(`-${tablesRemoved}`)} table(s) removed`);
|
|
496
|
+
}
|
|
497
|
+
if (columnsChanged > 0) {
|
|
498
|
+
console.log(` ${cli_utils_1.colors.cyan(`~${columnsChanged}`)} column change(s)`);
|
|
411
499
|
}
|
|
412
|
-
if (
|
|
413
|
-
console.log(` ${cli_utils_1.colors.
|
|
500
|
+
if (indexesChanged > 0) {
|
|
501
|
+
console.log(` ${cli_utils_1.colors.cyan(`~${indexesChanged}`)} index change(s)`);
|
|
502
|
+
}
|
|
503
|
+
if (otherChanges > 0) {
|
|
504
|
+
console.log(` ${cli_utils_1.colors.cyan(`~${otherChanges}`)} other change(s)`);
|
|
414
505
|
}
|
|
415
506
|
console.log('');
|
|
416
|
-
|
|
507
|
+
const noAutoMerge = flags['no-auto-merge'] === true;
|
|
508
|
+
if (!dryRun && noAutoMerge) {
|
|
417
509
|
const proceed = await (0, cli_utils_1.confirm)(`${cli_utils_1.colors.bold('Pull these changes?')}`, true);
|
|
418
510
|
if (!proceed) {
|
|
419
511
|
(0, cli_utils_1.fatal)('Operation cancelled by user');
|
|
420
512
|
}
|
|
421
513
|
console.log('');
|
|
422
514
|
}
|
|
515
|
+
else if (!dryRun) {
|
|
516
|
+
console.log(`${cli_utils_1.colors.green('Auto-merging')} (no conflicts detected)`);
|
|
517
|
+
console.log('');
|
|
518
|
+
}
|
|
423
519
|
}
|
|
424
520
|
else if (schemaExists && !force) {
|
|
425
521
|
(0, cli_utils_1.warning)('Local schema exists but not tracked');
|
|
@@ -481,6 +577,7 @@ async function pullCommand(context) {
|
|
|
481
577
|
}
|
|
482
578
|
spinner.start('Generating TypeScript schema...');
|
|
483
579
|
const parsedSchema = await (0, ast_transformer_1.introspectedToParsedSchema)(dbSchema);
|
|
580
|
+
(0, ast_codegen_1.assignTrackingIds)(parsedSchema);
|
|
484
581
|
const typescript = (0, ast_codegen_1.generateTypeScriptFromAST)(parsedSchema, {
|
|
485
582
|
camelCase: config.generate?.camelCase ?? true,
|
|
486
583
|
importPath: 'relq/schema-builder',
|
|
@@ -586,7 +683,7 @@ async function pullCommand(context) {
|
|
|
586
683
|
triggers: filteredTriggers || [],
|
|
587
684
|
};
|
|
588
685
|
const schemaChanges = (0, schema_comparator_1.compareSchemas)(beforeSchema, afterSchema);
|
|
589
|
-
|
|
686
|
+
(0, ast_codegen_1.copyTrackingIdsToNormalized)(parsedSchema, currentSchema);
|
|
590
687
|
(0, repo_manager_1.saveSnapshot)(currentSchema, projectRoot);
|
|
591
688
|
const duration = Date.now() - startTime;
|
|
592
689
|
if (noCommit) {
|
|
@@ -692,26 +789,3 @@ function detectObjectConflicts(local, remote) {
|
|
|
692
789
|
}
|
|
693
790
|
return conflicts;
|
|
694
791
|
}
|
|
695
|
-
function applyTrackingIdsToSnapshot(typescript, snapshot) {
|
|
696
|
-
for (const table of snapshot.tables) {
|
|
697
|
-
const tablePattern = new RegExp(`defineTable\\s*\\(\\s*['"]${table.name}['"]\\s*,\\s*\\{[^}]+\\}\\s*,\\s*\\{[^}]*\\$trackingId:\\s*['"]([^'"]+)['"]`, 's');
|
|
698
|
-
const tableMatch = typescript.match(tablePattern);
|
|
699
|
-
if (tableMatch) {
|
|
700
|
-
table.trackingId = tableMatch[1];
|
|
701
|
-
}
|
|
702
|
-
for (const col of table.columns) {
|
|
703
|
-
const colPattern = new RegExp(`(?:${col.tsName}|${col.name}):\\s*\\w+\\([^)]*\\)[^\\n]*\\.\\\$id\\(['"]([^'"]+)['"]\\)`);
|
|
704
|
-
const colMatch = typescript.match(colPattern);
|
|
705
|
-
if (colMatch) {
|
|
706
|
-
col.trackingId = colMatch[1];
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
for (const idx of table.indexes) {
|
|
710
|
-
const idxPattern = new RegExp(`index\\s*\\(\\s*['"]${idx.name}['"]\\s*\\)[^\\n]*\\.\\\$id\\(['"]([^'"]+)['"]\\)`);
|
|
711
|
-
const idxMatch = typescript.match(idxPattern);
|
|
712
|
-
if (idxMatch) {
|
|
713
|
-
idx.trackingId = idxMatch[1];
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
@@ -52,7 +52,7 @@ async function pushCommand(context) {
|
|
|
52
52
|
const { projectRoot } = context;
|
|
53
53
|
const force = flags['force'] === true;
|
|
54
54
|
const dryRun = flags['dry-run'] === true;
|
|
55
|
-
const
|
|
55
|
+
const metadataOnly = flags['metadata-only'] === true;
|
|
56
56
|
const noVerify = flags['no-verify'] === true;
|
|
57
57
|
const skipPrompt = flags['yes'] === true || flags['y'] === true;
|
|
58
58
|
const includeFunctions = config.includeFunctions ?? false;
|
|
@@ -165,9 +165,46 @@ async function pushCommand(context) {
|
|
|
165
165
|
console.log('');
|
|
166
166
|
}
|
|
167
167
|
if (dryRun) {
|
|
168
|
-
console.log(`${cli_utils_1.colors.yellow('Dry run')} -
|
|
168
|
+
console.log(`${cli_utils_1.colors.yellow('Dry run')} - showing changes that would be applied`);
|
|
169
169
|
console.log('');
|
|
170
|
-
|
|
170
|
+
if (hasObjectsToDrop && force) {
|
|
171
|
+
console.log(`${cli_utils_1.colors.red('DROP statements:')}`);
|
|
172
|
+
for (const obj of analysis.objectsToDrop.slice(0, 5)) {
|
|
173
|
+
console.log(` ${generateDropSQL(obj)}`);
|
|
174
|
+
}
|
|
175
|
+
if (analysis.objectsToDrop.length > 5) {
|
|
176
|
+
console.log(` ${cli_utils_1.colors.muted(`... and ${analysis.objectsToDrop.length - 5} more`)}`);
|
|
177
|
+
}
|
|
178
|
+
console.log('');
|
|
179
|
+
}
|
|
180
|
+
const commitsToProcess = [...toPush].reverse();
|
|
181
|
+
let totalStatements = 0;
|
|
182
|
+
for (const commit of commitsToProcess) {
|
|
183
|
+
const commitPath = path.join(projectRoot, '.relq', 'commits', `${commit.hash}.json`);
|
|
184
|
+
if (fs.existsSync(commitPath)) {
|
|
185
|
+
const enhancedCommit = JSON.parse(fs.readFileSync(commitPath, 'utf-8'));
|
|
186
|
+
if (enhancedCommit.sql && enhancedCommit.sql.trim()) {
|
|
187
|
+
const statements = enhancedCommit.sql.split(';').filter(s => s.trim());
|
|
188
|
+
totalStatements += statements.length;
|
|
189
|
+
console.log(`${cli_utils_1.colors.cyan(`Commit ${(0, repo_manager_1.shortHash)(commit.hash)}:`)} ${commit.message}`);
|
|
190
|
+
for (const stmt of statements.slice(0, 3)) {
|
|
191
|
+
console.log(` ${stmt.trim().substring(0, 80)}${stmt.trim().length > 80 ? '...' : ''};`);
|
|
192
|
+
}
|
|
193
|
+
if (statements.length > 3) {
|
|
194
|
+
console.log(` ${cli_utils_1.colors.muted(`... and ${statements.length - 3} more statements`)}`);
|
|
195
|
+
}
|
|
196
|
+
console.log('');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (totalStatements === 0 && !hasObjectsToDrop) {
|
|
201
|
+
console.log(`${cli_utils_1.colors.muted('No SQL changes to apply')}`);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(`${cli_utils_1.colors.muted('Total:')} ${totalStatements + (hasObjectsToDrop ? analysis.objectsToDrop.length : 0)} statements`);
|
|
205
|
+
}
|
|
206
|
+
console.log('');
|
|
207
|
+
console.log(`${cli_utils_1.colors.muted('Remove')} ${cli_utils_1.colors.cyan('--dry-run')} ${cli_utils_1.colors.muted('to execute these changes.')}`);
|
|
171
208
|
console.log('');
|
|
172
209
|
return;
|
|
173
210
|
}
|
|
@@ -180,8 +217,8 @@ async function pushCommand(context) {
|
|
|
180
217
|
}
|
|
181
218
|
spinner.succeed(`Pushed ${toPush.length} commit(s) to ${(0, repo_manager_1.getConnectionLabel)(connection)}`);
|
|
182
219
|
}
|
|
183
|
-
if (
|
|
184
|
-
spinner.start('Applying
|
|
220
|
+
if (!metadataOnly && !dryRun) {
|
|
221
|
+
spinner.start('Applying schema changes...');
|
|
185
222
|
const pg = await Promise.resolve().then(() => __importStar(require("../../addon/pg/index.cjs")));
|
|
186
223
|
const client = new pg.Client({
|
|
187
224
|
host: connection.host,
|
|
@@ -218,6 +255,9 @@ async function pushCommand(context) {
|
|
|
218
255
|
}
|
|
219
256
|
await client.query('COMMIT');
|
|
220
257
|
spinner.succeed(`Applied ${statementsRun} statement(s) from ${sqlExecuted} commit(s)`);
|
|
258
|
+
for (const commit of commitsToProcess) {
|
|
259
|
+
await (0, repo_manager_1.markCommitAsApplied)(connection, commit.hash);
|
|
260
|
+
}
|
|
221
261
|
let hasRenameOperations = false;
|
|
222
262
|
for (const commit of commitsToProcess) {
|
|
223
263
|
const commitPath = path.join(projectRoot, '.relq', 'commits', `${commit.hash}.json`);
|
|
@@ -262,13 +302,13 @@ async function pushCommand(context) {
|
|
|
262
302
|
const oldHash = remoteHead ? (0, repo_manager_1.shortHash)(remoteHead) : '(none)';
|
|
263
303
|
const newHash = (0, repo_manager_1.shortHash)(localHead);
|
|
264
304
|
console.log(` ${oldHash}..${newHash} ${cli_utils_1.colors.muted('main -> main')}`);
|
|
265
|
-
if (hasObjectsToDrop && force &&
|
|
305
|
+
if (hasObjectsToDrop && force && !metadataOnly && !dryRun) {
|
|
266
306
|
console.log('');
|
|
267
307
|
(0, cli_utils_1.warning)(`Dropped ${analysis.objectsToDrop.length} object(s) from remote`);
|
|
268
308
|
}
|
|
269
|
-
if (
|
|
309
|
+
if (metadataOnly) {
|
|
270
310
|
console.log('');
|
|
271
|
-
console.log(`${cli_utils_1.colors.muted('
|
|
311
|
+
console.log(`${cli_utils_1.colors.muted('Metadata only - SQL not executed. Remove')} ${cli_utils_1.colors.cyan('--metadata-only')} ${cli_utils_1.colors.muted('to apply changes.')}`);
|
|
272
312
|
}
|
|
273
313
|
console.log('');
|
|
274
314
|
}
|