@friggframework/devtools 2.0.0--canary.461.8cf93ae.0 → 2.0.0--canary.474.213c7d9.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 (32) hide show
  1. package/infrastructure/ARCHITECTURE.md +487 -0
  2. package/infrastructure/domains/database/aurora-builder.js +234 -57
  3. package/infrastructure/domains/database/aurora-builder.test.js +7 -2
  4. package/infrastructure/domains/database/aurora-resolver.js +210 -0
  5. package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
  6. package/infrastructure/domains/database/migration-builder.js +256 -215
  7. package/infrastructure/domains/database/migration-builder.test.js +5 -111
  8. package/infrastructure/domains/database/migration-resolver.js +163 -0
  9. package/infrastructure/domains/database/migration-resolver.test.js +337 -0
  10. package/infrastructure/domains/integration/integration-builder.js +258 -84
  11. package/infrastructure/domains/integration/integration-resolver.js +170 -0
  12. package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
  13. package/infrastructure/domains/networking/vpc-builder.js +856 -135
  14. package/infrastructure/domains/networking/vpc-builder.test.js +10 -6
  15. package/infrastructure/domains/networking/vpc-resolver.js +324 -0
  16. package/infrastructure/domains/networking/vpc-resolver.test.js +501 -0
  17. package/infrastructure/domains/security/kms-builder.js +179 -22
  18. package/infrastructure/domains/security/kms-resolver.js +96 -0
  19. package/infrastructure/domains/security/kms-resolver.test.js +216 -0
  20. package/infrastructure/domains/shared/base-resolver.js +186 -0
  21. package/infrastructure/domains/shared/base-resolver.test.js +305 -0
  22. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
  23. package/infrastructure/domains/shared/cloudformation-discovery.test.js +26 -1
  24. package/infrastructure/domains/shared/types/app-definition.js +205 -0
  25. package/infrastructure/domains/shared/types/discovery-result.js +106 -0
  26. package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
  27. package/infrastructure/domains/shared/types/index.js +46 -0
  28. package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
  29. package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
  30. package/package.json +6 -6
  31. package/infrastructure/REFACTOR.md +0 -532
  32. package/infrastructure/TRANSFORMATION-VISUAL.md +0 -239
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Aurora Resource Resolver Tests
3
+ *
4
+ * Tests the ownership resolution logic for Aurora resources.
5
+ */
6
+
7
+ const AuroraResourceResolver = require('./aurora-resolver');
8
+ const { ResourceOwnership } = require('../shared/types/resource-ownership');
9
+
10
+ describe('AuroraResourceResolver', () => {
11
+ let resolver;
12
+
13
+ beforeEach(() => {
14
+ resolver = new AuroraResourceResolver();
15
+ });
16
+
17
+ describe('resolveCluster', () => {
18
+ it('should resolve to EXTERNAL with user-provided cluster identifier', () => {
19
+ const appDefinition = {
20
+ database: {
21
+ postgres: {
22
+ ownership: { cluster: 'external' },
23
+ external: { clusterIdentifier: 'prod-aurora-cluster' }
24
+ }
25
+ }
26
+ };
27
+ const discovery = { stackManaged: [], external: [], fromCloudFormation: false };
28
+
29
+ const decision = resolver.resolveCluster(appDefinition, discovery);
30
+
31
+ expect(decision.ownership).toBe(ResourceOwnership.EXTERNAL);
32
+ expect(decision.physicalId).toBe('prod-aurora-cluster');
33
+ });
34
+
35
+ it('should resolve to STACK when cluster found in stack', () => {
36
+ const appDefinition = { database: { postgres: { ownership: { cluster: 'auto' } } } };
37
+ const discovery = {
38
+ stackManaged: [
39
+ { logicalId: 'FriggAuroraCluster', physicalId: 'frigg-cluster-prod', resourceType: 'AWS::RDS::DBCluster' }
40
+ ],
41
+ external: [],
42
+ fromCloudFormation: true
43
+ };
44
+
45
+ const decision = resolver.resolveCluster(appDefinition, discovery);
46
+
47
+ expect(decision.ownership).toBe(ResourceOwnership.STACK);
48
+ expect(decision.physicalId).toBe('frigg-cluster-prod');
49
+ expect(decision.reason).toContain('Found FriggAuroraCluster in CloudFormation stack');
50
+ });
51
+
52
+ it('should auto-resolve to EXTERNAL when cluster found externally', () => {
53
+ const appDefinition = { database: { postgres: { ownership: { cluster: 'auto' } } } };
54
+ const discovery = {
55
+ stackManaged: [],
56
+ external: [
57
+ { physicalId: 'shared-aurora-cluster', resourceType: 'AWS::RDS::DBCluster', source: 'aws-discovery' }
58
+ ],
59
+ fromCloudFormation: false
60
+ };
61
+
62
+ const decision = resolver.resolveCluster(appDefinition, discovery);
63
+
64
+ expect(decision.ownership).toBe(ResourceOwnership.EXTERNAL);
65
+ expect(decision.physicalId).toBe('shared-aurora-cluster');
66
+ });
67
+
68
+ it('should auto-resolve to STACK when not found (create new)', () => {
69
+ const appDefinition = { database: { postgres: { ownership: { cluster: 'auto' } } } };
70
+ const discovery = { stackManaged: [], external: [], fromCloudFormation: false };
71
+
72
+ const decision = resolver.resolveCluster(appDefinition, discovery);
73
+
74
+ expect(decision.ownership).toBe(ResourceOwnership.STACK);
75
+ expect(decision.physicalId).toBeFalsy(); // null or undefined
76
+ expect(decision.reason).toContain('No existing Aurora cluster');
77
+ });
78
+ });
79
+
80
+ describe('resolveInstance', () => {
81
+ it('should resolve to EXTERNAL with user-provided instance identifier', () => {
82
+ const appDefinition = {
83
+ database: {
84
+ postgres: {
85
+ ownership: { instance: 'external' },
86
+ external: { instanceIdentifier: 'prod-aurora-instance-1' }
87
+ }
88
+ }
89
+ };
90
+ const discovery = { stackManaged: [], external: [], fromCloudFormation: false };
91
+
92
+ const decision = resolver.resolveInstance(appDefinition, discovery);
93
+
94
+ expect(decision.ownership).toBe(ResourceOwnership.EXTERNAL);
95
+ expect(decision.physicalId).toBe('prod-aurora-instance-1');
96
+ });
97
+
98
+ it('should resolve to STACK when instance found in stack', () => {
99
+ const appDefinition = { database: { postgres: { ownership: { instance: 'auto' } } } };
100
+ const discovery = {
101
+ stackManaged: [
102
+ { logicalId: 'FriggAuroraInstance', physicalId: 'frigg-instance-1', resourceType: 'AWS::RDS::DBInstance' }
103
+ ],
104
+ external: [],
105
+ fromCloudFormation: true
106
+ };
107
+
108
+ const decision = resolver.resolveInstance(appDefinition, discovery);
109
+
110
+ expect(decision.ownership).toBe(ResourceOwnership.STACK);
111
+ expect(decision.physicalId).toBe('frigg-instance-1');
112
+ });
113
+ });
114
+
115
+ describe('resolveSubnetGroup', () => {
116
+ it('should resolve to EXTERNAL with user-provided subnet group name', () => {
117
+ const appDefinition = {
118
+ database: {
119
+ postgres: {
120
+ ownership: { subnetGroup: 'external' },
121
+ external: { subnetGroupName: 'prod-db-subnet-group' }
122
+ }
123
+ }
124
+ };
125
+ const discovery = { stackManaged: [], external: [], fromCloudFormation: false };
126
+
127
+ const decision = resolver.resolveSubnetGroup(appDefinition, discovery);
128
+
129
+ expect(decision.ownership).toBe(ResourceOwnership.EXTERNAL);
130
+ expect(decision.physicalId).toBe('prod-db-subnet-group');
131
+ });
132
+
133
+ it('should resolve to STACK when subnet group found in stack', () => {
134
+ const appDefinition = { database: { postgres: { ownership: { subnetGroup: 'auto' } } } };
135
+ const discovery = {
136
+ stackManaged: [
137
+ { logicalId: 'FriggDBSubnetGroup', physicalId: 'frigg-db-subnet-group', resourceType: 'AWS::RDS::DBSubnetGroup' }
138
+ ],
139
+ external: [],
140
+ fromCloudFormation: true
141
+ };
142
+
143
+ const decision = resolver.resolveSubnetGroup(appDefinition, discovery);
144
+
145
+ expect(decision.ownership).toBe(ResourceOwnership.STACK);
146
+ expect(decision.physicalId).toBe('frigg-db-subnet-group');
147
+ });
148
+
149
+ it('should always create subnet group for new deployments', () => {
150
+ const appDefinition = { database: { postgres: { ownership: { subnetGroup: 'auto' } } } };
151
+ const discovery = { stackManaged: [], external: [], fromCloudFormation: false };
152
+
153
+ const decision = resolver.resolveSubnetGroup(appDefinition, discovery);
154
+
155
+ expect(decision.ownership).toBe(ResourceOwnership.STACK);
156
+ expect(decision.physicalId).toBeFalsy(); // null or undefined
157
+ expect(decision.reason).toContain('No existing DB subnet group');
158
+ });
159
+ });
160
+
161
+ describe('resolveSecret', () => {
162
+ it('should resolve to EXTERNAL with user-provided secret ARN', () => {
163
+ const appDefinition = {
164
+ database: {
165
+ postgres: {
166
+ ownership: { secret: 'external' },
167
+ external: { secretArn: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:prod-db-creds' }
168
+ }
169
+ }
170
+ };
171
+ const discovery = { stackManaged: [], external: [], fromCloudFormation: false };
172
+
173
+ const decision = resolver.resolveSecret(appDefinition, discovery);
174
+
175
+ expect(decision.ownership).toBe(ResourceOwnership.EXTERNAL);
176
+ expect(decision.physicalId).toBe('arn:aws:secretsmanager:us-east-1:123456789012:secret:prod-db-creds');
177
+ });
178
+
179
+ it('should resolve to STACK when secret found in stack', () => {
180
+ const appDefinition = { database: { postgres: { ownership: { secret: 'auto' } } } };
181
+ const discovery = {
182
+ stackManaged: [
183
+ { logicalId: 'FriggDBSecret', physicalId: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:frigg-db', resourceType: 'AWS::SecretsManager::Secret' }
184
+ ],
185
+ external: [],
186
+ fromCloudFormation: true
187
+ };
188
+
189
+ const decision = resolver.resolveSecret(appDefinition, discovery);
190
+
191
+ expect(decision.ownership).toBe(ResourceOwnership.STACK);
192
+ expect(decision.physicalId).toBe('arn:aws:secretsmanager:us-east-1:123456789012:secret:frigg-db');
193
+ });
194
+ });
195
+
196
+ describe('resolveAll', () => {
197
+ it('should resolve all Aurora resources at once', () => {
198
+ const appDefinition = {
199
+ database: {
200
+ postgres: {
201
+ enable: true,
202
+ ownership: {}
203
+ }
204
+ }
205
+ };
206
+ const discovery = {
207
+ stackManaged: [],
208
+ external: [],
209
+ fromCloudFormation: false
210
+ };
211
+
212
+ const decisions = resolver.resolveAll(appDefinition, discovery);
213
+
214
+ expect(decisions.cluster).toBeDefined();
215
+ expect(decisions.instance).toBeDefined();
216
+ expect(decisions.subnetGroup).toBeDefined();
217
+ expect(decisions.secret).toBeDefined();
218
+
219
+ // All should be STACK (create new)
220
+ expect(decisions.cluster.ownership).toBe(ResourceOwnership.STACK);
221
+ expect(decisions.instance.ownership).toBe(ResourceOwnership.STACK);
222
+ expect(decisions.subnetGroup.ownership).toBe(ResourceOwnership.STACK);
223
+ expect(decisions.secret.ownership).toBe(ResourceOwnership.STACK);
224
+ });
225
+
226
+ it('should handle mixed ownership scenarios', () => {
227
+ const appDefinition = {
228
+ database: {
229
+ postgres: {
230
+ ownership: {
231
+ cluster: 'external',
232
+ instance: 'auto',
233
+ subnetGroup: 'stack',
234
+ secret: 'stack'
235
+ },
236
+ external: {
237
+ clusterIdentifier: 'shared-cluster'
238
+ }
239
+ }
240
+ }
241
+ };
242
+ const discovery = {
243
+ stackManaged: [
244
+ { logicalId: 'FriggDBSubnetGroup', physicalId: 'subnet-group-1', resourceType: 'AWS::RDS::DBSubnetGroup' },
245
+ { logicalId: 'FriggDBSecret', physicalId: 'arn:aws:secret-1', resourceType: 'AWS::SecretsManager::Secret' }
246
+ ],
247
+ external: [],
248
+ fromCloudFormation: true
249
+ };
250
+
251
+ const decisions = resolver.resolveAll(appDefinition, discovery);
252
+
253
+ expect(decisions.cluster.ownership).toBe(ResourceOwnership.EXTERNAL);
254
+ expect(decisions.cluster.physicalId).toBe('shared-cluster');
255
+ expect(decisions.instance.ownership).toBe(ResourceOwnership.STACK); // Not found, create new
256
+ expect(decisions.subnetGroup.ownership).toBe(ResourceOwnership.STACK);
257
+ expect(decisions.subnetGroup.physicalId).toBe('subnet-group-1');
258
+ expect(decisions.secret.ownership).toBe(ResourceOwnership.STACK);
259
+ });
260
+ });
261
+
262
+ describe('real-world scenarios', () => {
263
+ it('scenario: fresh deploy, no Aurora exists', () => {
264
+ const appDefinition = {
265
+ database: { postgres: { enable: true, ownership: {} } }
266
+ };
267
+ const discovery = {
268
+ stackManaged: [],
269
+ external: [],
270
+ fromCloudFormation: false
271
+ };
272
+
273
+ const decisions = resolver.resolveAll(appDefinition, discovery);
274
+
275
+ // All resources should be created in stack
276
+ expect(decisions.cluster.ownership).toBe(ResourceOwnership.STACK);
277
+ expect(decisions.cluster.physicalId).toBeFalsy(); // null or undefined
278
+ expect(decisions.instance.ownership).toBe(ResourceOwnership.STACK);
279
+ expect(decisions.subnetGroup.ownership).toBe(ResourceOwnership.STACK);
280
+ expect(decisions.secret.ownership).toBe(ResourceOwnership.STACK);
281
+ });
282
+
283
+ it('scenario: redeploy existing stack with Aurora', () => {
284
+ const appDefinition = {
285
+ database: { postgres: { enable: true, ownership: {} } }
286
+ };
287
+ const discovery = {
288
+ stackManaged: [
289
+ { logicalId: 'FriggAuroraCluster', physicalId: 'cluster-1', resourceType: 'AWS::RDS::DBCluster' },
290
+ { logicalId: 'FriggAuroraInstance', physicalId: 'instance-1', resourceType: 'AWS::RDS::DBInstance' },
291
+ { logicalId: 'FriggDBSubnetGroup', physicalId: 'subnet-group-1', resourceType: 'AWS::RDS::DBSubnetGroup' },
292
+ { logicalId: 'FriggDBSecret', physicalId: 'arn:aws:secret-1', resourceType: 'AWS::SecretsManager::Secret' }
293
+ ],
294
+ external: [],
295
+ fromCloudFormation: true,
296
+ stackName: 'frigg-production'
297
+ };
298
+
299
+ const decisions = resolver.resolveAll(appDefinition, discovery);
300
+
301
+ // All resources in stack, should reuse with STACK ownership
302
+ expect(decisions.cluster.ownership).toBe(ResourceOwnership.STACK);
303
+ expect(decisions.cluster.physicalId).toBe('cluster-1');
304
+ expect(decisions.instance.ownership).toBe(ResourceOwnership.STACK);
305
+ expect(decisions.instance.physicalId).toBe('instance-1');
306
+ expect(decisions.subnetGroup.ownership).toBe(ResourceOwnership.STACK);
307
+ expect(decisions.secret.ownership).toBe(ResourceOwnership.STACK);
308
+ });
309
+
310
+ it('scenario: use shared Aurora cluster with new stack resources', () => {
311
+ const appDefinition = {
312
+ database: {
313
+ postgres: {
314
+ enable: true,
315
+ ownership: {
316
+ cluster: 'external',
317
+ instance: 'external',
318
+ subnetGroup: 'auto',
319
+ secret: 'auto'
320
+ },
321
+ external: {
322
+ clusterIdentifier: 'shared-production-aurora',
323
+ instanceIdentifier: 'shared-production-aurora-instance-1'
324
+ }
325
+ }
326
+ }
327
+ };
328
+ const discovery = {
329
+ stackManaged: [],
330
+ external: [],
331
+ fromCloudFormation: false
332
+ };
333
+
334
+ const decisions = resolver.resolveAll(appDefinition, discovery);
335
+
336
+ // Cluster and instance are external
337
+ expect(decisions.cluster.ownership).toBe(ResourceOwnership.EXTERNAL);
338
+ expect(decisions.cluster.physicalId).toBe('shared-production-aurora');
339
+ expect(decisions.instance.ownership).toBe(ResourceOwnership.EXTERNAL);
340
+ expect(decisions.instance.physicalId).toBe('shared-production-aurora-instance-1');
341
+
342
+ // Subnet group and secret are created in our stack
343
+ expect(decisions.subnetGroup.ownership).toBe(ResourceOwnership.STACK);
344
+ expect(decisions.secret.ownership).toBe(ResourceOwnership.STACK);
345
+ });
346
+ });
347
+ });