@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.
Files changed (130) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +346 -153
  3. package/commands/{analyze.d.ts → codegen.d.ts} +2 -2
  4. package/commands/codegen.js +131 -0
  5. package/commands/explorer.js +94 -0
  6. package/commands/get-graphql-schema.js +73 -0
  7. package/commands/server.js +187 -0
  8. package/commands.d.ts +0 -1
  9. package/commands.js +42 -61
  10. package/esm/commands/codegen.js +126 -0
  11. package/esm/commands/explorer.js +92 -0
  12. package/esm/commands/get-graphql-schema.js +71 -0
  13. package/esm/commands/server.js +185 -0
  14. package/esm/commands.js +41 -59
  15. package/esm/index.js +16 -36
  16. package/esm/utils/display.js +26 -23
  17. package/esm/utils/index.js +3 -6
  18. package/index.d.ts +0 -22
  19. package/index.js +16 -72
  20. package/package.json +50 -25
  21. package/utils/display.d.ts +1 -1
  22. package/utils/display.js +26 -23
  23. package/utils/index.d.ts +3 -6
  24. package/utils/index.js +7 -20
  25. package/commands/add.d.ts +0 -7
  26. package/commands/add.js +0 -86
  27. package/commands/admin-users/add.d.ts +0 -4
  28. package/commands/admin-users/add.js +0 -89
  29. package/commands/admin-users/bootstrap.d.ts +0 -4
  30. package/commands/admin-users/bootstrap.js +0 -50
  31. package/commands/admin-users/remove.d.ts +0 -4
  32. package/commands/admin-users/remove.js +0 -82
  33. package/commands/admin-users.d.ts +0 -4
  34. package/commands/admin-users.js +0 -68
  35. package/commands/analyze.js +0 -21
  36. package/commands/clear.d.ts +0 -3
  37. package/commands/clear.js +0 -59
  38. package/commands/deploy.d.ts +0 -4
  39. package/commands/deploy.js +0 -146
  40. package/commands/docker.d.ts +0 -3
  41. package/commands/docker.js +0 -194
  42. package/commands/env.d.ts +0 -4
  43. package/commands/env.js +0 -124
  44. package/commands/export.js +0 -129
  45. package/commands/extension.js +0 -48
  46. package/commands/init/index.d.ts +0 -7
  47. package/commands/init/index.js +0 -47
  48. package/commands/init/module.d.ts +0 -4
  49. package/commands/init/module.js +0 -71
  50. package/commands/init/workspace.d.ts +0 -4
  51. package/commands/init/workspace.js +0 -52
  52. package/commands/install.d.ts +0 -4
  53. package/commands/install.js +0 -37
  54. package/commands/kill.js +0 -107
  55. package/commands/migrate/deps.d.ts +0 -4
  56. package/commands/migrate/deps.js +0 -186
  57. package/commands/migrate/init.d.ts +0 -4
  58. package/commands/migrate/init.js +0 -65
  59. package/commands/migrate/list.d.ts +0 -4
  60. package/commands/migrate/list.js +0 -85
  61. package/commands/migrate/status.d.ts +0 -4
  62. package/commands/migrate/status.js +0 -94
  63. package/commands/migrate.d.ts +0 -4
  64. package/commands/migrate.js +0 -69
  65. package/commands/package.d.ts +0 -3
  66. package/commands/package.js +0 -65
  67. package/commands/plan.d.ts +0 -3
  68. package/commands/plan.js +0 -62
  69. package/commands/remove.d.ts +0 -3
  70. package/commands/remove.js +0 -42
  71. package/commands/rename.d.ts +0 -4
  72. package/commands/rename.js +0 -35
  73. package/commands/revert.d.ts +0 -3
  74. package/commands/revert.js +0 -107
  75. package/commands/tag.d.ts +0 -6
  76. package/commands/tag.js +0 -168
  77. package/commands/verify.d.ts +0 -3
  78. package/commands/verify.js +0 -85
  79. package/dist/README.md +0 -412
  80. package/dist/package.json +0 -64
  81. package/esm/commands/add.js +0 -51
  82. package/esm/commands/admin-users/add.js +0 -87
  83. package/esm/commands/admin-users/bootstrap.js +0 -48
  84. package/esm/commands/admin-users/remove.js +0 -80
  85. package/esm/commands/admin-users.js +0 -63
  86. package/esm/commands/analyze.js +0 -16
  87. package/esm/commands/clear.js +0 -54
  88. package/esm/commands/deploy.js +0 -144
  89. package/esm/commands/docker.js +0 -192
  90. package/esm/commands/env.js +0 -122
  91. package/esm/commands/export.js +0 -127
  92. package/esm/commands/extension.js +0 -46
  93. package/esm/commands/init/index.js +0 -42
  94. package/esm/commands/init/module.js +0 -68
  95. package/esm/commands/init/workspace.js +0 -46
  96. package/esm/commands/install.js +0 -35
  97. package/esm/commands/kill.js +0 -105
  98. package/esm/commands/migrate/deps.js +0 -184
  99. package/esm/commands/migrate/init.js +0 -63
  100. package/esm/commands/migrate/list.js +0 -83
  101. package/esm/commands/migrate/status.js +0 -92
  102. package/esm/commands/migrate.js +0 -64
  103. package/esm/commands/package.js +0 -63
  104. package/esm/commands/plan.js +0 -60
  105. package/esm/commands/remove.js +0 -40
  106. package/esm/commands/rename.js +0 -30
  107. package/esm/commands/revert.js +0 -105
  108. package/esm/commands/tag.js +0 -133
  109. package/esm/commands/verify.js +0 -83
  110. package/esm/package.js +0 -26
  111. package/esm/utils/argv.js +0 -92
  112. package/esm/utils/cli-error.js +0 -48
  113. package/esm/utils/database.js +0 -78
  114. package/esm/utils/deployed-changes.js +0 -68
  115. package/esm/utils/module-utils.js +0 -51
  116. package/package.d.ts +0 -1
  117. package/package.js +0 -29
  118. package/utils/argv.d.ts +0 -46
  119. package/utils/argv.js +0 -100
  120. package/utils/cli-error.d.ts +0 -8
  121. package/utils/cli-error.js +0 -52
  122. package/utils/database.d.ts +0 -21
  123. package/utils/database.js +0 -83
  124. package/utils/deployed-changes.d.ts +0 -4
  125. package/utils/deployed-changes.js +0 -72
  126. package/utils/module-utils.d.ts +0 -8
  127. package/utils/module-utils.js +0 -54
  128. /package/commands/{export.d.ts → explorer.d.ts} +0 -0
  129. /package/commands/{extension.d.ts → get-graphql-schema.d.ts} +0 -0
  130. /package/commands/{kill.d.ts → server.d.ts} +0 -0
@@ -1,80 +0,0 @@
1
- import { LaunchQLInit } from '@launchql/core';
2
- import { Logger } from '@launchql/logger';
3
- import { getPgEnvOptions } from 'pg-env';
4
- const log = new Logger('admin-users-remove');
5
- const removeUsageText = `
6
- Admin Users Remove Command:
7
-
8
- constructive admin-users remove [OPTIONS]
9
-
10
- Remove database users and revoke their postgres roles.
11
-
12
- Options:
13
- --help, -h Show this help message
14
- --username <username> Username for the database user to remove
15
- --test Remove test users (app_user, app_admin)
16
- --cwd <directory> Working directory (default: current directory)
17
-
18
- Examples:
19
- constructive admin-users remove --username myuser
20
- constructive admin-users remove --test # Remove test users
21
- constructive admin-users remove # Will prompt for username
22
- `;
23
- export default async (argv, prompter, _options) => {
24
- // Show usage if explicitly requested
25
- if (argv.help || argv.h) {
26
- console.log(removeUsageText);
27
- process.exit(0);
28
- }
29
- const pgEnv = getPgEnvOptions();
30
- const isTest = argv.test;
31
- const init = new LaunchQLInit(pgEnv);
32
- try {
33
- if (isTest) {
34
- const { yes: confirmTest } = await prompter.prompt(argv, [
35
- {
36
- type: 'confirm',
37
- name: 'yes',
38
- message: 'Are you sure you want to remove test users (app_user, app_admin)?',
39
- default: false
40
- }
41
- ]);
42
- if (!confirmTest) {
43
- log.info('Operation cancelled.');
44
- return;
45
- }
46
- await init.removeDbRoles('app_user');
47
- await init.removeDbRoles('app_admin');
48
- log.success('Test users removed successfully.');
49
- }
50
- else {
51
- const prompts = [
52
- {
53
- type: 'text',
54
- name: 'username',
55
- message: 'Enter username for database user to remove:',
56
- validate: (input) => input && input.trim().length > 0
57
- }
58
- ];
59
- const { username } = await prompter.prompt(argv, prompts);
60
- const { yes } = await prompter.prompt(argv, [
61
- {
62
- type: 'confirm',
63
- name: 'yes',
64
- message: `Are you sure you want to remove database user "${username}"?`,
65
- default: false
66
- }
67
- ]);
68
- if (!yes) {
69
- log.info('Operation cancelled.');
70
- return;
71
- }
72
- await init.removeDbRoles(username);
73
- log.success(`Database user "${username}" removed successfully.`);
74
- }
75
- }
76
- finally {
77
- await init.close();
78
- }
79
- return argv;
80
- };
@@ -1,63 +0,0 @@
1
- import { extractFirst } from '../utils';
2
- import add from './admin-users/add';
3
- import bootstrap from './admin-users/bootstrap';
4
- import remove from './admin-users/remove';
5
- const subcommandMap = {
6
- add,
7
- bootstrap,
8
- remove
9
- };
10
- const adminUsersUsageText = `
11
- Admin Users Commands:
12
-
13
- constructive admin-users bootstrap Initialize postgres roles and permissions (must be run first)
14
- constructive admin-users add Add database users with roles
15
- constructive admin-users remove Remove database users and revoke roles
16
-
17
- Options:
18
- --help, -h Show this help message
19
- --cwd Working directory (default: current directory)
20
- `;
21
- export default async (argv, prompter, options) => {
22
- let { first: subcommand, newArgv } = extractFirst(argv);
23
- // Prompt if no subcommand provided
24
- if (!subcommand) {
25
- // Show usage if explicitly requested and no subcommand provided
26
- if (argv.help || argv.h) {
27
- console.log(adminUsersUsageText);
28
- process.exit(0);
29
- }
30
- const answer = await prompter.prompt(argv, [
31
- {
32
- type: 'autocomplete',
33
- name: 'subcommand',
34
- message: 'What admin users operation do you want to perform?',
35
- options: Object.keys(subcommandMap).map(cmd => ({
36
- name: cmd,
37
- value: cmd,
38
- description: getSubcommandDescription(cmd)
39
- }))
40
- }
41
- ]);
42
- subcommand = answer.subcommand;
43
- }
44
- if (subcommand === 'help') {
45
- console.log(adminUsersUsageText);
46
- process.exit(0);
47
- }
48
- const subcommandFn = subcommandMap[subcommand];
49
- if (!subcommandFn) {
50
- console.error(`Unknown admin-users subcommand: ${subcommand}`);
51
- console.log(adminUsersUsageText);
52
- process.exit(1);
53
- }
54
- await subcommandFn(newArgv, prompter, options);
55
- };
56
- function getSubcommandDescription(cmd) {
57
- const descriptions = {
58
- bootstrap: 'Initialize postgres roles and permissions (must be run first)',
59
- add: 'Add database users with roles',
60
- remove: 'Remove database users and revoke roles'
61
- };
62
- return descriptions[cmd] || '';
63
- }
@@ -1,16 +0,0 @@
1
- import { LaunchQLPackage } from '@launchql/core';
2
- import path from 'path';
3
- export default async (argv, _prompter) => {
4
- const cwd = argv.cwd || process.cwd();
5
- const proj = new LaunchQLPackage(path.resolve(cwd));
6
- const result = proj.analyzeModule();
7
- if (result.ok) {
8
- console.log(`OK ${result.name}`);
9
- return;
10
- }
11
- console.log(`NOT OK ${result.name}`);
12
- for (const issue of result.issues) {
13
- const loc = issue.file ? ` (${issue.file})` : '';
14
- console.log(`- [${issue.code}] ${issue.message}${loc}`);
15
- }
16
- };
@@ -1,54 +0,0 @@
1
- import { LaunchQLPackage } from '@launchql/core';
2
- import { parsePlanFile } from '@launchql/core';
3
- import { getEnvOptions } from '@launchql/env';
4
- import { Logger } from '@launchql/logger';
5
- import { errors } from '@launchql/types';
6
- import path from 'path';
7
- import { getPgEnvOptions } from 'pg-env';
8
- import { getTargetDatabase } from '../utils';
9
- const log = new Logger('clear');
10
- export default async (argv, prompter, _options) => {
11
- const database = await getTargetDatabase(argv, prompter, {
12
- message: 'Select database'
13
- });
14
- const questions = [
15
- {
16
- name: 'yes',
17
- type: 'confirm',
18
- message: 'Are you sure you want to clear ALL changes from the plan? This will remove all changes and their associated files.',
19
- required: true
20
- }
21
- ];
22
- let { yes, cwd } = await prompter.prompt(argv, questions);
23
- if (!yes) {
24
- log.info('Operation cancelled.');
25
- return;
26
- }
27
- log.debug(`Using current directory: ${cwd}`);
28
- const pkg = new LaunchQLPackage(cwd);
29
- if (!pkg.isInModule()) {
30
- throw new Error('Not in a LaunchQL module directory. Please run this command from within a module.');
31
- }
32
- const modulePath = pkg.getModulePath();
33
- if (!modulePath) {
34
- throw new Error('Could not resolve module path');
35
- }
36
- const planPath = path.join(modulePath, 'pgpm.plan');
37
- const result = parsePlanFile(planPath);
38
- if (result.errors.length > 0) {
39
- throw errors.PLAN_PARSE_ERROR({ planPath, errors: result.errors.map(e => e.message).join(', ') });
40
- }
41
- const plan = result.data;
42
- if (plan.changes.length === 0) {
43
- log.info('Plan is already empty - nothing to clear.');
44
- return;
45
- }
46
- const firstChange = plan.changes[0].name;
47
- log.info(`Found ${plan.changes.length} changes in plan. Clearing from first change: ${firstChange}`);
48
- const opts = getEnvOptions({
49
- pg: getPgEnvOptions({ database })
50
- });
51
- await pkg.removeFromPlan(firstChange);
52
- log.success(`✅ Successfully cleared all changes from the plan.`);
53
- return argv;
54
- };
@@ -1,144 +0,0 @@
1
- import { LaunchQLPackage } from '@launchql/core';
2
- import { getEnvOptions } from '@launchql/env';
3
- import { Logger } from '@launchql/logger';
4
- import { execSync } from 'child_process';
5
- import { getPgEnvOptions, getSpawnEnvWithPg, } from 'pg-env';
6
- import { getTargetDatabase } from '../utils';
7
- import { selectPackage } from '../utils/module-utils';
8
- const deployUsageText = `
9
- Deploy Command:
10
-
11
- constructive deploy [OPTIONS]
12
-
13
- Deploy database changes and migrations to target database.
14
-
15
- Options:
16
- --help, -h Show this help message
17
- --createdb Create database if it doesn't exist
18
- --recursive Deploy recursively through dependencies
19
- --package <name> Target specific package
20
- --to <target> Deploy to specific change or tag
21
- --tx Use transactions (default: true)
22
- --fast Use fast deployment strategy
23
- --logOnly Log-only mode, skip script execution
24
- --usePlan Use deployment plan
25
- --cache Enable caching
26
- --cwd <directory> Working directory (default: current directory)
27
-
28
- Examples:
29
- constructive deploy Deploy to selected database
30
- constructive deploy --createdb Deploy with database creation
31
- constructive deploy --package mypackage --to @v1.0.0 Deploy specific package to tag
32
- constructive deploy --fast --no-tx Fast deployment without transactions
33
- `;
34
- export default async (argv, prompter, _options) => {
35
- // Show usage if explicitly requested
36
- if (argv.help || argv.h) {
37
- console.log(deployUsageText);
38
- process.exit(0);
39
- }
40
- const pgEnv = getPgEnvOptions();
41
- const log = new Logger('cli');
42
- // Get target database
43
- let database;
44
- if (argv.createdb) {
45
- // Prompt for selection
46
- ({ database } = await prompter.prompt(argv, [
47
- {
48
- type: 'text',
49
- name: 'database',
50
- message: 'Database name',
51
- required: true
52
- }
53
- ]));
54
- }
55
- else {
56
- database = await getTargetDatabase(argv, prompter, {
57
- message: 'Select database'
58
- });
59
- }
60
- const questions = [
61
- {
62
- name: 'yes',
63
- type: 'confirm',
64
- message: 'Are you sure you want to proceed?',
65
- required: true
66
- },
67
- {
68
- name: 'recursive',
69
- type: 'confirm',
70
- message: 'Deploy recursively through dependencies?',
71
- useDefault: true,
72
- default: true,
73
- required: false
74
- },
75
- {
76
- name: 'tx',
77
- type: 'confirm',
78
- message: 'Use Transaction?',
79
- useDefault: true,
80
- default: true,
81
- required: false
82
- },
83
- {
84
- name: 'fast',
85
- type: 'confirm',
86
- message: 'Use Fast Deployment?',
87
- useDefault: true,
88
- default: false,
89
- required: false
90
- },
91
- {
92
- name: 'logOnly',
93
- type: 'confirm',
94
- message: 'Log-only mode (skip script execution)?',
95
- useDefault: true,
96
- default: false,
97
- required: false
98
- }
99
- ];
100
- let { yes, recursive, createdb, cwd, tx, fast, logOnly } = await prompter.prompt(argv, questions);
101
- if (!yes) {
102
- log.info('Operation cancelled.');
103
- return;
104
- }
105
- log.debug(`Using current directory: ${cwd}`);
106
- if (createdb) {
107
- log.info(`Creating database ${database}...`);
108
- execSync(`createdb ${database}`, {
109
- env: getSpawnEnvWithPg(pgEnv)
110
- });
111
- }
112
- let packageName;
113
- if (recursive) {
114
- packageName = await selectPackage(argv, prompter, cwd, 'deploy', log);
115
- }
116
- const cliOverrides = {
117
- pg: getPgEnvOptions({ database }),
118
- deployment: {
119
- useTx: tx !== false,
120
- fast: fast !== false,
121
- usePlan: argv.usePlan !== false,
122
- cache: argv.cache !== false,
123
- logOnly: argv.logOnly !== false,
124
- }
125
- };
126
- const opts = getEnvOptions(cliOverrides);
127
- const project = new LaunchQLPackage(cwd);
128
- let target;
129
- if (packageName && argv.to) {
130
- target = `${packageName}:${argv.to}`;
131
- }
132
- else if (packageName) {
133
- target = packageName;
134
- }
135
- else if (argv.package && argv.to) {
136
- target = `${argv.package}:${argv.to}`;
137
- }
138
- else if (argv.package) {
139
- target = argv.package;
140
- }
141
- await project.deploy(opts, target, recursive);
142
- log.success('Deployment complete.');
143
- return argv;
144
- };
@@ -1,192 +0,0 @@
1
- import { spawn } from 'child_process';
2
- import { cliExitWithError, extractFirst } from '../utils';
3
- const dockerUsageText = `
4
- Docker Command:
5
-
6
- constructive docker <subcommand> [OPTIONS]
7
-
8
- Manage PostgreSQL Docker containers for local development.
9
-
10
- Subcommands:
11
- start Start PostgreSQL container
12
- stop Stop PostgreSQL container
13
-
14
- Options:
15
- --help, -h Show this help message
16
- --name <name> Container name (default: postgres)
17
- --image <image> Docker image (default: pyramation/pgvector:13.3-alpine)
18
- --port <port> Host port mapping (default: 5432)
19
- --user <user> PostgreSQL user (default: postgres)
20
- --password <pass> PostgreSQL password (default: password)
21
- --recreate Remove and recreate container on start
22
-
23
- Examples:
24
- constructive docker start Start default PostgreSQL container
25
- constructive docker start --port 5433 Start on custom port
26
- constructive docker start --recreate Remove and recreate container
27
- constructive docker stop Stop PostgreSQL container
28
- `;
29
- function run(command, args, options = {}) {
30
- return new Promise((resolve, reject) => {
31
- const stdio = options.stdio || 'pipe';
32
- const child = spawn(command, args, { stdio });
33
- let stdout = '';
34
- let stderr = '';
35
- if (stdio === 'pipe') {
36
- child.stdout?.on('data', (data) => {
37
- stdout += data.toString();
38
- });
39
- child.stderr?.on('data', (data) => {
40
- stderr += data.toString();
41
- });
42
- }
43
- child.on('error', (error) => {
44
- reject(error);
45
- });
46
- child.on('close', (code) => {
47
- resolve({
48
- code: code ?? 0,
49
- stdout: stdout.trim(),
50
- stderr: stderr.trim()
51
- });
52
- });
53
- });
54
- }
55
- async function checkDockerAvailable() {
56
- try {
57
- const result = await run('docker', ['--version']);
58
- return result.code === 0;
59
- }
60
- catch (error) {
61
- return false;
62
- }
63
- }
64
- async function isContainerRunning(name) {
65
- try {
66
- const result = await run('docker', ['inspect', '-f', '{{.State.Running}}', name]);
67
- if (result.code === 0) {
68
- return result.stdout.trim() === 'true';
69
- }
70
- return null;
71
- }
72
- catch (error) {
73
- return null;
74
- }
75
- }
76
- async function containerExists(name) {
77
- try {
78
- const result = await run('docker', ['inspect', name]);
79
- return result.code === 0;
80
- }
81
- catch (error) {
82
- return false;
83
- }
84
- }
85
- async function startContainer(options) {
86
- const { name, image, port, user, password, recreate } = options;
87
- const dockerAvailable = await checkDockerAvailable();
88
- if (!dockerAvailable) {
89
- await cliExitWithError('Docker is not installed or not available in PATH. Please install Docker first.');
90
- return;
91
- }
92
- const exists = await containerExists(name);
93
- const running = await isContainerRunning(name);
94
- if (running === true) {
95
- console.log(`✅ Container "${name}" is already running`);
96
- return;
97
- }
98
- if (recreate && exists) {
99
- console.log(`🗑️ Removing existing container "${name}"...`);
100
- const removeResult = await run('docker', ['rm', '-f', name], { stdio: 'inherit' });
101
- if (removeResult.code !== 0) {
102
- await cliExitWithError(`Failed to remove container "${name}"`);
103
- return;
104
- }
105
- }
106
- if (exists && running === false) {
107
- console.log(`🔄 Starting existing container "${name}"...`);
108
- const startResult = await run('docker', ['start', name], { stdio: 'inherit' });
109
- if (startResult.code === 0) {
110
- console.log(`✅ Container "${name}" started successfully`);
111
- }
112
- else {
113
- await cliExitWithError(`Failed to start container "${name}"`);
114
- }
115
- return;
116
- }
117
- console.log(`🚀 Creating and starting new container "${name}"...`);
118
- const runArgs = [
119
- 'run',
120
- '-d',
121
- '--name', name,
122
- '-e', `POSTGRES_USER=${user}`,
123
- '-e', `POSTGRES_PASSWORD=${password}`,
124
- '-p', `${port}:5432`,
125
- image
126
- ];
127
- const runResult = await run('docker', runArgs, { stdio: 'inherit' });
128
- if (runResult.code === 0) {
129
- console.log(`✅ Container "${name}" created and started successfully`);
130
- console.log(`📌 PostgreSQL is available at localhost:${port}`);
131
- console.log(`👤 User: ${user}`);
132
- console.log(`🔑 Password: ${password}`);
133
- }
134
- else {
135
- await cliExitWithError(`Failed to create container "${name}". Check if port ${port} is already in use.`);
136
- }
137
- }
138
- async function stopContainer(name) {
139
- const dockerAvailable = await checkDockerAvailable();
140
- if (!dockerAvailable) {
141
- await cliExitWithError('Docker is not installed or not available in PATH. Please install Docker first.');
142
- return;
143
- }
144
- const exists = await containerExists(name);
145
- if (!exists) {
146
- console.log(`ℹ️ Container "${name}" not found`);
147
- return;
148
- }
149
- const running = await isContainerRunning(name);
150
- if (running === false) {
151
- console.log(`ℹ️ Container "${name}" is already stopped`);
152
- return;
153
- }
154
- console.log(`🛑 Stopping container "${name}"...`);
155
- const stopResult = await run('docker', ['stop', name], { stdio: 'inherit' });
156
- if (stopResult.code === 0) {
157
- console.log(`✅ Container "${name}" stopped successfully`);
158
- }
159
- else {
160
- await cliExitWithError(`Failed to stop container "${name}"`);
161
- }
162
- }
163
- export default async (argv, _prompter, _options) => {
164
- if (argv.help || argv.h) {
165
- console.log(dockerUsageText);
166
- process.exit(0);
167
- }
168
- const { first: subcommand, newArgv } = extractFirst(argv);
169
- const args = newArgv;
170
- if (!subcommand) {
171
- console.log(dockerUsageText);
172
- await cliExitWithError('No subcommand provided. Use "start" or "stop".');
173
- return;
174
- }
175
- const name = args.name || 'postgres';
176
- const image = args.image || 'pyramation/pgvector:13.3-alpine';
177
- const port = typeof args.port === 'number' ? args.port : 5432;
178
- const user = args.user || 'postgres';
179
- const password = args.password || 'password';
180
- const recreate = args.recreate === true;
181
- switch (subcommand) {
182
- case 'start':
183
- await startContainer({ name, image, port, user, password, recreate });
184
- break;
185
- case 'stop':
186
- await stopContainer(name);
187
- break;
188
- default:
189
- console.log(dockerUsageText);
190
- await cliExitWithError(`Unknown subcommand: ${subcommand}. Use "start" or "stop".`);
191
- }
192
- };
@@ -1,122 +0,0 @@
1
- import { spawn } from 'child_process';
2
- import { defaultPgConfig } from 'pg-env';
3
- const envUsageText = `
4
- Environment Command:
5
-
6
- constructive env [OPTIONS] [COMMAND...]
7
-
8
- Manage PostgreSQL environment variables with profile support.
9
-
10
- Profiles:
11
- (default) Use local Postgres development profile
12
- --supabase Use Supabase local development profile
13
-
14
- Modes:
15
- No command Print export statements for shell evaluation
16
- With command Execute command with environment variables applied
17
-
18
- Options:
19
- --help, -h Show this help message
20
- --supabase Use Supabase profile instead of default Postgres
21
-
22
- Examples:
23
- constructive env Print default Postgres env exports
24
- constructive env --supabase Print Supabase env exports
25
- eval "$(constructive env)" Load default Postgres env into shell
26
- eval "$(constructive env --supabase)" Load Supabase env into shell
27
- constructive env lql deploy --database db1 Run command with default Postgres env
28
- constructive env createdb mydb Run command with default Postgres env
29
- constructive env --supabase lql deploy --database db1 Run command with Supabase env
30
- constructive env --supabase createdb mydb Run command with Supabase env
31
- `;
32
- const SUPABASE_PROFILE = {
33
- host: 'localhost',
34
- port: 54322,
35
- user: 'supabase_admin',
36
- password: 'postgres',
37
- database: 'postgres'
38
- };
39
- const DEFAULT_PROFILE = {
40
- ...defaultPgConfig
41
- };
42
- function configToEnvVars(config) {
43
- return {
44
- PGHOST: config.host,
45
- PGPORT: String(config.port),
46
- PGUSER: config.user,
47
- PGPASSWORD: config.password,
48
- PGDATABASE: config.database
49
- };
50
- }
51
- function printExports(config) {
52
- const envVars = configToEnvVars(config);
53
- for (const [key, value] of Object.entries(envVars)) {
54
- const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
55
- console.log(`export ${key}="${escapedValue}"`);
56
- }
57
- }
58
- function executeCommand(config, command, args) {
59
- return new Promise((resolve, reject) => {
60
- const envVars = configToEnvVars(config);
61
- const env = {
62
- ...process.env,
63
- ...envVars
64
- };
65
- const child = spawn(command, args, {
66
- env,
67
- stdio: 'inherit',
68
- shell: false
69
- });
70
- child.on('error', (error) => {
71
- reject(error);
72
- });
73
- child.on('close', (code) => {
74
- resolve(code ?? 0);
75
- });
76
- });
77
- }
78
- export default async (argv, _prompter) => {
79
- if (argv.help || argv.h) {
80
- console.log(envUsageText);
81
- process.exit(0);
82
- }
83
- const useSupabase = argv.supabase === true || typeof argv.supabase === 'string';
84
- const profile = useSupabase ? SUPABASE_PROFILE : DEFAULT_PROFILE;
85
- const rawArgs = process.argv.slice(2);
86
- let envIndex = rawArgs.findIndex(arg => arg === 'env');
87
- if (envIndex === -1) {
88
- envIndex = 0;
89
- }
90
- const argsAfterEnv = rawArgs.slice(envIndex + 1);
91
- const supabaseIndex = argsAfterEnv.findIndex(arg => arg === '--supabase');
92
- let commandArgs;
93
- if (supabaseIndex !== -1) {
94
- commandArgs = argsAfterEnv.slice(supabaseIndex + 1);
95
- }
96
- else {
97
- commandArgs = argsAfterEnv;
98
- }
99
- commandArgs = commandArgs.filter(arg => arg !== '--cwd' && !arg.startsWith('--cwd='));
100
- const cwdIndex = commandArgs.findIndex(arg => arg === '--cwd');
101
- if (cwdIndex !== -1 && cwdIndex + 1 < commandArgs.length) {
102
- commandArgs.splice(cwdIndex, 2);
103
- }
104
- if (commandArgs.length === 0) {
105
- printExports(profile);
106
- return;
107
- }
108
- const [command, ...args] = commandArgs;
109
- try {
110
- const exitCode = await executeCommand(profile, command, args);
111
- process.exit(exitCode);
112
- }
113
- catch (error) {
114
- if (error instanceof Error) {
115
- console.error(`Error executing command: ${error.message}`);
116
- }
117
- else {
118
- console.error(`Error executing command: ${String(error)}`);
119
- }
120
- process.exit(1);
121
- }
122
- };