@friggframework/devtools 2.0.0--canary.490.eec7dcd.0 → 2.0.0--canary.490.72cc5dc.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.
@@ -111,6 +111,74 @@ class CloudFormationDiscovery {
111
111
  }
112
112
  }
113
113
 
114
+ /**
115
+ * Extract external resource references from stack resource properties
116
+ *
117
+ * When VPC/subnets/NAT are external, they're referenced in routing resources' properties.
118
+ * We query EC2 to get the actual VPC ID, NAT Gateway ID, and subnet IDs from the route table.
119
+ *
120
+ * @private
121
+ * @param {string} stackName - Stack name
122
+ * @param {Array} resources - CloudFormation stack resources
123
+ * @param {Object} discovered - Object to populate with discovered resources
124
+ */
125
+ async _extractExternalReferencesFromStackResources(stackName, resources, discovered) {
126
+ if (!this.provider || !this.provider.getEC2Client) {
127
+ console.log(' ℹ Skipping external reference extraction (EC2 client not available)');
128
+ return;
129
+ }
130
+
131
+ try {
132
+ // If we found a route table in the stack, query EC2 for its details
133
+ // This gives us VPC ID, NAT Gateway ID, and subnet IDs
134
+ if (discovered.routeTableId) {
135
+ try {
136
+ console.log(` ℹ Querying route table ${discovered.routeTableId} for external references...`);
137
+ const { DescribeRouteTablesCommand } = require('@aws-sdk/client-ec2');
138
+ const ec2 = this.provider.getEC2Client();
139
+ const rtResponse = await ec2.send(new DescribeRouteTablesCommand({
140
+ RouteTableIds: [discovered.routeTableId]
141
+ }));
142
+
143
+ if (rtResponse.RouteTables && rtResponse.RouteTables.length > 0) {
144
+ const routeTable = rtResponse.RouteTables[0];
145
+
146
+ // Extract VPC ID
147
+ if (routeTable.VpcId && !discovered.defaultVpcId) {
148
+ discovered.defaultVpcId = routeTable.VpcId;
149
+ console.log(` ✓ Extracted VPC ID from route table: ${routeTable.VpcId}`);
150
+ }
151
+
152
+ // Extract NAT Gateway ID from routes
153
+ const natRoute = routeTable.Routes?.find(r => r.NatGatewayId);
154
+ if (natRoute && natRoute.NatGatewayId && !discovered.natGatewayId) {
155
+ discovered.natGatewayId = natRoute.NatGatewayId;
156
+ discovered.existingNatGatewayId = natRoute.NatGatewayId;
157
+ console.log(` ✓ Extracted NAT Gateway ID from routes: ${natRoute.NatGatewayId}`);
158
+ }
159
+
160
+ // Extract subnet IDs from route table associations
161
+ const associations = routeTable.Associations || [];
162
+ const subnetAssociations = associations.filter(a => a.SubnetId);
163
+
164
+ if (subnetAssociations.length >= 1 && !discovered.privateSubnetId1) {
165
+ discovered.privateSubnetId1 = subnetAssociations[0].SubnetId;
166
+ console.log(` ✓ Extracted private subnet 1 from associations: ${subnetAssociations[0].SubnetId}`);
167
+ }
168
+ if (subnetAssociations.length >= 2 && !discovered.privateSubnetId2) {
169
+ discovered.privateSubnetId2 = subnetAssociations[1].SubnetId;
170
+ console.log(` ✓ Extracted private subnet 2 from associations: ${subnetAssociations[1].SubnetId}`);
171
+ }
172
+ }
173
+ } catch (error) {
174
+ console.warn(` ⚠️ Could not query route table for external references: ${error.message}`);
175
+ }
176
+ }
177
+ } catch (error) {
178
+ console.warn(` ⚠️ Error extracting external references: ${error.message}`);
179
+ }
180
+ }
181
+
114
182
  /**
115
183
  * Extract discovered resources from CloudFormation stack resources
116
184
  *
@@ -342,6 +410,10 @@ class CloudFormationDiscovery {
342
410
  }
343
411
  }
344
412
 
413
+ // Extract VPC ID and other external references from routing resource properties
414
+ // This handles the pattern where VPC is external but routing is in the stack
415
+ await this._extractExternalReferencesFromStackResources(stackName, resources, discovered);
416
+
345
417
  // If we have a VPC ID but no subnet IDs, query EC2 for Frigg-managed subnets
346
418
  if (discovered.defaultVpcId && this.provider &&
347
419
  !discovered.privateSubnetId1 && !discovered.publicSubnetId1) {
@@ -536,6 +536,29 @@ class AWSProviderAdapter extends CloudProviderAdapter {
536
536
  return [];
537
537
  }
538
538
  }
539
+
540
+ /**
541
+ * Describe a specific stack resource to get its full details including properties
542
+ * @param {string} stackName - Stack name
543
+ * @param {string} logicalResourceId - Logical resource ID
544
+ * @returns {Promise<Object>} Resource details
545
+ */
546
+ async describeStackResource(stackName, logicalResourceId) {
547
+ const cf = this.getCloudFormationClient();
548
+
549
+ try {
550
+ const { DescribeStackResourceCommand } = require('@aws-sdk/client-cloudformation');
551
+ const response = await cf.send(new DescribeStackResourceCommand({
552
+ StackName: stackName,
553
+ LogicalResourceId: logicalResourceId,
554
+ }));
555
+
556
+ return response.StackResourceDetail || null;
557
+ } catch (error) {
558
+ console.warn(`Failed to describe stack resource ${logicalResourceId}:`, error.message);
559
+ return null;
560
+ }
561
+ }
539
562
  }
540
563
 
541
564
  module.exports = {
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.eec7dcd.0",
4
+ "version": "2.0.0--canary.490.72cc5dc.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.eec7dcd.0",
20
- "@friggframework/schemas": "2.0.0--canary.490.eec7dcd.0",
21
- "@friggframework/test": "2.0.0--canary.490.eec7dcd.0",
19
+ "@friggframework/core": "2.0.0--canary.490.72cc5dc.0",
20
+ "@friggframework/schemas": "2.0.0--canary.490.72cc5dc.0",
21
+ "@friggframework/test": "2.0.0--canary.490.72cc5dc.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.eec7dcd.0",
50
- "@friggframework/prettier-config": "2.0.0--canary.490.eec7dcd.0",
49
+ "@friggframework/eslint-config": "2.0.0--canary.490.72cc5dc.0",
50
+ "@friggframework/prettier-config": "2.0.0--canary.490.72cc5dc.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": "eec7dcdaf12585353103eb99ebc141dfa60a6743"
82
+ "gitHead": "72cc5dc761ed4396235fcfbe016c090833e65f9d"
83
83
  }