popeye-cli 1.7.0 → 1.9.0

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 (174) hide show
  1. package/README.md +148 -7
  2. package/cheatsheet.md +440 -0
  3. package/dist/cli/commands/db.d.ts +10 -0
  4. package/dist/cli/commands/db.d.ts.map +1 -0
  5. package/dist/cli/commands/db.js +240 -0
  6. package/dist/cli/commands/db.js.map +1 -0
  7. package/dist/cli/commands/doctor.d.ts +18 -0
  8. package/dist/cli/commands/doctor.d.ts.map +1 -0
  9. package/dist/cli/commands/doctor.js +255 -0
  10. package/dist/cli/commands/doctor.js.map +1 -0
  11. package/dist/cli/commands/index.d.ts +3 -0
  12. package/dist/cli/commands/index.d.ts.map +1 -1
  13. package/dist/cli/commands/index.js +3 -0
  14. package/dist/cli/commands/index.js.map +1 -1
  15. package/dist/cli/commands/review.d.ts +31 -0
  16. package/dist/cli/commands/review.d.ts.map +1 -0
  17. package/dist/cli/commands/review.js +156 -0
  18. package/dist/cli/commands/review.js.map +1 -0
  19. package/dist/cli/index.d.ts.map +1 -1
  20. package/dist/cli/index.js +4 -1
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/interactive.d.ts.map +1 -1
  23. package/dist/cli/interactive.js +218 -61
  24. package/dist/cli/interactive.js.map +1 -1
  25. package/dist/generators/admin-wizard.d.ts +25 -0
  26. package/dist/generators/admin-wizard.d.ts.map +1 -0
  27. package/dist/generators/admin-wizard.js +123 -0
  28. package/dist/generators/admin-wizard.js.map +1 -0
  29. package/dist/generators/all.d.ts.map +1 -1
  30. package/dist/generators/all.js +10 -3
  31. package/dist/generators/all.js.map +1 -1
  32. package/dist/generators/database.d.ts +58 -0
  33. package/dist/generators/database.d.ts.map +1 -0
  34. package/dist/generators/database.js +229 -0
  35. package/dist/generators/database.js.map +1 -0
  36. package/dist/generators/fullstack.d.ts.map +1 -1
  37. package/dist/generators/fullstack.js +23 -7
  38. package/dist/generators/fullstack.js.map +1 -1
  39. package/dist/generators/index.d.ts +2 -0
  40. package/dist/generators/index.d.ts.map +1 -1
  41. package/dist/generators/index.js +2 -0
  42. package/dist/generators/index.js.map +1 -1
  43. package/dist/generators/templates/admin-wizard-python.d.ts +32 -0
  44. package/dist/generators/templates/admin-wizard-python.d.ts.map +1 -0
  45. package/dist/generators/templates/admin-wizard-python.js +425 -0
  46. package/dist/generators/templates/admin-wizard-python.js.map +1 -0
  47. package/dist/generators/templates/admin-wizard-react.d.ts +48 -0
  48. package/dist/generators/templates/admin-wizard-react.d.ts.map +1 -0
  49. package/dist/generators/templates/admin-wizard-react.js +554 -0
  50. package/dist/generators/templates/admin-wizard-react.js.map +1 -0
  51. package/dist/generators/templates/database-docker.d.ts +23 -0
  52. package/dist/generators/templates/database-docker.d.ts.map +1 -0
  53. package/dist/generators/templates/database-docker.js +221 -0
  54. package/dist/generators/templates/database-docker.js.map +1 -0
  55. package/dist/generators/templates/database-python.d.ts +54 -0
  56. package/dist/generators/templates/database-python.d.ts.map +1 -0
  57. package/dist/generators/templates/database-python.js +723 -0
  58. package/dist/generators/templates/database-python.js.map +1 -0
  59. package/dist/generators/templates/database-typescript.d.ts +34 -0
  60. package/dist/generators/templates/database-typescript.d.ts.map +1 -0
  61. package/dist/generators/templates/database-typescript.js +232 -0
  62. package/dist/generators/templates/database-typescript.js.map +1 -0
  63. package/dist/generators/templates/fullstack.d.ts.map +1 -1
  64. package/dist/generators/templates/fullstack.js +29 -0
  65. package/dist/generators/templates/fullstack.js.map +1 -1
  66. package/dist/generators/templates/index.d.ts +5 -0
  67. package/dist/generators/templates/index.d.ts.map +1 -1
  68. package/dist/generators/templates/index.js +5 -0
  69. package/dist/generators/templates/index.js.map +1 -1
  70. package/dist/state/index.d.ts +10 -0
  71. package/dist/state/index.d.ts.map +1 -1
  72. package/dist/state/index.js +21 -0
  73. package/dist/state/index.js.map +1 -1
  74. package/dist/types/audit.d.ts +623 -0
  75. package/dist/types/audit.d.ts.map +1 -0
  76. package/dist/types/audit.js +240 -0
  77. package/dist/types/audit.js.map +1 -0
  78. package/dist/types/database-runtime.d.ts +86 -0
  79. package/dist/types/database-runtime.d.ts.map +1 -0
  80. package/dist/types/database-runtime.js +61 -0
  81. package/dist/types/database-runtime.js.map +1 -0
  82. package/dist/types/database.d.ts +85 -0
  83. package/dist/types/database.d.ts.map +1 -0
  84. package/dist/types/database.js +71 -0
  85. package/dist/types/database.js.map +1 -0
  86. package/dist/types/index.d.ts +2 -0
  87. package/dist/types/index.d.ts.map +1 -1
  88. package/dist/types/index.js +4 -0
  89. package/dist/types/index.js.map +1 -1
  90. package/dist/types/workflow.d.ts +36 -0
  91. package/dist/types/workflow.d.ts.map +1 -1
  92. package/dist/types/workflow.js +7 -0
  93. package/dist/types/workflow.js.map +1 -1
  94. package/dist/workflow/audit-analyzer.d.ts +58 -0
  95. package/dist/workflow/audit-analyzer.d.ts.map +1 -0
  96. package/dist/workflow/audit-analyzer.js +420 -0
  97. package/dist/workflow/audit-analyzer.js.map +1 -0
  98. package/dist/workflow/audit-mode.d.ts +28 -0
  99. package/dist/workflow/audit-mode.d.ts.map +1 -0
  100. package/dist/workflow/audit-mode.js +169 -0
  101. package/dist/workflow/audit-mode.js.map +1 -0
  102. package/dist/workflow/audit-recovery.d.ts +61 -0
  103. package/dist/workflow/audit-recovery.d.ts.map +1 -0
  104. package/dist/workflow/audit-recovery.js +242 -0
  105. package/dist/workflow/audit-recovery.js.map +1 -0
  106. package/dist/workflow/audit-reporter.d.ts +65 -0
  107. package/dist/workflow/audit-reporter.d.ts.map +1 -0
  108. package/dist/workflow/audit-reporter.js +301 -0
  109. package/dist/workflow/audit-reporter.js.map +1 -0
  110. package/dist/workflow/audit-scanner.d.ts +87 -0
  111. package/dist/workflow/audit-scanner.d.ts.map +1 -0
  112. package/dist/workflow/audit-scanner.js +768 -0
  113. package/dist/workflow/audit-scanner.js.map +1 -0
  114. package/dist/workflow/db-setup-runner.d.ts +63 -0
  115. package/dist/workflow/db-setup-runner.d.ts.map +1 -0
  116. package/dist/workflow/db-setup-runner.js +336 -0
  117. package/dist/workflow/db-setup-runner.js.map +1 -0
  118. package/dist/workflow/db-state-machine.d.ts +30 -0
  119. package/dist/workflow/db-state-machine.d.ts.map +1 -0
  120. package/dist/workflow/db-state-machine.js +51 -0
  121. package/dist/workflow/db-state-machine.js.map +1 -0
  122. package/dist/workflow/index.d.ts +7 -0
  123. package/dist/workflow/index.d.ts.map +1 -1
  124. package/dist/workflow/index.js +7 -0
  125. package/dist/workflow/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/src/cli/commands/db.ts +281 -0
  128. package/src/cli/commands/doctor.ts +273 -0
  129. package/src/cli/commands/index.ts +3 -0
  130. package/src/cli/commands/review.ts +187 -0
  131. package/src/cli/index.ts +6 -0
  132. package/src/cli/interactive.ts +174 -4
  133. package/src/generators/admin-wizard.ts +146 -0
  134. package/src/generators/all.ts +10 -3
  135. package/src/generators/database.ts +286 -0
  136. package/src/generators/fullstack.ts +26 -9
  137. package/src/generators/index.ts +12 -0
  138. package/src/generators/templates/admin-wizard-python.ts +431 -0
  139. package/src/generators/templates/admin-wizard-react.ts +560 -0
  140. package/src/generators/templates/database-docker.ts +227 -0
  141. package/src/generators/templates/database-python.ts +734 -0
  142. package/src/generators/templates/database-typescript.ts +238 -0
  143. package/src/generators/templates/fullstack.ts +29 -0
  144. package/src/generators/templates/index.ts +5 -0
  145. package/src/state/index.ts +28 -0
  146. package/src/types/audit.ts +294 -0
  147. package/src/types/database-runtime.ts +69 -0
  148. package/src/types/database.ts +84 -0
  149. package/src/types/index.ts +29 -0
  150. package/src/types/workflow.ts +20 -0
  151. package/src/workflow/audit-analyzer.ts +491 -0
  152. package/src/workflow/audit-mode.ts +240 -0
  153. package/src/workflow/audit-recovery.ts +284 -0
  154. package/src/workflow/audit-reporter.ts +370 -0
  155. package/src/workflow/audit-scanner.ts +873 -0
  156. package/src/workflow/db-setup-runner.ts +391 -0
  157. package/src/workflow/db-state-machine.ts +58 -0
  158. package/src/workflow/index.ts +7 -0
  159. package/tests/cli/commands/review.test.ts +52 -0
  160. package/tests/generators/admin-wizard-orchestrator.test.ts +64 -0
  161. package/tests/generators/admin-wizard-templates.test.ts +366 -0
  162. package/tests/generators/cross-phase-integration.test.ts +383 -0
  163. package/tests/generators/database.test.ts +456 -0
  164. package/tests/generators/fe-be-db-integration.test.ts +613 -0
  165. package/tests/types/audit.test.ts +250 -0
  166. package/tests/types/database-runtime.test.ts +158 -0
  167. package/tests/types/database.test.ts +187 -0
  168. package/tests/workflow/audit-analyzer.test.ts +281 -0
  169. package/tests/workflow/audit-mode.test.ts +114 -0
  170. package/tests/workflow/audit-recovery.test.ts +237 -0
  171. package/tests/workflow/audit-reporter.test.ts +254 -0
  172. package/tests/workflow/audit-scanner.test.ts +270 -0
  173. package/tests/workflow/db-setup-runner.test.ts +211 -0
  174. package/tests/workflow/db-state-machine.test.ts +117 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2PpC;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAqBzC"}
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Database CLI command
3
+ * Provides subcommands: status, configure, apply
4
+ */
5
+ import { Command } from 'commander';
6
+ import path from 'node:path';
7
+ import { promises as fsPromises } from 'node:fs';
8
+ import { createInterface } from 'node:readline';
9
+ import { loadProject, updateState } from '../../state/index.js';
10
+ import { DEFAULT_DB_CONFIG } from '../../types/database.js';
11
+ import { transitionDbStatus } from '../../workflow/db-state-machine.js';
12
+ import { runDbSetupPipeline, resolveBackendDir, } from '../../workflow/db-setup-runner.js';
13
+ import { printHeader, printSection, printSuccess, printError, printWarning, printInfo, printKeyValue, startSpinner, succeedSpinner, failSpinner, } from '../output.js';
14
+ /**
15
+ * Prompt the user for a line of input
16
+ */
17
+ function promptLine(question) {
18
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
19
+ return new Promise((resolve) => {
20
+ rl.question(question, (answer) => {
21
+ rl.close();
22
+ resolve(answer.trim());
23
+ });
24
+ });
25
+ }
26
+ /**
27
+ * Display DB status from project state
28
+ */
29
+ async function handleDbStatus(directory) {
30
+ const projectDir = path.resolve(directory);
31
+ try {
32
+ const state = await loadProject(projectDir);
33
+ const dbConfig = state.dbConfig || { ...DEFAULT_DB_CONFIG, designed: false };
34
+ printHeader('Database Status');
35
+ printKeyValue('Designed', dbConfig.designed ? 'Yes' : 'No');
36
+ printKeyValue('Status', dbConfig.status);
37
+ printKeyValue('Mode', dbConfig.mode || 'not set');
38
+ printKeyValue('Vector Required', dbConfig.vectorRequired ? 'Yes' : 'No');
39
+ printKeyValue('Migrations Applied', String(dbConfig.migrationsApplied));
40
+ if (dbConfig.lastError) {
41
+ printSection('Last Error');
42
+ printError(dbConfig.lastError);
43
+ }
44
+ if (dbConfig.readinessCheckedAt) {
45
+ printKeyValue('Last Readiness Check', dbConfig.readinessCheckedAt);
46
+ }
47
+ // Show next steps based on status
48
+ console.log();
49
+ switch (dbConfig.status) {
50
+ case 'unconfigured':
51
+ printInfo('Run "popeye db configure" to set up database connection.');
52
+ break;
53
+ case 'configured':
54
+ printInfo('Run "popeye db apply" to apply migrations and finalize setup.');
55
+ break;
56
+ case 'error':
57
+ printWarning('Database setup failed. Run "popeye db apply" to retry.');
58
+ break;
59
+ case 'ready':
60
+ printSuccess('Database is ready.');
61
+ break;
62
+ case 'applying':
63
+ printInfo('Database setup is in progress...');
64
+ break;
65
+ }
66
+ }
67
+ catch (error) {
68
+ printError(error instanceof Error ? error.message : 'Failed to load project');
69
+ process.exit(1);
70
+ }
71
+ }
72
+ /**
73
+ * Configure database mode and connection URL
74
+ */
75
+ async function handleDbConfigure(directory) {
76
+ const projectDir = path.resolve(directory);
77
+ try {
78
+ const state = await loadProject(projectDir);
79
+ const dbConfig = state.dbConfig || { ...DEFAULT_DB_CONFIG };
80
+ printHeader('Database Configuration');
81
+ // Prompt for mode
82
+ console.log();
83
+ console.log(' Choose database mode:');
84
+ console.log(' 1. local_docker - PostgreSQL via Docker Compose (recommended for dev)');
85
+ console.log(' 2. managed - External managed database (Neon, Supabase, etc.)');
86
+ console.log();
87
+ const modeChoice = await promptLine(' Enter choice [1-2]: ');
88
+ let mode;
89
+ if (modeChoice === '2' || modeChoice === 'managed') {
90
+ mode = 'managed';
91
+ }
92
+ else {
93
+ mode = 'local_docker';
94
+ }
95
+ printKeyValue('Mode', mode);
96
+ // For managed mode, prompt for DATABASE_URL
97
+ if (mode === 'managed') {
98
+ const dbUrl = await promptLine(' Enter DATABASE_URL: ');
99
+ if (!dbUrl) {
100
+ printError('DATABASE_URL is required for managed mode.');
101
+ process.exit(1);
102
+ }
103
+ // Write DATABASE_URL to apps/backend/.env
104
+ const backendDir = resolveBackendDir(projectDir);
105
+ const envPath = path.join(backendDir, '.env');
106
+ let envContent = '';
107
+ try {
108
+ envContent = await fsPromises.readFile(envPath, 'utf-8');
109
+ }
110
+ catch {
111
+ // File doesn't exist yet
112
+ }
113
+ // Replace or add DATABASE_URL
114
+ if (envContent.includes('DATABASE_URL=')) {
115
+ envContent = envContent.replace(/DATABASE_URL=.*/, `DATABASE_URL=${dbUrl}`);
116
+ }
117
+ else {
118
+ envContent += `\nDATABASE_URL=${dbUrl}\n`;
119
+ }
120
+ await fsPromises.writeFile(envPath, envContent, 'utf-8');
121
+ printSuccess(`DATABASE_URL written to ${envPath}`);
122
+ }
123
+ else {
124
+ printInfo('Local Docker mode: PostgreSQL starts with "docker-compose up".');
125
+ printInfo('DATABASE_URL is set automatically in docker-compose.yml.');
126
+ }
127
+ // Update state: transition to configured
128
+ const newStatus = transitionDbStatus(dbConfig.status, 'configured');
129
+ await updateState(projectDir, {
130
+ dbConfig: {
131
+ ...dbConfig,
132
+ mode,
133
+ status: newStatus,
134
+ },
135
+ });
136
+ printSuccess('Database configured successfully.');
137
+ printInfo('Run "popeye db apply" to apply migrations.');
138
+ }
139
+ catch (error) {
140
+ printError(error instanceof Error ? error.message : 'Configuration failed');
141
+ process.exit(1);
142
+ }
143
+ }
144
+ /**
145
+ * Apply database setup (migrations, extensions, readiness)
146
+ */
147
+ async function handleDbApply(directory, options) {
148
+ const projectDir = path.resolve(directory);
149
+ try {
150
+ const state = await loadProject(projectDir);
151
+ const dbConfig = state.dbConfig || { ...DEFAULT_DB_CONFIG };
152
+ printHeader('Database Setup');
153
+ // Transition to applying
154
+ let currentStatus = dbConfig.status;
155
+ if (currentStatus === 'unconfigured') {
156
+ printError('Database not configured. Run "popeye db configure" first.');
157
+ process.exit(1);
158
+ }
159
+ startSpinner('Running database setup pipeline...');
160
+ const result = await runDbSetupPipeline(projectDir, {
161
+ skipSeed: options.skipSeed,
162
+ onStep: (step, status, message) => {
163
+ if (status === 'start') {
164
+ startSpinner(`[${step}] ${message}`);
165
+ }
166
+ else if (status === 'success') {
167
+ succeedSpinner(`[${step}] ${message}`);
168
+ }
169
+ else {
170
+ failSpinner(`[${step}] ${message}`);
171
+ }
172
+ },
173
+ });
174
+ // Print summary
175
+ console.log();
176
+ printSection('Setup Summary');
177
+ for (const step of result.steps) {
178
+ const icon = step.success ? ' [PASS]' : ' [FAIL]';
179
+ const duration = `(${step.durationMs}ms)`;
180
+ if (step.success) {
181
+ printSuccess(`${icon} ${step.step} ${duration}`);
182
+ }
183
+ else {
184
+ printError(`${icon} ${step.step} ${duration}`);
185
+ if (step.error) {
186
+ printError(` ${step.error}`);
187
+ }
188
+ }
189
+ }
190
+ printKeyValue('Total Duration', `${result.totalDurationMs}ms`);
191
+ // Update state with result
192
+ const newStatus = result.success ? 'ready' : 'error';
193
+ const now = new Date().toISOString();
194
+ await updateState(projectDir, {
195
+ dbConfig: {
196
+ ...dbConfig,
197
+ status: newStatus,
198
+ lastError: result.error,
199
+ readinessCheckedAt: result.success ? now : dbConfig.readinessCheckedAt,
200
+ },
201
+ });
202
+ if (result.success) {
203
+ console.log();
204
+ printSuccess('Database setup complete. Status: READY');
205
+ }
206
+ else {
207
+ console.log();
208
+ printError(`Database setup failed: ${result.error}`);
209
+ printInfo('Fix the issue and run "popeye db apply" to retry.');
210
+ process.exit(1);
211
+ }
212
+ }
213
+ catch (error) {
214
+ failSpinner('Setup failed');
215
+ printError(error instanceof Error ? error.message : 'Unknown error');
216
+ process.exit(1);
217
+ }
218
+ }
219
+ /**
220
+ * Create the db command with subcommands
221
+ */
222
+ export function createDbCommand() {
223
+ const db = new Command('db')
224
+ .description('Database management commands');
225
+ db.command('status')
226
+ .description('Show database configuration status')
227
+ .argument('[directory]', 'Project directory', '.')
228
+ .action(handleDbStatus);
229
+ db.command('configure')
230
+ .description('Configure database mode and connection')
231
+ .argument('[directory]', 'Project directory', '.')
232
+ .action(handleDbConfigure);
233
+ db.command('apply')
234
+ .description('Apply database setup (migrations, extensions, readiness)')
235
+ .argument('[directory]', 'Project directory', '.')
236
+ .option('--skip-seed', 'Skip seed step')
237
+ .action(handleDbApply);
238
+ return db;
239
+ }
240
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/cli/commands/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Doctor command
3
+ * Runs comprehensive readiness checks on database and project health
4
+ */
5
+ import { Command } from 'commander';
6
+ import type { ReadinessResult } from '../../types/database-runtime.js';
7
+ /**
8
+ * Run all readiness checks and return structured results
9
+ *
10
+ * @param projectDir - Project root directory
11
+ * @returns ReadinessResult with all check outcomes
12
+ */
13
+ export declare function runDoctorChecks(projectDir: string): Promise<ReadinessResult>;
14
+ /**
15
+ * Create the doctor command
16
+ */
17
+ export declare function createDoctorCommand(): Command;
18
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAavF;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA0MlF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAoC7C"}
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Doctor command
3
+ * Runs comprehensive readiness checks on database and project health
4
+ */
5
+ import { Command } from 'commander';
6
+ import path from 'node:path';
7
+ import { promises as fsPromises } from 'node:fs';
8
+ import { loadProject } from '../../state/index.js';
9
+ import { DEFAULT_DB_CONFIG } from '../../types/database.js';
10
+ import { readEnvFile, resolveBackendDir, } from '../../workflow/db-setup-runner.js';
11
+ import { printHeader, printSuccess, printError, printWarning, printInfo, } from '../output.js';
12
+ /**
13
+ * Run all readiness checks and return structured results
14
+ *
15
+ * @param projectDir - Project root directory
16
+ * @returns ReadinessResult with all check outcomes
17
+ */
18
+ export async function runDoctorChecks(projectDir) {
19
+ const checks = [];
20
+ // Check 1: Project state exists
21
+ try {
22
+ await loadProject(projectDir);
23
+ checks.push({
24
+ name: 'Project State',
25
+ passed: true,
26
+ message: 'Project state loaded successfully',
27
+ severity: 'critical',
28
+ });
29
+ }
30
+ catch {
31
+ checks.push({
32
+ name: 'Project State',
33
+ passed: false,
34
+ message: 'No valid project state found at this directory',
35
+ severity: 'critical',
36
+ });
37
+ return { healthy: false, checks, timestamp: new Date().toISOString() };
38
+ }
39
+ const state = await loadProject(projectDir);
40
+ const dbConfig = state.dbConfig || { ...DEFAULT_DB_CONFIG, designed: false };
41
+ const backendDir = resolveBackendDir(projectDir);
42
+ // Check 2: DB layer generated
43
+ checks.push({
44
+ name: 'DB Layer Generated',
45
+ passed: dbConfig.designed === true,
46
+ message: dbConfig.designed
47
+ ? 'Database layer files are present'
48
+ : 'Database layer not generated (dbConfig.designed = false)',
49
+ severity: 'critical',
50
+ });
51
+ // Check 3: Docker compose includes postgres service
52
+ let composeHasPostgres = false;
53
+ try {
54
+ const composePath = path.join(projectDir, 'docker-compose.yml');
55
+ const composeContent = await fsPromises.readFile(composePath, 'utf-8');
56
+ composeHasPostgres = composeContent.includes('postgres:') && composeContent.includes('pg_isready');
57
+ }
58
+ catch {
59
+ // File doesn't exist
60
+ }
61
+ checks.push({
62
+ name: 'Docker Compose Postgres',
63
+ passed: composeHasPostgres,
64
+ message: composeHasPostgres
65
+ ? 'docker-compose.yml includes postgres service with healthcheck'
66
+ : 'docker-compose.yml missing or does not include postgres service',
67
+ severity: 'warning',
68
+ });
69
+ // Check 4: .env has DATABASE_URL (not placeholder)
70
+ const env = await readEnvFile(path.join(backendDir, '.env'));
71
+ const dbUrl = env['DATABASE_URL'] || '';
72
+ const hasRealDbUrl = dbUrl.length > 0 && !dbUrl.includes('sqlite');
73
+ checks.push({
74
+ name: 'DATABASE_URL Configured',
75
+ passed: hasRealDbUrl,
76
+ message: hasRealDbUrl
77
+ ? 'DATABASE_URL is set to a PostgreSQL connection string'
78
+ : 'DATABASE_URL is missing or still using SQLite placeholder',
79
+ severity: 'critical',
80
+ });
81
+ // Check 5: DB connection reachable (only if URL is set)
82
+ if (hasRealDbUrl) {
83
+ try {
84
+ const { exec } = await import('node:child_process');
85
+ const { promisify } = await import('node:util');
86
+ const execAsync = promisify(exec);
87
+ const cmd = `cd "${backendDir}" && python3 -c "
88
+ import asyncio, asyncpg
89
+ async def check():
90
+ conn = await asyncpg.connect('${dbUrl.replace(/'/g, "\\'")}')
91
+ await conn.execute('SELECT 1')
92
+ await conn.close()
93
+ asyncio.run(check())
94
+ "`;
95
+ await execAsync(cmd, { timeout: 10000 });
96
+ checks.push({
97
+ name: 'DB Connection',
98
+ passed: true,
99
+ message: 'Database is reachable',
100
+ severity: 'critical',
101
+ });
102
+ }
103
+ catch {
104
+ checks.push({
105
+ name: 'DB Connection',
106
+ passed: false,
107
+ message: 'Cannot connect to database - check DATABASE_URL and server status',
108
+ severity: 'critical',
109
+ });
110
+ }
111
+ }
112
+ else {
113
+ checks.push({
114
+ name: 'DB Connection',
115
+ passed: false,
116
+ message: 'Skipped - DATABASE_URL not configured',
117
+ severity: 'info',
118
+ });
119
+ }
120
+ // Check 6: pgvector extension available (only if connected)
121
+ if (hasRealDbUrl && checks.find((c) => c.name === 'DB Connection')?.passed) {
122
+ try {
123
+ const { exec } = await import('node:child_process');
124
+ const { promisify } = await import('node:util');
125
+ const execAsync = promisify(exec);
126
+ const cmd = `cd "${backendDir}" && python3 -c "
127
+ import asyncio, asyncpg
128
+ async def check():
129
+ conn = await asyncpg.connect('${dbUrl.replace(/'/g, "\\'")}')
130
+ row = await conn.fetchrow(\"SELECT extname FROM pg_extension WHERE extname = 'vector'\")
131
+ await conn.close()
132
+ if row is None:
133
+ raise Exception('pgvector extension not found')
134
+ asyncio.run(check())
135
+ "`;
136
+ await execAsync(cmd, { timeout: 10000 });
137
+ checks.push({
138
+ name: 'pgvector Extension',
139
+ passed: true,
140
+ message: 'pgvector extension is installed',
141
+ severity: 'warning',
142
+ });
143
+ }
144
+ catch {
145
+ checks.push({
146
+ name: 'pgvector Extension',
147
+ passed: false,
148
+ message: 'pgvector extension not available - vector features will be disabled',
149
+ severity: 'warning',
150
+ });
151
+ }
152
+ }
153
+ // Check 7: Migrations applied
154
+ if (hasRealDbUrl && checks.find((c) => c.name === 'DB Connection')?.passed) {
155
+ try {
156
+ const { exec } = await import('node:child_process');
157
+ const { promisify } = await import('node:util');
158
+ const execAsync = promisify(exec);
159
+ const cmd = `cd "${backendDir}" && python3 -c "
160
+ import asyncio, asyncpg
161
+ async def check():
162
+ conn = await asyncpg.connect('${dbUrl.replace(/'/g, "\\'")}')
163
+ row = await conn.fetchrow('SELECT version_num FROM alembic_version LIMIT 1')
164
+ await conn.close()
165
+ if row is None:
166
+ raise Exception('No migrations applied')
167
+ asyncio.run(check())
168
+ "`;
169
+ await execAsync(cmd, { timeout: 10000 });
170
+ checks.push({
171
+ name: 'Migrations Applied',
172
+ passed: true,
173
+ message: 'Alembic migrations have been applied',
174
+ severity: 'critical',
175
+ });
176
+ }
177
+ catch {
178
+ checks.push({
179
+ name: 'Migrations Applied',
180
+ passed: false,
181
+ message: 'No migrations applied - run "popeye db apply" or "alembic upgrade head"',
182
+ severity: 'critical',
183
+ });
184
+ }
185
+ }
186
+ // Check 8: /health/db endpoint (optional - only if server is running)
187
+ try {
188
+ const response = await fetch('http://localhost:8000/health/db', {
189
+ signal: AbortSignal.timeout(3000),
190
+ });
191
+ checks.push({
192
+ name: 'Health Endpoint',
193
+ passed: response.status === 200,
194
+ message: response.status === 200
195
+ ? '/health/db returns 200 OK'
196
+ : `/health/db returns ${response.status}`,
197
+ severity: 'info',
198
+ });
199
+ }
200
+ catch {
201
+ checks.push({
202
+ name: 'Health Endpoint',
203
+ passed: false,
204
+ message: 'Backend server not running (optional check)',
205
+ severity: 'info',
206
+ });
207
+ }
208
+ const healthy = checks
209
+ .filter((c) => c.severity === 'critical')
210
+ .every((c) => c.passed);
211
+ return {
212
+ healthy,
213
+ checks,
214
+ timestamp: new Date().toISOString(),
215
+ };
216
+ }
217
+ /**
218
+ * Create the doctor command
219
+ */
220
+ export function createDoctorCommand() {
221
+ const doctor = new Command('doctor')
222
+ .description('Run comprehensive database and project readiness checks')
223
+ .argument('[directory]', 'Project directory', '.')
224
+ .action(async (directory) => {
225
+ const projectDir = path.resolve(directory);
226
+ printHeader('Popeye Doctor');
227
+ console.log();
228
+ const result = await runDoctorChecks(projectDir);
229
+ for (const check of result.checks) {
230
+ const statusLabel = check.passed ? '[PASS]' : check.severity === 'info' ? '[SKIP]' : '[FAIL]';
231
+ if (check.passed) {
232
+ printSuccess(` ${statusLabel} ${check.name}: ${check.message}`);
233
+ }
234
+ else if (check.severity === 'info') {
235
+ printInfo(` ${statusLabel} ${check.name}: ${check.message}`);
236
+ }
237
+ else if (check.severity === 'warning') {
238
+ printWarning(` ${statusLabel} ${check.name}: ${check.message}`);
239
+ }
240
+ else {
241
+ printError(` ${statusLabel} ${check.name}: ${check.message}`);
242
+ }
243
+ }
244
+ console.log();
245
+ if (result.healthy) {
246
+ printSuccess('All critical checks passed. Database is healthy.');
247
+ }
248
+ else {
249
+ printError('Some critical checks failed. Fix the issues above and re-run.');
250
+ process.exit(1);
251
+ }
252
+ });
253
+ return doctor;
254
+ }
255
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EACL,WAAW,EACX,iBAAiB,GAClB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,SAAS,GACV,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,MAAM,MAAM,GAAqB,EAAE,CAAC;IAEpC,gCAAgC;IAChC,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,mCAAmC;YAC5C,QAAQ,EAAE,UAAU;SACrB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,gDAAgD;YACzD,QAAQ,EAAE,UAAU;SACrB,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IACzE,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,GAAG,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7E,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAEjD,8BAA8B;IAC9B,MAAM,CAAC,IAAI,CAAC;QACV,IAAI,EAAE,oBAAoB;QAC1B,MAAM,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI;QAClC,OAAO,EAAE,QAAQ,CAAC,QAAQ;YACxB,CAAC,CAAC,kCAAkC;YACpC,CAAC,CAAC,0DAA0D;QAC9D,QAAQ,EAAE,UAAU;KACrB,CAAC,CAAC;IAEH,oDAAoD;IACpD,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAChE,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACvE,kBAAkB,GAAG,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACrG,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC;QACV,IAAI,EAAE,yBAAyB;QAC/B,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kBAAkB;YACzB,CAAC,CAAC,+DAA+D;YACjE,CAAC,CAAC,iEAAiE;QACrE,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IAEH,mDAAmD;IACnD,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnE,MAAM,CAAC,IAAI,CAAC;QACV,IAAI,EAAE,yBAAyB;QAC/B,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,YAAY;YACnB,CAAC,CAAC,uDAAuD;YACzD,CAAC,CAAC,2DAA2D;QAC/D,QAAQ,EAAE,UAAU;KACrB,CAAC,CAAC;IAEH,wDAAwD;IACxD,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACpD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAChD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG,OAAO,UAAU;;;oCAGC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;;;;EAI5D,CAAC;YACG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,uBAAuB;gBAChC,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,mEAAmE;gBAC5E,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,uCAAuC;YAChD,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;IACL,CAAC;IAED,4DAA4D;IAC5D,IAAI,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3E,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACpD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAChD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG,OAAO,UAAU;;;oCAGC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;;;;;;EAM5D,CAAC;YACG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,oBAAoB;gBAC1B,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,iCAAiC;gBAC1C,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,oBAAoB;gBAC1B,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,qEAAqE;gBAC9E,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,IAAI,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3E,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACpD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAChD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG,OAAO,UAAU;;;oCAGC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;;;;;;EAM5D,CAAC;YACG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,oBAAoB;gBAC1B,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,sCAAsC;gBAC/C,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,oBAAoB;gBAC1B,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,yEAAyE;gBAClF,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iCAAiC,EAAE;YAC9D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,QAAQ,CAAC,MAAM,KAAK,GAAG;YAC/B,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,GAAG;gBAC9B,CAAC,CAAC,2BAA2B;gBAC7B,CAAC,CAAC,sBAAsB,QAAQ,CAAC,MAAM,EAAE;YAC3C,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,6CAA6C;YACtD,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,MAAM;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC;SACxC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO;QACL,OAAO;QACP,MAAM;QACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;SACjC,WAAW,CAAC,yDAAyD,CAAC;SACtE,QAAQ,CAAC,aAAa,EAAE,mBAAmB,EAAE,GAAG,CAAC;SACjD,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAE3C,WAAW,CAAC,eAAe,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;QAEjD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YAE9F,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,YAAY,CAAC,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnE,CAAC;iBAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gBACrC,SAAS,CAAC,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACxC,YAAY,CAAC,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,YAAY,CAAC,kDAAkD,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,+DAA+D,CAAC,CAAC;YAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -7,4 +7,7 @@ export { createCreateCommand } from './create.js';
7
7
  export { createStatusCommand, createValidateCommand, createSummaryCommand } from './status.js';
8
8
  export { createResumeCommand, createResetCommand, createCancelCommand } from './resume.js';
9
9
  export { createConfigCommand } from './config.js';
10
+ export { createDbCommand } from './db.js';
11
+ export { createDoctorCommand } from './doctor.js';
12
+ export { createReviewCommand } from './review.js';
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -7,4 +7,7 @@ export { createCreateCommand } from './create.js';
7
7
  export { createStatusCommand, createValidateCommand, createSummaryCommand } from './status.js';
8
8
  export { createResumeCommand, createResetCommand, createCancelCommand } from './resume.js';
9
9
  export { createConfigCommand } from './config.js';
10
+ export { createDbCommand } from './db.js';
11
+ export { createDoctorCommand } from './doctor.js';
12
+ export { createReviewCommand } from './review.js';
10
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * CLI command: popeye review
3
+ *
4
+ * Runs a post-build audit/review of the project, producing a structured
5
+ * report with findings and optional recovery tasks.
6
+ *
7
+ * Pattern follows doctor.ts command factory.
8
+ */
9
+ import { Command } from 'commander';
10
+ import type { AuditModeResult } from '../../types/audit.js';
11
+ /**
12
+ * Execute the audit and print results to the console.
13
+ *
14
+ * @param projectDir - Absolute path to the project directory.
15
+ * @param options - CLI options.
16
+ * @returns The audit result.
17
+ */
18
+ export declare function runReview(projectDir: string, options?: {
19
+ depth?: number;
20
+ strict?: boolean;
21
+ format?: 'json' | 'md' | 'both';
22
+ recover?: boolean;
23
+ target?: string;
24
+ }): Promise<AuditModeResult>;
25
+ /**
26
+ * Create the `popeye review` CLI command.
27
+ *
28
+ * @returns Commander command instance.
29
+ */
30
+ export declare function createReviewCommand(): Command;
31
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/review.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,sBAAsB,CAAC;AAM3E;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACZ,GACL,OAAO,CAAC,eAAe,CAAC,CAoG1B;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAgC7C"}