@friggframework/devtools 2.0.0-next.44 → 2.0.0-next.46

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 (212) hide show
  1. package/infrastructure/ARCHITECTURE.md +487 -0
  2. package/infrastructure/HEALTH.md +468 -0
  3. package/infrastructure/README.md +51 -0
  4. package/infrastructure/__tests__/postgres-config.test.js +914 -0
  5. package/infrastructure/__tests__/template-generation.test.js +687 -0
  6. package/infrastructure/create-frigg-infrastructure.js +1 -1
  7. package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
  8. package/infrastructure/{DEPLOYMENT-INSTRUCTIONS.md → docs/deployment-instructions.md} +3 -3
  9. package/infrastructure/{IAM-POLICY-TEMPLATES.md → docs/iam-policy-templates.md} +9 -10
  10. package/infrastructure/domains/database/aurora-builder.js +809 -0
  11. package/infrastructure/domains/database/aurora-builder.test.js +950 -0
  12. package/infrastructure/domains/database/aurora-discovery.js +87 -0
  13. package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
  14. package/infrastructure/domains/database/aurora-resolver.js +210 -0
  15. package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
  16. package/infrastructure/domains/database/migration-builder.js +633 -0
  17. package/infrastructure/domains/database/migration-builder.test.js +294 -0
  18. package/infrastructure/domains/database/migration-resolver.js +163 -0
  19. package/infrastructure/domains/database/migration-resolver.test.js +337 -0
  20. package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
  21. package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
  22. package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
  23. package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
  24. package/infrastructure/domains/health/application/ports/index.js +26 -0
  25. package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
  26. package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
  27. package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
  28. package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
  29. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
  30. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
  31. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
  32. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
  33. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
  34. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
  35. package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
  36. package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
  37. package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
  38. package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
  39. package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
  40. package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
  41. package/infrastructure/domains/health/domain/entities/issue.js +299 -0
  42. package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
  43. package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
  44. package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
  45. package/infrastructure/domains/health/domain/entities/resource.js +159 -0
  46. package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
  47. package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
  48. package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
  49. package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
  50. package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
  51. package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
  52. package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
  53. package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
  54. package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
  55. package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
  56. package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
  57. package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
  58. package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
  59. package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
  60. package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
  61. package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
  62. package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
  63. package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
  64. package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
  65. package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
  66. package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
  67. package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
  68. package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
  69. package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
  70. package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
  71. package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
  72. package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
  73. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
  74. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
  75. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
  76. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
  77. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
  78. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
  79. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
  80. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
  81. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
  82. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
  83. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
  84. package/infrastructure/domains/integration/integration-builder.js +397 -0
  85. package/infrastructure/domains/integration/integration-builder.test.js +593 -0
  86. package/infrastructure/domains/integration/integration-resolver.js +170 -0
  87. package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
  88. package/infrastructure/domains/integration/websocket-builder.js +69 -0
  89. package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
  90. package/infrastructure/domains/networking/vpc-builder.js +1829 -0
  91. package/infrastructure/domains/networking/vpc-builder.test.js +1262 -0
  92. package/infrastructure/domains/networking/vpc-discovery.js +177 -0
  93. package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
  94. package/infrastructure/domains/networking/vpc-resolver.js +324 -0
  95. package/infrastructure/domains/networking/vpc-resolver.test.js +501 -0
  96. package/infrastructure/domains/parameters/ssm-builder.js +79 -0
  97. package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
  98. package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
  99. package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
  100. package/infrastructure/{iam-generator.js → domains/security/iam-generator.js} +2 -2
  101. package/infrastructure/domains/security/kms-builder.js +366 -0
  102. package/infrastructure/domains/security/kms-builder.test.js +374 -0
  103. package/infrastructure/domains/security/kms-discovery.js +80 -0
  104. package/infrastructure/domains/security/kms-discovery.test.js +177 -0
  105. package/infrastructure/domains/security/kms-resolver.js +96 -0
  106. package/infrastructure/domains/security/kms-resolver.test.js +216 -0
  107. package/infrastructure/domains/shared/base-builder.js +112 -0
  108. package/infrastructure/domains/shared/base-resolver.js +186 -0
  109. package/infrastructure/domains/shared/base-resolver.test.js +305 -0
  110. package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
  111. package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
  112. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
  113. package/infrastructure/domains/shared/cloudformation-discovery.js +375 -0
  114. package/infrastructure/domains/shared/cloudformation-discovery.test.js +590 -0
  115. package/infrastructure/domains/shared/environment-builder.js +119 -0
  116. package/infrastructure/domains/shared/environment-builder.test.js +247 -0
  117. package/infrastructure/domains/shared/providers/aws-provider-adapter.js +544 -0
  118. package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +377 -0
  119. package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
  120. package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
  121. package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
  122. package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
  123. package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
  124. package/infrastructure/domains/shared/resource-discovery.js +192 -0
  125. package/infrastructure/domains/shared/resource-discovery.test.js +552 -0
  126. package/infrastructure/domains/shared/types/app-definition.js +205 -0
  127. package/infrastructure/domains/shared/types/discovery-result.js +106 -0
  128. package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
  129. package/infrastructure/domains/shared/types/index.js +46 -0
  130. package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
  131. package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
  132. package/infrastructure/domains/shared/utilities/base-definition-factory.js +380 -0
  133. package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
  134. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +248 -0
  135. package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
  136. package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
  137. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +55 -0
  138. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +138 -0
  139. package/infrastructure/{env-validator.js → domains/shared/validation/env-validator.js} +2 -1
  140. package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
  141. package/infrastructure/esbuild.config.js +53 -0
  142. package/infrastructure/infrastructure-composer.js +87 -0
  143. package/infrastructure/{serverless-template.test.js → infrastructure-composer.test.js} +115 -24
  144. package/infrastructure/scripts/build-prisma-layer.js +553 -0
  145. package/infrastructure/scripts/build-prisma-layer.test.js +102 -0
  146. package/infrastructure/{build-time-discovery.js → scripts/build-time-discovery.js} +80 -48
  147. package/infrastructure/{build-time-discovery.test.js → scripts/build-time-discovery.test.js} +5 -4
  148. package/layers/prisma/nodejs/package.json +8 -0
  149. package/management-ui/server/utils/cliIntegration.js +1 -1
  150. package/management-ui/server/utils/environment/awsParameterStore.js +29 -18
  151. package/package.json +11 -11
  152. package/frigg-cli/.eslintrc.js +0 -141
  153. package/frigg-cli/__tests__/unit/commands/build.test.js +0 -251
  154. package/frigg-cli/__tests__/unit/commands/db-setup.test.js +0 -548
  155. package/frigg-cli/__tests__/unit/commands/install.test.js +0 -400
  156. package/frigg-cli/__tests__/unit/commands/ui.test.js +0 -346
  157. package/frigg-cli/__tests__/unit/utils/database-validator.test.js +0 -366
  158. package/frigg-cli/__tests__/unit/utils/error-messages.test.js +0 -304
  159. package/frigg-cli/__tests__/unit/utils/prisma-runner.test.js +0 -486
  160. package/frigg-cli/__tests__/utils/mock-factory.js +0 -270
  161. package/frigg-cli/__tests__/utils/prisma-mock.js +0 -194
  162. package/frigg-cli/__tests__/utils/test-fixtures.js +0 -463
  163. package/frigg-cli/__tests__/utils/test-setup.js +0 -287
  164. package/frigg-cli/build-command/index.js +0 -65
  165. package/frigg-cli/db-setup-command/index.js +0 -193
  166. package/frigg-cli/deploy-command/index.js +0 -175
  167. package/frigg-cli/generate-command/__tests__/generate-command.test.js +0 -301
  168. package/frigg-cli/generate-command/azure-generator.js +0 -43
  169. package/frigg-cli/generate-command/gcp-generator.js +0 -47
  170. package/frigg-cli/generate-command/index.js +0 -332
  171. package/frigg-cli/generate-command/terraform-generator.js +0 -555
  172. package/frigg-cli/generate-iam-command.js +0 -118
  173. package/frigg-cli/index.js +0 -75
  174. package/frigg-cli/index.test.js +0 -158
  175. package/frigg-cli/init-command/backend-first-handler.js +0 -756
  176. package/frigg-cli/init-command/index.js +0 -93
  177. package/frigg-cli/init-command/template-handler.js +0 -143
  178. package/frigg-cli/install-command/backend-js.js +0 -33
  179. package/frigg-cli/install-command/commit-changes.js +0 -16
  180. package/frigg-cli/install-command/environment-variables.js +0 -127
  181. package/frigg-cli/install-command/environment-variables.test.js +0 -136
  182. package/frigg-cli/install-command/index.js +0 -54
  183. package/frigg-cli/install-command/install-package.js +0 -13
  184. package/frigg-cli/install-command/integration-file.js +0 -30
  185. package/frigg-cli/install-command/logger.js +0 -12
  186. package/frigg-cli/install-command/template.js +0 -90
  187. package/frigg-cli/install-command/validate-package.js +0 -75
  188. package/frigg-cli/jest.config.js +0 -124
  189. package/frigg-cli/package.json +0 -54
  190. package/frigg-cli/start-command/index.js +0 -149
  191. package/frigg-cli/start-command/start-command.test.js +0 -297
  192. package/frigg-cli/test/init-command.test.js +0 -180
  193. package/frigg-cli/test/npm-registry.test.js +0 -319
  194. package/frigg-cli/ui-command/index.js +0 -154
  195. package/frigg-cli/utils/app-resolver.js +0 -319
  196. package/frigg-cli/utils/backend-path.js +0 -25
  197. package/frigg-cli/utils/database-validator.js +0 -161
  198. package/frigg-cli/utils/error-messages.js +0 -257
  199. package/frigg-cli/utils/npm-registry.js +0 -167
  200. package/frigg-cli/utils/prisma-runner.js +0 -280
  201. package/frigg-cli/utils/process-manager.js +0 -199
  202. package/frigg-cli/utils/repo-detection.js +0 -405
  203. package/infrastructure/aws-discovery.js +0 -1176
  204. package/infrastructure/aws-discovery.test.js +0 -1220
  205. package/infrastructure/serverless-template.js +0 -2074
  206. /package/infrastructure/{WEBSOCKET-CONFIGURATION.md → docs/WEBSOCKET-CONFIGURATION.md} +0 -0
  207. /package/infrastructure/{GENERATE-IAM-DOCS.md → docs/generate-iam-command.md} +0 -0
  208. /package/infrastructure/{iam-generator.test.js → domains/security/iam-generator.test.js} +0 -0
  209. /package/infrastructure/{frigg-deployment-iam-stack.yaml → domains/security/templates/frigg-deployment-iam-stack.yaml} +0 -0
  210. /package/infrastructure/{iam-policy-basic.json → domains/security/templates/iam-policy-basic.json} +0 -0
  211. /package/infrastructure/{iam-policy-full.json → domains/security/templates/iam-policy-full.json} +0 -0
  212. /package/infrastructure/{run-discovery.js → scripts/run-discovery.js} +0 -0
@@ -1,93 +0,0 @@
1
- /**
2
- * Copyright (c) 2024 Frigg Integration Framework
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const path = require('path');
11
- const chalk = require('chalk');
12
- const validateProjectName = require('validate-npm-package-name');
13
- const semver = require('semver');
14
- const BackendFirstHandler = require('./backend-first-handler');
15
-
16
- function checkAppName(appName) {
17
- const validationResult = validateProjectName(appName);
18
- if (!validationResult.validForNewPackages) {
19
- console.error(
20
- chalk.red(
21
- `Cannot create a project named ${chalk.green(
22
- `"${appName}"`
23
- )} because of npm naming restrictions:\n`
24
- )
25
- );
26
- [
27
- ...(validationResult.errors || []),
28
- ...(validationResult.warnings || []),
29
- ].forEach(error => {
30
- console.error(chalk.red(` * ${error}`));
31
- });
32
- console.error(chalk.red('\nPlease choose a different project name.'));
33
- process.exit(1);
34
- }
35
- }
36
-
37
- function checkNodeVersion() {
38
- const unsupportedNodeVersion = !semver.satisfies(
39
- semver.coerce(process.version),
40
- '>=14'
41
- );
42
-
43
- if (unsupportedNodeVersion) {
44
- console.log(
45
- chalk.yellow(
46
- `You are using Node ${process.version} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
47
- `Please update to Node 14 or higher for a better, fully supported experience.\n`
48
- )
49
- );
50
- }
51
- }
52
-
53
- async function initCommand(projectName, options) {
54
- const verbose = options.verbose || false;
55
- const force = options.force || false;
56
-
57
- checkNodeVersion();
58
-
59
- const root = path.resolve(projectName);
60
- const appName = path.basename(root);
61
-
62
- checkAppName(appName);
63
-
64
- // Use backend-first handler by default
65
- if (!options.template && !options.legacyFrontend) {
66
- try {
67
- const handler = new BackendFirstHandler(root, {
68
- force,
69
- verbose,
70
- mode: options.mode,
71
- frontend: options.frontend
72
- });
73
-
74
- await handler.initialize();
75
- return;
76
- } catch (error) {
77
- console.log();
78
- console.log(chalk.red('Aborting installation.'));
79
- console.log(chalk.red('Error:'), error.message);
80
- console.log();
81
- process.exit(1);
82
- }
83
- }
84
-
85
- // If we get here, show an error for legacy options
86
- console.log();
87
- console.log(chalk.red('Legacy template system is no longer supported.'));
88
- console.log(chalk.yellow('Please use the new backend-first approach.'));
89
- console.log();
90
- process.exit(1);
91
- }
92
-
93
- module.exports = { initCommand };
@@ -1,143 +0,0 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const { execSync } = require('child_process');
4
-
5
- /**
6
- * Handles template initialization for the frigg init command
7
- */
8
- class TemplateHandler {
9
- constructor(targetPath, options = {}) {
10
- this.targetPath = targetPath;
11
- this.options = options;
12
- this.templatesDir = path.join(__dirname, '..', 'templates');
13
- }
14
-
15
- /**
16
- * Initialize a new Frigg backend project from template
17
- */
18
- async initializeBackendTemplate() {
19
- const templatePath = path.join(this.templatesDir, 'backend');
20
-
21
- if (!fs.existsSync(templatePath)) {
22
- throw new Error('Backend template not found. Please ensure the CLI is properly installed.');
23
- }
24
-
25
- // Create target directory if it doesn't exist
26
- await fs.ensureDir(this.targetPath);
27
-
28
- // Check if directory is empty
29
- const files = await fs.readdir(this.targetPath);
30
- if (files.length > 0 && !this.options.force) {
31
- throw new Error('Target directory is not empty. Use --force to override.');
32
- }
33
-
34
- console.log('🚀 Initializing new Frigg backend project...');
35
-
36
- // Copy template files
37
- await this.copyTemplateFiles(templatePath, this.targetPath);
38
-
39
- // Update package.json with project name
40
- await this.updatePackageJson();
41
-
42
- // Update serverless.yml with project name
43
- await this.updateServerlessConfig();
44
-
45
- // Initialize git if requested
46
- if (this.options.git !== false) {
47
- await this.initializeGit();
48
- }
49
-
50
- // Install dependencies if requested
51
- if (this.options.install !== false) {
52
- await this.installDependencies();
53
- }
54
-
55
- console.log('✅ Frigg backend project initialized successfully!');
56
- console.log('\nNext steps:');
57
- console.log(` cd ${path.basename(this.targetPath)}`);
58
- if (this.options.install === false) {
59
- console.log(' npm install');
60
- }
61
- console.log(' npm run docker:start');
62
- console.log(' npm run backend-start');
63
- console.log('\nFor more information, check the README.md file.');
64
- }
65
-
66
- /**
67
- * Copy template files to target directory
68
- */
69
- async copyTemplateFiles(source, target) {
70
- await fs.copy(source, target, {
71
- overwrite: this.options.force || false,
72
- filter: (src) => {
73
- // Skip node_modules and other build artifacts
74
- const basename = path.basename(src);
75
- return !['node_modules', '.serverless', 'dist', 'build'].includes(basename);
76
- }
77
- });
78
- }
79
-
80
- /**
81
- * Update package.json with project-specific details
82
- */
83
- async updatePackageJson() {
84
- const packageJsonPath = path.join(this.targetPath, 'package.json');
85
- const packageJson = await fs.readJson(packageJsonPath);
86
-
87
- // Update package name based on directory name
88
- const projectName = path.basename(this.targetPath);
89
- packageJson.name = projectName;
90
-
91
- // Remove private flag for new projects
92
- delete packageJson.private;
93
-
94
- await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
95
- }
96
-
97
- /**
98
- * Update serverless.yml with project-specific details
99
- */
100
- async updateServerlessConfig() {
101
- const serverlessPath = path.join(this.targetPath, 'serverless.yml');
102
- let serverlessContent = await fs.readFile(serverlessPath, 'utf8');
103
-
104
- // Update service name based on directory name
105
- const projectName = path.basename(this.targetPath);
106
- serverlessContent = serverlessContent.replace(
107
- /^service: create-frigg-app$/m,
108
- `service: ${projectName}`
109
- );
110
-
111
- await fs.writeFile(serverlessPath, serverlessContent);
112
- }
113
-
114
- /**
115
- * Initialize git repository
116
- */
117
- async initializeGit() {
118
- try {
119
- console.log('📦 Initializing git repository...');
120
- execSync('git init', { cwd: this.targetPath, stdio: 'ignore' });
121
- execSync('git add .', { cwd: this.targetPath, stdio: 'ignore' });
122
- execSync('git commit -m "Initial commit from Frigg CLI"', {
123
- cwd: this.targetPath,
124
- stdio: 'ignore'
125
- });
126
- } catch (error) {
127
- console.warn('⚠️ Git initialization failed. You can initialize git manually later.');
128
- }
129
- }
130
-
131
- /**
132
- * Install npm dependencies
133
- */
134
- async installDependencies() {
135
- console.log('📦 Installing dependencies...');
136
- execSync('npm install', {
137
- cwd: this.targetPath,
138
- stdio: 'inherit'
139
- });
140
- }
141
- }
142
-
143
- module.exports = TemplateHandler;
@@ -1,33 +0,0 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const { logInfo } = require('./logger');
4
- const INTEGRATIONS_DIR = 'src/integrations';
5
- const BACKEND_JS = 'backend.js';
6
-
7
- function updateBackendJsFile(backendPath, apiModuleName) {
8
- const backendJsPath = path.join(path.dirname(backendPath), BACKEND_JS);
9
- logInfo(`Updating backend.js: ${backendJsPath}`);
10
- updateBackendJs(backendJsPath, apiModuleName);
11
- }
12
-
13
- function updateBackendJs(backendJsPath, apiModuleName) {
14
- const backendJsContent = fs.readFileSync(backendJsPath, 'utf-8');
15
- const importStatement = `const ${apiModuleName}Integration = require('./${INTEGRATIONS_DIR}/${apiModuleName}Integration');\n`;
16
-
17
- if (!backendJsContent.includes(importStatement)) {
18
- const updatedContent = backendJsContent.replace(
19
- /(integrations\s*:\s*\[)([\s\S]*?)(\])/,
20
- `$1\n ${apiModuleName}Integration,$2$3`
21
- );
22
- fs.writeFileSync(backendJsPath, importStatement + updatedContent);
23
- } else {
24
- logInfo(
25
- `Import statement for ${apiModuleName}Integration already exists in backend.js`
26
- );
27
- }
28
- }
29
-
30
- module.exports = {
31
- updateBackendJsFile,
32
- updateBackendJs,
33
- };
@@ -1,16 +0,0 @@
1
- const { execSync } = require('child_process');
2
- const path = require('path');
3
-
4
- function commitChanges(backendPath, apiModuleName) {
5
- const apiModulePath = path.join(path.dirname(backendPath), 'src', 'integrations', `${apiModuleName}Integration.js`);
6
- try {
7
- execSync(`git add ${apiModulePath}`);
8
- execSync(`git commit -m "Add ${apiModuleName}Integration to ${apiModuleName}Integration.js"`);
9
- } catch (error) {
10
- throw new Error('Failed to commit changes:', error);
11
- }
12
- }
13
-
14
- module.exports = {
15
- commitChanges,
16
- };
@@ -1,127 +0,0 @@
1
- const fs = require('fs');
2
- const dotenv = require('dotenv');
3
- const { readFileSync, writeFileSync, existsSync } = require('fs');
4
- const { logInfo } = require('./logger');
5
- const { resolve } = require('node:path');
6
- const { confirm, input } = require('@inquirer/prompts');
7
- const { parse } = require('@babel/parser');
8
- const traverse = require('@babel/traverse').default;
9
-
10
- const extractRawEnvVariables = (modulePath) => {
11
- const filePath = resolve(modulePath, 'definition.js');
12
-
13
- const fileContent = fs.readFileSync(filePath, 'utf-8');
14
- const ast = parse(fileContent, {
15
- sourceType: 'module',
16
- plugins: ['jsx', 'typescript'], // Add more plugins if needed
17
- });
18
-
19
- const envVariables = {};
20
-
21
- traverse(ast, {
22
- ObjectProperty(path) {
23
- if (path.node.key.name === 'env') {
24
- path.node.value.properties.forEach((prop) => {
25
- const key = prop.key.name;
26
- if (prop.value.type === 'MemberExpression') {
27
- const property = prop.value.property.name;
28
- envVariables[key] = `${property}`;
29
- } else if (prop.value.type === 'TemplateLiteral') {
30
- // Handle template literals
31
- const expressions = prop.value.expressions.map((exp) =>
32
- exp.type === 'MemberExpression'
33
- ? `${exp.property.name}`
34
- : exp.name
35
- );
36
- envVariables[key] = expressions.join('');
37
- }
38
- });
39
- }
40
- },
41
- });
42
-
43
- return envVariables;
44
- };
45
- const handleEnvVariables = async (backendPath, modulePath) => {
46
- logInfo('Searching for missing environment variables...');
47
- const Definition = { env: extractRawEnvVariables(modulePath) };
48
- if (Definition && Definition.env) {
49
- console.log('Here is Definition.env:', Definition.env);
50
- const envVars = Object.values(Definition.env);
51
-
52
- console.log(
53
- 'Found the following environment variables in the API module:',
54
- envVars
55
- );
56
-
57
- const localEnvPath = resolve(backendPath, '../.env');
58
- const localDevConfigPath = resolve(
59
- backendPath,
60
- '../src/configs/dev.json'
61
- );
62
-
63
- // Load local .env variables
64
- let localEnvVars = {};
65
- if (existsSync(localEnvPath)) {
66
- localEnvVars = dotenv.parse(readFileSync(localEnvPath, 'utf8'));
67
- }
68
-
69
- // Load local dev.json variables
70
- let localDevConfig = {};
71
- if (existsSync(localDevConfigPath)) {
72
- localDevConfig = JSON.parse(
73
- readFileSync(localDevConfigPath, 'utf8')
74
- );
75
- }
76
-
77
- const missingEnvVars = envVars.filter(
78
- (envVar) => !localEnvVars[envVar] && !localDevConfig[envVar]
79
- );
80
-
81
- logInfo(`Missing environment variables: ${missingEnvVars.join(', ')}`);
82
-
83
- if (missingEnvVars.length > 0) {
84
- const addEnvVars = await confirm({
85
- message: `The following environment variables are required: ${missingEnvVars.join(
86
- ', '
87
- )}. Do you want to add them now?`,
88
- });
89
-
90
- if (addEnvVars) {
91
- const envValues = {};
92
- for (const envVar of missingEnvVars) {
93
- const value = await input({
94
- type: 'input',
95
- name: 'value',
96
- message: `Enter value for ${envVar}:`,
97
- });
98
- envValues[envVar] = value;
99
- }
100
-
101
- // Add the envValues to the local .env file if it exists
102
- if (existsSync(localEnvPath)) {
103
- const envContent = Object.entries(envValues)
104
- .map(([key, value]) => `${key}=${value}`)
105
- .join('\n');
106
- fs.appendFileSync(localEnvPath, `\n${envContent}`);
107
- }
108
-
109
- // Add the envValues to the local dev.json file if it exists
110
- if (existsSync(localDevConfigPath)) {
111
- const updatedDevConfig = {
112
- ...localDevConfig,
113
- ...envValues,
114
- };
115
- writeFileSync(
116
- localDevConfigPath,
117
- JSON.stringify(updatedDevConfig, null, 2)
118
- );
119
- }
120
- } else {
121
- logInfo("Edit whenever you're able, safe travels friend!");
122
- }
123
- }
124
- }
125
- };
126
-
127
- module.exports = { handleEnvVariables };
@@ -1,136 +0,0 @@
1
- const { handleEnvVariables } = require('./environment-variables');
2
- const { logInfo } = require('./logger');
3
- const inquirer = require('inquirer');
4
- const fs = require('fs');
5
- const dotenv = require('dotenv');
6
- const { resolve } = require('node:path');
7
- const { parse } = require('@babel/parser');
8
- const traverse = require('@babel/traverse');
9
-
10
- jest.mock('inquirer');
11
- jest.mock('fs');
12
- jest.mock('dotenv');
13
- jest.mock('./logger');
14
- jest.mock('@babel/parser');
15
- jest.mock('@babel/traverse');
16
-
17
- describe('handleEnvVariables', () => {
18
- const backendPath = '/mock/backend/path';
19
- const modulePath = '/mock/module/path';
20
-
21
- beforeEach(() => {
22
- jest.clearAllMocks();
23
- fs.readFileSync.mockReturnValue(`
24
- const Definition = {
25
- env: {
26
- client_id: process.env.GOOGLE_CALENDAR_CLIENT_ID,
27
- client_secret: process.env.GOOGLE_CALENDAR_CLIENT_SECRET,
28
- redirect_uri: \`\${process.env.REDIRECT_URI}/google-calendar\`,
29
- scope: process.env.GOOGLE_CALENDAR_SCOPE,
30
- }
31
- };
32
- `);
33
- parse.mockReturnValue({});
34
- traverse.default.mockImplementation((ast, visitor) => {
35
- visitor.ObjectProperty({
36
- node: {
37
- key: { name: 'env' },
38
- value: {
39
- properties: [
40
- {
41
- key: { name: 'client_id' },
42
- value: {
43
- type: 'MemberExpression',
44
- object: { name: 'process' },
45
- property: {
46
- name: 'GOOGLE_CALENDAR_CLIENT_ID',
47
- },
48
- },
49
- },
50
- {
51
- key: { name: 'client_secret' },
52
- value: {
53
- type: 'MemberExpression',
54
- object: { name: 'process' },
55
- property: {
56
- name: 'GOOGLE_CALENDAR_CLIENT_SECRET',
57
- },
58
- },
59
- },
60
- {
61
- key: { name: 'redirect_uri' },
62
- value: {
63
- type: 'MemberExpression',
64
- object: { name: 'process' },
65
- property: { name: 'REDIRECT_URI' },
66
- },
67
- },
68
- {
69
- key: { name: 'scope' },
70
- value: {
71
- type: 'MemberExpression',
72
- object: { name: 'process' },
73
- property: { name: 'GOOGLE_CALENDAR_SCOPE' },
74
- },
75
- },
76
- ],
77
- },
78
- },
79
- });
80
- });
81
- });
82
-
83
- xit('should identify and handle missing environment variables', async () => {
84
- const localEnvPath = resolve(backendPath, '../.env');
85
- const localDevConfigPath = resolve(
86
- backendPath,
87
- '../src/configs/dev.json'
88
- );
89
-
90
- fs.existsSync.mockImplementation(
91
- (path) => path === localEnvPath || path === localDevConfigPath
92
- );
93
- dotenv.parse.mockReturnValue({});
94
- fs.readFileSync.mockImplementation((path) => {
95
- if (path === resolve(modulePath, 'index.js'))
96
- return 'mock module content';
97
- if (path === localEnvPath) return '';
98
- if (path === localDevConfigPath) return '{}';
99
- return '';
100
- });
101
-
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' });
108
-
109
- await handleEnvVariables(backendPath, modulePath);
110
-
111
- expect(logInfo).toHaveBeenCalledWith(
112
- 'Searching for missing environment variables...'
113
- );
114
- expect(logInfo).toHaveBeenCalledWith(
115
- 'Missing environment variables: GOOGLE_CALENDAR_CLIENT_ID, GOOGLE_CALENDAR_CLIENT_SECRET, REDIRECT_URI, GOOGLE_CALENDAR_SCOPE'
116
- );
117
- expect(inquirer.prompt).toHaveBeenCalledTimes(5);
118
- expect(fs.appendFileSync).toHaveBeenCalledWith(
119
- localEnvPath,
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'
121
- );
122
- expect(fs.writeFileSync).toHaveBeenCalledWith(
123
- localDevConfigPath,
124
- JSON.stringify(
125
- {
126
- GOOGLE_CALENDAR_CLIENT_ID: 'client_id_value',
127
- GOOGLE_CALENDAR_CLIENT_SECRET: 'client_secret_value',
128
- REDIRECT_URI: 'redirect_uri_value',
129
- GOOGLE_CALENDAR_SCOPE: 'scope_value',
130
- },
131
- null,
132
- 2
133
- )
134
- );
135
- });
136
- });
@@ -1,54 +0,0 @@
1
- const { installPackage } = require('./install-package');
2
- const { createIntegrationFile } = require('./integration-file');
3
- const { resolve } = require('node:path');
4
- const { updateBackendJsFile } = require('./backend-js');
5
- const { logInfo, logError } = require('./logger');
6
- const { commitChanges } = require('./commit-changes');
7
- const { handleEnvVariables } = require('./environment-variables');
8
- const {
9
- validatePackageExists,
10
- searchAndSelectPackage,
11
- } = require('./validate-package');
12
- const { findNearestBackendPackageJson, validateBackendPath } = require('@friggframework/core/utils');
13
-
14
- const installCommand = async (apiModuleName) => {
15
- try {
16
- const packageNames = await searchAndSelectPackage(apiModuleName);
17
- if (!packageNames || packageNames.length === 0) return;
18
-
19
- const backendPath = findNearestBackendPackageJson();
20
- validateBackendPath(backendPath);
21
-
22
- for (const packageName of packageNames) {
23
- await validatePackageExists(packageName);
24
- installPackage(backendPath, packageName);
25
-
26
- const modulePath = resolve(
27
- backendPath,
28
- `../../node_modules/${packageName}`
29
- );
30
- const {
31
- Config: { label },
32
- Api: ApiClass,
33
- } = require(modulePath);
34
-
35
- const sanitizedLabel = label.replace(
36
- /[<>:"/\\|?*\x00-\x1F\s]/g,
37
- ''
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
- );
45
-
46
- await handleEnvVariables(backendPath, modulePath);
47
- }
48
- } catch (error) {
49
- logError('An error occurred:', error);
50
- process.exit(1);
51
- }
52
- };
53
-
54
- module.exports = { installCommand };
@@ -1,13 +0,0 @@
1
- const { execSync } = require('child_process');
2
- const path = require('path');
3
-
4
- function installPackage(backendPath, packageName) {
5
- execSync(`npm install ${packageName}`, {
6
- cwd: path.dirname(backendPath),
7
- stdio: 'inherit',
8
- });
9
- }
10
-
11
- module.exports = {
12
- installPackage,
13
- };
@@ -1,30 +0,0 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const { logInfo } = require('./logger');
4
- const { getIntegrationTemplate } = require('./template');
5
- const INTEGRATIONS_DIR = 'src/integrations';
6
-
7
- function createIntegrationFile(backendPath, apiModuleName, ApiClass) {
8
- const integrationDir = path.join(
9
- path.dirname(backendPath),
10
- INTEGRATIONS_DIR
11
- );
12
- logInfo(`Ensuring directory exists: ${integrationDir}`);
13
- fs.ensureDirSync(integrationDir);
14
-
15
- const integrationFilePath = path.join(
16
- integrationDir,
17
- `${apiModuleName}Integration.js`
18
- );
19
- logInfo(`Writing integration file: ${integrationFilePath}`);
20
- const integrationTemplate = getIntegrationTemplate(
21
- apiModuleName,
22
- backendPath,
23
- ApiClass
24
- );
25
- fs.writeFileSync(integrationFilePath, integrationTemplate);
26
- }
27
-
28
- module.exports = {
29
- createIntegrationFile,
30
- };
@@ -1,12 +0,0 @@
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
- };