@friggframework/devtools 2.0.0--canary.522.cbd3d5a.0 → 2.0.0--canary.517.21b69ac.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 (247) hide show
  1. package/.eslintrc.json +3 -0
  2. package/CHANGELOG.md +132 -0
  3. package/frigg-cli/README.md +1 -1
  4. package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
  5. package/frigg-cli/__tests__/unit/commands/install.test.js +17 -21
  6. package/frigg-cli/doctor-command/index.js +16 -17
  7. package/frigg-cli/index.js +6 -21
  8. package/frigg-cli/index.test.js +1 -7
  9. package/frigg-cli/init-command/backend-first-handler.js +42 -124
  10. package/frigg-cli/init-command/index.js +1 -2
  11. package/frigg-cli/init-command/template-handler.js +3 -13
  12. package/frigg-cli/install-command/backend-js.js +3 -3
  13. package/frigg-cli/install-command/environment-variables.js +19 -16
  14. package/frigg-cli/install-command/environment-variables.test.js +13 -12
  15. package/frigg-cli/install-command/index.js +9 -14
  16. package/frigg-cli/install-command/integration-file.js +3 -3
  17. package/frigg-cli/install-command/logger.js +12 -0
  18. package/frigg-cli/install-command/validate-package.js +9 -5
  19. package/frigg-cli/jest.config.js +1 -4
  20. package/frigg-cli/repair-command/index.js +128 -101
  21. package/frigg-cli/start-command/index.js +2 -246
  22. package/frigg-cli/ui-command/index.js +36 -58
  23. package/frigg-cli/utils/repo-detection.js +37 -85
  24. package/infrastructure/docs/iam-policy-templates.md +1 -1
  25. package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
  26. package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
  27. package/infrastructure/domains/shared/cloudformation-discovery.test.js +7 -4
  28. package/infrastructure/domains/shared/resource-discovery.js +5 -5
  29. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  30. package/infrastructure/domains/shared/utilities/base-definition-factory.js +2 -25
  31. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  32. package/infrastructure/infrastructure-composer.test.js +2 -2
  33. package/layers/prisma/.build-complete +3 -0
  34. package/layers/prisma/nodejs/package.json +8 -0
  35. package/management-ui/.eslintrc.js +22 -0
  36. package/management-ui/README.md +109 -245
  37. package/management-ui/components.json +21 -0
  38. package/management-ui/docs/phase2-integration-guide.md +320 -0
  39. package/management-ui/index.html +13 -0
  40. package/management-ui/package.json +76 -0
  41. package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
  42. package/management-ui/postcss.config.js +6 -0
  43. package/management-ui/server/api/backend.js +256 -0
  44. package/management-ui/server/api/cli.js +315 -0
  45. package/management-ui/server/api/codegen.js +663 -0
  46. package/management-ui/server/api/connections.js +857 -0
  47. package/management-ui/server/api/discovery.js +185 -0
  48. package/management-ui/server/api/environment/index.js +1 -0
  49. package/management-ui/server/api/environment/router.js +378 -0
  50. package/management-ui/server/api/environment.js +328 -0
  51. package/management-ui/server/api/integrations.js +876 -0
  52. package/management-ui/server/api/logs.js +248 -0
  53. package/management-ui/server/api/monitoring.js +282 -0
  54. package/management-ui/server/api/open-ide.js +31 -0
  55. package/management-ui/server/api/project.js +1029 -0
  56. package/management-ui/server/api/users/sessions.js +371 -0
  57. package/management-ui/server/api/users/simulation.js +254 -0
  58. package/management-ui/server/api/users.js +362 -0
  59. package/management-ui/server/api-contract.md +275 -0
  60. package/management-ui/server/index.js +873 -0
  61. package/management-ui/server/middleware/errorHandler.js +93 -0
  62. package/management-ui/server/middleware/security.js +32 -0
  63. package/management-ui/server/processManager.js +296 -0
  64. package/management-ui/server/server.js +346 -0
  65. package/management-ui/server/services/aws-monitor.js +413 -0
  66. package/management-ui/server/services/npm-registry.js +347 -0
  67. package/management-ui/server/services/template-engine.js +538 -0
  68. package/management-ui/server/utils/cliIntegration.js +220 -0
  69. package/management-ui/server/utils/environment/auditLogger.js +471 -0
  70. package/management-ui/server/utils/environment/awsParameterStore.js +275 -0
  71. package/management-ui/server/utils/environment/encryption.js +278 -0
  72. package/management-ui/server/utils/environment/envFileManager.js +286 -0
  73. package/management-ui/server/utils/import-commonjs.js +28 -0
  74. package/management-ui/server/utils/response.js +83 -0
  75. package/management-ui/server/websocket/handler.js +325 -0
  76. package/management-ui/src/App.jsx +25 -0
  77. package/management-ui/src/assets/FriggLogo.svg +1 -0
  78. package/management-ui/src/components/AppRouter.jsx +65 -0
  79. package/management-ui/src/components/Button.jsx +70 -0
  80. package/management-ui/src/components/Card.jsx +97 -0
  81. package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
  82. package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
  83. package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
  84. package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
  85. package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
  86. package/management-ui/src/components/ErrorBoundary.jsx +73 -0
  87. package/management-ui/src/components/IntegrationCard.jsx +481 -0
  88. package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
  89. package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
  90. package/management-ui/src/components/IntegrationStatus.jsx +336 -0
  91. package/management-ui/src/components/Layout.jsx +716 -0
  92. package/management-ui/src/components/LoadingSpinner.jsx +113 -0
  93. package/management-ui/src/components/RepositoryPicker.jsx +248 -0
  94. package/management-ui/src/components/SessionMonitor.jsx +350 -0
  95. package/management-ui/src/components/StatusBadge.jsx +208 -0
  96. package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
  97. package/management-ui/src/components/UserSimulation.jsx +327 -0
  98. package/management-ui/src/components/Welcome.jsx +434 -0
  99. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
  100. package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
  101. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
  102. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
  103. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
  104. package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
  105. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
  106. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
  107. package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
  108. package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
  109. package/management-ui/src/components/codegen/index.js +10 -0
  110. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
  111. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
  112. package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
  113. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
  114. package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
  115. package/management-ui/src/components/connections/index.js +5 -0
  116. package/management-ui/src/components/index.js +21 -0
  117. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
  118. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
  119. package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
  120. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
  121. package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
  122. package/management-ui/src/components/monitoring/index.js +6 -0
  123. package/management-ui/src/components/monitoring/monitoring.css +218 -0
  124. package/management-ui/src/components/theme-provider.jsx +52 -0
  125. package/management-ui/src/components/theme-toggle.jsx +39 -0
  126. package/management-ui/src/components/ui/badge.tsx +36 -0
  127. package/management-ui/src/components/ui/button.test.jsx +56 -0
  128. package/management-ui/src/components/ui/button.tsx +57 -0
  129. package/management-ui/src/components/ui/card.tsx +76 -0
  130. package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
  131. package/management-ui/src/components/ui/select.tsx +157 -0
  132. package/management-ui/src/components/ui/skeleton.jsx +15 -0
  133. package/management-ui/src/hooks/useFrigg.jsx +387 -0
  134. package/management-ui/src/hooks/useSocket.jsx +58 -0
  135. package/management-ui/src/index.css +193 -0
  136. package/management-ui/src/lib/utils.ts +6 -0
  137. package/management-ui/src/main.jsx +10 -0
  138. package/management-ui/src/pages/CodeGeneration.jsx +14 -0
  139. package/management-ui/src/pages/Connections.jsx +252 -0
  140. package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
  141. package/management-ui/src/pages/Dashboard.jsx +311 -0
  142. package/management-ui/src/pages/Environment.jsx +314 -0
  143. package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
  144. package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
  145. package/management-ui/src/pages/IntegrationTest.jsx +742 -0
  146. package/management-ui/src/pages/Integrations.jsx +253 -0
  147. package/management-ui/src/pages/Monitoring.jsx +17 -0
  148. package/management-ui/src/pages/Simulation.jsx +155 -0
  149. package/management-ui/src/pages/Users.jsx +492 -0
  150. package/management-ui/src/services/api.js +41 -0
  151. package/management-ui/src/services/apiModuleService.js +193 -0
  152. package/management-ui/src/services/websocket-handlers.js +120 -0
  153. package/management-ui/src/test/api/project.test.js +273 -0
  154. package/management-ui/src/test/components/Welcome.test.jsx +378 -0
  155. package/management-ui/src/test/mocks/server.js +178 -0
  156. package/management-ui/src/test/setup.js +61 -0
  157. package/management-ui/src/test/utils/test-utils.jsx +134 -0
  158. package/management-ui/src/utils/repository.js +98 -0
  159. package/management-ui/src/utils/repository.test.js +118 -0
  160. package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
  161. package/management-ui/tailwind.config.js +63 -0
  162. package/management-ui/tsconfig.json +37 -0
  163. package/management-ui/tsconfig.node.json +10 -0
  164. package/management-ui/vite.config.js +26 -0
  165. package/management-ui/vitest.config.js +38 -0
  166. package/package.json +7 -17
  167. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  168. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  169. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  170. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  171. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  172. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  173. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  174. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  175. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  176. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -430
  177. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  178. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  179. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  180. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  181. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  182. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  183. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  184. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  185. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  186. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  187. package/frigg-cli/container.js +0 -172
  188. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  189. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  190. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  191. package/frigg-cli/domain/entities/Integration.js +0 -198
  192. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  193. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  194. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  195. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  196. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  197. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  198. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  199. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  200. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  201. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  202. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  203. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  204. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  205. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  206. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  207. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  208. package/frigg-cli/package-lock.json +0 -16226
  209. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  210. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  211. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  212. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  213. package/frigg-cli/templates/backend/.env.example +0 -62
  214. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  215. package/frigg-cli/templates/backend/.prettierrc +0 -6
  216. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  217. package/frigg-cli/templates/backend/index.js +0 -96
  218. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  219. package/frigg-cli/templates/backend/jest.config.js +0 -17
  220. package/frigg-cli/templates/backend/package.json +0 -50
  221. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  222. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  223. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  224. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  225. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  226. package/frigg-cli/templates/backend/test/setup.js +0 -30
  227. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  228. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  229. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  230. package/frigg-cli/utils/output.js +0 -382
  231. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  232. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  233. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  234. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  235. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  236. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  237. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  238. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  239. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  240. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  241. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  242. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  243. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  244. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  245. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  246. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -128
  247. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
@@ -1,155 +0,0 @@
1
- /**
2
- * Template Validation Tests
3
- *
4
- * Validates that the frigg init templates produce valid configurations
5
- * when run through the validator.
6
- */
7
-
8
- const path = require('path');
9
- const { AppDefinitionValidator } = require('../../infrastructure/validators/app-definition-validator');
10
- const { IntegrationClassValidator } = require('../../infrastructure/validators/integration-class-validator');
11
- const { ApiModuleValidator } = require('../../infrastructure/validators/api-module-validator');
12
-
13
- // Resolve template paths relative to frigg-cli package root
14
- const FRIGG_CLI_ROOT = path.resolve(__dirname, '../../..');
15
- const TEMPLATES_DIR = path.join(FRIGG_CLI_ROOT, 'templates');
16
-
17
- describe('Template Validation', () => {
18
- let appDefinitionValidator;
19
- let integrationClassValidator;
20
- let apiModuleValidator;
21
-
22
- beforeEach(() => {
23
- appDefinitionValidator = new AppDefinitionValidator();
24
- integrationClassValidator = new IntegrationClassValidator();
25
- apiModuleValidator = new ApiModuleValidator();
26
- });
27
-
28
- describe('backend/index.js template', () => {
29
- // Load the actual template
30
- const templatePath = path.join(TEMPLATES_DIR, 'backend/index.js');
31
- let templateModule;
32
-
33
- beforeAll(() => {
34
- // Clear require cache to ensure fresh load
35
- delete require.cache[require.resolve(templatePath)];
36
- templateModule = require(templatePath);
37
- });
38
-
39
- it('exports a Definition property', () => {
40
- expect(templateModule.Definition).toBeDefined();
41
- expect(typeof templateModule.Definition).toBe('object');
42
- });
43
-
44
- it('has valid app definition structure', () => {
45
- const result = appDefinitionValidator.validate(templateModule.Definition);
46
-
47
- // Log errors for debugging
48
- if (!result.isValid()) {
49
- console.log('App Definition Errors:', result.getErrors().map(e => `${e.path}: ${e.message}`));
50
- }
51
-
52
- expect(result.isValid()).toBe(true);
53
- });
54
-
55
- it('has required integrations array', () => {
56
- expect(templateModule.Definition.integrations).toBeDefined();
57
- expect(Array.isArray(templateModule.Definition.integrations)).toBe(true);
58
- });
59
-
60
- it('has valid user configuration', () => {
61
- const userConfig = templateModule.Definition.user;
62
- expect(userConfig).toBeDefined();
63
- expect(typeof userConfig.usePassword).toBe('boolean');
64
- expect(['individual', 'organization']).toContain(userConfig.primary);
65
- });
66
-
67
- it('has valid database configuration', () => {
68
- const dbConfig = templateModule.Definition.database;
69
- expect(dbConfig).toBeDefined();
70
- // Should have at least one database type configured
71
- expect(dbConfig.postgres || dbConfig.mongoDB || dbConfig.documentDB).toBeDefined();
72
- });
73
-
74
- it('has valid vpc configuration', () => {
75
- const vpcConfig = templateModule.Definition.vpc;
76
- expect(vpcConfig).toBeDefined();
77
- expect(typeof vpcConfig.enable).toBe('boolean');
78
- });
79
-
80
- it('has valid encryption configuration', () => {
81
- const encConfig = templateModule.Definition.encryption;
82
- expect(encConfig).toBeDefined();
83
- expect(['kms', 'aes', 'none']).toContain(encConfig.fieldLevelEncryptionMethod);
84
- });
85
- });
86
-
87
- describe('ExampleIntegration template', () => {
88
- const templatePath = path.join(TEMPLATES_DIR, 'backend/src/integrations/ExampleIntegration.js');
89
- let ExampleIntegration;
90
-
91
- beforeAll(() => {
92
- // Mock @friggframework/core since it may not be installed in CLI package
93
- jest.mock('@friggframework/core', () => ({
94
- Integration: class Integration {
95
- static Config = {};
96
- }
97
- }), { virtual: true });
98
-
99
- delete require.cache[require.resolve(templatePath)];
100
- ExampleIntegration = require(templatePath);
101
- });
102
-
103
- afterAll(() => {
104
- jest.unmock('@friggframework/core');
105
- });
106
-
107
- it('is a class/function', () => {
108
- expect(typeof ExampleIntegration).toBe('function');
109
- });
110
-
111
- it('has static Definition property', () => {
112
- expect(ExampleIntegration.Definition).toBeDefined();
113
- });
114
-
115
- it('Definition has required properties', () => {
116
- const definition = ExampleIntegration.Definition;
117
- expect(definition.name).toBeDefined();
118
- expect(definition.version).toBeDefined();
119
- });
120
-
121
- it('Definition matches pattern used in core integrations', () => {
122
- // ExampleIntegration uses static Definition (not Config)
123
- // to match the pattern expected by IntegrationClassValidator
124
- expect(ExampleIntegration.Definition).toBeDefined();
125
- expect(typeof ExampleIntegration.Definition.name).toBe('string');
126
- expect(typeof ExampleIntegration.Definition.version).toBe('string');
127
- });
128
- });
129
-
130
- describe('Template schema compliance', () => {
131
- it('template app definition does not use unknown properties', () => {
132
- const templatePath = path.join(TEMPLATES_DIR, 'backend/index.js');
133
- delete require.cache[require.resolve(templatePath)];
134
- const { Definition } = require(templatePath);
135
-
136
- const result = appDefinitionValidator.validate(Definition);
137
- const errors = result.getErrors();
138
-
139
- // Check for "additional property" errors which indicate unknown fields
140
- const additionalPropErrors = errors.filter(e =>
141
- e.message.includes('additional properties') ||
142
- e.code === 'ADDITIONALPROPERTIES'
143
- );
144
-
145
- if (additionalPropErrors.length > 0) {
146
- console.log('Unknown properties in template:',
147
- additionalPropErrors.map(e => e.message));
148
- }
149
-
150
- // For now, document what additional properties exist
151
- // These may need to be added to the schema or removed from template
152
- expect(additionalPropErrors).toEqual([]);
153
- });
154
- });
155
- });
@@ -1,199 +0,0 @@
1
- const path = require('path');
2
- const fs = require('fs');
3
- const { ValidateAppUseCase } = require('../../application/use-cases/validate-app-use-case');
4
- const { AppDefinitionValidator } = require('../../infrastructure/validators/app-definition-validator');
5
- const { IntegrationClassValidator } = require('../../infrastructure/validators/integration-class-validator');
6
- const { ApiModuleValidator } = require('../../infrastructure/validators/api-module-validator');
7
-
8
- function createValidateCommand(program) {
9
- program
10
- .command('validate [path]')
11
- .description('Validate a Frigg application configuration (auto-detects local app if no path given)')
12
- .option('-f, --format <format>', 'Output format (console, json)', 'console')
13
- .option('-v, --verbose', 'Show detailed output including fix suggestions', false)
14
- .action(async (appPath, options) => {
15
- const output = require('../../../utils/output');
16
- await validateCommand(appPath, options, { output });
17
- });
18
- }
19
-
20
- function autoDetectFriggApp(startDir = process.cwd()) {
21
- let currentDir = startDir;
22
- const root = path.parse(currentDir).root;
23
-
24
- while (currentDir !== root) {
25
- const backendPath = findBackendPathInDir(currentDir);
26
- if (backendPath) {
27
- return { appRoot: currentDir, backendPath };
28
- }
29
- currentDir = path.dirname(currentDir);
30
- }
31
-
32
- return null;
33
- }
34
-
35
- function findBackendPathInDir(dir) {
36
- const backendDir = path.join(dir, 'backend');
37
- if (fs.existsSync(path.join(backendDir, 'index.js'))) {
38
- return backendDir;
39
- }
40
-
41
- if (fs.existsSync(path.join(dir, 'index.js'))) {
42
- const content = fs.readFileSync(path.join(dir, 'index.js'), 'utf-8');
43
- if (content.includes('integrations') || content.includes('Definition')) {
44
- return dir;
45
- }
46
- }
47
-
48
- return null;
49
- }
50
-
51
- function findBackendPath(startPath) {
52
- const absolutePath = path.isAbsolute(startPath) ? startPath : path.resolve(process.cwd(), startPath);
53
-
54
- const backendDir = path.join(absolutePath, 'backend');
55
- if (fs.existsSync(path.join(backendDir, 'package.json')) || fs.existsSync(path.join(backendDir, 'index.js'))) {
56
- return backendDir;
57
- }
58
-
59
- if (fs.existsSync(path.join(absolutePath, 'package.json')) || fs.existsSync(path.join(absolutePath, 'index.js'))) {
60
- return absolutePath;
61
- }
62
-
63
- return null;
64
- }
65
-
66
- function loadAppDefinition(backendPath) {
67
- const indexPath = path.join(backendPath, 'index.js');
68
- if (!fs.existsSync(indexPath)) {
69
- throw new Error(`No index.js found at ${backendPath}`);
70
- }
71
-
72
- const originalCwd = process.cwd();
73
- try {
74
- process.chdir(backendPath);
75
- delete require.cache[require.resolve(indexPath)];
76
- const exported = require(indexPath);
77
- return exported.Definition || exported.default || exported;
78
- } finally {
79
- process.chdir(originalCwd);
80
- }
81
- }
82
-
83
- async function validateCommand(appPath, options, { output }) {
84
- try {
85
- let backendPath;
86
- let definition;
87
-
88
- if (!appPath) {
89
- const detected = autoDetectFriggApp();
90
- if (!detected) {
91
- output.error('No Frigg app found. Run from within a Frigg app directory or specify a path.');
92
- return;
93
- }
94
- backendPath = detected.backendPath;
95
- output.info(`Auto-detected Frigg app at: ${detected.appRoot}`);
96
- } else {
97
- backendPath = findBackendPath(appPath);
98
- if (!backendPath) {
99
- output.error(`Could not find backend directory in ${appPath}`);
100
- return;
101
- }
102
- output.info(`Validating Frigg app at: ${appPath}`);
103
- }
104
-
105
- try {
106
- definition = loadAppDefinition(backendPath);
107
- } catch (err) {
108
- output.error(`Could not load app definition: ${err.message}`);
109
- return;
110
- }
111
-
112
- const appDefinitionValidator = new AppDefinitionValidator();
113
- const integrationClassValidator = new IntegrationClassValidator();
114
- const apiModuleValidator = new ApiModuleValidator();
115
- const useCase = new ValidateAppUseCase({
116
- appDefinitionValidator,
117
- integrationClassValidator,
118
- apiModuleValidator
119
- });
120
-
121
- const result = await useCase.execute({ definition, appPath: backendPath });
122
-
123
- if (options.format === 'json') {
124
- output.log(JSON.stringify(result.toJSON(), null, 2));
125
- return;
126
- }
127
-
128
- formatConsoleOutput(result, options, output);
129
- } catch (err) {
130
- output.error(`Validation failed: ${err.message}`);
131
- if (options.verbose) {
132
- output.error(err.stack);
133
- }
134
- }
135
- }
136
-
137
- function formatConsoleOutput(result, options, output) {
138
- const summary = result.getSummary();
139
-
140
- output.log('');
141
- output.log('═'.repeat(60));
142
- output.log(' FRIGG VALIDATE - App Configuration Report');
143
- output.log('═'.repeat(60));
144
- output.log('');
145
-
146
- if (result.isValid()) {
147
- output.success('App configuration is valid');
148
- } else {
149
- output.error(`App configuration has ${summary.errorCount} error(s)`);
150
- }
151
-
152
- if (summary.warningCount > 0) {
153
- output.warn(`${summary.warningCount} warning(s) found`);
154
- }
155
-
156
- output.log('');
157
-
158
- if (result.getErrors().length > 0) {
159
- output.log('─'.repeat(60));
160
- output.log('ERRORS:');
161
- output.log('');
162
- result.getErrors().forEach((error, idx) => {
163
- output.log(` ${idx + 1}. [${error.path}] ${error.message}`);
164
- if (options.verbose && error.fix) {
165
- output.log(` Fix: ${error.fix.description}`);
166
- if (error.fix.template) {
167
- output.log(` Template: ${JSON.stringify(error.fix.template)}`);
168
- }
169
- }
170
- });
171
- output.log('');
172
- }
173
-
174
- if (result.getWarnings().length > 0) {
175
- output.log('─'.repeat(60));
176
- output.log('WARNINGS:');
177
- output.log('');
178
- result.getWarnings().forEach((warning, idx) => {
179
- output.log(` ${idx + 1}. [${warning.path}] ${warning.message}`);
180
- if (options.verbose && warning.fix) {
181
- output.log(` Fix: ${warning.fix.description}`);
182
- }
183
- });
184
- output.log('');
185
- }
186
-
187
- output.log('═'.repeat(60));
188
- output.log('');
189
- }
190
-
191
- module.exports = {
192
- validateCommand,
193
- createValidateCommand,
194
- formatConsoleOutput,
195
- autoDetectFriggApp,
196
- findBackendPathInDir,
197
- findBackendPath,
198
- loadAppDefinition
199
- };
@@ -1,35 +0,0 @@
1
- const { ValidationResult } = require('../../domain/entities/validation-result');
2
-
3
- class ValidateAppUseCase {
4
- constructor({ appDefinitionValidator, integrationClassValidator, apiModuleValidator }) {
5
- this.appDefinitionValidator = appDefinitionValidator;
6
- this.integrationClassValidator = integrationClassValidator;
7
- this.apiModuleValidator = apiModuleValidator;
8
- }
9
-
10
- async execute({ definition, appPath }) {
11
- let result = ValidationResult.create({
12
- context: { appPath }
13
- });
14
-
15
- const appResult = this.appDefinitionValidator.validate(definition);
16
- result = result.merge(appResult);
17
-
18
- if (definition.integrations && Array.isArray(definition.integrations)) {
19
- definition.integrations.forEach((integration, index) => {
20
- const integrationResult = this.integrationClassValidator.validate(integration, index);
21
- result = result.merge(integrationResult);
22
-
23
- // Validate API modules within the integration
24
- if (this.apiModuleValidator && integration.Definition) {
25
- const moduleResult = this.apiModuleValidator.validate(integration.Definition, index);
26
- result = result.merge(moduleResult);
27
- }
28
- });
29
- }
30
-
31
- return result;
32
- }
33
- }
34
-
35
- module.exports = { ValidateAppUseCase };
@@ -1,74 +0,0 @@
1
- class ValidationResult {
2
- constructor({ errors, context }) {
3
- this.errors = errors || [];
4
- this.context = context || {};
5
- }
6
-
7
- static create(props = {}) {
8
- return new ValidationResult(props);
9
- }
10
-
11
- isValid() {
12
- return !this.errors.some(e => e.isError());
13
- }
14
-
15
- getErrors() {
16
- return this.errors.filter(e => e.isError());
17
- }
18
-
19
- getWarnings() {
20
- return this.errors.filter(e => e.isWarning());
21
- }
22
-
23
- getInfos() {
24
- return this.errors.filter(e => e.isInfo());
25
- }
26
-
27
- addError(error) {
28
- this.errors.push(error);
29
- return this;
30
- }
31
-
32
- merge(other) {
33
- return ValidationResult.create({
34
- errors: [...this.errors, ...other.errors],
35
- context: { ...this.context, ...other.context }
36
- });
37
- }
38
-
39
- getContext() {
40
- return this.context;
41
- }
42
-
43
- filterByPath(pathPrefix) {
44
- return ValidationResult.create({
45
- errors: this.errors.filter(e => e.path.startsWith(pathPrefix)),
46
- context: this.context
47
- });
48
- }
49
-
50
- getBySeverity(severity) {
51
- return this.errors.filter(e => e.severity === severity);
52
- }
53
-
54
- getSummary() {
55
- return {
56
- isValid: this.isValid(),
57
- errorCount: this.getErrors().length,
58
- warningCount: this.getWarnings().length,
59
- infoCount: this.getInfos().length,
60
- totalCount: this.errors.length
61
- };
62
- }
63
-
64
- toJSON() {
65
- return {
66
- valid: this.isValid(),
67
- errors: this.errors.map(e => e.toJSON()),
68
- summary: this.getSummary(),
69
- context: this.context
70
- };
71
- }
72
- }
73
-
74
- module.exports = { ValidationResult };
@@ -1,74 +0,0 @@
1
- const VALID_ACTIONS = ['add', 'remove', 'replace', 'rename', 'update'];
2
-
3
- class FixSuggestion {
4
- constructor({ action, description, template, codeSnippet, targetPath, targetFile }) {
5
- if (!action) {
6
- throw new Error('action is required');
7
- }
8
- if (!description) {
9
- throw new Error('description is required');
10
- }
11
- if (!VALID_ACTIONS.includes(action)) {
12
- throw new Error(`Invalid action: ${action}. Must be one of: ${VALID_ACTIONS.join(', ')}`);
13
- }
14
-
15
- this.action = action;
16
- this.description = description;
17
- this.template = template || null;
18
- this.codeSnippet = codeSnippet || null;
19
- this.targetPath = targetPath || null;
20
- this.targetFile = targetFile || null;
21
- }
22
-
23
- static create(props) {
24
- return new FixSuggestion(props);
25
- }
26
-
27
- isAdd() {
28
- return this.action === 'add';
29
- }
30
-
31
- isRemove() {
32
- return this.action === 'remove';
33
- }
34
-
35
- isReplace() {
36
- return this.action === 'replace';
37
- }
38
-
39
- isRename() {
40
- return this.action === 'rename';
41
- }
42
-
43
- isUpdate() {
44
- return this.action === 'update';
45
- }
46
-
47
- isAutoApplicable() {
48
- return this.template !== null || this.codeSnippet !== null;
49
- }
50
-
51
- toJSON() {
52
- return {
53
- action: this.action,
54
- description: this.description,
55
- template: this.template,
56
- codeSnippet: this.codeSnippet,
57
- targetPath: this.targetPath,
58
- targetFile: this.targetFile
59
- };
60
- }
61
-
62
- format() {
63
- let output = `[${this.action}] ${this.description}`;
64
- if (this.template) {
65
- output += `\n Template: ${JSON.stringify(this.template)}`;
66
- }
67
- if (this.codeSnippet) {
68
- output += `\n Code: ${this.codeSnippet}`;
69
- }
70
- return output;
71
- }
72
- }
73
-
74
- module.exports = { FixSuggestion };
@@ -1,68 +0,0 @@
1
- const VALID_SEVERITIES = ['error', 'warning', 'info'];
2
-
3
- class ValidationError {
4
- constructor({ path, message, severity, code, fix }) {
5
- if (!path) {
6
- throw new Error('path is required');
7
- }
8
- if (!message) {
9
- throw new Error('message is required');
10
- }
11
- if (severity && !VALID_SEVERITIES.includes(severity)) {
12
- throw new Error(`Invalid severity: ${severity}. Must be one of: ${VALID_SEVERITIES.join(', ')}`);
13
- }
14
-
15
- this.path = path;
16
- this.message = message;
17
- this.severity = severity || 'error';
18
- this.code = code || null;
19
- this.fix = fix || null;
20
- }
21
-
22
- static create(props) {
23
- return new ValidationError(props);
24
- }
25
-
26
- getPathSegments() {
27
- return this.path
28
- .replace(/\[(\d+)\]/g, '.$1')
29
- .split('.')
30
- .filter(Boolean);
31
- }
32
-
33
- getRootPath() {
34
- return this.getPathSegments()[0];
35
- }
36
-
37
- isError() {
38
- return this.severity === 'error';
39
- }
40
-
41
- isWarning() {
42
- return this.severity === 'warning';
43
- }
44
-
45
- isInfo() {
46
- return this.severity === 'info';
47
- }
48
-
49
- hasFix() {
50
- return this.fix !== null;
51
- }
52
-
53
- equals(other) {
54
- return this.path === other.path && this.message === other.message;
55
- }
56
-
57
- toJSON() {
58
- return {
59
- path: this.path,
60
- message: this.message,
61
- severity: this.severity,
62
- code: this.code,
63
- fix: this.fix ? this.fix.toJSON() : null
64
- };
65
- }
66
- }
67
-
68
- module.exports = { ValidationError };