@chimerai/cli 0.2.73

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -0
  3. package/dist/cli.d.ts +7 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +317 -0
  6. package/dist/commands/add.d.ts +11 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +2126 -0
  9. package/dist/commands/create.d.ts +12 -0
  10. package/dist/commands/create.d.ts.map +1 -0
  11. package/dist/commands/create.js +1703 -0
  12. package/dist/commands/deploy.d.ts +11 -0
  13. package/dist/commands/deploy.d.ts.map +1 -0
  14. package/dist/commands/deploy.js +219 -0
  15. package/dist/commands/dev.d.ts +17 -0
  16. package/dist/commands/dev.d.ts.map +1 -0
  17. package/dist/commands/dev.js +206 -0
  18. package/dist/commands/doctor.d.ts +11 -0
  19. package/dist/commands/doctor.d.ts.map +1 -0
  20. package/dist/commands/doctor.js +728 -0
  21. package/dist/commands/generate.d.ts +19 -0
  22. package/dist/commands/generate.d.ts.map +1 -0
  23. package/dist/commands/generate.js +429 -0
  24. package/dist/commands/init.d.ts +11 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +269 -0
  27. package/dist/commands/list.d.ts +12 -0
  28. package/dist/commands/list.d.ts.map +1 -0
  29. package/dist/commands/list.js +328 -0
  30. package/dist/commands/migrate.d.ts +14 -0
  31. package/dist/commands/migrate.d.ts.map +1 -0
  32. package/dist/commands/migrate.js +197 -0
  33. package/dist/commands/plugin.d.ts +10 -0
  34. package/dist/commands/plugin.d.ts.map +1 -0
  35. package/dist/commands/plugin.js +239 -0
  36. package/dist/commands/remove.d.ts +11 -0
  37. package/dist/commands/remove.d.ts.map +1 -0
  38. package/dist/commands/remove.js +472 -0
  39. package/dist/commands/secret.d.ts +12 -0
  40. package/dist/commands/secret.d.ts.map +1 -0
  41. package/dist/commands/secret.js +102 -0
  42. package/dist/commands/setup.d.ts +9 -0
  43. package/dist/commands/setup.d.ts.map +1 -0
  44. package/dist/commands/setup.js +788 -0
  45. package/dist/commands/update.d.ts +14 -0
  46. package/dist/commands/update.d.ts.map +1 -0
  47. package/dist/commands/update.js +211 -0
  48. package/dist/commands/use.d.ts +9 -0
  49. package/dist/commands/use.d.ts.map +1 -0
  50. package/dist/commands/use.js +51 -0
  51. package/dist/index.d.ts +22 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +45 -0
  54. package/dist/license.d.ts +55 -0
  55. package/dist/license.d.ts.map +1 -0
  56. package/dist/license.js +258 -0
  57. package/dist/scanner.d.ts +31 -0
  58. package/dist/scanner.d.ts.map +1 -0
  59. package/dist/scanner.js +113 -0
  60. package/dist/schema-manager.d.ts +26 -0
  61. package/dist/schema-manager.d.ts.map +1 -0
  62. package/dist/schema-manager.js +132 -0
  63. package/dist/templates/admin.d.ts +49 -0
  64. package/dist/templates/admin.d.ts.map +1 -0
  65. package/dist/templates/admin.js +1358 -0
  66. package/dist/templates/ai-routes.d.ts +17 -0
  67. package/dist/templates/ai-routes.d.ts.map +1 -0
  68. package/dist/templates/ai-routes.js +1130 -0
  69. package/dist/templates/ai-service-tools.d.ts +22 -0
  70. package/dist/templates/ai-service-tools.d.ts.map +1 -0
  71. package/dist/templates/ai-service-tools.js +1424 -0
  72. package/dist/templates/ai-service.d.ts +66 -0
  73. package/dist/templates/ai-service.d.ts.map +1 -0
  74. package/dist/templates/ai-service.js +2202 -0
  75. package/dist/templates/api-routes.d.ts +108 -0
  76. package/dist/templates/api-routes.d.ts.map +1 -0
  77. package/dist/templates/api-routes.js +1219 -0
  78. package/dist/templates/auth.d.ts +48 -0
  79. package/dist/templates/auth.d.ts.map +1 -0
  80. package/dist/templates/auth.js +381 -0
  81. package/dist/templates/billing.d.ts +44 -0
  82. package/dist/templates/billing.d.ts.map +1 -0
  83. package/dist/templates/billing.js +551 -0
  84. package/dist/templates/chat.d.ts +63 -0
  85. package/dist/templates/chat.d.ts.map +1 -0
  86. package/dist/templates/chat.js +1979 -0
  87. package/dist/templates/components.d.ts +22 -0
  88. package/dist/templates/components.d.ts.map +1 -0
  89. package/dist/templates/components.js +672 -0
  90. package/dist/templates/config.d.ts +6 -0
  91. package/dist/templates/config.d.ts.map +1 -0
  92. package/dist/templates/config.js +86 -0
  93. package/dist/templates/docker.d.ts +25 -0
  94. package/dist/templates/docker.d.ts.map +1 -0
  95. package/dist/templates/docker.js +165 -0
  96. package/dist/templates/gdpr.d.ts +16 -0
  97. package/dist/templates/gdpr.d.ts.map +1 -0
  98. package/dist/templates/gdpr.js +259 -0
  99. package/dist/templates/index.d.ts +77 -0
  100. package/dist/templates/index.d.ts.map +1 -0
  101. package/dist/templates/index.js +339 -0
  102. package/dist/templates/layout.d.ts +67 -0
  103. package/dist/templates/layout.d.ts.map +1 -0
  104. package/dist/templates/layout.js +670 -0
  105. package/dist/templates/mfa.d.ts +23 -0
  106. package/dist/templates/mfa.d.ts.map +1 -0
  107. package/dist/templates/mfa.js +353 -0
  108. package/dist/templates/middleware.d.ts +12 -0
  109. package/dist/templates/middleware.d.ts.map +1 -0
  110. package/dist/templates/middleware.js +116 -0
  111. package/dist/templates/prisma.d.ts +35 -0
  112. package/dist/templates/prisma.d.ts.map +1 -0
  113. package/dist/templates/prisma.js +724 -0
  114. package/dist/templates/provider-routes.d.ts +21 -0
  115. package/dist/templates/provider-routes.d.ts.map +1 -0
  116. package/dist/templates/provider-routes.js +1203 -0
  117. package/dist/templates/rag.d.ts +48 -0
  118. package/dist/templates/rag.d.ts.map +1 -0
  119. package/dist/templates/rag.js +532 -0
  120. package/dist/templates/widget.d.ts +64 -0
  121. package/dist/templates/widget.d.ts.map +1 -0
  122. package/dist/templates/widget.js +1360 -0
  123. package/dist/utils/provider-db.d.ts +63 -0
  124. package/dist/utils/provider-db.d.ts.map +1 -0
  125. package/dist/utils/provider-db.js +300 -0
  126. package/dist/utils.d.ts +78 -0
  127. package/dist/utils.d.ts.map +1 -0
  128. package/dist/utils.js +330 -0
  129. package/package.json +60 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Deploy Command - Deployment preparation and config generation
3
+ */
4
+ interface DeployOptions {
5
+ dir: string;
6
+ target: string;
7
+ checkOnly: boolean;
8
+ }
9
+ export declare function deployCommand(options: DeployOptions): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAQD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,iBAkCzD"}
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ /**
3
+ * Deploy Command - Deployment preparation and config generation
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.deployCommand = deployCommand;
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const ora_1 = __importDefault(require("ora"));
12
+ const fs_extra_1 = __importDefault(require("fs-extra"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const utils_js_1 = require("../utils.js");
15
+ const index_js_1 = require("../templates/index.js");
16
+ async function deployCommand(options) {
17
+ console.log(chalk_1.default.bold.cyan('\n🚀 ChimerAI Deploy\n'));
18
+ const targetDir = (0, utils_js_1.resolveTargetDir)(options.dir);
19
+ if (!(0, utils_js_1.validateWorkspace)(targetDir))
20
+ return;
21
+ const checks = await runChecks(targetDir);
22
+ displayChecks(checks);
23
+ const fails = checks.filter((c) => c.status === 'fail');
24
+ if (fails.length > 0) {
25
+ console.log(chalk_1.default.bold.red('\n❌ Fix issues above before deploying.\n'));
26
+ if (options.checkOnly)
27
+ return;
28
+ return; // Graceful exit instead of process.exit(1)
29
+ }
30
+ if (options.checkOnly) {
31
+ console.log(chalk_1.default.bold.green('\n✅ All deployment checks passed!\n'));
32
+ return;
33
+ }
34
+ switch (options.target) {
35
+ case 'vercel':
36
+ await deployVercel(targetDir);
37
+ break;
38
+ case 'docker':
39
+ await deployDocker(targetDir);
40
+ break;
41
+ case 'railway':
42
+ await deployRailway(targetDir);
43
+ break;
44
+ default:
45
+ console.log(chalk_1.default.red(`❌ Unknown target: ${options.target}`));
46
+ console.log(chalk_1.default.yellow('Targets: vercel, docker, railway'));
47
+ }
48
+ }
49
+ async function runChecks(targetDir) {
50
+ const checks = [];
51
+ const spinner = (0, ora_1.default)('Running deployment checks...').start();
52
+ try {
53
+ const pkg = await fs_extra_1.default.readJson(path_1.default.join(targetDir, 'package.json'));
54
+ checks.push(pkg.scripts?.build
55
+ ? { name: 'Build script', status: 'pass', message: 'Found' }
56
+ : { name: 'Build script', status: 'fail', message: 'Missing in package.json' });
57
+ }
58
+ catch {
59
+ checks.push({ name: 'Build script', status: 'fail', message: 'Cannot read package.json' });
60
+ }
61
+ const envPath = path_1.default.join(targetDir, '.env');
62
+ if (fs_extra_1.default.existsSync(envPath)) {
63
+ const env = await fs_extra_1.default.readFile(envPath, 'utf-8');
64
+ checks.push(env.includes('localhost')
65
+ ? {
66
+ name: 'DATABASE_URL',
67
+ status: 'warn',
68
+ message: 'Using localhost - update for production',
69
+ }
70
+ : { name: 'DATABASE_URL', status: 'pass', message: 'Production URL detected' });
71
+ checks.push(env.includes('your-secret-key-change-in-production')
72
+ ? {
73
+ name: 'NEXTAUTH_SECRET',
74
+ status: 'warn',
75
+ message: 'Using default - change for production',
76
+ }
77
+ : { name: 'NEXTAUTH_SECRET', status: 'pass', message: 'Custom secret set' });
78
+ }
79
+ else {
80
+ checks.push({ name: 'Environment', status: 'fail', message: 'No .env file' });
81
+ }
82
+ checks.push(fs_extra_1.default.existsSync(path_1.default.join(targetDir, 'prisma/schema.prisma'))
83
+ ? { name: 'Prisma schema', status: 'pass', message: 'Found' }
84
+ : { name: 'Prisma schema', status: 'fail', message: 'Missing' });
85
+ const gpath = path_1.default.join(targetDir, '.gitignore');
86
+ if (fs_extra_1.default.existsSync(gpath)) {
87
+ const g = await fs_extra_1.default.readFile(gpath, 'utf-8');
88
+ checks.push(g.includes('.env')
89
+ ? { name: 'Secrets protection', status: 'pass', message: '.env excluded' }
90
+ : { name: 'Secrets protection', status: 'fail', message: '.env may be committed!' });
91
+ }
92
+ spinner.stop();
93
+ return checks;
94
+ }
95
+ function displayChecks(checks) {
96
+ console.log(chalk_1.default.bold('📋 Deployment Readiness:\n'));
97
+ for (const c of checks) {
98
+ const icon = c.status === 'pass'
99
+ ? chalk_1.default.green('✓')
100
+ : c.status === 'warn'
101
+ ? chalk_1.default.yellow('⚠')
102
+ : chalk_1.default.red('✗');
103
+ console.log(` ${icon} ${c.name}: ${c.message}`);
104
+ }
105
+ }
106
+ /* ------------------------------------------------------------------ */
107
+ /* Deployment Targets */
108
+ /* ------------------------------------------------------------------ */
109
+ async function deployVercel(targetDir) {
110
+ const spinner = (0, ora_1.default)('Generating Vercel config...').start();
111
+ try {
112
+ await fs_extra_1.default.writeJson(path_1.default.join(targetDir, 'vercel.json'), {
113
+ $schema: 'https://openapi.vercel.sh/vercel.json',
114
+ framework: 'nextjs',
115
+ buildCommand: 'prisma generate && next build',
116
+ installCommand: 'pnpm install',
117
+ }, { spaces: 2 });
118
+ spinner.succeed('Created vercel.json');
119
+ console.log(chalk_1.default.bold.green('\n✅ Vercel config generated!\n'));
120
+ console.log(chalk_1.default.cyan('Next steps:'));
121
+ console.log(chalk_1.default.white(' 1. Set env vars in Vercel dashboard'));
122
+ console.log(chalk_1.default.white(' 2. Deploy: vercel --prod\n'));
123
+ }
124
+ catch (error) {
125
+ spinner.fail('Failed to generate Vercel config');
126
+ console.error(chalk_1.default.red(error.message));
127
+ }
128
+ }
129
+ async function deployDocker(targetDir) {
130
+ const spinner = (0, ora_1.default)('Generating Docker config...').start();
131
+ try {
132
+ // Generate Docker files using inline generators (no external template dependency)
133
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'Dockerfile'), (0, index_js_1.generateDockerfile)());
134
+ spinner.succeed('Created Dockerfile (multi-stage)');
135
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, '.dockerignore'), (0, index_js_1.generateDockerignore)());
136
+ spinner.succeed('Created .dockerignore');
137
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'docker-compose.prod.yml'), (0, index_js_1.generateDockerComposeProd)());
138
+ spinner.succeed('Created docker-compose.prod.yml');
139
+ console.log(chalk_1.default.bold.green('\n✅ Docker config generated!\n'));
140
+ console.log(chalk_1.default.cyan('Next steps:'));
141
+ console.log(chalk_1.default.white(' 1. Build: docker build -t chimerai-app .'));
142
+ console.log(chalk_1.default.white(' 2. Or: docker-compose -f docker-compose.prod.yml up -d\n'));
143
+ }
144
+ catch (error) {
145
+ spinner.fail('Failed to generate Docker config');
146
+ console.error(chalk_1.default.red(error.message));
147
+ }
148
+ }
149
+ async function deployRailway(targetDir) {
150
+ const spinner = (0, ora_1.default)('Generating Railway config...').start();
151
+ try {
152
+ // Detect start command based on package.json
153
+ let startCommand = 'npx prisma migrate deploy && pnpm start';
154
+ try {
155
+ const pkg = await fs_extra_1.default.readJson(path_1.default.join(targetDir, 'package.json'));
156
+ if (pkg.scripts?.start) {
157
+ startCommand = `npx prisma migrate deploy && ${pkg.scripts.start.includes('node') ? pkg.scripts.start : 'pnpm start'}`;
158
+ }
159
+ else {
160
+ // No start script — check for standalone output
161
+ const nextConfig = path_1.default.join(targetDir, 'next.config.js');
162
+ const nextConfigMjs = path_1.default.join(targetDir, 'next.config.mjs');
163
+ let hasStandalone = false;
164
+ for (const cfg of [nextConfig, nextConfigMjs]) {
165
+ if (fs_extra_1.default.existsSync(cfg)) {
166
+ const content = await fs_extra_1.default.readFile(cfg, 'utf-8');
167
+ if (content.includes("'standalone'") || content.includes('"standalone"')) {
168
+ hasStandalone = true;
169
+ }
170
+ }
171
+ }
172
+ startCommand = hasStandalone
173
+ ? 'npx prisma migrate deploy && node server.js'
174
+ : 'npx prisma migrate deploy && pnpm start';
175
+ }
176
+ }
177
+ catch {
178
+ // Fallback to default
179
+ }
180
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'railway.toml'), `[build]
181
+ builder = "nixpacks"
182
+ buildCommand = "pnpm install && npx prisma generate && pnpm build"
183
+
184
+ [deploy]
185
+ startCommand = "${startCommand}"
186
+ healthcheckPath = "/api/health"
187
+ restartPolicyType = "on_failure"
188
+ restartPolicyMaxRetries = 3
189
+
190
+ [service]
191
+ internalPort = 3000
192
+ `);
193
+ spinner.succeed('Created railway.toml');
194
+ console.log(chalk_1.default.gray(` Start command: ${startCommand}`));
195
+ const healthPath = path_1.default.join(targetDir, 'app/api/health/route.ts');
196
+ if (!fs_extra_1.default.existsSync(healthPath)) {
197
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(healthPath));
198
+ await fs_extra_1.default.writeFile(healthPath, `import { NextResponse } from 'next/server';
199
+
200
+ export async function GET() {
201
+ return NextResponse.json({
202
+ status: 'ok',
203
+ timestamp: new Date().toISOString(),
204
+ uptime: process.uptime(),
205
+ });
206
+ }
207
+ `);
208
+ spinner.succeed('Created health check endpoint');
209
+ }
210
+ console.log(chalk_1.default.bold.green('\n✅ Railway config generated!\n'));
211
+ console.log(chalk_1.default.cyan('Next steps:'));
212
+ console.log(chalk_1.default.white(' 1. Install: npm i -g @railway/cli'));
213
+ console.log(chalk_1.default.white(' 2. Deploy: railway up\n'));
214
+ }
215
+ catch (error) {
216
+ spinner.fail('Failed to generate Railway config');
217
+ console.error(chalk_1.default.red(error.message));
218
+ }
219
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Dev Command - PHASE 3.3
3
+ * Orchestrates complete development environment setup
4
+ * Starts Docker, installs dependencies, runs migrations, then starts dev server
5
+ */
6
+ export interface DevOptions {
7
+ dir: string;
8
+ skipDocker: boolean;
9
+ skipMigrate: boolean;
10
+ port: number;
11
+ }
12
+ /**
13
+ * Start dev environment: Docker → Dependencies → Migrations → Dev Server
14
+ * @param options - DevOptions with directory and flags
15
+ */
16
+ export declare function devCommand(options: DevOptions): Promise<void>;
17
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAWD;;;GAGG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BnE"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ /**
3
+ * Dev Command - PHASE 3.3
4
+ * Orchestrates complete development environment setup
5
+ * Starts Docker, installs dependencies, runs migrations, then starts dev server
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.devCommand = devCommand;
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const ora_1 = __importDefault(require("ora"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const fs_extra_1 = __importDefault(require("fs-extra"));
16
+ const execa_1 = require("execa");
17
+ const scanner_js_1 = require("../scanner.js");
18
+ const utils_js_1 = require("../utils.js");
19
+ /**
20
+ * Validate project structure
21
+ * @param targetDir - Project root directory
22
+ * @returns true if valid ChimerAI project
23
+ */
24
+ function validateWorkspace(targetDir) {
25
+ return fs_extra_1.default.existsSync(path_1.default.join(targetDir, 'package.json'));
26
+ }
27
+ /**
28
+ * Start dev environment: Docker → Dependencies → Migrations → Dev Server
29
+ * @param options - DevOptions with directory and flags
30
+ */
31
+ async function devCommand(options) {
32
+ const targetDir = (0, utils_js_1.resolveTargetDir)(options.dir || '.');
33
+ // Validate project
34
+ if (!validateWorkspace(targetDir)) {
35
+ (0, utils_js_1.handleCliError)('Not a valid ChimerAI project. Run: chimerai create <name>');
36
+ }
37
+ // Scan project
38
+ const project = await (0, scanner_js_1.scanProject)(targetDir);
39
+ console.log(chalk_1.default.blue.bold('\n 🚀 ChimerAI Dev Environment\n'));
40
+ console.log(chalk_1.default.cyan(` Project: ${chalk_1.default.white(path_1.default.basename(targetDir))}`));
41
+ console.log(chalk_1.default.cyan(` Next.js: ${chalk_1.default.white(project.nextVersion || 'not found')}`));
42
+ console.log(chalk_1.default.cyan(` Router: ${chalk_1.default.white(project.hasAppRouter ? 'app' : 'pages')}\n`));
43
+ // 1. Docker Compose
44
+ if (!options.skipDocker) {
45
+ await startDockerServices(targetDir);
46
+ }
47
+ // 2. Dependencies
48
+ await ensureDependencies(targetDir, project);
49
+ // 3. Prisma Migrations
50
+ if (!options.skipMigrate) {
51
+ await applyMigrations(targetDir, project);
52
+ }
53
+ // 4. Start dev server
54
+ await startDevServer(targetDir, project, options.port);
55
+ }
56
+ /**
57
+ * Start Docker Compose services (PostgreSQL, Redis, etc.)
58
+ */
59
+ async function startDockerServices(targetDir) {
60
+ const composePath = path_1.default.join(targetDir, 'docker-compose.yml');
61
+ if (!(await fs_extra_1.default.pathExists(composePath))) {
62
+ return; // No docker-compose.yml, skip
63
+ }
64
+ const spinner = (0, ora_1.default)('Starting Docker services...').start();
65
+ try {
66
+ await (0, execa_1.execa)('docker', ['compose', 'up', '-d'], { cwd: targetDir });
67
+ spinner.succeed(chalk_1.default.green('Docker services running (PostgreSQL + Redis)'));
68
+ }
69
+ catch (error) {
70
+ spinner.warn(chalk_1.default.yellow('Docker not available - skipping'));
71
+ }
72
+ }
73
+ /**
74
+ * Install dependencies if node_modules doesn't exist
75
+ */
76
+ async function ensureDependencies(targetDir, project) {
77
+ const nmPath = path_1.default.join(targetDir, 'node_modules');
78
+ if (await fs_extra_1.default.pathExists(nmPath)) {
79
+ return; // Dependencies already installed
80
+ }
81
+ const pm = project.packageManager === 'unknown' ? 'npm' : project.packageManager;
82
+ const spinner = (0, ora_1.default)(`Installing dependencies with ${pm}...`).start();
83
+ try {
84
+ await (0, execa_1.execa)(pm, ['install'], { cwd: targetDir });
85
+ spinner.succeed(chalk_1.default.green('Dependencies installed'));
86
+ }
87
+ catch (error) {
88
+ spinner.fail(chalk_1.default.red('Failed to install dependencies'));
89
+ (0, utils_js_1.handleCliError)(error.message);
90
+ }
91
+ }
92
+ /**
93
+ * Apply Prisma database migrations
94
+ */
95
+ async function applyMigrations(targetDir, project) {
96
+ if (!project.hasPrisma) {
97
+ return; // No Prisma, skip
98
+ }
99
+ const spinner = (0, ora_1.default)('Applying database migrations...').start();
100
+ try {
101
+ await (0, execa_1.execa)('npx', ['prisma', 'db', 'push', '--skip-generate'], { cwd: targetDir });
102
+ spinner.succeed(chalk_1.default.green('Database schema applied'));
103
+ }
104
+ catch (error) {
105
+ spinner.warn(chalk_1.default.yellow('Database migration failed - check DATABASE_URL in .env'));
106
+ console.log(chalk_1.default.gray(` Error: ${error.message}`));
107
+ }
108
+ }
109
+ /**
110
+ * Start Next.js dev server with graceful shutdown handling
111
+ * Also starts AI service in parallel if services/ai/ exists
112
+ */
113
+ async function startDevServer(targetDir, project, port) {
114
+ const pm = project.packageManager === 'unknown' ? 'npm' : project.packageManager;
115
+ // Check if AI service exists
116
+ const aiServiceDir = path_1.default.join(targetDir, 'services', 'ai');
117
+ const hasAiService = await fs_extra_1.default.pathExists(path_1.default.join(aiServiceDir, 'main.py'));
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
+ let aiProcess = null;
120
+ // Start AI service if present
121
+ if (hasAiService) {
122
+ const spinner = (0, ora_1.default)('Preparing AI service...').start();
123
+ try {
124
+ const isWindows = process.platform === 'win32';
125
+ const venvDir = path_1.default.join(aiServiceDir, '.venv');
126
+ // Create venv if not exists
127
+ if (!(await fs_extra_1.default.pathExists(venvDir))) {
128
+ spinner.text = 'Creating Python virtual environment...';
129
+ await (0, execa_1.execa)('python', ['-m', 'venv', venvDir], { cwd: aiServiceDir });
130
+ // Install requirements
131
+ spinner.text = 'Installing Python dependencies...';
132
+ const pipPath = isWindows
133
+ ? path_1.default.join(venvDir, 'Scripts', 'pip')
134
+ : path_1.default.join(venvDir, 'bin', 'pip');
135
+ await (0, execa_1.execa)(pipPath, ['install', '-r', 'requirements.txt'], { cwd: aiServiceDir });
136
+ }
137
+ // Start uvicorn
138
+ const uvicornPath = isWindows
139
+ ? path_1.default.join(venvDir, 'Scripts', 'uvicorn')
140
+ : path_1.default.join(venvDir, 'bin', 'uvicorn');
141
+ const aiChild = (0, execa_1.execa)(uvicornPath, ['main:app', '--reload', '--port', '8002'], {
142
+ cwd: aiServiceDir,
143
+ stdio: 'pipe',
144
+ });
145
+ aiProcess = aiChild;
146
+ // Prefix AI service output
147
+ aiChild.stdout?.on('data', (data) => {
148
+ const lines = data.toString().trim().split('\n');
149
+ lines.forEach((line) => {
150
+ console.log(chalk_1.default.magenta('[AI] ') + line);
151
+ });
152
+ });
153
+ aiChild.stderr?.on('data', (data) => {
154
+ const lines = data.toString().trim().split('\n');
155
+ lines.forEach((line) => {
156
+ console.log(chalk_1.default.magenta('[AI] ') + chalk_1.default.yellow(line));
157
+ });
158
+ });
159
+ spinner.succeed(chalk_1.default.green('AI service starting on http://localhost:8002'));
160
+ }
161
+ catch (error) {
162
+ spinner.warn(chalk_1.default.yellow(`AI service failed to start: ${error.message}`));
163
+ aiProcess = null;
164
+ }
165
+ }
166
+ console.log(chalk_1.default.green(`\n ▶️ Starting dev server on ${chalk_1.default.white(`http://localhost:${port}`)}\n`));
167
+ if (hasAiService) {
168
+ console.log(chalk_1.default.green(` ▶️ AI service on ${chalk_1.default.white('http://localhost:8002')}\n`));
169
+ }
170
+ console.log(chalk_1.default.gray(' Press Ctrl+C to stop\n'));
171
+ // Spawn child process with stdio inheritance (shows all output)
172
+ const child = (0, execa_1.execa)(pm, ['run', 'dev'], {
173
+ cwd: targetDir,
174
+ stdio: 'inherit',
175
+ env: { ...process.env, PORT: String(port) },
176
+ });
177
+ // Handle graceful shutdown on Ctrl+C
178
+ const shutdownHandler = async () => {
179
+ console.log(chalk_1.default.yellow('\n\n ⏹️ Shutting down...\n'));
180
+ // Kill dev server
181
+ child.kill();
182
+ // Kill AI service if running
183
+ if (aiProcess) {
184
+ aiProcess.kill();
185
+ console.log(chalk_1.default.magenta(' [AI] Service stopped'));
186
+ }
187
+ // Stop Docker services if running
188
+ const composePath = path_1.default.join(targetDir, 'docker-compose.yml');
189
+ if (!(await fs_extra_1.default.pathExists(composePath))) {
190
+ process.exit(0);
191
+ }
192
+ const spinner = (0, ora_1.default)('Stopping Docker services...').start();
193
+ try {
194
+ await (0, execa_1.execa)('docker', ['compose', 'stop'], { cwd: targetDir });
195
+ spinner.succeed(chalk_1.default.green('Docker services stopped'));
196
+ }
197
+ catch {
198
+ spinner.warn(chalk_1.default.yellow('Could not stop Docker services'));
199
+ }
200
+ process.exit(0);
201
+ };
202
+ process.on('SIGINT', shutdownHandler);
203
+ process.on('SIGTERM', shutdownHandler);
204
+ // Wait for dev server to finish
205
+ await child;
206
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Doctor Command - Health check for ChimerAI projects
3
+ * Validates configuration, dependencies, and environment setup
4
+ */
5
+ interface DoctorOptions {
6
+ dir: string;
7
+ fix: boolean;
8
+ }
9
+ export declare function doctorCommand(options: DoctorOptions): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,OAAO,CAAC;CACd;AASD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,iBAoFzD"}