relq 1.0.1 → 1.0.3
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/addon/buffer/index.cjs +1881 -0
- package/dist/cjs/addon/pg/index.cjs +4812 -0
- package/dist/cjs/addon/pg-cursor/index.cjs +1451 -0
- package/dist/cjs/addon/pg-format/index.cjs +2270 -0
- package/dist/cjs/cli/commands/add.cjs +430 -25
- package/dist/cjs/cli/commands/branch.cjs +131 -0
- package/dist/cjs/cli/commands/checkout.cjs +121 -0
- package/dist/cjs/cli/commands/cherry-pick.cjs +282 -0
- package/dist/cjs/cli/commands/commit.cjs +21 -29
- package/dist/cjs/cli/commands/diff.cjs +144 -69
- package/dist/cjs/cli/commands/export.cjs +70 -11
- package/dist/cjs/cli/commands/fetch.cjs +42 -18
- package/dist/cjs/cli/commands/generate.cjs +28 -54
- package/dist/cjs/cli/commands/history.cjs +19 -40
- package/dist/cjs/cli/commands/import.cjs +305 -41
- package/dist/cjs/cli/commands/init.cjs +69 -59
- package/dist/cjs/cli/commands/introspect.cjs +4 -8
- package/dist/cjs/cli/commands/log.cjs +84 -15
- package/dist/cjs/cli/commands/merge.cjs +207 -0
- package/dist/cjs/cli/commands/migrate.cjs +13 -26
- package/dist/cjs/cli/commands/pull.cjs +321 -95
- package/dist/cjs/cli/commands/push.cjs +228 -52
- package/dist/cjs/cli/commands/remote.cjs +17 -0
- package/dist/cjs/cli/commands/reset.cjs +148 -0
- package/dist/cjs/cli/commands/resolve.cjs +191 -0
- package/dist/cjs/cli/commands/rollback.cjs +17 -39
- package/dist/cjs/cli/commands/stash.cjs +152 -0
- package/dist/cjs/cli/commands/status.cjs +52 -9
- package/dist/cjs/cli/commands/sync.cjs +30 -50
- package/dist/cjs/cli/commands/tag.cjs +146 -0
- package/dist/cjs/cli/index.cjs +117 -10
- package/dist/cjs/cli/utils/change-tracker.cjs +107 -3
- package/dist/cjs/cli/utils/cli-utils.cjs +217 -0
- package/dist/cjs/cli/utils/commit-manager.cjs +3 -3
- package/dist/cjs/cli/utils/config-loader.cjs +34 -8
- package/dist/cjs/cli/utils/env-loader.cjs +3 -2
- package/dist/cjs/cli/utils/fast-introspect.cjs +110 -4
- package/dist/cjs/cli/utils/git-utils.cjs +42 -161
- package/dist/cjs/cli/utils/pool-manager.cjs +156 -0
- package/dist/cjs/cli/utils/project-root.cjs +107 -0
- package/dist/cjs/cli/utils/relqignore.cjs +297 -38
- package/dist/cjs/cli/utils/repo-manager.cjs +92 -3
- package/dist/cjs/cli/utils/schema-comparator.cjs +301 -11
- package/dist/cjs/cli/utils/schema-diff.cjs +202 -1
- package/dist/cjs/cli/utils/schema-hash.cjs +2 -1
- package/dist/cjs/cli/utils/schema-introspect.cjs +9 -5
- package/dist/cjs/cli/utils/snapshot-manager.cjs +1 -0
- package/dist/cjs/cli/utils/spinner.cjs +14 -106
- package/dist/cjs/cli/utils/sql-generator.cjs +2 -2
- package/dist/cjs/cli/utils/sql-parser.cjs +94 -7
- package/dist/cjs/cli/utils/type-generator.cjs +28 -16
- package/dist/cjs/condition/array-condition-builder.cjs +1 -1
- package/dist/cjs/condition/condition-collector.cjs +1 -1
- package/dist/cjs/condition/fulltext-condition-builder.cjs +1 -1
- package/dist/cjs/condition/geometric-condition-builder.cjs +1 -1
- package/dist/cjs/condition/jsonb-condition-builder.cjs +1 -1
- package/dist/cjs/condition/network-condition-builder.cjs +1 -1
- package/dist/cjs/condition/range-condition-builder.cjs +1 -1
- package/dist/cjs/copy/copy-builder.cjs +1 -1
- package/dist/cjs/core/query-builder.cjs +1 -1
- package/dist/cjs/core/relq-client.cjs +2 -2
- package/dist/cjs/count/count-builder.cjs +1 -1
- package/dist/cjs/cte/cte-builder.cjs +1 -1
- package/dist/cjs/delete/delete-builder.cjs +1 -1
- package/dist/cjs/function/create-function-builder.cjs +1 -1
- package/dist/cjs/functions/advanced-functions.cjs +1 -1
- package/dist/cjs/functions/case-builder.cjs +1 -1
- package/dist/cjs/functions/geometric-functions.cjs +1 -1
- package/dist/cjs/functions/network-functions.cjs +1 -1
- package/dist/cjs/functions/sql-functions.cjs +1 -1
- package/dist/cjs/indexing/create-index-builder.cjs +1 -1
- package/dist/cjs/indexing/drop-index-builder.cjs +1 -1
- package/dist/cjs/insert/conflict-builder.cjs +1 -1
- package/dist/cjs/insert/insert-builder.cjs +1 -1
- package/dist/cjs/maintenance/vacuum-builder.cjs +1 -1
- package/dist/cjs/pubsub/listen-notify-builder.cjs +1 -1
- package/dist/cjs/pubsub/listener-connection.cjs +2 -2
- package/dist/cjs/raw/raw-query-builder.cjs +1 -1
- package/dist/cjs/schema/schema-builder.cjs +1 -1
- package/dist/cjs/schema-definition/table-definition.cjs +1 -1
- package/dist/cjs/select/aggregate-builder.cjs +1 -1
- package/dist/cjs/select/select-builder.cjs +1 -1
- package/dist/cjs/sequence/sequence-builder.cjs +1 -1
- package/dist/cjs/table/alter-table-builder.cjs +1 -1
- package/dist/cjs/table/constraint-builder.cjs +1 -1
- package/dist/cjs/table/create-table-builder.cjs +1 -1
- package/dist/cjs/table/partition-builder.cjs +1 -1
- package/dist/cjs/table/truncate-builder.cjs +1 -1
- package/dist/cjs/transaction/transaction-builder.cjs +1 -1
- package/dist/cjs/trigger/create-trigger-builder.cjs +1 -1
- package/dist/cjs/update/array-update-builder.cjs +1 -1
- package/dist/cjs/update/update-builder.cjs +1 -1
- package/dist/cjs/utils/index.cjs +1 -1
- package/dist/cjs/view/create-view-builder.cjs +1 -1
- package/dist/cjs/window/window-builder.cjs +1 -1
- package/dist/config.d.ts +16 -25
- package/dist/esm/cli/commands/add.js +399 -27
- package/dist/esm/cli/commands/branch.js +95 -0
- package/dist/esm/cli/commands/checkout.js +85 -0
- package/dist/esm/cli/commands/cherry-pick.js +246 -0
- package/dist/esm/cli/commands/commit.js +22 -30
- package/dist/esm/cli/commands/diff.js +144 -69
- package/dist/esm/cli/commands/export.js +71 -12
- package/dist/esm/cli/commands/fetch.js +42 -18
- package/dist/esm/cli/commands/generate.js +28 -54
- package/dist/esm/cli/commands/history.js +11 -32
- package/dist/esm/cli/commands/import.js +306 -42
- package/dist/esm/cli/commands/init.js +65 -55
- package/dist/esm/cli/commands/introspect.js +4 -8
- package/dist/esm/cli/commands/log.js +78 -10
- package/dist/esm/cli/commands/merge.js +171 -0
- package/dist/esm/cli/commands/migrate.js +13 -26
- package/dist/esm/cli/commands/pull.js +313 -87
- package/dist/esm/cli/commands/push.js +223 -47
- package/dist/esm/cli/commands/remote.js +14 -0
- package/dist/esm/cli/commands/reset.js +112 -0
- package/dist/esm/cli/commands/resolve.js +155 -0
- package/dist/esm/cli/commands/rollback.js +17 -39
- package/dist/esm/cli/commands/stash.js +116 -0
- package/dist/esm/cli/commands/status.js +20 -10
- package/dist/esm/cli/commands/sync.js +30 -50
- package/dist/esm/cli/commands/tag.js +110 -0
- package/dist/esm/cli/index.js +118 -11
- package/dist/esm/cli/utils/change-tracker.js +107 -3
- package/dist/esm/cli/utils/cli-utils.js +169 -0
- package/dist/esm/cli/utils/commit-manager.js +3 -3
- package/dist/esm/cli/utils/config-loader.js +34 -8
- package/dist/esm/cli/utils/env-loader.js +3 -2
- package/dist/esm/cli/utils/fast-introspect.js +110 -4
- package/dist/esm/cli/utils/git-utils.js +2 -124
- package/dist/esm/cli/utils/pool-manager.js +114 -0
- package/dist/esm/cli/utils/project-root.js +69 -0
- package/dist/esm/cli/utils/relqignore.js +278 -37
- package/dist/esm/cli/utils/repo-manager.js +83 -3
- package/dist/esm/cli/utils/schema-comparator.js +301 -11
- package/dist/esm/cli/utils/schema-diff.js +202 -1
- package/dist/esm/cli/utils/schema-hash.js +2 -1
- package/dist/esm/cli/utils/schema-introspect.js +9 -5
- package/dist/esm/cli/utils/snapshot-manager.js +1 -0
- package/dist/esm/cli/utils/spinner.js +1 -101
- package/dist/esm/cli/utils/sql-generator.js +2 -2
- package/dist/esm/cli/utils/sql-parser.js +94 -7
- package/dist/esm/cli/utils/type-generator.js +28 -16
- package/dist/esm/condition/array-condition-builder.js +1 -1
- package/dist/esm/condition/condition-collector.js +1 -1
- package/dist/esm/condition/fulltext-condition-builder.js +1 -1
- package/dist/esm/condition/geometric-condition-builder.js +1 -1
- package/dist/esm/condition/jsonb-condition-builder.js +1 -1
- package/dist/esm/condition/network-condition-builder.js +1 -1
- package/dist/esm/condition/range-condition-builder.js +1 -1
- package/dist/esm/copy/copy-builder.js +1 -1
- package/dist/esm/core/query-builder.js +1 -1
- package/dist/esm/core/relq-client.js +2 -2
- package/dist/esm/count/count-builder.js +1 -1
- package/dist/esm/cte/cte-builder.js +1 -1
- package/dist/esm/delete/delete-builder.js +1 -1
- package/dist/esm/function/create-function-builder.js +1 -1
- package/dist/esm/functions/advanced-functions.js +1 -1
- package/dist/esm/functions/case-builder.js +1 -1
- package/dist/esm/functions/geometric-functions.js +1 -1
- package/dist/esm/functions/network-functions.js +1 -1
- package/dist/esm/functions/sql-functions.js +1 -1
- package/dist/esm/indexing/create-index-builder.js +1 -1
- package/dist/esm/indexing/drop-index-builder.js +1 -1
- package/dist/esm/insert/conflict-builder.js +1 -1
- package/dist/esm/insert/insert-builder.js +1 -1
- package/dist/esm/maintenance/vacuum-builder.js +1 -1
- package/dist/esm/pubsub/listen-notify-builder.js +1 -1
- package/dist/esm/pubsub/listener-connection.js +2 -2
- package/dist/esm/raw/raw-query-builder.js +1 -1
- package/dist/esm/schema/schema-builder.js +1 -1
- package/dist/esm/schema-definition/table-definition.js +1 -1
- package/dist/esm/select/aggregate-builder.js +1 -1
- package/dist/esm/select/select-builder.js +1 -1
- package/dist/esm/sequence/sequence-builder.js +1 -1
- package/dist/esm/table/alter-table-builder.js +1 -1
- package/dist/esm/table/constraint-builder.js +1 -1
- package/dist/esm/table/create-table-builder.js +1 -1
- package/dist/esm/table/partition-builder.js +1 -1
- package/dist/esm/table/truncate-builder.js +1 -1
- package/dist/esm/transaction/transaction-builder.js +1 -1
- package/dist/esm/trigger/create-trigger-builder.js +1 -1
- package/dist/esm/update/array-update-builder.js +1 -1
- package/dist/esm/update/update-builder.js +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/view/create-view-builder.js +1 -1
- package/dist/esm/window/window-builder.js +1 -1
- package/dist/index.d.ts +25 -8
- package/dist/schema-builder.d.ts +16 -6
- package/package.json +1 -1
- /package/dist/{addons/buffer.js → esm/addon/buffer/index.js} +0 -0
- /package/dist/{addons/pg.js → esm/addon/pg/index.js} +0 -0
- /package/dist/{addons/pg-cursor.js → esm/addon/pg-cursor/index.js} +0 -0
- /package/dist/{addons/pg-format.js → esm/addon/pg-format/index.js} +0 -0
|
@@ -37,27 +37,19 @@ exports.historyCommand = historyCommand;
|
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const config_loader_1 = require("../utils/config-loader.cjs");
|
|
39
39
|
const env_loader_1 = require("../utils/env-loader.cjs");
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
bold: '\x1b[1m',
|
|
43
|
-
dim: '\x1b[2m',
|
|
44
|
-
red: '\x1b[31m',
|
|
45
|
-
green: '\x1b[32m',
|
|
46
|
-
yellow: '\x1b[33m',
|
|
47
|
-
cyan: '\x1b[36m',
|
|
48
|
-
};
|
|
40
|
+
const cli_utils_1 = require("../utils/cli-utils.cjs");
|
|
41
|
+
const pool_manager_1 = require("../utils/pool-manager.cjs");
|
|
49
42
|
async function historyCommand(context) {
|
|
50
43
|
const { config, flags } = context;
|
|
51
44
|
if (!config) {
|
|
52
|
-
|
|
53
|
-
process.exit(1);
|
|
45
|
+
(0, cli_utils_1.fatal)('No configuration found', `run ${cli_utils_1.colors.cyan('relq init')} to create a configuration file`);
|
|
54
46
|
}
|
|
55
|
-
(0, config_loader_1.requireValidConfig)(config);
|
|
47
|
+
await (0, config_loader_1.requireValidConfig)(config, { calledFrom: 'history' });
|
|
56
48
|
const connection = config.connection;
|
|
57
49
|
const migrationsDir = config.migrations?.directory || './migrations';
|
|
58
50
|
const tableName = config.migrations?.tableName || '_relq_migrations';
|
|
59
51
|
const limit = parseInt(flags['n']) || 20;
|
|
60
|
-
console.log(
|
|
52
|
+
console.log('Migration History');
|
|
61
53
|
console.log(`Database: ${(0, env_loader_1.getConnectionDescription)(connection)}`);
|
|
62
54
|
console.log('');
|
|
63
55
|
try {
|
|
@@ -76,42 +68,41 @@ async function historyCommand(context) {
|
|
|
76
68
|
const toShow = history.slice(0, limit);
|
|
77
69
|
const pendingCount = history.filter(h => h.pending).length;
|
|
78
70
|
const appliedCount = history.filter(h => !h.pending).length;
|
|
79
|
-
console.log(
|
|
80
|
-
console.log(`${
|
|
71
|
+
console.log(`Showing ${toShow.length} of ${history.length} migrations`);
|
|
72
|
+
console.log(`${appliedCount} applied, ${pendingCount} pending`);
|
|
81
73
|
console.log('');
|
|
82
74
|
for (const record of toShow) {
|
|
83
75
|
if (record.pending) {
|
|
84
|
-
console.log(`${colors.yellow}○ ${record.name}${colors.reset} ${colors.dim}(pending)${colors.reset}`);
|
|
76
|
+
console.log(`${cli_utils_1.colors.yellow}○ ${record.name}${cli_utils_1.colors.reset} ${cli_utils_1.colors.dim}(pending)${cli_utils_1.colors.reset}`);
|
|
85
77
|
}
|
|
86
78
|
else {
|
|
87
79
|
const date = record.appliedAt ? formatDate(record.appliedAt) : '';
|
|
88
|
-
console.log(`${colors.green}● ${record.name}${colors.reset} ${colors.dim}${date}${colors.reset}`);
|
|
80
|
+
console.log(`${cli_utils_1.colors.green}● ${record.name}${cli_utils_1.colors.reset} ${cli_utils_1.colors.dim}${date}${cli_utils_1.colors.reset}`);
|
|
89
81
|
}
|
|
90
82
|
}
|
|
91
83
|
if (history.length > limit) {
|
|
92
84
|
console.log('');
|
|
93
|
-
console.log(`${colors.dim}Use "relq history -n ${history.length}" to see all.${colors.reset}`);
|
|
85
|
+
console.log(`${cli_utils_1.colors.dim}Use "relq history -n ${history.length}" to see all.${cli_utils_1.colors.reset}`);
|
|
94
86
|
}
|
|
95
87
|
}
|
|
96
88
|
catch (error) {
|
|
97
89
|
if (error?.code === '42P01') {
|
|
98
|
-
console.log(`${colors.yellow}No migration table found.${colors.reset}`);
|
|
99
|
-
console.log(`Run "${colors.cyan}relq push${colors.reset}" to initialize.`);
|
|
90
|
+
console.log(`${cli_utils_1.colors.yellow}No migration table found.${cli_utils_1.colors.reset}`);
|
|
91
|
+
console.log(`Run "${cli_utils_1.colors.cyan}relq push${cli_utils_1.colors.reset}" to initialize.`);
|
|
100
92
|
console.log('');
|
|
101
93
|
const files = getMigrationFiles(migrationsDir);
|
|
102
94
|
if (files.length > 0) {
|
|
103
|
-
console.log(`${colors.bold}Pending migrations:${colors.reset}`);
|
|
95
|
+
console.log(`${cli_utils_1.colors.bold}Pending migrations:${cli_utils_1.colors.reset}`);
|
|
104
96
|
for (const file of files.slice(0, limit)) {
|
|
105
|
-
console.log(` ${colors.yellow}○ ${file}${colors.reset}`);
|
|
97
|
+
console.log(` ${cli_utils_1.colors.yellow}○ ${file}${cli_utils_1.colors.reset}`);
|
|
106
98
|
}
|
|
107
99
|
}
|
|
108
100
|
else {
|
|
109
|
-
console.log(`${colors.dim}No migration files found.${colors.reset}`);
|
|
101
|
+
console.log(`${cli_utils_1.colors.dim}No migration files found.${cli_utils_1.colors.reset}`);
|
|
110
102
|
}
|
|
111
103
|
return;
|
|
112
104
|
}
|
|
113
|
-
|
|
114
|
-
process.exit(1);
|
|
105
|
+
(0, cli_utils_1.fatal)('Failed to load history', error instanceof Error ? error.message : String(error));
|
|
115
106
|
}
|
|
116
107
|
}
|
|
117
108
|
function getMigrationFiles(migrationsDir) {
|
|
@@ -123,29 +114,17 @@ function getMigrationFiles(migrationsDir) {
|
|
|
123
114
|
.sort();
|
|
124
115
|
}
|
|
125
116
|
async function getAppliedMigrations(connection, tableName) {
|
|
126
|
-
|
|
127
|
-
const pool = new Pool({
|
|
128
|
-
host: connection.host,
|
|
129
|
-
port: connection.port || 5432,
|
|
130
|
-
database: connection.database,
|
|
131
|
-
user: connection.user,
|
|
132
|
-
password: connection.password,
|
|
133
|
-
connectionString: connection.url,
|
|
134
|
-
});
|
|
135
|
-
try {
|
|
117
|
+
return (0, pool_manager_1.withPool)(connection, async (pool) => {
|
|
136
118
|
const result = await pool.query(`
|
|
137
119
|
SELECT name, applied_at
|
|
138
120
|
FROM "${tableName}"
|
|
139
121
|
ORDER BY id DESC;
|
|
140
122
|
`);
|
|
141
|
-
return result.rows.map(r => ({
|
|
123
|
+
return result.rows.map((r) => ({
|
|
142
124
|
name: r.name,
|
|
143
125
|
appliedAt: new Date(r.applied_at),
|
|
144
126
|
}));
|
|
145
|
-
}
|
|
146
|
-
finally {
|
|
147
|
-
await pool.end();
|
|
148
|
-
}
|
|
127
|
+
});
|
|
149
128
|
}
|
|
150
129
|
function formatDate(date) {
|
|
151
130
|
const now = new Date();
|
|
@@ -41,27 +41,24 @@ const type_generator_1 = require("../utils/type-generator.cjs");
|
|
|
41
41
|
const repo_manager_1 = require("../utils/repo-manager.cjs");
|
|
42
42
|
const schema_comparator_1 = require("../utils/schema-comparator.cjs");
|
|
43
43
|
const change_tracker_1 = require("../utils/change-tracker.cjs");
|
|
44
|
+
const relqignore_1 = require("../utils/relqignore.cjs");
|
|
44
45
|
const git_utils_1 = require("../utils/git-utils.cjs");
|
|
45
|
-
async function importCommand(sqlFilePath, options = {}) {
|
|
46
|
+
async function importCommand(sqlFilePath, options = {}, projectRoot = process.cwd()) {
|
|
46
47
|
const { includeFunctions = false, includeTriggers = false, force = false, dryRun = false } = options;
|
|
47
|
-
const projectRoot = process.cwd();
|
|
48
48
|
const spinner = (0, git_utils_1.createSpinner)();
|
|
49
49
|
console.log('');
|
|
50
50
|
if (!sqlFilePath) {
|
|
51
|
-
(0, git_utils_1.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
console.log(' --include-functions Include functions in import');
|
|
63
|
-
console.log(' --include-triggers Include triggers in import');
|
|
64
|
-
process.exit(1);
|
|
51
|
+
(0, git_utils_1.fatal)('No SQL file specified', 'usage: relq import <sql-file> [options]\n\n' +
|
|
52
|
+
'Options:\n' +
|
|
53
|
+
' --output <path> Output schema file path\n' +
|
|
54
|
+
' --force Force import, overwrite local changes\n' +
|
|
55
|
+
' --dry-run Preview changes without applying\n' +
|
|
56
|
+
' --theirs Accept all incoming changes\n' +
|
|
57
|
+
' --ours Keep all local changes (reject incoming)\n' +
|
|
58
|
+
' --abort Abort the import operation\n' +
|
|
59
|
+
' --include-functions Include functions in import\n' +
|
|
60
|
+
' --include-triggers Include triggers in import');
|
|
61
|
+
return;
|
|
65
62
|
}
|
|
66
63
|
if (options.abort) {
|
|
67
64
|
console.log('Aborting import...');
|
|
@@ -84,11 +81,8 @@ async function importCommand(sqlFilePath, options = {}) {
|
|
|
84
81
|
(0, git_utils_1.warning)(warn);
|
|
85
82
|
}
|
|
86
83
|
if (!validation.valid) {
|
|
87
|
-
(0, git_utils_1.
|
|
88
|
-
|
|
89
|
-
console.log(` - ${err}`);
|
|
90
|
-
}
|
|
91
|
-
process.exit(1);
|
|
84
|
+
(0, git_utils_1.fatal)('Invalid PostgreSQL SQL file', validation.errors.join('\n - '));
|
|
85
|
+
return;
|
|
92
86
|
}
|
|
93
87
|
console.log(`Importing ${git_utils_1.colors.cyan(path.basename(sqlFilePath))} ${git_utils_1.colors.gray(`(${(0, git_utils_1.formatBytes)(sqlContent.length)})`)}`);
|
|
94
88
|
console.log('');
|
|
@@ -103,7 +97,8 @@ async function importCommand(sqlFilePath, options = {}) {
|
|
|
103
97
|
(0, git_utils_1.printDirtyWorkingTreeError)(status, 'import');
|
|
104
98
|
console.log('');
|
|
105
99
|
(0, git_utils_1.printMergeStrategyHelp)();
|
|
106
|
-
|
|
100
|
+
(0, git_utils_1.fatal)('Working tree is not clean', 'Commit or stash your changes before importing.');
|
|
101
|
+
return;
|
|
107
102
|
}
|
|
108
103
|
}
|
|
109
104
|
spinner.start('Parsing SQL schema');
|
|
@@ -144,26 +139,138 @@ async function importCommand(sqlFilePath, options = {}) {
|
|
|
144
139
|
}
|
|
145
140
|
}
|
|
146
141
|
console.log('');
|
|
142
|
+
const ignorePatterns = (0, relqignore_1.loadRelqignore)(projectRoot);
|
|
143
|
+
let ignoredCount = 0;
|
|
144
|
+
const filteredTables = parsedSchema.tables.filter(table => {
|
|
145
|
+
if ((0, relqignore_1.isTableIgnored)(table.name, ignorePatterns).ignored) {
|
|
146
|
+
ignoredCount++;
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}).map(table => {
|
|
151
|
+
const filteredColumns = table.columns.filter(col => {
|
|
152
|
+
if ((0, relqignore_1.isColumnIgnored)(table.name, col.name, ignorePatterns).ignored) {
|
|
153
|
+
ignoredCount++;
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
});
|
|
158
|
+
const filteredIndexes = table.indexes.filter(idx => {
|
|
159
|
+
if ((0, relqignore_1.isIndexIgnored)(table.name, idx.name, ignorePatterns).ignored) {
|
|
160
|
+
ignoredCount++;
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
});
|
|
165
|
+
const filteredConstraints = table.constraints.filter(con => {
|
|
166
|
+
if ((0, relqignore_1.isConstraintIgnored)(table.name, con.name, ignorePatterns).ignored) {
|
|
167
|
+
ignoredCount++;
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
return true;
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
...table,
|
|
174
|
+
columns: filteredColumns,
|
|
175
|
+
indexes: filteredIndexes,
|
|
176
|
+
constraints: filteredConstraints,
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
const filteredEnums = parsedSchema.enums.filter(e => {
|
|
180
|
+
if ((0, relqignore_1.isEnumIgnored)(e.name, ignorePatterns).ignored) {
|
|
181
|
+
ignoredCount++;
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return true;
|
|
185
|
+
});
|
|
186
|
+
const filteredDomains = parsedSchema.domains.filter(d => {
|
|
187
|
+
if ((0, relqignore_1.isDomainIgnored)(d.name, ignorePatterns).ignored) {
|
|
188
|
+
ignoredCount++;
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
return true;
|
|
192
|
+
});
|
|
193
|
+
const filteredCompositeTypes = parsedSchema.compositeTypes.filter(c => {
|
|
194
|
+
if ((0, relqignore_1.isCompositeTypeIgnored)(c.name, ignorePatterns).ignored) {
|
|
195
|
+
ignoredCount++;
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
});
|
|
200
|
+
const filteredSequences = parsedSchema.sequences.filter(s => {
|
|
201
|
+
if ((0, relqignore_1.isSequenceIgnored)(s.name, ignorePatterns).ignored) {
|
|
202
|
+
ignoredCount++;
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
return true;
|
|
206
|
+
});
|
|
207
|
+
const filteredFunctions = functions.filter(f => {
|
|
208
|
+
if ((0, relqignore_1.isFunctionIgnored)(f.name, ignorePatterns).ignored) {
|
|
209
|
+
ignoredCount++;
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
});
|
|
214
|
+
const filteredSchema = {
|
|
215
|
+
tables: filteredTables,
|
|
216
|
+
enums: filteredEnums,
|
|
217
|
+
domains: filteredDomains,
|
|
218
|
+
compositeTypes: filteredCompositeTypes,
|
|
219
|
+
sequences: filteredSequences,
|
|
220
|
+
collations: parsedSchema.collations,
|
|
221
|
+
foreignTables: parsedSchema.foreignTables,
|
|
222
|
+
views: parsedSchema.views,
|
|
223
|
+
materializedViews: parsedSchema.materializedViews,
|
|
224
|
+
foreignServers: parsedSchema.foreignServers,
|
|
225
|
+
extensions: parsedSchema.extensions,
|
|
226
|
+
partitions: parsedSchema.partitions,
|
|
227
|
+
};
|
|
228
|
+
if (ignoredCount > 0) {
|
|
229
|
+
console.log(`${ignoredCount} object(s) ignored by .relqignore`);
|
|
230
|
+
}
|
|
231
|
+
const dependencyErrors = (0, relqignore_1.validateIgnoreDependencies)({
|
|
232
|
+
tables: filteredTables.map(t => ({
|
|
233
|
+
name: t.name,
|
|
234
|
+
columns: t.columns.map(c => ({
|
|
235
|
+
name: c.name,
|
|
236
|
+
type: c.dataType,
|
|
237
|
+
default: c.defaultValue,
|
|
238
|
+
})),
|
|
239
|
+
})),
|
|
240
|
+
enums: parsedSchema.enums,
|
|
241
|
+
domains: parsedSchema.domains,
|
|
242
|
+
sequences: parsedSchema.sequences,
|
|
243
|
+
compositeTypes: parsedSchema.compositeTypes,
|
|
244
|
+
}, ignorePatterns);
|
|
245
|
+
if (dependencyErrors.length > 0) {
|
|
246
|
+
spinner.stop();
|
|
247
|
+
const errorMessages = dependencyErrors.map(e => e.message).join('\n ');
|
|
248
|
+
(0, git_utils_1.fatal)('Dependency validation failed', `${errorMessages}\n\nEither un-ignore the type or add the column to .relqignore`);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
147
251
|
spinner.start('Generating TypeScript schema');
|
|
148
|
-
const dbSchema = convertToDbSchema(
|
|
252
|
+
const dbSchema = convertToDbSchema(filteredSchema, filteredFunctions, triggers, comments);
|
|
149
253
|
const typescriptContent = (0, type_generator_1.generateTypeScript)(dbSchema, {
|
|
150
254
|
camelCase: true,
|
|
151
255
|
includeFunctions,
|
|
152
256
|
includeTriggers,
|
|
153
257
|
});
|
|
154
258
|
spinner.succeed('Generated TypeScript schema');
|
|
155
|
-
const
|
|
259
|
+
const incomingSchema = convertToNormalizedSchema(filteredSchema, filteredFunctions, triggers);
|
|
156
260
|
const existingSnapshot = (0, repo_manager_1.loadSnapshot)(projectRoot);
|
|
261
|
+
const replaceAll = options.theirs === true;
|
|
262
|
+
let mergedSchema;
|
|
157
263
|
let changes = [];
|
|
158
264
|
if (existingSnapshot) {
|
|
159
265
|
spinner.start('Detecting changes');
|
|
266
|
+
mergedSchema = mergeSchemas(existingSnapshot, incomingSchema, replaceAll);
|
|
160
267
|
const beforeSchema = snapshotToDbSchema(existingSnapshot);
|
|
161
|
-
const afterSchema = snapshotToDbSchema(
|
|
268
|
+
const afterSchema = snapshotToDbSchema(mergedSchema);
|
|
162
269
|
changes = (0, schema_comparator_1.compareSchemas)(beforeSchema, afterSchema);
|
|
163
270
|
spinner.stop();
|
|
164
271
|
if (changes.length > 0) {
|
|
165
272
|
console.log('');
|
|
166
|
-
console.log(`${git_utils_1.colors.bold('Changes detected:')}`);
|
|
273
|
+
console.log(`${git_utils_1.colors.bold('Changes detected:')}${replaceAll ? git_utils_1.colors.yellow(' (--theirs: full replacement)') : ''}`);
|
|
167
274
|
console.log('');
|
|
168
275
|
const creates = changes.filter(c => c.type === 'CREATE');
|
|
169
276
|
const alters = changes.filter(c => c.type === 'ALTER');
|
|
@@ -185,11 +292,17 @@ async function importCommand(sqlFilePath, options = {}) {
|
|
|
185
292
|
}
|
|
186
293
|
}
|
|
187
294
|
if (drops.length > 0) {
|
|
188
|
-
|
|
189
|
-
|
|
295
|
+
if (replaceAll) {
|
|
296
|
+
for (const change of drops.slice(0, 10)) {
|
|
297
|
+
console.log(`\t${git_utils_1.colors.red((0, change_tracker_1.getChangeDisplayName)(change))}`);
|
|
298
|
+
}
|
|
299
|
+
if (drops.length > 10) {
|
|
300
|
+
console.log(`\t${git_utils_1.colors.gray(`... and ${drops.length - 10} more deletions`)}`);
|
|
301
|
+
}
|
|
190
302
|
}
|
|
191
|
-
|
|
192
|
-
console.log(
|
|
303
|
+
else {
|
|
304
|
+
console.log('');
|
|
305
|
+
console.log(`${drops.length} object(s) only in existing schema (preserved)`);
|
|
193
306
|
}
|
|
194
307
|
}
|
|
195
308
|
console.log('');
|
|
@@ -201,16 +314,25 @@ async function importCommand(sqlFilePath, options = {}) {
|
|
|
201
314
|
}
|
|
202
315
|
}
|
|
203
316
|
else {
|
|
317
|
+
mergedSchema = incomingSchema;
|
|
204
318
|
changes = [];
|
|
205
319
|
console.log(`${git_utils_1.colors.cyan('First import')} - creating initial snapshot`);
|
|
206
320
|
}
|
|
321
|
+
const mergedDbSchema = snapshotToDbSchemaForGeneration(mergedSchema);
|
|
322
|
+
const finalTypescriptContent = (0, type_generator_1.generateTypeScript)(mergedDbSchema, {
|
|
323
|
+
camelCase: true,
|
|
324
|
+
includeFunctions,
|
|
325
|
+
includeTriggers,
|
|
326
|
+
});
|
|
207
327
|
if (dryRun) {
|
|
208
328
|
console.log('');
|
|
209
329
|
console.log(`${git_utils_1.colors.yellow('Dry run mode')} - no files written`);
|
|
210
330
|
console.log('');
|
|
211
331
|
console.log('Would write:');
|
|
212
|
-
|
|
213
|
-
|
|
332
|
+
const dryRunOutputPath = options.output || './db/schema.ts';
|
|
333
|
+
const dryRunAbsPath = path.resolve(projectRoot, dryRunOutputPath);
|
|
334
|
+
console.log(` ${git_utils_1.colors.cyan(dryRunAbsPath)} ${git_utils_1.colors.gray(`(${(0, git_utils_1.formatBytes)(finalTypescriptContent.length)})`)}`);
|
|
335
|
+
console.log(` ${git_utils_1.colors.cyan(path.join(projectRoot, '.relq/snapshot.json'))}`);
|
|
214
336
|
if (changes.length > 0) {
|
|
215
337
|
console.log(` Stage ${changes.length} change(s)`);
|
|
216
338
|
}
|
|
@@ -218,29 +340,29 @@ async function importCommand(sqlFilePath, options = {}) {
|
|
|
218
340
|
return;
|
|
219
341
|
}
|
|
220
342
|
const outputPath = options.output || './db/schema.ts';
|
|
221
|
-
const absoluteOutputPath = path.resolve(outputPath);
|
|
343
|
+
const absoluteOutputPath = path.resolve(projectRoot, outputPath);
|
|
222
344
|
const outputDir = path.dirname(absoluteOutputPath);
|
|
223
345
|
if (!fs.existsSync(outputDir)) {
|
|
224
346
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
225
347
|
}
|
|
226
|
-
fs.writeFileSync(absoluteOutputPath,
|
|
227
|
-
console.log(`Written ${git_utils_1.colors.cyan(
|
|
228
|
-
(0, repo_manager_1.saveSnapshot)(
|
|
348
|
+
fs.writeFileSync(absoluteOutputPath, finalTypescriptContent, 'utf-8');
|
|
349
|
+
console.log(`Written ${git_utils_1.colors.cyan(absoluteOutputPath)} ${git_utils_1.colors.gray(`(${(0, git_utils_1.formatBytes)(finalTypescriptContent.length)})`)}`);
|
|
350
|
+
(0, repo_manager_1.saveSnapshot)(mergedSchema, projectRoot);
|
|
229
351
|
if (changes.length > 0) {
|
|
230
352
|
(0, repo_manager_1.addUnstagedChanges)(changes, projectRoot);
|
|
231
353
|
(0, repo_manager_1.stageChanges)(['.'], projectRoot);
|
|
232
354
|
console.log('');
|
|
233
|
-
console.log(`${
|
|
355
|
+
console.log(`${changes.length} change(s) staged for commit`);
|
|
234
356
|
}
|
|
235
357
|
console.log('');
|
|
236
|
-
console.log(
|
|
358
|
+
console.log('Import successful.');
|
|
237
359
|
console.log('');
|
|
238
360
|
if (changes.length > 0) {
|
|
239
|
-
(0, git_utils_1.hint)('
|
|
240
|
-
(0, git_utils_1.hint)('
|
|
361
|
+
(0, git_utils_1.hint)("run 'relq status' to see staged changes");
|
|
362
|
+
(0, git_utils_1.hint)("run 'relq commit -m <message>' to commit");
|
|
241
363
|
}
|
|
242
364
|
else {
|
|
243
|
-
(0, git_utils_1.hint)('
|
|
365
|
+
(0, git_utils_1.hint)("run 'relq status' to see current state");
|
|
244
366
|
}
|
|
245
367
|
console.log('');
|
|
246
368
|
}
|
|
@@ -337,6 +459,7 @@ function convertToDbSchema(parsed, functions = [], triggers = [], comments = [])
|
|
|
337
459
|
cycle: s.cycle,
|
|
338
460
|
ownedBy: s.ownedBy,
|
|
339
461
|
})) || [],
|
|
462
|
+
collations: [],
|
|
340
463
|
extensions: parsed.extensions,
|
|
341
464
|
partitions: parsed.partitions,
|
|
342
465
|
functions: functions.map(f => ({
|
|
@@ -442,6 +565,17 @@ function convertToNormalizedSchema(parsed, functions = [], triggers = []) {
|
|
|
442
565
|
forEach: 'STATEMENT',
|
|
443
566
|
functionName: t.functionName || '',
|
|
444
567
|
})),
|
|
568
|
+
views: parsed.views.map(v => ({
|
|
569
|
+
name: v.name,
|
|
570
|
+
schema: v.schema || 'public',
|
|
571
|
+
definition: v.definition,
|
|
572
|
+
})),
|
|
573
|
+
materializedViews: parsed.materializedViews.map(mv => ({
|
|
574
|
+
name: mv.name,
|
|
575
|
+
schema: mv.schema || 'public',
|
|
576
|
+
definition: mv.definition,
|
|
577
|
+
withData: mv.withData ?? true,
|
|
578
|
+
})),
|
|
445
579
|
};
|
|
446
580
|
}
|
|
447
581
|
function snapshotToDbSchema(snapshot) {
|
|
@@ -521,4 +655,134 @@ function snapshotToDbSchema(snapshot) {
|
|
|
521
655
|
sequences: [],
|
|
522
656
|
});
|
|
523
657
|
}
|
|
658
|
+
function snapshotToDbSchemaForGeneration(snapshot) {
|
|
659
|
+
return {
|
|
660
|
+
tables: snapshot.tables.map(t => ({
|
|
661
|
+
name: t.name,
|
|
662
|
+
schema: t.schema || 'public',
|
|
663
|
+
comment: null,
|
|
664
|
+
columns: t.columns.map(c => ({
|
|
665
|
+
name: c.name,
|
|
666
|
+
dataType: c.type,
|
|
667
|
+
udtName: c.type,
|
|
668
|
+
isNullable: c.nullable,
|
|
669
|
+
defaultValue: c.default ?? null,
|
|
670
|
+
isPrimaryKey: c.primaryKey || false,
|
|
671
|
+
isUnique: c.unique || false,
|
|
672
|
+
maxLength: null,
|
|
673
|
+
precision: null,
|
|
674
|
+
scale: null,
|
|
675
|
+
references: null,
|
|
676
|
+
comment: null,
|
|
677
|
+
isGenerated: c.isGenerated || false,
|
|
678
|
+
generationExpression: c.generationExpression || null,
|
|
679
|
+
identityGeneration: c.identity?.type || null,
|
|
680
|
+
})),
|
|
681
|
+
indexes: t.indexes.map(i => ({
|
|
682
|
+
name: i.name,
|
|
683
|
+
columns: Array.isArray(i.columns) ? i.columns : [i.columns],
|
|
684
|
+
isUnique: i.unique || false,
|
|
685
|
+
isPrimary: false,
|
|
686
|
+
type: i.type || 'btree',
|
|
687
|
+
definition: i.definition,
|
|
688
|
+
whereClause: i.whereClause,
|
|
689
|
+
comment: null,
|
|
690
|
+
})),
|
|
691
|
+
constraints: t.constraints?.map(c => ({
|
|
692
|
+
name: c.name,
|
|
693
|
+
type: c.type,
|
|
694
|
+
columns: [],
|
|
695
|
+
definition: c.definition,
|
|
696
|
+
})) || [],
|
|
697
|
+
rowCount: 0,
|
|
698
|
+
isPartitioned: t.isPartitioned || false,
|
|
699
|
+
partitionType: t.partitionType,
|
|
700
|
+
partitionKey: t.partitionKey ? [t.partitionKey].flat() : undefined,
|
|
701
|
+
})),
|
|
702
|
+
enums: snapshot.enums?.map(e => ({
|
|
703
|
+
name: e.name,
|
|
704
|
+
values: e.values,
|
|
705
|
+
})) || [],
|
|
706
|
+
domains: snapshot.domains?.map(d => ({
|
|
707
|
+
name: d.name,
|
|
708
|
+
baseType: d.baseType,
|
|
709
|
+
isNotNull: d.notNull || false,
|
|
710
|
+
defaultValue: d.default || null,
|
|
711
|
+
checkExpression: d.check || null,
|
|
712
|
+
check: d.check,
|
|
713
|
+
default: d.default,
|
|
714
|
+
notNull: d.notNull,
|
|
715
|
+
})) || [],
|
|
716
|
+
compositeTypes: snapshot.compositeTypes?.map(c => ({
|
|
717
|
+
name: c.name,
|
|
718
|
+
attributes: c.attributes || [],
|
|
719
|
+
})) || [],
|
|
720
|
+
sequences: snapshot.sequences?.map(s => ({
|
|
721
|
+
name: s.name,
|
|
722
|
+
dataType: s.dataType,
|
|
723
|
+
start: s.startValue,
|
|
724
|
+
increment: s.increment,
|
|
725
|
+
minValue: s.minValue,
|
|
726
|
+
maxValue: s.maxValue,
|
|
727
|
+
cache: s.cache,
|
|
728
|
+
cycle: s.cycle,
|
|
729
|
+
ownedBy: s.ownedBy ?? undefined,
|
|
730
|
+
})) || [],
|
|
731
|
+
collations: [],
|
|
732
|
+
extensions: (snapshot.extensions || []).map(e => typeof e === 'string' ? e : e.name),
|
|
733
|
+
partitions: [],
|
|
734
|
+
functions: snapshot.functions?.map(f => ({
|
|
735
|
+
name: f.name,
|
|
736
|
+
schema: 'public',
|
|
737
|
+
returnType: f.returnType,
|
|
738
|
+
argTypes: f.argTypes || [],
|
|
739
|
+
language: f.language,
|
|
740
|
+
definition: '',
|
|
741
|
+
isAggregate: false,
|
|
742
|
+
volatility: 'VOLATILE',
|
|
743
|
+
})) || [],
|
|
744
|
+
triggers: snapshot.triggers?.map(t => ({
|
|
745
|
+
name: t.name,
|
|
746
|
+
tableName: t.table,
|
|
747
|
+
timing: t.timing,
|
|
748
|
+
event: t.events?.[0] || '',
|
|
749
|
+
functionName: t.functionName || '',
|
|
750
|
+
definition: '',
|
|
751
|
+
isEnabled: t.isEnabled ?? true,
|
|
752
|
+
})) || [],
|
|
753
|
+
policies: [],
|
|
754
|
+
foreignServers: [],
|
|
755
|
+
foreignTables: [],
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
function mergeSchemas(existing, incoming, replaceAll = false) {
|
|
759
|
+
if (replaceAll) {
|
|
760
|
+
return incoming;
|
|
761
|
+
}
|
|
762
|
+
function mergeByName(existingArr, incomingArr) {
|
|
763
|
+
const incomingMap = new Map(incomingArr.map(item => [item.name, item]));
|
|
764
|
+
const resultMap = new Map();
|
|
765
|
+
for (const item of existingArr) {
|
|
766
|
+
resultMap.set(item.name, item);
|
|
767
|
+
}
|
|
768
|
+
for (const item of incomingArr) {
|
|
769
|
+
resultMap.set(item.name, item);
|
|
770
|
+
}
|
|
771
|
+
return Array.from(resultMap.values());
|
|
772
|
+
}
|
|
773
|
+
return {
|
|
774
|
+
extensions: mergeByName(existing.extensions || [], incoming.extensions || []),
|
|
775
|
+
enums: mergeByName(existing.enums || [], incoming.enums || []),
|
|
776
|
+
domains: mergeByName(existing.domains || [], incoming.domains || []),
|
|
777
|
+
compositeTypes: mergeByName(existing.compositeTypes || [], incoming.compositeTypes || []),
|
|
778
|
+
sequences: mergeByName(existing.sequences || [], incoming.sequences || []),
|
|
779
|
+
collations: mergeByName(existing.collations || [], incoming.collations || []),
|
|
780
|
+
tables: mergeByName(existing.tables || [], incoming.tables || []),
|
|
781
|
+
functions: mergeByName(existing.functions || [], incoming.functions || []),
|
|
782
|
+
triggers: mergeByName(existing.triggers || [], incoming.triggers || []),
|
|
783
|
+
views: mergeByName(existing.views || [], incoming.views || []),
|
|
784
|
+
materializedViews: mergeByName(existing.materializedViews || [], incoming.materializedViews || []),
|
|
785
|
+
foreignTables: mergeByName(existing.foreignTables || [], incoming.foreignTables || []),
|
|
786
|
+
};
|
|
787
|
+
}
|
|
524
788
|
exports.default = importCommand;
|