@friggframework/devtools 2.0.0--canary.545.69acce5.0 → 2.0.0--canary.549.b074651.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 (127) 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/networking/vpc-builder.test.js +4 -2
  30. package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
  31. package/infrastructure/domains/shared/resource-discovery.js +5 -5
  32. package/infrastructure/domains/shared/types/app-definition.js +0 -21
  33. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  34. package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
  35. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  36. package/infrastructure/infrastructure-composer.js +0 -2
  37. package/infrastructure/infrastructure-composer.test.js +2 -2
  38. package/management-ui/README.md +109 -245
  39. package/package.json +7 -8
  40. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  41. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  42. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  43. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  44. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  45. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  46. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  47. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  48. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  49. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
  50. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  51. package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
  52. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  53. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  54. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  55. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  56. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  57. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  58. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  59. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  60. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  61. package/frigg-cli/container.js +0 -172
  62. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  63. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  64. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  65. package/frigg-cli/domain/entities/Integration.js +0 -198
  66. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  67. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  68. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  69. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  70. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  71. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  72. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  73. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  74. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  75. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  76. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  77. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  78. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  79. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  80. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  81. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  82. package/frigg-cli/package-lock.json +0 -16226
  83. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  84. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  85. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  86. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  87. package/frigg-cli/templates/backend/.env.example +0 -62
  88. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  89. package/frigg-cli/templates/backend/.prettierrc +0 -6
  90. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  91. package/frigg-cli/templates/backend/index.js +0 -96
  92. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  93. package/frigg-cli/templates/backend/jest.config.js +0 -17
  94. package/frigg-cli/templates/backend/package.json +0 -50
  95. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  96. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  97. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  98. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  99. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  100. package/frigg-cli/templates/backend/test/setup.js +0 -30
  101. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  102. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  103. package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
  104. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  105. package/frigg-cli/utils/output.js +0 -382
  106. package/frigg-cli/utils/provider-helper.js +0 -75
  107. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  108. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  109. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  110. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  111. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  112. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  113. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  114. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  115. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  116. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  117. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  118. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  119. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  120. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  121. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  122. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -128
  123. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
  124. package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
  125. package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
  126. package/infrastructure/domains/admin-scripts/index.js +0 -5
  127. package/infrastructure/jest.config.js +0 -16
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
- const { select, confirm, checkbox } = require('@inquirer/prompts');
4
+ const { select, confirm, multiselect } = require('@inquirer/prompts');
5
5
  const { execSync } = require('child_process');
6
6
  const spawn = require('cross-spawn');
7
7
  const npmRegistry = require('../utils/npm-registry');
@@ -35,15 +35,15 @@ class BackendFirstHandler {
35
35
  await this.createProject(deploymentMode, config);
36
36
 
37
37
  console.log(chalk.green('\n✅ Frigg application created successfully!'));
38
-
39
- // If user needs custom API module, prompt to create it (skip in --yes mode)
40
- if (config.needsCustomApiModule && !this.options.yes) {
38
+
39
+ // If user needs custom API module, prompt to create it
40
+ if (config.needsCustomApiModule) {
41
41
  console.log(chalk.cyan('\n🔧 Now let\'s create your custom API module...'));
42
42
  const createModule = await confirm({
43
43
  message: 'Would you like to create your custom API module now?',
44
44
  default: true
45
45
  });
46
-
46
+
47
47
  if (createModule) {
48
48
  console.log(chalk.gray('\n Run this command after setup:'));
49
49
  console.log(chalk.cyan(` cd ${path.relative(process.cwd(), this.targetPath)}`));
@@ -62,11 +62,6 @@ class BackendFirstHandler {
62
62
  return this.options.mode;
63
63
  }
64
64
 
65
- // If --yes flag is set, use default
66
- if (this.options.yes) {
67
- return 'standalone';
68
- }
69
-
70
65
  const mode = await select({
71
66
  message: 'How will you deploy this Frigg application?',
72
67
  choices: [
@@ -93,21 +88,6 @@ class BackendFirstHandler {
93
88
  async getProjectConfiguration(deploymentMode) {
94
89
  const config = { deploymentMode };
95
90
 
96
- // If --yes flag is set, use all defaults
97
- if (this.options.yes) {
98
- return {
99
- deploymentMode,
100
- appPurpose: 'exploring',
101
- needsCustomApiModule: false,
102
- includeIntegrations: false,
103
- starterIntegrations: [],
104
- includeDemoFrontend: false,
105
- serverlessProvider: deploymentMode === 'standalone' ? 'aws' : undefined,
106
- installDependencies: true,
107
- initializeGit: true,
108
- };
109
- }
110
-
111
91
  // Ask about the purpose of this Frigg application
112
92
  config.appPurpose = await select({
113
93
  message: 'What are you building with Frigg?',
@@ -178,7 +158,7 @@ class BackendFirstHandler {
178
158
  }
179
159
  });
180
160
 
181
- config.starterIntegrations = await checkbox({
161
+ config.starterIntegrations = await multiselect({
182
162
  message: 'Select API modules to integrate (space to select, enter to confirm):',
183
163
  choices,
184
164
  instructions: '\n Press <space> to select, <a> to toggle all, <enter> to confirm\n',
@@ -286,115 +266,63 @@ class BackendFirstHandler {
286
266
 
287
267
  /**
288
268
  * Create standalone Frigg service
289
- *
290
- * Structure:
291
- * my-app/
292
- * ├── package.json # Root - delegates to backend with "cd backend &&"
293
- * ├── backend/ # Actual Frigg app with its own package.json & node_modules
294
- * │ ├── index.js
295
- * │ ├── infrastructure.js
296
- * │ ├── package.json
297
- * │ └── src/
298
- * └── ui-extensions/ # Platform-specific UI extensions
299
- * └── README.md
300
269
  */
301
270
  async createStandaloneProject(config) {
302
- const backendPath = path.join(this.targetPath, 'backend');
303
- const uiExtensionsPath = path.join(this.targetPath, 'ui-extensions');
304
-
305
- // Copy backend template to backend/ subdirectory
271
+ // Copy backend template
306
272
  const backendTemplate = path.join(this.templatesDir, 'backend');
307
- await fs.copy(backendTemplate, backendPath);
308
-
309
- // Read template package.json
310
- const templatePackageJsonPath = path.join(backendPath, 'package.json');
311
- let templatePackageJson = {};
312
- if (await fs.pathExists(templatePackageJsonPath)) {
313
- templatePackageJson = await fs.readJSON(templatePackageJsonPath);
314
- }
273
+ await fs.copy(backendTemplate, this.targetPath);
315
274
 
316
- // Create backend package.json with all dependencies
317
- const backendPackageJson = {
318
- name: `${this.appName}-backend`,
275
+ // Create package.json for standalone mode
276
+ const packageJson = {
277
+ name: this.appName,
319
278
  version: '0.1.0',
320
279
  private: true,
321
- prettier: templatePackageJson.prettier || '@friggframework/prettier-config',
322
280
  scripts: {
323
- ...templatePackageJson.scripts,
324
281
  "backend-start": "node infrastructure.js start",
325
282
  "start": "npm run backend-start",
326
283
  "build": "node infrastructure.js package",
327
284
  "deploy": "node infrastructure.js deploy",
285
+ "test": "jest"
328
286
  },
329
287
  dependencies: {
330
- ...templatePackageJson.dependencies,
331
- "@friggframework/core": "2.0.0-next.58"
332
- },
333
- devDependencies: {
334
- ...templatePackageJson.devDependencies
335
- }
336
- };
337
-
338
- // Add selected integrations as dependencies to backend
339
- if (config.starterIntegrations && config.starterIntegrations.length > 0) {
340
- for (const integration of config.starterIntegrations) {
341
- backendPackageJson.dependencies[`@friggframework/api-module-${integration}`] = '^2.0.0';
342
- }
343
- }
344
-
345
- await fs.writeJSON(templatePackageJsonPath, backendPackageJson, { spaces: 2 });
346
-
347
- // Create root package.json that delegates to backend
348
- const rootPackageJson = {
349
- name: this.appName,
350
- version: '0.1.0',
351
- private: true,
352
- scripts: {
353
- "start": "cd backend && npm run frigg:start",
354
- "docker:start": "cd backend && npm run docker:start",
355
- "docker:stop": "cd backend && npm run docker:stop",
356
- "test": "cd backend && npm test",
357
- "build": "cd backend && npm run build",
358
- "deploy": "cd backend && npm run deploy",
359
- "lint": "cd backend && npm run lint",
360
- "format": "cd backend && npm run format"
288
+ "@friggframework/core": "^2.0.0"
361
289
  }
362
290
  };
363
291
 
364
292
  // Add demo frontend if requested
365
293
  if (config.includeDemoFrontend) {
366
- rootPackageJson.scripts['dev'] = 'concurrently "cd backend && npm run backend-start" "cd frontend && npm run dev"';
367
- rootPackageJson.scripts['frontend:dev'] = 'cd frontend && npm run dev';
368
- rootPackageJson.devDependencies = { concurrently: '^8.2.2' };
369
-
294
+ packageJson.workspaces = ['backend', 'frontend'];
295
+ packageJson.scripts['dev'] = 'concurrently "npm run backend-start" "npm run frontend:dev"';
296
+ packageJson.scripts['frontend:dev'] = 'cd frontend && npm run dev';
297
+
370
298
  await this.createDemoFrontend(config);
371
299
  }
372
300
 
301
+ // Add selected integrations as dependencies
302
+ if (config.starterIntegrations && config.starterIntegrations.length > 0) {
303
+ for (const integration of config.starterIntegrations) {
304
+ packageJson.dependencies[`@friggframework/api-module-${integration}`] = '^2.0.0';
305
+ }
306
+ }
307
+
373
308
  await fs.writeJSON(
374
309
  path.join(this.targetPath, 'package.json'),
375
- rootPackageJson,
310
+ packageJson,
376
311
  { spaces: 2 }
377
312
  );
378
313
 
379
- // Create ui-extensions directory with README
380
- await fs.ensureDir(uiExtensionsPath);
381
- const uiExtensionsReadme = path.join(this.templatesDir, 'backend', 'ui-extensions', 'README.md');
382
- if (await fs.pathExists(uiExtensionsReadme)) {
383
- await fs.copy(uiExtensionsReadme, path.join(uiExtensionsPath, 'README.md'));
384
- }
385
-
386
314
  // Update index.js with selected integrations
387
315
  if (config.starterIntegrations && config.starterIntegrations.length > 0) {
388
- await this.updateAppDefinition(config.starterIntegrations, backendPath);
316
+ await this.updateAppDefinition(config.starterIntegrations);
389
317
  }
390
318
 
391
319
  // Validate generated app definition against schema
392
- const appDefPath = path.join(backendPath, 'index.js');
320
+ const appDefPath = path.join(this.targetPath, 'index.js');
393
321
  await this.validateGeneratedAppDefinition(appDefPath);
394
322
 
395
323
  // Update serverless.yml based on provider
396
324
  if (config.serverlessProvider === 'aws') {
397
- await this.configureAWSServerless(backendPath);
325
+ await this.configureAWSServerless();
398
326
  }
399
327
  }
400
328
 
@@ -578,9 +506,9 @@ To integrate Frigg into your production application:
578
506
  /**
579
507
  * Configure AWS serverless
580
508
  */
581
- async configureAWSServerless(targetDir = this.targetPath) {
509
+ async configureAWSServerless() {
582
510
  // Update serverless.yml for AWS
583
- const serverlessPath = path.join(targetDir, 'serverless.yml');
511
+ const serverlessPath = path.join(this.targetPath, 'serverless.yml');
584
512
  if (await fs.pathExists(serverlessPath)) {
585
513
  // Keep existing AWS configuration
586
514
  console.log(chalk.gray('AWS Lambda configuration ready'));
@@ -605,25 +533,23 @@ To integrate Frigg into your production application:
605
533
  }
606
534
 
607
535
  /**
608
- * Install dependencies in the backend directory
536
+ * Install dependencies
609
537
  */
610
538
  async installDependencies(config) {
611
- console.log(chalk.blue('\n📦 Installing dependencies in backend...'));
612
-
539
+ console.log(chalk.blue('\n📦 Installing dependencies...'));
540
+
613
541
  const useYarn = this.isUsingYarn();
614
542
  const command = useYarn ? 'yarn' : 'npm';
615
543
  const args = useYarn ? [] : ['install'];
616
544
 
617
- // Install in backend directory where package.json with dependencies lives
618
- const backendPath = path.join(this.targetPath, 'backend');
619
545
  const proc = spawn.sync(command, args, {
620
- cwd: backendPath,
546
+ cwd: this.targetPath,
621
547
  stdio: 'inherit'
622
548
  });
623
549
 
624
550
  if (proc.status !== 0) {
625
551
  console.log(chalk.yellow('\n⚠️ Dependency installation failed'));
626
- console.log(chalk.gray(`You can install manually with: cd backend && ${command} install`));
552
+ console.log(chalk.gray(`You can install manually with: ${command} install`));
627
553
  }
628
554
  }
629
555
 
@@ -651,7 +577,7 @@ To integrate Frigg into your production application:
651
577
  * Select from default integrations when npm is unavailable
652
578
  */
653
579
  async selectDefaultIntegrations() {
654
- return await checkbox({
580
+ return await multiselect({
655
581
  message: 'Select starter integrations (space to select, enter to confirm):',
656
582
  choices: [
657
583
  { name: 'Salesforce - CRM integration', value: 'salesforce' },
@@ -670,8 +596,8 @@ To integrate Frigg into your production application:
670
596
  /**
671
597
  * Update index.js with selected integrations
672
598
  */
673
- async updateAppDefinition(integrations, targetDir = this.targetPath) {
674
- const appDefPath = path.join(targetDir, 'index.js');
599
+ async updateAppDefinition(integrations) {
600
+ const appDefPath = path.join(this.targetPath, 'index.js');
675
601
  if (await fs.pathExists(appDefPath)) {
676
602
  let content = await fs.readFile(appDefPath, 'utf8');
677
603
 
@@ -794,18 +720,14 @@ To integrate Frigg into your production application:
794
720
  console.log(chalk.cyan(` cd ${cdPath}\n`));
795
721
 
796
722
  if (deploymentMode === 'standalone') {
797
- console.log(`2. Install backend dependencies:`);
798
- console.log(chalk.cyan(` cd backend && npm install\n`));
799
-
800
- console.log(`3. Start the development server:`);
723
+ console.log(`2. Start the development server:`);
801
724
  console.log(chalk.cyan(` npm start\n`));
802
- console.log(chalk.gray(` (or from backend: npm run frigg:start)\n`));
803
725
 
804
- console.log(`4. Open the Frigg UI for development:`);
726
+ console.log(`3. Open the Frigg UI for development:`);
805
727
  console.log(chalk.cyan(` frigg ui\n`));
806
728
 
807
729
  if (config.serverlessProvider === 'aws') {
808
- console.log(`5. Deploy to AWS Lambda:`);
730
+ console.log(`4. Deploy to AWS Lambda:`);
809
731
  console.log(chalk.cyan(` npm run deploy\n`));
810
732
  }
811
733
  } else {
@@ -825,12 +747,8 @@ To integrate Frigg into your production application:
825
747
  console.log(chalk.gray(' See frontend/README.md for integration guidance.'));
826
748
  }
827
749
 
828
- console.log(chalk.gray('\n📁 Project Structure:'));
829
- console.log(chalk.gray(' backend/ - Frigg app (run npm install here)'));
830
- console.log(chalk.gray(' ui-extensions/ - Platform-specific UI extensions'));
831
-
832
750
  console.log(chalk.green('\n🎉 Happy integrating with Frigg!\n'));
833
- console.log(chalk.gray('Documentation: https://docs.friggframework.org'));
751
+ console.log(chalk.gray('Documentation: https://docs.frigg.dev'));
834
752
  console.log(chalk.gray('Support: https://github.com/friggframework/frigg/issues'));
835
753
  }
836
754
  }
@@ -68,8 +68,7 @@ async function initCommand(projectName, options) {
68
68
  force,
69
69
  verbose,
70
70
  mode: options.mode,
71
- frontend: options.frontend,
72
- yes: options.yes
71
+ frontend: options.frontend
73
72
  });
74
73
 
75
74
  await handler.initialize();
@@ -75,16 +75,6 @@ class TemplateHandler {
75
75
  return !['node_modules', '.serverless', 'dist', 'build'].includes(basename);
76
76
  }
77
77
  });
78
-
79
- // Rename .env.default to .env if it exists and .env doesn't already exist
80
- const envDefaultPath = path.join(target, '.env.default');
81
- const envPath = path.join(target, '.env');
82
- if (fs.existsSync(envDefaultPath) && !fs.existsSync(envPath)) {
83
- await fs.rename(envDefaultPath, envPath);
84
- } else if (fs.existsSync(envDefaultPath)) {
85
- // Remove the .env.default if .env already exists
86
- await fs.remove(envDefaultPath);
87
- }
88
78
  }
89
79
 
90
80
  /**
@@ -110,14 +100,14 @@ class TemplateHandler {
110
100
  async updateServerlessConfig() {
111
101
  const serverlessPath = path.join(this.targetPath, 'serverless.yml');
112
102
  let serverlessContent = await fs.readFile(serverlessPath, 'utf8');
113
-
103
+
114
104
  // Update service name based on directory name
115
105
  const projectName = path.basename(this.targetPath);
116
106
  serverlessContent = serverlessContent.replace(
117
- /^service: frigg-app$/m,
107
+ /^service: create-frigg-app$/m,
118
108
  `service: ${projectName}`
119
109
  );
120
-
110
+
121
111
  await fs.writeFile(serverlessPath, serverlessContent);
122
112
  }
123
113
 
@@ -1,12 +1,12 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
- const output = require('../utils/output');
3
+ const { logInfo } = require('./logger');
4
4
  const INTEGRATIONS_DIR = 'src/integrations';
5
5
  const BACKEND_JS = 'backend.js';
6
6
 
7
7
  function updateBackendJsFile(backendPath, apiModuleName) {
8
8
  const backendJsPath = path.join(path.dirname(backendPath), BACKEND_JS);
9
- output.debug(`Updating backend.js: ${backendJsPath}`);
9
+ logInfo(`Updating backend.js: ${backendJsPath}`);
10
10
  updateBackendJs(backendJsPath, apiModuleName);
11
11
  }
12
12
 
@@ -21,7 +21,7 @@ function updateBackendJs(backendJsPath, apiModuleName) {
21
21
  );
22
22
  fs.writeFileSync(backendJsPath, importStatement + updatedContent);
23
23
  } else {
24
- output.debug(
24
+ logInfo(
25
25
  `Import statement for ${apiModuleName}Integration already exists in backend.js`
26
26
  );
27
27
  }
@@ -1,8 +1,9 @@
1
1
  const fs = require('fs');
2
2
  const dotenv = require('dotenv');
3
3
  const { readFileSync, writeFileSync, existsSync } = require('fs');
4
- const output = require('../utils/output');
4
+ const { logInfo } = require('./logger');
5
5
  const { resolve } = require('node:path');
6
+ const { confirm, input } = require('@inquirer/prompts');
6
7
  const { parse } = require('@babel/parser');
7
8
  const traverse = require('@babel/traverse').default;
8
9
 
@@ -42,14 +43,15 @@ const extractRawEnvVariables = (modulePath) => {
42
43
  return envVariables;
43
44
  };
44
45
  const handleEnvVariables = async (backendPath, modulePath) => {
45
- output.info('Searching for missing environment variables...');
46
+ logInfo('Searching for missing environment variables...');
46
47
  const Definition = { env: extractRawEnvVariables(modulePath) };
47
48
  if (Definition && Definition.env) {
48
- output.debug('Definition.env:', JSON.stringify(Definition.env));
49
+ console.log('Here is Definition.env:', Definition.env);
49
50
  const envVars = Object.values(Definition.env);
50
51
 
51
- output.info(
52
- `Found environment variables in API module: ${envVars.join(', ')}`
52
+ console.log(
53
+ 'Found the following environment variables in the API module:',
54
+ envVars
53
55
  );
54
56
 
55
57
  const localEnvPath = resolve(backendPath, '../.env');
@@ -76,19 +78,23 @@ const handleEnvVariables = async (backendPath, modulePath) => {
76
78
  (envVar) => !localEnvVars[envVar] && !localDevConfig[envVar]
77
79
  );
78
80
 
79
- if (missingEnvVars.length > 0) {
80
- output.warn(`Missing environment variables: ${missingEnvVars.join(', ')}`);
81
+ logInfo(`Missing environment variables: ${missingEnvVars.join(', ')}`);
81
82
 
82
- const addEnvVars = await output.confirm(
83
- `The following environment variables are required: ${missingEnvVars.join(
83
+ if (missingEnvVars.length > 0) {
84
+ const addEnvVars = await confirm({
85
+ message: `The following environment variables are required: ${missingEnvVars.join(
84
86
  ', '
85
- )}. Do you want to add them now?`
86
- );
87
+ )}. Do you want to add them now?`,
88
+ });
87
89
 
88
90
  if (addEnvVars) {
89
91
  const envValues = {};
90
92
  for (const envVar of missingEnvVars) {
91
- const value = await output.input(`Enter value for ${envVar}:`);
93
+ const value = await input({
94
+ type: 'input',
95
+ name: 'value',
96
+ message: `Enter value for ${envVar}:`,
97
+ });
92
98
  envValues[envVar] = value;
93
99
  }
94
100
 
@@ -111,12 +117,9 @@ const handleEnvVariables = async (backendPath, modulePath) => {
111
117
  JSON.stringify(updatedDevConfig, null, 2)
112
118
  );
113
119
  }
114
- output.success('Environment variables added successfully');
115
120
  } else {
116
- output.info("Edit whenever you're able, safe travels friend!");
121
+ logInfo("Edit whenever you're able, safe travels friend!");
117
122
  }
118
- } else {
119
- output.success('All required environment variables are already configured');
120
123
  }
121
124
  }
122
125
  };
@@ -1,14 +1,16 @@
1
1
  const { handleEnvVariables } = require('./environment-variables');
2
- const output = require('../utils/output');
2
+ const { logInfo } = require('./logger');
3
+ const inquirer = require('inquirer');
3
4
  const fs = require('fs');
4
5
  const dotenv = require('dotenv');
5
6
  const { resolve } = require('node:path');
6
7
  const { parse } = require('@babel/parser');
7
8
  const traverse = require('@babel/traverse');
8
9
 
9
- jest.mock('../utils/output');
10
+ jest.mock('inquirer');
10
11
  jest.mock('fs');
11
12
  jest.mock('dotenv');
13
+ jest.mock('./logger');
12
14
  jest.mock('@babel/parser');
13
15
  jest.mock('@babel/traverse');
14
16
 
@@ -97,23 +99,22 @@ describe('handleEnvVariables', () => {
97
99
  return '';
98
100
  });
99
101
 
100
- output.confirm.mockResolvedValueOnce(true);
101
- output.input
102
- .mockResolvedValueOnce('client_id_value')
103
- .mockResolvedValueOnce('client_secret_value')
104
- .mockResolvedValueOnce('redirect_uri_value')
105
- .mockResolvedValueOnce('scope_value');
102
+ inquirer.prompt
103
+ .mockResolvedValueOnce({ addEnvVars: true })
104
+ .mockResolvedValueOnce({ value: 'client_id_value' })
105
+ .mockResolvedValueOnce({ value: 'client_secret_value' })
106
+ .mockResolvedValueOnce({ value: 'redirect_uri_value' })
107
+ .mockResolvedValueOnce({ value: 'scope_value' });
106
108
 
107
109
  await handleEnvVariables(backendPath, modulePath);
108
110
 
109
- expect(output.info).toHaveBeenCalledWith(
111
+ expect(logInfo).toHaveBeenCalledWith(
110
112
  'Searching for missing environment variables...'
111
113
  );
112
- expect(output.warn).toHaveBeenCalledWith(
114
+ expect(logInfo).toHaveBeenCalledWith(
113
115
  'Missing environment variables: GOOGLE_CALENDAR_CLIENT_ID, GOOGLE_CALENDAR_CLIENT_SECRET, REDIRECT_URI, GOOGLE_CALENDAR_SCOPE'
114
116
  );
115
- expect(output.confirm).toHaveBeenCalledTimes(1);
116
- expect(output.input).toHaveBeenCalledTimes(4);
117
+ expect(inquirer.prompt).toHaveBeenCalledTimes(5);
117
118
  expect(fs.appendFileSync).toHaveBeenCalledWith(
118
119
  localEnvPath,
119
120
  '\nGOOGLE_CALENDAR_CLIENT_ID=client_id_value\nGOOGLE_CALENDAR_CLIENT_SECRET=client_secret_value\nREDIRECT_URI=redirect_uri_value\nGOOGLE_CALENDAR_SCOPE=scope_value'
@@ -2,7 +2,7 @@ const { installPackage } = require('./install-package');
2
2
  const { createIntegrationFile } = require('./integration-file');
3
3
  const { resolve } = require('node:path');
4
4
  const { updateBackendJsFile } = require('./backend-js');
5
- const output = require('../utils/output');
5
+ const { logInfo, logError } = require('./logger');
6
6
  const { commitChanges } = require('./commit-changes');
7
7
  const { handleEnvVariables } = require('./environment-variables');
8
8
  const {
@@ -35,23 +35,18 @@ const installCommand = async (apiModuleName) => {
35
35
  const sanitizedLabel = label.replace(
36
36
  /[<>:"/\\|?*\x00-\x1F\s]/g,
37
37
  ''
38
- ); // Remove invalid characters and spaces
39
-
40
- const spinner = output.spinner(`Installing integration for ${sanitizedLabel}...`);
41
- try {
42
- createIntegrationFile(backendPath, sanitizedLabel, ApiClass);
43
- updateBackendJsFile(backendPath, sanitizedLabel);
44
- commitChanges(backendPath, sanitizedLabel);
45
- spinner.succeed(`Successfully installed ${packageName} and updated the project.`);
46
- } catch (innerError) {
47
- spinner.fail(`Failed to install ${packageName}`);
48
- throw innerError;
49
- }
38
+ ); // Remove invalid characters and spaces console.log('Installing integration for:', sanitizedLabel);
39
+ createIntegrationFile(backendPath, sanitizedLabel, ApiClass);
40
+ updateBackendJsFile(backendPath, sanitizedLabel);
41
+ commitChanges(backendPath, sanitizedLabel);
42
+ logInfo(
43
+ `Successfully installed ${packageName} and updated the project.`
44
+ );
50
45
 
51
46
  await handleEnvVariables(backendPath, modulePath);
52
47
  }
53
48
  } catch (error) {
54
- output.error('An error occurred:', error);
49
+ logError('An error occurred:', error);
55
50
  process.exit(1);
56
51
  }
57
52
  };
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
- const output = require('../utils/output');
3
+ const { logInfo } = require('./logger');
4
4
  const { getIntegrationTemplate } = require('./template');
5
5
  const INTEGRATIONS_DIR = 'src/integrations';
6
6
 
@@ -9,14 +9,14 @@ function createIntegrationFile(backendPath, apiModuleName, ApiClass) {
9
9
  path.dirname(backendPath),
10
10
  INTEGRATIONS_DIR
11
11
  );
12
- output.debug(`Ensuring directory exists: ${integrationDir}`);
12
+ logInfo(`Ensuring directory exists: ${integrationDir}`);
13
13
  fs.ensureDirSync(integrationDir);
14
14
 
15
15
  const integrationFilePath = path.join(
16
16
  integrationDir,
17
17
  `${apiModuleName}Integration.js`
18
18
  );
19
- output.debug(`Writing integration file: ${integrationFilePath}`);
19
+ logInfo(`Writing integration file: ${integrationFilePath}`);
20
20
  const integrationTemplate = getIntegrationTemplate(
21
21
  apiModuleName,
22
22
  backendPath,
@@ -0,0 +1,12 @@
1
+ function logInfo(message) {
2
+ console.log(message);
3
+ }
4
+
5
+ function logError(message, error) {
6
+ console.error(message, error);
7
+ }
8
+
9
+ module.exports = {
10
+ logInfo,
11
+ logError,
12
+ };
@@ -1,6 +1,7 @@
1
1
  const { execSync } = require('child_process');
2
2
  const axios = require('axios');
3
- const output = require('../utils/output');
3
+ const { logError } = require('./logger');
4
+ const { checkbox } = require('@inquirer/prompts');
4
5
 
5
6
  async function searchPackages(apiModuleName) {
6
7
  const searchCommand = `npm search @friggframework/api-module-${apiModuleName} --json`;
@@ -30,7 +31,7 @@ const searchAndSelectPackage = async (apiModuleName) => {
30
31
  const searchResults = await searchPackages(apiModuleName || '');
31
32
 
32
33
  if (searchResults.length === 0) {
33
- output.error(`No packages found matching ${apiModuleName}`);
34
+ logError(`No packages found matching ${apiModuleName}`);
34
35
  process.exit(1);
35
36
  }
36
37
 
@@ -43,7 +44,7 @@ const searchAndSelectPackage = async (apiModuleName) => {
43
44
  const earlierVersions = searchResults
44
45
  .map((pkg) => `${pkg.name} (${pkg.version})`)
45
46
  .join(', ');
46
- output.error(
47
+ logError(
47
48
  `No packages found with version 1.0.0 or above for ${apiModuleName}. Found earlier versions: ${earlierVersions}`
48
49
  );
49
50
  process.exit(1);
@@ -57,8 +58,11 @@ const searchAndSelectPackage = async (apiModuleName) => {
57
58
  };
58
59
  });
59
60
 
60
- const selectedPackages = await output.checkbox('Select the packages to install:', choices);
61
- output.info(`Selected packages: ${selectedPackages.join(', ')}`);
61
+ const selectedPackages = await checkbox({
62
+ message: 'Select the packages to install:',
63
+ choices,
64
+ });
65
+ console.log('Selected packages:', selectedPackages);
62
66
 
63
67
  return selectedPackages.map((choice) => choice.split(' ')[0]);
64
68
  };
@@ -1,8 +1,5 @@
1
- const path = require('path');
2
-
3
1
  module.exports = {
4
2
  displayName: 'Frigg CLI Tests',
5
- rootDir: __dirname,
6
3
  testMatch: [
7
4
  '<rootDir>/__tests__/**/*.test.js',
8
5
  '<rootDir>/__tests__/**/*.spec.js',
@@ -96,7 +93,7 @@ module.exports = {
96
93
  }
97
94
  },
98
95
  setupFilesAfterEnv: [
99
- path.join(__dirname, '__tests__', 'utils', 'test-setup.js')
96
+ '<rootDir>/__tests__/utils/test-setup.js'
100
97
  ],
101
98
  testTimeout: 10000,
102
99
  maxWorkers: '50%',