@launchframe/cli 1.0.0-beta.26 → 1.0.0-beta.27
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 +2 -1
- package/src/commands/database-console.js +84 -0
- package/src/commands/help.js +3 -0
- package/src/index.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@launchframe/cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.27",
|
|
4
4
|
"description": "Production-ready B2B SaaS boilerplate with subscriptions, credits, and multi-tenancy",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"chalk": "^4.1.2",
|
|
44
|
+
"dotenv": "^17.3.1",
|
|
44
45
|
"fs-extra": "^11.1.1",
|
|
45
46
|
"inquirer": "^8.2.5"
|
|
46
47
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
const { spawnSync } = require('child_process');
|
|
6
|
+
const { requireProject, getProjectConfig } = require('../utils/project-helpers');
|
|
7
|
+
|
|
8
|
+
async function databaseConsole({ remote = false } = {}) {
|
|
9
|
+
requireProject();
|
|
10
|
+
|
|
11
|
+
const infrastructurePath = path.join(process.cwd(), 'infrastructure');
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(infrastructurePath)) {
|
|
14
|
+
console.error(chalk.red('\n❌ Error: infrastructure/ directory not found'));
|
|
15
|
+
console.log(chalk.gray('Make sure you are in the root of your LaunchFrame project.\n'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (remote) {
|
|
20
|
+
// 1. Check deployment is configured
|
|
21
|
+
const config = getProjectConfig();
|
|
22
|
+
|
|
23
|
+
if (!config.deployConfigured || !config.deployment) {
|
|
24
|
+
console.error(chalk.red('\n❌ Deployment is not configured.'));
|
|
25
|
+
console.log(chalk.gray('Run deploy:configure first.\n'));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { vpsUser, vpsHost, vpsAppFolder } = config.deployment;
|
|
30
|
+
|
|
31
|
+
// 2. Warn before connecting to production
|
|
32
|
+
console.log(chalk.yellow.bold('\n⚠️ You are about to connect to the PRODUCTION database.\n'));
|
|
33
|
+
console.log(chalk.gray(` Host: ${vpsHost}`));
|
|
34
|
+
console.log(chalk.gray(` Folder: ${vpsAppFolder}\n`));
|
|
35
|
+
|
|
36
|
+
const { confirmed } = await inquirer.prompt([
|
|
37
|
+
{
|
|
38
|
+
type: 'confirm',
|
|
39
|
+
name: 'confirmed',
|
|
40
|
+
message: 'Are you sure you want to open a console to the production database?',
|
|
41
|
+
default: false
|
|
42
|
+
}
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
if (!confirmed) {
|
|
46
|
+
console.log(chalk.gray('\nAborted.\n'));
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
console.log(chalk.blue.bold('\n🔌 Connecting to production database...\n'));
|
|
51
|
+
|
|
52
|
+
// 3. Let the shell inside the container expand $POSTGRES_USER / $POSTGRES_DB.
|
|
53
|
+
// Pass the remote command as a single ssh argument (spawnSync array form)
|
|
54
|
+
// so the local shell never touches it.
|
|
55
|
+
const remoteCmd = `cd ${vpsAppFolder}/infrastructure && docker compose -f docker-compose.yml -f docker-compose.prod.yml exec -it database sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'`;
|
|
56
|
+
|
|
57
|
+
const result = spawnSync('ssh', ['-t', `${vpsUser}@${vpsHost}`, remoteCmd], { stdio: 'inherit' });
|
|
58
|
+
|
|
59
|
+
if (result.status !== 0) {
|
|
60
|
+
console.error(chalk.red('\n❌ Could not connect to the production database.'));
|
|
61
|
+
console.log(chalk.gray('Check that the VPS is reachable and services are running.\n'));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.log(chalk.blue.bold('\n🗄️ Opening local database console...\n'));
|
|
66
|
+
|
|
67
|
+
// Let the shell inside the container expand $POSTGRES_USER / $POSTGRES_DB
|
|
68
|
+
const psqlCmd = [
|
|
69
|
+
'compose', '-f', 'docker-compose.yml', '-f', 'docker-compose.dev.yml',
|
|
70
|
+
'exec', 'database', 'sh', '-c', 'psql -U $POSTGRES_USER $POSTGRES_DB'
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const result = spawnSync('docker', psqlCmd, { cwd: infrastructurePath, stdio: 'inherit' });
|
|
74
|
+
|
|
75
|
+
if (result.status !== 0) {
|
|
76
|
+
console.error(chalk.red('\n❌ Could not connect to the local database container.'));
|
|
77
|
+
console.log(chalk.gray('Make sure services are running:'));
|
|
78
|
+
console.log(chalk.white(' launchframe docker:up\n'));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = { databaseConsole };
|
package/src/commands/help.js
CHANGED
|
@@ -41,6 +41,9 @@ function help() {
|
|
|
41
41
|
console.log(chalk.gray(' migration:run Run pending database migrations'));
|
|
42
42
|
console.log(chalk.gray(' migration:create Create new database migration'));
|
|
43
43
|
console.log(chalk.gray(' migration:revert Revert last database migration\n'));
|
|
44
|
+
console.log(chalk.white('Database:'));
|
|
45
|
+
console.log(chalk.gray(' database:console Open a PostgreSQL console (local)'));
|
|
46
|
+
console.log(chalk.gray(' --remote Connect to the production database\n'));
|
|
44
47
|
|
|
45
48
|
console.log(chalk.white('Service Management:'));
|
|
46
49
|
console.log(chalk.gray(' service:add <name> Add an optional service to your project'));
|
package/src/index.js
CHANGED
|
@@ -32,6 +32,7 @@ const { dockerLogs } = require('./commands/docker-logs');
|
|
|
32
32
|
const { migrateRun } = require('./commands/migration-run');
|
|
33
33
|
const { migrateCreate } = require('./commands/migration-create');
|
|
34
34
|
const { migrateRevert } = require('./commands/migration-revert');
|
|
35
|
+
const { databaseConsole } = require('./commands/database-console');
|
|
35
36
|
const { dockerDestroy } = require('./commands/docker-destroy');
|
|
36
37
|
const { doctor } = require('./commands/doctor');
|
|
37
38
|
const { help } = require('./commands/help');
|
|
@@ -160,6 +161,9 @@ async function main() {
|
|
|
160
161
|
case 'migration:revert':
|
|
161
162
|
await migrateRevert();
|
|
162
163
|
break;
|
|
164
|
+
case 'database:console':
|
|
165
|
+
await databaseConsole({ remote: flags.remote });
|
|
166
|
+
break;
|
|
163
167
|
case 'doctor':
|
|
164
168
|
await doctor();
|
|
165
169
|
break;
|