@constructive-io/cli 0.0.3 → 5.1.1
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 +1 -1
- package/README.md +346 -153
- package/commands/{analyze.d.ts → codegen.d.ts} +2 -2
- package/commands/codegen.js +131 -0
- package/commands/explorer.js +94 -0
- package/commands/get-graphql-schema.js +73 -0
- package/commands/server.js +187 -0
- package/commands.d.ts +0 -1
- package/commands.js +42 -61
- package/esm/commands/codegen.js +126 -0
- package/esm/commands/explorer.js +92 -0
- package/esm/commands/get-graphql-schema.js +71 -0
- package/esm/commands/server.js +185 -0
- package/esm/commands.js +41 -59
- package/esm/index.js +16 -36
- package/esm/utils/display.js +26 -23
- package/esm/utils/index.js +3 -6
- package/index.d.ts +0 -22
- package/index.js +16 -72
- package/package.json +50 -25
- package/utils/display.d.ts +1 -1
- package/utils/display.js +26 -23
- package/utils/index.d.ts +3 -6
- package/utils/index.js +7 -20
- package/commands/add.d.ts +0 -7
- package/commands/add.js +0 -86
- package/commands/admin-users/add.d.ts +0 -4
- package/commands/admin-users/add.js +0 -89
- package/commands/admin-users/bootstrap.d.ts +0 -4
- package/commands/admin-users/bootstrap.js +0 -50
- package/commands/admin-users/remove.d.ts +0 -4
- package/commands/admin-users/remove.js +0 -82
- package/commands/admin-users.d.ts +0 -4
- package/commands/admin-users.js +0 -68
- package/commands/analyze.js +0 -21
- package/commands/clear.d.ts +0 -3
- package/commands/clear.js +0 -59
- package/commands/deploy.d.ts +0 -4
- package/commands/deploy.js +0 -146
- package/commands/docker.d.ts +0 -3
- package/commands/docker.js +0 -194
- package/commands/env.d.ts +0 -4
- package/commands/env.js +0 -124
- package/commands/export.js +0 -129
- package/commands/extension.js +0 -48
- package/commands/init/index.d.ts +0 -7
- package/commands/init/index.js +0 -47
- package/commands/init/module.d.ts +0 -4
- package/commands/init/module.js +0 -71
- package/commands/init/workspace.d.ts +0 -4
- package/commands/init/workspace.js +0 -52
- package/commands/install.d.ts +0 -4
- package/commands/install.js +0 -37
- package/commands/kill.js +0 -107
- package/commands/migrate/deps.d.ts +0 -4
- package/commands/migrate/deps.js +0 -186
- package/commands/migrate/init.d.ts +0 -4
- package/commands/migrate/init.js +0 -65
- package/commands/migrate/list.d.ts +0 -4
- package/commands/migrate/list.js +0 -85
- package/commands/migrate/status.d.ts +0 -4
- package/commands/migrate/status.js +0 -94
- package/commands/migrate.d.ts +0 -4
- package/commands/migrate.js +0 -69
- package/commands/package.d.ts +0 -3
- package/commands/package.js +0 -65
- package/commands/plan.d.ts +0 -3
- package/commands/plan.js +0 -62
- package/commands/remove.d.ts +0 -3
- package/commands/remove.js +0 -42
- package/commands/rename.d.ts +0 -4
- package/commands/rename.js +0 -35
- package/commands/revert.d.ts +0 -3
- package/commands/revert.js +0 -107
- package/commands/tag.d.ts +0 -6
- package/commands/tag.js +0 -168
- package/commands/verify.d.ts +0 -3
- package/commands/verify.js +0 -85
- package/dist/README.md +0 -412
- package/dist/package.json +0 -64
- package/esm/commands/add.js +0 -51
- package/esm/commands/admin-users/add.js +0 -87
- package/esm/commands/admin-users/bootstrap.js +0 -48
- package/esm/commands/admin-users/remove.js +0 -80
- package/esm/commands/admin-users.js +0 -63
- package/esm/commands/analyze.js +0 -16
- package/esm/commands/clear.js +0 -54
- package/esm/commands/deploy.js +0 -144
- package/esm/commands/docker.js +0 -192
- package/esm/commands/env.js +0 -122
- package/esm/commands/export.js +0 -127
- package/esm/commands/extension.js +0 -46
- package/esm/commands/init/index.js +0 -42
- package/esm/commands/init/module.js +0 -68
- package/esm/commands/init/workspace.js +0 -46
- package/esm/commands/install.js +0 -35
- package/esm/commands/kill.js +0 -105
- package/esm/commands/migrate/deps.js +0 -184
- package/esm/commands/migrate/init.js +0 -63
- package/esm/commands/migrate/list.js +0 -83
- package/esm/commands/migrate/status.js +0 -92
- package/esm/commands/migrate.js +0 -64
- package/esm/commands/package.js +0 -63
- package/esm/commands/plan.js +0 -60
- package/esm/commands/remove.js +0 -40
- package/esm/commands/rename.js +0 -30
- package/esm/commands/revert.js +0 -105
- package/esm/commands/tag.js +0 -133
- package/esm/commands/verify.js +0 -83
- package/esm/package.js +0 -26
- package/esm/utils/argv.js +0 -92
- package/esm/utils/cli-error.js +0 -48
- package/esm/utils/database.js +0 -78
- package/esm/utils/deployed-changes.js +0 -68
- package/esm/utils/module-utils.js +0 -51
- package/package.d.ts +0 -1
- package/package.js +0 -29
- package/utils/argv.d.ts +0 -46
- package/utils/argv.js +0 -100
- package/utils/cli-error.d.ts +0 -8
- package/utils/cli-error.js +0 -52
- package/utils/database.d.ts +0 -21
- package/utils/database.js +0 -83
- package/utils/deployed-changes.d.ts +0 -4
- package/utils/deployed-changes.js +0 -72
- package/utils/module-utils.d.ts +0 -8
- package/utils/module-utils.js +0 -54
- /package/commands/{export.d.ts → explorer.d.ts} +0 -0
- /package/commands/{extension.d.ts → get-graphql-schema.d.ts} +0 -0
- /package/commands/{kill.d.ts → server.d.ts} +0 -0
package/esm/commands/tag.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { LaunchQLPackage } from '@launchql/core';
|
|
2
|
-
import { Logger } from '@launchql/logger';
|
|
3
|
-
import { errors } from '@launchql/types';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import { extractFirst } from '../utils/argv';
|
|
6
|
-
import { selectPackage } from '../utils/module-utils';
|
|
7
|
-
const log = new Logger('tag');
|
|
8
|
-
const tagUsageText = `
|
|
9
|
-
Tag Command:
|
|
10
|
-
|
|
11
|
-
constructive tag [tag_name] [OPTIONS]
|
|
12
|
-
|
|
13
|
-
Add tags to changes for versioning.
|
|
14
|
-
|
|
15
|
-
Arguments:
|
|
16
|
-
tag_name Name of the tag to create
|
|
17
|
-
|
|
18
|
-
Options:
|
|
19
|
-
--help, -h Show this help message
|
|
20
|
-
--package <name> Target specific package
|
|
21
|
-
--changeName <name> Target specific change (default: latest)
|
|
22
|
-
--comment <text> Optional tag comment
|
|
23
|
-
--cwd <directory> Working directory (default: current directory)
|
|
24
|
-
|
|
25
|
-
Examples:
|
|
26
|
-
constructive tag v1.0.0 Add tag to latest change
|
|
27
|
-
constructive tag v1.0.0 --comment "Initial release" Add tag with comment
|
|
28
|
-
constructive tag v1.1.0 --package mypackage --changeName my-change Tag specific change in package
|
|
29
|
-
`;
|
|
30
|
-
export default async (argv, prompter, _options) => {
|
|
31
|
-
// Show usage if explicitly requested
|
|
32
|
-
if (argv.help || argv.h) {
|
|
33
|
-
console.log(tagUsageText);
|
|
34
|
-
process.exit(0);
|
|
35
|
-
}
|
|
36
|
-
const { first: tagName, newArgv } = extractFirst(argv);
|
|
37
|
-
const cwdResult = await prompter.prompt(newArgv, [
|
|
38
|
-
{
|
|
39
|
-
type: 'text',
|
|
40
|
-
name: 'cwd',
|
|
41
|
-
message: 'Working directory',
|
|
42
|
-
required: false,
|
|
43
|
-
default: process.cwd(),
|
|
44
|
-
useDefault: true
|
|
45
|
-
}
|
|
46
|
-
]);
|
|
47
|
-
const cwd = cwdResult.cwd || process.cwd();
|
|
48
|
-
const pkg = new LaunchQLPackage(cwd);
|
|
49
|
-
let packageName;
|
|
50
|
-
if (argv.package) {
|
|
51
|
-
packageName = argv.package;
|
|
52
|
-
log.info(`Using specified package: ${packageName}`);
|
|
53
|
-
}
|
|
54
|
-
else if (pkg.isInModule()) {
|
|
55
|
-
packageName = pkg.getModuleName();
|
|
56
|
-
log.info(`Using current module: ${packageName}`);
|
|
57
|
-
}
|
|
58
|
-
else if (pkg.isInWorkspace()) {
|
|
59
|
-
packageName = await selectPackage(newArgv, prompter, cwd, 'add tag to', log);
|
|
60
|
-
if (!packageName) {
|
|
61
|
-
throw new Error('No package selected. Cannot add tag without specifying a target package.');
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
throw new Error('This command must be run inside a LaunchQL workspace or module.');
|
|
66
|
-
}
|
|
67
|
-
const questions = [];
|
|
68
|
-
if (!tagName) {
|
|
69
|
-
questions.push({
|
|
70
|
-
type: 'text',
|
|
71
|
-
name: 'tagName',
|
|
72
|
-
message: 'Tag name',
|
|
73
|
-
required: true,
|
|
74
|
-
validate: (value) => {
|
|
75
|
-
if (!value || value.trim().length === 0) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
if (value.includes('/')) {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
if (value.includes('@')) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
questions.push({
|
|
89
|
-
type: 'text',
|
|
90
|
-
name: 'changeName',
|
|
91
|
-
message: 'Target change name (leave empty for latest change)',
|
|
92
|
-
required: false
|
|
93
|
-
}, {
|
|
94
|
-
type: 'text',
|
|
95
|
-
name: 'comment',
|
|
96
|
-
message: 'Tag comment (optional)',
|
|
97
|
-
required: false
|
|
98
|
-
});
|
|
99
|
-
const answers = await prompter.prompt(newArgv, questions);
|
|
100
|
-
const finalTagName = tagName || answers.tagName;
|
|
101
|
-
const changeName = answers.changeName;
|
|
102
|
-
const comment = answers.comment;
|
|
103
|
-
try {
|
|
104
|
-
if (argv.package || !pkg.isInModule()) {
|
|
105
|
-
const moduleMap = pkg.getModuleMap();
|
|
106
|
-
const module = moduleMap[packageName];
|
|
107
|
-
if (!module) {
|
|
108
|
-
throw errors.MODULE_NOT_FOUND({ name: packageName });
|
|
109
|
-
}
|
|
110
|
-
const workspacePath = pkg.getWorkspacePath();
|
|
111
|
-
const absoluteModulePath = path.resolve(workspacePath, module.path);
|
|
112
|
-
const originalCwd = process.cwd();
|
|
113
|
-
process.chdir(absoluteModulePath);
|
|
114
|
-
try {
|
|
115
|
-
const modulePkg = new LaunchQLPackage(absoluteModulePath);
|
|
116
|
-
modulePkg.addTag(finalTagName.trim(), changeName?.trim() || undefined, comment?.trim() || undefined);
|
|
117
|
-
log.info(`Successfully added tag '${finalTagName}' to ${changeName || 'latest change'} in package '${packageName}'`);
|
|
118
|
-
}
|
|
119
|
-
finally {
|
|
120
|
-
process.chdir(originalCwd);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
pkg.addTag(finalTagName.trim(), changeName?.trim() || undefined, comment?.trim() || undefined);
|
|
125
|
-
log.info(`Successfully added tag '${finalTagName}' to ${changeName || 'latest change'}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
catch (error) {
|
|
129
|
-
log.error(`Failed to add tag: ${error instanceof Error ? error.message : String(error)}`);
|
|
130
|
-
throw error;
|
|
131
|
-
}
|
|
132
|
-
return newArgv;
|
|
133
|
-
};
|
package/esm/commands/verify.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { LaunchQLPackage } from '@launchql/core';
|
|
2
|
-
import { getEnvOptions } from '@launchql/env';
|
|
3
|
-
import { Logger } from '@launchql/logger';
|
|
4
|
-
import { getPgEnvOptions } from 'pg-env';
|
|
5
|
-
import { getTargetDatabase } from '../utils';
|
|
6
|
-
import { cliExitWithError } from '../utils/cli-error';
|
|
7
|
-
import { selectDeployedChange, selectDeployedPackage } from '../utils/deployed-changes';
|
|
8
|
-
const log = new Logger('verify');
|
|
9
|
-
const verifyUsageText = `
|
|
10
|
-
Verify Command:
|
|
11
|
-
|
|
12
|
-
constructive verify [OPTIONS]
|
|
13
|
-
|
|
14
|
-
Verify database state matches expected migrations.
|
|
15
|
-
|
|
16
|
-
Options:
|
|
17
|
-
--help, -h Show this help message
|
|
18
|
-
--recursive Verify recursively through dependencies
|
|
19
|
-
--package <name> Verify specific package
|
|
20
|
-
--to <target> Verify up to specific change or tag
|
|
21
|
-
--to Interactive selection of deployed changes
|
|
22
|
-
--cwd <directory> Working directory (default: current directory)
|
|
23
|
-
|
|
24
|
-
Examples:
|
|
25
|
-
constructive verify Verify current database state
|
|
26
|
-
constructive verify --package mypackage Verify specific package
|
|
27
|
-
constructive verify --to Interactive selection from deployed changes
|
|
28
|
-
`;
|
|
29
|
-
export default async (argv, prompter, _options) => {
|
|
30
|
-
// Show usage if explicitly requested
|
|
31
|
-
if (argv.help || argv.h) {
|
|
32
|
-
console.log(verifyUsageText);
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
|
-
const database = await getTargetDatabase(argv, prompter, {
|
|
36
|
-
message: 'Select database'
|
|
37
|
-
});
|
|
38
|
-
const questions = [
|
|
39
|
-
{
|
|
40
|
-
name: 'recursive',
|
|
41
|
-
type: 'confirm',
|
|
42
|
-
message: 'Deploy recursively through dependencies?',
|
|
43
|
-
useDefault: true,
|
|
44
|
-
default: true,
|
|
45
|
-
required: false
|
|
46
|
-
},
|
|
47
|
-
];
|
|
48
|
-
let { recursive, cwd } = await prompter.prompt(argv, questions);
|
|
49
|
-
log.debug(`Using current directory: ${cwd}`);
|
|
50
|
-
let packageName;
|
|
51
|
-
if (recursive && argv.to !== true) {
|
|
52
|
-
packageName = await selectDeployedPackage(database, argv, prompter, log, 'verify');
|
|
53
|
-
if (!packageName) {
|
|
54
|
-
await cliExitWithError('No package found to verify');
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const project = new LaunchQLPackage(cwd);
|
|
58
|
-
const opts = getEnvOptions({
|
|
59
|
-
pg: getPgEnvOptions({ database })
|
|
60
|
-
});
|
|
61
|
-
let target;
|
|
62
|
-
if (argv.to === true) {
|
|
63
|
-
target = await selectDeployedChange(database, argv, prompter, log, 'verify');
|
|
64
|
-
if (!target) {
|
|
65
|
-
await cliExitWithError('No target selected, operation cancelled');
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else if (packageName && argv.to) {
|
|
69
|
-
target = `${packageName}:${argv.to}`;
|
|
70
|
-
}
|
|
71
|
-
else if (packageName) {
|
|
72
|
-
target = packageName;
|
|
73
|
-
}
|
|
74
|
-
else if (argv.package && argv.to) {
|
|
75
|
-
target = `${argv.package}:${argv.to}`;
|
|
76
|
-
}
|
|
77
|
-
else if (argv.package) {
|
|
78
|
-
target = argv.package;
|
|
79
|
-
}
|
|
80
|
-
await project.verify(opts, target, recursive);
|
|
81
|
-
log.success('Verify complete.');
|
|
82
|
-
return argv;
|
|
83
|
-
};
|
package/esm/package.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'fs';
|
|
2
|
-
import { dirname, join } from 'path';
|
|
3
|
-
// need to search due to the dist/ folder and src/, etc.
|
|
4
|
-
function findPackageJson(currentDir) {
|
|
5
|
-
const filePath = join(currentDir, 'package.json');
|
|
6
|
-
// Check if package.json exists in the current directory
|
|
7
|
-
if (existsSync(filePath)) {
|
|
8
|
-
return filePath;
|
|
9
|
-
}
|
|
10
|
-
// Get the parent directory
|
|
11
|
-
const parentDir = dirname(currentDir);
|
|
12
|
-
// If reached the root directory, package.json is not found
|
|
13
|
-
if (parentDir === currentDir) {
|
|
14
|
-
throw new Error('package.json not found in any parent directory');
|
|
15
|
-
}
|
|
16
|
-
// Recursively look in the parent directory
|
|
17
|
-
return findPackageJson(parentDir);
|
|
18
|
-
}
|
|
19
|
-
export function readAndParsePackageJson() {
|
|
20
|
-
// Start searching from the current directory
|
|
21
|
-
const pkgPath = findPackageJson(__dirname);
|
|
22
|
-
// Read and parse the package.json
|
|
23
|
-
const str = readFileSync(pkgPath, 'utf8');
|
|
24
|
-
const pkg = JSON.parse(str);
|
|
25
|
-
return pkg;
|
|
26
|
-
}
|
package/esm/utils/argv.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@launchql/logger';
|
|
2
|
-
const log = new Logger('argv-utils');
|
|
3
|
-
export const extractFirst = (argv) => {
|
|
4
|
-
const first = argv._?.[0];
|
|
5
|
-
const newArgv = {
|
|
6
|
-
...argv,
|
|
7
|
-
_: argv._?.slice(1) ?? []
|
|
8
|
-
};
|
|
9
|
-
return { first, newArgv };
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Validates and normalizes common CLI arguments
|
|
13
|
-
*/
|
|
14
|
-
export function validateCommonArgs(argv) {
|
|
15
|
-
const validated = {
|
|
16
|
-
...argv,
|
|
17
|
-
cwd: argv.cwd || process.cwd(),
|
|
18
|
-
_: argv._ || []
|
|
19
|
-
};
|
|
20
|
-
const booleanFlags = ['recursive', 'yes', 'tx', 'fast', 'logOnly', 'createdb', 'usePlan', 'cache', 'drop', 'all', 'summary', 'help', 'h'];
|
|
21
|
-
for (const flag of booleanFlags) {
|
|
22
|
-
if (argv[flag] !== undefined && typeof argv[flag] !== 'boolean') {
|
|
23
|
-
log.warn(`--${flag} flag should be boolean, converting to true`);
|
|
24
|
-
validated[flag] = true;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const stringFlags = ['package', 'to', 'database'];
|
|
28
|
-
for (const flag of stringFlags) {
|
|
29
|
-
if (argv[flag] !== undefined && typeof argv[flag] !== 'string') {
|
|
30
|
-
log.warn(`--${flag} should be a string, converting`);
|
|
31
|
-
validated[flag] = String(argv[flag]);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return validated;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Checks if required flags are provided when certain conditions are met
|
|
38
|
-
*/
|
|
39
|
-
export function validateFlagDependencies(argv) {
|
|
40
|
-
if (argv.to && !argv.package && !argv.recursive) {
|
|
41
|
-
log.warn('--to flag provided without --package or --recursive. Target may not work as expected.');
|
|
42
|
-
}
|
|
43
|
-
if (argv.package && argv.recursive) {
|
|
44
|
-
if (argv.package.includes(':')) {
|
|
45
|
-
log.warn('--package should not contain ":" when using --recursive. Use --to for target specification.');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Logs the effective CLI arguments for debugging
|
|
51
|
-
*/
|
|
52
|
-
export function logEffectiveArgs(argv, commandName) {
|
|
53
|
-
const relevantArgs = {
|
|
54
|
-
cwd: argv.cwd,
|
|
55
|
-
database: argv.database,
|
|
56
|
-
package: argv.package,
|
|
57
|
-
to: argv.to,
|
|
58
|
-
recursive: argv.recursive,
|
|
59
|
-
yes: argv.yes,
|
|
60
|
-
tx: argv.tx,
|
|
61
|
-
fast: argv.fast,
|
|
62
|
-
logOnly: argv.logOnly,
|
|
63
|
-
createdb: argv.createdb,
|
|
64
|
-
usePlan: argv.usePlan,
|
|
65
|
-
cache: argv.cache,
|
|
66
|
-
drop: argv.drop,
|
|
67
|
-
all: argv.all,
|
|
68
|
-
summary: argv.summary
|
|
69
|
-
};
|
|
70
|
-
const definedArgs = Object.fromEntries(Object.entries(relevantArgs).filter(([_, value]) => value !== undefined));
|
|
71
|
-
if (Object.keys(definedArgs).length > 1) { // More than just cwd
|
|
72
|
-
log.debug(`${commandName} effective arguments:`, definedArgs);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Constructs a deployment target string from package and to arguments
|
|
77
|
-
*/
|
|
78
|
-
export function constructTarget(argv, packageName) {
|
|
79
|
-
if (packageName && argv.to) {
|
|
80
|
-
return `${packageName}:${argv.to}`;
|
|
81
|
-
}
|
|
82
|
-
else if (packageName) {
|
|
83
|
-
return packageName;
|
|
84
|
-
}
|
|
85
|
-
else if (argv.package && argv.to) {
|
|
86
|
-
return `${argv.package}:${argv.to}`;
|
|
87
|
-
}
|
|
88
|
-
else if (argv.package) {
|
|
89
|
-
return argv.package;
|
|
90
|
-
}
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
package/esm/utils/cli-error.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@launchql/logger';
|
|
2
|
-
import { LaunchQLError } from '@launchql/types';
|
|
3
|
-
import { teardownPgPools } from 'pg-cache';
|
|
4
|
-
const log = new Logger('cli');
|
|
5
|
-
/**
|
|
6
|
-
* CLI error utility that logs error information and exits with code 1.
|
|
7
|
-
* Provides consistent error handling and user experience across all CLI commands.
|
|
8
|
-
*
|
|
9
|
-
* IMPORTANT: This function properly cleans up PostgreSQL connections before exiting.
|
|
10
|
-
*/
|
|
11
|
-
export const cliExitWithError = async (error, context) => {
|
|
12
|
-
if (error instanceof LaunchQLError) {
|
|
13
|
-
// For LaunchQLError instances, use structured logging
|
|
14
|
-
log.error(`Error: ${error.message}`);
|
|
15
|
-
// Log additional context if available
|
|
16
|
-
if (error.context && Object.keys(error.context).length > 0) {
|
|
17
|
-
log.debug('Error context:', error.context);
|
|
18
|
-
}
|
|
19
|
-
// Log any additional context provided
|
|
20
|
-
if (context) {
|
|
21
|
-
log.debug('Additional context:', context);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
else if (error instanceof Error) {
|
|
25
|
-
// For generic Error instances
|
|
26
|
-
log.error(`Error: ${error.message}`);
|
|
27
|
-
if (context) {
|
|
28
|
-
log.debug('Context:', context);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else if (typeof error === 'string') {
|
|
32
|
-
// For simple string messages
|
|
33
|
-
log.error(`Error: ${error}`);
|
|
34
|
-
if (context) {
|
|
35
|
-
log.debug('Context:', context);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Perform cleanup before exiting
|
|
39
|
-
try {
|
|
40
|
-
await teardownPgPools();
|
|
41
|
-
log.debug('Database connections cleaned up');
|
|
42
|
-
}
|
|
43
|
-
catch (cleanupError) {
|
|
44
|
-
log.warn('Failed to cleanup database connections:', cleanupError);
|
|
45
|
-
// Don't let cleanup errors prevent the exit
|
|
46
|
-
}
|
|
47
|
-
process.exit(1);
|
|
48
|
-
};
|
package/esm/utils/database.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { getPgPool } from 'pg-cache';
|
|
2
|
-
import { getPgEnvOptions } from 'pg-env';
|
|
3
|
-
/**
|
|
4
|
-
* Get list of available databases from PostgreSQL
|
|
5
|
-
*/
|
|
6
|
-
export async function getAvailableDatabases(options = {}) {
|
|
7
|
-
const { excludeTemplates = true, excludePostgres = true, excludeSystemDbs = true } = options;
|
|
8
|
-
const db = await getPgPool({
|
|
9
|
-
database: 'postgres'
|
|
10
|
-
});
|
|
11
|
-
let query = `
|
|
12
|
-
SELECT datname FROM pg_catalog.pg_database
|
|
13
|
-
WHERE 1=1
|
|
14
|
-
`;
|
|
15
|
-
if (excludeTemplates) {
|
|
16
|
-
query += ` AND datistemplate = FALSE`;
|
|
17
|
-
}
|
|
18
|
-
if (excludePostgres) {
|
|
19
|
-
query += ` AND datname NOT IN ('postgres')`;
|
|
20
|
-
}
|
|
21
|
-
if (excludeSystemDbs) {
|
|
22
|
-
query += ` AND datname !~ '^pg_'`;
|
|
23
|
-
}
|
|
24
|
-
query += ` ORDER BY datname`;
|
|
25
|
-
const result = await db.query(query);
|
|
26
|
-
return result.rows.map((row) => row.datname);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Prompt user to select a database
|
|
30
|
-
*/
|
|
31
|
-
export async function selectDatabase(argv, prompter, options = {}) {
|
|
32
|
-
const { message = 'Select target database', multiple = false } = options;
|
|
33
|
-
// Check if database is already specified
|
|
34
|
-
if (!multiple && (argv.db || argv.database)) {
|
|
35
|
-
return argv.db || argv.database;
|
|
36
|
-
}
|
|
37
|
-
// Get available databases
|
|
38
|
-
const databases = await getAvailableDatabases(options);
|
|
39
|
-
if (databases.length === 0) {
|
|
40
|
-
throw new Error('No databases found');
|
|
41
|
-
}
|
|
42
|
-
// If only one database and not forcing selection, use it
|
|
43
|
-
if (!multiple && databases.length === 1 && !argv.interactive) {
|
|
44
|
-
return databases[0];
|
|
45
|
-
}
|
|
46
|
-
// Prompt for selection
|
|
47
|
-
const answer = await prompter.prompt(argv, [
|
|
48
|
-
{
|
|
49
|
-
type: multiple ? 'checkbox' : 'autocomplete',
|
|
50
|
-
name: 'database',
|
|
51
|
-
message,
|
|
52
|
-
options: databases,
|
|
53
|
-
required: true
|
|
54
|
-
}
|
|
55
|
-
]);
|
|
56
|
-
return answer.database;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Get target database with fallback to environment
|
|
60
|
-
*/
|
|
61
|
-
export async function getTargetDatabase(argv, prompter, options = {}) {
|
|
62
|
-
// If database is specified in args, use it
|
|
63
|
-
if (argv.db || argv.database) {
|
|
64
|
-
return argv.db || argv.database;
|
|
65
|
-
}
|
|
66
|
-
// Try to select from available databases
|
|
67
|
-
try {
|
|
68
|
-
return await selectDatabase(argv, prompter, options);
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
// Fall back to environment database
|
|
72
|
-
const pgEnv = getPgEnvOptions();
|
|
73
|
-
if (pgEnv.database) {
|
|
74
|
-
return pgEnv.database;
|
|
75
|
-
}
|
|
76
|
-
throw new Error('No database specified and no default database found');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { LaunchQLMigrate } from '@launchql/core';
|
|
2
|
-
import { getPgEnvOptions } from 'pg-env';
|
|
3
|
-
export async function selectDeployedChange(database, argv, prompter, log, action = 'revert') {
|
|
4
|
-
const pgEnv = getPgEnvOptions({ database });
|
|
5
|
-
const client = new LaunchQLMigrate(pgEnv);
|
|
6
|
-
let selectedPackage;
|
|
7
|
-
if (argv.package) {
|
|
8
|
-
selectedPackage = argv.package;
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
const packageStatuses = await client.status();
|
|
12
|
-
if (packageStatuses.length === 0) {
|
|
13
|
-
log.warn('No deployed packages found in database');
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
const packageAnswer = await prompter.prompt(argv, [{
|
|
17
|
-
type: 'autocomplete',
|
|
18
|
-
name: 'package',
|
|
19
|
-
message: `Select package to ${action} from:`,
|
|
20
|
-
options: packageStatuses.map(status => ({
|
|
21
|
-
name: status.package,
|
|
22
|
-
value: status.package,
|
|
23
|
-
description: `${status.totalDeployed} changes, last: ${status.lastChange}`
|
|
24
|
-
}))
|
|
25
|
-
}]);
|
|
26
|
-
selectedPackage = packageAnswer.package;
|
|
27
|
-
}
|
|
28
|
-
const deployedChanges = await client.getDeployedChanges(database, selectedPackage);
|
|
29
|
-
if (deployedChanges.length === 0) {
|
|
30
|
-
log.warn(`No deployed changes found for package ${selectedPackage}`);
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
const changeAnswer = await prompter.prompt(argv, [{
|
|
34
|
-
type: 'autocomplete',
|
|
35
|
-
name: 'change',
|
|
36
|
-
message: `Select change to ${action} to in ${selectedPackage}:`,
|
|
37
|
-
options: deployedChanges.map(change => ({
|
|
38
|
-
name: change.change_name,
|
|
39
|
-
value: change.change_name,
|
|
40
|
-
description: `Deployed: ${new Date(change.deployed_at).toLocaleString()}`
|
|
41
|
-
}))
|
|
42
|
-
}]);
|
|
43
|
-
const selectedChange = changeAnswer.change;
|
|
44
|
-
return `${selectedPackage}:${selectedChange}`;
|
|
45
|
-
}
|
|
46
|
-
export async function selectDeployedPackage(database, argv, prompter, log, action = 'revert') {
|
|
47
|
-
if (argv.package) {
|
|
48
|
-
return argv.package;
|
|
49
|
-
}
|
|
50
|
-
const pgEnv = getPgEnvOptions({ database });
|
|
51
|
-
const client = new LaunchQLMigrate(pgEnv);
|
|
52
|
-
const packageStatuses = await client.status();
|
|
53
|
-
if (packageStatuses.length === 0) {
|
|
54
|
-
log.warn('No deployed packages found in database');
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
const packageAnswer = await prompter.prompt(argv, [{
|
|
58
|
-
type: 'autocomplete',
|
|
59
|
-
name: 'package',
|
|
60
|
-
message: `Select package to ${action}:`,
|
|
61
|
-
options: packageStatuses.map(status => ({
|
|
62
|
-
name: status.package,
|
|
63
|
-
value: status.package,
|
|
64
|
-
description: `${status.totalDeployed} changes, last: ${status.lastChange}`
|
|
65
|
-
}))
|
|
66
|
-
}]);
|
|
67
|
-
return packageAnswer.package;
|
|
68
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { LaunchQLPackage } from '@launchql/core';
|
|
2
|
-
import { errors } from '@launchql/types';
|
|
3
|
-
/**
|
|
4
|
-
* Handle package selection for operations that need a specific package
|
|
5
|
-
* Returns the selected package name, or undefined if validation fails or no packages exist
|
|
6
|
-
*/
|
|
7
|
-
export async function selectPackage(argv, prompter, cwd, operationName, log) {
|
|
8
|
-
const pkg = new LaunchQLPackage(cwd);
|
|
9
|
-
const modules = await pkg.getModules();
|
|
10
|
-
const moduleNames = modules.map(mod => mod.getModuleName());
|
|
11
|
-
// Check if any modules exist
|
|
12
|
-
if (!moduleNames.length) {
|
|
13
|
-
const errorMsg = 'No modules found in the specified directory.';
|
|
14
|
-
if (log) {
|
|
15
|
-
log.error(errorMsg);
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
prompter.close();
|
|
20
|
-
throw errors.NOT_FOUND({}, errorMsg);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
// If a specific package was provided, validate it
|
|
24
|
-
if (argv.package) {
|
|
25
|
-
const packageName = argv.package;
|
|
26
|
-
if (log)
|
|
27
|
-
log.info(`Using specified package: ${packageName}`);
|
|
28
|
-
if (!moduleNames.includes(packageName)) {
|
|
29
|
-
const errorMsg = `Package '${packageName}' not found. Available packages: ${moduleNames.join(', ')}`;
|
|
30
|
-
if (log) {
|
|
31
|
-
log.error(errorMsg);
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
throw errors.NOT_FOUND({}, errorMsg);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return packageName;
|
|
39
|
-
}
|
|
40
|
-
// Interactive selection
|
|
41
|
-
const { package: selectedPackage } = await prompter.prompt(argv, [{
|
|
42
|
-
type: 'autocomplete',
|
|
43
|
-
name: 'package',
|
|
44
|
-
message: `Choose a package to ${operationName}`,
|
|
45
|
-
options: moduleNames,
|
|
46
|
-
required: true
|
|
47
|
-
}]);
|
|
48
|
-
if (log)
|
|
49
|
-
log.info(`Selected package: ${selectedPackage}`);
|
|
50
|
-
return selectedPackage;
|
|
51
|
-
}
|
package/package.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function readAndParsePackageJson(): any;
|
package/package.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.readAndParsePackageJson = readAndParsePackageJson;
|
|
4
|
-
const fs_1 = require("fs");
|
|
5
|
-
const path_1 = require("path");
|
|
6
|
-
// need to search due to the dist/ folder and src/, etc.
|
|
7
|
-
function findPackageJson(currentDir) {
|
|
8
|
-
const filePath = (0, path_1.join)(currentDir, 'package.json');
|
|
9
|
-
// Check if package.json exists in the current directory
|
|
10
|
-
if ((0, fs_1.existsSync)(filePath)) {
|
|
11
|
-
return filePath;
|
|
12
|
-
}
|
|
13
|
-
// Get the parent directory
|
|
14
|
-
const parentDir = (0, path_1.dirname)(currentDir);
|
|
15
|
-
// If reached the root directory, package.json is not found
|
|
16
|
-
if (parentDir === currentDir) {
|
|
17
|
-
throw new Error('package.json not found in any parent directory');
|
|
18
|
-
}
|
|
19
|
-
// Recursively look in the parent directory
|
|
20
|
-
return findPackageJson(parentDir);
|
|
21
|
-
}
|
|
22
|
-
function readAndParsePackageJson() {
|
|
23
|
-
// Start searching from the current directory
|
|
24
|
-
const pkgPath = findPackageJson(__dirname);
|
|
25
|
-
// Read and parse the package.json
|
|
26
|
-
const str = (0, fs_1.readFileSync)(pkgPath, 'utf8');
|
|
27
|
-
const pkg = JSON.parse(str);
|
|
28
|
-
return pkg;
|
|
29
|
-
}
|
package/utils/argv.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { ParsedArgs } from 'minimist';
|
|
2
|
-
export declare const extractFirst: (argv: Partial<ParsedArgs>) => {
|
|
3
|
-
first: string;
|
|
4
|
-
newArgv: {
|
|
5
|
-
_: string[];
|
|
6
|
-
"--"?: string[] | undefined;
|
|
7
|
-
};
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Common CLI argument validation and processing utilities
|
|
11
|
-
*/
|
|
12
|
-
export interface ValidatedArgv extends ParsedArgs {
|
|
13
|
-
cwd: string;
|
|
14
|
-
database?: string;
|
|
15
|
-
package?: string;
|
|
16
|
-
to?: string;
|
|
17
|
-
recursive?: boolean;
|
|
18
|
-
yes?: boolean;
|
|
19
|
-
tx?: boolean;
|
|
20
|
-
fast?: boolean;
|
|
21
|
-
logOnly?: boolean;
|
|
22
|
-
createdb?: boolean;
|
|
23
|
-
usePlan?: boolean;
|
|
24
|
-
cache?: boolean;
|
|
25
|
-
drop?: boolean;
|
|
26
|
-
all?: boolean;
|
|
27
|
-
summary?: boolean;
|
|
28
|
-
help?: boolean;
|
|
29
|
-
h?: boolean;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Validates and normalizes common CLI arguments
|
|
33
|
-
*/
|
|
34
|
-
export declare function validateCommonArgs(argv: Partial<ParsedArgs>): ValidatedArgv;
|
|
35
|
-
/**
|
|
36
|
-
* Checks if required flags are provided when certain conditions are met
|
|
37
|
-
*/
|
|
38
|
-
export declare function validateFlagDependencies(argv: ValidatedArgv): void;
|
|
39
|
-
/**
|
|
40
|
-
* Logs the effective CLI arguments for debugging
|
|
41
|
-
*/
|
|
42
|
-
export declare function logEffectiveArgs(argv: ValidatedArgv, commandName: string): void;
|
|
43
|
-
/**
|
|
44
|
-
* Constructs a deployment target string from package and to arguments
|
|
45
|
-
*/
|
|
46
|
-
export declare function constructTarget(argv: ValidatedArgv, packageName?: string): string | undefined;
|