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,444 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as crypto from 'crypto';
|
|
4
|
+
const RELQ_DIR = '.relq';
|
|
5
|
+
const HEAD_FILE = 'HEAD';
|
|
6
|
+
const FETCH_HEAD_FILE = 'FETCH_HEAD';
|
|
7
|
+
const STAGED_FILE = 'staged.json';
|
|
8
|
+
const WORKING_FILE = 'working.json';
|
|
9
|
+
const SNAPSHOT_FILE = 'snapshot.json';
|
|
10
|
+
const COMMITS_DIR = 'commits';
|
|
11
|
+
export function isInitialized(projectRoot = process.cwd()) {
|
|
12
|
+
const relqPath = path.join(projectRoot, RELQ_DIR);
|
|
13
|
+
const headPath = path.join(relqPath, HEAD_FILE);
|
|
14
|
+
return fs.existsSync(relqPath) && fs.existsSync(headPath);
|
|
15
|
+
}
|
|
16
|
+
export function initRepository(projectRoot = process.cwd()) {
|
|
17
|
+
const relqPath = path.join(projectRoot, RELQ_DIR);
|
|
18
|
+
const commitsPath = path.join(relqPath, COMMITS_DIR);
|
|
19
|
+
if (!fs.existsSync(relqPath)) {
|
|
20
|
+
fs.mkdirSync(relqPath, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
if (!fs.existsSync(commitsPath)) {
|
|
23
|
+
fs.mkdirSync(commitsPath, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
const headPath = path.join(relqPath, HEAD_FILE);
|
|
26
|
+
if (!fs.existsSync(headPath)) {
|
|
27
|
+
fs.writeFileSync(headPath, '', 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
const workingPath = path.join(relqPath, WORKING_FILE);
|
|
30
|
+
if (!fs.existsSync(workingPath)) {
|
|
31
|
+
const initialState = {
|
|
32
|
+
timestamp: new Date().toISOString(),
|
|
33
|
+
staged: [],
|
|
34
|
+
unstaged: [],
|
|
35
|
+
};
|
|
36
|
+
fs.writeFileSync(workingPath, JSON.stringify(initialState, null, 2), 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function getHead(projectRoot = process.cwd()) {
|
|
40
|
+
const headPath = path.join(projectRoot, RELQ_DIR, HEAD_FILE);
|
|
41
|
+
if (!fs.existsSync(headPath)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const content = fs.readFileSync(headPath, 'utf-8').trim();
|
|
45
|
+
return content || null;
|
|
46
|
+
}
|
|
47
|
+
export function setHead(hash, projectRoot = process.cwd()) {
|
|
48
|
+
const headPath = path.join(projectRoot, RELQ_DIR, HEAD_FILE);
|
|
49
|
+
fs.writeFileSync(headPath, hash, 'utf-8');
|
|
50
|
+
}
|
|
51
|
+
export function getFetchHead(projectRoot = process.cwd()) {
|
|
52
|
+
const fetchPath = path.join(projectRoot, RELQ_DIR, FETCH_HEAD_FILE);
|
|
53
|
+
if (!fs.existsSync(fetchPath)) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return fs.readFileSync(fetchPath, 'utf-8').trim() || null;
|
|
57
|
+
}
|
|
58
|
+
export function setFetchHead(hash, projectRoot = process.cwd()) {
|
|
59
|
+
const fetchPath = path.join(projectRoot, RELQ_DIR, FETCH_HEAD_FILE);
|
|
60
|
+
fs.writeFileSync(fetchPath, hash, 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
export function generateHash(schema) {
|
|
63
|
+
const normalized = JSON.stringify(schema, Object.keys(schema).sort());
|
|
64
|
+
return crypto.createHash('sha1').update(normalized).digest('hex');
|
|
65
|
+
}
|
|
66
|
+
export function shortHash(hash) {
|
|
67
|
+
return hash.substring(0, 7);
|
|
68
|
+
}
|
|
69
|
+
export function saveCommit(commit, projectRoot = process.cwd()) {
|
|
70
|
+
const commitsPath = path.join(projectRoot, RELQ_DIR, COMMITS_DIR);
|
|
71
|
+
const commitPath = path.join(commitsPath, `${commit.hash}.json`);
|
|
72
|
+
fs.writeFileSync(commitPath, JSON.stringify(commit, null, 2), 'utf-8');
|
|
73
|
+
}
|
|
74
|
+
export function loadCommit(hash, projectRoot = process.cwd()) {
|
|
75
|
+
const commitPath = path.join(projectRoot, RELQ_DIR, COMMITS_DIR, `${hash}.json`);
|
|
76
|
+
if (!fs.existsSync(commitPath)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return JSON.parse(fs.readFileSync(commitPath, 'utf-8'));
|
|
80
|
+
}
|
|
81
|
+
export function getAllCommits(projectRoot = process.cwd()) {
|
|
82
|
+
const commitsPath = path.join(projectRoot, RELQ_DIR, COMMITS_DIR);
|
|
83
|
+
if (!fs.existsSync(commitsPath)) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const files = fs.readdirSync(commitsPath).filter(f => f.endsWith('.json'));
|
|
87
|
+
const commits = [];
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
const content = fs.readFileSync(path.join(commitsPath, file), 'utf-8');
|
|
90
|
+
commits.push(JSON.parse(content));
|
|
91
|
+
}
|
|
92
|
+
commits.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
93
|
+
return commits;
|
|
94
|
+
}
|
|
95
|
+
export function getCommitHistory(limit = 20, projectRoot = process.cwd()) {
|
|
96
|
+
const head = getHead(projectRoot);
|
|
97
|
+
if (!head)
|
|
98
|
+
return [];
|
|
99
|
+
const history = [];
|
|
100
|
+
let currentHash = head;
|
|
101
|
+
while (currentHash && history.length < limit) {
|
|
102
|
+
const commit = loadCommit(currentHash, projectRoot);
|
|
103
|
+
if (!commit)
|
|
104
|
+
break;
|
|
105
|
+
history.push(commit);
|
|
106
|
+
currentHash = commit.parentHash;
|
|
107
|
+
}
|
|
108
|
+
return history;
|
|
109
|
+
}
|
|
110
|
+
export function createCommit(schema, author, message, projectRoot = process.cwd()) {
|
|
111
|
+
const hash = generateHash(schema);
|
|
112
|
+
const parentHash = getHead(projectRoot);
|
|
113
|
+
const commit = {
|
|
114
|
+
hash,
|
|
115
|
+
parentHash,
|
|
116
|
+
author,
|
|
117
|
+
message,
|
|
118
|
+
timestamp: new Date().toISOString(),
|
|
119
|
+
schema,
|
|
120
|
+
stats: {
|
|
121
|
+
tables: schema.tables.length,
|
|
122
|
+
columns: schema.tables.reduce((acc, t) => acc + t.columns.length, 0),
|
|
123
|
+
indexes: schema.tables.reduce((acc, t) => acc + t.indexes.length, 0),
|
|
124
|
+
enums: schema.enums?.length || 0,
|
|
125
|
+
domains: schema.domains?.length || 0,
|
|
126
|
+
compositeTypes: schema.compositeTypes?.length || 0,
|
|
127
|
+
sequences: schema.sequences?.length || 0,
|
|
128
|
+
functions: schema.functions?.length || 0,
|
|
129
|
+
triggers: schema.triggers?.length || 0,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
saveCommit(commit, projectRoot);
|
|
133
|
+
setHead(hash, projectRoot);
|
|
134
|
+
clearStaged(projectRoot);
|
|
135
|
+
return commit;
|
|
136
|
+
}
|
|
137
|
+
export function getStaged(projectRoot = process.cwd()) {
|
|
138
|
+
const stagedPath = path.join(projectRoot, RELQ_DIR, STAGED_FILE);
|
|
139
|
+
if (!fs.existsSync(stagedPath)) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const content = fs.readFileSync(stagedPath, 'utf-8');
|
|
143
|
+
return content === 'null' ? null : JSON.parse(content);
|
|
144
|
+
}
|
|
145
|
+
export function setStaged(staged, projectRoot = process.cwd()) {
|
|
146
|
+
const stagedPath = path.join(projectRoot, RELQ_DIR, STAGED_FILE);
|
|
147
|
+
fs.writeFileSync(stagedPath, staged ? JSON.stringify(staged, null, 2) : 'null', 'utf-8');
|
|
148
|
+
}
|
|
149
|
+
export function clearStaged(projectRoot = process.cwd()) {
|
|
150
|
+
setStaged(null, projectRoot);
|
|
151
|
+
}
|
|
152
|
+
export function hasStaged(projectRoot = process.cwd()) {
|
|
153
|
+
const staged = getStaged(projectRoot);
|
|
154
|
+
if (!staged)
|
|
155
|
+
return false;
|
|
156
|
+
return (staged.tables.added.length > 0 ||
|
|
157
|
+
staged.tables.modified.length > 0 ||
|
|
158
|
+
staged.tables.removed.length > 0 ||
|
|
159
|
+
staged.functions.added.length > 0 ||
|
|
160
|
+
staged.functions.modified.length > 0 ||
|
|
161
|
+
staged.functions.removed.length > 0);
|
|
162
|
+
}
|
|
163
|
+
export function loadSnapshot(projectRoot = process.cwd()) {
|
|
164
|
+
const snapshotPath = path.join(projectRoot, RELQ_DIR, SNAPSHOT_FILE);
|
|
165
|
+
if (!fs.existsSync(snapshotPath)) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const raw = JSON.parse(fs.readFileSync(snapshotPath, 'utf-8'));
|
|
169
|
+
return migrateSnapshot(raw);
|
|
170
|
+
}
|
|
171
|
+
export function saveSnapshot(schema, projectRoot = process.cwd()) {
|
|
172
|
+
const snapshotPath = path.join(projectRoot, RELQ_DIR, SNAPSHOT_FILE);
|
|
173
|
+
fs.writeFileSync(snapshotPath, JSON.stringify(schema, null, 2), 'utf-8');
|
|
174
|
+
}
|
|
175
|
+
export function loadWorkingState(projectRoot = process.cwd()) {
|
|
176
|
+
const workingPath = path.join(projectRoot, RELQ_DIR, WORKING_FILE);
|
|
177
|
+
if (!fs.existsSync(workingPath)) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const content = fs.readFileSync(workingPath, 'utf-8');
|
|
181
|
+
return content === 'null' ? null : JSON.parse(content);
|
|
182
|
+
}
|
|
183
|
+
export function saveWorkingState(state, projectRoot = process.cwd()) {
|
|
184
|
+
const workingPath = path.join(projectRoot, RELQ_DIR, WORKING_FILE);
|
|
185
|
+
fs.writeFileSync(workingPath, JSON.stringify(state, null, 2), 'utf-8');
|
|
186
|
+
}
|
|
187
|
+
export function getOrCreateWorkingState(projectRoot = process.cwd()) {
|
|
188
|
+
const existing = loadWorkingState(projectRoot);
|
|
189
|
+
if (existing)
|
|
190
|
+
return existing;
|
|
191
|
+
return {
|
|
192
|
+
timestamp: new Date().toISOString(),
|
|
193
|
+
staged: [],
|
|
194
|
+
unstaged: [],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
export function addUnstagedChanges(changes, projectRoot = process.cwd()) {
|
|
198
|
+
const state = getOrCreateWorkingState(projectRoot);
|
|
199
|
+
const existingIds = new Set(state.unstaged.map(c => c.id));
|
|
200
|
+
for (const change of changes) {
|
|
201
|
+
if (!existingIds.has(change.id)) {
|
|
202
|
+
state.unstaged.push(change);
|
|
203
|
+
existingIds.add(change.id);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
state.timestamp = new Date().toISOString();
|
|
207
|
+
saveWorkingState(state, projectRoot);
|
|
208
|
+
}
|
|
209
|
+
export function stageChanges(patterns, projectRoot = process.cwd()) {
|
|
210
|
+
const state = getOrCreateWorkingState(projectRoot);
|
|
211
|
+
const staged = [];
|
|
212
|
+
const remaining = [];
|
|
213
|
+
const isAll = patterns.includes('*') || patterns.includes('.');
|
|
214
|
+
for (const change of state.unstaged) {
|
|
215
|
+
const matchesPattern = isAll || patterns.some(p => {
|
|
216
|
+
const fullName = change.parentName
|
|
217
|
+
? `${change.parentName}.${change.objectName}`
|
|
218
|
+
: change.objectName;
|
|
219
|
+
return fullName.includes(p) ||
|
|
220
|
+
change.objectName === p ||
|
|
221
|
+
change.objectType.toLowerCase() === p.toLowerCase();
|
|
222
|
+
});
|
|
223
|
+
if (matchesPattern) {
|
|
224
|
+
staged.push(change);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
remaining.push(change);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
state.staged.push(...staged);
|
|
231
|
+
state.unstaged = remaining;
|
|
232
|
+
state.timestamp = new Date().toISOString();
|
|
233
|
+
saveWorkingState(state, projectRoot);
|
|
234
|
+
return staged;
|
|
235
|
+
}
|
|
236
|
+
export function unstageChanges(patterns, projectRoot = process.cwd()) {
|
|
237
|
+
const state = getOrCreateWorkingState(projectRoot);
|
|
238
|
+
const unstaged = [];
|
|
239
|
+
const remaining = [];
|
|
240
|
+
const isAll = patterns.includes('*') || patterns.includes('.');
|
|
241
|
+
for (const change of state.staged) {
|
|
242
|
+
const matchesPattern = isAll || patterns.some(p => {
|
|
243
|
+
const fullName = change.parentName
|
|
244
|
+
? `${change.parentName}.${change.objectName}`
|
|
245
|
+
: change.objectName;
|
|
246
|
+
return fullName.includes(p) || change.objectName === p;
|
|
247
|
+
});
|
|
248
|
+
if (matchesPattern) {
|
|
249
|
+
unstaged.push(change);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
remaining.push(change);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
state.unstaged.push(...unstaged);
|
|
256
|
+
state.staged = remaining;
|
|
257
|
+
state.timestamp = new Date().toISOString();
|
|
258
|
+
saveWorkingState(state, projectRoot);
|
|
259
|
+
return unstaged;
|
|
260
|
+
}
|
|
261
|
+
export function clearWorkingState(projectRoot = process.cwd()) {
|
|
262
|
+
const workingPath = path.join(projectRoot, RELQ_DIR, WORKING_FILE);
|
|
263
|
+
if (fs.existsSync(workingPath)) {
|
|
264
|
+
fs.unlinkSync(workingPath);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
export function getStagedChanges(projectRoot = process.cwd()) {
|
|
268
|
+
const state = loadWorkingState(projectRoot);
|
|
269
|
+
return state?.staged || [];
|
|
270
|
+
}
|
|
271
|
+
export function getUnstagedChanges(projectRoot = process.cwd()) {
|
|
272
|
+
const state = loadWorkingState(projectRoot);
|
|
273
|
+
return state?.unstaged || [];
|
|
274
|
+
}
|
|
275
|
+
export function hasUncommittedChanges(projectRoot = process.cwd()) {
|
|
276
|
+
const state = loadWorkingState(projectRoot);
|
|
277
|
+
if (!state)
|
|
278
|
+
return false;
|
|
279
|
+
return state.staged.length > 0 || state.unstaged.length > 0;
|
|
280
|
+
}
|
|
281
|
+
export async function ensureRemoteTable(connection) {
|
|
282
|
+
const { Pool } = await import("../../addon/pg.js");
|
|
283
|
+
const pool = new Pool({
|
|
284
|
+
host: connection.host,
|
|
285
|
+
port: connection.port || 5432,
|
|
286
|
+
database: connection.database,
|
|
287
|
+
user: connection.user,
|
|
288
|
+
password: connection.password,
|
|
289
|
+
connectionString: connection.url,
|
|
290
|
+
ssl: connection.ssl,
|
|
291
|
+
});
|
|
292
|
+
try {
|
|
293
|
+
await pool.query(`
|
|
294
|
+
CREATE TABLE IF NOT EXISTS _relq_commits (
|
|
295
|
+
id SERIAL PRIMARY KEY,
|
|
296
|
+
hash VARCHAR(40) UNIQUE NOT NULL,
|
|
297
|
+
parent_hash VARCHAR(40),
|
|
298
|
+
author VARCHAR(255) NOT NULL,
|
|
299
|
+
message TEXT,
|
|
300
|
+
schema_snapshot JSONB NOT NULL,
|
|
301
|
+
stats JSONB,
|
|
302
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
CREATE INDEX IF NOT EXISTS idx_relq_commits_hash ON _relq_commits(hash);
|
|
306
|
+
CREATE INDEX IF NOT EXISTS idx_relq_commits_created ON _relq_commits(created_at DESC);
|
|
307
|
+
`);
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
await pool.end();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
export async function fetchRemoteCommits(connection, limit = 100) {
|
|
314
|
+
const { Pool } = await import("../../addon/pg.js");
|
|
315
|
+
const pool = new Pool({
|
|
316
|
+
host: connection.host,
|
|
317
|
+
port: connection.port || 5432,
|
|
318
|
+
database: connection.database,
|
|
319
|
+
user: connection.user,
|
|
320
|
+
password: connection.password,
|
|
321
|
+
connectionString: connection.url,
|
|
322
|
+
ssl: connection.ssl,
|
|
323
|
+
});
|
|
324
|
+
try {
|
|
325
|
+
const result = await pool.query(`
|
|
326
|
+
SELECT hash, parent_hash, author, message, schema_snapshot, stats, created_at
|
|
327
|
+
FROM _relq_commits
|
|
328
|
+
ORDER BY created_at DESC
|
|
329
|
+
LIMIT $1
|
|
330
|
+
`, [limit]);
|
|
331
|
+
return result.rows.map(row => ({
|
|
332
|
+
hash: row.hash,
|
|
333
|
+
parentHash: row.parent_hash,
|
|
334
|
+
author: row.author,
|
|
335
|
+
message: row.message || '',
|
|
336
|
+
timestamp: row.created_at.toISOString(),
|
|
337
|
+
schema: row.schema_snapshot,
|
|
338
|
+
stats: row.stats || { tables: 0, columns: 0, indexes: 0, functions: 0, triggers: 0 },
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
await pool.end();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
export async function getRemoteHead(connection) {
|
|
346
|
+
const commits = await fetchRemoteCommits(connection, 1);
|
|
347
|
+
return commits.length > 0 ? commits[0].hash : null;
|
|
348
|
+
}
|
|
349
|
+
export async function pushCommit(connection, commit) {
|
|
350
|
+
const { Pool } = await import("../../addon/pg.js");
|
|
351
|
+
const pool = new Pool({
|
|
352
|
+
host: connection.host,
|
|
353
|
+
port: connection.port || 5432,
|
|
354
|
+
database: connection.database,
|
|
355
|
+
user: connection.user,
|
|
356
|
+
password: connection.password,
|
|
357
|
+
connectionString: connection.url,
|
|
358
|
+
ssl: connection.ssl,
|
|
359
|
+
});
|
|
360
|
+
try {
|
|
361
|
+
await pool.query(`
|
|
362
|
+
INSERT INTO _relq_commits (hash, parent_hash, author, message, schema_snapshot, stats)
|
|
363
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
364
|
+
ON CONFLICT (hash) DO NOTHING
|
|
365
|
+
`, [
|
|
366
|
+
commit.hash,
|
|
367
|
+
commit.parentHash,
|
|
368
|
+
commit.author,
|
|
369
|
+
commit.message,
|
|
370
|
+
JSON.stringify(commit.schema),
|
|
371
|
+
JSON.stringify(commit.stats),
|
|
372
|
+
]);
|
|
373
|
+
}
|
|
374
|
+
finally {
|
|
375
|
+
await pool.end();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
export async function getRepoStatus(connection, projectRoot = process.cwd()) {
|
|
379
|
+
const initialized = isInitialized(projectRoot);
|
|
380
|
+
const head = getHead(projectRoot);
|
|
381
|
+
const staged = getStaged(projectRoot);
|
|
382
|
+
const localCommits = getAllCommits(projectRoot).length;
|
|
383
|
+
let aheadBy = 0;
|
|
384
|
+
let behindBy = 0;
|
|
385
|
+
if (initialized && head) {
|
|
386
|
+
try {
|
|
387
|
+
const remoteHead = await getRemoteHead(connection);
|
|
388
|
+
const localHashes = new Set(getAllCommits(projectRoot).map(c => c.hash));
|
|
389
|
+
const remoteCommits = await fetchRemoteCommits(connection, 100);
|
|
390
|
+
const remoteHashes = new Set(remoteCommits.map(c => c.hash));
|
|
391
|
+
aheadBy = [...localHashes].filter(h => !remoteHashes.has(h)).length;
|
|
392
|
+
behindBy = [...remoteHashes].filter(h => !localHashes.has(h)).length;
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return {
|
|
398
|
+
initialized,
|
|
399
|
+
head,
|
|
400
|
+
staged,
|
|
401
|
+
localCommits,
|
|
402
|
+
aheadBy,
|
|
403
|
+
behindBy,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
export function createEmptySchema() {
|
|
407
|
+
return {
|
|
408
|
+
extensions: [],
|
|
409
|
+
enums: [],
|
|
410
|
+
domains: [],
|
|
411
|
+
compositeTypes: [],
|
|
412
|
+
sequences: [],
|
|
413
|
+
collations: [],
|
|
414
|
+
tables: [],
|
|
415
|
+
functions: [],
|
|
416
|
+
triggers: [],
|
|
417
|
+
views: [],
|
|
418
|
+
materializedViews: [],
|
|
419
|
+
foreignTables: [],
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
export function migrateSnapshot(snapshot) {
|
|
423
|
+
const extensions = (snapshot.extensions || []).map(ext => typeof ext === 'string' ? { name: ext } : ext);
|
|
424
|
+
const triggers = (snapshot.triggers || []).map((t) => ({
|
|
425
|
+
...t,
|
|
426
|
+
events: t.events || (t.event ? [t.event] : []),
|
|
427
|
+
forEach: t.forEach || 'STATEMENT',
|
|
428
|
+
functionName: t.functionName || '',
|
|
429
|
+
}));
|
|
430
|
+
return {
|
|
431
|
+
extensions,
|
|
432
|
+
enums: snapshot.enums || [],
|
|
433
|
+
domains: snapshot.domains || [],
|
|
434
|
+
compositeTypes: snapshot.compositeTypes || [],
|
|
435
|
+
sequences: snapshot.sequences || [],
|
|
436
|
+
collations: snapshot.collations || [],
|
|
437
|
+
tables: snapshot.tables || [],
|
|
438
|
+
functions: snapshot.functions || [],
|
|
439
|
+
triggers,
|
|
440
|
+
views: snapshot.views || [],
|
|
441
|
+
materializedViews: snapshot.materializedViews || [],
|
|
442
|
+
foreignTables: snapshot.foreignTables || [],
|
|
443
|
+
};
|
|
444
|
+
}
|