pgpm 0.0.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 (121) hide show
  1. package/README.md +416 -0
  2. package/commands/add.d.ts +7 -0
  3. package/commands/add.js +86 -0
  4. package/commands/admin-users/add.d.ts +4 -0
  5. package/commands/admin-users/add.js +89 -0
  6. package/commands/admin-users/bootstrap.d.ts +4 -0
  7. package/commands/admin-users/bootstrap.js +50 -0
  8. package/commands/admin-users/remove.d.ts +4 -0
  9. package/commands/admin-users/remove.js +82 -0
  10. package/commands/admin-users.d.ts +4 -0
  11. package/commands/admin-users.js +68 -0
  12. package/commands/analyze.d.ts +4 -0
  13. package/commands/analyze.js +21 -0
  14. package/commands/clear.d.ts +3 -0
  15. package/commands/clear.js +59 -0
  16. package/commands/deploy.d.ts +4 -0
  17. package/commands/deploy.js +146 -0
  18. package/commands/explorer.d.ts +3 -0
  19. package/commands/explorer.js +94 -0
  20. package/commands/export.d.ts +3 -0
  21. package/commands/export.js +129 -0
  22. package/commands/extension.d.ts +4 -0
  23. package/commands/extension.js +48 -0
  24. package/commands/init/index.d.ts +7 -0
  25. package/commands/init/index.js +47 -0
  26. package/commands/init/module.d.ts +4 -0
  27. package/commands/init/module.js +71 -0
  28. package/commands/init/workspace.d.ts +4 -0
  29. package/commands/init/workspace.js +52 -0
  30. package/commands/install.d.ts +4 -0
  31. package/commands/install.js +37 -0
  32. package/commands/kill.d.ts +3 -0
  33. package/commands/kill.js +107 -0
  34. package/commands/migrate/deps.d.ts +4 -0
  35. package/commands/migrate/deps.js +186 -0
  36. package/commands/migrate/init.d.ts +4 -0
  37. package/commands/migrate/init.js +65 -0
  38. package/commands/migrate/list.d.ts +4 -0
  39. package/commands/migrate/list.js +85 -0
  40. package/commands/migrate/status.d.ts +4 -0
  41. package/commands/migrate/status.js +94 -0
  42. package/commands/migrate.d.ts +4 -0
  43. package/commands/migrate.js +69 -0
  44. package/commands/package.d.ts +3 -0
  45. package/commands/package.js +65 -0
  46. package/commands/plan.d.ts +3 -0
  47. package/commands/plan.js +62 -0
  48. package/commands/remove.d.ts +3 -0
  49. package/commands/remove.js +42 -0
  50. package/commands/rename.d.ts +4 -0
  51. package/commands/rename.js +35 -0
  52. package/commands/revert.d.ts +3 -0
  53. package/commands/revert.js +107 -0
  54. package/commands/server.d.ts +3 -0
  55. package/commands/server.js +187 -0
  56. package/commands/tag.d.ts +6 -0
  57. package/commands/tag.js +168 -0
  58. package/commands/verify.d.ts +3 -0
  59. package/commands/verify.js +85 -0
  60. package/commands.d.ts +5 -0
  61. package/commands.js +118 -0
  62. package/dist/README.md +416 -0
  63. package/dist/package.json +77 -0
  64. package/esm/commands/add.js +51 -0
  65. package/esm/commands/admin-users/add.js +87 -0
  66. package/esm/commands/admin-users/bootstrap.js +48 -0
  67. package/esm/commands/admin-users/remove.js +80 -0
  68. package/esm/commands/admin-users.js +63 -0
  69. package/esm/commands/analyze.js +16 -0
  70. package/esm/commands/clear.js +54 -0
  71. package/esm/commands/deploy.js +144 -0
  72. package/esm/commands/explorer.js +92 -0
  73. package/esm/commands/export.js +127 -0
  74. package/esm/commands/extension.js +46 -0
  75. package/esm/commands/init/index.js +42 -0
  76. package/esm/commands/init/module.js +68 -0
  77. package/esm/commands/init/workspace.js +46 -0
  78. package/esm/commands/install.js +35 -0
  79. package/esm/commands/kill.js +105 -0
  80. package/esm/commands/migrate/deps.js +184 -0
  81. package/esm/commands/migrate/init.js +63 -0
  82. package/esm/commands/migrate/list.js +83 -0
  83. package/esm/commands/migrate/status.js +92 -0
  84. package/esm/commands/migrate.js +64 -0
  85. package/esm/commands/package.js +63 -0
  86. package/esm/commands/plan.js +60 -0
  87. package/esm/commands/remove.js +40 -0
  88. package/esm/commands/rename.js +30 -0
  89. package/esm/commands/revert.js +105 -0
  90. package/esm/commands/server.js +185 -0
  91. package/esm/commands/tag.js +133 -0
  92. package/esm/commands/verify.js +83 -0
  93. package/esm/commands.js +111 -0
  94. package/esm/index.js +20 -0
  95. package/esm/package.js +26 -0
  96. package/esm/utils/argv.js +92 -0
  97. package/esm/utils/cli-error.js +48 -0
  98. package/esm/utils/database.js +78 -0
  99. package/esm/utils/deployed-changes.js +68 -0
  100. package/esm/utils/display.js +58 -0
  101. package/esm/utils/index.js +3 -0
  102. package/esm/utils/module-utils.js +51 -0
  103. package/index.d.ts +3 -0
  104. package/index.js +23 -0
  105. package/package.d.ts +1 -0
  106. package/package.js +29 -0
  107. package/package.json +77 -0
  108. package/utils/argv.d.ts +46 -0
  109. package/utils/argv.js +100 -0
  110. package/utils/cli-error.d.ts +8 -0
  111. package/utils/cli-error.js +52 -0
  112. package/utils/database.d.ts +21 -0
  113. package/utils/database.js +83 -0
  114. package/utils/deployed-changes.d.ts +4 -0
  115. package/utils/deployed-changes.js +72 -0
  116. package/utils/display.d.ts +3 -0
  117. package/utils/display.js +66 -0
  118. package/utils/index.d.ts +3 -0
  119. package/utils/index.js +19 -0
  120. package/utils/module-utils.d.ts +8 -0
  121. package/utils/module-utils.js +54 -0
@@ -0,0 +1,80 @@
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
+ LaunchQL Admin Users Remove Command:
7
+
8
+ lql admin-users remove [OPTIONS]
9
+
10
+ Remove database users and revoke their LaunchQL 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
+ lql admin-users remove --username myuser
20
+ lql admin-users remove --test # Remove test users
21
+ lql 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 LaunchQL 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
+ };
@@ -0,0 +1,63 @@
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
+ LaunchQL Admin Users Commands:
12
+
13
+ lql admin-users bootstrap Initialize LaunchQL roles and permissions (must be run first)
14
+ lql admin-users add Add database users with roles
15
+ lql 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 LaunchQL 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
+ }
@@ -0,0 +1,16 @@
1
+ import path from 'path';
2
+ import { LaunchQLPackage } from '@launchql/core';
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
+ };
@@ -0,0 +1,54 @@
1
+ import { LaunchQLPackage } from '@launchql/core';
2
+ import { Logger } from '@launchql/logger';
3
+ import { getEnvOptions } from '@launchql/env';
4
+ import { getPgEnvOptions } from 'pg-env';
5
+ import { parsePlanFile } from '@launchql/core';
6
+ import { errors } from '@launchql/types';
7
+ import path from 'path';
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, 'launchql.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
+ };
@@ -0,0 +1,144 @@
1
+ import { LaunchQLPackage } from '@launchql/core';
2
+ import { Logger } from '@launchql/logger';
3
+ import { getEnvOptions } from '@launchql/env';
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
+ LaunchQL Deploy Command:
10
+
11
+ lql 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
+ lql deploy Deploy to selected database
30
+ lql deploy --createdb Deploy with database creation
31
+ lql deploy --package mypackage --to @v1.0.0 Deploy specific package to tag
32
+ lql 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
+ };
@@ -0,0 +1,92 @@
1
+ import { LaunchQLExplorer as explorer } from '@launchql/explorer';
2
+ import { Logger } from '@launchql/logger';
3
+ import { getEnvOptions } from '@launchql/env';
4
+ const log = new Logger('explorer');
5
+ const explorerUsageText = `
6
+ LaunchQL Explorer Command:
7
+
8
+ lql explorer [OPTIONS]
9
+
10
+ Launch GraphiQL explorer interface.
11
+
12
+ Options:
13
+ --help, -h Show this help message
14
+ --port <number> Server port (default: 5555)
15
+ --origin <url> CORS origin URL (default: http://localhost:3000)
16
+ --simpleInflection Use simple inflection (default: true)
17
+ --oppositeBaseNames Use opposite base names (default: false)
18
+ --postgis Enable PostGIS extension (default: true)
19
+ --cwd <directory> Working directory (default: current directory)
20
+
21
+ Examples:
22
+ lql explorer Launch explorer with defaults
23
+ lql explorer --origin http://localhost:4000 Launch explorer with custom origin
24
+ `;
25
+ const questions = [
26
+ {
27
+ name: 'simpleInflection',
28
+ message: 'Use simple inflection?',
29
+ type: 'confirm',
30
+ required: false,
31
+ default: true,
32
+ useDefault: true
33
+ },
34
+ {
35
+ name: 'oppositeBaseNames',
36
+ message: 'Use opposite base names?',
37
+ type: 'confirm',
38
+ required: false,
39
+ default: false,
40
+ useDefault: true
41
+ },
42
+ {
43
+ name: 'postgis',
44
+ message: 'Enable PostGIS extension?',
45
+ type: 'confirm',
46
+ required: false,
47
+ default: true,
48
+ useDefault: true
49
+ },
50
+ {
51
+ name: 'port',
52
+ message: 'Development server port',
53
+ type: 'number',
54
+ required: false,
55
+ default: 5555,
56
+ useDefault: true
57
+ },
58
+ {
59
+ name: 'origin',
60
+ message: 'CORS origin URL',
61
+ type: 'text',
62
+ required: false,
63
+ default: 'http://localhost:3000',
64
+ useDefault: true
65
+ }
66
+ ];
67
+ export default async (argv, prompter, _options) => {
68
+ // Show usage if explicitly requested
69
+ if (argv.help || argv.h) {
70
+ console.log(explorerUsageText);
71
+ process.exit(0);
72
+ }
73
+ log.info('🔧 LaunchQL Explorer Configuration:\n');
74
+ const { oppositeBaseNames, origin, port, postgis, simpleInflection } = await prompter.prompt(argv, questions);
75
+ const options = getEnvOptions({
76
+ features: {
77
+ oppositeBaseNames,
78
+ simpleInflection,
79
+ postgis
80
+ },
81
+ server: {
82
+ origin,
83
+ port
84
+ }
85
+ });
86
+ log.success('✅ Selected Configuration:');
87
+ for (const [key, value] of Object.entries(options)) {
88
+ log.debug(`${key}: ${JSON.stringify(value)}`);
89
+ }
90
+ log.success('🚀 Launching Explorer...\n');
91
+ explorer(options);
92
+ };
@@ -0,0 +1,127 @@
1
+ import { exportMigrations, LaunchQLPackage } from '@launchql/core';
2
+ import { getGitConfigInfo } from '@launchql/types';
3
+ import { getEnvOptions } from '@launchql/env';
4
+ import { resolve } from 'path';
5
+ import { getPgPool } from 'pg-cache';
6
+ const exportUsageText = `
7
+ LaunchQL Export Command:
8
+
9
+ lql export [OPTIONS]
10
+
11
+ Export database migrations from existing databases.
12
+
13
+ Options:
14
+ --help, -h Show this help message
15
+ --author <name> Project author (default: from git config)
16
+ --extensionName <name> Extension name
17
+ --metaExtensionName <name> Meta extension name (default: svc)
18
+ --cwd <directory> Working directory (default: current directory)
19
+
20
+ Examples:
21
+ lql export Export migrations from selected database
22
+ `;
23
+ export default async (argv, prompter, _options) => {
24
+ // Show usage if explicitly requested
25
+ if (argv.help || argv.h) {
26
+ console.log(exportUsageText);
27
+ process.exit(0);
28
+ }
29
+ const { email, username } = getGitConfigInfo();
30
+ const cwd = argv.cwd ?? process.cwd();
31
+ const project = new LaunchQLPackage(cwd);
32
+ project.ensureWorkspace();
33
+ project.resetCwd(project.workspacePath);
34
+ const options = getEnvOptions();
35
+ const db = await getPgPool({
36
+ database: 'postgres'
37
+ });
38
+ const databasesResult = await db.query(`
39
+ SELECT datname FROM pg_catalog.pg_database
40
+ WHERE datistemplate = FALSE AND datname NOT IN ('postgres')
41
+ AND datname !~ '^pg_';
42
+ `);
43
+ let databases;
44
+ ({ databases } = await prompter.prompt(argv, [
45
+ {
46
+ type: 'checkbox',
47
+ name: 'databases',
48
+ message: 'Select a database',
49
+ options: databasesResult.rows.map(row => row.datname),
50
+ required: true
51
+ }
52
+ ]));
53
+ const dbname = databases.filter(d => d.selected).map(d => d.value)[0];
54
+ const selectedDb = await getPgPool({
55
+ database: dbname
56
+ });
57
+ const dbsResult = await selectedDb.query(`
58
+ SELECT id, name FROM collections_public.database;
59
+ `);
60
+ let database_ids;
61
+ ({ database_ids } = await prompter.prompt({}, [
62
+ {
63
+ type: 'checkbox',
64
+ name: 'database_ids',
65
+ message: 'Select database_id(s)',
66
+ options: dbsResult.rows.map(db => db.name),
67
+ required: true
68
+ }
69
+ ]));
70
+ const dbInfo = {
71
+ dbname,
72
+ database_ids: database_ids.map(did => dbsResult.rows.find(db => db.name === did.name).id)
73
+ };
74
+ const { author, extensionName, metaExtensionName } = await prompter.prompt(argv, [
75
+ {
76
+ type: 'text',
77
+ name: 'author',
78
+ message: 'Project author',
79
+ default: `${username} <${email}>`,
80
+ required: true
81
+ },
82
+ {
83
+ type: 'text',
84
+ name: 'extensionName',
85
+ message: 'Extension name',
86
+ default: dbInfo.database_ids[0],
87
+ required: true
88
+ },
89
+ {
90
+ type: 'text',
91
+ name: 'metaExtensionName',
92
+ message: 'Meta extension name',
93
+ default: 'svc',
94
+ required: true
95
+ }
96
+ ]);
97
+ const schemasResult = await selectedDb.query(`SELECT * FROM collections_public.schema WHERE database_id = $1`, [dbInfo.database_ids[0]]);
98
+ const { schema_names } = await prompter.prompt({}, [
99
+ {
100
+ type: 'checkbox',
101
+ name: 'schema_names',
102
+ message: 'Select schema_name(s)',
103
+ options: schemasResult.rows.map(s => s.schema_name),
104
+ default: schemasResult.rows.map(s => s.schema_name),
105
+ required: true
106
+ }
107
+ ]);
108
+ const outdir = resolve(project.workspacePath, 'packages/');
109
+ await exportMigrations({
110
+ project,
111
+ options,
112
+ dbInfo,
113
+ author,
114
+ schema_names,
115
+ outdir,
116
+ extensionName,
117
+ metaExtensionName
118
+ });
119
+ console.log(`
120
+
121
+ |||
122
+ (o o)
123
+ ooO--(_)--Ooo-
124
+
125
+ ✨ finished!
126
+ `);
127
+ };
@@ -0,0 +1,46 @@
1
+ import { LaunchQLPackage } from '@launchql/core';
2
+ const extensionUsageText = `
3
+ LaunchQL Extension Command:
4
+
5
+ lql extension [OPTIONS]
6
+
7
+ Manage module dependencies.
8
+
9
+ Options:
10
+ --help, -h Show this help message
11
+ --cwd <directory> Working directory (default: current directory)
12
+
13
+ Examples:
14
+ lql extension Manage dependencies for current module
15
+ `;
16
+ export default async (argv, prompter, _options) => {
17
+ // Show usage if explicitly requested
18
+ if (argv.help || argv.h) {
19
+ console.log(extensionUsageText);
20
+ process.exit(0);
21
+ }
22
+ const { cwd = process.cwd() } = argv;
23
+ const project = new LaunchQLPackage(cwd);
24
+ if (!project.isInModule()) {
25
+ throw new Error('You must run this command inside a LaunchQL module.');
26
+ }
27
+ const info = project.getModuleInfo();
28
+ const installed = project.getRequiredModules();
29
+ const available = project.getAvailableModules();
30
+ const filtered = available.filter(name => name !== info.extname);
31
+ const questions = [
32
+ {
33
+ name: 'extensions',
34
+ message: 'Which modules does this one depend on?',
35
+ type: 'checkbox',
36
+ allowCustomOptions: true,
37
+ options: filtered,
38
+ default: installed
39
+ }
40
+ ];
41
+ const answers = await prompter.prompt(argv, questions);
42
+ const selected = answers.extensions
43
+ .filter(opt => opt.selected)
44
+ .map(opt => opt.name);
45
+ project.setModuleDependencies(selected);
46
+ };
@@ -0,0 +1,42 @@
1
+ import runModuleSetup from './module';
2
+ import runWorkspaceSetup from './workspace';
3
+ const initUsageText = `
4
+ LaunchQL Init Command:
5
+
6
+ lql init [OPTIONS]
7
+
8
+ Initialize LaunchQL workspace or module.
9
+
10
+ Options:
11
+ --help, -h Show this help message
12
+ --workspace Initialize workspace instead of module
13
+ --cwd <directory> Working directory (default: current directory)
14
+ --repo <repo> Use templates from GitHub repository (e.g., owner/repo)
15
+ --template-path <path> Use templates from local path
16
+ --from-branch <branch> Specify branch when using --repo (default: main)
17
+
18
+ Examples:
19
+ lql init Initialize new module in existing workspace
20
+ lql init --workspace Initialize new workspace
21
+ lql init --repo owner/repo Use templates from GitHub repository
22
+ lql init --template-path ./custom-templates Use templates from local path
23
+ lql init --repo owner/repo --from-branch develop Use specific branch
24
+ `;
25
+ export default async (argv, prompter, _options) => {
26
+ // Show usage if explicitly requested
27
+ if (argv.help || argv.h) {
28
+ console.log(initUsageText);
29
+ process.exit(0);
30
+ }
31
+ return handlePromptFlow(argv, prompter);
32
+ };
33
+ async function handlePromptFlow(argv, prompter) {
34
+ const { workspace } = argv;
35
+ switch (workspace) {
36
+ case true:
37
+ return runWorkspaceSetup(argv, prompter);
38
+ case false:
39
+ default:
40
+ return runModuleSetup(argv, prompter);
41
+ }
42
+ }