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.
- package/bin/alchemy.js +196353 -0
- package/bin/alchemy.ts +2 -2
- package/bin/commands/init.ts +1190 -0
- package/bin/constants.ts +18 -0
- package/bin/services/execute-alchemy.ts +7 -2
- package/bin/services/package-manager.ts +1 -1
- package/bin/types.ts +14 -5
- package/lib/aws/ec2/index.d.ts +10 -0
- package/lib/aws/ec2/index.d.ts.map +1 -0
- package/lib/aws/ec2/index.js +10 -0
- package/lib/aws/ec2/index.js.map +1 -0
- package/lib/aws/ec2/internet-gateway-attachment.d.ts +150 -0
- package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway-attachment.js +248 -0
- package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -0
- package/lib/aws/ec2/internet-gateway.d.ts +132 -0
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.js +311 -0
- package/lib/aws/ec2/internet-gateway.js.map +1 -0
- package/lib/aws/ec2/nat-gateway.d.ts +145 -0
- package/lib/aws/ec2/nat-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/nat-gateway.js +618 -0
- package/lib/aws/ec2/nat-gateway.js.map +1 -0
- package/lib/aws/ec2/route-table-association.d.ts +134 -0
- package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.js +364 -0
- package/lib/aws/ec2/route-table-association.js.map +1 -0
- package/lib/aws/ec2/route-table.d.ts +94 -0
- package/lib/aws/ec2/route-table.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.js +253 -0
- package/lib/aws/ec2/route-table.js.map +1 -0
- package/lib/aws/ec2/route.d.ts +130 -0
- package/lib/aws/ec2/route.d.ts.map +1 -0
- package/lib/aws/ec2/route.js +253 -0
- package/lib/aws/ec2/route.js.map +1 -0
- package/lib/aws/ec2/security-group-rule.d.ts +84 -0
- package/lib/aws/ec2/security-group-rule.d.ts.map +1 -0
- package/lib/aws/ec2/security-group-rule.js +123 -0
- package/lib/aws/ec2/security-group-rule.js.map +1 -0
- package/lib/aws/ec2/security-group.d.ts +84 -0
- package/lib/aws/ec2/security-group.d.ts.map +1 -0
- package/lib/aws/ec2/security-group.js +207 -0
- package/lib/aws/ec2/security-group.js.map +1 -0
- package/lib/aws/ec2/subnet.d.ts +110 -0
- package/lib/aws/ec2/subnet.d.ts.map +1 -0
- package/lib/aws/ec2/subnet.js +336 -0
- package/lib/aws/ec2/subnet.js.map +1 -0
- package/lib/aws/ec2/utils.d.ts +15 -0
- package/lib/aws/ec2/utils.d.ts.map +1 -0
- package/lib/aws/ec2/utils.js +79 -0
- package/lib/aws/ec2/utils.js.map +1 -0
- package/lib/aws/ec2/vpc.d.ts +160 -0
- package/lib/aws/ec2/vpc.d.ts.map +1 -0
- package/lib/aws/ec2/vpc.js +453 -0
- package/lib/aws/ec2/vpc.js.map +1 -0
- package/lib/aws/index.d.ts +7 -0
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +8 -0
- package/lib/aws/index.js.map +1 -1
- package/lib/aws/utils.d.ts +25 -0
- package/lib/aws/utils.d.ts.map +1 -0
- package/lib/aws/utils.js +89 -0
- package/lib/aws/utils.js.map +1 -0
- package/lib/build-date.d.ts +6 -0
- package/lib/build-date.d.ts.map +1 -0
- package/lib/build-date.js +8 -0
- package/lib/build-date.js.map +1 -0
- package/lib/cloudflare/astro.d.ts.map +1 -1
- package/lib/cloudflare/astro.js +4 -3
- package/lib/cloudflare/astro.js.map +1 -1
- package/lib/cloudflare/bundle/externals.d.ts +3 -0
- package/lib/cloudflare/bundle/externals.d.ts.map +1 -0
- package/lib/cloudflare/bundle/externals.js +35 -0
- package/lib/cloudflare/bundle/externals.js.map +1 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.d.ts +8 -1
- package/lib/cloudflare/bundle/internal-worker-bundle.d.ts.map +1 -1
- package/lib/cloudflare/bundle/internal-worker-bundle.js +11 -4
- package/lib/cloudflare/bundle/internal-worker-bundle.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-hot-reload.d.ts +4 -1
- package/lib/cloudflare/bundle/plugin-hot-reload.d.ts.map +1 -1
- package/lib/cloudflare/bundle/plugin-hot-reload.js +27 -11
- package/lib/cloudflare/bundle/plugin-hot-reload.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js +5 -1
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-wasm.d.ts +6 -2
- package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -1
- package/lib/cloudflare/bundle/plugin-wasm.js +21 -47
- package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
- package/lib/cloudflare/bundle/validate-node-compat.d.ts +2 -1
- package/lib/cloudflare/bundle/validate-node-compat.d.ts.map +1 -1
- package/lib/cloudflare/bundle/validate-node-compat.js +5 -4
- package/lib/cloudflare/bundle/validate-node-compat.js.map +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/d1-database.js +1 -1
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/cloudflare/d1-migrations.d.ts.map +1 -1
- package/lib/cloudflare/d1-migrations.js +8 -10
- package/lib/cloudflare/d1-migrations.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-options.d.ts +3 -3
- package/lib/cloudflare/miniflare/miniflare-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-options.js +23 -6
- package/lib/cloudflare/miniflare/miniflare-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare.js +2 -4
- package/lib/cloudflare/miniflare/miniflare.js.map +1 -1
- package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/remote-binding-proxy.js +4 -6
- package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -1
- package/lib/cloudflare/react-router.d.ts +4 -0
- package/lib/cloudflare/react-router.d.ts.map +1 -1
- package/lib/cloudflare/react-router.js +8 -5
- package/lib/cloudflare/react-router.js.map +1 -1
- package/lib/cloudflare/worker-bundle.d.ts +80 -0
- package/lib/cloudflare/worker-bundle.d.ts.map +1 -0
- package/lib/cloudflare/worker-bundle.js +266 -0
- package/lib/cloudflare/worker-bundle.js.map +1 -0
- package/lib/cloudflare/worker.d.ts +1 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +81 -195
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/esbuild/bundle.d.ts +1 -0
- package/lib/esbuild/bundle.d.ts.map +1 -1
- package/lib/state/cloudflare-state-store.js +1 -5
- package/lib/state/cloudflare-state-store.js.map +1 -1
- package/lib/state/dofs-state-store/store.d.ts.map +1 -1
- package/lib/state/dofs-state-store/store.js +4 -4
- package/lib/state/dofs-state-store/store.js.map +1 -1
- package/lib/util/params.d.ts +5 -0
- package/lib/util/params.d.ts.map +1 -0
- package/lib/util/params.js +30 -0
- package/lib/util/params.js.map +1 -0
- package/lib/util/timeout.d.ts +31 -0
- package/lib/util/timeout.d.ts.map +1 -0
- package/lib/util/timeout.js +109 -0
- package/lib/util/timeout.js.map +1 -0
- package/lib/util/xml.d.ts +5 -0
- package/lib/util/xml.d.ts.map +1 -0
- package/lib/util/xml.js +8 -0
- package/lib/util/xml.js.map +1 -0
- package/package.json +12 -5
- package/src/aws/ec2/index.ts +9 -0
- package/src/aws/ec2/internet-gateway-attachment.ts +468 -0
- package/src/aws/ec2/internet-gateway.ts +557 -0
- package/src/aws/ec2/nat-gateway.ts +1123 -0
- package/src/aws/ec2/route-table-association.ts +747 -0
- package/src/aws/ec2/route-table.ts +452 -0
- package/src/aws/ec2/route.ts +447 -0
- package/src/aws/ec2/security-group-rule.ts +229 -0
- package/src/aws/ec2/security-group.ts +418 -0
- package/src/aws/ec2/subnet.ts +625 -0
- package/src/aws/ec2/utils.ts +102 -0
- package/src/aws/ec2/vpc.ts +969 -0
- package/src/aws/index.ts +9 -0
- package/src/aws/utils.ts +137 -0
- package/src/build-date.ts +8 -0
- package/src/cloudflare/astro.ts +4 -3
- package/src/cloudflare/bundle/externals.ts +36 -0
- package/src/cloudflare/bundle/internal-worker-bundle.ts +12 -3
- package/src/cloudflare/bundle/plugin-hot-reload.ts +32 -12
- package/src/cloudflare/bundle/plugin-hybrid-node-compat.ts +6 -1
- package/src/cloudflare/bundle/plugin-wasm.ts +26 -54
- package/src/cloudflare/bundle/validate-node-compat.ts +6 -5
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/d1-database.ts +1 -1
- package/src/cloudflare/d1-migrations.ts +19 -18
- package/src/cloudflare/miniflare/miniflare-worker-options.ts +27 -13
- package/src/cloudflare/miniflare/miniflare.ts +2 -4
- package/src/cloudflare/miniflare/remote-binding-proxy.ts +5 -7
- package/src/cloudflare/react-router.ts +14 -6
- package/src/cloudflare/worker-bundle.ts +364 -0
- package/src/cloudflare/worker.ts +104 -241
- package/src/state/cloudflare-state-store.ts +1 -5
- package/src/state/dofs-state-store/store.ts +4 -4
- package/src/util/params.ts +33 -0
- package/src/util/timeout.ts +178 -0
- package/src/util/xml.ts +7 -0
- package/templates/nuxt/package.json +1 -1
- package/templates/nuxt/types/env.d.ts +11 -0
- package/templates/react-router/workers/app.ts +2 -2
- package/templates/rwsdk/.cursor/rules/alchemy_cloudflare.mdc +385 -0
- package/templates/rwsdk/wrangler.jsonc +10 -7
- package/templates/typescript/tsconfig.json +1 -2
- package/bin/alchemy.mjs +0 -51766
- package/lib/cloudflare/bundle/esbuild.d.ts +0 -16
- package/lib/cloudflare/bundle/esbuild.d.ts.map +0 -1
- package/lib/cloudflare/bundle/esbuild.js +0 -159
- package/lib/cloudflare/bundle/esbuild.js.map +0 -1
- package/lib/cloudflare/bundle/fs.d.ts +0 -18
- package/lib/cloudflare/bundle/fs.d.ts.map +0 -1
- package/lib/cloudflare/bundle/fs.js +0 -78
- package/lib/cloudflare/bundle/fs.js.map +0 -1
- package/lib/cloudflare/bundle/index.d.ts +0 -3
- package/lib/cloudflare/bundle/index.d.ts.map +0 -1
- package/lib/cloudflare/bundle/index.js +0 -2
- package/lib/cloudflare/bundle/index.js.map +0 -1
- package/lib/cloudflare/bundle/inline.d.ts +0 -12
- package/lib/cloudflare/bundle/inline.d.ts.map +0 -1
- package/lib/cloudflare/bundle/inline.js +0 -32
- package/lib/cloudflare/bundle/inline.js.map +0 -1
- package/lib/cloudflare/bundle/normalize.d.ts +0 -21
- package/lib/cloudflare/bundle/normalize.d.ts.map +0 -1
- package/lib/cloudflare/bundle/normalize.js +0 -49
- package/lib/cloudflare/bundle/normalize.js.map +0 -1
- package/lib/cloudflare/bundle/shared.d.ts +0 -30
- package/lib/cloudflare/bundle/shared.d.ts.map +0 -1
- package/lib/cloudflare/bundle/shared.js +0 -34
- package/lib/cloudflare/bundle/shared.js.map +0 -1
- package/src/cloudflare/bundle/esbuild.ts +0 -194
- package/src/cloudflare/bundle/fs.ts +0 -103
- package/src/cloudflare/bundle/index.ts +0 -6
- package/src/cloudflare/bundle/inline.ts +0 -42
- package/src/cloudflare/bundle/normalize.ts +0 -76
- 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
|
+
}
|