Skip to content

Commit e4b0570

Browse files
Add new commands for environment setup, service management, and system checks; enhance existing commands and update scripts
1 parent e51c0a0 commit e4b0570

File tree

20 files changed

+524
-19
lines changed

20 files changed

+524
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ coverage/
88
bin/
99

1010
*.exe
11+
*.zip

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
},
1010
"scripts": {
1111
"build": "tsup src/cli.ts --format cjs --minify --out-dir dist --no-splitting",
12-
"package": "powershell -ExecutionPolicy Bypass -File tools/build-sea.ps1",
12+
"package": "pkg dist/cli.js --targets node20-win-x64 --output bin/cloudsqlctl.exe",
13+
"zip": "powershell -Command \"Get-ChildItem -Path src, tests, tools, package.json, tsconfig.json, tsup.config.ts, jest.config.ts, .gitignore, eslint.config.mjs, LICENSE, *.md -ErrorAction SilentlyContinue | Compress-Archive -DestinationPath cloudsqlctl.zip -Force\"",
1314
"lint": "eslint src",
1415
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --passWithNoTests",
1516
"prepare": "husky install"

src/cli.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import { statusCommand } from './commands/status.js';
1111
import { logsCommand } from './commands/logs.js';
1212
import { doctorCommand } from './commands/doctor.js';
1313
import { resetCommand } from './commands/reset.js';
14+
import { setenvCommand } from './commands/setenv.js';
15+
import { ps1Command } from './commands/ps1.js';
16+
import { repairCommand } from './commands/repair.js';
17+
import { checkCommand } from './commands/check.js';
1418
import { logger } from './core/logger.js';
1519

1620
const program = new Command();
@@ -31,6 +35,10 @@ program.addCommand(statusCommand);
3135
program.addCommand(logsCommand);
3236
program.addCommand(doctorCommand);
3337
program.addCommand(resetCommand);
38+
program.addCommand(setenvCommand);
39+
program.addCommand(ps1Command);
40+
program.addCommand(repairCommand);
41+
program.addCommand(checkCommand);
3442

3543
program.parseAsync(process.argv).catch(err => {
3644
logger.error('Unhandled error', err);

src/commands/check.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Command } from 'commander';
2+
import { checkEnvironment } from '../system/env.js';
3+
import { isServiceInstalled, isServiceRunning } from '../system/service.js';
4+
import { SYSTEM_PATHS } from '../system/paths.js';
5+
import fs from 'fs-extra';
6+
import { logger } from '../core/logger.js';
7+
8+
export const checkCommand = new Command('check')
9+
.description('Verify full system configuration')
10+
.action(async () => {
11+
try {
12+
logger.info('Checking system configuration...');
13+
14+
const envOk = await checkEnvironment();
15+
logger.info(`Environment Variables: ${envOk ? 'OK' : 'MISSING/INCORRECT'}`);
16+
17+
const binaryOk = await fs.pathExists(SYSTEM_PATHS.PROXY_EXE);
18+
logger.info(`Proxy Binary: ${binaryOk ? 'OK' : 'MISSING'}`);
19+
20+
const serviceInstalled = await isServiceInstalled();
21+
logger.info(`Service Installed: ${serviceInstalled ? 'YES' : 'NO'}`);
22+
23+
if (serviceInstalled) {
24+
const serviceRunning = await isServiceRunning();
25+
logger.info(`Service Running: ${serviceRunning ? 'YES' : 'NO'}`);
26+
}
27+
28+
if (envOk && binaryOk && serviceInstalled) {
29+
logger.info('System check passed.');
30+
} else {
31+
logger.warn('System check failed. Run "cloudsqlctl repair" to fix.');
32+
process.exit(1);
33+
}
34+
} catch (error) {
35+
logger.error('Check failed', error);
36+
process.exit(1);
37+
}
38+
});

src/commands/doctor.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { Command } from 'commander';
22
import { logger } from '../core/logger.js';
33
import { checkGcloudInstalled, getActiveAccount } from '../core/gcloud.js';
4+
import { checkEnvironment } from '../system/env.js';
5+
import { isServiceInstalled } from '../system/service.js';
6+
import { SYSTEM_PATHS } from '../system/paths.js';
7+
import fs from 'fs-extra';
48
import axios from 'axios';
59

610
export const doctorCommand = new Command('doctor')
@@ -24,6 +28,28 @@ export const doctorCommand = new Command('doctor')
2428
logger.warn('⚠️ No active gcloud account found. Run "gcloud auth login"');
2529
}
2630

31+
// Check Environment Variables
32+
const envOk = await checkEnvironment();
33+
if (envOk) {
34+
logger.info('✅ System Environment Variables are correct');
35+
} else {
36+
logger.warn('⚠️ System Environment Variables are missing or incorrect');
37+
}
38+
39+
// Check Proxy Binary
40+
if (await fs.pathExists(SYSTEM_PATHS.PROXY_EXE)) {
41+
logger.info('✅ Cloud SQL Proxy binary found');
42+
} else {
43+
logger.error('❌ Cloud SQL Proxy binary NOT found');
44+
}
45+
46+
// Check Service
47+
if (await isServiceInstalled()) {
48+
logger.info('✅ Windows Service is installed');
49+
} else {
50+
logger.info('ℹ️ Windows Service is NOT installed (Optional)');
51+
}
52+
2753
// Check Network (GitHub API)
2854
try {
2955
await axios.get('https://api.github.com');

src/commands/install.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import { Command } from 'commander';
22
import { getLatestVersion, downloadProxy } from '../core/updater.js';
33
import { logger } from '../core/logger.js';
44
import { isRunning, stopProxy } from '../core/proxy.js';
5+
import { setupEnvironment } from '../system/env.js';
6+
import { generateScripts } from '../system/ps1.js';
7+
import { installService } from '../system/service.js';
58

69
export const installCommand = new Command('install')
7-
.description('Download and install Cloud SQL Proxy')
10+
.description('Download and install Cloud SQL Proxy, setup environment and service')
811
.option('-v, --version <version>', 'Specific version to install')
912
.action(async (options) => {
1013
try {
@@ -20,7 +23,17 @@ export const installCommand = new Command('install')
2023
}
2124
logger.info(`Installing Cloud SQL Proxy version ${version}...`);
2225
await downloadProxy(version);
23-
logger.info('Installation successful.');
26+
27+
logger.info('Setting up environment variables...');
28+
await setupEnvironment();
29+
30+
logger.info('Generating PowerShell scripts...');
31+
await generateScripts();
32+
33+
logger.info('Installing Windows Service...');
34+
await installService();
35+
36+
logger.info('Installation and setup successful.');
2437
} catch (error) {
2538
logger.error('Installation failed', error);
2639
process.exit(1);

src/commands/ps1.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Command } from 'commander';
2+
import { generateScripts } from '../system/ps1.js';
3+
import { logger } from '../core/logger.js';
4+
5+
export const ps1Command = new Command('ps1')
6+
.description('Manage PowerShell scripts');
7+
8+
ps1Command.command('generate')
9+
.description('Generate management PowerShell scripts')
10+
.action(async () => {
11+
try {
12+
await generateScripts();
13+
logger.info('PowerShell scripts generated successfully.');
14+
} catch (error) {
15+
logger.error('Failed to generate scripts', error);
16+
process.exit(1);
17+
}
18+
});

src/commands/repair.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Command } from 'commander';
2+
import { selfHeal } from '../system/selfheal.js';
3+
import { logger } from '../core/logger.js';
4+
5+
export const repairCommand = new Command('repair')
6+
.description('Self-heal missing or corrupted files and configurations')
7+
.action(async () => {
8+
try {
9+
await selfHeal();
10+
} catch (error) {
11+
logger.error('Repair failed', error);
12+
process.exit(1);
13+
}
14+
});

src/commands/setenv.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Command } from 'commander';
2+
import { setupEnvironment } from '../system/env.js';
3+
import { logger } from '../core/logger.js';
4+
5+
export const setenvCommand = new Command('setenv')
6+
.description('Create system-wide environment variables')
7+
.action(async () => {
8+
try {
9+
await setupEnvironment();
10+
logger.info('Environment variables set successfully.');
11+
} catch (error) {
12+
logger.error('Failed to set environment variables', error);
13+
process.exit(1);
14+
}
15+
});

src/commands/status.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,37 @@ import { Command } from 'commander';
22
import { isRunning } from '../core/proxy.js';
33
import { logger } from '../core/logger.js';
44
import { readConfig } from '../core/config.js';
5+
import { isServiceInstalled, isServiceRunning } from '../system/service.js';
56

67
export const statusCommand = new Command('status')
7-
.description('Check the status of the Cloud SQL Proxy')
8+
.description('Check the status of the Cloud SQL Proxy and Service')
89
.action(async () => {
910
try {
10-
const running = await isRunning();
11+
const processRunning = await isRunning();
12+
const serviceInstalled = await isServiceInstalled();
13+
const serviceRunning = serviceInstalled ? await isServiceRunning() : false;
1114
const config = await readConfig();
1215

13-
if (running) {
14-
logger.info('Proxy is RUNNING');
16+
logger.info('--- Status ---');
17+
18+
if (serviceInstalled) {
19+
logger.info(`Service: ${serviceRunning ? 'RUNNING' : 'STOPPED'}`);
20+
} else {
21+
logger.info('Service: NOT INSTALLED');
22+
}
23+
24+
if (processRunning) {
25+
logger.info('Process: RUNNING');
1526
logger.info(`Instance: ${config.selectedInstance || 'Unknown'}`);
1627
logger.info(`Port: ${config.proxyPort || 5432}`);
1728
} else {
18-
logger.info('Proxy is STOPPED');
29+
logger.info('Process: STOPPED');
1930
}
31+
32+
if (!processRunning && !serviceRunning) {
33+
logger.info('Cloud SQL Proxy is not active.');
34+
}
35+
2036
} catch (error) {
2137
logger.error('Failed to check status', error);
2238
process.exit(1);

0 commit comments

Comments
 (0)