@friggframework/devtools 2.0.0-next.45 → 2.0.0-next.47

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 +695 -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 -2094
  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,257 +0,0 @@
1
- const chalk = require('chalk');
2
-
3
- /**
4
- * Error Messages Module
5
- * Provides helpful, context-aware error messages for database setup issues
6
- */
7
-
8
- /**
9
- * Database URL examples for both supported database types
10
- */
11
- const DATABASE_URL_EXAMPLES = {
12
- mongodb: 'mongodb://localhost:27017/frigg?replicaSet=rs0',
13
- postgresql: 'postgresql://postgres:postgres@localhost:5432/frigg?schema=public'
14
- };
15
-
16
- /**
17
- * Gets helpful error message for missing DATABASE_URL
18
- * @returns {string} Formatted error message
19
- */
20
- function getDatabaseUrlMissingError() {
21
- return `
22
- ${chalk.red('❌ DATABASE_URL environment variable not found')}
23
-
24
- ${chalk.bold('Add DATABASE_URL to your .env file:')}
25
-
26
- ${chalk.cyan('For MongoDB:')}
27
- ${chalk.gray('DATABASE_URL')}=${chalk.green(`"${DATABASE_URL_EXAMPLES.mongodb}"`)}
28
-
29
- ${chalk.cyan('For PostgreSQL:')}
30
- ${chalk.gray('DATABASE_URL')}=${chalk.green(`"${DATABASE_URL_EXAMPLES.postgresql}"`)}
31
-
32
- ${chalk.yellow('Then run:')} ${chalk.cyan('frigg db:setup')}
33
- `;
34
- }
35
-
36
- /**
37
- * Gets helpful error message for missing database type configuration
38
- * @returns {string} Formatted error message
39
- */
40
- function getDatabaseTypeNotConfiguredError() {
41
- return `
42
- ${chalk.red('❌ Database type not configured in app definition')}
43
-
44
- ${chalk.bold('Add database configuration to your app definition file:')}
45
- ${chalk.gray('(backend/index.js or index.js)')}
46
-
47
- ${chalk.cyan('For PostgreSQL:')}
48
- ${chalk.gray(`
49
- const appDefinition = {
50
- // ... other configuration
51
- database: {
52
- postgres: { enable: true }
53
- }
54
- };
55
- `)}
56
-
57
- ${chalk.cyan('For MongoDB:')}
58
- ${chalk.gray(`
59
- const appDefinition = {
60
- // ... other configuration
61
- database: {
62
- mongoDB: { enable: true }
63
- }
64
- };
65
- `)}
66
-
67
- ${chalk.cyan('For AWS DocumentDB (MongoDB-compatible):')}
68
- ${chalk.gray(`
69
- const appDefinition = {
70
- // ... other configuration
71
- database: {
72
- documentDB: { enable: true }
73
- }
74
- };
75
- `)}
76
- `;
77
- }
78
-
79
- /**
80
- * Gets helpful error message for database connection failure
81
- * @param {string} error - Connection error message
82
- * @param {'mongodb'|'postgresql'} dbType - Database type
83
- * @returns {string} Formatted error message
84
- */
85
- function getDatabaseConnectionError(error, dbType) {
86
- const troubleshootingSteps = dbType === 'mongodb'
87
- ? getMongoDatabaseTroubleshooting()
88
- : getPostgresTroubleshooting();
89
-
90
- return `
91
- ${chalk.red('❌ Failed to connect to database')}
92
-
93
- ${chalk.bold('Connection error:')}
94
- ${chalk.gray(error)}
95
-
96
- ${chalk.bold('Troubleshooting steps:')}
97
- ${troubleshootingSteps}
98
-
99
- ${chalk.yellow('Verify your DATABASE_URL:')} ${chalk.cyan(process.env.DATABASE_URL || 'not set')}
100
- `;
101
- }
102
-
103
- /**
104
- * Gets MongoDB-specific troubleshooting steps
105
- * @returns {string} Formatted troubleshooting steps
106
- */
107
- function getMongoDatabaseTroubleshooting() {
108
- return `
109
- ${chalk.gray('1.')} Verify MongoDB is running
110
- ${chalk.cyan('docker ps')} ${chalk.gray('(if using Docker)')}
111
- ${chalk.cyan('mongosh --eval "db.version()"')} ${chalk.gray('(test connection)')}
112
-
113
- ${chalk.gray('2.')} Check if replica set is initialized
114
- ${chalk.gray('MongoDB requires a replica set for Prisma')}
115
- ${chalk.cyan('mongosh')}
116
- ${chalk.cyan('rs.status()')} ${chalk.gray('(should show replica set info)')}
117
-
118
- ${chalk.gray('3.')} Initialize replica set if needed
119
- ${chalk.cyan('docker exec -it <mongodb-container> mongosh')}
120
- ${chalk.cyan('rs.initiate()')}
121
-
122
- ${chalk.gray('4.')} Verify connection string format
123
- ${chalk.gray('mongodb://[username:password@]host[:port]/database[?options]')}
124
- ${chalk.green('Example: mongodb://localhost:27017/frigg?replicaSet=rs0')}
125
-
126
- ${chalk.gray('5.')} Check network/firewall settings
127
- ${chalk.gray('Ensure port 27017 (default) is accessible')}
128
- `;
129
- }
130
-
131
- /**
132
- * Gets PostgreSQL-specific troubleshooting steps
133
- * @returns {string} Formatted troubleshooting steps
134
- */
135
- function getPostgresTroubleshooting() {
136
- return `
137
- ${chalk.gray('1.')} Verify PostgreSQL is running
138
- ${chalk.cyan('docker ps')} ${chalk.gray('(if using Docker)')}
139
- ${chalk.cyan('pg_isready')} ${chalk.gray('(test if server is ready)')}
140
-
141
- ${chalk.gray('2.')} Check connection string format
142
- ${chalk.gray('postgresql://[username:password@]host[:port]/database[?options]')}
143
- ${chalk.green('Example: postgresql://postgres:postgres@localhost:5432/frigg?schema=public')}
144
-
145
- ${chalk.gray('3.')} Verify database exists
146
- ${chalk.cyan('psql -U postgres -l')} ${chalk.gray('(list databases)')}
147
- ${chalk.cyan('CREATE DATABASE frigg;')} ${chalk.gray('(if needed)')}
148
-
149
- ${chalk.gray('4.')} Check pg_hba.conf allows connections
150
- ${chalk.gray('Location: /var/lib/postgresql/data/pg_hba.conf (Docker)')}
151
- ${chalk.gray('Ensure trust/md5 authentication is enabled for your host')}
152
-
153
- ${chalk.gray('5.')} Verify network/firewall settings
154
- ${chalk.gray('Ensure port 5432 (default) is accessible')}
155
- `;
156
- }
157
-
158
- /**
159
- * Gets helpful error message for missing Prisma client
160
- * @param {'mongodb'|'postgresql'} dbType - Database type
161
- * @returns {string} Formatted error message
162
- */
163
- function getPrismaClientNotGeneratedError(dbType) {
164
- const clientName = `@prisma-${dbType}/client`;
165
-
166
- return `
167
- ${chalk.red(`❌ Prisma client not generated for ${dbType}`)}
168
-
169
- ${chalk.bold('The Prisma client needs to be generated before starting the application.')}
170
-
171
- ${chalk.yellow('Run:')} ${chalk.cyan('frigg db:setup')}
172
-
173
- ${chalk.gray('This will:')}
174
- ${chalk.gray(' • Generate the Prisma client')} ${chalk.gray(`(${clientName})`)}
175
- ${chalk.gray(' • Set up database schema')}
176
- ${chalk.gray(' • Run migrations (PostgreSQL) or db push (MongoDB)')}
177
- `;
178
- }
179
-
180
- /**
181
- * Gets helpful error message for Prisma command failures
182
- * @param {string} command - Command that failed (generate, migrate, push)
183
- * @param {string} error - Error message
184
- * @returns {string} Formatted error message
185
- */
186
- function getPrismaCommandError(command, error) {
187
- return `
188
- ${chalk.red(`❌ Prisma ${command} failed`)}
189
-
190
- ${chalk.bold('Error:')}
191
- ${chalk.gray(error)}
192
-
193
- ${chalk.bold('Common causes:')}
194
- ${chalk.gray(' • Database schema has conflicts')}
195
- ${chalk.gray(' • Database connection lost during operation')}
196
- ${chalk.gray(' • Insufficient permissions')}
197
- ${chalk.gray(' • Schema file is invalid')}
198
-
199
- ${chalk.yellow('Try:')}
200
- ${chalk.cyan(' frigg db:setup')} ${chalk.gray('(re-run setup)')}
201
- ${chalk.cyan(' Check your DATABASE_URL')} ${chalk.gray('(verify connection string)')}
202
- ${chalk.cyan(' Review Prisma schema')} ${chalk.gray('(node_modules/@friggframework/core/prisma-*/schema.prisma)')}
203
- `;
204
- }
205
-
206
- /**
207
- * Gets success message for database setup completion
208
- * @param {'mongodb'|'postgresql'} dbType - Database type
209
- * @param {string} stage - Deployment stage
210
- * @returns {string} Formatted success message
211
- */
212
- function getDatabaseSetupSuccess(dbType, stage) {
213
- return `
214
- ${chalk.green('✅ Database setup completed successfully!')}
215
-
216
- ${chalk.bold('Configuration:')}
217
- ${chalk.gray(' Database type:')} ${chalk.cyan(dbType)}
218
- ${chalk.gray(' Stage:')} ${chalk.cyan(stage)}
219
- ${chalk.gray(' Connection:')} ${chalk.green('verified')}
220
-
221
- ${chalk.bold('What happened:')}
222
- ${chalk.gray(' ✓')} Prisma client generated
223
- ${chalk.gray(' ✓')} Database connection verified
224
- ${chalk.gray(' ✓')} ${dbType === 'postgresql' ? 'Migrations applied' : 'Schema pushed to database'}
225
-
226
- ${chalk.yellow('Next steps:')}
227
- ${chalk.cyan(' frigg start')} ${chalk.gray('(start your application)')}
228
- `;
229
- }
230
-
231
- /**
232
- * Gets warning message for database already up-to-date
233
- * @returns {string} Formatted warning message
234
- */
235
- function getDatabaseAlreadyUpToDate() {
236
- return `
237
- ${chalk.yellow('⚠️ Database is already up-to-date')}
238
-
239
- ${chalk.gray('No migrations or schema changes detected.')}
240
-
241
- ${chalk.yellow('If you expected changes:')}
242
- ${chalk.gray(' • Check if schema was modified in node_modules/@friggframework/core/prisma-*/')}
243
- ${chalk.gray(' • Verify DATABASE_URL points to the correct database')}
244
- ${chalk.gray(' • Check if you\'re in the correct project directory')}
245
- `;
246
- }
247
-
248
- module.exports = {
249
- DATABASE_URL_EXAMPLES,
250
- getDatabaseUrlMissingError,
251
- getDatabaseTypeNotConfiguredError,
252
- getDatabaseConnectionError,
253
- getPrismaClientNotGeneratedError,
254
- getPrismaCommandError,
255
- getDatabaseSetupSuccess,
256
- getDatabaseAlreadyUpToDate
257
- };
@@ -1,167 +0,0 @@
1
- /**
2
- * NPM Registry Service for CLI
3
- * CommonJS version of the npm-registry service
4
- */
5
-
6
- 'use strict';
7
-
8
- const axios = require('axios');
9
- const NodeCache = require('node-cache');
10
- const semver = require('semver');
11
-
12
- class NPMRegistryService {
13
- constructor() {
14
- // Cache with 1 hour TTL by default
15
- this.cache = new NodeCache({
16
- stdTTL: 3600,
17
- checkperiod: 600,
18
- useClones: false
19
- });
20
-
21
- this.npmRegistryUrl = 'https://registry.npmjs.org';
22
- this.searchUrl = `${this.npmRegistryUrl}/-/v1/search`;
23
- this.packageScope = '@friggframework';
24
- this.modulePrefix = 'api-module-';
25
- }
26
-
27
- /**
28
- * Search for all @friggframework/api-module-* packages
29
- * @param {Object} options - Search options
30
- * @param {boolean} options.includePrerelease - Include prerelease versions
31
- * @param {boolean} options.forceRefresh - Force cache refresh
32
- * @returns {Promise<Array>} Array of package information
33
- */
34
- async searchApiModules(options = {}) {
35
- const cacheKey = `api-modules-${JSON.stringify(options)}`;
36
-
37
- // Check cache first unless force refresh is requested
38
- if (!options.forceRefresh) {
39
- const cached = this.cache.get(cacheKey);
40
- if (cached) {
41
- return cached;
42
- }
43
- }
44
-
45
- try {
46
- // Search for packages matching our pattern
47
- const searchQuery = `${this.packageScope}/${this.modulePrefix}`;
48
- const response = await axios.get(this.searchUrl, {
49
- params: {
50
- text: searchQuery,
51
- size: 250, // Get up to 250 results
52
- quality: 0.65,
53
- popularity: 0.98,
54
- maintenance: 0.5
55
- },
56
- timeout: 10000
57
- });
58
-
59
- const packages = response.data.objects
60
- .filter(obj => obj.package.name.startsWith(`${this.packageScope}/${this.modulePrefix}`))
61
- .map(obj => this.formatPackageInfo(obj.package));
62
-
63
- // Filter out prereleases if requested
64
- const filtered = options.includePrerelease
65
- ? packages
66
- : packages.filter(pkg => !semver.prerelease(pkg.version));
67
-
68
- // Cache the results
69
- this.cache.set(cacheKey, filtered);
70
-
71
- return filtered;
72
- } catch (error) {
73
- console.error('Error searching NPM registry:', error.message);
74
- // Return empty array on error to allow offline usage
75
- return [];
76
- }
77
- }
78
-
79
- /**
80
- * Extract integration name from package name
81
- * @private
82
- */
83
- extractIntegrationName(packageName) {
84
- return packageName
85
- .replace(`${this.packageScope}/${this.modulePrefix}`, '')
86
- .replace(/-/g, ' ')
87
- .replace(/\b\w/g, l => l.toUpperCase());
88
- }
89
-
90
- /**
91
- * Format package information for API response
92
- * @private
93
- */
94
- formatPackageInfo(pkg) {
95
- return {
96
- name: pkg.name,
97
- version: pkg.version,
98
- description: pkg.description,
99
- keywords: pkg.keywords || [],
100
- author: pkg.author,
101
- publisher: pkg.publisher,
102
- date: pkg.date,
103
- links: pkg.links,
104
- integrationName: this.extractIntegrationName(pkg.name),
105
- category: this.categorizeModule(pkg)
106
- };
107
- }
108
-
109
- /**
110
- * Categorize module based on keywords and name
111
- * @private
112
- */
113
- categorizeModule(module) {
114
- const name = module.name?.toLowerCase() || '';
115
- const keywords = module.keywords?.map(k => k.toLowerCase()) || [];
116
- const allTerms = [...keywords, name];
117
-
118
- // Categories based on common integration types - ordered by specificity
119
- const categories = {
120
- 'Marketing': ['marketing', 'mailchimp', 'campaign', 'automation', 'klaviyo', 'activecampaign'],
121
- 'CRM': ['crm', 'customer', 'salesforce', 'hubspot', 'pipedrive', 'zoho'],
122
- 'E-commerce': ['ecommerce', 'shop', 'store', 'payment', 'stripe', 'paypal', 'shopify', 'woocommerce'],
123
- 'Analytics': ['analytics', 'tracking', 'google-analytics', 'mixpanel', 'segment', 'amplitude'],
124
- 'Social Media': ['social', 'facebook', 'twitter', 'instagram', 'linkedin', 'youtube'],
125
- 'Project Management': ['project', 'task', 'jira', 'trello', 'asana', 'monday', 'notion'],
126
- 'Storage': ['storage', 'file', 'dropbox', 'google-drive', 's3', 'box', 'onedrive'],
127
- 'Productivity': ['spreadsheet', 'google-sheets', 'airtable', 'calendar', 'todo'],
128
- 'Development': ['github', 'gitlab', 'bitbucket', 'git', 'ci', 'cd', 'jenkins'],
129
- 'Support': ['support', 'zendesk', 'freshdesk', 'intercom', 'helpdesk'],
130
- 'Finance': ['accounting', 'quickbooks', 'xero', 'sage', 'invoice', 'billing'],
131
- 'Communication': ['email', 'sms', 'chat', 'messaging', 'slack', 'discord', 'twilio', 'sendgrid'],
132
- 'Other': []
133
- };
134
-
135
- for (const [category, terms] of Object.entries(categories)) {
136
- if (category === 'Other') continue;
137
-
138
- if (terms.some(term => allTerms.some(t => t.includes(term)))) {
139
- return category;
140
- }
141
- }
142
-
143
- return 'Other';
144
- }
145
-
146
- /**
147
- * Get grouped modules by integration type
148
- * @returns {Promise<Object>} Modules grouped by type
149
- */
150
- async getModulesByType() {
151
- const modules = await this.searchApiModules();
152
-
153
- const grouped = modules.reduce((acc, module) => {
154
- const type = module.category;
155
- if (!acc[type]) {
156
- acc[type] = [];
157
- }
158
- acc[type].push(module);
159
- return acc;
160
- }, {});
161
-
162
- return grouped;
163
- }
164
- }
165
-
166
- // Export singleton instance
167
- module.exports = new NPMRegistryService();
@@ -1,280 +0,0 @@
1
- const { execSync, spawn } = require('child_process');
2
- const path = require('path');
3
- const fs = require('fs');
4
- const chalk = require('chalk');
5
-
6
- /**
7
- * Prisma Command Runner Utility
8
- * Handles execution of Prisma CLI commands for database setup
9
- */
10
-
11
- /**
12
- * Gets the path to the Prisma schema file for the database type
13
- * @param {'mongodb'|'postgresql'} dbType - Database type
14
- * @param {string} projectRoot - Project root directory
15
- * @returns {string} Absolute path to schema file
16
- * @throws {Error} If schema file doesn't exist
17
- */
18
- function getPrismaSchemaPath(dbType, projectRoot = process.cwd()) {
19
- // Try multiple locations for the schema file
20
- // Priority order:
21
- // 1. Local node_modules (where @friggframework/core is installed - production scenario)
22
- // 2. Parent node_modules (workspace/monorepo setup)
23
- const possiblePaths = [
24
- // Check where Frigg is installed via npm (production scenario)
25
- path.join(projectRoot, 'node_modules', '@friggframework', 'core', `prisma-${dbType}`, 'schema.prisma'),
26
- path.join(projectRoot, '..', 'node_modules', '@friggframework', 'core', `prisma-${dbType}`, 'schema.prisma')
27
- ];
28
-
29
- for (const schemaPath of possiblePaths) {
30
- if (fs.existsSync(schemaPath)) {
31
- return schemaPath;
32
- }
33
- }
34
-
35
- // If not found in any location, throw error
36
- throw new Error(
37
- `Prisma schema not found at:\n${possiblePaths.join('\n')}\n\n` +
38
- 'Ensure @friggframework/core is installed.'
39
- );
40
- }
41
-
42
- /**
43
- * Runs prisma generate for the specified database type
44
- * @param {'mongodb'|'postgresql'} dbType - Database type
45
- * @param {boolean} verbose - Enable verbose output
46
- * @returns {Promise<Object>} { success: boolean, output?: string, error?: string }
47
- */
48
- async function runPrismaGenerate(dbType, verbose = false) {
49
- try {
50
- const schemaPath = getPrismaSchemaPath(dbType);
51
-
52
- if (verbose) {
53
- console.log(chalk.gray(`Running: npx prisma generate --schema=${schemaPath}`));
54
- }
55
-
56
- const output = execSync(
57
- `npx prisma generate --schema=${schemaPath}`,
58
- {
59
- encoding: 'utf8',
60
- stdio: verbose ? 'inherit' : 'pipe',
61
- env: {
62
- ...process.env,
63
- // Suppress Prisma telemetry prompts
64
- PRISMA_HIDE_UPDATE_MESSAGE: '1'
65
- }
66
- }
67
- );
68
-
69
- return {
70
- success: true,
71
- output: verbose ? 'Generated successfully' : output
72
- };
73
-
74
- } catch (error) {
75
- return {
76
- success: false,
77
- error: error.message,
78
- output: error.stdout?.toString() || error.stderr?.toString()
79
- };
80
- }
81
- }
82
-
83
- /**
84
- * Checks database migration status
85
- * @param {'mongodb'|'postgresql'} dbType - Database type
86
- * @returns {Promise<Object>} { upToDate: boolean, pendingMigrations?: number, error?: string }
87
- */
88
- async function checkDatabaseState(dbType) {
89
- try {
90
- // Only applicable for PostgreSQL (MongoDB uses db push)
91
- if (dbType !== 'postgresql') {
92
- return { upToDate: true };
93
- }
94
-
95
- const schemaPath = getPrismaSchemaPath(dbType);
96
-
97
- const output = execSync(
98
- `npx prisma migrate status --schema=${schemaPath}`,
99
- {
100
- encoding: 'utf8',
101
- stdio: 'pipe',
102
- env: {
103
- ...process.env,
104
- PRISMA_HIDE_UPDATE_MESSAGE: '1'
105
- }
106
- }
107
- );
108
-
109
- if (output.includes('Database schema is up to date')) {
110
- return { upToDate: true };
111
- }
112
-
113
- // Parse pending migrations count
114
- const pendingMatch = output.match(/(\d+) migration/);
115
- const pendingMigrations = pendingMatch ? parseInt(pendingMatch[1]) : 0;
116
-
117
- return {
118
- upToDate: false,
119
- pendingMigrations
120
- };
121
-
122
- } catch (error) {
123
- // If migrate status fails, database might not be initialized
124
- return {
125
- upToDate: false,
126
- error: error.message
127
- };
128
- }
129
- }
130
-
131
- /**
132
- * Runs Prisma migrate for PostgreSQL
133
- * @param {'dev'|'deploy'} command - Migration command (dev or deploy)
134
- * @param {boolean} verbose - Enable verbose output
135
- * @returns {Promise<Object>} { success: boolean, output?: string, error?: string }
136
- */
137
- async function runPrismaMigrate(command = 'dev', verbose = false) {
138
- return new Promise((resolve) => {
139
- try {
140
- const schemaPath = getPrismaSchemaPath('postgresql');
141
-
142
- const args = [
143
- 'prisma',
144
- 'migrate',
145
- command,
146
- '--schema',
147
- schemaPath
148
- ];
149
-
150
- if (verbose) {
151
- console.log(chalk.gray(`Running: npx ${args.join(' ')}`));
152
- }
153
-
154
- const proc = spawn('npx', args, {
155
- stdio: 'inherit',
156
- env: {
157
- ...process.env,
158
- PRISMA_HIDE_UPDATE_MESSAGE: '1'
159
- }
160
- });
161
-
162
- proc.on('error', (error) => {
163
- resolve({
164
- success: false,
165
- error: error.message
166
- });
167
- });
168
-
169
- proc.on('close', (code) => {
170
- if (code === 0) {
171
- resolve({
172
- success: true,
173
- output: 'Migration completed successfully'
174
- });
175
- } else {
176
- resolve({
177
- success: false,
178
- error: `Migration process exited with code ${code}`
179
- });
180
- }
181
- });
182
-
183
- } catch (error) {
184
- resolve({
185
- success: false,
186
- error: error.message
187
- });
188
- }
189
- });
190
- }
191
-
192
- /**
193
- * Runs Prisma db push for MongoDB
194
- * Interactive - will prompt user if data loss detected
195
- * @param {boolean} verbose - Enable verbose output
196
- * @returns {Promise<Object>} { success: boolean, output?: string, error?: string }
197
- */
198
- async function runPrismaDbPush(verbose = false) {
199
- return new Promise((resolve) => {
200
- try {
201
- const schemaPath = getPrismaSchemaPath('mongodb');
202
-
203
- const args = [
204
- 'prisma',
205
- 'db',
206
- 'push',
207
- '--schema',
208
- schemaPath,
209
- '--skip-generate' // We generate separately
210
- ];
211
-
212
- if (verbose) {
213
- console.log(chalk.gray(`Running: npx ${args.join(' ')}`));
214
- }
215
-
216
- console.log(chalk.yellow('⚠️ Interactive mode: You may be prompted if schema changes cause data loss'));
217
-
218
- const proc = spawn('npx', args, {
219
- stdio: 'inherit', // Interactive mode - user can respond to prompts
220
- env: {
221
- ...process.env,
222
- PRISMA_HIDE_UPDATE_MESSAGE: '1'
223
- }
224
- });
225
-
226
- proc.on('error', (error) => {
227
- resolve({
228
- success: false,
229
- error: error.message
230
- });
231
- });
232
-
233
- proc.on('close', (code) => {
234
- if (code === 0) {
235
- resolve({
236
- success: true,
237
- output: 'Database push completed successfully'
238
- });
239
- } else {
240
- resolve({
241
- success: false,
242
- error: `Database push process exited with code ${code}`
243
- });
244
- }
245
- });
246
-
247
- } catch (error) {
248
- resolve({
249
- success: false,
250
- error: error.message
251
- });
252
- }
253
- });
254
- }
255
-
256
- /**
257
- * Determines migration command based on STAGE environment variable
258
- * @param {string} stage - Stage from CLI option or environment
259
- * @returns {'dev'|'deploy'}
260
- */
261
- function getMigrationCommand(stage) {
262
- const normalizedStage = (stage || process.env.STAGE || 'development').toLowerCase();
263
-
264
- const developmentStages = ['dev', 'local', 'test', 'development'];
265
-
266
- if (developmentStages.includes(normalizedStage)) {
267
- return 'dev';
268
- }
269
-
270
- return 'deploy';
271
- }
272
-
273
- module.exports = {
274
- getPrismaSchemaPath,
275
- runPrismaGenerate,
276
- checkDatabaseState,
277
- runPrismaMigrate,
278
- runPrismaDbPush,
279
- getMigrationCommand
280
- };