@friggframework/devtools 2.0.0--canary.490.71c435d.0 → 2.0.0--canary.490.a6abe40.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.
@@ -640,7 +640,6 @@ class VpcBuilder extends InfrastructureBuilder {
640
640
  buildSecurityGroupFromDecision(decision, appDefinition, result) {
641
641
  if (decision.ownership === ResourceOwnership.STACK) {
642
642
  // Always create security group resource in template
643
- // CloudFormation handles idempotency if it already exists
644
643
  console.log(' → Adding Lambda Security Group to template...');
645
644
 
646
645
  result.resources.FriggLambdaSecurityGroup = {
@@ -690,7 +689,6 @@ class VpcBuilder extends InfrastructureBuilder {
690
689
  }
691
690
 
692
691
  // For STACK ownership: ALWAYS add definitions to template
693
- // CloudFormation idempotency ensures existing resources won't be recreated
694
692
  if (decision.physicalIds && decision.physicalIds.length >= 2) {
695
693
  console.log(` → Adding subnet definitions to template (existing: ${decision.physicalIds.join(', ')})`);
696
694
  } else {
@@ -398,6 +398,66 @@ describe('VpcBuilder', () => {
398
398
  expect(result.resources.FriggS3VPCEndpoint.Properties.VpcId).toBe('vpc-123');
399
399
  });
400
400
 
401
+ it('should add stack-managed security group back to template to prevent deletion', async () => {
402
+ const appDefinition = {
403
+ vpc: { enable: true },
404
+ };
405
+
406
+ const discoveredResources = {
407
+ fromCloudFormationStack: true,
408
+ stackName: 'test-stack',
409
+ existingLogicalIds: ['FriggLambdaSecurityGroup'],
410
+ defaultVpcId: 'vpc-123',
411
+ privateSubnetId1: 'subnet-1',
412
+ privateSubnetId2: 'subnet-2',
413
+ lambdaSecurityGroupId: 'sg-existing-stack', // Existing in stack
414
+ };
415
+
416
+ const result = await vpcBuilder.build(appDefinition, discoveredResources);
417
+
418
+ // CRITICAL: Must RE-ADD stack-managed SG to template or CloudFormation will DELETE it
419
+ expect(result.resources.FriggLambdaSecurityGroup).toBeDefined();
420
+ expect(result.resources.FriggLambdaSecurityGroup.Type).toBe('AWS::EC2::SecurityGroup');
421
+ expect(result.resources.FriggLambdaSecurityGroup.Properties.VpcId).toBe('vpc-123');
422
+ expect(result.resources.FriggLambdaSecurityGroup.Properties.GroupDescription).toBeDefined();
423
+
424
+ // Should use Ref in Lambda config (not recreating)
425
+ expect(result.vpcConfig.securityGroupIds).toContainEqual({ Ref: 'FriggLambdaSecurityGroup' });
426
+ });
427
+
428
+ it('should add stack-managed subnets back to template to prevent deletion', async () => {
429
+ const appDefinition = {
430
+ vpc: { enable: true },
431
+ };
432
+
433
+ const discoveredResources = {
434
+ fromCloudFormationStack: true,
435
+ stackName: 'test-stack',
436
+ existingLogicalIds: ['FriggPrivateSubnet1', 'FriggPrivateSubnet2'],
437
+ defaultVpcId: 'vpc-123',
438
+ // Subnets exist in stack with specific IDs
439
+ privateSubnetId1: 'subnet-existing-1',
440
+ privateSubnetId2: 'subnet-existing-2',
441
+ };
442
+
443
+ const result = await vpcBuilder.build(appDefinition, discoveredResources);
444
+
445
+ // CRITICAL: Must RE-ADD stack-managed subnets to template or CloudFormation will DELETE them
446
+ expect(result.resources.FriggPrivateSubnet1).toBeDefined();
447
+ expect(result.resources.FriggPrivateSubnet1.Type).toBe('AWS::EC2::Subnet');
448
+ expect(result.resources.FriggPrivateSubnet1.Properties.VpcId).toBe('vpc-123');
449
+
450
+ expect(result.resources.FriggPrivateSubnet2).toBeDefined();
451
+ expect(result.resources.FriggPrivateSubnet2.Type).toBe('AWS::EC2::Subnet');
452
+ expect(result.resources.FriggPrivateSubnet2.Properties.VpcId).toBe('vpc-123');
453
+
454
+ // Should use Refs (not external IDs)
455
+ expect(result.vpcConfig.subnetIds).toEqual([
456
+ { Ref: 'FriggPrivateSubnet1' },
457
+ { Ref: 'FriggPrivateSubnet2' }
458
+ ]);
459
+ });
460
+
401
461
  it('should add stack-managed VPC endpoints back to template to prevent deletion', async () => {
402
462
  const appDefinition = {
403
463
  vpc: { enable: true },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/devtools",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.490.71c435d.0",
4
+ "version": "2.0.0--canary.490.a6abe40.0",
5
5
  "bin": {
6
6
  "frigg": "./frigg-cli/index.js"
7
7
  },
@@ -16,9 +16,9 @@
16
16
  "@babel/eslint-parser": "^7.18.9",
17
17
  "@babel/parser": "^7.25.3",
18
18
  "@babel/traverse": "^7.25.3",
19
- "@friggframework/core": "2.0.0--canary.490.71c435d.0",
20
- "@friggframework/schemas": "2.0.0--canary.490.71c435d.0",
21
- "@friggframework/test": "2.0.0--canary.490.71c435d.0",
19
+ "@friggframework/core": "2.0.0--canary.490.a6abe40.0",
20
+ "@friggframework/schemas": "2.0.0--canary.490.a6abe40.0",
21
+ "@friggframework/test": "2.0.0--canary.490.a6abe40.0",
22
22
  "@hapi/boom": "^10.0.1",
23
23
  "@inquirer/prompts": "^5.3.8",
24
24
  "axios": "^1.7.2",
@@ -46,8 +46,8 @@
46
46
  "validate-npm-package-name": "^5.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@friggframework/eslint-config": "2.0.0--canary.490.71c435d.0",
50
- "@friggframework/prettier-config": "2.0.0--canary.490.71c435d.0",
49
+ "@friggframework/eslint-config": "2.0.0--canary.490.a6abe40.0",
50
+ "@friggframework/prettier-config": "2.0.0--canary.490.a6abe40.0",
51
51
  "aws-sdk-client-mock": "^4.1.0",
52
52
  "aws-sdk-client-mock-jest": "^4.1.0",
53
53
  "jest": "^30.1.3",
@@ -79,5 +79,5 @@
79
79
  "publishConfig": {
80
80
  "access": "public"
81
81
  },
82
- "gitHead": "71c435df870654de6b8f2594674ac35c32c2bd93"
82
+ "gitHead": "a6abe40b6a1d1a48bc28accdf401e2583e73c60c"
83
83
  }