@pgpmjs/core 3.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 +23 -0
- package/README.md +99 -0
- package/core/boilerplate-scanner.d.ts +41 -0
- package/core/boilerplate-scanner.js +106 -0
- package/core/boilerplate-types.d.ts +52 -0
- package/core/boilerplate-types.js +6 -0
- package/core/class/pgpm.d.ts +150 -0
- package/core/class/pgpm.js +1470 -0
- package/core/template-scaffold.d.ts +29 -0
- package/core/template-scaffold.js +168 -0
- package/esm/core/boilerplate-scanner.js +96 -0
- package/esm/core/boilerplate-types.js +5 -0
- package/esm/core/class/pgpm.js +1430 -0
- package/esm/core/template-scaffold.js +161 -0
- package/esm/export/export-meta.js +240 -0
- package/esm/export/export-migrations.js +180 -0
- package/esm/extensions/extensions.js +31 -0
- package/esm/files/extension/index.js +3 -0
- package/esm/files/extension/reader.js +79 -0
- package/esm/files/extension/writer.js +63 -0
- package/esm/files/index.js +6 -0
- package/esm/files/plan/generator.js +49 -0
- package/esm/files/plan/index.js +5 -0
- package/esm/files/plan/parser.js +296 -0
- package/esm/files/plan/validators.js +181 -0
- package/esm/files/plan/writer.js +114 -0
- package/esm/files/sql/index.js +1 -0
- package/esm/files/sql/writer.js +107 -0
- package/esm/files/sql-scripts/index.js +2 -0
- package/esm/files/sql-scripts/reader.js +19 -0
- package/esm/files/types/index.js +1 -0
- package/esm/files/types/package.js +1 -0
- package/esm/index.js +21 -0
- package/esm/init/client.js +144 -0
- package/esm/init/sql/bootstrap-roles.sql +55 -0
- package/esm/init/sql/bootstrap-test-roles.sql +72 -0
- package/esm/migrate/clean.js +23 -0
- package/esm/migrate/client.js +551 -0
- package/esm/migrate/index.js +5 -0
- package/esm/migrate/sql/procedures.sql +258 -0
- package/esm/migrate/sql/schema.sql +37 -0
- package/esm/migrate/types.js +1 -0
- package/esm/migrate/utils/event-logger.js +28 -0
- package/esm/migrate/utils/hash.js +27 -0
- package/esm/migrate/utils/transaction.js +125 -0
- package/esm/modules/modules.js +49 -0
- package/esm/packaging/package.js +96 -0
- package/esm/packaging/transform.js +70 -0
- package/esm/projects/deploy.js +123 -0
- package/esm/projects/revert.js +75 -0
- package/esm/projects/verify.js +61 -0
- package/esm/resolution/deps.js +526 -0
- package/esm/resolution/resolve.js +101 -0
- package/esm/utils/debug.js +147 -0
- package/esm/utils/target-utils.js +37 -0
- package/esm/workspace/paths.js +43 -0
- package/esm/workspace/utils.js +31 -0
- package/export/export-meta.d.ts +8 -0
- package/export/export-meta.js +244 -0
- package/export/export-migrations.d.ts +17 -0
- package/export/export-migrations.js +187 -0
- package/extensions/extensions.d.ts +5 -0
- package/extensions/extensions.js +35 -0
- package/files/extension/index.d.ts +2 -0
- package/files/extension/index.js +19 -0
- package/files/extension/reader.d.ts +24 -0
- package/files/extension/reader.js +86 -0
- package/files/extension/writer.d.ts +39 -0
- package/files/extension/writer.js +70 -0
- package/files/index.d.ts +5 -0
- package/files/index.js +22 -0
- package/files/plan/generator.d.ts +22 -0
- package/files/plan/generator.js +57 -0
- package/files/plan/index.d.ts +4 -0
- package/files/plan/index.js +21 -0
- package/files/plan/parser.d.ts +27 -0
- package/files/plan/parser.js +303 -0
- package/files/plan/validators.d.ts +52 -0
- package/files/plan/validators.js +187 -0
- package/files/plan/writer.d.ts +27 -0
- package/files/plan/writer.js +124 -0
- package/files/sql/index.d.ts +1 -0
- package/files/sql/index.js +17 -0
- package/files/sql/writer.d.ts +12 -0
- package/files/sql/writer.js +114 -0
- package/files/sql-scripts/index.d.ts +1 -0
- package/files/sql-scripts/index.js +18 -0
- package/files/sql-scripts/reader.d.ts +8 -0
- package/files/sql-scripts/reader.js +23 -0
- package/files/types/index.d.ts +46 -0
- package/files/types/index.js +17 -0
- package/files/types/package.d.ts +20 -0
- package/files/types/package.js +2 -0
- package/index.d.ts +21 -0
- package/index.js +45 -0
- package/init/client.d.ts +26 -0
- package/init/client.js +148 -0
- package/init/sql/bootstrap-roles.sql +55 -0
- package/init/sql/bootstrap-test-roles.sql +72 -0
- package/migrate/clean.d.ts +1 -0
- package/migrate/clean.js +27 -0
- package/migrate/client.d.ts +80 -0
- package/migrate/client.js +555 -0
- package/migrate/index.d.ts +5 -0
- package/migrate/index.js +21 -0
- package/migrate/sql/procedures.sql +258 -0
- package/migrate/sql/schema.sql +37 -0
- package/migrate/types.d.ts +67 -0
- package/migrate/types.js +2 -0
- package/migrate/utils/event-logger.d.ts +13 -0
- package/migrate/utils/event-logger.js +32 -0
- package/migrate/utils/hash.d.ts +12 -0
- package/migrate/utils/hash.js +32 -0
- package/migrate/utils/transaction.d.ts +27 -0
- package/migrate/utils/transaction.js +129 -0
- package/modules/modules.d.ts +31 -0
- package/modules/modules.js +56 -0
- package/package.json +70 -0
- package/packaging/package.d.ts +19 -0
- package/packaging/package.js +102 -0
- package/packaging/transform.d.ts +22 -0
- package/packaging/transform.js +75 -0
- package/projects/deploy.d.ts +8 -0
- package/projects/deploy.js +160 -0
- package/projects/revert.d.ts +15 -0
- package/projects/revert.js +112 -0
- package/projects/verify.d.ts +8 -0
- package/projects/verify.js +98 -0
- package/resolution/deps.d.ts +57 -0
- package/resolution/deps.js +531 -0
- package/resolution/resolve.d.ts +37 -0
- package/resolution/resolve.js +107 -0
- package/utils/debug.d.ts +21 -0
- package/utils/debug.js +153 -0
- package/utils/target-utils.d.ts +5 -0
- package/utils/target-utils.js +40 -0
- package/workspace/paths.d.ts +14 -0
- package/workspace/paths.js +50 -0
- package/workspace/utils.d.ts +8 -0
- package/workspace/utils.js +36 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { deparse } from 'pgsql-deparser';
|
|
2
|
+
import { parse } from 'pgsql-parser';
|
|
3
|
+
/**
|
|
4
|
+
* Recursively transforms the properties of an object based on a transformation map.
|
|
5
|
+
*
|
|
6
|
+
* @param obj - The object to transform.
|
|
7
|
+
* @param props - A map of properties and their transformation rules.
|
|
8
|
+
* @returns A new object with transformed properties.
|
|
9
|
+
*/
|
|
10
|
+
export const transformProps = (obj, props) => {
|
|
11
|
+
let copy;
|
|
12
|
+
// Handle primitive types, null, or undefined
|
|
13
|
+
if (obj === null || typeof obj !== 'object')
|
|
14
|
+
return obj;
|
|
15
|
+
// Handle Date
|
|
16
|
+
if (obj instanceof Date) {
|
|
17
|
+
copy = new Date();
|
|
18
|
+
copy.setTime(obj.getTime());
|
|
19
|
+
return copy;
|
|
20
|
+
}
|
|
21
|
+
// Handle Array
|
|
22
|
+
if (Array.isArray(obj)) {
|
|
23
|
+
copy = [];
|
|
24
|
+
for (let i = 0, len = obj.length; i < len; i++) {
|
|
25
|
+
copy[i] = transformProps(obj[i], props);
|
|
26
|
+
}
|
|
27
|
+
return copy;
|
|
28
|
+
}
|
|
29
|
+
// Handle Object
|
|
30
|
+
if (obj instanceof Object || typeof obj === 'object') {
|
|
31
|
+
copy = {};
|
|
32
|
+
for (const attr in obj) {
|
|
33
|
+
if (Object.prototype.hasOwnProperty.call(obj, attr)) {
|
|
34
|
+
if (props.hasOwnProperty(attr)) {
|
|
35
|
+
const propRule = props[attr];
|
|
36
|
+
if (typeof propRule === 'function') {
|
|
37
|
+
// Apply function transformation
|
|
38
|
+
copy[attr] = propRule(obj[attr]);
|
|
39
|
+
}
|
|
40
|
+
else if (typeof propRule === 'object' && propRule !== null) {
|
|
41
|
+
// Apply value-based transformation
|
|
42
|
+
if (propRule.hasOwnProperty(obj[attr])) {
|
|
43
|
+
copy[attr] = propRule[obj[attr]];
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
copy[attr] = transformProps(obj[attr], props);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
copy[attr] = transformProps(obj[attr], props);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return copy;
|
|
56
|
+
}
|
|
57
|
+
throw new Error("Unable to copy obj! Its type isn't supported.");
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Parses a SQL statement, transforms its properties, and regenerates the SQL.
|
|
61
|
+
*
|
|
62
|
+
* @param statement - The SQL statement to transform.
|
|
63
|
+
* @param props - A map of properties and their transformation rules.
|
|
64
|
+
* @returns The transformed SQL statement.
|
|
65
|
+
*/
|
|
66
|
+
export const transform = async (statement, props) => {
|
|
67
|
+
let tree = await parse(statement);
|
|
68
|
+
tree = transformProps(tree, props);
|
|
69
|
+
return await deparse(tree);
|
|
70
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { getEnvOptions } from '@pgpmjs/env';
|
|
2
|
+
import { Logger } from '@pgpmjs/logger';
|
|
3
|
+
import { errors } from '@pgpmjs/types';
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { getPgPool } from 'pg-cache';
|
|
7
|
+
import { PgpmPackage } from '../core/class/pgpm';
|
|
8
|
+
import { PgpmMigrate } from '../migrate/client';
|
|
9
|
+
import { packageModule } from '../packaging/package';
|
|
10
|
+
// Cache for fast deployment
|
|
11
|
+
const deployFastCache = {};
|
|
12
|
+
const getCacheKey = (pg, name, database) => {
|
|
13
|
+
const { host, port, user } = pg ?? {};
|
|
14
|
+
return `${host}:${port}:${user}:${database}:${name}`;
|
|
15
|
+
};
|
|
16
|
+
const log = new Logger('deploy');
|
|
17
|
+
export const deployProject = async (opts, name, database, pkg, toChange) => {
|
|
18
|
+
const mergedOpts = getEnvOptions(opts);
|
|
19
|
+
log.info(`๐ Gathering modules from ${pkg.workspacePath}...`);
|
|
20
|
+
const modules = pkg.getModuleMap();
|
|
21
|
+
if (!modules[name]) {
|
|
22
|
+
log.error(`โ Module "${name}" not found in modules list.`);
|
|
23
|
+
throw errors.MODULE_NOT_FOUND({ name });
|
|
24
|
+
}
|
|
25
|
+
const modulePath = path.resolve(pkg.workspacePath, modules[name].path);
|
|
26
|
+
const moduleProject = new PgpmPackage(modulePath);
|
|
27
|
+
log.info(`๐ฆ Resolving dependencies for ${name}...`);
|
|
28
|
+
const extensions = moduleProject.getModuleExtensions();
|
|
29
|
+
const pgPool = getPgPool({ ...opts.pg, database });
|
|
30
|
+
log.success(`๐ Starting deployment to database ${database}...`);
|
|
31
|
+
for (const extension of extensions.resolved) {
|
|
32
|
+
try {
|
|
33
|
+
if (extensions.external.includes(extension)) {
|
|
34
|
+
const msg = `CREATE EXTENSION IF NOT EXISTS "${extension}" CASCADE;`;
|
|
35
|
+
log.info(`๐ฅ Installing external extension: ${extension}`);
|
|
36
|
+
log.debug(`> ${msg}`);
|
|
37
|
+
await pgPool.query(msg);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const modulePath = resolve(pkg.workspacePath, modules[extension].path);
|
|
41
|
+
log.info(`๐ Deploying local module: ${extension}`);
|
|
42
|
+
log.debug(`โ Path: ${modulePath}`);
|
|
43
|
+
if (mergedOpts.deployment.fast) {
|
|
44
|
+
// Use fast deployment strategy
|
|
45
|
+
const localProject = new PgpmPackage(modulePath);
|
|
46
|
+
const cacheKey = getCacheKey(mergedOpts.pg, extension, database);
|
|
47
|
+
if (mergedOpts.deployment.cache && deployFastCache[cacheKey]) {
|
|
48
|
+
log.warn(`โก Using cached package for ${extension}.`);
|
|
49
|
+
await pgPool.query(deployFastCache[cacheKey].sql);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
let modulePackage;
|
|
53
|
+
try {
|
|
54
|
+
modulePackage = await packageModule(localProject.modulePath, {
|
|
55
|
+
usePlan: mergedOpts.deployment.usePlan,
|
|
56
|
+
extension: false
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
// Build comprehensive error message
|
|
61
|
+
const errorLines = [];
|
|
62
|
+
errorLines.push(`โ Failed to package module "${extension}" at path: ${modulePath}`);
|
|
63
|
+
errorLines.push(` Module Path: ${modulePath}`);
|
|
64
|
+
errorLines.push(` Workspace Path: ${pkg.workspacePath}`);
|
|
65
|
+
errorLines.push(` Error Code: ${err.code || 'N/A'}`);
|
|
66
|
+
errorLines.push(` Error Message: ${err.message || 'Unknown error'}`);
|
|
67
|
+
// Provide debugging hints
|
|
68
|
+
if (err.code === 'ENOENT') {
|
|
69
|
+
errorLines.push('๐ก Hint: File or directory not found. Check if the module path is correct.');
|
|
70
|
+
}
|
|
71
|
+
else if (err.code === 'EACCES') {
|
|
72
|
+
errorLines.push('๐ก Hint: Permission denied. Check file permissions.');
|
|
73
|
+
}
|
|
74
|
+
else if (err.message && err.message.includes('pgpm.plan')) {
|
|
75
|
+
errorLines.push('๐ก Hint: pgpm.plan file issue. Check if the plan file exists and is valid.');
|
|
76
|
+
}
|
|
77
|
+
// Log the consolidated error message
|
|
78
|
+
log.error(errorLines.join('\n'));
|
|
79
|
+
console.error(err); // Preserve full stack trace
|
|
80
|
+
throw errors.DEPLOYMENT_FAILED({
|
|
81
|
+
type: 'Deployment',
|
|
82
|
+
module: extension
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
log.debug(`โ Command: sqitch deploy db:pg:${database}`);
|
|
86
|
+
log.debug(`> ${modulePackage.sql}`);
|
|
87
|
+
await pgPool.query(modulePackage.sql);
|
|
88
|
+
if (mergedOpts.deployment.cache) {
|
|
89
|
+
deployFastCache[cacheKey] = modulePackage;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// Use new migration system
|
|
94
|
+
log.debug(`โ Command: launchql migrate deploy db:pg:${database}`);
|
|
95
|
+
try {
|
|
96
|
+
const client = new PgpmMigrate(mergedOpts.pg);
|
|
97
|
+
const result = await client.deploy({
|
|
98
|
+
modulePath,
|
|
99
|
+
toChange,
|
|
100
|
+
useTransaction: mergedOpts.deployment.useTx,
|
|
101
|
+
logOnly: mergedOpts.deployment.logOnly
|
|
102
|
+
});
|
|
103
|
+
if (result.failed) {
|
|
104
|
+
throw errors.OPERATION_FAILED({ operation: 'Deployment', target: result.failed });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (deployError) {
|
|
108
|
+
log.error(`โ Deployment failed for module ${extension}`);
|
|
109
|
+
console.error(deployError);
|
|
110
|
+
throw errors.DEPLOYMENT_FAILED({ type: 'Deployment', module: extension });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
log.error(`๐ Error during deployment: ${err instanceof Error ? err.message : err}`);
|
|
117
|
+
console.error(err); // Keep raw error output for stack traces
|
|
118
|
+
throw errors.DEPLOYMENT_FAILED({ type: 'Deployment', module: extension });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
log.success(`โ
Deployment complete for ${name}.`);
|
|
122
|
+
return extensions;
|
|
123
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Logger } from '@pgpmjs/logger';
|
|
2
|
+
import { errors } from '@pgpmjs/types';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { getPgPool } from 'pg-cache';
|
|
6
|
+
import { PgpmPackage } from '../core/class/pgpm';
|
|
7
|
+
import { PgpmMigrate } from '../migrate/client';
|
|
8
|
+
const log = new Logger('revert');
|
|
9
|
+
export const revertProject = async (opts, name, database, pkg, options) => {
|
|
10
|
+
log.info(`๐ Gathering modules from ${pkg.workspacePath}...`);
|
|
11
|
+
const modules = pkg.getModuleMap();
|
|
12
|
+
if (!modules[name]) {
|
|
13
|
+
log.error(`โ Module "${name}" not found in modules list.`);
|
|
14
|
+
throw errors.MODULE_NOT_FOUND({ name });
|
|
15
|
+
}
|
|
16
|
+
const modulePath = path.resolve(pkg.workspacePath, modules[name].path);
|
|
17
|
+
const moduleProject = new PgpmPackage(modulePath);
|
|
18
|
+
log.info(`๐ฆ Resolving dependencies for ${name}...`);
|
|
19
|
+
const extensions = moduleProject.getModuleExtensions();
|
|
20
|
+
const pgPool = getPgPool({
|
|
21
|
+
...opts.pg,
|
|
22
|
+
database
|
|
23
|
+
});
|
|
24
|
+
log.success(`๐งน Starting revert process on database ${database}...`);
|
|
25
|
+
const reversedExtensions = [...extensions.resolved].reverse();
|
|
26
|
+
for (const extension of reversedExtensions) {
|
|
27
|
+
try {
|
|
28
|
+
if (extensions.external.includes(extension)) {
|
|
29
|
+
const msg = `DROP EXTENSION IF EXISTS "${extension}" RESTRICT;`;
|
|
30
|
+
log.warn(`โ ๏ธ Dropping external extension: ${extension}`);
|
|
31
|
+
log.debug(`> ${msg}`);
|
|
32
|
+
try {
|
|
33
|
+
await pgPool.query(msg);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (err.code === '2BP01') { // dependent_objects_still_exist
|
|
37
|
+
log.warn(`โ ๏ธ Cannot drop extension ${extension} due to dependencies, skipping`);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const modulePath = resolve(pkg.workspacePath, modules[extension].path);
|
|
46
|
+
log.info(`๐ Reverting local module: ${extension}`);
|
|
47
|
+
log.debug(`โ Path: ${modulePath}`);
|
|
48
|
+
// Use new migration system
|
|
49
|
+
log.debug(`โ Command: launchql migrate revert db:pg:${database}`);
|
|
50
|
+
try {
|
|
51
|
+
const client = new PgpmMigrate(opts.pg);
|
|
52
|
+
const result = await client.revert({
|
|
53
|
+
modulePath,
|
|
54
|
+
toChange: options?.toChange,
|
|
55
|
+
useTransaction: options?.useTransaction
|
|
56
|
+
});
|
|
57
|
+
if (result.failed) {
|
|
58
|
+
throw errors.OPERATION_FAILED({ operation: 'Revert', target: result.failed });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (revertError) {
|
|
62
|
+
log.error(`โ Revert failed for module ${extension}`);
|
|
63
|
+
throw errors.DEPLOYMENT_FAILED({ type: 'Revert', module: extension });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
log.error(`๐ Error during revert: ${e instanceof Error ? e.message : e}`);
|
|
69
|
+
console.error(e); // optional raw stack trace
|
|
70
|
+
throw errors.DEPLOYMENT_FAILED({ type: 'Revert', module: extension });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
log.success(`โ
Revert complete for ${name}.`);
|
|
74
|
+
return extensions;
|
|
75
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Logger } from '@pgpmjs/logger';
|
|
2
|
+
import { errors } from '@pgpmjs/types';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { getPgPool } from 'pg-cache';
|
|
6
|
+
import { PgpmPackage } from '../core/class/pgpm';
|
|
7
|
+
import { PgpmMigrate } from '../migrate/client';
|
|
8
|
+
const log = new Logger('verify');
|
|
9
|
+
export const verifyProject = async (opts, name, database, pkg, options) => {
|
|
10
|
+
log.info(`๐ Gathering modules from ${pkg.workspacePath}...`);
|
|
11
|
+
const modules = pkg.getModuleMap();
|
|
12
|
+
if (!modules[name]) {
|
|
13
|
+
log.error(`โ Module "${name}" not found in modules list.`);
|
|
14
|
+
throw errors.MODULE_NOT_FOUND({ name });
|
|
15
|
+
}
|
|
16
|
+
const modulePath = path.resolve(pkg.workspacePath, modules[name].path);
|
|
17
|
+
const moduleProject = new PgpmPackage(modulePath);
|
|
18
|
+
log.info(`๐ฆ Resolving dependencies for ${name}...`);
|
|
19
|
+
const extensions = moduleProject.getModuleExtensions();
|
|
20
|
+
const pgPool = getPgPool({
|
|
21
|
+
...opts.pg,
|
|
22
|
+
database
|
|
23
|
+
});
|
|
24
|
+
log.success(`๐ Verifying deployment of ${name} on database ${database}...`);
|
|
25
|
+
for (const extension of extensions.resolved) {
|
|
26
|
+
try {
|
|
27
|
+
if (extensions.external.includes(extension)) {
|
|
28
|
+
const query = `SELECT 1/count(*) FROM pg_available_extensions WHERE name = $1`;
|
|
29
|
+
log.info(`๐ Verifying external extension: ${extension}`);
|
|
30
|
+
log.debug(`> ${query}`);
|
|
31
|
+
await pgPool.query(query, [extension]);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const modulePath = resolve(pkg.workspacePath, modules[extension].path);
|
|
35
|
+
log.info(`๐ Verifying local module: ${extension}`);
|
|
36
|
+
log.debug(`โ Path: ${modulePath}`);
|
|
37
|
+
log.debug(`โ Command: launchql migrate verify db:pg:${database}`);
|
|
38
|
+
try {
|
|
39
|
+
const client = new PgpmMigrate(opts.pg);
|
|
40
|
+
const result = await client.verify({
|
|
41
|
+
modulePath
|
|
42
|
+
});
|
|
43
|
+
if (result.failed.length > 0) {
|
|
44
|
+
throw errors.OPERATION_FAILED({ operation: 'Verification', reason: `${result.failed.length} changes: ${result.failed.join(', ')}` });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (verifyError) {
|
|
48
|
+
log.error(`โ Verification failed for module ${extension}`);
|
|
49
|
+
throw errors.DEPLOYMENT_FAILED({ type: 'Verify', module: extension });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
log.error(`๐ Error during verification: ${e instanceof Error ? e.message : e}`);
|
|
55
|
+
console.error(e);
|
|
56
|
+
throw errors.DEPLOYMENT_FAILED({ type: 'Verify', module: extension });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
log.success(`โ
Verification complete for ${name}.`);
|
|
60
|
+
return extensions;
|
|
61
|
+
};
|