alchemy 0.54.0 → 0.55.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 (91) hide show
  1. package/lib/aws/ec2/index.d.ts +10 -0
  2. package/lib/aws/ec2/index.d.ts.map +1 -0
  3. package/lib/aws/ec2/index.js +10 -0
  4. package/lib/aws/ec2/index.js.map +1 -0
  5. package/lib/aws/ec2/internet-gateway-attachment.d.ts +150 -0
  6. package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -0
  7. package/lib/aws/ec2/internet-gateway-attachment.js +248 -0
  8. package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -0
  9. package/lib/aws/ec2/internet-gateway.d.ts +132 -0
  10. package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
  11. package/lib/aws/ec2/internet-gateway.js +311 -0
  12. package/lib/aws/ec2/internet-gateway.js.map +1 -0
  13. package/lib/aws/ec2/nat-gateway.d.ts +145 -0
  14. package/lib/aws/ec2/nat-gateway.d.ts.map +1 -0
  15. package/lib/aws/ec2/nat-gateway.js +618 -0
  16. package/lib/aws/ec2/nat-gateway.js.map +1 -0
  17. package/lib/aws/ec2/route-table-association.d.ts +134 -0
  18. package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
  19. package/lib/aws/ec2/route-table-association.js +364 -0
  20. package/lib/aws/ec2/route-table-association.js.map +1 -0
  21. package/lib/aws/ec2/route-table.d.ts +94 -0
  22. package/lib/aws/ec2/route-table.d.ts.map +1 -0
  23. package/lib/aws/ec2/route-table.js +253 -0
  24. package/lib/aws/ec2/route-table.js.map +1 -0
  25. package/lib/aws/ec2/route.d.ts +130 -0
  26. package/lib/aws/ec2/route.d.ts.map +1 -0
  27. package/lib/aws/ec2/route.js +253 -0
  28. package/lib/aws/ec2/route.js.map +1 -0
  29. package/lib/aws/ec2/security-group-rule.d.ts +84 -0
  30. package/lib/aws/ec2/security-group-rule.d.ts.map +1 -0
  31. package/lib/aws/ec2/security-group-rule.js +123 -0
  32. package/lib/aws/ec2/security-group-rule.js.map +1 -0
  33. package/lib/aws/ec2/security-group.d.ts +84 -0
  34. package/lib/aws/ec2/security-group.d.ts.map +1 -0
  35. package/lib/aws/ec2/security-group.js +207 -0
  36. package/lib/aws/ec2/security-group.js.map +1 -0
  37. package/lib/aws/ec2/subnet.d.ts +110 -0
  38. package/lib/aws/ec2/subnet.d.ts.map +1 -0
  39. package/lib/aws/ec2/subnet.js +336 -0
  40. package/lib/aws/ec2/subnet.js.map +1 -0
  41. package/lib/aws/ec2/utils.d.ts +15 -0
  42. package/lib/aws/ec2/utils.d.ts.map +1 -0
  43. package/lib/aws/ec2/utils.js +79 -0
  44. package/lib/aws/ec2/utils.js.map +1 -0
  45. package/lib/aws/ec2/vpc.d.ts +160 -0
  46. package/lib/aws/ec2/vpc.d.ts.map +1 -0
  47. package/lib/aws/ec2/vpc.js +453 -0
  48. package/lib/aws/ec2/vpc.js.map +1 -0
  49. package/lib/aws/index.d.ts +7 -0
  50. package/lib/aws/index.d.ts.map +1 -1
  51. package/lib/aws/index.js +8 -0
  52. package/lib/aws/index.js.map +1 -1
  53. package/lib/aws/utils.d.ts +25 -0
  54. package/lib/aws/utils.d.ts.map +1 -0
  55. package/lib/aws/utils.js +89 -0
  56. package/lib/aws/utils.js.map +1 -0
  57. package/lib/build-date.d.ts +6 -0
  58. package/lib/build-date.d.ts.map +1 -0
  59. package/lib/build-date.js +8 -0
  60. package/lib/build-date.js.map +1 -0
  61. package/lib/util/params.d.ts +5 -0
  62. package/lib/util/params.d.ts.map +1 -0
  63. package/lib/util/params.js +30 -0
  64. package/lib/util/params.js.map +1 -0
  65. package/lib/util/timeout.d.ts +31 -0
  66. package/lib/util/timeout.d.ts.map +1 -0
  67. package/lib/util/timeout.js +109 -0
  68. package/lib/util/timeout.js.map +1 -0
  69. package/lib/util/xml.d.ts +5 -0
  70. package/lib/util/xml.d.ts.map +1 -0
  71. package/lib/util/xml.js +8 -0
  72. package/lib/util/xml.js.map +1 -0
  73. package/package.json +3 -1
  74. package/src/aws/ec2/index.ts +9 -0
  75. package/src/aws/ec2/internet-gateway-attachment.ts +468 -0
  76. package/src/aws/ec2/internet-gateway.ts +557 -0
  77. package/src/aws/ec2/nat-gateway.ts +1123 -0
  78. package/src/aws/ec2/route-table-association.ts +747 -0
  79. package/src/aws/ec2/route-table.ts +452 -0
  80. package/src/aws/ec2/route.ts +447 -0
  81. package/src/aws/ec2/security-group-rule.ts +229 -0
  82. package/src/aws/ec2/security-group.ts +418 -0
  83. package/src/aws/ec2/subnet.ts +625 -0
  84. package/src/aws/ec2/utils.ts +102 -0
  85. package/src/aws/ec2/vpc.ts +969 -0
  86. package/src/aws/index.ts +9 -0
  87. package/src/aws/utils.ts +137 -0
  88. package/src/build-date.ts +8 -0
  89. package/src/util/params.ts +33 -0
  90. package/src/util/timeout.ts +178 -0
  91. package/src/util/xml.ts +7 -0
@@ -0,0 +1,418 @@
1
+ import type { AwsClient } from "aws4fetch";
2
+ import { XMLParser } from "fast-xml-parser";
3
+ import type { Context } from "../../context.ts";
4
+ import { Resource } from "../../resource.ts";
5
+ import { ignore } from "../../util/ignore.ts";
6
+ import {
7
+ mergeTimeoutConfig,
8
+ type TimeoutConfig,
9
+ waitForResourceState,
10
+ } from "../../util/timeout.ts";
11
+ import { callEC2Api, createEC2Client } from "./utils.ts";
12
+ import type { Vpc } from "./vpc.ts";
13
+
14
+ /**
15
+ * Security Group timeout constants
16
+ */
17
+ export const SECURITY_GROUP_TIMEOUT: TimeoutConfig = {
18
+ maxAttempts: 30,
19
+ delayMs: 1000, // 1 second - Security Groups are fast resources
20
+ };
21
+
22
+ /**
23
+ * Properties for creating or updating a Security Group
24
+ */
25
+ export interface SecurityGroupProps {
26
+ /**
27
+ * The VPC to create the security group in.
28
+ */
29
+ vpc: Vpc | string;
30
+
31
+ /**
32
+ * The name of the security group.
33
+ */
34
+ groupName: string;
35
+
36
+ /**
37
+ * The description of the security group.
38
+ */
39
+ description: string;
40
+
41
+ /**
42
+ * Tags to apply to the security group.
43
+ */
44
+ tags?: Record<string, string>;
45
+
46
+ /**
47
+ * Timeout configuration for Security Group operations.
48
+ * @default Security Group-specific sensible defaults (30 attempts, 1000ms delay)
49
+ */
50
+ timeout?: Partial<TimeoutConfig>;
51
+ }
52
+
53
+ /**
54
+ * Output returned after Security Group creation/update
55
+ */
56
+ export interface SecurityGroup
57
+ extends Resource<"aws::SecurityGroup">,
58
+ SecurityGroupProps {
59
+ /**
60
+ * The ID of the security group.
61
+ */
62
+ groupId: string;
63
+
64
+ /**
65
+ * The ID of the VPC the security group belongs to.
66
+ */
67
+ vpcId: string;
68
+
69
+ /**
70
+ * The AWS account ID that owns the security group.
71
+ */
72
+ ownerId: string;
73
+ }
74
+
75
+ /**
76
+ * AWS Security Group Resource
77
+ *
78
+ * Creates and manages security groups. Acts as a virtual firewall for EC2
79
+ * instances and other AWS resources. Rules are managed separately using the
80
+ * `SecurityGroupRule` resource.
81
+ *
82
+ * @example
83
+ * // Create a web server security group
84
+ * const webSecurityGroup = await SecurityGroup("web-sg", {
85
+ * vpc: mainVpc,
86
+ * groupName: "web-server-sg",
87
+ * description: "Security group for web servers",
88
+ * tags: {
89
+ * Name: "web-server-security-group",
90
+ * Environment: "production"
91
+ * }
92
+ * });
93
+ *
94
+ * @example
95
+ * // Separately, define a rule to allow HTTP traffic
96
+ * const httpRule = await SecurityGroupRule("web-sg-http-rule", {
97
+ * securityGroup: webSecurityGroup,
98
+ * type: "ingress",
99
+ * protocol: "tcp",
100
+ * fromPort: 80,
101
+ * toPort: 80,
102
+ * cidrBlocks: ["0.0.0.0/0"],
103
+ * description: "Allow HTTP access from anywhere"
104
+ * });
105
+ */
106
+ export const SecurityGroup = Resource(
107
+ "aws::SecurityGroup",
108
+ async function (
109
+ this: Context<SecurityGroup>,
110
+ _id: string,
111
+ props: SecurityGroupProps,
112
+ ): Promise<SecurityGroup> {
113
+ const client = await createEC2Client();
114
+ const vpcId = typeof props.vpc === "string" ? props.vpc : props.vpc.vpcId;
115
+ const timeoutConfig = mergeTimeoutConfig(
116
+ SECURITY_GROUP_TIMEOUT,
117
+ props.timeout,
118
+ );
119
+
120
+ if (this.phase === "delete") {
121
+ if (this.output?.groupId) {
122
+ console.log(`🗑️ Deleting Security Group: ${this.output.groupId}`);
123
+ await ignore(
124
+ ["InvalidGroupId.NotFound", "DependencyViolation"],
125
+ async () => {
126
+ await callEC2Api(
127
+ client,
128
+ "DeleteSecurityGroup",
129
+ parseSecurityGroupXmlResponse,
130
+ {
131
+ GroupId: this.output!.groupId,
132
+ },
133
+ );
134
+ },
135
+ );
136
+ await waitForSecurityGroupDeleted(
137
+ client,
138
+ this.output.groupId,
139
+ timeoutConfig,
140
+ );
141
+ console.log(
142
+ ` ✅ Security Group ${this.output.groupId} deletion completed`,
143
+ );
144
+ }
145
+ return this.destroy();
146
+ }
147
+
148
+ let securityGroup: AwsSecurityGroup;
149
+
150
+ if (this.phase === "update" && this.output?.groupId) {
151
+ // Get existing security group
152
+ const response = await callEC2Api<DescribeSecurityGroupsResponse>(
153
+ client,
154
+ "DescribeSecurityGroups",
155
+ parseSecurityGroupXmlResponse,
156
+ {
157
+ "GroupId.1": this.output.groupId,
158
+ },
159
+ );
160
+
161
+ if (!response.SecurityGroups?.[0]) {
162
+ throw new Error(`Security Group ${this.output.groupId} not found`);
163
+ }
164
+ securityGroup = response.SecurityGroups[0];
165
+ } else {
166
+ // Create new security group
167
+ const createParams: CreateSecurityGroupParams = {
168
+ GroupName: props.groupName,
169
+ GroupDescription: props.description,
170
+ VpcId: vpcId,
171
+ };
172
+
173
+ // Add tags if specified
174
+ if (props.tags) {
175
+ createParams.TagSpecifications = [
176
+ {
177
+ ResourceType: "security-group",
178
+ Tags: Object.entries(props.tags).map(([Key, Value]) => ({
179
+ Key,
180
+ Value,
181
+ })),
182
+ },
183
+ ];
184
+ }
185
+
186
+ const response = await callEC2Api<CreateSecurityGroupResponse>(
187
+ client,
188
+ "CreateSecurityGroup",
189
+ parseSecurityGroupXmlResponse,
190
+ convertCreateSecurityGroupParamsToAwsFormat(createParams),
191
+ );
192
+
193
+ if (!response.GroupId) {
194
+ throw new Error("Failed to create security group");
195
+ }
196
+
197
+ // Wait for the security group to be available
198
+ await waitForSecurityGroupAvailable(
199
+ client,
200
+ response.GroupId,
201
+ timeoutConfig,
202
+ );
203
+
204
+ // Get the full security group details
205
+ const sgResponse = await callEC2Api<DescribeSecurityGroupsResponse>(
206
+ client,
207
+ "DescribeSecurityGroups",
208
+ parseSecurityGroupXmlResponse,
209
+ {
210
+ "GroupId.1": response.GroupId,
211
+ },
212
+ );
213
+
214
+ if (!sgResponse.SecurityGroups?.[0]) {
215
+ throw new Error("Failed to retrieve created security group");
216
+ }
217
+ securityGroup = sgResponse.SecurityGroups[0];
218
+ }
219
+
220
+ return this({
221
+ groupId: securityGroup.GroupId,
222
+ vpcId: securityGroup.VpcId,
223
+ ownerId: securityGroup.OwnerId,
224
+ ...props,
225
+ vpc: vpcId,
226
+ });
227
+ },
228
+ );
229
+
230
+ // --- Helper Functions and Interfaces ---
231
+
232
+ /**
233
+ * AWS Security Group API response types
234
+ */
235
+ interface AwsSecurityGroup {
236
+ GroupId: string;
237
+ GroupName: string;
238
+ Description: string;
239
+ VpcId: string;
240
+ OwnerId: string;
241
+ }
242
+
243
+ interface CreateSecurityGroupResponse {
244
+ GroupId: string;
245
+ }
246
+
247
+ interface DescribeSecurityGroupsResponse {
248
+ SecurityGroups: AwsSecurityGroup[];
249
+ }
250
+
251
+ /**
252
+ * Raw XML parsing interfaces for type safety
253
+ */
254
+ interface RawSecurityGroupXmlItem {
255
+ groupId: string;
256
+ groupName: string;
257
+ groupDescription: string;
258
+ vpcId: string;
259
+ ownerId: string;
260
+ }
261
+
262
+ /**
263
+ * API Parameter types
264
+ */
265
+ interface TagSpecification {
266
+ ResourceType: string;
267
+ Tags: Array<{ Key: string; Value: string }>;
268
+ }
269
+
270
+ interface CreateSecurityGroupParams {
271
+ GroupName: string;
272
+ GroupDescription: string;
273
+ VpcId: string;
274
+ TagSpecifications?: TagSpecification[];
275
+ DryRun?: boolean;
276
+ }
277
+
278
+ /**
279
+ * Parse XML responses specifically for Security Group operations
280
+ */
281
+ function parseSecurityGroupXmlResponse<T>(xmlText: string): T {
282
+ const parser = new XMLParser({
283
+ ignoreAttributes: true,
284
+ parseAttributeValue: true,
285
+ parseTagValue: true,
286
+ trimValues: true,
287
+ });
288
+
289
+ const parsed = parser.parse(xmlText);
290
+ const result: Record<string, unknown> = {};
291
+
292
+ if (parsed.CreateSecurityGroupResponse) {
293
+ result.GroupId = parsed.CreateSecurityGroupResponse.groupId;
294
+ }
295
+
296
+ if (parsed.DescribeSecurityGroupsResponse) {
297
+ const securityGroupSet =
298
+ parsed.DescribeSecurityGroupsResponse.securityGroupInfo;
299
+ if (securityGroupSet?.item) {
300
+ const securityGroups = Array.isArray(securityGroupSet.item)
301
+ ? securityGroupSet.item
302
+ : [securityGroupSet.item];
303
+ result.SecurityGroups = securityGroups.map(
304
+ (sg: RawSecurityGroupXmlItem) => ({
305
+ GroupId: sg.groupId,
306
+ GroupName: sg.groupName,
307
+ Description: sg.groupDescription,
308
+ VpcId: sg.vpcId,
309
+ OwnerId: sg.ownerId,
310
+ }),
311
+ );
312
+ } else {
313
+ result.SecurityGroups = [];
314
+ }
315
+ }
316
+
317
+ if (parsed.DeleteSecurityGroupResponse) {
318
+ result.success = true;
319
+ }
320
+
321
+ return result as T;
322
+ }
323
+
324
+ /**
325
+ * Convert CreateSecurityGroupParams to the format required by the AWS API.
326
+ */
327
+ function convertCreateSecurityGroupParamsToAwsFormat(
328
+ params: CreateSecurityGroupParams,
329
+ ): Record<string, string> {
330
+ const awsParams: Record<string, string> = {
331
+ GroupName: params.GroupName,
332
+ GroupDescription: params.GroupDescription,
333
+ VpcId: params.VpcId,
334
+ };
335
+
336
+ if (params.DryRun !== undefined) {
337
+ awsParams.DryRun = params.DryRun.toString();
338
+ }
339
+
340
+ if (params.TagSpecifications) {
341
+ params.TagSpecifications.forEach((tagSpec, specIndex) => {
342
+ const specNum = specIndex + 1;
343
+ awsParams[`TagSpecification.${specNum}.ResourceType`] =
344
+ tagSpec.ResourceType;
345
+ tagSpec.Tags.forEach((tag, tagIndex) => {
346
+ const tagNum = tagIndex + 1;
347
+ awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Key`] = tag.Key;
348
+ awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Value`] =
349
+ tag.Value;
350
+ });
351
+ });
352
+ }
353
+
354
+ return awsParams;
355
+ }
356
+
357
+ /**
358
+ * Wait for a security group to become available.
359
+ */
360
+ async function waitForSecurityGroupAvailable(
361
+ client: AwsClient,
362
+ groupId: string,
363
+ timeoutConfig: TimeoutConfig,
364
+ ): Promise<void> {
365
+ const checkFunction = async () => {
366
+ const response = await callEC2Api<DescribeSecurityGroupsResponse>(
367
+ client,
368
+ "DescribeSecurityGroups",
369
+ parseSecurityGroupXmlResponse,
370
+ { "GroupId.1": groupId },
371
+ );
372
+ return response.SecurityGroups?.[0];
373
+ };
374
+
375
+ await waitForResourceState(
376
+ checkFunction,
377
+ (sg) => !!sg,
378
+ timeoutConfig,
379
+ groupId,
380
+ "Security Group",
381
+ "to be available",
382
+ );
383
+ }
384
+
385
+ /**
386
+ * Wait for a security group to be deleted.
387
+ */
388
+ async function waitForSecurityGroupDeleted(
389
+ client: AwsClient,
390
+ groupId: string,
391
+ timeoutConfig: TimeoutConfig,
392
+ ): Promise<void> {
393
+ const checkFunction = async () => {
394
+ try {
395
+ const response = await callEC2Api<DescribeSecurityGroupsResponse>(
396
+ client,
397
+ "DescribeSecurityGroups",
398
+ parseSecurityGroupXmlResponse,
399
+ { "GroupId.1": groupId },
400
+ );
401
+ return response.SecurityGroups?.[0];
402
+ } catch (error: any) {
403
+ if (error.code === "InvalidGroup.NotFound") {
404
+ return undefined;
405
+ }
406
+ throw error;
407
+ }
408
+ };
409
+
410
+ await waitForResourceState(
411
+ checkFunction,
412
+ (sg) => !sg,
413
+ timeoutConfig,
414
+ groupId,
415
+ "Security Group",
416
+ "to be deleted",
417
+ );
418
+ }