relq 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +862 -0
- package/dist/addons/buffer.js +1869 -0
- package/dist/addons/pg-cursor.js +1425 -0
- package/dist/addons/pg-format.js +2248 -0
- package/dist/addons/pg.js +4790 -0
- package/dist/bin/relq.js +2 -0
- package/dist/cjs/cache/index.cjs +9 -0
- package/dist/cjs/cache/query-cache.cjs +311 -0
- package/dist/cjs/cli/commands/add.cjs +82 -0
- package/dist/cjs/cli/commands/commit.cjs +145 -0
- package/dist/cjs/cli/commands/diff.cjs +84 -0
- package/dist/cjs/cli/commands/export.cjs +333 -0
- package/dist/cjs/cli/commands/fetch.cjs +59 -0
- package/dist/cjs/cli/commands/generate.cjs +242 -0
- package/dist/cjs/cli/commands/history.cjs +165 -0
- package/dist/cjs/cli/commands/import.cjs +524 -0
- package/dist/cjs/cli/commands/init.cjs +437 -0
- package/dist/cjs/cli/commands/introspect.cjs +142 -0
- package/dist/cjs/cli/commands/log.cjs +62 -0
- package/dist/cjs/cli/commands/migrate.cjs +167 -0
- package/dist/cjs/cli/commands/pull.cjs +410 -0
- package/dist/cjs/cli/commands/push.cjs +165 -0
- package/dist/cjs/cli/commands/rollback.cjs +169 -0
- package/dist/cjs/cli/commands/status.cjs +110 -0
- package/dist/cjs/cli/commands/sync.cjs +79 -0
- package/dist/cjs/cli/index.cjs +275 -0
- package/dist/cjs/cli/utils/change-tracker.cjs +446 -0
- package/dist/cjs/cli/utils/commit-manager.cjs +239 -0
- package/dist/cjs/cli/utils/config-loader.cjs +127 -0
- package/dist/cjs/cli/utils/env-loader.cjs +62 -0
- package/dist/cjs/cli/utils/fast-introspect.cjs +398 -0
- package/dist/cjs/cli/utils/git-utils.cjs +404 -0
- package/dist/cjs/cli/utils/migration-generator.cjs +269 -0
- package/dist/cjs/cli/utils/relqignore.cjs +114 -0
- package/dist/cjs/cli/utils/repo-manager.cjs +515 -0
- package/dist/cjs/cli/utils/schema-comparator.cjs +313 -0
- package/dist/cjs/cli/utils/schema-diff.cjs +284 -0
- package/dist/cjs/cli/utils/schema-hash.cjs +108 -0
- package/dist/cjs/cli/utils/schema-introspect.cjs +455 -0
- package/dist/cjs/cli/utils/snapshot-manager.cjs +223 -0
- package/dist/cjs/cli/utils/spinner.cjs +108 -0
- package/dist/cjs/cli/utils/sql-generator.cjs +520 -0
- package/dist/cjs/cli/utils/sql-parser.cjs +999 -0
- package/dist/cjs/cli/utils/type-generator.cjs +2061 -0
- package/dist/cjs/condition/array-condition-builder.cjs +503 -0
- package/dist/cjs/condition/array-numeric-condition-builder.cjs +186 -0
- package/dist/cjs/condition/array-specialized-condition-builder.cjs +206 -0
- package/dist/cjs/condition/array-string-condition-builder.cjs +146 -0
- package/dist/cjs/condition/base-condition-builder.cjs +2 -0
- package/dist/cjs/condition/condition-collector.cjs +284 -0
- package/dist/cjs/condition/fulltext-condition-builder.cjs +61 -0
- package/dist/cjs/condition/geometric-condition-builder.cjs +208 -0
- package/dist/cjs/condition/index.cjs +25 -0
- package/dist/cjs/condition/jsonb-condition-builder.cjs +160 -0
- package/dist/cjs/condition/network-condition-builder.cjs +230 -0
- package/dist/cjs/condition/range-condition-builder.cjs +82 -0
- package/dist/cjs/config/config.cjs +190 -0
- package/dist/cjs/config/index.cjs +9 -0
- package/dist/cjs/constants/pg-values.cjs +68 -0
- package/dist/cjs/copy/copy-builder.cjs +316 -0
- package/dist/cjs/copy/index.cjs +6 -0
- package/dist/cjs/core/query-builder.cjs +440 -0
- package/dist/cjs/core/relq-client.cjs +1831 -0
- package/dist/cjs/core/typed-kuery-client.cjs +2 -0
- package/dist/cjs/count/count-builder.cjs +88 -0
- package/dist/cjs/count/index.cjs +5 -0
- package/dist/cjs/cte/cte-builder.cjs +89 -0
- package/dist/cjs/cte/index.cjs +5 -0
- package/dist/cjs/ddl/function.cjs +48 -0
- package/dist/cjs/ddl/index.cjs +7 -0
- package/dist/cjs/ddl/sql.cjs +54 -0
- package/dist/cjs/delete/delete-builder.cjs +135 -0
- package/dist/cjs/delete/index.cjs +5 -0
- package/dist/cjs/errors/relq-errors.cjs +329 -0
- package/dist/cjs/examples/fulltext-search-test.cjs +122 -0
- package/dist/cjs/explain/explain-builder.cjs +99 -0
- package/dist/cjs/explain/index.cjs +5 -0
- package/dist/cjs/function/create-function-builder.cjs +196 -0
- package/dist/cjs/function/index.cjs +6 -0
- package/dist/cjs/functions/advanced-functions.cjs +241 -0
- package/dist/cjs/functions/case-builder.cjs +66 -0
- package/dist/cjs/functions/geometric-functions.cjs +104 -0
- package/dist/cjs/functions/index.cjs +184 -0
- package/dist/cjs/functions/network-functions.cjs +86 -0
- package/dist/cjs/functions/sql-functions.cjs +431 -0
- package/dist/cjs/index.cjs +164 -0
- package/dist/cjs/indexing/create-index-builder.cjs +187 -0
- package/dist/cjs/indexing/drop-index-builder.cjs +89 -0
- package/dist/cjs/indexing/index-types.cjs +2 -0
- package/dist/cjs/indexing/index.cjs +8 -0
- package/dist/cjs/insert/conflict-builder.cjs +173 -0
- package/dist/cjs/insert/index.cjs +5 -0
- package/dist/cjs/insert/insert-builder.cjs +254 -0
- package/dist/cjs/introspect/index.cjs +229 -0
- package/dist/cjs/maintenance/index.cjs +6 -0
- package/dist/cjs/maintenance/vacuum-builder.cjs +166 -0
- package/dist/cjs/pubsub/index.cjs +7 -0
- package/dist/cjs/pubsub/listen-notify-builder.cjs +57 -0
- package/dist/cjs/pubsub/listener-connection.cjs +180 -0
- package/dist/cjs/raw/index.cjs +5 -0
- package/dist/cjs/raw/raw-query-builder.cjs +27 -0
- package/dist/cjs/schema/index.cjs +15 -0
- package/dist/cjs/schema/schema-builder.cjs +1167 -0
- package/dist/cjs/schema-builder.cjs +21 -0
- package/dist/cjs/schema-definition/column-types.cjs +829 -0
- package/dist/cjs/schema-definition/index.cjs +62 -0
- package/dist/cjs/schema-definition/introspection.cjs +620 -0
- package/dist/cjs/schema-definition/partitions.cjs +129 -0
- package/dist/cjs/schema-definition/pg-enum.cjs +76 -0
- package/dist/cjs/schema-definition/pg-function.cjs +91 -0
- package/dist/cjs/schema-definition/pg-sequence.cjs +56 -0
- package/dist/cjs/schema-definition/pg-trigger.cjs +108 -0
- package/dist/cjs/schema-definition/relations.cjs +98 -0
- package/dist/cjs/schema-definition/sql-expressions.cjs +202 -0
- package/dist/cjs/schema-definition/table-definition.cjs +636 -0
- package/dist/cjs/select/aggregate-builder.cjs +179 -0
- package/dist/cjs/select/index.cjs +5 -0
- package/dist/cjs/select/select-builder.cjs +233 -0
- package/dist/cjs/sequence/index.cjs +7 -0
- package/dist/cjs/sequence/sequence-builder.cjs +264 -0
- package/dist/cjs/table/alter-table-builder.cjs +146 -0
- package/dist/cjs/table/constraint-builder.cjs +102 -0
- package/dist/cjs/table/create-table-builder.cjs +248 -0
- package/dist/cjs/table/index.cjs +17 -0
- package/dist/cjs/table/partition-builder.cjs +131 -0
- package/dist/cjs/table/truncate-builder.cjs +70 -0
- package/dist/cjs/transaction/index.cjs +6 -0
- package/dist/cjs/transaction/transaction-builder.cjs +78 -0
- package/dist/cjs/trigger/create-trigger-builder.cjs +174 -0
- package/dist/cjs/trigger/index.cjs +6 -0
- package/dist/cjs/types/aggregate-types.cjs +2 -0
- package/dist/cjs/types/config-types.cjs +40 -0
- package/dist/cjs/types/inference-types.cjs +18 -0
- package/dist/cjs/types/pagination-types.cjs +7 -0
- package/dist/cjs/types/result-types.cjs +2 -0
- package/dist/cjs/types/schema-types.cjs +2 -0
- package/dist/cjs/types/subscription-types.cjs +2 -0
- package/dist/cjs/types.cjs +2 -0
- package/dist/cjs/update/array-update-builder.cjs +205 -0
- package/dist/cjs/update/index.cjs +13 -0
- package/dist/cjs/update/update-builder.cjs +195 -0
- package/dist/cjs/utils/case-converter.cjs +58 -0
- package/dist/cjs/utils/environment-detection.cjs +120 -0
- package/dist/cjs/utils/index.cjs +10 -0
- package/dist/cjs/utils/pool-defaults.cjs +106 -0
- package/dist/cjs/utils/type-coercion.cjs +118 -0
- package/dist/cjs/view/create-view-builder.cjs +180 -0
- package/dist/cjs/view/index.cjs +7 -0
- package/dist/cjs/window/index.cjs +5 -0
- package/dist/cjs/window/window-builder.cjs +80 -0
- package/dist/config.cjs +1 -0
- package/dist/config.d.ts +655 -0
- package/dist/config.js +1 -0
- package/dist/esm/cache/index.js +1 -0
- package/dist/esm/cache/query-cache.js +303 -0
- package/dist/esm/cli/commands/add.js +78 -0
- package/dist/esm/cli/commands/commit.js +109 -0
- package/dist/esm/cli/commands/diff.js +81 -0
- package/dist/esm/cli/commands/export.js +297 -0
- package/dist/esm/cli/commands/fetch.js +56 -0
- package/dist/esm/cli/commands/generate.js +206 -0
- package/dist/esm/cli/commands/history.js +129 -0
- package/dist/esm/cli/commands/import.js +488 -0
- package/dist/esm/cli/commands/init.js +401 -0
- package/dist/esm/cli/commands/introspect.js +106 -0
- package/dist/esm/cli/commands/log.js +59 -0
- package/dist/esm/cli/commands/migrate.js +131 -0
- package/dist/esm/cli/commands/pull.js +374 -0
- package/dist/esm/cli/commands/push.js +129 -0
- package/dist/esm/cli/commands/rollback.js +133 -0
- package/dist/esm/cli/commands/status.js +107 -0
- package/dist/esm/cli/commands/sync.js +76 -0
- package/dist/esm/cli/index.js +240 -0
- package/dist/esm/cli/utils/change-tracker.js +405 -0
- package/dist/esm/cli/utils/commit-manager.js +191 -0
- package/dist/esm/cli/utils/config-loader.js +86 -0
- package/dist/esm/cli/utils/env-loader.js +57 -0
- package/dist/esm/cli/utils/fast-introspect.js +362 -0
- package/dist/esm/cli/utils/git-utils.js +347 -0
- package/dist/esm/cli/utils/migration-generator.js +263 -0
- package/dist/esm/cli/utils/relqignore.js +74 -0
- package/dist/esm/cli/utils/repo-manager.js +444 -0
- package/dist/esm/cli/utils/schema-comparator.js +307 -0
- package/dist/esm/cli/utils/schema-diff.js +276 -0
- package/dist/esm/cli/utils/schema-hash.js +69 -0
- package/dist/esm/cli/utils/schema-introspect.js +418 -0
- package/dist/esm/cli/utils/snapshot-manager.js +179 -0
- package/dist/esm/cli/utils/spinner.js +101 -0
- package/dist/esm/cli/utils/sql-generator.js +504 -0
- package/dist/esm/cli/utils/sql-parser.js +992 -0
- package/dist/esm/cli/utils/type-generator.js +2058 -0
- package/dist/esm/condition/array-condition-builder.js +495 -0
- package/dist/esm/condition/array-numeric-condition-builder.js +182 -0
- package/dist/esm/condition/array-specialized-condition-builder.js +200 -0
- package/dist/esm/condition/array-string-condition-builder.js +142 -0
- package/dist/esm/condition/base-condition-builder.js +1 -0
- package/dist/esm/condition/condition-collector.js +275 -0
- package/dist/esm/condition/fulltext-condition-builder.js +53 -0
- package/dist/esm/condition/geometric-condition-builder.js +200 -0
- package/dist/esm/condition/index.js +7 -0
- package/dist/esm/condition/jsonb-condition-builder.js +152 -0
- package/dist/esm/condition/network-condition-builder.js +222 -0
- package/dist/esm/condition/range-condition-builder.js +74 -0
- package/dist/esm/config/config.js +150 -0
- package/dist/esm/config/index.js +1 -0
- package/dist/esm/constants/pg-values.js +63 -0
- package/dist/esm/copy/copy-builder.js +308 -0
- package/dist/esm/copy/index.js +1 -0
- package/dist/esm/core/query-builder.js +426 -0
- package/dist/esm/core/relq-client.js +1791 -0
- package/dist/esm/core/typed-kuery-client.js +1 -0
- package/dist/esm/count/count-builder.js +81 -0
- package/dist/esm/count/index.js +1 -0
- package/dist/esm/cte/cte-builder.js +82 -0
- package/dist/esm/cte/index.js +1 -0
- package/dist/esm/ddl/function.js +45 -0
- package/dist/esm/ddl/index.js +2 -0
- package/dist/esm/ddl/sql.js +51 -0
- package/dist/esm/delete/delete-builder.js +128 -0
- package/dist/esm/delete/index.js +1 -0
- package/dist/esm/errors/relq-errors.js +310 -0
- package/dist/esm/examples/fulltext-search-test.js +117 -0
- package/dist/esm/explain/explain-builder.js +95 -0
- package/dist/esm/explain/index.js +1 -0
- package/dist/esm/function/create-function-builder.js +188 -0
- package/dist/esm/function/index.js +1 -0
- package/dist/esm/functions/advanced-functions.js +231 -0
- package/dist/esm/functions/case-builder.js +58 -0
- package/dist/esm/functions/geometric-functions.js +97 -0
- package/dist/esm/functions/index.js +171 -0
- package/dist/esm/functions/network-functions.js +79 -0
- package/dist/esm/functions/sql-functions.js +421 -0
- package/dist/esm/index.js +34 -0
- package/dist/esm/indexing/create-index-builder.js +180 -0
- package/dist/esm/indexing/drop-index-builder.js +81 -0
- package/dist/esm/indexing/index-types.js +1 -0
- package/dist/esm/indexing/index.js +2 -0
- package/dist/esm/insert/conflict-builder.js +162 -0
- package/dist/esm/insert/index.js +1 -0
- package/dist/esm/insert/insert-builder.js +247 -0
- package/dist/esm/introspect/index.js +224 -0
- package/dist/esm/maintenance/index.js +1 -0
- package/dist/esm/maintenance/vacuum-builder.js +158 -0
- package/dist/esm/pubsub/index.js +1 -0
- package/dist/esm/pubsub/listen-notify-builder.js +48 -0
- package/dist/esm/pubsub/listener-connection.js +173 -0
- package/dist/esm/raw/index.js +1 -0
- package/dist/esm/raw/raw-query-builder.js +20 -0
- package/dist/esm/schema/index.js +1 -0
- package/dist/esm/schema/schema-builder.js +1150 -0
- package/dist/esm/schema-builder.js +2 -0
- package/dist/esm/schema-definition/column-types.js +738 -0
- package/dist/esm/schema-definition/index.js +10 -0
- package/dist/esm/schema-definition/introspection.js +614 -0
- package/dist/esm/schema-definition/partitions.js +123 -0
- package/dist/esm/schema-definition/pg-enum.js +70 -0
- package/dist/esm/schema-definition/pg-function.js +85 -0
- package/dist/esm/schema-definition/pg-sequence.js +50 -0
- package/dist/esm/schema-definition/pg-trigger.js +102 -0
- package/dist/esm/schema-definition/relations.js +90 -0
- package/dist/esm/schema-definition/sql-expressions.js +193 -0
- package/dist/esm/schema-definition/table-definition.js +630 -0
- package/dist/esm/select/aggregate-builder.js +172 -0
- package/dist/esm/select/index.js +1 -0
- package/dist/esm/select/select-builder.js +226 -0
- package/dist/esm/sequence/index.js +1 -0
- package/dist/esm/sequence/sequence-builder.js +255 -0
- package/dist/esm/table/alter-table-builder.js +138 -0
- package/dist/esm/table/constraint-builder.js +95 -0
- package/dist/esm/table/create-table-builder.js +241 -0
- package/dist/esm/table/index.js +5 -0
- package/dist/esm/table/partition-builder.js +121 -0
- package/dist/esm/table/truncate-builder.js +63 -0
- package/dist/esm/transaction/index.js +1 -0
- package/dist/esm/transaction/transaction-builder.js +70 -0
- package/dist/esm/trigger/create-trigger-builder.js +166 -0
- package/dist/esm/trigger/index.js +1 -0
- package/dist/esm/types/aggregate-types.js +1 -0
- package/dist/esm/types/config-types.js +36 -0
- package/dist/esm/types/inference-types.js +12 -0
- package/dist/esm/types/pagination-types.js +4 -0
- package/dist/esm/types/result-types.js +1 -0
- package/dist/esm/types/schema-types.js +1 -0
- package/dist/esm/types/subscription-types.js +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/update/array-update-builder.js +192 -0
- package/dist/esm/update/index.js +2 -0
- package/dist/esm/update/update-builder.js +188 -0
- package/dist/esm/utils/case-converter.js +55 -0
- package/dist/esm/utils/environment-detection.js +113 -0
- package/dist/esm/utils/index.js +2 -0
- package/dist/esm/utils/pool-defaults.js +100 -0
- package/dist/esm/utils/type-coercion.js +110 -0
- package/dist/esm/view/create-view-builder.js +171 -0
- package/dist/esm/view/index.js +1 -0
- package/dist/esm/window/index.js +1 -0
- package/dist/esm/window/window-builder.js +73 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +10341 -0
- package/dist/index.js +1 -0
- package/dist/schema-builder.cjs +1 -0
- package/dist/schema-builder.d.ts +2272 -0
- package/dist/schema-builder.js +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,404 @@
|
|
|
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.colors = void 0;
|
|
37
|
+
exports.error = error;
|
|
38
|
+
exports.fatal = fatal;
|
|
39
|
+
exports.warning = warning;
|
|
40
|
+
exports.hint = hint;
|
|
41
|
+
exports.success = success;
|
|
42
|
+
exports.info = info;
|
|
43
|
+
exports.getWorkingTreeStatus = getWorkingTreeStatus;
|
|
44
|
+
exports.requireRepository = requireRepository;
|
|
45
|
+
exports.requireCleanWorkingTree = requireCleanWorkingTree;
|
|
46
|
+
exports.printDirtyWorkingTreeError = printDirtyWorkingTreeError;
|
|
47
|
+
exports.detectConflicts = detectConflicts;
|
|
48
|
+
exports.printConflictError = printConflictError;
|
|
49
|
+
exports.checkUncommittedChanges = checkUncommittedChanges;
|
|
50
|
+
exports.printMergeStrategyHelp = printMergeStrategyHelp;
|
|
51
|
+
exports.validatePostgresSQL = validatePostgresSQL;
|
|
52
|
+
exports.readSQLFile = readSQLFile;
|
|
53
|
+
exports.createSpinner = createSpinner;
|
|
54
|
+
exports.confirm = confirm;
|
|
55
|
+
exports.select = select;
|
|
56
|
+
exports.formatBytes = formatBytes;
|
|
57
|
+
exports.formatDuration = formatDuration;
|
|
58
|
+
const fs = __importStar(require("fs"));
|
|
59
|
+
const path = __importStar(require("path"));
|
|
60
|
+
const repo_manager_1 = require("./repo-manager.cjs");
|
|
61
|
+
const isColorSupported = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
62
|
+
exports.colors = {
|
|
63
|
+
red: (s) => isColorSupported ? `\x1b[31m${s}\x1b[0m` : s,
|
|
64
|
+
green: (s) => isColorSupported ? `\x1b[32m${s}\x1b[0m` : s,
|
|
65
|
+
yellow: (s) => isColorSupported ? `\x1b[33m${s}\x1b[0m` : s,
|
|
66
|
+
blue: (s) => isColorSupported ? `\x1b[34m${s}\x1b[0m` : s,
|
|
67
|
+
magenta: (s) => isColorSupported ? `\x1b[35m${s}\x1b[0m` : s,
|
|
68
|
+
cyan: (s) => isColorSupported ? `\x1b[36m${s}\x1b[0m` : s,
|
|
69
|
+
white: (s) => isColorSupported ? `\x1b[37m${s}\x1b[0m` : s,
|
|
70
|
+
gray: (s) => isColorSupported ? `\x1b[90m${s}\x1b[0m` : s,
|
|
71
|
+
bold: (s) => isColorSupported ? `\x1b[1m${s}\x1b[0m` : s,
|
|
72
|
+
dim: (s) => isColorSupported ? `\x1b[2m${s}\x1b[0m` : s,
|
|
73
|
+
};
|
|
74
|
+
function error(message) {
|
|
75
|
+
console.error(`${exports.colors.red('error:')} ${message}`);
|
|
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
|
+
}
|
|
90
|
+
function info(message) {
|
|
91
|
+
console.log(message);
|
|
92
|
+
}
|
|
93
|
+
function getWorkingTreeStatus(projectRoot = process.cwd()) {
|
|
94
|
+
const initialized = (0, repo_manager_1.isInitialized)(projectRoot);
|
|
95
|
+
const head = initialized ? (0, repo_manager_1.getHead)(projectRoot) : null;
|
|
96
|
+
const headCommit = head ? (0, repo_manager_1.loadCommit)(head, projectRoot) : null;
|
|
97
|
+
const staged = initialized ? (0, repo_manager_1.getStagedChanges)(projectRoot) : [];
|
|
98
|
+
const unstaged = initialized ? (0, repo_manager_1.getUnstagedChanges)(projectRoot) : [];
|
|
99
|
+
return {
|
|
100
|
+
isInitialized: initialized,
|
|
101
|
+
hasHead: !!head,
|
|
102
|
+
headHash: head,
|
|
103
|
+
headMessage: headCommit?.message || null,
|
|
104
|
+
stagedChanges: staged,
|
|
105
|
+
unstagedChanges: unstaged,
|
|
106
|
+
isClean: staged.length === 0 && unstaged.length === 0,
|
|
107
|
+
hasUncommittedChanges: staged.length > 0,
|
|
108
|
+
hasUnstagedChanges: unstaged.length > 0,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function requireRepository(projectRoot = process.cwd()) {
|
|
112
|
+
if (!(0, repo_manager_1.isInitialized)(projectRoot)) {
|
|
113
|
+
fatal('not a relq repository (or any of the parent directories): .relq');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function requireCleanWorkingTree(projectRoot = process.cwd(), operation = 'operation') {
|
|
117
|
+
const status = getWorkingTreeStatus(projectRoot);
|
|
118
|
+
if (status.isClean) {
|
|
119
|
+
return { clean: true };
|
|
120
|
+
}
|
|
121
|
+
const lines = [];
|
|
122
|
+
if (status.hasUnstagedChanges && status.hasUncommittedChanges) {
|
|
123
|
+
lines.push(`Your local changes would be overwritten by ${operation}.`);
|
|
124
|
+
lines.push(`Please commit your changes or stash them before you ${operation}.`);
|
|
125
|
+
}
|
|
126
|
+
else if (status.hasUncommittedChanges) {
|
|
127
|
+
lines.push(`You have uncommitted changes.`);
|
|
128
|
+
lines.push(`Please commit your changes before you ${operation}.`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
lines.push(`You have unstaged changes.`);
|
|
132
|
+
lines.push(`Please stage and commit your changes before you ${operation}.`);
|
|
133
|
+
}
|
|
134
|
+
return { clean: false, message: lines.join('\n') };
|
|
135
|
+
}
|
|
136
|
+
function printDirtyWorkingTreeError(status, operation) {
|
|
137
|
+
console.log('');
|
|
138
|
+
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}.`);
|
|
141
|
+
}
|
|
142
|
+
else if (status.hasUncommittedChanges) {
|
|
143
|
+
error(`You have uncommitted changes.`);
|
|
144
|
+
hint(`Please commit your changes before you ${operation}.`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
error(`You have unstaged changes.`);
|
|
148
|
+
hint(`Please stage and commit your changes before you ${operation}.`);
|
|
149
|
+
}
|
|
150
|
+
console.log('');
|
|
151
|
+
if (status.hasUncommittedChanges) {
|
|
152
|
+
console.log(`Changes to be committed:`);
|
|
153
|
+
console.log(` ${exports.colors.gray('(use "relq restore --staged <file>..." to unstage)')}`);
|
|
154
|
+
console.log('');
|
|
155
|
+
for (const change of status.stagedChanges.slice(0, 10)) {
|
|
156
|
+
const prefix = change.type === 'CREATE' ? 'new' : change.type === 'DROP' ? 'deleted' : 'modified';
|
|
157
|
+
const color = change.type === 'CREATE' ? exports.colors.green : change.type === 'DROP' ? exports.colors.red : exports.colors.yellow;
|
|
158
|
+
console.log(`\t${color(`${prefix}:`.padEnd(12))}${change.objectName}`);
|
|
159
|
+
}
|
|
160
|
+
if (status.stagedChanges.length > 10) {
|
|
161
|
+
console.log(`\t${exports.colors.gray(`... and ${status.stagedChanges.length - 10} more`)}`);
|
|
162
|
+
}
|
|
163
|
+
console.log('');
|
|
164
|
+
}
|
|
165
|
+
if (status.hasUnstagedChanges) {
|
|
166
|
+
console.log(`Changes not staged for commit:`);
|
|
167
|
+
console.log(` ${exports.colors.gray('(use "relq add <file>..." to update what will be committed)')}`);
|
|
168
|
+
console.log(` ${exports.colors.gray('(use "relq restore <file>..." to discard changes in working directory)')}`);
|
|
169
|
+
console.log('');
|
|
170
|
+
for (const change of status.unstagedChanges.slice(0, 10)) {
|
|
171
|
+
const prefix = change.type === 'CREATE' ? 'new' : change.type === 'DROP' ? 'deleted' : 'modified';
|
|
172
|
+
const color = change.type === 'CREATE' ? exports.colors.green : change.type === 'DROP' ? exports.colors.red : exports.colors.yellow;
|
|
173
|
+
console.log(`\t${color(`${prefix}:`.padEnd(12))}${change.objectName}`);
|
|
174
|
+
}
|
|
175
|
+
if (status.unstagedChanges.length > 10) {
|
|
176
|
+
console.log(`\t${exports.colors.gray(`... and ${status.unstagedChanges.length - 10} more`)}`);
|
|
177
|
+
}
|
|
178
|
+
console.log('');
|
|
179
|
+
}
|
|
180
|
+
console.log('Aborting.');
|
|
181
|
+
}
|
|
182
|
+
function detectConflicts(localChanges, incomingChanges) {
|
|
183
|
+
const conflicts = [];
|
|
184
|
+
const localByKey = new Map();
|
|
185
|
+
for (const change of localChanges) {
|
|
186
|
+
const key = `${change.objectType}:${change.parentName || ''}:${change.objectName}`;
|
|
187
|
+
localByKey.set(key, change);
|
|
188
|
+
}
|
|
189
|
+
const incomingByKey = new Map();
|
|
190
|
+
for (const change of incomingChanges) {
|
|
191
|
+
const key = `${change.objectType}:${change.parentName || ''}:${change.objectName}`;
|
|
192
|
+
incomingByKey.set(key, change);
|
|
193
|
+
}
|
|
194
|
+
for (const [key, localChange] of localByKey) {
|
|
195
|
+
const incomingChange = incomingByKey.get(key);
|
|
196
|
+
if (incomingChange) {
|
|
197
|
+
conflicts.push({
|
|
198
|
+
objectType: localChange.objectType,
|
|
199
|
+
objectName: localChange.objectName,
|
|
200
|
+
localChange,
|
|
201
|
+
incomingChange,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
hasConflicts: conflicts.length > 0,
|
|
207
|
+
conflicts,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function printConflictError(conflictInfo, operation) {
|
|
211
|
+
console.log('');
|
|
212
|
+
error(`Automatic ${operation} failed; fix conflicts and then commit the result.`);
|
|
213
|
+
console.log('');
|
|
214
|
+
console.log(`CONFLICT (content): Merge conflict in schema`);
|
|
215
|
+
console.log('');
|
|
216
|
+
for (const conflict of conflictInfo.conflicts.slice(0, 10)) {
|
|
217
|
+
console.log(` ${exports.colors.red('both modified:')} ${conflict.objectType.toLowerCase()} ${conflict.objectName}`);
|
|
218
|
+
}
|
|
219
|
+
if (conflictInfo.conflicts.length > 10) {
|
|
220
|
+
console.log(` ${exports.colors.gray(`... and ${conflictInfo.conflicts.length - 10} more conflicts`)}`);
|
|
221
|
+
}
|
|
222
|
+
console.log('');
|
|
223
|
+
hint(`Fix conflicts manually and use:`);
|
|
224
|
+
hint(` relq add . - to mark resolution`);
|
|
225
|
+
hint(` relq commit - to complete the ${operation}`);
|
|
226
|
+
console.log('');
|
|
227
|
+
hint(`Or abort the ${operation} with:`);
|
|
228
|
+
hint(` relq ${operation} --abort`);
|
|
229
|
+
console.log('');
|
|
230
|
+
}
|
|
231
|
+
function checkUncommittedChanges(projectRoot = process.cwd()) {
|
|
232
|
+
const status = getWorkingTreeStatus(projectRoot);
|
|
233
|
+
if (status.isClean) {
|
|
234
|
+
return { status: 'clean' };
|
|
235
|
+
}
|
|
236
|
+
if (status.hasUnstagedChanges) {
|
|
237
|
+
return { status: 'needs_staging', changes: status.unstagedChanges };
|
|
238
|
+
}
|
|
239
|
+
if (status.hasUncommittedChanges) {
|
|
240
|
+
return { status: 'needs_commit', changes: status.stagedChanges };
|
|
241
|
+
}
|
|
242
|
+
return { status: 'clean' };
|
|
243
|
+
}
|
|
244
|
+
function printMergeStrategyHelp() {
|
|
245
|
+
console.log('');
|
|
246
|
+
console.log('Resolution options:');
|
|
247
|
+
console.log(` ${exports.colors.cyan('--theirs')} Accept all incoming changes (overwrite local)`);
|
|
248
|
+
console.log(` ${exports.colors.cyan('--ours')} Keep all local changes (reject incoming)`);
|
|
249
|
+
console.log(` ${exports.colors.cyan('--force')} Force operation, overwrite local changes`);
|
|
250
|
+
console.log(` ${exports.colors.cyan('--abort')} Abort and restore previous state`);
|
|
251
|
+
console.log('');
|
|
252
|
+
}
|
|
253
|
+
function validatePostgresSQL(content) {
|
|
254
|
+
const errors = [];
|
|
255
|
+
const warnings = [];
|
|
256
|
+
if (!content.trim()) {
|
|
257
|
+
errors.push('SQL file is empty');
|
|
258
|
+
return { valid: false, errors, warnings };
|
|
259
|
+
}
|
|
260
|
+
const hasValidStatements = /\b(CREATE|ALTER|DROP|INSERT|UPDATE|DELETE|SELECT|GRANT|REVOKE|COMMENT)\b/i.test(content);
|
|
261
|
+
if (!hasValidStatements) {
|
|
262
|
+
errors.push('No valid SQL statements found');
|
|
263
|
+
}
|
|
264
|
+
let contentForQuoteCheck = content;
|
|
265
|
+
contentForQuoteCheck = contentForQuoteCheck.replace(/--[^\n]*/g, '');
|
|
266
|
+
contentForQuoteCheck = contentForQuoteCheck.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
267
|
+
contentForQuoteCheck = contentForQuoteCheck.replace(/\$([a-zA-Z_]*)\$[\s\S]*?\$\1\$/g, '');
|
|
268
|
+
const openParens = (contentForQuoteCheck.match(/\(/g) || []).length;
|
|
269
|
+
const closeParens = (contentForQuoteCheck.match(/\)/g) || []).length;
|
|
270
|
+
if (Math.abs(openParens - closeParens) > 5) {
|
|
271
|
+
errors.push(`Significantly unbalanced parentheses: ${openParens} opening, ${closeParens} closing`);
|
|
272
|
+
}
|
|
273
|
+
const hasPostgresPatterns = (/\bSERIAL\b/i.test(content) ||
|
|
274
|
+
/\bTEXT\b/i.test(content) ||
|
|
275
|
+
/\bJSONB?\b/i.test(content) ||
|
|
276
|
+
/\bUUID\b/i.test(content) ||
|
|
277
|
+
/\bTIMESTAMPTZ\b/i.test(content) ||
|
|
278
|
+
/\bBOOLEAN\b/i.test(content) ||
|
|
279
|
+
/\bCREATE\s+TABLE\b/i.test(content) ||
|
|
280
|
+
/\bCREATE\s+TYPE\b/i.test(content) ||
|
|
281
|
+
/\bCREATE\s+EXTENSION\b/i.test(content));
|
|
282
|
+
if (!hasPostgresPatterns) {
|
|
283
|
+
warnings.push('No PostgreSQL-specific syntax detected. Ensure this is a PostgreSQL schema.');
|
|
284
|
+
}
|
|
285
|
+
if (/\bDROP\s+DATABASE\b/i.test(content)) {
|
|
286
|
+
warnings.push('Found DROP DATABASE statement - this may be dangerous');
|
|
287
|
+
}
|
|
288
|
+
if (/\bTRUNCATE\b/i.test(content)) {
|
|
289
|
+
warnings.push('Found TRUNCATE statement - this will delete data');
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
valid: errors.length === 0,
|
|
293
|
+
errors,
|
|
294
|
+
warnings,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function readSQLFile(filePath) {
|
|
298
|
+
const absolutePath = path.resolve(filePath);
|
|
299
|
+
if (!fs.existsSync(absolutePath)) {
|
|
300
|
+
return { error: `pathspec '${filePath}' did not match any files` };
|
|
301
|
+
}
|
|
302
|
+
const stat = fs.statSync(absolutePath);
|
|
303
|
+
if (stat.isDirectory()) {
|
|
304
|
+
return { error: `'${filePath}' is a directory, not a file` };
|
|
305
|
+
}
|
|
306
|
+
const content = fs.readFileSync(absolutePath, 'utf-8');
|
|
307
|
+
const validation = validatePostgresSQL(content);
|
|
308
|
+
return { content, validation };
|
|
309
|
+
}
|
|
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,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMigration = generateMigration;
|
|
4
|
+
exports.generateMigrationFile = generateMigrationFile;
|
|
5
|
+
exports.getNextMigrationNumber = getNextMigrationNumber;
|
|
6
|
+
exports.generateTimestampedName = generateTimestampedName;
|
|
7
|
+
function generateMigration(diff, options = {}) {
|
|
8
|
+
const { includeDown = true } = options;
|
|
9
|
+
const up = [];
|
|
10
|
+
const down = [];
|
|
11
|
+
for (const table of diff.tables.filter(t => t.action === 'remove')) {
|
|
12
|
+
up.push(...generateDropTable(table));
|
|
13
|
+
if (includeDown && table.before) {
|
|
14
|
+
down.unshift(...generateCreateTable(table.before));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
for (const table of diff.tables.filter(t => t.action === 'add')) {
|
|
18
|
+
if (table.after) {
|
|
19
|
+
up.push(...generateCreateTable(table.after));
|
|
20
|
+
if (includeDown) {
|
|
21
|
+
down.unshift(`DROP TABLE IF EXISTS "${table.name}" CASCADE;`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (const table of diff.tables.filter(t => t.action === 'modify')) {
|
|
26
|
+
const { upSQL, downSQL } = generateAlterTable(table, includeDown);
|
|
27
|
+
up.push(...upSQL);
|
|
28
|
+
down.unshift(...downSQL);
|
|
29
|
+
}
|
|
30
|
+
return { up, down };
|
|
31
|
+
}
|
|
32
|
+
function generateMigrationFile(diff, name, options = {}) {
|
|
33
|
+
const { message, includeComments = true } = options;
|
|
34
|
+
const { up, down } = generateMigration(diff, options);
|
|
35
|
+
const lines = [];
|
|
36
|
+
lines.push(`-- Migration: ${name}`);
|
|
37
|
+
if (message) {
|
|
38
|
+
lines.push(`-- ${message}`);
|
|
39
|
+
}
|
|
40
|
+
lines.push(`-- Generated: ${new Date().toISOString()}`);
|
|
41
|
+
lines.push('');
|
|
42
|
+
lines.push('-- UP');
|
|
43
|
+
if (up.length === 0) {
|
|
44
|
+
lines.push('-- No changes');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
if (includeComments) {
|
|
48
|
+
lines.push(`-- ${diff.summary.tablesAdded} tables added, ${diff.summary.tablesRemoved} removed, ${diff.summary.tablesModified} modified`);
|
|
49
|
+
}
|
|
50
|
+
lines.push('');
|
|
51
|
+
lines.push(...up);
|
|
52
|
+
}
|
|
53
|
+
lines.push('');
|
|
54
|
+
lines.push('-- DOWN');
|
|
55
|
+
if (down.length === 0) {
|
|
56
|
+
lines.push('-- No rollback');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
lines.push('');
|
|
60
|
+
lines.push(...down);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
content: lines.join('\n'),
|
|
65
|
+
upSQL: up,
|
|
66
|
+
downSQL: down,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function generateCreateTable(table) {
|
|
70
|
+
const sql = [];
|
|
71
|
+
const columnDefs = [];
|
|
72
|
+
const constraintDefs = [];
|
|
73
|
+
for (const col of table.columns) {
|
|
74
|
+
columnDefs.push(` ${generateColumnDefinition(col)}`);
|
|
75
|
+
}
|
|
76
|
+
const hasPKColumn = table.columns.some(c => c.isPrimaryKey);
|
|
77
|
+
for (const con of table.constraints || []) {
|
|
78
|
+
if (con.type === 'PRIMARY KEY' && hasPKColumn)
|
|
79
|
+
continue;
|
|
80
|
+
constraintDefs.push(` CONSTRAINT "${con.name}" ${con.definition}`);
|
|
81
|
+
}
|
|
82
|
+
const allDefs = [...columnDefs, ...constraintDefs];
|
|
83
|
+
let createSQL = `CREATE TABLE "${table.name}" (\n${allDefs.join(',\n')}\n)`;
|
|
84
|
+
if (table.isPartitioned && table.partitionType && table.partitionKey?.length) {
|
|
85
|
+
createSQL += ` PARTITION BY ${table.partitionType} (${table.partitionKey.join(', ')})`;
|
|
86
|
+
}
|
|
87
|
+
sql.push(createSQL + ';');
|
|
88
|
+
for (const idx of table.indexes || []) {
|
|
89
|
+
if (idx.isPrimary)
|
|
90
|
+
continue;
|
|
91
|
+
sql.push(generateCreateIndex(table.name, idx));
|
|
92
|
+
}
|
|
93
|
+
return sql;
|
|
94
|
+
}
|
|
95
|
+
function generateDropTable(table) {
|
|
96
|
+
return [`DROP TABLE IF EXISTS "${table.name}" CASCADE;`];
|
|
97
|
+
}
|
|
98
|
+
function generateAlterTable(table, includeDown) {
|
|
99
|
+
const upSQL = [];
|
|
100
|
+
const downSQL = [];
|
|
101
|
+
const tableName = table.name;
|
|
102
|
+
for (const col of table.columns || []) {
|
|
103
|
+
const { up, down } = generateColumnChange(tableName, col);
|
|
104
|
+
upSQL.push(...up);
|
|
105
|
+
if (includeDown)
|
|
106
|
+
downSQL.unshift(...down);
|
|
107
|
+
}
|
|
108
|
+
for (const idx of table.indexes || []) {
|
|
109
|
+
const { up, down } = generateIndexChange(tableName, idx);
|
|
110
|
+
upSQL.push(...up);
|
|
111
|
+
if (includeDown)
|
|
112
|
+
downSQL.unshift(...down);
|
|
113
|
+
}
|
|
114
|
+
for (const con of table.constraints || []) {
|
|
115
|
+
const { up, down } = generateConstraintChange(tableName, con);
|
|
116
|
+
upSQL.push(...up);
|
|
117
|
+
if (includeDown)
|
|
118
|
+
downSQL.unshift(...down);
|
|
119
|
+
}
|
|
120
|
+
return { upSQL, downSQL };
|
|
121
|
+
}
|
|
122
|
+
function generateColumnDefinition(col) {
|
|
123
|
+
const parts = [`"${col.name}"`, mapDataType(col)];
|
|
124
|
+
if (col.isPrimaryKey) {
|
|
125
|
+
parts.push('PRIMARY KEY');
|
|
126
|
+
}
|
|
127
|
+
if (!col.isNullable && !col.isPrimaryKey) {
|
|
128
|
+
parts.push('NOT NULL');
|
|
129
|
+
}
|
|
130
|
+
if (col.isUnique && !col.isPrimaryKey) {
|
|
131
|
+
parts.push('UNIQUE');
|
|
132
|
+
}
|
|
133
|
+
if (col.defaultValue) {
|
|
134
|
+
parts.push(`DEFAULT ${col.defaultValue}`);
|
|
135
|
+
}
|
|
136
|
+
if (col.references) {
|
|
137
|
+
parts.push(`REFERENCES "${col.references.table}"("${col.references.column}")`);
|
|
138
|
+
}
|
|
139
|
+
return parts.join(' ');
|
|
140
|
+
}
|
|
141
|
+
function generateColumnChange(tableName, col) {
|
|
142
|
+
const up = [];
|
|
143
|
+
const down = [];
|
|
144
|
+
if (col.action === 'add' && col.after) {
|
|
145
|
+
up.push(`ALTER TABLE "${tableName}" ADD COLUMN ${generateColumnDefinition(col.after)};`);
|
|
146
|
+
down.push(`ALTER TABLE "${tableName}" DROP COLUMN IF EXISTS "${col.name}";`);
|
|
147
|
+
}
|
|
148
|
+
if (col.action === 'remove' && col.before) {
|
|
149
|
+
up.push(`ALTER TABLE "${tableName}" DROP COLUMN IF EXISTS "${col.name}";`);
|
|
150
|
+
down.push(`ALTER TABLE "${tableName}" ADD COLUMN ${generateColumnDefinition(col.before)};`);
|
|
151
|
+
}
|
|
152
|
+
if (col.action === 'modify' && col.changesV2 && col.before && col.after) {
|
|
153
|
+
if (col.changesV2.type) {
|
|
154
|
+
const newType = mapDataType(col.after);
|
|
155
|
+
up.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" TYPE ${newType} USING "${col.name}"::${newType};`);
|
|
156
|
+
down.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" TYPE ${mapDataType(col.before)} USING "${col.name}"::${mapDataType(col.before)};`);
|
|
157
|
+
}
|
|
158
|
+
if (col.changesV2.nullable) {
|
|
159
|
+
if (col.changesV2.nullable.to) {
|
|
160
|
+
up.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" DROP NOT NULL;`);
|
|
161
|
+
down.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" SET NOT NULL;`);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
up.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" SET NOT NULL;`);
|
|
165
|
+
down.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" DROP NOT NULL;`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (col.changesV2.default) {
|
|
169
|
+
if (col.changesV2.default.to) {
|
|
170
|
+
up.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" SET DEFAULT ${col.changesV2.default.to};`);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
up.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" DROP DEFAULT;`);
|
|
174
|
+
}
|
|
175
|
+
if (col.changesV2.default.from) {
|
|
176
|
+
down.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" SET DEFAULT ${col.changesV2.default.from};`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
down.push(`ALTER TABLE "${tableName}" ALTER COLUMN "${col.name}" DROP DEFAULT;`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { up, down };
|
|
184
|
+
}
|
|
185
|
+
function generateCreateIndex(tableName, idx) {
|
|
186
|
+
const unique = idx.isUnique ? 'UNIQUE ' : '';
|
|
187
|
+
const cols = Array.isArray(idx.columns) ? idx.columns : [idx.columns];
|
|
188
|
+
const colList = cols.map(c => `"${c}"`).join(', ');
|
|
189
|
+
const using = idx.type && idx.type !== 'btree' ? ` USING ${idx.type}` : '';
|
|
190
|
+
return `CREATE ${unique}INDEX IF NOT EXISTS "${idx.name}" ON "${tableName}"${using} (${colList});`;
|
|
191
|
+
}
|
|
192
|
+
function generateIndexChange(tableName, idx) {
|
|
193
|
+
const up = [];
|
|
194
|
+
const down = [];
|
|
195
|
+
if (idx.action === 'add' && idx.after) {
|
|
196
|
+
up.push(generateCreateIndex(tableName, idx.after));
|
|
197
|
+
down.push(`DROP INDEX IF EXISTS "${idx.name}";`);
|
|
198
|
+
}
|
|
199
|
+
if (idx.action === 'remove' && idx.before) {
|
|
200
|
+
up.push(`DROP INDEX IF EXISTS "${idx.name}";`);
|
|
201
|
+
down.push(generateCreateIndex(tableName, idx.before));
|
|
202
|
+
}
|
|
203
|
+
return { up, down };
|
|
204
|
+
}
|
|
205
|
+
function generateConstraintChange(tableName, con) {
|
|
206
|
+
const up = [];
|
|
207
|
+
const down = [];
|
|
208
|
+
if (con.action === 'add' && con.after) {
|
|
209
|
+
up.push(`ALTER TABLE "${tableName}" ADD CONSTRAINT "${con.name}" ${con.after.definition};`);
|
|
210
|
+
down.push(`ALTER TABLE "${tableName}" DROP CONSTRAINT IF EXISTS "${con.name}";`);
|
|
211
|
+
}
|
|
212
|
+
if (con.action === 'remove' && con.before) {
|
|
213
|
+
up.push(`ALTER TABLE "${tableName}" DROP CONSTRAINT IF EXISTS "${con.name}";`);
|
|
214
|
+
down.push(`ALTER TABLE "${tableName}" ADD CONSTRAINT "${con.name}" ${con.before.definition};`);
|
|
215
|
+
}
|
|
216
|
+
return { up, down };
|
|
217
|
+
}
|
|
218
|
+
function mapDataType(col) {
|
|
219
|
+
let type = col.dataType.toUpperCase();
|
|
220
|
+
if ((type === 'VARCHAR' || type === 'CHARACTER VARYING') && col.maxLength) {
|
|
221
|
+
return `VARCHAR(${col.maxLength})`;
|
|
222
|
+
}
|
|
223
|
+
if ((type === 'CHAR' || type === 'CHARACTER' || type === 'BPCHAR') && col.maxLength) {
|
|
224
|
+
return `CHAR(${col.maxLength})`;
|
|
225
|
+
}
|
|
226
|
+
if ((type === 'NUMERIC' || type === 'DECIMAL') && col.precision) {
|
|
227
|
+
if (col.scale) {
|
|
228
|
+
return `NUMERIC(${col.precision}, ${col.scale})`;
|
|
229
|
+
}
|
|
230
|
+
return `NUMERIC(${col.precision})`;
|
|
231
|
+
}
|
|
232
|
+
const typeMap = {
|
|
233
|
+
'INT4': 'INTEGER',
|
|
234
|
+
'INT8': 'BIGINT',
|
|
235
|
+
'INT2': 'SMALLINT',
|
|
236
|
+
'FLOAT4': 'REAL',
|
|
237
|
+
'FLOAT8': 'DOUBLE PRECISION',
|
|
238
|
+
'BOOL': 'BOOLEAN',
|
|
239
|
+
'TIMESTAMPTZ': 'TIMESTAMP WITH TIME ZONE',
|
|
240
|
+
'TIMETZ': 'TIME WITH TIME ZONE',
|
|
241
|
+
};
|
|
242
|
+
return typeMap[type] || type;
|
|
243
|
+
}
|
|
244
|
+
function getNextMigrationNumber(migrationsDir) {
|
|
245
|
+
const fs = require('fs');
|
|
246
|
+
if (!fs.existsSync(migrationsDir)) {
|
|
247
|
+
return '001';
|
|
248
|
+
}
|
|
249
|
+
const files = fs.readdirSync(migrationsDir)
|
|
250
|
+
.filter((f) => f.endsWith('.sql'))
|
|
251
|
+
.sort();
|
|
252
|
+
if (files.length === 0) {
|
|
253
|
+
return '001';
|
|
254
|
+
}
|
|
255
|
+
const lastFile = files[files.length - 1];
|
|
256
|
+
const match = lastFile.match(/^(\d+)/);
|
|
257
|
+
if (match) {
|
|
258
|
+
const num = parseInt(match[1]) + 1;
|
|
259
|
+
return num.toString().padStart(3, '0');
|
|
260
|
+
}
|
|
261
|
+
return '001';
|
|
262
|
+
}
|
|
263
|
+
function generateTimestampedName(name) {
|
|
264
|
+
const now = new Date();
|
|
265
|
+
const timestamp = now.toISOString()
|
|
266
|
+
.replace(/[-:T]/g, '')
|
|
267
|
+
.slice(0, 14);
|
|
268
|
+
return `${timestamp}_${name.replace(/\s+/g, '_').toLowerCase()}`;
|
|
269
|
+
}
|