@friggframework/devtools 2.0.0--canary.545.e256e95.0 → 2.0.0--canary.553.dc5f898.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 (129) hide show
  1. package/frigg-cli/README.md +1 -1
  2. package/frigg-cli/__tests__/unit/commands/build.test.js +1 -1
  3. package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
  4. package/frigg-cli/__tests__/unit/commands/install.test.js +19 -23
  5. package/frigg-cli/__tests__/unit/dependencies.test.js +2 -2
  6. package/frigg-cli/build-command/index.js +11 -123
  7. package/frigg-cli/deploy-command/index.js +1 -83
  8. package/frigg-cli/doctor-command/index.js +16 -37
  9. package/frigg-cli/generate-iam-command.js +1 -21
  10. package/frigg-cli/index.js +6 -21
  11. package/frigg-cli/index.test.js +2 -7
  12. package/frigg-cli/init-command/backend-first-handler.js +42 -124
  13. package/frigg-cli/init-command/index.js +1 -2
  14. package/frigg-cli/init-command/template-handler.js +3 -13
  15. package/frigg-cli/install-command/backend-js.js +3 -3
  16. package/frigg-cli/install-command/environment-variables.js +19 -16
  17. package/frigg-cli/install-command/environment-variables.test.js +13 -12
  18. package/frigg-cli/install-command/index.js +9 -14
  19. package/frigg-cli/install-command/integration-file.js +3 -3
  20. package/frigg-cli/install-command/logger.js +12 -0
  21. package/frigg-cli/install-command/validate-package.js +9 -5
  22. package/frigg-cli/jest.config.js +1 -4
  23. package/frigg-cli/repair-command/index.js +128 -121
  24. package/frigg-cli/start-command/index.js +2 -324
  25. package/frigg-cli/ui-command/index.js +36 -58
  26. package/frigg-cli/utils/repo-detection.js +37 -85
  27. package/infrastructure/create-frigg-infrastructure.js +0 -93
  28. package/infrastructure/docs/iam-policy-templates.md +1 -1
  29. package/infrastructure/domains/integration/integration-builder.js +3 -2
  30. package/infrastructure/domains/integration/integration-builder.test.js +54 -2
  31. package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
  32. package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
  33. package/infrastructure/domains/shared/resource-discovery.js +5 -5
  34. package/infrastructure/domains/shared/types/app-definition.js +0 -35
  35. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  36. package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
  37. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  38. package/infrastructure/infrastructure-composer.js +0 -2
  39. package/infrastructure/infrastructure-composer.test.js +6 -5
  40. package/management-ui/README.md +109 -245
  41. package/package.json +7 -8
  42. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  43. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  44. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  45. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  46. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  47. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  48. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  49. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  50. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  51. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
  52. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  53. package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
  54. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  55. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  56. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  57. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  58. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  59. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  60. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  61. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  62. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  63. package/frigg-cli/container.js +0 -172
  64. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  65. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  66. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  67. package/frigg-cli/domain/entities/Integration.js +0 -198
  68. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  69. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  70. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  71. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  72. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  73. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  74. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  75. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  76. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  77. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  78. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  79. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  80. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  81. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  82. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  83. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  84. package/frigg-cli/package-lock.json +0 -16226
  85. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  86. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  87. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  88. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  89. package/frigg-cli/templates/backend/.env.example +0 -62
  90. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  91. package/frigg-cli/templates/backend/.prettierrc +0 -6
  92. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  93. package/frigg-cli/templates/backend/index.js +0 -96
  94. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  95. package/frigg-cli/templates/backend/jest.config.js +0 -17
  96. package/frigg-cli/templates/backend/package.json +0 -50
  97. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  98. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  99. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  100. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  101. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  102. package/frigg-cli/templates/backend/test/setup.js +0 -30
  103. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  104. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  105. package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
  106. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  107. package/frigg-cli/utils/output.js +0 -382
  108. package/frigg-cli/utils/provider-helper.js +0 -75
  109. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  110. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  111. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  112. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  113. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  114. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  115. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  116. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  117. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  118. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  119. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  120. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  121. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  122. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  123. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  124. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -145
  125. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
  126. package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
  127. package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
  128. package/infrastructure/domains/admin-scripts/index.js +0 -5
  129. package/infrastructure/jest.config.js +0 -16
@@ -1,6 +1,5 @@
1
1
  const { spawn } = require('node:child_process');
2
2
  const path = require('node:path');
3
- const fs = require('node:fs');
4
3
  const dotenv = require('dotenv');
5
4
  const chalk = require('chalk');
6
5
  const {
@@ -14,12 +13,6 @@ const {
14
13
  getPrismaClientNotGeneratedError
15
14
  } = require('../utils/error-messages');
16
15
 
17
- // Import new pre-flight infrastructure
18
- const { DockerAdapter } = require('./infrastructure/DockerAdapter');
19
- const { DatabaseAdapter } = require('./infrastructure/DatabaseAdapter');
20
- const { RunPreflightChecksUseCase } = require('./application/RunPreflightChecksUseCase');
21
- const { InteractivePromptAdapter } = require('./presentation/InteractivePromptAdapter');
22
-
23
16
  async function startCommand(options) {
24
17
  if (options.verbose) {
25
18
  console.log('Verbose mode enabled');
@@ -32,26 +25,7 @@ async function startCommand(options) {
32
25
  const envPath = path.join(process.cwd(), '.env');
33
26
  dotenv.config({ path: envPath });
34
27
 
35
- const projectPath = process.cwd();
36
-
37
- // Run interactive pre-flight checks if enabled (default: true)
38
- if (options.interactive !== false) {
39
- try {
40
- const preflightPassed = await runInteractivePreflightChecks(projectPath, options);
41
- if (!preflightPassed) {
42
- console.error(chalk.red('\n❌ Pre-flight checks failed'));
43
- console.error(chalk.gray('Fix the issues above before starting the application.\n'));
44
- process.exit(1);
45
- }
46
- } catch (error) {
47
- if (options.verbose) {
48
- console.error(chalk.yellow(`Pre-flight check error: ${error.message}`));
49
- }
50
- // Fall back to legacy checks if new system fails
51
- }
52
- }
53
-
54
- // Legacy pre-flight database checks (still run for Prisma validation)
28
+ // Pre-flight database checks
55
29
  try {
56
30
  await performDatabaseChecks(options.verbose);
57
31
  } catch (error) {
@@ -60,16 +34,9 @@ async function startCommand(options) {
60
34
  process.exit(1);
61
35
  }
62
36
 
63
- console.log(chalk.green('✓ Pre-flight checks passed\n'));
37
+ console.log(chalk.green('✓ Database checks passed\n'));
64
38
  console.log('Starting backend and optional frontend...');
65
39
 
66
- // Check if the app uses a non-AWS provider
67
- const providerResult = loadProviderIfConfigured();
68
- if (providerResult) {
69
- return startWithProvider(providerResult, options);
70
- }
71
-
72
- // Default: AWS local development via serverless-offline
73
40
  // Suppress AWS SDK warning message about maintenance mode
74
41
  process.env.AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE = '1';
75
42
  // Skip AWS discovery for local development
@@ -116,295 +83,6 @@ async function startCommand(options) {
116
83
  });
117
84
  }
118
85
 
119
- /**
120
- * Check if the appDefinition specifies a non-AWS provider and resolve it.
121
- * Returns null for AWS (default) so the caller falls through to existing behavior.
122
- */
123
- function loadProviderIfConfigured() {
124
- try {
125
- const { loadProviderForCli } = require('../utils/provider-helper');
126
- const result = loadProviderForCli();
127
- if (result && result.provider) {
128
- return result;
129
- }
130
- } catch {
131
- // Provider helper not available or appDefinition not found — fall through
132
- }
133
- return null;
134
- }
135
-
136
- /**
137
- * Start local dev server using the provider's recommended approach.
138
- * Each provider has a different local dev story:
139
- * - Netlify: `netlify dev` (reads netlify.toml, serves functions locally)
140
- * - AWS: `osls offline` (serverless-offline, handled by default path above)
141
- */
142
- function startWithProvider({ provider, providerName }, options) {
143
- const backendPath = path.resolve(process.cwd());
144
-
145
- // Provider-specific dev server commands
146
- const DEV_COMMANDS = {
147
- netlify: { command: 'netlify', args: ['dev'] },
148
- };
149
-
150
- const devCmd = DEV_COMMANDS[providerName];
151
- if (!devCmd) {
152
- console.error(chalk.red(
153
- `Provider '${providerName}' does not have a local dev server configured.\n` +
154
- ` Supported providers for local dev: ${Object.keys(DEV_COMMANDS).join(', ')}, aws`
155
- ));
156
- process.exit(1);
157
- }
158
-
159
- console.log(chalk.blue(`Starting local dev server (${providerName})...`));
160
-
161
- const args = [...devCmd.args];
162
- if (options.verbose) {
163
- console.log(`Executing command: ${devCmd.command} ${args.join(' ')}`);
164
- console.log(`Working directory: ${backendPath}`);
165
- }
166
-
167
- const childProcess = spawn(devCmd.command, args, {
168
- cwd: backendPath,
169
- stdio: 'inherit',
170
- env: { ...process.env },
171
- });
172
-
173
- childProcess.on('error', (error) => {
174
- if (error.code === 'ENOENT') {
175
- console.error(chalk.red(
176
- `'${devCmd.command}' not found. Install it with: npm install -g ${devCmd.command}-cli`
177
- ));
178
- } else {
179
- console.error(`Error executing command: ${error.message}`);
180
- }
181
- });
182
-
183
- childProcess.on('close', (code) => {
184
- if (code !== 0) {
185
- console.log(`Child process exited with code ${code}`);
186
- }
187
- });
188
- }
189
-
190
- /**
191
- * Run interactive pre-flight checks with resolution prompts
192
- * @param {string} projectPath - Path to the Frigg project
193
- * @param {object} options - Command options
194
- * @returns {Promise<boolean>} True if all checks pass or were resolved
195
- */
196
- async function runInteractivePreflightChecks(projectPath, options) {
197
- // Create adapters and use case
198
- const dockerAdapter = new DockerAdapter();
199
- const databaseAdapter = new DatabaseAdapter();
200
- const preflightUseCase = new RunPreflightChecksUseCase({
201
- dockerAdapter,
202
- databaseAdapter
203
- });
204
-
205
- // Create prompt adapter based on mode (terminal or IPC)
206
- const promptMode = options.ipc ? 'ipc' : 'terminal';
207
- const promptAdapter = InteractivePromptAdapter.create({ mode: promptMode });
208
-
209
- if (options.verbose) {
210
- console.log(chalk.gray('Running pre-flight checks...'));
211
- }
212
-
213
- // Track which checks we've already processed to avoid infinite loops
214
- const processedChecks = new Set();
215
-
216
- // Keep running checks and resolving issues until all pass or no more can be resolved
217
- let maxIterations = 10; // Safety limit to prevent infinite loops
218
- while (maxIterations > 0) {
219
- maxIterations--;
220
-
221
- // Run checks
222
- const result = await preflightUseCase.execute({ projectPath });
223
-
224
- // If all passed, we're done
225
- if (result.allPassed) {
226
- return true;
227
- }
228
-
229
- // Get resolvable checks that we haven't already processed
230
- const resolvableChecks = preflightUseCase.getResolvableChecks(result)
231
- .filter(check => !processedChecks.has(check.name));
232
-
233
- // If no new resolvable checks, show failures and exit
234
- if (resolvableChecks.length === 0) {
235
- const failedChecks = result.checks.filter(c => c.status === 'failed');
236
- for (const check of failedChecks) {
237
- console.log(chalk.red(` ✗ ${check.name}: ${check.message}`));
238
- if (check.resolution?.instructions) {
239
- console.log(chalk.gray(` ${check.resolution.instructions}`));
240
- }
241
- }
242
- return false;
243
- }
244
-
245
- // Process the first resolvable check
246
- const check = resolvableChecks[0];
247
- processedChecks.add(check.name);
248
-
249
- // Display the failure
250
- console.log(chalk.yellow(`\n⚠️ ${check.message}`));
251
-
252
- // Only prompt if check is resolvable
253
- if (!check.canResolve) {
254
- if (check.resolution?.instructions) {
255
- console.log(chalk.gray(` ${check.resolution.instructions}`));
256
- }
257
- continue;
258
- }
259
-
260
- // Ask user if they want to resolve
261
- const response = await promptAdapter.promptForResolution(check);
262
-
263
- if (!response.shouldResolve) {
264
- console.log(chalk.gray(' Skipping resolution'));
265
- // User declined, show remaining failures and exit
266
- const failedChecks = result.checks.filter(c => c.status === 'failed');
267
- for (const failedCheck of failedChecks) {
268
- if (failedCheck.name !== check.name) {
269
- console.log(chalk.red(` ✗ ${failedCheck.name}: ${failedCheck.message}`));
270
- }
271
- }
272
- return false;
273
- }
274
-
275
- // Execute the resolution
276
- const resolved = await executeResolution(check, dockerAdapter, options);
277
-
278
- if (!resolved) {
279
- return false;
280
- }
281
-
282
- // Loop will continue and re-run checks
283
- }
284
-
285
- // If we exhausted iterations, something went wrong
286
- console.log(chalk.yellow(' ⚠️ Pre-flight check loop limit reached'));
287
- return false;
288
- }
289
-
290
- /**
291
- * Execute a resolution action
292
- * @param {object} check - The check that failed
293
- * @param {DockerAdapter} dockerAdapter - Docker adapter
294
- * @param {object} options - Command options
295
- * @returns {Promise<boolean>} True if resolution succeeded
296
- */
297
- async function executeResolution(check, dockerAdapter, options) {
298
- const { resolution } = check;
299
-
300
- switch (resolution.type) {
301
- case 'start_docker':
302
- console.log(chalk.blue(' Starting Docker Desktop...'));
303
- const dockerResult = await dockerAdapter.startDockerDesktop();
304
- if (!dockerResult.success) {
305
- console.error(chalk.red(` Failed to start Docker: ${dockerResult.error}`));
306
- return false;
307
- }
308
- // Wait for Docker to be ready
309
- console.log(chalk.gray(' Waiting for Docker to start...'));
310
- const isReady = await dockerAdapter.waitForDockerReady({
311
- maxAttempts: 60,
312
- intervalMs: 1000
313
- });
314
- if (!isReady) {
315
- console.error(chalk.red(' Docker did not start in time'));
316
- return false;
317
- }
318
- console.log(chalk.green(' ✓ Docker is now running'));
319
- return true;
320
-
321
- case 'start_docker_compose':
322
- console.log(chalk.blue(' Starting Docker Compose services...'));
323
- const composeResult = await dockerAdapter.startDockerCompose(resolution.composePath);
324
- if (!composeResult.success) {
325
- console.error(chalk.red(` Failed to start services: ${composeResult.error}`));
326
- return false;
327
- }
328
- console.log(chalk.green(' ✓ Docker Compose services started'));
329
- // Poll LocalStack health endpoint until services are ready
330
- console.log(chalk.gray(' Waiting for LocalStack to initialize...'));
331
- const localstackResult = await dockerAdapter.waitForLocalStack({
332
- maxAttempts: 30,
333
- intervalMs: 2000
334
- });
335
- if (localstackResult.ready) {
336
- console.log(chalk.green(' ✓ LocalStack services ready'));
337
- if (options.verbose && localstackResult.services) {
338
- console.log(chalk.gray(` Services: ${Object.keys(localstackResult.services).join(', ')}`));
339
- }
340
- } else {
341
- console.log(chalk.yellow(' ⚠️ LocalStack may not be fully ready'));
342
- if (localstackResult.error) {
343
- console.log(chalk.gray(` ${localstackResult.error}`));
344
- }
345
- // Continue anyway - the service might still work
346
- }
347
- return true;
348
-
349
- case 'create_env':
350
- // Try to copy .env.example to .env
351
- const projectPath = process.cwd();
352
- const envExamplePath = path.join(projectPath, '.env.example');
353
- const envPath = path.join(projectPath, '.env');
354
-
355
- if (fs.existsSync(envExamplePath)) {
356
- try {
357
- fs.copyFileSync(envExamplePath, envPath);
358
- console.log(chalk.green(' ✓ Created .env file from .env.example'));
359
- console.log(chalk.yellow(' ⚠️ Please edit .env to set your DATABASE_URL'));
360
-
361
- // Reload environment variables from the new .env file
362
- dotenv.config({ path: envPath, override: true });
363
-
364
- // Check if DATABASE_URL is now set
365
- if (process.env.DATABASE_URL && process.env.DATABASE_URL.trim() !== '') {
366
- console.log(chalk.green(' ✓ DATABASE_URL is now configured'));
367
- return true;
368
- } else {
369
- console.log(chalk.yellow(' ⚠️ DATABASE_URL is still not set in .env'));
370
- console.log(chalk.gray(' Please edit .env and set DATABASE_URL, then try again'));
371
- return false;
372
- }
373
- } catch (err) {
374
- console.error(chalk.red(` Failed to create .env: ${err.message}`));
375
- return false;
376
- }
377
- } else {
378
- console.log(chalk.yellow(' No .env.example file found'));
379
- console.log(chalk.gray(' Please create a .env file manually with DATABASE_URL'));
380
- return false;
381
- }
382
-
383
- case 'run_migrations':
384
- console.log(chalk.blue(' Running PostgreSQL migrations...'));
385
- const databaseAdapter = new DatabaseAdapter();
386
- const migrationProjectPath = process.cwd();
387
-
388
- // Use deploy mode (default) - non-interactive, applies existing migrations
389
- const migrateResult = await databaseAdapter.runMigrations(migrationProjectPath);
390
-
391
- if (!migrateResult.success) {
392
- console.error(chalk.red(` Failed to run migrations: ${migrateResult.error}`));
393
- console.log(chalk.gray(' Try running "frigg db:setup" manually'));
394
- return false;
395
- }
396
-
397
- console.log(chalk.green(' ✓ Database migrations applied successfully'));
398
- return true;
399
-
400
- default:
401
- if (options.verbose) {
402
- console.log(chalk.gray(` Unknown resolution type: ${resolution.type}`));
403
- }
404
- return false;
405
- }
406
- }
407
-
408
86
  /**
409
87
  * Performs pre-flight database validation checks
410
88
  * @param {boolean} verbose - Enable verbose output
@@ -2,19 +2,16 @@ const open = require('open');
2
2
  const chalk = require('chalk');
3
3
  const path = require('path');
4
4
  const ProcessManager = require('../utils/process-manager');
5
- const {
6
- getCurrentRepositoryInfo,
7
- discoverFriggRepositories,
5
+ const {
6
+ getCurrentRepositoryInfo,
7
+ discoverFriggRepositories,
8
8
  promptRepositorySelection,
9
- formatRepositoryInfo
9
+ formatRepositoryInfo
10
10
  } = require('../utils/repo-detection');
11
11
 
12
12
  async function uiCommand(options) {
13
- const { port = 3210, open: shouldOpen = true, repo: specifiedRepo, dev = false } = options;
14
-
15
- // Fix: --no-open should set open to false, not use the default true
16
- const shouldOpenBrowser = options.open !== false;
17
-
13
+ const { port = 3001, open: shouldOpen = true, repo: specifiedRepo, dev = false } = options;
14
+
18
15
  let targetRepo = null;
19
16
  let workingDirectory = process.cwd();
20
17
 
@@ -28,7 +25,7 @@ async function uiCommand(options) {
28
25
  // Check if we're already in a Frigg repository
29
26
  console.log(chalk.blue('Detecting Frigg repository...'));
30
27
  const currentRepo = await getCurrentRepositoryInfo();
31
-
28
+
32
29
  if (currentRepo) {
33
30
  console.log(chalk.green(`✓ Found Frigg repository: ${formatRepositoryInfo(currentRepo)}`));
34
31
  if (currentRepo.currentSubPath) {
@@ -40,40 +37,40 @@ async function uiCommand(options) {
40
37
  // Discover Frigg repositories
41
38
  console.log(chalk.yellow('Current directory is not a Frigg repository.'));
42
39
  console.log(chalk.blue('Searching for Frigg repositories...'));
43
-
40
+
44
41
  const discoveredRepos = await discoverFriggRepositories();
45
-
42
+
46
43
  if (discoveredRepos.length === 0) {
47
44
  console.log(chalk.red('No Frigg repositories found. Please create one first.'));
48
45
  process.exit(1);
49
46
  }
50
-
47
+
51
48
  // For UI command, we'll let the UI handle repository selection
52
49
  // Set a placeholder and pass the discovered repos via environment
53
- targetRepo = {
54
- name: 'Multiple Repositories Available',
50
+ targetRepo = {
51
+ name: 'Multiple Repositories Available',
55
52
  path: process.cwd(),
56
53
  isMultiRepo: true,
57
54
  availableRepos: discoveredRepos
58
55
  };
59
56
  workingDirectory = process.cwd();
60
-
57
+
61
58
  console.log(chalk.blue(`Found ${discoveredRepos.length} Frigg repositories. You'll be able to select one in the UI.`));
62
59
  }
63
60
  }
64
61
 
65
62
  console.log(chalk.blue('🚀 Starting Frigg Management UI...'));
66
-
63
+
67
64
  const processManager = new ProcessManager();
68
-
65
+
69
66
  try {
70
67
  const managementUiPath = path.join(__dirname, '../../management-ui');
71
-
68
+
72
69
  // Check if we're in development mode
73
70
  // For CLI usage, we prefer development mode unless explicitly set to production
74
71
  const fs = require('fs');
75
72
  const isDevelopment = dev || process.env.NODE_ENV !== 'production';
76
-
73
+
77
74
  if (isDevelopment) {
78
75
  const env = {
79
76
  ...process.env,
@@ -83,15 +80,15 @@ async function uiCommand(options) {
83
80
  REPOSITORY_INFO: JSON.stringify(targetRepo),
84
81
  AVAILABLE_REPOSITORIES: targetRepo.isMultiRepo ? JSON.stringify(targetRepo.availableRepos) : null
85
82
  };
86
-
87
- // Start backend server with nodemon for auto-restart
83
+
84
+ // Start backend server
88
85
  processManager.spawnProcess(
89
86
  'backend',
90
87
  'npm',
91
- ['run', 'server:dev'],
88
+ ['run', 'server'],
92
89
  { cwd: managementUiPath, env }
93
90
  );
94
-
91
+
95
92
  // Start frontend dev server
96
93
  processManager.spawnProcess(
97
94
  'frontend',
@@ -99,71 +96,52 @@ async function uiCommand(options) {
99
96
  ['run', 'dev'],
100
97
  { cwd: managementUiPath, env }
101
98
  );
102
-
103
- // Wait for backend to be ready by polling health endpoint
104
- const maxAttempts = 20;
105
- const delayMs = 250;
106
- let backendReady = false;
107
-
108
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
109
- try {
110
- const response = await fetch(`http://localhost:${port}/api/health`);
111
- if (response.ok) {
112
- backendReady = true;
113
- break;
114
- }
115
- } catch (err) {
116
- // Backend not ready yet, wait and retry
117
- }
118
- await new Promise(resolve => setTimeout(resolve, delayMs));
119
- }
120
-
121
- if (!backendReady) {
122
- console.warn('⚠️ Backend health check timed out, but continuing anyway...');
123
- }
124
-
99
+
100
+ // Wait for servers to start
101
+ await new Promise(resolve => setTimeout(resolve, 2000));
102
+
125
103
  // Display clean status
126
104
  processManager.printStatus(
127
105
  'http://localhost:5173',
128
106
  `http://localhost:${port}`,
129
107
  targetRepo.name
130
108
  );
131
-
109
+
132
110
  // Open browser if requested
133
- if (shouldOpenBrowser) {
111
+ if (shouldOpen) {
134
112
  setTimeout(() => {
135
113
  open('http://localhost:5173');
136
114
  }, 1000);
137
115
  }
138
-
116
+
139
117
  } else {
140
118
  // Production mode - just start the backend server
141
119
  const { FriggManagementServer } = await import('../../management-ui/server/index.js');
142
-
143
- const server = new FriggManagementServer({
144
- port,
120
+
121
+ const server = new FriggManagementServer({
122
+ port,
145
123
  projectRoot: workingDirectory,
146
124
  repositoryInfo: targetRepo,
147
125
  availableRepositories: targetRepo.isMultiRepo ? targetRepo.availableRepos : null
148
126
  });
149
127
  await server.start();
150
-
128
+
151
129
  processManager.printStatus(
152
130
  `http://localhost:${port}`,
153
131
  `http://localhost:${port}/api`,
154
132
  targetRepo.name
155
133
  );
156
-
157
- if (shouldOpenBrowser) {
134
+
135
+ if (shouldOpen) {
158
136
  setTimeout(() => {
159
137
  open(`http://localhost:${port}`);
160
138
  }, 1000);
161
139
  }
162
140
  }
163
-
141
+
164
142
  // Keep the process running
165
143
  process.stdin.resume();
166
-
144
+
167
145
  } catch (error) {
168
146
  console.error(chalk.red('Failed to start Management UI:'), error.message);
169
147
  if (error.code === 'EADDRINUSE') {