relq 1.0.2 → 1.0.4
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/add.cjs +403 -27
- package/dist/cjs/cli/commands/branch.cjs +13 -23
- package/dist/cjs/cli/commands/checkout.cjs +16 -29
- package/dist/cjs/cli/commands/cherry-pick.cjs +3 -4
- package/dist/cjs/cli/commands/commit.cjs +21 -29
- package/dist/cjs/cli/commands/diff.cjs +28 -32
- package/dist/cjs/cli/commands/export.cjs +7 -7
- package/dist/cjs/cli/commands/fetch.cjs +15 -21
- 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 +34 -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 +26 -32
- package/dist/cjs/cli/commands/merge.cjs +24 -41
- package/dist/cjs/cli/commands/migrate.cjs +12 -25
- package/dist/cjs/cli/commands/pull.cjs +216 -106
- package/dist/cjs/cli/commands/push.cjs +35 -75
- package/dist/cjs/cli/commands/remote.cjs +2 -1
- package/dist/cjs/cli/commands/reset.cjs +22 -43
- package/dist/cjs/cli/commands/resolve.cjs +12 -14
- package/dist/cjs/cli/commands/rollback.cjs +16 -38
- package/dist/cjs/cli/commands/stash.cjs +5 -7
- package/dist/cjs/cli/commands/status.cjs +5 -10
- package/dist/cjs/cli/commands/sync.cjs +30 -50
- package/dist/cjs/cli/commands/tag.cjs +3 -4
- package/dist/cjs/cli/index.cjs +72 -9
- 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/config-loader.cjs +34 -8
- package/dist/cjs/cli/utils/fast-introspect.cjs +109 -3
- 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 +56 -5
- package/dist/cjs/cli/utils/relqignore.cjs +1 -0
- package/dist/cjs/cli/utils/repo-manager.cjs +47 -0
- 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 +7 -3
- 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 +10 -2
- package/dist/cjs/cli/utils/type-generator.cjs +28 -16
- package/dist/config.d.ts +16 -6
- package/dist/esm/cli/commands/add.js +372 -29
- package/dist/esm/cli/commands/branch.js +14 -24
- package/dist/esm/cli/commands/checkout.js +16 -29
- package/dist/esm/cli/commands/cherry-pick.js +3 -4
- package/dist/esm/cli/commands/commit.js +22 -30
- package/dist/esm/cli/commands/diff.js +6 -10
- package/dist/esm/cli/commands/export.js +8 -8
- package/dist/esm/cli/commands/fetch.js +14 -20
- 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 +35 -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 +6 -12
- package/dist/esm/cli/commands/merge.js +20 -37
- package/dist/esm/cli/commands/migrate.js +12 -25
- package/dist/esm/cli/commands/pull.js +204 -94
- package/dist/esm/cli/commands/push.js +21 -61
- package/dist/esm/cli/commands/remote.js +2 -1
- package/dist/esm/cli/commands/reset.js +16 -37
- package/dist/esm/cli/commands/resolve.js +13 -15
- package/dist/esm/cli/commands/rollback.js +16 -38
- package/dist/esm/cli/commands/stash.js +6 -8
- package/dist/esm/cli/commands/status.js +6 -11
- package/dist/esm/cli/commands/sync.js +30 -50
- package/dist/esm/cli/commands/tag.js +3 -4
- package/dist/esm/cli/index.js +72 -9
- 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/config-loader.js +34 -8
- package/dist/esm/cli/utils/fast-introspect.js +109 -3
- 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 +55 -5
- package/dist/esm/cli/utils/relqignore.js +1 -0
- package/dist/esm/cli/utils/repo-manager.js +42 -0
- 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 +7 -3
- 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 +10 -2
- package/dist/esm/cli/utils/type-generator.js +28 -16
- package/dist/index.d.ts +25 -8
- package/dist/schema-builder.d.ts +18 -7
- package/package.json +1 -1
|
@@ -41,16 +41,11 @@ const spinner_1 = require("../utils/spinner.cjs");
|
|
|
41
41
|
const relqignore_1 = require("../utils/relqignore.cjs");
|
|
42
42
|
const repo_manager_1 = require("../utils/repo-manager.cjs");
|
|
43
43
|
async function statusCommand(context) {
|
|
44
|
-
const { config, flags } = context;
|
|
45
|
-
const projectRoot = process.cwd();
|
|
44
|
+
const { config, flags, projectRoot } = context;
|
|
46
45
|
const connection = config?.connection;
|
|
47
46
|
console.log('');
|
|
48
47
|
if (!(0, repo_manager_1.isInitialized)(projectRoot)) {
|
|
49
|
-
|
|
50
|
-
console.log('');
|
|
51
|
-
console.log(`${spinner_1.colors.muted('Run')} ${spinner_1.colors.cyan('relq init')} ${spinner_1.colors.muted('to initialize.')}`);
|
|
52
|
-
console.log('');
|
|
53
|
-
return;
|
|
48
|
+
(0, spinner_1.fatal)('not a relq repository (or any parent directories): .relq', `Run ${spinner_1.colors.cyan('relq init')} to initialize.`);
|
|
54
49
|
}
|
|
55
50
|
const head = (0, repo_manager_1.getHead)(projectRoot);
|
|
56
51
|
const staged = (0, repo_manager_1.getStagedChanges)(projectRoot);
|
|
@@ -73,7 +68,7 @@ async function statusCommand(context) {
|
|
|
73
68
|
console.log(`${spinner_1.colors.green('Changes to be committed:')}`);
|
|
74
69
|
console.log(` ${spinner_1.colors.muted('(use "relq restore --staged <name>..." to unstage)')}`);
|
|
75
70
|
console.log('');
|
|
76
|
-
displayChanges(staged, '
|
|
71
|
+
displayChanges(staged, ' ');
|
|
77
72
|
console.log('');
|
|
78
73
|
}
|
|
79
74
|
if (unstaged.length > 0) {
|
|
@@ -81,7 +76,7 @@ async function statusCommand(context) {
|
|
|
81
76
|
console.log(` ${spinner_1.colors.muted('(use "relq add <name>..." to stage)')}`);
|
|
82
77
|
console.log(` ${spinner_1.colors.muted('(use "relq restore <name>..." to discard)')}`);
|
|
83
78
|
console.log('');
|
|
84
|
-
displayChanges(unstaged, '
|
|
79
|
+
displayChanges(unstaged, ' ');
|
|
85
80
|
console.log('');
|
|
86
81
|
}
|
|
87
82
|
const ignorePatterns = (0, relqignore_1.loadRelqignore)(projectRoot);
|
|
@@ -92,7 +87,7 @@ async function statusCommand(context) {
|
|
|
92
87
|
!p.raw.startsWith('_temp_') &&
|
|
93
88
|
!p.raw.startsWith('tmp_'));
|
|
94
89
|
if (userPatterns.length > 0) {
|
|
95
|
-
console.log(`${spinner_1.colors.muted(
|
|
90
|
+
console.log(`${spinner_1.colors.muted(`${userPatterns.length} pattern(s) active from .relqignore`)}`);
|
|
96
91
|
console.log('');
|
|
97
92
|
}
|
|
98
93
|
}
|
|
@@ -3,77 +3,57 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.syncCommand = syncCommand;
|
|
4
4
|
const config_loader_1 = require("../utils/config-loader.cjs");
|
|
5
5
|
const env_loader_1 = require("../utils/env-loader.cjs");
|
|
6
|
-
const
|
|
6
|
+
const cli_utils_1 = require("../utils/cli-utils.cjs");
|
|
7
7
|
const repo_manager_1 = require("../utils/repo-manager.cjs");
|
|
8
8
|
const pull_1 = require("./pull.cjs");
|
|
9
9
|
async function syncCommand(context) {
|
|
10
10
|
const { config, flags } = context;
|
|
11
11
|
if (!config) {
|
|
12
|
-
|
|
13
|
-
process.exit(1);
|
|
12
|
+
(0, cli_utils_1.fatal)('No configuration found', `Run ${cli_utils_1.colors.cyan('relq init')} to create one.`);
|
|
14
13
|
}
|
|
15
|
-
(0, config_loader_1.requireValidConfig)(config);
|
|
14
|
+
await (0, config_loader_1.requireValidConfig)(config, { calledFrom: 'sync' });
|
|
16
15
|
const connection = config.connection;
|
|
17
|
-
const projectRoot =
|
|
16
|
+
const { projectRoot } = context;
|
|
18
17
|
console.log('');
|
|
19
18
|
if (!(0, repo_manager_1.isInitialized)(projectRoot)) {
|
|
20
|
-
|
|
21
|
-
console.log('');
|
|
22
|
-
console.log(`${spinner_1.colors.muted('Run')} ${spinner_1.colors.cyan('relq init')} ${spinner_1.colors.muted('to initialize.')}`);
|
|
23
|
-
return;
|
|
19
|
+
(0, cli_utils_1.fatal)('not a relq repository (or any parent directories): .relq', `Run ${cli_utils_1.colors.cyan('relq init')} to initialize.`);
|
|
24
20
|
}
|
|
25
|
-
const spinner = (0,
|
|
21
|
+
const spinner = (0, cli_utils_1.createSpinner)();
|
|
26
22
|
try {
|
|
27
|
-
|
|
28
|
-
const status = await (0, repo_manager_1.getRepoStatus)(connection, projectRoot);
|
|
29
|
-
spinner.stop();
|
|
30
|
-
console.log(`On database: ${spinner_1.colors.cyan((0, env_loader_1.getConnectionDescription)(connection))}`);
|
|
23
|
+
console.log(`Syncing with ${cli_utils_1.colors.cyan((0, env_loader_1.getConnectionDescription)(connection))}...`);
|
|
31
24
|
console.log('');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
25
|
+
await (0, pull_1.pullCommand)(context);
|
|
26
|
+
await (0, repo_manager_1.ensureRemoteTable)(connection);
|
|
27
|
+
const remoteCommits = await (0, repo_manager_1.fetchRemoteCommits)(connection, 100);
|
|
28
|
+
const remoteHashes = new Set(remoteCommits.map(c => c.hash));
|
|
29
|
+
const localCommitsAfter = (0, repo_manager_1.getAllCommits)(projectRoot);
|
|
30
|
+
const toPush = localCommitsAfter.filter(c => !remoteHashes.has(c.hash));
|
|
31
|
+
if (toPush.length === 0) {
|
|
32
|
+
(0, cli_utils_1.success)('Sync complete - up to date');
|
|
40
33
|
console.log('');
|
|
41
34
|
return;
|
|
42
35
|
}
|
|
36
|
+
console.log(`Pushing ${toPush.length} local commit(s)...`);
|
|
43
37
|
console.log('');
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const pullContext = {
|
|
48
|
-
...context,
|
|
49
|
-
flags: { ...flags, force: true },
|
|
50
|
-
};
|
|
51
|
-
await (0, pull_1.pullCommand)(pullContext);
|
|
38
|
+
spinner.start(`Pushing ${toPush.length} commit(s)...`);
|
|
39
|
+
for (const commit of toPush.reverse()) {
|
|
40
|
+
await (0, repo_manager_1.pushCommit)(connection, commit);
|
|
52
41
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
spinner.start(`Pushing ${toPush.length} commit(s)...`);
|
|
62
|
-
for (const commit of toPush.reverse()) {
|
|
63
|
-
await (0, repo_manager_1.pushCommit)(connection, commit);
|
|
64
|
-
}
|
|
65
|
-
spinner.succeed(`Pushed ${toPush.length} commit(s)`);
|
|
42
|
+
spinner.succeed(`Pushed ${toPush.length} commit(s)`);
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log('Pushed commits:');
|
|
45
|
+
for (const commit of toPush.slice(0, 5)) {
|
|
46
|
+
console.log(` ${cli_utils_1.colors.yellow((0, repo_manager_1.shortHash)(commit.hash))} ${commit.message}`);
|
|
47
|
+
}
|
|
48
|
+
if (toPush.length > 5) {
|
|
49
|
+
console.log(` ${cli_utils_1.colors.muted(`... and ${toPush.length - 5} more`)}`);
|
|
66
50
|
}
|
|
67
51
|
console.log('');
|
|
68
|
-
|
|
69
|
-
const pushedText = status.aheadBy > 0 ? `${spinner_1.colors.green(`↑ ${status.aheadBy}`)} pushed` : '';
|
|
70
|
-
const separator = pulledText && pushedText ? ' | ' : '';
|
|
71
|
-
console.log(`${spinner_1.colors.green('✓')} Sync complete: ${pulledText}${separator}${pushedText}`);
|
|
52
|
+
(0, cli_utils_1.success)(`Sync complete - pushed ${toPush.length} commit(s)`);
|
|
72
53
|
}
|
|
73
|
-
catch (
|
|
54
|
+
catch (err) {
|
|
74
55
|
spinner.fail('Sync failed');
|
|
75
|
-
|
|
76
|
-
process.exit(1);
|
|
56
|
+
(0, cli_utils_1.fatal)(err instanceof Error ? err.message : String(err));
|
|
77
57
|
}
|
|
78
58
|
console.log('');
|
|
79
59
|
}
|
|
@@ -50,8 +50,7 @@ function saveTags(tags, projectRoot) {
|
|
|
50
50
|
fs.writeFileSync(tagPath, JSON.stringify(tags, null, 2));
|
|
51
51
|
}
|
|
52
52
|
async function tagCommand(context) {
|
|
53
|
-
const { args, flags } = context;
|
|
54
|
-
const projectRoot = process.cwd();
|
|
53
|
+
const { args, flags, projectRoot } = context;
|
|
55
54
|
console.log('');
|
|
56
55
|
if (!(0, repo_manager_1.isInitialized)(projectRoot)) {
|
|
57
56
|
console.log(`${spinner_1.colors.red('fatal:')} not a relq repository`);
|
|
@@ -75,7 +74,7 @@ async function tagCommand(context) {
|
|
|
75
74
|
}
|
|
76
75
|
delete tags[tagName];
|
|
77
76
|
saveTags(tags, projectRoot);
|
|
78
|
-
console.log(
|
|
77
|
+
console.log(`Deleted tag '${tagName}'`);
|
|
79
78
|
console.log('');
|
|
80
79
|
return;
|
|
81
80
|
}
|
|
@@ -123,7 +122,7 @@ async function tagCommand(context) {
|
|
|
123
122
|
createdAt: new Date().toISOString(),
|
|
124
123
|
};
|
|
125
124
|
saveTags(tags, projectRoot);
|
|
126
|
-
console.log(
|
|
125
|
+
console.log(`Tagged ${spinner_1.colors.yellow((0, repo_manager_1.shortHash)(hash))} as '${tagName}'`);
|
|
127
126
|
console.log(` ${commit.message}`);
|
|
128
127
|
console.log('');
|
|
129
128
|
return;
|
package/dist/cjs/cli/index.cjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
"use strict";
|
|
3
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
3
|
if (k2 === undefined) k2 = k;
|
|
@@ -34,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
33
|
};
|
|
35
34
|
})();
|
|
36
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.main = main;
|
|
37
37
|
const init_1 = require("./commands/init.cjs");
|
|
38
38
|
const pull_1 = require("./commands/pull.cjs");
|
|
39
39
|
const push_1 = require("./commands/push.cjs");
|
|
@@ -57,6 +57,34 @@ const merge_1 = require("./commands/merge.cjs");
|
|
|
57
57
|
const tag_1 = require("./commands/tag.cjs");
|
|
58
58
|
const cherry_pick_1 = require("./commands/cherry-pick.cjs");
|
|
59
59
|
const remote_1 = require("./commands/remote.cjs");
|
|
60
|
+
const fs = __importStar(require("fs"));
|
|
61
|
+
const path = __importStar(require("path"));
|
|
62
|
+
function loadEnvFile() {
|
|
63
|
+
let currentDir = process.cwd();
|
|
64
|
+
const root = path.parse(currentDir).root;
|
|
65
|
+
while (currentDir !== root) {
|
|
66
|
+
const envPath = path.join(currentDir, '.env');
|
|
67
|
+
if (fs.existsSync(envPath)) {
|
|
68
|
+
const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
69
|
+
for (const line of envContent.split('\n')) {
|
|
70
|
+
const trimmed = line.trim();
|
|
71
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
72
|
+
continue;
|
|
73
|
+
const match = trimmed.match(/^([^=]+)=(.*)$/);
|
|
74
|
+
if (match) {
|
|
75
|
+
const key = match[1].trim();
|
|
76
|
+
const value = match[2].trim().replace(/^["']|["']$/g, '');
|
|
77
|
+
if (!process.env[key]) {
|
|
78
|
+
process.env[key] = value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
currentDir = path.dirname(currentDir);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
loadEnvFile();
|
|
60
88
|
const VERSION = '1.1.0';
|
|
61
89
|
function parseArgs(argv) {
|
|
62
90
|
const args = [];
|
|
@@ -184,20 +212,56 @@ async function main() {
|
|
|
184
212
|
process.exit(1);
|
|
185
213
|
}
|
|
186
214
|
let config = null;
|
|
215
|
+
let resolvedProjectRoot = process.cwd();
|
|
187
216
|
if (requiresConfig(command)) {
|
|
188
217
|
const configPath = flags.config;
|
|
189
218
|
try {
|
|
190
219
|
const { loadConfigWithEnv, findConfigFileRecursive } = await Promise.resolve().then(() => __importStar(require("./utils/config-loader.cjs")));
|
|
191
|
-
const
|
|
220
|
+
const { findProjectRoot } = await Promise.resolve().then(() => __importStar(require("./utils/project-root.cjs")));
|
|
221
|
+
const configResult = configPath ? { path: configPath, directory: path.dirname(path.resolve(configPath)) } : findConfigFileRecursive();
|
|
222
|
+
if (!configResult) {
|
|
223
|
+
const projectRoot = findProjectRoot();
|
|
224
|
+
if (!projectRoot) {
|
|
225
|
+
const colors = {
|
|
226
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
227
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
228
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
229
|
+
};
|
|
230
|
+
console.error('');
|
|
231
|
+
console.error(colors.red('fatal:') + ' not a relq project (or any of the parent directories)');
|
|
232
|
+
console.error('');
|
|
233
|
+
console.error(colors.yellow('hint:') + ` Run ${colors.cyan('relq init')} in your project directory to initialize relq.`);
|
|
234
|
+
console.error('');
|
|
235
|
+
process.exit(128);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
resolvedProjectRoot = configResult?.directory || findProjectRoot() || process.cwd();
|
|
239
|
+
const foundConfig = configResult?.path;
|
|
192
240
|
if (!foundConfig) {
|
|
193
|
-
|
|
194
|
-
|
|
241
|
+
const colors = {
|
|
242
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
243
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
244
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
245
|
+
};
|
|
246
|
+
console.error('');
|
|
247
|
+
console.error(colors.red('error:') + ' relq.config.ts not found');
|
|
248
|
+
console.error('');
|
|
249
|
+
console.error(colors.yellow('hint:') + ` Run ${colors.cyan('relq init')} to create one or use ${colors.cyan('--config')} to specify a path.`);
|
|
250
|
+
console.error('');
|
|
195
251
|
process.exit(1);
|
|
196
252
|
}
|
|
197
253
|
config = await loadConfigWithEnv(configPath);
|
|
198
254
|
if (requiresDbConnection(command, flags) && !config.connection?.host && !config.connection?.url) {
|
|
199
|
-
|
|
200
|
-
|
|
255
|
+
const colors = {
|
|
256
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
257
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
258
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
259
|
+
};
|
|
260
|
+
console.error('');
|
|
261
|
+
console.error(colors.red('error:') + ' No database connection configured');
|
|
262
|
+
console.error('');
|
|
263
|
+
console.error(colors.yellow('hint:') + ` Run ${colors.cyan('relq init')} or set DATABASE_* environment variables.`);
|
|
264
|
+
console.error('');
|
|
201
265
|
process.exit(1);
|
|
202
266
|
}
|
|
203
267
|
}
|
|
@@ -206,7 +270,7 @@ async function main() {
|
|
|
206
270
|
process.exit(1);
|
|
207
271
|
}
|
|
208
272
|
}
|
|
209
|
-
const context = { config, args, flags };
|
|
273
|
+
const context = { config, args, flags, projectRoot: resolvedProjectRoot };
|
|
210
274
|
try {
|
|
211
275
|
switch (command) {
|
|
212
276
|
case 'init':
|
|
@@ -296,7 +360,7 @@ async function main() {
|
|
|
296
360
|
theirs: Boolean(flags.theirs),
|
|
297
361
|
ours: Boolean(flags.ours),
|
|
298
362
|
abort: Boolean(flags.abort),
|
|
299
|
-
});
|
|
363
|
+
}, resolvedProjectRoot);
|
|
300
364
|
break;
|
|
301
365
|
case 'export':
|
|
302
366
|
await (0, export_1.exportCommand)(context);
|
|
@@ -316,4 +380,3 @@ async function main() {
|
|
|
316
380
|
process.exit(1);
|
|
317
381
|
}
|
|
318
382
|
}
|
|
319
|
-
main().catch(console.error);
|
|
@@ -72,6 +72,12 @@ function generateChangeSQL(change) {
|
|
|
72
72
|
return generateConstraintSQL(change);
|
|
73
73
|
case 'PARTITION':
|
|
74
74
|
return generatePartitionSQL(change);
|
|
75
|
+
case 'PARTITION_CHILD':
|
|
76
|
+
return generatePartitionChildSQL(change);
|
|
77
|
+
case 'TABLE_COMMENT':
|
|
78
|
+
return generateTableCommentSQL(change);
|
|
79
|
+
case 'COLUMN_COMMENT':
|
|
80
|
+
return generateColumnCommentSQL(change);
|
|
75
81
|
case 'VIEW':
|
|
76
82
|
return generateViewSQL(change);
|
|
77
83
|
case 'MATERIALIZED_VIEW':
|
|
@@ -85,6 +91,8 @@ function generateChangeSQL(change) {
|
|
|
85
91
|
return generateForeignServerSQL(change);
|
|
86
92
|
case 'FOREIGN_TABLE':
|
|
87
93
|
return generateForeignTableSQL(change);
|
|
94
|
+
case 'COLLATION':
|
|
95
|
+
return generateCollationSQL(change);
|
|
88
96
|
default:
|
|
89
97
|
return `-- Unsupported object type: ${change.objectType}`;
|
|
90
98
|
}
|
|
@@ -185,8 +193,11 @@ function generateTableSQL(change) {
|
|
|
185
193
|
}
|
|
186
194
|
const allDefs = [...colDefs, ...constraintDefs].join(',\n');
|
|
187
195
|
let sql = `CREATE TABLE "${data.name}" (\n${allDefs}\n)`;
|
|
188
|
-
if (data.isPartitioned && data.partitionType && data.partitionKey
|
|
189
|
-
|
|
196
|
+
if (data.isPartitioned && data.partitionType && data.partitionKey) {
|
|
197
|
+
const keyArr = Array.isArray(data.partitionKey) ? data.partitionKey : [data.partitionKey];
|
|
198
|
+
if (keyArr.length) {
|
|
199
|
+
sql += ` PARTITION BY ${data.partitionType} (${keyArr.join(', ')})`;
|
|
200
|
+
}
|
|
190
201
|
}
|
|
191
202
|
return sql + ';';
|
|
192
203
|
}
|
|
@@ -267,6 +278,9 @@ function generateConstraintSQL(change) {
|
|
|
267
278
|
return '';
|
|
268
279
|
}
|
|
269
280
|
function generatePartitionSQL(change) {
|
|
281
|
+
return '';
|
|
282
|
+
}
|
|
283
|
+
function generatePartitionChildSQL(change) {
|
|
270
284
|
const data = change.after;
|
|
271
285
|
if (change.type === 'CREATE' && data) {
|
|
272
286
|
return `CREATE TABLE "${data.name}" PARTITION OF "${data.parentTable}" ${data.bound};`;
|
|
@@ -276,6 +290,33 @@ function generatePartitionSQL(change) {
|
|
|
276
290
|
}
|
|
277
291
|
return '';
|
|
278
292
|
}
|
|
293
|
+
function generateTableCommentSQL(change) {
|
|
294
|
+
const data = change.after;
|
|
295
|
+
if ((change.type === 'CREATE' || change.type === 'ALTER') && data) {
|
|
296
|
+
const escaped = data.comment.replace(/'/g, "''");
|
|
297
|
+
return `COMMENT ON TABLE "${data.tableName}" IS '${escaped}';`;
|
|
298
|
+
}
|
|
299
|
+
else if (change.type === 'DROP') {
|
|
300
|
+
const beforeData = change.before;
|
|
301
|
+
const tableName = beforeData?.tableName || change.objectName;
|
|
302
|
+
return `COMMENT ON TABLE "${tableName}" IS NULL;`;
|
|
303
|
+
}
|
|
304
|
+
return '';
|
|
305
|
+
}
|
|
306
|
+
function generateColumnCommentSQL(change) {
|
|
307
|
+
const data = change.after;
|
|
308
|
+
if ((change.type === 'CREATE' || change.type === 'ALTER') && data) {
|
|
309
|
+
const escaped = data.comment.replace(/'/g, "''");
|
|
310
|
+
return `COMMENT ON COLUMN "${data.tableName}"."${data.columnName}" IS '${escaped}';`;
|
|
311
|
+
}
|
|
312
|
+
else if (change.type === 'DROP') {
|
|
313
|
+
const beforeData = change.before;
|
|
314
|
+
const tableName = beforeData?.tableName || change.parentName || '';
|
|
315
|
+
const columnName = beforeData?.columnName || change.objectName;
|
|
316
|
+
return `COMMENT ON COLUMN "${tableName}"."${columnName}" IS NULL;`;
|
|
317
|
+
}
|
|
318
|
+
return '';
|
|
319
|
+
}
|
|
279
320
|
function generateViewSQL(change) {
|
|
280
321
|
const data = change.after;
|
|
281
322
|
if (change.type === 'CREATE' && data) {
|
|
@@ -361,6 +402,28 @@ function generateForeignTableSQL(change) {
|
|
|
361
402
|
}
|
|
362
403
|
return '';
|
|
363
404
|
}
|
|
405
|
+
function generateCollationSQL(change) {
|
|
406
|
+
const data = change.after;
|
|
407
|
+
if (change.type === 'CREATE' && data) {
|
|
408
|
+
const options = [];
|
|
409
|
+
if (data.locale)
|
|
410
|
+
options.push(`LOCALE = '${data.locale}'`);
|
|
411
|
+
if (data.lcCollate)
|
|
412
|
+
options.push(`LC_COLLATE = '${data.lcCollate}'`);
|
|
413
|
+
if (data.lcCtype)
|
|
414
|
+
options.push(`LC_CTYPE = '${data.lcCtype}'`);
|
|
415
|
+
if (data.provider)
|
|
416
|
+
options.push(`PROVIDER = ${data.provider}`);
|
|
417
|
+
if (data.deterministic !== undefined) {
|
|
418
|
+
options.push(`DETERMINISTIC = ${data.deterministic ? 'TRUE' : 'FALSE'}`);
|
|
419
|
+
}
|
|
420
|
+
return `CREATE COLLATION IF NOT EXISTS "${data.name}" (${options.join(', ')});`;
|
|
421
|
+
}
|
|
422
|
+
else if (change.type === 'DROP') {
|
|
423
|
+
return `DROP COLLATION IF EXISTS "${change.objectName}";`;
|
|
424
|
+
}
|
|
425
|
+
return '';
|
|
426
|
+
}
|
|
364
427
|
function createChange(type, objectType, objectName, before, after, parentName) {
|
|
365
428
|
const id = generateChangeId(type, objectType, objectName, parentName);
|
|
366
429
|
const change = {
|
|
@@ -382,6 +445,42 @@ function getChangeDisplayName(change) {
|
|
|
382
445
|
change.type === 'DROP' ? '-' :
|
|
383
446
|
change.type === 'ALTER' ? '~' :
|
|
384
447
|
'>';
|
|
448
|
+
if (change.objectType === 'INDEX') {
|
|
449
|
+
const data = change.after;
|
|
450
|
+
const tableName = data?.tableName || change.parentName;
|
|
451
|
+
if (tableName) {
|
|
452
|
+
return `${prefix} ${change.objectType} ${change.objectName} on ${tableName}`;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (change.objectType === 'PARTITION') {
|
|
456
|
+
const data = change.after;
|
|
457
|
+
if (data?.tableName && data?.type && data?.key) {
|
|
458
|
+
let keyStr = Array.isArray(data.key) ? data.key.join(', ') : data.key;
|
|
459
|
+
keyStr = keyStr.replace(/[{}]/g, '');
|
|
460
|
+
return `${prefix} PARTITIONED ${data.tableName} by ${data.type.toUpperCase()}(${keyStr})`;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
if (change.objectType === 'PARTITION_CHILD') {
|
|
464
|
+
const data = change.after;
|
|
465
|
+
if (data?.name && data?.parentTable) {
|
|
466
|
+
const bound = data.bound || '';
|
|
467
|
+
return `${prefix} PARTITION ${data.name} of ${data.parentTable} ${bound}`;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (change.objectType === 'CHECK') {
|
|
471
|
+
const actionWord = change.type === 'CREATE' ? 'ADD' : change.type === 'DROP' ? 'DROP' : 'ALTER';
|
|
472
|
+
if (change.parentName) {
|
|
473
|
+
return `${prefix} ${actionWord} CHECK ${change.objectName} on ${change.parentName}`;
|
|
474
|
+
}
|
|
475
|
+
return `${prefix} ${actionWord} CHECK ${change.objectName}`;
|
|
476
|
+
}
|
|
477
|
+
if (change.objectType === 'PRIMARY_KEY' || change.objectType === 'FOREIGN_KEY' || change.objectType === 'EXCLUSION') {
|
|
478
|
+
const actionWord = change.type === 'CREATE' ? 'ADD' : change.type === 'DROP' ? 'DROP' : 'ALTER';
|
|
479
|
+
if (change.parentName) {
|
|
480
|
+
return `${prefix} ${actionWord} ${change.objectType.replace('_', ' ')} ${change.objectName} on ${change.parentName}`;
|
|
481
|
+
}
|
|
482
|
+
return `${prefix} ${actionWord} ${change.objectType.replace('_', ' ')} ${change.objectName}`;
|
|
483
|
+
}
|
|
385
484
|
if (change.parentName) {
|
|
386
485
|
return `${prefix} ${change.objectType} ${change.parentName}.${change.objectName}`;
|
|
387
486
|
}
|
|
@@ -391,14 +490,18 @@ function sortChangesByDependency(changes) {
|
|
|
391
490
|
const order = {
|
|
392
491
|
'EXTENSION': 1,
|
|
393
492
|
'SCHEMA': 2,
|
|
493
|
+
'SCHEMA_FILE': 0,
|
|
394
494
|
'ENUM': 3,
|
|
395
495
|
'DOMAIN': 4,
|
|
396
496
|
'COMPOSITE_TYPE': 5,
|
|
397
497
|
'SEQUENCE': 6,
|
|
398
498
|
'FOREIGN_SERVER': 7,
|
|
399
499
|
'TABLE': 10,
|
|
500
|
+
'TABLE_COMMENT': 10,
|
|
400
501
|
'PARTITION': 11,
|
|
401
|
-
'
|
|
502
|
+
'PARTITION_CHILD': 12,
|
|
503
|
+
'COLUMN': 13,
|
|
504
|
+
'COLUMN_COMMENT': 12,
|
|
402
505
|
'INDEX': 13,
|
|
403
506
|
'CONSTRAINT': 14,
|
|
404
507
|
'PRIMARY_KEY': 14,
|
|
@@ -411,6 +514,7 @@ function sortChangesByDependency(changes) {
|
|
|
411
514
|
'PROCEDURE': 31,
|
|
412
515
|
'TRIGGER': 40,
|
|
413
516
|
'ENUM_VALUE': 3,
|
|
517
|
+
'COLLATION': 4,
|
|
414
518
|
'FOREIGN_TABLE': 8,
|
|
415
519
|
};
|
|
416
520
|
return [...changes].sort((a, b) => {
|