alchemy 0.53.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 (214) hide show
  1. package/bin/alchemy.js +196353 -0
  2. package/bin/alchemy.ts +2 -2
  3. package/bin/commands/init.ts +1190 -0
  4. package/bin/constants.ts +18 -0
  5. package/bin/services/execute-alchemy.ts +7 -2
  6. package/bin/services/package-manager.ts +1 -1
  7. package/bin/types.ts +14 -5
  8. package/lib/aws/ec2/index.d.ts +10 -0
  9. package/lib/aws/ec2/index.d.ts.map +1 -0
  10. package/lib/aws/ec2/index.js +10 -0
  11. package/lib/aws/ec2/index.js.map +1 -0
  12. package/lib/aws/ec2/internet-gateway-attachment.d.ts +150 -0
  13. package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -0
  14. package/lib/aws/ec2/internet-gateway-attachment.js +248 -0
  15. package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -0
  16. package/lib/aws/ec2/internet-gateway.d.ts +132 -0
  17. package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
  18. package/lib/aws/ec2/internet-gateway.js +311 -0
  19. package/lib/aws/ec2/internet-gateway.js.map +1 -0
  20. package/lib/aws/ec2/nat-gateway.d.ts +145 -0
  21. package/lib/aws/ec2/nat-gateway.d.ts.map +1 -0
  22. package/lib/aws/ec2/nat-gateway.js +618 -0
  23. package/lib/aws/ec2/nat-gateway.js.map +1 -0
  24. package/lib/aws/ec2/route-table-association.d.ts +134 -0
  25. package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
  26. package/lib/aws/ec2/route-table-association.js +364 -0
  27. package/lib/aws/ec2/route-table-association.js.map +1 -0
  28. package/lib/aws/ec2/route-table.d.ts +94 -0
  29. package/lib/aws/ec2/route-table.d.ts.map +1 -0
  30. package/lib/aws/ec2/route-table.js +253 -0
  31. package/lib/aws/ec2/route-table.js.map +1 -0
  32. package/lib/aws/ec2/route.d.ts +130 -0
  33. package/lib/aws/ec2/route.d.ts.map +1 -0
  34. package/lib/aws/ec2/route.js +253 -0
  35. package/lib/aws/ec2/route.js.map +1 -0
  36. package/lib/aws/ec2/security-group-rule.d.ts +84 -0
  37. package/lib/aws/ec2/security-group-rule.d.ts.map +1 -0
  38. package/lib/aws/ec2/security-group-rule.js +123 -0
  39. package/lib/aws/ec2/security-group-rule.js.map +1 -0
  40. package/lib/aws/ec2/security-group.d.ts +84 -0
  41. package/lib/aws/ec2/security-group.d.ts.map +1 -0
  42. package/lib/aws/ec2/security-group.js +207 -0
  43. package/lib/aws/ec2/security-group.js.map +1 -0
  44. package/lib/aws/ec2/subnet.d.ts +110 -0
  45. package/lib/aws/ec2/subnet.d.ts.map +1 -0
  46. package/lib/aws/ec2/subnet.js +336 -0
  47. package/lib/aws/ec2/subnet.js.map +1 -0
  48. package/lib/aws/ec2/utils.d.ts +15 -0
  49. package/lib/aws/ec2/utils.d.ts.map +1 -0
  50. package/lib/aws/ec2/utils.js +79 -0
  51. package/lib/aws/ec2/utils.js.map +1 -0
  52. package/lib/aws/ec2/vpc.d.ts +160 -0
  53. package/lib/aws/ec2/vpc.d.ts.map +1 -0
  54. package/lib/aws/ec2/vpc.js +453 -0
  55. package/lib/aws/ec2/vpc.js.map +1 -0
  56. package/lib/aws/index.d.ts +7 -0
  57. package/lib/aws/index.d.ts.map +1 -1
  58. package/lib/aws/index.js +8 -0
  59. package/lib/aws/index.js.map +1 -1
  60. package/lib/aws/utils.d.ts +25 -0
  61. package/lib/aws/utils.d.ts.map +1 -0
  62. package/lib/aws/utils.js +89 -0
  63. package/lib/aws/utils.js.map +1 -0
  64. package/lib/build-date.d.ts +6 -0
  65. package/lib/build-date.d.ts.map +1 -0
  66. package/lib/build-date.js +8 -0
  67. package/lib/build-date.js.map +1 -0
  68. package/lib/cloudflare/astro.d.ts.map +1 -1
  69. package/lib/cloudflare/astro.js +4 -3
  70. package/lib/cloudflare/astro.js.map +1 -1
  71. package/lib/cloudflare/bundle/externals.d.ts +3 -0
  72. package/lib/cloudflare/bundle/externals.d.ts.map +1 -0
  73. package/lib/cloudflare/bundle/externals.js +35 -0
  74. package/lib/cloudflare/bundle/externals.js.map +1 -0
  75. package/lib/cloudflare/bundle/internal-worker-bundle.d.ts +8 -1
  76. package/lib/cloudflare/bundle/internal-worker-bundle.d.ts.map +1 -1
  77. package/lib/cloudflare/bundle/internal-worker-bundle.js +11 -4
  78. package/lib/cloudflare/bundle/internal-worker-bundle.js.map +1 -1
  79. package/lib/cloudflare/bundle/plugin-hot-reload.d.ts +4 -1
  80. package/lib/cloudflare/bundle/plugin-hot-reload.d.ts.map +1 -1
  81. package/lib/cloudflare/bundle/plugin-hot-reload.js +27 -11
  82. package/lib/cloudflare/bundle/plugin-hot-reload.js.map +1 -1
  83. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js +5 -1
  84. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -1
  85. package/lib/cloudflare/bundle/plugin-wasm.d.ts +6 -2
  86. package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -1
  87. package/lib/cloudflare/bundle/plugin-wasm.js +21 -47
  88. package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
  89. package/lib/cloudflare/bundle/validate-node-compat.d.ts +2 -1
  90. package/lib/cloudflare/bundle/validate-node-compat.d.ts.map +1 -1
  91. package/lib/cloudflare/bundle/validate-node-compat.js +5 -4
  92. package/lib/cloudflare/bundle/validate-node-compat.js.map +1 -1
  93. package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
  94. package/lib/cloudflare/compatibility-date.gen.js +1 -1
  95. package/lib/cloudflare/d1-database.js +1 -1
  96. package/lib/cloudflare/d1-database.js.map +1 -1
  97. package/lib/cloudflare/d1-migrations.d.ts.map +1 -1
  98. package/lib/cloudflare/d1-migrations.js +8 -10
  99. package/lib/cloudflare/d1-migrations.js.map +1 -1
  100. package/lib/cloudflare/miniflare/miniflare-worker-options.d.ts +3 -3
  101. package/lib/cloudflare/miniflare/miniflare-worker-options.d.ts.map +1 -1
  102. package/lib/cloudflare/miniflare/miniflare-worker-options.js +23 -6
  103. package/lib/cloudflare/miniflare/miniflare-worker-options.js.map +1 -1
  104. package/lib/cloudflare/miniflare/miniflare.d.ts.map +1 -1
  105. package/lib/cloudflare/miniflare/miniflare.js +2 -4
  106. package/lib/cloudflare/miniflare/miniflare.js.map +1 -1
  107. package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -1
  108. package/lib/cloudflare/miniflare/remote-binding-proxy.js +4 -6
  109. package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -1
  110. package/lib/cloudflare/react-router.d.ts +4 -0
  111. package/lib/cloudflare/react-router.d.ts.map +1 -1
  112. package/lib/cloudflare/react-router.js +8 -5
  113. package/lib/cloudflare/react-router.js.map +1 -1
  114. package/lib/cloudflare/worker-bundle.d.ts +80 -0
  115. package/lib/cloudflare/worker-bundle.d.ts.map +1 -0
  116. package/lib/cloudflare/worker-bundle.js +266 -0
  117. package/lib/cloudflare/worker-bundle.js.map +1 -0
  118. package/lib/cloudflare/worker.d.ts +1 -1
  119. package/lib/cloudflare/worker.d.ts.map +1 -1
  120. package/lib/cloudflare/worker.js +81 -195
  121. package/lib/cloudflare/worker.js.map +1 -1
  122. package/lib/esbuild/bundle.d.ts +1 -0
  123. package/lib/esbuild/bundle.d.ts.map +1 -1
  124. package/lib/state/cloudflare-state-store.js +1 -5
  125. package/lib/state/cloudflare-state-store.js.map +1 -1
  126. package/lib/state/dofs-state-store/store.d.ts.map +1 -1
  127. package/lib/state/dofs-state-store/store.js +4 -4
  128. package/lib/state/dofs-state-store/store.js.map +1 -1
  129. package/lib/util/params.d.ts +5 -0
  130. package/lib/util/params.d.ts.map +1 -0
  131. package/lib/util/params.js +30 -0
  132. package/lib/util/params.js.map +1 -0
  133. package/lib/util/timeout.d.ts +31 -0
  134. package/lib/util/timeout.d.ts.map +1 -0
  135. package/lib/util/timeout.js +109 -0
  136. package/lib/util/timeout.js.map +1 -0
  137. package/lib/util/xml.d.ts +5 -0
  138. package/lib/util/xml.d.ts.map +1 -0
  139. package/lib/util/xml.js +8 -0
  140. package/lib/util/xml.js.map +1 -0
  141. package/package.json +12 -5
  142. package/src/aws/ec2/index.ts +9 -0
  143. package/src/aws/ec2/internet-gateway-attachment.ts +468 -0
  144. package/src/aws/ec2/internet-gateway.ts +557 -0
  145. package/src/aws/ec2/nat-gateway.ts +1123 -0
  146. package/src/aws/ec2/route-table-association.ts +747 -0
  147. package/src/aws/ec2/route-table.ts +452 -0
  148. package/src/aws/ec2/route.ts +447 -0
  149. package/src/aws/ec2/security-group-rule.ts +229 -0
  150. package/src/aws/ec2/security-group.ts +418 -0
  151. package/src/aws/ec2/subnet.ts +625 -0
  152. package/src/aws/ec2/utils.ts +102 -0
  153. package/src/aws/ec2/vpc.ts +969 -0
  154. package/src/aws/index.ts +9 -0
  155. package/src/aws/utils.ts +137 -0
  156. package/src/build-date.ts +8 -0
  157. package/src/cloudflare/astro.ts +4 -3
  158. package/src/cloudflare/bundle/externals.ts +36 -0
  159. package/src/cloudflare/bundle/internal-worker-bundle.ts +12 -3
  160. package/src/cloudflare/bundle/plugin-hot-reload.ts +32 -12
  161. package/src/cloudflare/bundle/plugin-hybrid-node-compat.ts +6 -1
  162. package/src/cloudflare/bundle/plugin-wasm.ts +26 -54
  163. package/src/cloudflare/bundle/validate-node-compat.ts +6 -5
  164. package/src/cloudflare/compatibility-date.gen.ts +1 -1
  165. package/src/cloudflare/d1-database.ts +1 -1
  166. package/src/cloudflare/d1-migrations.ts +19 -18
  167. package/src/cloudflare/miniflare/miniflare-worker-options.ts +27 -13
  168. package/src/cloudflare/miniflare/miniflare.ts +2 -4
  169. package/src/cloudflare/miniflare/remote-binding-proxy.ts +5 -7
  170. package/src/cloudflare/react-router.ts +14 -6
  171. package/src/cloudflare/worker-bundle.ts +364 -0
  172. package/src/cloudflare/worker.ts +104 -241
  173. package/src/state/cloudflare-state-store.ts +1 -5
  174. package/src/state/dofs-state-store/store.ts +4 -4
  175. package/src/util/params.ts +33 -0
  176. package/src/util/timeout.ts +178 -0
  177. package/src/util/xml.ts +7 -0
  178. package/templates/nuxt/package.json +1 -1
  179. package/templates/nuxt/types/env.d.ts +11 -0
  180. package/templates/react-router/workers/app.ts +2 -2
  181. package/templates/rwsdk/.cursor/rules/alchemy_cloudflare.mdc +385 -0
  182. package/templates/rwsdk/wrangler.jsonc +10 -7
  183. package/templates/typescript/tsconfig.json +1 -2
  184. package/bin/alchemy.mjs +0 -51766
  185. package/lib/cloudflare/bundle/esbuild.d.ts +0 -16
  186. package/lib/cloudflare/bundle/esbuild.d.ts.map +0 -1
  187. package/lib/cloudflare/bundle/esbuild.js +0 -159
  188. package/lib/cloudflare/bundle/esbuild.js.map +0 -1
  189. package/lib/cloudflare/bundle/fs.d.ts +0 -18
  190. package/lib/cloudflare/bundle/fs.d.ts.map +0 -1
  191. package/lib/cloudflare/bundle/fs.js +0 -78
  192. package/lib/cloudflare/bundle/fs.js.map +0 -1
  193. package/lib/cloudflare/bundle/index.d.ts +0 -3
  194. package/lib/cloudflare/bundle/index.d.ts.map +0 -1
  195. package/lib/cloudflare/bundle/index.js +0 -2
  196. package/lib/cloudflare/bundle/index.js.map +0 -1
  197. package/lib/cloudflare/bundle/inline.d.ts +0 -12
  198. package/lib/cloudflare/bundle/inline.d.ts.map +0 -1
  199. package/lib/cloudflare/bundle/inline.js +0 -32
  200. package/lib/cloudflare/bundle/inline.js.map +0 -1
  201. package/lib/cloudflare/bundle/normalize.d.ts +0 -21
  202. package/lib/cloudflare/bundle/normalize.d.ts.map +0 -1
  203. package/lib/cloudflare/bundle/normalize.js +0 -49
  204. package/lib/cloudflare/bundle/normalize.js.map +0 -1
  205. package/lib/cloudflare/bundle/shared.d.ts +0 -30
  206. package/lib/cloudflare/bundle/shared.d.ts.map +0 -1
  207. package/lib/cloudflare/bundle/shared.js +0 -34
  208. package/lib/cloudflare/bundle/shared.js.map +0 -1
  209. package/src/cloudflare/bundle/esbuild.ts +0 -194
  210. package/src/cloudflare/bundle/fs.ts +0 -103
  211. package/src/cloudflare/bundle/index.ts +0 -6
  212. package/src/cloudflare/bundle/inline.ts +0 -42
  213. package/src/cloudflare/bundle/normalize.ts +0 -76
  214. package/src/cloudflare/bundle/shared.ts +0 -73
@@ -0,0 +1,557 @@
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 { logger } from "../../util/logger.ts";
7
+ import {
8
+ mergeTimeoutConfig,
9
+ type TimeoutConfig,
10
+ waitForResourceState,
11
+ } from "../../util/timeout.ts";
12
+ import { callEC2Api, createEC2Client } from "./utils.ts";
13
+
14
+ /**
15
+ * Properties for creating or updating an Internet Gateway
16
+ */
17
+ export interface InternetGatewayProps {
18
+ /**
19
+ * Tags to apply to the Internet Gateway
20
+ */
21
+ tags?: Record<string, string>;
22
+
23
+ /**
24
+ * Timeout configuration for Internet Gateway operations
25
+ * @default Internet Gateway-specific sensible defaults (60 attempts, 2000ms delay)
26
+ */
27
+ timeout?: Partial<TimeoutConfig>;
28
+ }
29
+
30
+ /**
31
+ * Output returned after Internet Gateway creation/update
32
+ */
33
+ export interface InternetGateway
34
+ extends Resource<"aws::InternetGateway">,
35
+ InternetGatewayProps {
36
+ /**
37
+ * The ID of the Internet Gateway
38
+ */
39
+ internetGatewayId: string;
40
+
41
+ /**
42
+ * The current state of the Internet Gateway
43
+ */
44
+ state: "available";
45
+
46
+ /**
47
+ * Information about the VPCs attached to the Internet Gateway
48
+ */
49
+ attachments?: Array<{
50
+ vpcId: string;
51
+ state: "attaching" | "attached" | "detaching" | "detached";
52
+ }>;
53
+
54
+ /**
55
+ * The ID of the AWS account that owns the Internet Gateway
56
+ */
57
+ ownerId?: string;
58
+ }
59
+
60
+ /**
61
+ * Wait for Internet Gateway to be in available state
62
+ */
63
+ async function waitForInternetGatewayAvailable(
64
+ client: AwsClient,
65
+ internetGatewayId: string,
66
+ timeoutConfig: TimeoutConfig,
67
+ ): Promise<void> {
68
+ const checkFunction = async () => {
69
+ const response = await callEC2Api<DescribeInternetGatewaysResponse>(
70
+ client,
71
+ "DescribeInternetGateways",
72
+ parseInternetGatewayXmlResponse,
73
+ {
74
+ "InternetGatewayId.1": internetGatewayId,
75
+ },
76
+ );
77
+ return response.InternetGateways?.[0];
78
+ };
79
+
80
+ const isReady = (igw: AwsInternetGateway | undefined) => {
81
+ return igw?.State === "available" || igw !== undefined; // IGWs are usually immediately available
82
+ };
83
+
84
+ await waitForResourceState(
85
+ checkFunction,
86
+ isReady,
87
+ timeoutConfig,
88
+ internetGatewayId,
89
+ "Internet Gateway",
90
+ "is now available",
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Wait for Internet Gateway to be deleted
96
+ */
97
+ async function waitForInternetGatewayDeleted(
98
+ client: AwsClient,
99
+ internetGatewayId: string,
100
+ timeoutConfig: TimeoutConfig,
101
+ ): Promise<void> {
102
+ const checkFunction = async () => {
103
+ try {
104
+ const response = await callEC2Api<DescribeInternetGatewaysResponse>(
105
+ client,
106
+ "DescribeInternetGateways",
107
+ parseInternetGatewayXmlResponse,
108
+ {
109
+ "InternetGatewayId.1": internetGatewayId,
110
+ },
111
+ );
112
+ return response.InternetGateways?.[0];
113
+ } catch (error: any) {
114
+ // If Internet Gateway is not found, it's been deleted - return undefined
115
+ if (
116
+ error.code === "InvalidInternetGatewayID.NotFound" ||
117
+ error.code === "InvalidInternetGateway.NotFound"
118
+ ) {
119
+ return undefined;
120
+ }
121
+ throw error;
122
+ }
123
+ };
124
+
125
+ const isReady = (igw: AwsInternetGateway | undefined) => {
126
+ // Internet Gateway is deleted if it doesn't exist
127
+ return !igw;
128
+ };
129
+
130
+ await waitForResourceState(
131
+ checkFunction,
132
+ isReady,
133
+ timeoutConfig,
134
+ internetGatewayId,
135
+ "Internet Gateway",
136
+ "deletion completed",
137
+ );
138
+ }
139
+
140
+ /**
141
+ * AWS Internet Gateway Resource
142
+ *
143
+ * An Internet Gateway is a horizontally scaled, redundant, and highly available VPC component
144
+ * that allows communication between your VPC and the internet. It serves two purposes:
145
+ * 1. Provide a target in your VPC route tables for internet-routable traffic
146
+ * 2. Perform network address translation (NAT) for instances with public IPv4 addresses
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * // Create a basic Internet Gateway
151
+ * const igw = new InternetGateway({
152
+ * tags: {
153
+ * Name: "my-internet-gateway",
154
+ * Environment: "production"
155
+ * }
156
+ * });
157
+ * ```
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * // Create Internet Gateway with custom timeout configuration
162
+ * const igw = new InternetGateway({
163
+ * tags: { Name: "custom-igw" },
164
+ * timeoutConfig: {
165
+ * maxAttempts: 30,
166
+ * delayMs: 1000
167
+ * }
168
+ * });
169
+ * ```
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * // Create Internet Gateway and attach to VPC
174
+ * const vpc = new VPC({ cidrBlock: "10.0.0.0/16" });
175
+ * const igw = new InternetGateway({ tags: { Name: "vpc-igw" } });
176
+ * const attachment = new InternetGatewayAttachment({
177
+ * internetGatewayId: igw.internetGatewayId,
178
+ * vpcId: vpc.vpcId
179
+ * });
180
+ * ```
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Access Internet Gateway properties
185
+ * const igw = new InternetGateway({ tags: { Name: "example-igw" } });
186
+ * logger.log(`Internet Gateway ID: ${igw.internetGatewayId}`);
187
+ * logger.log(`State: ${igw.state}`);
188
+ * ```
189
+ *
190
+ * Creates and manages Internet Gateways that provide internet access to VPCs.
191
+ * Note: Use InternetGatewayAttachment to attach the gateway to a VPC.
192
+ *
193
+ * @example
194
+ * // Create a basic Internet Gateway
195
+ * const igw = await InternetGateway("main-igw", {
196
+ * tags: {
197
+ * Name: "main-internet-gateway",
198
+ * Environment: "production"
199
+ * }
200
+ * });
201
+ *
202
+ * @example
203
+ * // Create an Internet Gateway for development environment
204
+ * const devIgw = await InternetGateway("dev-igw", {
205
+ * tags: {
206
+ * Name: "dev-internet-gateway",
207
+ * Environment: "development",
208
+ * Team: "backend"
209
+ * }
210
+ * });
211
+ *
212
+ * @example
213
+ * // Create an Internet Gateway with custom timeout configuration
214
+ * const customIgw = await InternetGateway("custom-igw", {
215
+ * timeout: {
216
+ * maxAttempts: 90,
217
+ * delayMs: 1500
218
+ * },
219
+ * tags: {
220
+ * Name: "custom-timeout-igw",
221
+ * Purpose: "high-availability"
222
+ * }
223
+ * });
224
+ */
225
+ export const InternetGateway = Resource(
226
+ "aws::InternetGateway",
227
+ async function (
228
+ this: Context<InternetGateway>,
229
+ _id: string,
230
+ props: InternetGatewayProps,
231
+ ): Promise<InternetGateway> {
232
+ const client = await createEC2Client();
233
+ const timeoutConfig = mergeTimeoutConfig(
234
+ INTERNET_GATEWAY_TIMEOUT,
235
+ props.timeout,
236
+ );
237
+
238
+ if (this.phase === "delete") {
239
+ if (this.output?.internetGatewayId) {
240
+ logger.log(
241
+ `🗑️ Deleting Internet Gateway: ${this.output.internetGatewayId}`,
242
+ );
243
+
244
+ // Simply delete the Internet Gateway - attachments should handle themselves
245
+ await ignore("InvalidInternetGatewayID.NotFound", async () => {
246
+ await callEC2Api(
247
+ client,
248
+ "DeleteInternetGateway",
249
+ parseInternetGatewayXmlResponse,
250
+ {
251
+ InternetGatewayId: this.output.internetGatewayId,
252
+ },
253
+ );
254
+ });
255
+
256
+ // Wait for Internet Gateway to be fully deleted
257
+ await waitForInternetGatewayDeleted(
258
+ client,
259
+ this.output.internetGatewayId,
260
+ timeoutConfig,
261
+ );
262
+
263
+ logger.log(
264
+ ` ✅ Internet Gateway ${this.output.internetGatewayId} deletion completed`,
265
+ );
266
+ }
267
+ return this.destroy();
268
+ }
269
+
270
+ let internetGateway: AwsInternetGateway;
271
+
272
+ if (this.phase === "update" && this.output?.internetGatewayId) {
273
+ // Get existing Internet Gateway
274
+ const response = await callEC2Api<DescribeInternetGatewaysResponse>(
275
+ client,
276
+ "DescribeInternetGateways",
277
+ parseInternetGatewayXmlResponse,
278
+ {
279
+ "InternetGatewayId.1": this.output.internetGatewayId,
280
+ },
281
+ );
282
+
283
+ if (!response.InternetGateways?.[0]) {
284
+ throw new Error(
285
+ `Internet Gateway ${this.output.internetGatewayId} not found`,
286
+ );
287
+ }
288
+
289
+ internetGateway = response.InternetGateways[0];
290
+ } else {
291
+ // Create new Internet Gateway
292
+ const createInternetGatewayParams: CreateInternetGatewayParams = {};
293
+
294
+ // Add tags if provided
295
+ if (props.tags) {
296
+ createInternetGatewayParams.TagSpecifications = [
297
+ {
298
+ ResourceType: "internet-gateway",
299
+ Tags: Object.entries(props.tags).map(([key, value]) => ({
300
+ Key: key,
301
+ Value: value,
302
+ })),
303
+ },
304
+ ];
305
+ }
306
+
307
+ const createParams = convertCreateInternetGatewayParamsToAwsFormat(
308
+ createInternetGatewayParams,
309
+ );
310
+
311
+ const response = await callEC2Api<CreateInternetGatewayResponse>(
312
+ client,
313
+ "CreateInternetGateway",
314
+ parseInternetGatewayXmlResponse,
315
+ createParams,
316
+ );
317
+
318
+ if (!response.InternetGateway) {
319
+ throw new Error("Failed to create Internet Gateway");
320
+ }
321
+
322
+ internetGateway = response.InternetGateway;
323
+
324
+ // Wait for Internet Gateway to be available
325
+ await waitForInternetGatewayAvailable(
326
+ client,
327
+ internetGateway.InternetGatewayId!,
328
+ timeoutConfig,
329
+ );
330
+ }
331
+
332
+ return this({
333
+ internetGatewayId: internetGateway.InternetGatewayId!,
334
+ state: "available",
335
+ attachments: internetGateway.Attachments?.map((att) => ({
336
+ vpcId: att.VpcId,
337
+ state: att.State,
338
+ })),
339
+ ownerId: internetGateway.OwnerId,
340
+ ...props,
341
+ });
342
+ },
343
+ );
344
+
345
+ /**
346
+ * Internet Gateway timeout constants
347
+ */
348
+ export const INTERNET_GATEWAY_TIMEOUT: TimeoutConfig = {
349
+ maxAttempts: 60,
350
+ delayMs: 2000, // 2 seconds - IGWs are medium speed resources
351
+ };
352
+
353
+ /**
354
+ * Comprehensive AWS Internet Gateway API Parameter Types
355
+ */
356
+
357
+ // Common structures
358
+ interface TagSpecification {
359
+ ResourceType: string;
360
+ Tags: Array<{
361
+ Key: string;
362
+ Value: string;
363
+ }>;
364
+ }
365
+
366
+ // Internet Gateway API Request Parameters
367
+ interface CreateInternetGatewayParams {
368
+ TagSpecifications?: TagSpecification[];
369
+ DryRun?: boolean;
370
+ }
371
+
372
+ /**
373
+ * Helper functions to convert typed parameters to AWS API format
374
+ */
375
+ function convertCreateInternetGatewayParamsToAwsFormat(
376
+ params: CreateInternetGatewayParams,
377
+ ): Record<string, string> {
378
+ const awsParams: Record<string, string> = {};
379
+
380
+ if (params.DryRun !== undefined) {
381
+ awsParams.DryRun = params.DryRun.toString();
382
+ }
383
+
384
+ // Handle TagSpecifications
385
+ if (params.TagSpecifications) {
386
+ params.TagSpecifications.forEach((tagSpec, specIndex) => {
387
+ const specNum = specIndex + 1;
388
+ awsParams[`TagSpecification.${specNum}.ResourceType`] =
389
+ tagSpec.ResourceType;
390
+
391
+ tagSpec.Tags.forEach((tag, tagIndex) => {
392
+ const tagNum = tagIndex + 1;
393
+ awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Key`] = tag.Key;
394
+ awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Value`] =
395
+ tag.Value;
396
+ });
397
+ });
398
+ }
399
+
400
+ return awsParams;
401
+ }
402
+
403
+ /**
404
+ * AWS Internet Gateway API response types
405
+ */
406
+ interface AwsInternetGateway {
407
+ InternetGatewayId: string;
408
+ State: "available";
409
+ Attachments: Array<{
410
+ VpcId: string;
411
+ State: "attaching" | "attached" | "detaching" | "detached";
412
+ }>;
413
+ Tags?: Array<{
414
+ Key: string;
415
+ Value: string;
416
+ }>;
417
+ OwnerId?: string;
418
+ }
419
+
420
+ interface CreateInternetGatewayResponse {
421
+ InternetGateway: AwsInternetGateway;
422
+ }
423
+
424
+ interface DescribeInternetGatewaysResponse {
425
+ InternetGateways: AwsInternetGateway[];
426
+ }
427
+
428
+ /**
429
+ * Raw XML parsing interfaces for type safety
430
+ */
431
+ interface RawInternetGatewayXmlItem {
432
+ internetGatewayId: string;
433
+ attachmentSet?: {
434
+ item?:
435
+ | Array<{
436
+ vpcId: string;
437
+ state: string;
438
+ }>
439
+ | {
440
+ vpcId: string;
441
+ state: string;
442
+ };
443
+ };
444
+ tagSet?: {
445
+ item?:
446
+ | Array<{
447
+ key: string;
448
+ value: string;
449
+ }>
450
+ | {
451
+ key: string;
452
+ value: string;
453
+ };
454
+ };
455
+ ownerId?: string;
456
+ }
457
+
458
+ /**
459
+ * Parse XML responses specifically for Internet Gateway operations
460
+ */
461
+ function parseInternetGatewayXmlResponse<T>(xmlText: string): T {
462
+ const parser = new XMLParser({
463
+ ignoreAttributes: true,
464
+ parseAttributeValue: true,
465
+ parseTagValue: true,
466
+ trimValues: true,
467
+ });
468
+
469
+ const parsed = parser.parse(xmlText);
470
+ const result: Record<string, unknown> = {};
471
+
472
+ // Parse CreateInternetGatewayResponse
473
+ if (parsed.CreateInternetGatewayResponse) {
474
+ const internetGateway = parsed.CreateInternetGatewayResponse
475
+ .internetGateway as RawInternetGatewayXmlItem;
476
+ if (internetGateway) {
477
+ result.InternetGateway = {
478
+ InternetGatewayId: internetGateway.internetGatewayId,
479
+ State: "available" as const, // Internet Gateways are immediately available
480
+ Attachments: internetGateway.attachmentSet?.item
481
+ ? (Array.isArray(internetGateway.attachmentSet.item)
482
+ ? internetGateway.attachmentSet.item
483
+ : [internetGateway.attachmentSet.item]
484
+ ).map((attachment) => ({
485
+ VpcId: attachment.vpcId,
486
+ State: attachment.state as
487
+ | "attaching"
488
+ | "attached"
489
+ | "detaching"
490
+ | "detached",
491
+ }))
492
+ : [],
493
+ Tags: internetGateway.tagSet?.item
494
+ ? Array.isArray(internetGateway.tagSet.item)
495
+ ? internetGateway.tagSet.item.map((tag) => ({
496
+ Key: tag.key,
497
+ Value: tag.value,
498
+ }))
499
+ : [
500
+ {
501
+ Key: internetGateway.tagSet.item.key,
502
+ Value: internetGateway.tagSet.item.value,
503
+ },
504
+ ]
505
+ : undefined,
506
+ OwnerId: internetGateway.ownerId,
507
+ };
508
+ }
509
+ }
510
+
511
+ // Parse DescribeInternetGatewaysResponse
512
+ if (parsed.DescribeInternetGatewaysResponse) {
513
+ const internetGatewaySet =
514
+ parsed.DescribeInternetGatewaysResponse.internetGatewaySet;
515
+ if (internetGatewaySet?.item) {
516
+ const igws = Array.isArray(internetGatewaySet.item)
517
+ ? internetGatewaySet.item
518
+ : [internetGatewaySet.item];
519
+ result.InternetGateways = igws.map((igw: RawInternetGatewayXmlItem) => ({
520
+ InternetGatewayId: igw.internetGatewayId,
521
+ State: "available" as const,
522
+ Attachments: igw.attachmentSet?.item
523
+ ? (Array.isArray(igw.attachmentSet.item)
524
+ ? igw.attachmentSet.item
525
+ : [igw.attachmentSet.item]
526
+ ).map((attachment) => ({
527
+ VpcId: attachment.vpcId,
528
+ State: attachment.state as
529
+ | "attaching"
530
+ | "attached"
531
+ | "detaching"
532
+ | "detached",
533
+ }))
534
+ : [],
535
+ Tags: igw.tagSet?.item
536
+ ? Array.isArray(igw.tagSet.item)
537
+ ? igw.tagSet.item.map((tag) => ({ Key: tag.key, Value: tag.value }))
538
+ : [{ Key: igw.tagSet.item.key, Value: igw.tagSet.item.value }]
539
+ : undefined,
540
+ OwnerId: igw.ownerId,
541
+ }));
542
+ } else {
543
+ result.InternetGateways = [];
544
+ }
545
+ }
546
+
547
+ // Handle success responses
548
+ if (
549
+ parsed.AttachInternetGatewayResponse ||
550
+ parsed.DetachInternetGatewayResponse ||
551
+ parsed.DeleteInternetGatewayResponse
552
+ ) {
553
+ result.success = true;
554
+ }
555
+
556
+ return result as T;
557
+ }