@launchframe/cli 1.0.1 → 1.0.3
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/package.json
CHANGED
|
@@ -5,7 +5,7 @@ const inquirer = require('inquirer');
|
|
|
5
5
|
const { spawnSync } = require('child_process');
|
|
6
6
|
const { requireProject, getProjectConfig } = require('../utils/project-helpers');
|
|
7
7
|
|
|
8
|
-
async function databaseConsole({ remote = false, query = null } = {}) {
|
|
8
|
+
async function databaseConsole({ remote = false, query = null, skipPermission = false } = {}) {
|
|
9
9
|
requireProject();
|
|
10
10
|
|
|
11
11
|
const infrastructurePath = path.join(process.cwd(), 'infrastructure');
|
|
@@ -31,12 +31,15 @@ async function databaseConsole({ remote = false, query = null } = {}) {
|
|
|
31
31
|
if (query) {
|
|
32
32
|
// Non-interactive query mode — pipe SQL via stdin, skip confirmation
|
|
33
33
|
const remoteCmd = `cd ${vpsAppFolder}/infrastructure && docker compose -f docker-compose.yml -f docker-compose.prod.yml exec -T database sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'`;
|
|
34
|
-
const result = spawnSync('ssh', [`${vpsUser}@${vpsHost}`, remoteCmd], {
|
|
34
|
+
const result = spawnSync('ssh', ['-T', `${vpsUser}@${vpsHost}`, remoteCmd], {
|
|
35
35
|
input: query,
|
|
36
|
-
stdio: ['pipe', '
|
|
36
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
37
37
|
encoding: 'utf8'
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
41
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
42
|
+
|
|
40
43
|
if (result.status !== 0) {
|
|
41
44
|
console.error(chalk.red('\n❌ Could not execute query on the production database.'));
|
|
42
45
|
console.log(chalk.gray('Check that the VPS is reachable and services are running.\n'));
|
|
@@ -46,22 +49,24 @@ async function databaseConsole({ remote = false, query = null } = {}) {
|
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
// 2. Warn before connecting to production (interactive mode only)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
if (!skipPermission) {
|
|
53
|
+
console.log(chalk.yellow.bold('\n⚠️ You are about to connect to the PRODUCTION database.\n'));
|
|
54
|
+
console.log(chalk.gray(` Host: ${vpsHost}`));
|
|
55
|
+
console.log(chalk.gray(` Folder: ${vpsAppFolder}\n`));
|
|
56
|
+
|
|
57
|
+
const { confirmed } = await inquirer.prompt([
|
|
58
|
+
{
|
|
59
|
+
type: 'confirm',
|
|
60
|
+
name: 'confirmed',
|
|
61
|
+
message: 'Are you sure you want to open a console to the production database?',
|
|
62
|
+
default: false
|
|
63
|
+
}
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
if (!confirmed) {
|
|
67
|
+
console.log(chalk.gray('\nAborted.\n'));
|
|
68
|
+
process.exit(0);
|
|
59
69
|
}
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
if (!confirmed) {
|
|
63
|
-
console.log(chalk.gray('\nAborted.\n'));
|
|
64
|
-
process.exit(0);
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
console.log(chalk.blue.bold('\n🔌 Connecting to production database...\n'));
|
|
@@ -89,10 +94,13 @@ async function databaseConsole({ remote = false, query = null } = {}) {
|
|
|
89
94
|
const result = spawnSync('docker', psqlCmd, {
|
|
90
95
|
cwd: infrastructurePath,
|
|
91
96
|
input: query,
|
|
92
|
-
stdio: ['pipe', '
|
|
97
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
93
98
|
encoding: 'utf8'
|
|
94
99
|
});
|
|
95
100
|
|
|
101
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
102
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
103
|
+
|
|
96
104
|
if (result.status !== 0) {
|
|
97
105
|
console.error(chalk.red('\n❌ Could not execute query on the local database container.'));
|
|
98
106
|
console.log(chalk.gray('Make sure services are running:'));
|
package/src/index.js
CHANGED
|
@@ -63,14 +63,22 @@ function parseFlags(args) {
|
|
|
63
63
|
for (let i = 1; i < args.length; i++) {
|
|
64
64
|
const arg = args[i];
|
|
65
65
|
if (arg.startsWith('--')) {
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
const withoutDashes = arg.substring(2);
|
|
67
|
+
const eqIndex = withoutDashes.indexOf('=');
|
|
68
|
+
if (eqIndex !== -1) {
|
|
69
|
+
// --key=value format
|
|
70
|
+
const flagName = withoutDashes.substring(0, eqIndex);
|
|
71
|
+
flags[flagName] = withoutDashes.substring(eqIndex + 1) || true;
|
|
72
72
|
} else {
|
|
73
|
-
|
|
73
|
+
const flagName = withoutDashes;
|
|
74
|
+
const nextArg = args[i + 1];
|
|
75
|
+
// Check if next arg is a value (not a flag)
|
|
76
|
+
if (nextArg && !nextArg.startsWith('-')) {
|
|
77
|
+
flags[flagName] = nextArg;
|
|
78
|
+
i++; // Skip next arg since we consumed it
|
|
79
|
+
} else {
|
|
80
|
+
flags[flagName] = true; // Boolean flag
|
|
81
|
+
}
|
|
74
82
|
}
|
|
75
83
|
} else if (arg.startsWith('-') && arg.length === 2) {
|
|
76
84
|
const flagName = arg.substring(1);
|
|
@@ -171,7 +179,7 @@ async function main() {
|
|
|
171
179
|
await migrateRevert();
|
|
172
180
|
break;
|
|
173
181
|
case 'database:console':
|
|
174
|
-
await databaseConsole({ remote: flags.remote, query: flags.query });
|
|
182
|
+
await databaseConsole({ remote: flags.remote, query: flags.query, skipPermission: !!flags['skip-permission'] });
|
|
175
183
|
break;
|
|
176
184
|
case 'doctor':
|
|
177
185
|
await doctor();
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
// Module configuration - defines files, sections, and dependencies for each module
|
|
2
2
|
const MODULE_CONFIG = {
|
|
3
|
+
ai: {
|
|
4
|
+
backend: {
|
|
5
|
+
files: ['src/modules/domain/ai'],
|
|
6
|
+
sections: {
|
|
7
|
+
'src/modules/app/app.module.ts': ['EXTRA_MODULE_IMPORT', 'EXTRA_MODULE'],
|
|
8
|
+
},
|
|
9
|
+
dependencies: {
|
|
10
|
+
'@anthropic-ai/sdk': '^0.39.0',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
infrastructure: {
|
|
14
|
+
sections: {
|
|
15
|
+
'.env.example': ['EXTRA_ENV_VARS'],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
3
19
|
blog: {
|
|
4
20
|
website: {
|
|
5
21
|
files: [
|
|
@@ -6,6 +6,13 @@ const MODULE_REGISTRY = {
|
|
|
6
6
|
description: 'Markdown-based blog using local .md files with YAML front-matter — no database required',
|
|
7
7
|
services: ['website'],
|
|
8
8
|
version: '1.0.0'
|
|
9
|
+
},
|
|
10
|
+
ai: {
|
|
11
|
+
name: 'ai',
|
|
12
|
+
displayName: 'AI',
|
|
13
|
+
description: 'LLM integration via Anthropic SDK — call generateResponse() from LLMService in any backend service',
|
|
14
|
+
services: ['backend'],
|
|
15
|
+
version: '1.0.0'
|
|
9
16
|
}
|
|
10
17
|
};
|
|
11
18
|
|