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
|
@@ -33,12 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.colors = void 0;
|
|
37
|
-
exports.error = error;
|
|
38
|
-
exports.fatal = fatal;
|
|
39
|
-
exports.warning = warning;
|
|
40
|
-
exports.hint = hint;
|
|
41
|
-
exports.success = success;
|
|
36
|
+
exports.requireInit = exports.progressBar = exports.formatDuration = exports.formatBytes = exports.select = exports.success = exports.hint = exports.warning = exports.error = exports.fatal = exports.createSpinner = exports.colors = void 0;
|
|
42
37
|
exports.info = info;
|
|
43
38
|
exports.getWorkingTreeStatus = getWorkingTreeStatus;
|
|
44
39
|
exports.requireRepository = requireRepository;
|
|
@@ -50,43 +45,24 @@ exports.checkUncommittedChanges = checkUncommittedChanges;
|
|
|
50
45
|
exports.printMergeStrategyHelp = printMergeStrategyHelp;
|
|
51
46
|
exports.validatePostgresSQL = validatePostgresSQL;
|
|
52
47
|
exports.readSQLFile = readSQLFile;
|
|
53
|
-
exports.createSpinner = createSpinner;
|
|
54
|
-
exports.confirm = confirm;
|
|
55
|
-
exports.select = select;
|
|
56
|
-
exports.formatBytes = formatBytes;
|
|
57
|
-
exports.formatDuration = formatDuration;
|
|
58
48
|
const fs = __importStar(require("fs"));
|
|
59
49
|
const path = __importStar(require("path"));
|
|
60
50
|
const repo_manager_1 = require("./repo-manager.cjs");
|
|
61
|
-
|
|
62
|
-
exports.colors
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
function fatal(message) {
|
|
78
|
-
console.error(`${exports.colors.red('fatal:')} ${message}`);
|
|
79
|
-
process.exit(128);
|
|
80
|
-
}
|
|
81
|
-
function warning(message) {
|
|
82
|
-
console.error(`${exports.colors.yellow('warning:')} ${message}`);
|
|
83
|
-
}
|
|
84
|
-
function hint(message) {
|
|
85
|
-
console.log(`${exports.colors.yellow('hint:')} ${message}`);
|
|
86
|
-
}
|
|
87
|
-
function success(message) {
|
|
88
|
-
console.log(`${exports.colors.green('✓')} ${message}`);
|
|
89
|
-
}
|
|
51
|
+
var cli_utils_1 = require("./cli-utils.cjs");
|
|
52
|
+
Object.defineProperty(exports, "colors", { enumerable: true, get: function () { return cli_utils_1.colors; } });
|
|
53
|
+
Object.defineProperty(exports, "createSpinner", { enumerable: true, get: function () { return cli_utils_1.createSpinner; } });
|
|
54
|
+
Object.defineProperty(exports, "fatal", { enumerable: true, get: function () { return cli_utils_1.fatal; } });
|
|
55
|
+
Object.defineProperty(exports, "error", { enumerable: true, get: function () { return cli_utils_1.error; } });
|
|
56
|
+
Object.defineProperty(exports, "warning", { enumerable: true, get: function () { return cli_utils_1.warning; } });
|
|
57
|
+
Object.defineProperty(exports, "hint", { enumerable: true, get: function () { return cli_utils_1.hint; } });
|
|
58
|
+
Object.defineProperty(exports, "success", { enumerable: true, get: function () { return cli_utils_1.success; } });
|
|
59
|
+
Object.defineProperty(exports, "confirm", { enumerable: true, get: function () { return cli_utils_1.confirm; } });
|
|
60
|
+
Object.defineProperty(exports, "select", { enumerable: true, get: function () { return cli_utils_1.select; } });
|
|
61
|
+
Object.defineProperty(exports, "formatBytes", { enumerable: true, get: function () { return cli_utils_1.formatBytes; } });
|
|
62
|
+
Object.defineProperty(exports, "formatDuration", { enumerable: true, get: function () { return cli_utils_1.formatDuration; } });
|
|
63
|
+
Object.defineProperty(exports, "progressBar", { enumerable: true, get: function () { return cli_utils_1.progressBar; } });
|
|
64
|
+
Object.defineProperty(exports, "requireInit", { enumerable: true, get: function () { return cli_utils_1.requireInit; } });
|
|
65
|
+
const cli_utils_2 = require("./cli-utils.cjs");
|
|
90
66
|
function info(message) {
|
|
91
67
|
console.log(message);
|
|
92
68
|
}
|
|
@@ -110,7 +86,7 @@ function getWorkingTreeStatus(projectRoot = process.cwd()) {
|
|
|
110
86
|
}
|
|
111
87
|
function requireRepository(projectRoot = process.cwd()) {
|
|
112
88
|
if (!(0, repo_manager_1.isInitialized)(projectRoot)) {
|
|
113
|
-
fatal('not a relq repository (or any of the parent directories): .relq');
|
|
89
|
+
(0, cli_utils_2.fatal)('not a relq repository (or any of the parent directories): .relq');
|
|
114
90
|
}
|
|
115
91
|
}
|
|
116
92
|
function requireCleanWorkingTree(projectRoot = process.cwd(), operation = 'operation') {
|
|
@@ -136,44 +112,44 @@ function requireCleanWorkingTree(projectRoot = process.cwd(), operation = 'opera
|
|
|
136
112
|
function printDirtyWorkingTreeError(status, operation) {
|
|
137
113
|
console.log('');
|
|
138
114
|
if (status.hasUnstagedChanges && status.hasUncommittedChanges) {
|
|
139
|
-
error(`Your local changes would be overwritten by ${operation}.`);
|
|
140
|
-
hint(`Commit your changes or stash them before you ${operation}.`);
|
|
115
|
+
(0, cli_utils_2.error)(`Your local changes would be overwritten by ${operation}.`);
|
|
116
|
+
(0, cli_utils_2.hint)(`Commit your changes or stash them before you ${operation}.`);
|
|
141
117
|
}
|
|
142
118
|
else if (status.hasUncommittedChanges) {
|
|
143
|
-
error(`You have uncommitted changes.`);
|
|
144
|
-
hint(`Please commit your changes before you ${operation}.`);
|
|
119
|
+
(0, cli_utils_2.error)(`You have uncommitted changes.`);
|
|
120
|
+
(0, cli_utils_2.hint)(`Please commit your changes before you ${operation}.`);
|
|
145
121
|
}
|
|
146
122
|
else {
|
|
147
|
-
error(`You have unstaged changes.`);
|
|
148
|
-
hint(`Please stage and commit your changes before you ${operation}.`);
|
|
123
|
+
(0, cli_utils_2.error)(`You have unstaged changes.`);
|
|
124
|
+
(0, cli_utils_2.hint)(`Please stage and commit your changes before you ${operation}.`);
|
|
149
125
|
}
|
|
150
126
|
console.log('');
|
|
151
127
|
if (status.hasUncommittedChanges) {
|
|
152
128
|
console.log(`Changes to be committed:`);
|
|
153
|
-
console.log(` ${
|
|
129
|
+
console.log(` ${cli_utils_2.colors.gray('(use "relq restore --staged <file>..." to unstage)')}`);
|
|
154
130
|
console.log('');
|
|
155
131
|
for (const change of status.stagedChanges.slice(0, 10)) {
|
|
156
132
|
const prefix = change.type === 'CREATE' ? 'new' : change.type === 'DROP' ? 'deleted' : 'modified';
|
|
157
|
-
const color = change.type === 'CREATE' ?
|
|
133
|
+
const color = change.type === 'CREATE' ? cli_utils_2.colors.green : change.type === 'DROP' ? cli_utils_2.colors.red : cli_utils_2.colors.yellow;
|
|
158
134
|
console.log(`\t${color(`${prefix}:`.padEnd(12))}${change.objectName}`);
|
|
159
135
|
}
|
|
160
136
|
if (status.stagedChanges.length > 10) {
|
|
161
|
-
console.log(`\t${
|
|
137
|
+
console.log(`\t${cli_utils_2.colors.gray(`... and ${status.stagedChanges.length - 10} more`)}`);
|
|
162
138
|
}
|
|
163
139
|
console.log('');
|
|
164
140
|
}
|
|
165
141
|
if (status.hasUnstagedChanges) {
|
|
166
142
|
console.log(`Changes not staged for commit:`);
|
|
167
|
-
console.log(` ${
|
|
168
|
-
console.log(` ${
|
|
143
|
+
console.log(` ${cli_utils_2.colors.gray('(use "relq add <file>..." to update what will be committed)')}`);
|
|
144
|
+
console.log(` ${cli_utils_2.colors.gray('(use "relq restore <file>..." to discard changes in working directory)')}`);
|
|
169
145
|
console.log('');
|
|
170
146
|
for (const change of status.unstagedChanges.slice(0, 10)) {
|
|
171
147
|
const prefix = change.type === 'CREATE' ? 'new' : change.type === 'DROP' ? 'deleted' : 'modified';
|
|
172
|
-
const color = change.type === 'CREATE' ?
|
|
148
|
+
const color = change.type === 'CREATE' ? cli_utils_2.colors.green : change.type === 'DROP' ? cli_utils_2.colors.red : cli_utils_2.colors.yellow;
|
|
173
149
|
console.log(`\t${color(`${prefix}:`.padEnd(12))}${change.objectName}`);
|
|
174
150
|
}
|
|
175
151
|
if (status.unstagedChanges.length > 10) {
|
|
176
|
-
console.log(`\t${
|
|
152
|
+
console.log(`\t${cli_utils_2.colors.gray(`... and ${status.unstagedChanges.length - 10} more`)}`);
|
|
177
153
|
}
|
|
178
154
|
console.log('');
|
|
179
155
|
}
|
|
@@ -209,23 +185,23 @@ function detectConflicts(localChanges, incomingChanges) {
|
|
|
209
185
|
}
|
|
210
186
|
function printConflictError(conflictInfo, operation) {
|
|
211
187
|
console.log('');
|
|
212
|
-
error(`Automatic ${operation} failed; fix conflicts and then commit the result.`);
|
|
188
|
+
(0, cli_utils_2.error)(`Automatic ${operation} failed; fix conflicts and then commit the result.`);
|
|
213
189
|
console.log('');
|
|
214
190
|
console.log(`CONFLICT (content): Merge conflict in schema`);
|
|
215
191
|
console.log('');
|
|
216
192
|
for (const conflict of conflictInfo.conflicts.slice(0, 10)) {
|
|
217
|
-
console.log(` ${
|
|
193
|
+
console.log(` ${cli_utils_2.colors.red('both modified:')} ${conflict.objectType.toLowerCase()} ${conflict.objectName}`);
|
|
218
194
|
}
|
|
219
195
|
if (conflictInfo.conflicts.length > 10) {
|
|
220
|
-
console.log(` ${
|
|
196
|
+
console.log(` ${cli_utils_2.colors.gray(`... and ${conflictInfo.conflicts.length - 10} more conflicts`)}`);
|
|
221
197
|
}
|
|
222
198
|
console.log('');
|
|
223
|
-
hint(`Fix conflicts manually and use:`);
|
|
224
|
-
hint(` relq add . - to mark resolution`);
|
|
225
|
-
hint(` relq commit - to complete the ${operation}`);
|
|
199
|
+
(0, cli_utils_2.hint)(`Fix conflicts manually and use:`);
|
|
200
|
+
(0, cli_utils_2.hint)(` relq add . - to mark resolution`);
|
|
201
|
+
(0, cli_utils_2.hint)(` relq commit - to complete the ${operation}`);
|
|
226
202
|
console.log('');
|
|
227
|
-
hint(`Or abort the ${operation} with:`);
|
|
228
|
-
hint(` relq ${operation} --abort`);
|
|
203
|
+
(0, cli_utils_2.hint)(`Or abort the ${operation} with:`);
|
|
204
|
+
(0, cli_utils_2.hint)(` relq ${operation} --abort`);
|
|
229
205
|
console.log('');
|
|
230
206
|
}
|
|
231
207
|
function checkUncommittedChanges(projectRoot = process.cwd()) {
|
|
@@ -244,10 +220,10 @@ function checkUncommittedChanges(projectRoot = process.cwd()) {
|
|
|
244
220
|
function printMergeStrategyHelp() {
|
|
245
221
|
console.log('');
|
|
246
222
|
console.log('Resolution options:');
|
|
247
|
-
console.log(` ${
|
|
248
|
-
console.log(` ${
|
|
249
|
-
console.log(` ${
|
|
250
|
-
console.log(` ${
|
|
223
|
+
console.log(` ${cli_utils_2.colors.cyan('--theirs')} Accept all incoming changes (overwrite local)`);
|
|
224
|
+
console.log(` ${cli_utils_2.colors.cyan('--ours')} Keep all local changes (reject incoming)`);
|
|
225
|
+
console.log(` ${cli_utils_2.colors.cyan('--force')} Force operation, overwrite local changes`);
|
|
226
|
+
console.log(` ${cli_utils_2.colors.cyan('--abort')} Abort and restore previous state`);
|
|
251
227
|
console.log('');
|
|
252
228
|
}
|
|
253
229
|
function validatePostgresSQL(content) {
|
|
@@ -307,98 +283,3 @@ function readSQLFile(filePath) {
|
|
|
307
283
|
const validation = validatePostgresSQL(content);
|
|
308
284
|
return { content, validation };
|
|
309
285
|
}
|
|
310
|
-
function createSpinner() {
|
|
311
|
-
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
312
|
-
let frameIndex = 0;
|
|
313
|
-
let interval = null;
|
|
314
|
-
let currentMessage = '';
|
|
315
|
-
return {
|
|
316
|
-
start(message) {
|
|
317
|
-
currentMessage = message;
|
|
318
|
-
if (process.stdout.isTTY) {
|
|
319
|
-
interval = setInterval(() => {
|
|
320
|
-
process.stdout.write(`\r${frames[frameIndex]} ${currentMessage}`);
|
|
321
|
-
frameIndex = (frameIndex + 1) % frames.length;
|
|
322
|
-
}, 80);
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
console.log(` ${message}...`);
|
|
326
|
-
}
|
|
327
|
-
},
|
|
328
|
-
stop() {
|
|
329
|
-
if (interval) {
|
|
330
|
-
clearInterval(interval);
|
|
331
|
-
interval = null;
|
|
332
|
-
if (process.stdout.isTTY) {
|
|
333
|
-
process.stdout.write('\r' + ' '.repeat(currentMessage.length + 4) + '\r');
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
},
|
|
337
|
-
succeed(message) {
|
|
338
|
-
this.stop();
|
|
339
|
-
console.log(`${exports.colors.green('✓')} ${message}`);
|
|
340
|
-
},
|
|
341
|
-
fail(message) {
|
|
342
|
-
this.stop();
|
|
343
|
-
console.log(`${exports.colors.red('✗')} ${message}`);
|
|
344
|
-
},
|
|
345
|
-
info(message) {
|
|
346
|
-
this.stop();
|
|
347
|
-
console.log(`${exports.colors.blue('ℹ')} ${message}`);
|
|
348
|
-
},
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
const readline = __importStar(require("readline"));
|
|
352
|
-
function confirm(question, defaultYes = true) {
|
|
353
|
-
const rl = readline.createInterface({
|
|
354
|
-
input: process.stdin,
|
|
355
|
-
output: process.stdout,
|
|
356
|
-
});
|
|
357
|
-
const suffix = defaultYes ? '[Y/n]' : '[y/N]';
|
|
358
|
-
return new Promise((resolve) => {
|
|
359
|
-
rl.question(`${question} ${exports.colors.gray(suffix)} `, (answer) => {
|
|
360
|
-
rl.close();
|
|
361
|
-
const a = answer.trim().toLowerCase();
|
|
362
|
-
if (!a)
|
|
363
|
-
resolve(defaultYes);
|
|
364
|
-
else
|
|
365
|
-
resolve(a === 'y' || a === 'yes');
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
function select(question, options) {
|
|
370
|
-
const rl = readline.createInterface({
|
|
371
|
-
input: process.stdin,
|
|
372
|
-
output: process.stdout,
|
|
373
|
-
});
|
|
374
|
-
console.log(question);
|
|
375
|
-
options.forEach((opt, i) => {
|
|
376
|
-
console.log(` ${i + 1}) ${opt}`);
|
|
377
|
-
});
|
|
378
|
-
return new Promise((resolve) => {
|
|
379
|
-
rl.question(`${exports.colors.gray('Select [1-' + options.length + ']:')} `, (answer) => {
|
|
380
|
-
rl.close();
|
|
381
|
-
const num = parseInt(answer.trim(), 10);
|
|
382
|
-
if (num >= 1 && num <= options.length) {
|
|
383
|
-
resolve(num - 1);
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
resolve(0);
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
function formatBytes(bytes) {
|
|
392
|
-
if (bytes < 1024)
|
|
393
|
-
return `${bytes} B`;
|
|
394
|
-
if (bytes < 1024 * 1024)
|
|
395
|
-
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
396
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
397
|
-
}
|
|
398
|
-
function formatDuration(ms) {
|
|
399
|
-
if (ms < 1000)
|
|
400
|
-
return `${ms}ms`;
|
|
401
|
-
if (ms < 60000)
|
|
402
|
-
return `${(ms / 1000).toFixed(1)}s`;
|
|
403
|
-
return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
|
|
404
|
-
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getPool = getPool;
|
|
37
|
+
exports.releasePool = releasePool;
|
|
38
|
+
exports.withPool = withPool;
|
|
39
|
+
exports.withClient = withClient;
|
|
40
|
+
exports.withTransaction = withTransaction;
|
|
41
|
+
exports.closeAllPools = closeAllPools;
|
|
42
|
+
exports.getActivePoolCount = getActivePoolCount;
|
|
43
|
+
const pools = new Map();
|
|
44
|
+
const IDLE_TIMEOUT = 30000;
|
|
45
|
+
let cleanupInterval = null;
|
|
46
|
+
function getPoolKey(config) {
|
|
47
|
+
if (config.url) {
|
|
48
|
+
return config.url;
|
|
49
|
+
}
|
|
50
|
+
return `${config.host || 'localhost'}:${config.port || 5432}/${config.database}@${config.user}`;
|
|
51
|
+
}
|
|
52
|
+
function startCleanupInterval() {
|
|
53
|
+
if (cleanupInterval)
|
|
54
|
+
return;
|
|
55
|
+
cleanupInterval = setInterval(() => {
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
for (const [key, entry] of pools.entries()) {
|
|
58
|
+
if (entry.refCount === 0 && now - entry.lastUsed > IDLE_TIMEOUT) {
|
|
59
|
+
entry.pool.end().catch(() => { });
|
|
60
|
+
pools.delete(key);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (pools.size === 0 && cleanupInterval) {
|
|
64
|
+
clearInterval(cleanupInterval);
|
|
65
|
+
cleanupInterval = null;
|
|
66
|
+
}
|
|
67
|
+
}, IDLE_TIMEOUT);
|
|
68
|
+
cleanupInterval.unref();
|
|
69
|
+
}
|
|
70
|
+
async function getPool(config) {
|
|
71
|
+
const key = getPoolKey(config);
|
|
72
|
+
let entry = pools.get(key);
|
|
73
|
+
if (entry) {
|
|
74
|
+
entry.refCount++;
|
|
75
|
+
entry.lastUsed = Date.now();
|
|
76
|
+
return entry.pool;
|
|
77
|
+
}
|
|
78
|
+
const { Pool } = await Promise.resolve().then(() => __importStar(require("../../addon/pg/index.cjs")));
|
|
79
|
+
const pool = new Pool({
|
|
80
|
+
host: config.host,
|
|
81
|
+
port: config.port || 5432,
|
|
82
|
+
database: config.database,
|
|
83
|
+
user: config.user,
|
|
84
|
+
password: config.password,
|
|
85
|
+
connectionString: config.url,
|
|
86
|
+
ssl: config.ssl,
|
|
87
|
+
max: config.max || 10,
|
|
88
|
+
idleTimeoutMillis: config.idleTimeoutMillis || 10000,
|
|
89
|
+
connectionTimeoutMillis: config.connectionTimeoutMillis || 5000,
|
|
90
|
+
});
|
|
91
|
+
entry = {
|
|
92
|
+
pool,
|
|
93
|
+
refCount: 1,
|
|
94
|
+
lastUsed: Date.now(),
|
|
95
|
+
};
|
|
96
|
+
pools.set(key, entry);
|
|
97
|
+
startCleanupInterval();
|
|
98
|
+
return pool;
|
|
99
|
+
}
|
|
100
|
+
function releasePool(config) {
|
|
101
|
+
const key = getPoolKey(config);
|
|
102
|
+
const entry = pools.get(key);
|
|
103
|
+
if (entry && entry.refCount > 0) {
|
|
104
|
+
entry.refCount--;
|
|
105
|
+
entry.lastUsed = Date.now();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function withPool(config, fn) {
|
|
109
|
+
const pool = await getPool(config);
|
|
110
|
+
try {
|
|
111
|
+
return await fn(pool);
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
releasePool(config);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function withClient(config, fn) {
|
|
118
|
+
const pool = await getPool(config);
|
|
119
|
+
const client = await pool.connect();
|
|
120
|
+
try {
|
|
121
|
+
return await fn(client);
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
client.release();
|
|
125
|
+
releasePool(config);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function withTransaction(config, fn) {
|
|
129
|
+
return withClient(config, async (client) => {
|
|
130
|
+
await client.query('BEGIN');
|
|
131
|
+
try {
|
|
132
|
+
const result = await fn(client);
|
|
133
|
+
await client.query('COMMIT');
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
await client.query('ROLLBACK');
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
async function closeAllPools() {
|
|
143
|
+
if (cleanupInterval) {
|
|
144
|
+
clearInterval(cleanupInterval);
|
|
145
|
+
cleanupInterval = null;
|
|
146
|
+
}
|
|
147
|
+
const closePromises = [];
|
|
148
|
+
for (const [key, entry] of pools.entries()) {
|
|
149
|
+
closePromises.push(entry.pool.end());
|
|
150
|
+
pools.delete(key);
|
|
151
|
+
}
|
|
152
|
+
await Promise.all(closePromises);
|
|
153
|
+
}
|
|
154
|
+
function getActivePoolCount() {
|
|
155
|
+
return pools.size;
|
|
156
|
+
}
|
|
@@ -35,22 +35,73 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.findProjectRoot = findProjectRoot;
|
|
37
37
|
exports.getRelqDir = getRelqDir;
|
|
38
|
+
exports.getProjectRoot = getProjectRoot;
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const path = __importStar(require("path"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const CONFIG_FILENAMES = [
|
|
43
|
+
'relq.config.ts',
|
|
44
|
+
'relq.config.js',
|
|
45
|
+
'relq.config.mjs',
|
|
46
|
+
];
|
|
47
|
+
function hasProjectMarker(dir) {
|
|
48
|
+
for (const filename of CONFIG_FILENAMES) {
|
|
49
|
+
if (fs.existsSync(path.join(dir, filename))) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
40
58
|
function findProjectRoot(startDir = process.cwd()) {
|
|
41
59
|
let currentDir = path.resolve(startDir);
|
|
42
60
|
const root = path.parse(currentDir).root;
|
|
61
|
+
const homeDir = os.homedir();
|
|
43
62
|
while (currentDir !== root) {
|
|
44
|
-
|
|
45
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
63
|
+
if (hasProjectMarker(currentDir)) {
|
|
46
64
|
return currentDir;
|
|
47
65
|
}
|
|
66
|
+
if (currentDir === homeDir) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
48
69
|
currentDir = path.dirname(currentDir);
|
|
49
70
|
}
|
|
50
|
-
return
|
|
71
|
+
return null;
|
|
51
72
|
}
|
|
52
73
|
function getRelqDir(startDir = process.cwd()) {
|
|
53
|
-
const projectRoot = findProjectRoot(startDir)
|
|
74
|
+
const projectRoot = findProjectRoot(startDir);
|
|
75
|
+
if (!projectRoot) {
|
|
76
|
+
const colors = {
|
|
77
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
78
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
79
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
80
|
+
};
|
|
81
|
+
console.error('');
|
|
82
|
+
console.error(colors.red('fatal:') + ' not a relq project (or any of the parent directories)');
|
|
83
|
+
console.error('');
|
|
84
|
+
console.error(colors.yellow('hint:') + ` Run ${colors.cyan('relq init')} in your project directory to initialize relq.`);
|
|
85
|
+
console.error('');
|
|
86
|
+
process.exit(128);
|
|
87
|
+
}
|
|
54
88
|
return path.join(projectRoot, '.relq');
|
|
55
89
|
}
|
|
56
|
-
|
|
90
|
+
function getProjectRoot(startDir = process.cwd()) {
|
|
91
|
+
const projectRoot = findProjectRoot(startDir);
|
|
92
|
+
if (!projectRoot) {
|
|
93
|
+
const colors = {
|
|
94
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
95
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
96
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
97
|
+
};
|
|
98
|
+
console.error('');
|
|
99
|
+
console.error(colors.red('fatal:') + ' not a relq project (or any of the parent directories)');
|
|
100
|
+
console.error('');
|
|
101
|
+
console.error(colors.yellow('hint:') + ` Run ${colors.cyan('relq init')} in your project directory to initialize relq.`);
|
|
102
|
+
console.error('');
|
|
103
|
+
process.exit(128);
|
|
104
|
+
}
|
|
105
|
+
return projectRoot;
|
|
106
|
+
}
|
|
107
|
+
exports.default = { findProjectRoot, getRelqDir, getProjectRoot };
|
|
@@ -52,10 +52,15 @@ exports.clearStaged = clearStaged;
|
|
|
52
52
|
exports.hasStaged = hasStaged;
|
|
53
53
|
exports.loadSnapshot = loadSnapshot;
|
|
54
54
|
exports.saveSnapshot = saveSnapshot;
|
|
55
|
+
exports.hashFileContent = hashFileContent;
|
|
56
|
+
exports.getSavedFileHash = getSavedFileHash;
|
|
57
|
+
exports.saveFileHash = saveFileHash;
|
|
58
|
+
exports.detectFileChanges = detectFileChanges;
|
|
55
59
|
exports.loadWorkingState = loadWorkingState;
|
|
56
60
|
exports.saveWorkingState = saveWorkingState;
|
|
57
61
|
exports.getOrCreateWorkingState = getOrCreateWorkingState;
|
|
58
62
|
exports.addUnstagedChanges = addUnstagedChanges;
|
|
63
|
+
exports.clearUnstagedChanges = clearUnstagedChanges;
|
|
59
64
|
exports.stageChanges = stageChanges;
|
|
60
65
|
exports.unstageChanges = unstageChanges;
|
|
61
66
|
exports.clearWorkingState = clearWorkingState;
|
|
@@ -83,6 +88,7 @@ const STAGED_FILE = 'staged.json';
|
|
|
83
88
|
const WORKING_FILE = 'working.json';
|
|
84
89
|
const SNAPSHOT_FILE = 'snapshot.json';
|
|
85
90
|
const COMMITS_DIR = 'commits';
|
|
91
|
+
const FILE_HASH_FILE = 'file_hash';
|
|
86
92
|
function isInitialized(projectRoot = process.cwd()) {
|
|
87
93
|
const relqPath = path.join(projectRoot, RELQ_DIR);
|
|
88
94
|
const headPath = path.join(relqPath, HEAD_FILE);
|
|
@@ -247,6 +253,41 @@ function saveSnapshot(schema, projectRoot = process.cwd()) {
|
|
|
247
253
|
const snapshotPath = path.join(projectRoot, RELQ_DIR, SNAPSHOT_FILE);
|
|
248
254
|
fs.writeFileSync(snapshotPath, JSON.stringify(schema, null, 2), 'utf-8');
|
|
249
255
|
}
|
|
256
|
+
function hashFileContent(content) {
|
|
257
|
+
return crypto.createHash('sha1').update(content, 'utf8').digest('hex');
|
|
258
|
+
}
|
|
259
|
+
function getSavedFileHash(projectRoot = process.cwd()) {
|
|
260
|
+
const hashPath = path.join(projectRoot, RELQ_DIR, FILE_HASH_FILE);
|
|
261
|
+
if (!fs.existsSync(hashPath)) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
return fs.readFileSync(hashPath, 'utf-8').trim() || null;
|
|
265
|
+
}
|
|
266
|
+
function saveFileHash(hash, projectRoot = process.cwd()) {
|
|
267
|
+
const hashPath = path.join(projectRoot, RELQ_DIR, FILE_HASH_FILE);
|
|
268
|
+
fs.writeFileSync(hashPath, hash, 'utf-8');
|
|
269
|
+
}
|
|
270
|
+
function detectFileChanges(schemaPath, projectRoot = process.cwd()) {
|
|
271
|
+
if (!fs.existsSync(schemaPath)) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const currentContent = fs.readFileSync(schemaPath, 'utf-8');
|
|
275
|
+
const currentHash = hashFileContent(currentContent);
|
|
276
|
+
const savedHash = getSavedFileHash(projectRoot);
|
|
277
|
+
if (!savedHash || currentHash === savedHash) {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
id: `file_${currentHash.substring(0, 8)}`,
|
|
282
|
+
type: 'ALTER',
|
|
283
|
+
objectType: 'SCHEMA_FILE',
|
|
284
|
+
objectName: path.basename(schemaPath),
|
|
285
|
+
before: { hash: savedHash },
|
|
286
|
+
after: { hash: currentHash },
|
|
287
|
+
sql: '-- Schema file modified (comments, formatting, or manual edits)',
|
|
288
|
+
detectedAt: new Date().toISOString(),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
250
291
|
function loadWorkingState(projectRoot = process.cwd()) {
|
|
251
292
|
const workingPath = path.join(projectRoot, RELQ_DIR, WORKING_FILE);
|
|
252
293
|
if (!fs.existsSync(workingPath)) {
|
|
@@ -281,6 +322,12 @@ function addUnstagedChanges(changes, projectRoot = process.cwd()) {
|
|
|
281
322
|
state.timestamp = new Date().toISOString();
|
|
282
323
|
saveWorkingState(state, projectRoot);
|
|
283
324
|
}
|
|
325
|
+
function clearUnstagedChanges(projectRoot = process.cwd()) {
|
|
326
|
+
const state = getOrCreateWorkingState(projectRoot);
|
|
327
|
+
state.unstaged = [];
|
|
328
|
+
state.timestamp = new Date().toISOString();
|
|
329
|
+
saveWorkingState(state, projectRoot);
|
|
330
|
+
}
|
|
284
331
|
function stageChanges(patterns, projectRoot = process.cwd()) {
|
|
285
332
|
const state = getOrCreateWorkingState(projectRoot);
|
|
286
333
|
const staged = [];
|