@friggframework/devtools 2.0.0--canary.545.e256e95.0 → 2.0.0--canary.553.dc5f898.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/frigg-cli/README.md +1 -1
  2. package/frigg-cli/__tests__/unit/commands/build.test.js +1 -1
  3. package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
  4. package/frigg-cli/__tests__/unit/commands/install.test.js +19 -23
  5. package/frigg-cli/__tests__/unit/dependencies.test.js +2 -2
  6. package/frigg-cli/build-command/index.js +11 -123
  7. package/frigg-cli/deploy-command/index.js +1 -83
  8. package/frigg-cli/doctor-command/index.js +16 -37
  9. package/frigg-cli/generate-iam-command.js +1 -21
  10. package/frigg-cli/index.js +6 -21
  11. package/frigg-cli/index.test.js +2 -7
  12. package/frigg-cli/init-command/backend-first-handler.js +42 -124
  13. package/frigg-cli/init-command/index.js +1 -2
  14. package/frigg-cli/init-command/template-handler.js +3 -13
  15. package/frigg-cli/install-command/backend-js.js +3 -3
  16. package/frigg-cli/install-command/environment-variables.js +19 -16
  17. package/frigg-cli/install-command/environment-variables.test.js +13 -12
  18. package/frigg-cli/install-command/index.js +9 -14
  19. package/frigg-cli/install-command/integration-file.js +3 -3
  20. package/frigg-cli/install-command/logger.js +12 -0
  21. package/frigg-cli/install-command/validate-package.js +9 -5
  22. package/frigg-cli/jest.config.js +1 -4
  23. package/frigg-cli/repair-command/index.js +128 -121
  24. package/frigg-cli/start-command/index.js +2 -324
  25. package/frigg-cli/ui-command/index.js +36 -58
  26. package/frigg-cli/utils/repo-detection.js +37 -85
  27. package/infrastructure/create-frigg-infrastructure.js +0 -93
  28. package/infrastructure/docs/iam-policy-templates.md +1 -1
  29. package/infrastructure/domains/integration/integration-builder.js +3 -2
  30. package/infrastructure/domains/integration/integration-builder.test.js +54 -2
  31. package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
  32. package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
  33. package/infrastructure/domains/shared/resource-discovery.js +5 -5
  34. package/infrastructure/domains/shared/types/app-definition.js +0 -35
  35. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  36. package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
  37. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  38. package/infrastructure/infrastructure-composer.js +0 -2
  39. package/infrastructure/infrastructure-composer.test.js +6 -5
  40. package/management-ui/README.md +109 -245
  41. package/package.json +7 -8
  42. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  43. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  44. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  45. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  46. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  47. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  48. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  49. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  50. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  51. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
  52. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  53. package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
  54. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  55. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  56. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  57. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  58. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  59. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  60. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  61. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  62. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  63. package/frigg-cli/container.js +0 -172
  64. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  65. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  66. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  67. package/frigg-cli/domain/entities/Integration.js +0 -198
  68. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  69. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  70. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  71. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  72. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  73. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  74. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  75. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  76. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  77. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  78. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  79. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  80. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  81. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  82. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  83. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  84. package/frigg-cli/package-lock.json +0 -16226
  85. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  86. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  87. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  88. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  89. package/frigg-cli/templates/backend/.env.example +0 -62
  90. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  91. package/frigg-cli/templates/backend/.prettierrc +0 -6
  92. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  93. package/frigg-cli/templates/backend/index.js +0 -96
  94. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  95. package/frigg-cli/templates/backend/jest.config.js +0 -17
  96. package/frigg-cli/templates/backend/package.json +0 -50
  97. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  98. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  99. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  100. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  101. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  102. package/frigg-cli/templates/backend/test/setup.js +0 -30
  103. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  104. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  105. package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
  106. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  107. package/frigg-cli/utils/output.js +0 -382
  108. package/frigg-cli/utils/provider-helper.js +0 -75
  109. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  110. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  111. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  112. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  113. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  114. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  115. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  116. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  117. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  118. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  119. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  120. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  121. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  122. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  123. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  124. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -145
  125. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
  126. package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
  127. package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
  128. package/infrastructure/domains/admin-scripts/index.js +0 -5
  129. package/infrastructure/jest.config.js +0 -16
@@ -1,332 +0,0 @@
1
- const { ApiModuleValidator } = require('../../infrastructure/validators/api-module-validator');
2
-
3
- describe('ApiModuleValidator', () => {
4
- let validator;
5
-
6
- beforeEach(() => {
7
- validator = new ApiModuleValidator();
8
- });
9
-
10
- describe('valid modules', () => {
11
- it('validates integration with no modules', () => {
12
- const definition = {
13
- name: 'test-integration',
14
- version: '1.0.0'
15
- };
16
-
17
- const result = validator.validate(definition, 0);
18
- expect(result.isValid()).toBe(true);
19
- expect(result.getErrors()).toHaveLength(0);
20
- });
21
-
22
- it('validates integration with valid module definition', () => {
23
- const definition = {
24
- name: 'test-integration',
25
- version: '1.0.0',
26
- modules: {
27
- hubspot: {
28
- definition: {
29
- moduleName: 'hubspot',
30
- getName: { type: 'function' },
31
- requiredAuthMethods: {
32
- getToken: { type: 'function', async: true },
33
- getCredentialDetails: { type: 'function', async: true },
34
- getEntityDetails: { type: 'function', async: true },
35
- apiPropertiesToPersist: {
36
- credential: ['access_token', 'refresh_token'],
37
- entity: ['external_id', 'name']
38
- }
39
- }
40
- }
41
- }
42
- }
43
- };
44
-
45
- const result = validator.validate(definition, 0);
46
- expect(result.isValid()).toBe(true);
47
- });
48
-
49
- it('validates module with actual functions (not descriptors)', () => {
50
- // Real-world API modules have actual functions, not {type: "function"} descriptors
51
- // The validator should sanitize these before JSON Schema validation
52
- const definition = {
53
- name: 'test-integration',
54
- version: '1.0.0',
55
- modules: {
56
- xero: {
57
- definition: {
58
- moduleName: 'xero',
59
- getName: function() { return 'Xero'; },
60
- API: class XeroApi {},
61
- requiredAuthMethods: {
62
- getToken: async function() { return {}; },
63
- getCredentialDetails: async function() { return {}; },
64
- getEntityDetails: async function() { return {}; },
65
- apiPropertiesToPersist: {
66
- credential: ['access_token', 'refresh_token'],
67
- entity: ['tenant_id', 'name']
68
- }
69
- }
70
- }
71
- }
72
- }
73
- };
74
-
75
- const result = validator.validate(definition, 0);
76
- // Should not have errors about "must be object" for functions
77
- const typeErrors = result.getErrors().filter(e =>
78
- e.message.includes('must be object') ||
79
- e.message.includes('must be Object')
80
- );
81
- expect(typeErrors).toHaveLength(0);
82
- });
83
-
84
-
85
- it('validates multiple modules', () => {
86
- const definition = {
87
- name: 'test-integration',
88
- version: '1.0.0',
89
- modules: {
90
- source: {
91
- definition: {
92
- moduleName: 'source-api',
93
- getName: { type: 'function' },
94
- requiredAuthMethods: {
95
- getToken: { type: 'function', async: true },
96
- getCredentialDetails: { type: 'function', async: true },
97
- getEntityDetails: { type: 'function', async: true },
98
- apiPropertiesToPersist: {
99
- credential: ['token'],
100
- entity: ['id']
101
- }
102
- }
103
- }
104
- },
105
- target: {
106
- definition: {
107
- moduleName: 'target-api',
108
- getName: { type: 'function' },
109
- requiredAuthMethods: {
110
- getToken: { type: 'function', async: true },
111
- getCredentialDetails: { type: 'function', async: true },
112
- getEntityDetails: { type: 'function', async: true },
113
- apiPropertiesToPersist: {
114
- credential: ['api_key'],
115
- entity: ['external_id']
116
- }
117
- }
118
- }
119
- }
120
- }
121
- };
122
-
123
- const result = validator.validate(definition, 0);
124
- expect(result.isValid()).toBe(true);
125
- });
126
- });
127
-
128
- describe('missing definition', () => {
129
- it('errors when module lacks definition property', () => {
130
- const definition = {
131
- name: 'test-integration',
132
- version: '1.0.0',
133
- modules: {
134
- hubspot: {
135
- // missing definition
136
- }
137
- }
138
- };
139
-
140
- const result = validator.validate(definition, 0);
141
- expect(result.isValid()).toBe(false);
142
- expect(result.getErrors().some(e => e.code === 'MISSING_DEFINITION')).toBe(true);
143
- });
144
- });
145
-
146
- describe('schema validation', () => {
147
- it('errors when moduleName is missing', () => {
148
- const definition = {
149
- name: 'test-integration',
150
- version: '1.0.0',
151
- modules: {
152
- hubspot: {
153
- definition: {
154
- // missing moduleName
155
- getName: { type: 'function' },
156
- requiredAuthMethods: {}
157
- }
158
- }
159
- }
160
- };
161
-
162
- const result = validator.validate(definition, 0);
163
- expect(result.isValid()).toBe(false);
164
- expect(result.getErrors().some(e =>
165
- e.path.includes('definition') && e.message.includes('moduleName')
166
- )).toBe(true);
167
- });
168
-
169
- it('errors when moduleName has invalid pattern', () => {
170
- const definition = {
171
- name: 'test-integration',
172
- version: '1.0.0',
173
- modules: {
174
- test: {
175
- definition: {
176
- moduleName: '123-invalid', // must start with letter
177
- getName: { type: 'function' },
178
- requiredAuthMethods: {}
179
- }
180
- }
181
- }
182
- };
183
-
184
- const result = validator.validate(definition, 0);
185
- expect(result.isValid()).toBe(false);
186
- });
187
- });
188
-
189
- describe('method validation', () => {
190
- it('warns when getToken is missing', () => {
191
- const definition = {
192
- name: 'test-integration',
193
- version: '1.0.0',
194
- modules: {
195
- test: {
196
- definition: {
197
- moduleName: 'test-module',
198
- getName: { type: 'function' },
199
- requiredAuthMethods: {
200
- getCredentialDetails: { type: 'function' },
201
- getEntityDetails: { type: 'function' }
202
- // missing getToken
203
- }
204
- }
205
- }
206
- }
207
- };
208
-
209
- const result = validator.validate(definition, 0);
210
- const warnings = result.getWarnings();
211
- expect(warnings.some(w =>
212
- w.code === 'MISSING_METHOD' && w.message.includes('getToken')
213
- )).toBe(true);
214
- });
215
-
216
- it('warns when getEntityDetails is missing', () => {
217
- const definition = {
218
- name: 'test-integration',
219
- version: '1.0.0',
220
- modules: {
221
- test: {
222
- definition: {
223
- moduleName: 'test-module',
224
- getName: { type: 'function' },
225
- requiredAuthMethods: {
226
- getToken: { type: 'function' },
227
- getCredentialDetails: { type: 'function' }
228
- // missing getEntityDetails
229
- }
230
- }
231
- }
232
- }
233
- };
234
-
235
- const result = validator.validate(definition, 0);
236
- const warnings = result.getWarnings();
237
- expect(warnings.some(w =>
238
- w.code === 'MISSING_METHOD' && w.message.includes('getEntityDetails')
239
- )).toBe(true);
240
- });
241
- });
242
-
243
- describe('apiPropertiesToPersist validation', () => {
244
- it('warns when credential properties are missing', () => {
245
- const definition = {
246
- name: 'test-integration',
247
- version: '1.0.0',
248
- modules: {
249
- test: {
250
- definition: {
251
- moduleName: 'test-module',
252
- getName: { type: 'function' },
253
- requiredAuthMethods: {
254
- getToken: { type: 'function' },
255
- getCredentialDetails: { type: 'function' },
256
- getEntityDetails: { type: 'function' },
257
- apiPropertiesToPersist: {
258
- credential: [], // empty
259
- entity: ['external_id']
260
- }
261
- }
262
- }
263
- }
264
- }
265
- };
266
-
267
- const result = validator.validate(definition, 0);
268
- const warnings = result.getWarnings();
269
- expect(warnings.some(w => w.code === 'MISSING_CREDENTIAL_PROPS')).toBe(true);
270
- });
271
-
272
- it('warns when entity properties are missing', () => {
273
- const definition = {
274
- name: 'test-integration',
275
- version: '1.0.0',
276
- modules: {
277
- test: {
278
- definition: {
279
- moduleName: 'test-module',
280
- getName: { type: 'function' },
281
- requiredAuthMethods: {
282
- getToken: { type: 'function' },
283
- getCredentialDetails: { type: 'function' },
284
- getEntityDetails: { type: 'function' },
285
- apiPropertiesToPersist: {
286
- credential: ['access_token'],
287
- entity: [] // empty
288
- }
289
- }
290
- }
291
- }
292
- }
293
- };
294
-
295
- const result = validator.validate(definition, 0);
296
- const warnings = result.getWarnings();
297
- expect(warnings.some(w => w.code === 'MISSING_ENTITY_PROPS')).toBe(true);
298
- });
299
- });
300
-
301
- describe('path formatting', () => {
302
- it('includes correct path prefix for errors', () => {
303
- const definition = {
304
- name: 'test-integration',
305
- version: '1.0.0',
306
- modules: {
307
- myModule: {
308
- definition: {
309
- // missing required fields
310
- }
311
- }
312
- }
313
- };
314
-
315
- const result = validator.validate(definition, 2);
316
- const errors = result.getErrors();
317
- expect(errors[0].path).toContain('integrations[2].Definition.modules.myModule');
318
- });
319
- });
320
-
321
- describe('result type', () => {
322
- it('returns ValidationResult instance', () => {
323
- const definition = {
324
- name: 'test-integration',
325
- version: '1.0.0'
326
- };
327
-
328
- const result = validator.validate(definition, 0);
329
- expect(result.constructor.name).toBe('ValidationResult');
330
- });
331
- });
332
- });
@@ -1,191 +0,0 @@
1
- const { AppDefinitionValidator } = require('../../infrastructure/validators/app-definition-validator');
2
- const { ValidationResult } = require('../../domain/entities/validation-result');
3
-
4
- describe('AppDefinitionValidator', () => {
5
- let validator;
6
-
7
- beforeEach(() => {
8
- validator = new AppDefinitionValidator();
9
- });
10
-
11
- describe('valid definitions', () => {
12
- it('validates minimal valid definition', () => {
13
- const definition = {
14
- integrations: []
15
- };
16
- const result = validator.validate(definition);
17
- expect(result.isValid()).toBe(true);
18
- });
19
-
20
- it('validates definition with database config', () => {
21
- const definition = {
22
- integrations: [],
23
- database: { mongoDB: { enable: true } }
24
- };
25
- const result = validator.validate(definition);
26
- expect(result.isValid()).toBe(true);
27
- });
28
-
29
- it('validates definition with integration objects', () => {
30
- const definition = {
31
- integrations: [{ Definition: { name: 'test-integration' } }]
32
- };
33
- const result = validator.validate(definition);
34
- expect(result.isValid()).toBe(true);
35
- });
36
-
37
- it('validates definition with integration classes (functions)', () => {
38
- // This tests that integration classes are properly sanitized
39
- // before JSON Schema validation (classes become stub objects)
40
- class MyIntegration {
41
- static Definition = {
42
- name: 'my-integration',
43
- version: '1.0.0'
44
- };
45
- }
46
- const definition = {
47
- integrations: [MyIntegration]
48
- };
49
- const result = validator.validate(definition);
50
- // Should not have schema errors about "must be object"
51
- const schemaErrors = result.getErrors().filter(e =>
52
- e.message.includes('must be object') ||
53
- e.message.includes('must be Object')
54
- );
55
- expect(schemaErrors).toHaveLength(0);
56
- });
57
-
58
- it('validates definition with multiple integration classes', () => {
59
- class IntegrationA {
60
- static Definition = { name: 'integration-a', version: '1.0.0' };
61
- }
62
- class IntegrationB {
63
- static Definition = { name: 'integration-b', version: '1.0.0' };
64
- }
65
- const definition = {
66
- integrations: [IntegrationA, IntegrationB]
67
- };
68
- const result = validator.validate(definition);
69
- expect(result.isValid()).toBe(true);
70
- });
71
- });
72
-
73
- describe('integrations validation', () => {
74
- it('errors when integrations is not an array', () => {
75
- const definition = { integrations: 'not-an-array' };
76
- const result = validator.validate(definition);
77
- expect(result.isValid()).toBe(false);
78
- expect(result.getErrors()[0].path).toBe('integrations');
79
- });
80
-
81
- it('errors when integrations is missing', () => {
82
- const definition = {};
83
- const result = validator.validate(definition);
84
- expect(result.isValid()).toBe(false);
85
- expect(result.getErrors().some(e => e.message.includes('integrations'))).toBe(true);
86
- });
87
-
88
- it('errors when integration lacks Definition property', () => {
89
- const BadIntegration = class {};
90
- const definition = { integrations: [BadIntegration] };
91
- const result = validator.validate(definition);
92
- expect(result.isValid()).toBe(false);
93
- expect(result.getErrors().some(e => e.path === 'integrations[0]' && e.message.includes('Definition'))).toBe(true);
94
- });
95
-
96
- it('errors when integration Definition lacks name', () => {
97
- const BadIntegration = class {
98
- static Definition = {};
99
- };
100
- const definition = { integrations: [BadIntegration] };
101
- const result = validator.validate(definition);
102
- expect(result.isValid()).toBe(false);
103
- expect(result.getErrors().some(e => e.path.includes('integrations[0]') && e.message.includes('name'))).toBe(true);
104
- });
105
-
106
- it('warns on duplicate integration names', () => {
107
- const Int1 = class { static Definition = { name: 'same-name', version: '1.0.0' }; };
108
- const Int2 = class { static Definition = { name: 'same-name', version: '1.0.0' }; };
109
- const definition = { integrations: [Int1, Int2] };
110
- const result = validator.validate(definition);
111
- expect(result.getWarnings().some(w => w.message.includes('duplicate'))).toBe(true);
112
- });
113
- });
114
-
115
- describe('database validation', () => {
116
- it('validates mongoDB configuration', () => {
117
- const definition = {
118
- integrations: [],
119
- database: { mongoDB: { enable: true } }
120
- };
121
- const result = validator.validate(definition);
122
- const dbErrors = result.getErrors().filter(e => e.path.startsWith('database'));
123
- expect(dbErrors).toHaveLength(0);
124
- });
125
-
126
- it('validates postgres configuration', () => {
127
- const definition = {
128
- integrations: [],
129
- database: { postgres: { enable: true } }
130
- };
131
- const result = validator.validate(definition);
132
- const dbErrors = result.getErrors().filter(e => e.path.startsWith('database'));
133
- expect(dbErrors).toHaveLength(0);
134
- });
135
-
136
- it('validates documentDB configuration', () => {
137
- const definition = {
138
- integrations: [],
139
- database: { documentDB: { enable: true } }
140
- };
141
- const result = validator.validate(definition);
142
- const dbErrors = result.getErrors().filter(e => e.path.startsWith('database'));
143
- expect(dbErrors).toHaveLength(0);
144
- });
145
- });
146
-
147
- describe('user configuration', () => {
148
- it('validates user with password enabled', () => {
149
- const definition = {
150
- integrations: [],
151
- user: { usePassword: true }
152
- };
153
- const result = validator.validate(definition);
154
- const userErrors = result.getErrors().filter(e => e.path.startsWith('user'));
155
- expect(userErrors).toHaveLength(0);
156
- });
157
-
158
- it('validates user with custom model object', () => {
159
- const definition = {
160
- integrations: [],
161
- user: { model: { name: 'CustomUserModel' } }
162
- };
163
- const result = validator.validate(definition);
164
- const userErrors = result.getErrors().filter(e => e.path.startsWith('user'));
165
- expect(userErrors).toHaveLength(0);
166
- });
167
-
168
- it('validates user authModes configuration', () => {
169
- const definition = {
170
- integrations: [],
171
- user: {
172
- authModes: {
173
- friggToken: true,
174
- sharedSecret: true
175
- }
176
- }
177
- };
178
- const result = validator.validate(definition);
179
- const userErrors = result.getErrors().filter(e => e.path.startsWith('user'));
180
- expect(userErrors).toHaveLength(0);
181
- });
182
- });
183
-
184
- describe('result type', () => {
185
- it('returns ValidationResult instance', () => {
186
- const definition = { integrations: [] };
187
- const result = validator.validate(definition);
188
- expect(result).toBeInstanceOf(ValidationResult);
189
- });
190
- });
191
- });
@@ -1,146 +0,0 @@
1
- const { IntegrationClassValidator } = require('../../infrastructure/validators/integration-class-validator');
2
-
3
- describe('IntegrationClassValidator', () => {
4
- let validator;
5
-
6
- beforeEach(() => {
7
- validator = new IntegrationClassValidator();
8
- });
9
-
10
- describe('valid integration classes', () => {
11
- it('validates class with Definition static property', () => {
12
- class ValidIntegration {
13
- static Definition = {
14
- name: 'test-integration',
15
- version: '1.0.0',
16
- modules: {}
17
- };
18
- }
19
- const result = validator.validate(ValidIntegration, 0);
20
- expect(result.isValid()).toBe(true);
21
- });
22
-
23
- it('validates class with modules configuration', () => {
24
- class ValidIntegration {
25
- static Definition = {
26
- name: 'oauth-integration',
27
- version: '1.0.0',
28
- modules: {
29
- hubspot: {
30
- definition: { moduleName: 'hubspot' },
31
- options: {}
32
- }
33
- }
34
- };
35
- }
36
- const result = validator.validate(ValidIntegration, 0);
37
- expect(result.isValid()).toBe(true);
38
- });
39
- });
40
-
41
- describe('invalid integration classes', () => {
42
- it('errors when not a function/class', () => {
43
- const notAClass = { Definition: { name: 'test' } };
44
- const result = validator.validate(notAClass, 0);
45
- expect(result.isValid()).toBe(false);
46
- expect(result.getErrors()[0].message).toContain('class');
47
- });
48
-
49
- it('errors when Definition is missing', () => {
50
- class NoDefinition {}
51
- const result = validator.validate(NoDefinition, 0);
52
- expect(result.isValid()).toBe(false);
53
- expect(result.getErrors()[0].path).toBe('integrations[0].Definition');
54
- });
55
-
56
- it('errors when Definition.name is missing', () => {
57
- class MissingName {
58
- static Definition = { version: '1.0.0' };
59
- }
60
- const result = validator.validate(MissingName, 0);
61
- expect(result.isValid()).toBe(false);
62
- expect(result.getErrors()[0].path).toBe('integrations[0].Definition');
63
- expect(result.getErrors()[0].message).toContain('name');
64
- });
65
-
66
- it('errors when Definition.name is not a string', () => {
67
- class BadName {
68
- static Definition = { name: 123, version: '1.0.0' };
69
- }
70
- const result = validator.validate(BadName, 0);
71
- expect(result.isValid()).toBe(false);
72
- expect(result.getErrors()[0].path).toBe('integrations[0].Definition.name');
73
- });
74
- });
75
-
76
- describe('modules validation', () => {
77
- it('errors when module lacks definition', () => {
78
- class BadModule {
79
- static Definition = {
80
- name: 'test',
81
- version: '1.0.0',
82
- modules: {
83
- hubspot: { options: {} }
84
- }
85
- };
86
- }
87
- const result = validator.validate(BadModule, 0);
88
- expect(result.isValid()).toBe(false);
89
- expect(result.getErrors().some(e => e.path.includes('modules.hubspot') && e.message.includes('definition'))).toBe(true);
90
- });
91
-
92
- it('warns when module definition lacks moduleName', () => {
93
- class ModuleNoModuleName {
94
- static Definition = {
95
- name: 'test',
96
- version: '1.0.0',
97
- modules: {
98
- hubspot: {
99
- definition: {},
100
- options: {}
101
- }
102
- }
103
- };
104
- }
105
- const result = validator.validate(ModuleNoModuleName, 0);
106
- expect(result.getWarnings().some(w =>
107
- w.code === 'MISSING_MODULE_NAME' && w.message.includes('moduleName')
108
- )).toBe(true);
109
- });
110
- });
111
-
112
- describe('lifecycle methods', () => {
113
- it('warns when onCreate is not implemented', () => {
114
- class NoOnCreate {
115
- static Definition = { name: 'test-integration', version: '1.0.0' };
116
- }
117
- const result = validator.validate(NoOnCreate, 0);
118
- expect(result.getWarnings().some(w => w.message.includes('onCreate'))).toBe(true);
119
- });
120
-
121
- it('passes when onCreate is implemented', () => {
122
- class WithOnCreate {
123
- static Definition = { name: 'test-integration', version: '1.0.0' };
124
- async onCreate() {}
125
- }
126
- const result = validator.validate(WithOnCreate, 0);
127
- expect(result.getWarnings().filter(w => w.message.includes('onCreate'))).toHaveLength(0);
128
- });
129
-
130
- it('warns when getConfigOptions is not implemented', () => {
131
- class NoConfigOptions {
132
- static Definition = { name: 'test-integration', version: '1.0.0' };
133
- }
134
- const result = validator.validate(NoConfigOptions, 0);
135
- expect(result.getWarnings().some(w => w.message.includes('getConfigOptions'))).toBe(true);
136
- });
137
- });
138
-
139
- describe('index parameter', () => {
140
- it('includes correct index in error paths', () => {
141
- class Invalid {}
142
- const result = validator.validate(Invalid, 5);
143
- expect(result.getErrors()[0].path).toContain('integrations[5]');
144
- });
145
- });
146
- });