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,468 @@
|
|
|
1
|
+
import { XMLParser } from "fast-xml-parser";
|
|
2
|
+
import type { Context } from "../../context.ts";
|
|
3
|
+
import { Resource } from "../../resource.ts";
|
|
4
|
+
import { ignore } from "../../util/ignore.ts";
|
|
5
|
+
import { logger } from "../../util/logger.ts";
|
|
6
|
+
import {
|
|
7
|
+
mergeTimeoutConfig,
|
|
8
|
+
type TimeoutConfig,
|
|
9
|
+
waitForResourceState,
|
|
10
|
+
} from "../../util/timeout.ts";
|
|
11
|
+
import type { InternetGateway } from "./internet-gateway.ts";
|
|
12
|
+
import { callEC2Api, createEC2Client } from "./utils.ts";
|
|
13
|
+
import type { Vpc } from "./vpc.ts";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Properties for creating or updating an Internet Gateway Attachment
|
|
17
|
+
*/
|
|
18
|
+
export interface InternetGatewayAttachmentProps {
|
|
19
|
+
/**
|
|
20
|
+
* The Internet Gateway to attach
|
|
21
|
+
*/
|
|
22
|
+
internetGateway: InternetGateway | string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The VPC to attach the Internet Gateway to
|
|
26
|
+
*/
|
|
27
|
+
vpc: Vpc | string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Timeout configuration for Internet Gateway Attachment operations
|
|
31
|
+
* @default Internet Gateway Attachment-specific sensible defaults (60 attempts, 2000ms delay)
|
|
32
|
+
*/
|
|
33
|
+
timeout?: Partial<TimeoutConfig>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Output returned after Internet Gateway Attachment creation/update
|
|
38
|
+
*/
|
|
39
|
+
export interface InternetGatewayAttachment
|
|
40
|
+
extends Resource<"aws::InternetGatewayAttachment">,
|
|
41
|
+
InternetGatewayAttachmentProps {
|
|
42
|
+
/**
|
|
43
|
+
* The ID of the Internet Gateway
|
|
44
|
+
*/
|
|
45
|
+
internetGatewayId: string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The ID of the VPC
|
|
49
|
+
*/
|
|
50
|
+
vpcId: string;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The current state of the attachment
|
|
54
|
+
*/
|
|
55
|
+
state: "attaching" | "attached" | "detaching" | "detached";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* AWS Internet Gateway Attachment Resource
|
|
60
|
+
*
|
|
61
|
+
* Manages the attachment of an Internet Gateway to a VPC, enabling internet connectivity
|
|
62
|
+
* for the VPC. This is a separate resource to ensure proper dependency ordering and
|
|
63
|
+
* lifecycle management between Internet Gateways and VPCs.
|
|
64
|
+
*
|
|
65
|
+
* An Internet Gateway attachment is required for any VPC that needs internet access.
|
|
66
|
+
* The attachment creates a logical connection between the Internet Gateway and the VPC,
|
|
67
|
+
* allowing traffic to flow between the VPC and the internet when combined with proper
|
|
68
|
+
* routing configuration.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // Basic Internet Gateway attachment for internet connectivity
|
|
72
|
+
* const vpc = await Vpc("main-vpc", {
|
|
73
|
+
* cidrBlock: "10.0.0.0/16"
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* const igw = await InternetGateway("main-igw", {});
|
|
77
|
+
*
|
|
78
|
+
* const attachment = await InternetGatewayAttachment("main-igw-attachment", {
|
|
79
|
+
* internetGateway: igw,
|
|
80
|
+
* vpc: vpc
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* // Internet Gateway attachment with custom timeout configuration
|
|
85
|
+
* // for environments with slower AWS API responses
|
|
86
|
+
* const attachment = await InternetGatewayAttachment("slow-env-attachment", {
|
|
87
|
+
* internetGateway: "igw-1234567890abcdef0",
|
|
88
|
+
* vpc: "vpc-0987654321fedcba0",
|
|
89
|
+
* timeout: {
|
|
90
|
+
* maxAttempts: 120,
|
|
91
|
+
* delayMs: 3000
|
|
92
|
+
* }
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* // Complete setup for a VPC with internet access including routing
|
|
97
|
+
* const vpc = await Vpc("web-vpc", {
|
|
98
|
+
* cidrBlock: "10.0.0.0/16",
|
|
99
|
+
* enableDnsHostnames: true,
|
|
100
|
+
* enableDnsSupport: true
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* const igw = await InternetGateway("web-igw", {});
|
|
104
|
+
*
|
|
105
|
+
* const attachment = await InternetGatewayAttachment("web-igw-attachment", {
|
|
106
|
+
* internetGateway: igw,
|
|
107
|
+
* vpc: vpc
|
|
108
|
+
* });
|
|
109
|
+
*
|
|
110
|
+
* // Create public subnet and route table for internet access
|
|
111
|
+
* const publicSubnet = await Subnet("public-subnet", {
|
|
112
|
+
* vpc,
|
|
113
|
+
* cidrBlock: "10.0.1.0/24",
|
|
114
|
+
* availabilityZone: "us-east-1a"
|
|
115
|
+
* });
|
|
116
|
+
*
|
|
117
|
+
* const publicRouteTable = await RouteTable("public-rt", {
|
|
118
|
+
* vpc: vpc
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* const internetRoute = await Route("internet-route", {
|
|
122
|
+
* routeTable: publicRouteTable,
|
|
123
|
+
* destinationCidrBlock: "0.0.0.0/0",
|
|
124
|
+
* gateway: igw
|
|
125
|
+
* });
|
|
126
|
+
*/
|
|
127
|
+
export const InternetGatewayAttachment = Resource(
|
|
128
|
+
"aws::InternetGatewayAttachment",
|
|
129
|
+
async function (
|
|
130
|
+
this: Context<InternetGatewayAttachment>,
|
|
131
|
+
_id: string,
|
|
132
|
+
props: InternetGatewayAttachmentProps,
|
|
133
|
+
): Promise<InternetGatewayAttachment> {
|
|
134
|
+
const client = await createEC2Client();
|
|
135
|
+
const timeoutConfig = mergeTimeoutConfig(
|
|
136
|
+
INTERNET_GATEWAY_ATTACHMENT_TIMEOUT,
|
|
137
|
+
props.timeout,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const internetGatewayId =
|
|
141
|
+
typeof props.internetGateway === "string"
|
|
142
|
+
? props.internetGateway
|
|
143
|
+
: props.internetGateway.internetGatewayId;
|
|
144
|
+
const vpcId = typeof props.vpc === "string" ? props.vpc : props.vpc.vpcId;
|
|
145
|
+
|
|
146
|
+
if (this.phase === "delete") {
|
|
147
|
+
if (this.output?.internetGatewayId && this.output?.vpcId) {
|
|
148
|
+
logger.log(
|
|
149
|
+
`🗑️ Detaching Internet Gateway: ${this.output.internetGatewayId} from VPC: ${this.output.vpcId}`,
|
|
150
|
+
);
|
|
151
|
+
await ignore("Gateway.NotAttached", async () => {
|
|
152
|
+
await ignore("InvalidInternetGatewayID.NotFound", async () => {
|
|
153
|
+
await ignore("InvalidVpcID.NotFound", async () => {
|
|
154
|
+
await callEC2Api(
|
|
155
|
+
client,
|
|
156
|
+
"DetachInternetGateway",
|
|
157
|
+
parseInternetGatewayAttachmentXmlResponse,
|
|
158
|
+
{
|
|
159
|
+
InternetGatewayId: this.output!.internetGatewayId,
|
|
160
|
+
VpcId: this.output!.vpcId,
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const checkDetached = async () => {
|
|
168
|
+
try {
|
|
169
|
+
const response =
|
|
170
|
+
await callEC2Api<DescribeInternetGatewaysApiResponse>(
|
|
171
|
+
client,
|
|
172
|
+
"DescribeInternetGateways",
|
|
173
|
+
parseInternetGatewayAttachmentXmlResponse,
|
|
174
|
+
{
|
|
175
|
+
"InternetGatewayId.1": this.output!.internetGatewayId,
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
const igw = response.InternetGateways?.[0];
|
|
179
|
+
if (!igw) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
return igw.Attachments?.find(
|
|
183
|
+
(att) => att.VpcId === this.output!.vpcId,
|
|
184
|
+
);
|
|
185
|
+
} catch (error: any) {
|
|
186
|
+
if (error.code === "InvalidInternetGatewayID.NotFound") {
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
await waitForResourceState(
|
|
194
|
+
checkDetached,
|
|
195
|
+
(attachment) => !attachment,
|
|
196
|
+
timeoutConfig,
|
|
197
|
+
`${this.output.internetGatewayId} to ${this.output.vpcId}`,
|
|
198
|
+
"Internet Gateway Attachment",
|
|
199
|
+
"to be detached",
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
logger.log(
|
|
203
|
+
` ✅ Internet Gateway ${this.output.internetGatewayId} detached from VPC ${this.output.vpcId}`,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
return this.destroy();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Check if already attached
|
|
210
|
+
if (this.phase === "update" && this.output?.internetGatewayId) {
|
|
211
|
+
// Verify the attachment still exists
|
|
212
|
+
const response = await callEC2Api<DescribeInternetGatewaysApiResponse>(
|
|
213
|
+
client,
|
|
214
|
+
"DescribeInternetGateways",
|
|
215
|
+
parseInternetGatewayAttachmentXmlResponse,
|
|
216
|
+
{
|
|
217
|
+
"InternetGatewayId.1": this.output.internetGatewayId,
|
|
218
|
+
},
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const igw = response.InternetGateways?.[0];
|
|
222
|
+
const attachment = igw?.Attachments?.find((att) => att.VpcId === vpcId);
|
|
223
|
+
|
|
224
|
+
if (attachment) {
|
|
225
|
+
return this({
|
|
226
|
+
internetGatewayId,
|
|
227
|
+
vpcId,
|
|
228
|
+
state: "attached",
|
|
229
|
+
...props,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Check if already attached before creating
|
|
235
|
+
const checkResponse = await callEC2Api<DescribeInternetGatewaysApiResponse>(
|
|
236
|
+
client,
|
|
237
|
+
"DescribeInternetGateways",
|
|
238
|
+
parseInternetGatewayAttachmentXmlResponse,
|
|
239
|
+
{
|
|
240
|
+
"InternetGatewayId.1": internetGatewayId,
|
|
241
|
+
},
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const existingIgw = checkResponse.InternetGateways?.[0];
|
|
245
|
+
const existingAttachment = existingIgw?.Attachments?.find(
|
|
246
|
+
(att) => att.VpcId === vpcId,
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
if (!existingAttachment) {
|
|
250
|
+
// Create the attachment only if it doesn't exist
|
|
251
|
+
await callEC2Api(
|
|
252
|
+
client,
|
|
253
|
+
"AttachInternetGateway",
|
|
254
|
+
parseInternetGatewayAttachmentXmlResponse,
|
|
255
|
+
{
|
|
256
|
+
InternetGatewayId: internetGatewayId,
|
|
257
|
+
VpcId: vpcId,
|
|
258
|
+
},
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Wait for attachment to complete
|
|
263
|
+
const checkAttached = async () => {
|
|
264
|
+
try {
|
|
265
|
+
const response = await callEC2Api<DescribeInternetGatewaysApiResponse>(
|
|
266
|
+
client,
|
|
267
|
+
"DescribeInternetGateways",
|
|
268
|
+
parseInternetGatewayAttachmentXmlResponse,
|
|
269
|
+
{
|
|
270
|
+
"InternetGatewayId.1": internetGatewayId,
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
const igw = response.InternetGateways?.[0];
|
|
274
|
+
if (!igw) {
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
return igw.Attachments?.find((att) => att.VpcId === vpcId);
|
|
278
|
+
} catch (error: any) {
|
|
279
|
+
if (error.code === "InvalidInternetGatewayID.NotFound") {
|
|
280
|
+
return undefined;
|
|
281
|
+
}
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const isAttached = (attachment: DescribedAttachment | undefined) => {
|
|
287
|
+
return (
|
|
288
|
+
attachment?.State === "attached" || attachment?.State === "available"
|
|
289
|
+
);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
await waitForResourceState(
|
|
293
|
+
checkAttached,
|
|
294
|
+
isAttached,
|
|
295
|
+
timeoutConfig,
|
|
296
|
+
`${internetGatewayId} to ${vpcId}`,
|
|
297
|
+
"Internet Gateway Attachment",
|
|
298
|
+
"to be attached",
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
return this({
|
|
302
|
+
internetGatewayId,
|
|
303
|
+
vpcId,
|
|
304
|
+
state: "attached",
|
|
305
|
+
...props,
|
|
306
|
+
});
|
|
307
|
+
},
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Possible states for an Internet Gateway attachment.
|
|
312
|
+
*/
|
|
313
|
+
type AttachmentState =
|
|
314
|
+
| "attaching"
|
|
315
|
+
| "attached"
|
|
316
|
+
| "detaching"
|
|
317
|
+
| "detached"
|
|
318
|
+
| "available";
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Represents an attachment as described by the EC2 API.
|
|
322
|
+
*/
|
|
323
|
+
interface DescribedAttachment {
|
|
324
|
+
VpcId: string;
|
|
325
|
+
State: AttachmentState;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Represents a tag as described by the EC2 API.
|
|
330
|
+
*/
|
|
331
|
+
interface DescribedTag {
|
|
332
|
+
Key: string;
|
|
333
|
+
Value: string;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Represents an Internet Gateway as described by the EC2 API.
|
|
338
|
+
*/
|
|
339
|
+
interface DescribedInternetGateway {
|
|
340
|
+
InternetGatewayId: string;
|
|
341
|
+
State: "available";
|
|
342
|
+
Attachments: DescribedAttachment[];
|
|
343
|
+
Tags?: DescribedTag[];
|
|
344
|
+
OwnerId: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* The structure of the response from the DescribeInternetGateways API call.
|
|
349
|
+
*/
|
|
350
|
+
export interface DescribeInternetGatewaysApiResponse {
|
|
351
|
+
InternetGateways: DescribedInternetGateway[];
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Represents a tag item parsed from the raw XML response.
|
|
356
|
+
*/
|
|
357
|
+
interface XmlTagItem {
|
|
358
|
+
key: string;
|
|
359
|
+
value: string;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Represents an attachment item parsed from the raw XML response.
|
|
364
|
+
*/
|
|
365
|
+
interface XmlAttachmentItem {
|
|
366
|
+
vpcId: string;
|
|
367
|
+
state: AttachmentState;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Represents an Internet Gateway item parsed from the raw XML response.
|
|
372
|
+
*/
|
|
373
|
+
interface XmlInternetGatewayItem {
|
|
374
|
+
internetGatewayId: string;
|
|
375
|
+
ownerId: string;
|
|
376
|
+
attachmentSet?: {
|
|
377
|
+
item: XmlAttachmentItem | XmlAttachmentItem[];
|
|
378
|
+
};
|
|
379
|
+
tagSet?: {
|
|
380
|
+
item: XmlTagItem | XmlTagItem[];
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Internet Gateway Attachment timeout constants
|
|
386
|
+
*/
|
|
387
|
+
export const INTERNET_GATEWAY_ATTACHMENT_TIMEOUT: TimeoutConfig = {
|
|
388
|
+
maxAttempts: 60,
|
|
389
|
+
delayMs: 2000, // 2 seconds - IGW attachments are usually fast
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Parse XML responses for Internet Gateway Attachment operations
|
|
394
|
+
*/
|
|
395
|
+
function parseInternetGatewayAttachmentXmlResponse<T>(xmlText: string): T {
|
|
396
|
+
const parser = new XMLParser({
|
|
397
|
+
ignoreAttributes: true,
|
|
398
|
+
parseAttributeValue: true,
|
|
399
|
+
parseTagValue: true,
|
|
400
|
+
trimValues: true,
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const parsed = parser.parse(xmlText);
|
|
404
|
+
const result: Record<string, unknown> = {};
|
|
405
|
+
|
|
406
|
+
// Handle success responses
|
|
407
|
+
if (parsed.AttachInternetGatewayResponse) {
|
|
408
|
+
result.success = true;
|
|
409
|
+
result.return = parsed.AttachInternetGatewayResponse.return;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (parsed.DetachInternetGatewayResponse) {
|
|
413
|
+
result.success = true;
|
|
414
|
+
result.return = parsed.DetachInternetGatewayResponse.return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Handle DescribeInternetGatewaysResponse
|
|
418
|
+
if (parsed.DescribeInternetGatewaysResponse) {
|
|
419
|
+
const internetGatewaySet =
|
|
420
|
+
parsed.DescribeInternetGatewaysResponse.internetGatewaySet;
|
|
421
|
+
if (internetGatewaySet?.item) {
|
|
422
|
+
const igws: XmlInternetGatewayItem[] = Array.isArray(
|
|
423
|
+
internetGatewaySet.item,
|
|
424
|
+
)
|
|
425
|
+
? internetGatewaySet.item
|
|
426
|
+
: [internetGatewaySet.item];
|
|
427
|
+
|
|
428
|
+
result.InternetGateways = igws.map((igw): DescribedInternetGateway => {
|
|
429
|
+
const attachments = igw.attachmentSet?.item
|
|
430
|
+
? Array.isArray(igw.attachmentSet.item)
|
|
431
|
+
? igw.attachmentSet.item
|
|
432
|
+
: [igw.attachmentSet.item]
|
|
433
|
+
: [];
|
|
434
|
+
|
|
435
|
+
const tags = igw.tagSet?.item
|
|
436
|
+
? Array.isArray(igw.tagSet.item)
|
|
437
|
+
? igw.tagSet.item
|
|
438
|
+
: [igw.tagSet.item]
|
|
439
|
+
: [];
|
|
440
|
+
|
|
441
|
+
return {
|
|
442
|
+
InternetGatewayId: igw.internetGatewayId,
|
|
443
|
+
State: "available", // IGWs are always available once created
|
|
444
|
+
Attachments: attachments.map(
|
|
445
|
+
(attachment): DescribedAttachment => ({
|
|
446
|
+
VpcId: attachment.vpcId,
|
|
447
|
+
State: attachment.state,
|
|
448
|
+
}),
|
|
449
|
+
),
|
|
450
|
+
Tags:
|
|
451
|
+
tags.length > 0
|
|
452
|
+
? tags.map(
|
|
453
|
+
(tag): DescribedTag => ({
|
|
454
|
+
Key: tag.key,
|
|
455
|
+
Value: tag.value,
|
|
456
|
+
}),
|
|
457
|
+
)
|
|
458
|
+
: undefined,
|
|
459
|
+
OwnerId: igw.ownerId,
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
} else {
|
|
463
|
+
result.InternetGateways = [];
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return result as T;
|
|
468
|
+
}
|