alchemy 0.61.0 → 0.62.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 (143) hide show
  1. package/README.md +1 -2
  2. package/bin/alchemy.js +1406 -1464
  3. package/bin/commands/init.ts +29 -2
  4. package/bin/services/execute-alchemy.ts +1 -2
  5. package/lib/alchemy.d.ts +2 -2
  6. package/lib/alchemy.d.ts.map +1 -1
  7. package/lib/alchemy.js.map +1 -1
  8. package/lib/aws/client-props.d.ts +149 -0
  9. package/lib/aws/client-props.d.ts.map +1 -0
  10. package/lib/aws/client-props.js +1 -0
  11. package/lib/aws/client-props.js.map +1 -0
  12. package/lib/aws/credentials.d.ts +68 -5
  13. package/lib/aws/credentials.d.ts.map +1 -1
  14. package/lib/aws/credentials.js +148 -0
  15. package/lib/aws/credentials.js.map +1 -1
  16. package/lib/aws/ec2/internet-gateway-attachment.d.ts +57 -3
  17. package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -1
  18. package/lib/aws/ec2/internet-gateway-attachment.js +57 -3
  19. package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -1
  20. package/lib/aws/ec2/internet-gateway.d.ts +68 -40
  21. package/lib/aws/ec2/internet-gateway.d.ts.map +1 -1
  22. package/lib/aws/ec2/internet-gateway.js +68 -40
  23. package/lib/aws/ec2/internet-gateway.js.map +1 -1
  24. package/lib/aws/ec2/nat-gateway.d.ts +99 -18
  25. package/lib/aws/ec2/nat-gateway.d.ts.map +1 -1
  26. package/lib/aws/ec2/nat-gateway.js +113 -37
  27. package/lib/aws/ec2/nat-gateway.js.map +1 -1
  28. package/lib/aws/ec2/route-table-association.d.ts +1 -1
  29. package/lib/aws/ec2/route-table-association.js +1 -1
  30. package/lib/aws/ec2/route-table.d.ts +64 -1
  31. package/lib/aws/ec2/route-table.d.ts.map +1 -1
  32. package/lib/aws/ec2/route-table.js +64 -1
  33. package/lib/aws/ec2/route-table.js.map +1 -1
  34. package/lib/aws/ec2/route.d.ts +60 -1
  35. package/lib/aws/ec2/route.d.ts.map +1 -1
  36. package/lib/aws/ec2/route.js +60 -1
  37. package/lib/aws/ec2/route.js.map +1 -1
  38. package/lib/aws/ec2/security-group.d.ts +96 -3
  39. package/lib/aws/ec2/security-group.d.ts.map +1 -1
  40. package/lib/aws/ec2/security-group.js +96 -3
  41. package/lib/aws/ec2/security-group.js.map +1 -1
  42. package/lib/aws/ec2/subnet.d.ts +61 -3
  43. package/lib/aws/ec2/subnet.d.ts.map +1 -1
  44. package/lib/aws/ec2/subnet.js +61 -3
  45. package/lib/aws/ec2/subnet.js.map +1 -1
  46. package/lib/aws/ec2/utils.d.ts +10 -2
  47. package/lib/aws/ec2/utils.d.ts.map +1 -1
  48. package/lib/aws/ec2/utils.js +68 -7
  49. package/lib/aws/ec2/utils.js.map +1 -1
  50. package/lib/aws/ec2/vpc.d.ts +50 -2
  51. package/lib/aws/ec2/vpc.d.ts.map +1 -1
  52. package/lib/aws/ec2/vpc.js +50 -2
  53. package/lib/aws/ec2/vpc.js.map +1 -1
  54. package/lib/aws/index.d.ts +2 -0
  55. package/lib/aws/index.d.ts.map +1 -1
  56. package/lib/aws/index.js +2 -0
  57. package/lib/aws/index.js.map +1 -1
  58. package/lib/cloudflare/api-response.js +2 -2
  59. package/lib/cloudflare/api-response.js.map +1 -1
  60. package/lib/cloudflare/api.d.ts +19 -0
  61. package/lib/cloudflare/api.d.ts.map +1 -1
  62. package/lib/cloudflare/api.js +4 -0
  63. package/lib/cloudflare/api.js.map +1 -1
  64. package/lib/cloudflare/assets.d.ts.map +1 -1
  65. package/lib/cloudflare/assets.js +3 -4
  66. package/lib/cloudflare/assets.js.map +1 -1
  67. package/lib/cloudflare/bucket.d.ts +5 -3
  68. package/lib/cloudflare/bucket.d.ts.map +1 -1
  69. package/lib/cloudflare/bucket.js +22 -18
  70. package/lib/cloudflare/bucket.js.map +1 -1
  71. package/lib/cloudflare/bundle/plugin-compat-warning.js +7 -7
  72. package/lib/cloudflare/bundle/plugin-compat-warning.js.map +1 -1
  73. package/lib/cloudflare/cloudflare-env-proxy.js.map +1 -1
  74. package/lib/cloudflare/kv-namespace.d.ts +2 -2
  75. package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
  76. package/lib/cloudflare/kv-namespace.js.map +1 -1
  77. package/lib/cloudflare/oauth.js +3 -3
  78. package/lib/cloudflare/oauth.js.map +1 -1
  79. package/lib/cloudflare/quick-tunnel.d.ts +1 -1
  80. package/lib/cloudflare/website.d.ts.map +1 -1
  81. package/lib/cloudflare/website.js +26 -97
  82. package/lib/cloudflare/website.js.map +1 -1
  83. package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
  84. package/lib/cloudflare/worker-bundle.js +9 -8
  85. package/lib/cloudflare/worker-bundle.js.map +1 -1
  86. package/lib/cloudflare/worker-tail.d.ts.map +1 -1
  87. package/lib/cloudflare/worker-tail.js +6 -6
  88. package/lib/cloudflare/worker-tail.js.map +1 -1
  89. package/lib/resource.d.ts +1 -0
  90. package/lib/resource.d.ts.map +1 -1
  91. package/lib/resource.js +13 -2
  92. package/lib/resource.js.map +1 -1
  93. package/lib/scope.d.ts +24 -23
  94. package/lib/scope.d.ts.map +1 -1
  95. package/lib/scope.js +25 -20
  96. package/lib/scope.js.map +1 -1
  97. package/lib/state/cloudflare-state-store.d.ts.map +1 -1
  98. package/lib/state/cloudflare-state-store.js +2 -1
  99. package/lib/state/cloudflare-state-store.js.map +1 -1
  100. package/lib/util/idempotent-spawn.d.ts +10 -8
  101. package/lib/util/idempotent-spawn.d.ts.map +1 -1
  102. package/lib/util/idempotent-spawn.js +97 -78
  103. package/lib/util/idempotent-spawn.js.map +1 -1
  104. package/lib/util/index.d.ts +2 -0
  105. package/lib/util/index.d.ts.map +1 -0
  106. package/lib/util/index.js +2 -0
  107. package/lib/util/index.js.map +1 -0
  108. package/lib/util/safe-fetch.d.ts +24 -0
  109. package/lib/util/safe-fetch.d.ts.map +1 -1
  110. package/lib/util/safe-fetch.js +72 -0
  111. package/lib/util/safe-fetch.js.map +1 -1
  112. package/package.json +8 -5
  113. package/src/alchemy.ts +2 -2
  114. package/src/aws/client-props.ts +156 -0
  115. package/src/aws/credentials.ts +165 -4
  116. package/src/aws/ec2/internet-gateway-attachment.ts +59 -4
  117. package/src/aws/ec2/internet-gateway.ts +70 -41
  118. package/src/aws/ec2/nat-gateway.ts +123 -33
  119. package/src/aws/ec2/route-table-association.ts +1 -1
  120. package/src/aws/ec2/route-table.ts +66 -2
  121. package/src/aws/ec2/route.ts +62 -2
  122. package/src/aws/ec2/security-group.ts +98 -4
  123. package/src/aws/ec2/subnet.ts +63 -4
  124. package/src/aws/ec2/utils.ts +73 -7
  125. package/src/aws/ec2/vpc.ts +52 -3
  126. package/src/aws/index.ts +2 -0
  127. package/src/cloudflare/api-response.ts +2 -2
  128. package/src/cloudflare/api.ts +23 -0
  129. package/src/cloudflare/assets.ts +3 -4
  130. package/src/cloudflare/bucket.ts +27 -25
  131. package/src/cloudflare/bundle/plugin-compat-warning.ts +7 -7
  132. package/src/cloudflare/cloudflare-env-proxy.ts +2 -2
  133. package/src/cloudflare/kv-namespace.ts +26 -27
  134. package/src/cloudflare/oauth.ts +3 -3
  135. package/src/cloudflare/website.ts +30 -111
  136. package/src/cloudflare/worker-bundle.ts +9 -8
  137. package/src/cloudflare/worker-tail.ts +6 -8
  138. package/src/resource.ts +19 -2
  139. package/src/scope.ts +73 -43
  140. package/src/state/cloudflare-state-store.ts +2 -1
  141. package/src/util/idempotent-spawn.ts +117 -100
  142. package/src/util/index.ts +1 -0
  143. package/src/util/safe-fetch.ts +114 -0
@@ -1,6 +1,167 @@
1
- import type { Secret } from "../secret.ts";
1
+ import { alchemy } from "../alchemy.ts";
2
+ import { isSecret } from "../secret.ts";
3
+ import type { AwsClientProps } from "./client-props.ts";
2
4
 
3
- export interface AwsCredentials {
4
- accessKeyId: Secret;
5
- secretAccessKey: Secret;
5
+ /**
6
+ * Validate AWS client properties to ensure they are strings.
7
+ * This follows the same pattern as Cloudflare credential validation.
8
+ */
9
+ function validateAwsClientProps(props: AwsClientProps, context: string): void {
10
+ const validKeys = [
11
+ "accessKeyId",
12
+ "secretAccessKey",
13
+ "sessionToken",
14
+ "region",
15
+ "profile",
16
+ "roleArn",
17
+ "externalId",
18
+ "roleSessionName",
19
+ ];
20
+
21
+ for (const [key, value] of Object.entries(props)) {
22
+ if (!validKeys.includes(key)) {
23
+ continue; // Ignore unknown properties
24
+ }
25
+
26
+ if (value !== undefined && typeof value !== "string" && !isSecret(value)) {
27
+ throw new Error(
28
+ `Invalid AWS configuration in ${context}: Property '${key}' must be a string or Secret, got ${typeof value}. ` +
29
+ "Please ensure all AWS credential properties are strings or Secret objects.",
30
+ );
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Get global AWS configuration from environment variables.
37
+ * This provides the base layer of AWS credential configuration.
38
+ */
39
+ export function getGlobalAwsConfig(): AwsClientProps {
40
+ return {
41
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID
42
+ ? alchemy.secret(process.env.AWS_ACCESS_KEY_ID)
43
+ : undefined,
44
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
45
+ ? alchemy.secret(process.env.AWS_SECRET_ACCESS_KEY)
46
+ : undefined,
47
+ sessionToken: process.env.AWS_SESSION_TOKEN
48
+ ? alchemy.secret(process.env.AWS_SESSION_TOKEN)
49
+ : undefined,
50
+ region: process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION,
51
+ profile: process.env.AWS_PROFILE,
52
+ roleArn: process.env.AWS_ROLE_ARN,
53
+ externalId: process.env.AWS_EXTERNAL_ID,
54
+ roleSessionName: process.env.AWS_ROLE_SESSION_NAME,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Resolve AWS credentials using three-tier resolution: global → scope → resource.
60
+ *
61
+ * This function implements a comprehensive credential resolution system that allows
62
+ * for flexible AWS credential management across different levels of your application.
63
+ * It enables multi-account and multi-region deployments by providing a consistent
64
+ * way to override credentials at different scopes.
65
+ *
66
+ * The resolution follows this precedence order:
67
+ * 1. Resource-level credentials (highest priority)
68
+ * 2. Scope-level credentials (medium priority)
69
+ * 3. Global environment variables (lowest priority)
70
+ *
71
+ * Supported credential properties include:
72
+ * - `region`: AWS region (e.g., 'us-west-2', 'eu-central-1')
73
+ * - `profile`: AWS profile name from credentials file
74
+ * - `accessKeyId`: AWS access key ID
75
+ * - `secretAccessKey`: AWS secret access key
76
+ * - `sessionToken`: AWS session token for temporary credentials
77
+ * - `roleArn`: AWS role ARN to assume
78
+ * - `roleSessionName`: Session name when assuming a role
79
+ * - `externalId`: External ID when assuming a role
80
+ *
81
+ * @param resourceProps - Resource-level AWS credential properties (optional)
82
+ * @returns Resolved AWS client properties with validation
83
+ *
84
+ * @throws {Error} When scope contains invalid AWS configuration
85
+ * @throws {Error} When resource properties contain invalid AWS configuration
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * // Basic usage with resource-level credentials
90
+ * const credentials = resolveAwsCredentials({
91
+ * region: "us-west-2",
92
+ * profile: "production"
93
+ * });
94
+ * ```
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // Usage with scope-level credentials
99
+ * await alchemy.run("my-app", {
100
+ * aws: {
101
+ * region: "eu-west-1",
102
+ * profile: "staging"
103
+ * }
104
+ * }, async () => {
105
+ * // Resources created here will use the scope credentials by default
106
+ * const vpc = await Vpc("main-vpc", {
107
+ * cidrBlock: "10.0.0.0/16"
108
+ * });
109
+ *
110
+ * // Resources can override scope credentials
111
+ * const crossRegionSubnet = await Subnet("cross-region-subnet", {
112
+ * vpc,
113
+ * cidrBlock: "10.0.1.0/24",
114
+ * region: "us-east-1" // Override scope region
115
+ * });
116
+ * });
117
+ * ```
118
+ */
119
+ export async function resolveAwsCredentials(
120
+ resourceProps?: AwsClientProps,
121
+ ): Promise<AwsClientProps> {
122
+ // 1. Start with global environment variables (lowest priority)
123
+ const globalConfig = getGlobalAwsConfig();
124
+
125
+ // 2. Layer in scope-level credentials (medium priority)
126
+ let scopeConfig: AwsClientProps = {};
127
+ try {
128
+ // Import Scope dynamically to avoid circular dependency
129
+ const { Scope } = await import("../scope.ts");
130
+ const currentScope = Scope.getScope();
131
+ if (currentScope?.providerCredentials?.aws) {
132
+ scopeConfig = currentScope.providerCredentials.aws;
133
+
134
+ // Validate scope-level credentials if provided
135
+ validateAwsClientProps(scopeConfig, "scope");
136
+ }
137
+ } catch (error) {
138
+ // If we can't access scope (e.g., not running in scope context), just continue
139
+ // with empty scope config unless it's a validation error
140
+ if (
141
+ error instanceof Error &&
142
+ error.message.includes("Invalid AWS configuration")
143
+ ) {
144
+ throw error;
145
+ }
146
+ }
147
+
148
+ // 3. Layer in resource-level credentials (highest priority)
149
+ const resourceConfig = resourceProps || {};
150
+
151
+ // Validate resource-level credentials if provided
152
+ if (resourceProps && Object.keys(resourceProps).length > 0) {
153
+ validateAwsClientProps(resourceProps, "resource properties");
154
+ }
155
+
156
+ // Merge configurations with proper precedence (later properties override earlier ones)
157
+ const resolvedConfig = {
158
+ ...globalConfig,
159
+ ...scopeConfig,
160
+ ...resourceConfig,
161
+ };
162
+
163
+ // Filter out undefined values from the final result
164
+ return Object.fromEntries(
165
+ Object.entries(resolvedConfig).filter(([_, value]) => value !== undefined),
166
+ ) as AwsClientProps;
6
167
  }
@@ -8,6 +8,7 @@ import {
8
8
  type TimeoutConfig,
9
9
  waitForResourceState,
10
10
  } from "../../util/timeout.ts";
11
+ import type { AwsClientProps } from "../client-props.ts";
11
12
  import type { InternetGateway } from "./internet-gateway.ts";
12
13
  import { callEC2Api, createEC2Client } from "./utils.ts";
13
14
  import type { Vpc } from "./vpc.ts";
@@ -15,7 +16,7 @@ import type { Vpc } from "./vpc.ts";
15
16
  /**
16
17
  * Properties for creating or updating an Internet Gateway Attachment
17
18
  */
18
- export interface InternetGatewayAttachmentProps {
19
+ export interface InternetGatewayAttachmentProps extends AwsClientProps {
19
20
  /**
20
21
  * The Internet Gateway to attach
21
22
  */
@@ -67,6 +68,9 @@ export interface InternetGatewayAttachment
67
68
  * allowing traffic to flow between the VPC and the internet when combined with proper
68
69
  * routing configuration.
69
70
  *
71
+ * Supports AWS credential overrides at the resource level, allowing you to deploy Internet Gateway Attachments
72
+ * to different AWS accounts or regions than the default scope configuration.
73
+ *
70
74
  * @example
71
75
  * // Basic Internet Gateway attachment for internet connectivity
72
76
  * const vpc = await Vpc("main-vpc", {
@@ -81,6 +85,36 @@ export interface InternetGatewayAttachment
81
85
  * });
82
86
  *
83
87
  * @example
88
+ * // Internet Gateway Attachment with AWS credential overrides
89
+ * const crossAccountAttachment = await InternetGatewayAttachment("cross-account-attachment", {
90
+ * internetGateway: igw,
91
+ * vpc: vpc,
92
+ * // Override AWS credentials for this specific resource
93
+ * region: "us-east-1",
94
+ * profile: "production-account",
95
+ * });
96
+ *
97
+ * @example
98
+ * // Internet Gateway Attachment in different region with role assumption
99
+ * const multiRegionAttachment = await InternetGatewayAttachment("multi-region-attachment", {
100
+ * internetGateway: euIgw,
101
+ * vpc: euVpc,
102
+ * region: "eu-west-1",
103
+ * roleArn: "arn:aws:iam::123456789012:role/CrossRegionRole",
104
+ * roleSessionName: "igw-attachment-deployment",
105
+ * });
106
+ *
107
+ * @example
108
+ * // Internet Gateway Attachment with explicit credentials
109
+ * const explicitCredsAttachment = await InternetGatewayAttachment("explicit-creds-attachment", {
110
+ * internetGateway: testIgw,
111
+ * vpc: testVpc,
112
+ * accessKeyId: alchemy.secret("AKIAIOSFODNN7EXAMPLE"),
113
+ * secretAccessKey: alchemy.secret("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
114
+ * region: "us-west-2",
115
+ * });
116
+ *
117
+ * @example
84
118
  * // Internet Gateway attachment with custom timeout configuration
85
119
  * // for environments with slower AWS API responses
86
120
  * const attachment = await InternetGatewayAttachment("slow-env-attachment", {
@@ -109,7 +143,7 @@ export interface InternetGatewayAttachment
109
143
  *
110
144
  * // Create public subnet and route table for internet access
111
145
  * const publicSubnet = await Subnet("public-subnet", {
112
- * vpc,
146
+ * vpc: vpc,
113
147
  * cidrBlock: "10.0.1.0/24",
114
148
  * availabilityZone: "us-east-1a"
115
149
  * });
@@ -121,7 +155,27 @@ export interface InternetGatewayAttachment
121
155
  * const internetRoute = await Route("internet-route", {
122
156
  * routeTable: publicRouteTable,
123
157
  * destinationCidrBlock: "0.0.0.0/0",
124
- * gateway: igw
158
+ * target: { internetGateway: igw }
159
+ * });
160
+ *
161
+ * @example
162
+ * // Multi-account deployment with scope-level and resource-level overrides
163
+ * await alchemy.run("production", {
164
+ * aws: { region: "us-west-2", profile: "main-account" }
165
+ * }, async () => {
166
+ * // This Internet Gateway Attachment uses scope credentials (main-account, us-west-2)
167
+ * const mainAttachment = await InternetGatewayAttachment("main-attachment", {
168
+ * internetGateway: mainIgw,
169
+ * vpc: mainVpc
170
+ * });
171
+ *
172
+ * // This Internet Gateway Attachment overrides to use different account
173
+ * const crossAccountAttachment = await InternetGatewayAttachment("cross-account-attachment", {
174
+ * internetGateway: crossIgw,
175
+ * vpc: crossVpc,
176
+ * profile: "secondary-account",
177
+ * region: "us-east-1", // Also override region
178
+ * });
125
179
  * });
126
180
  */
127
181
  export const InternetGatewayAttachment = Resource(
@@ -131,7 +185,8 @@ export const InternetGatewayAttachment = Resource(
131
185
  _id: string,
132
186
  props: InternetGatewayAttachmentProps,
133
187
  ): Promise<InternetGatewayAttachment> {
134
- const client = await createEC2Client();
188
+ // Create EC2 client with credential resolution handled internally
189
+ const client = await createEC2Client(props);
135
190
  const timeoutConfig = mergeTimeoutConfig(
136
191
  INTERNET_GATEWAY_ATTACHMENT_TIMEOUT,
137
192
  props.timeout,
@@ -9,12 +9,13 @@ import {
9
9
  type TimeoutConfig,
10
10
  waitForResourceState,
11
11
  } from "../../util/timeout.ts";
12
+ import type { AwsClientProps } from "../client-props.ts";
12
13
  import { callEC2Api, createEC2Client } from "./utils.ts";
13
14
 
14
15
  /**
15
16
  * Properties for creating or updating an Internet Gateway
16
17
  */
17
- export interface InternetGatewayProps {
18
+ export interface InternetGatewayProps extends AwsClientProps {
18
19
  /**
19
20
  * Tags to apply to the Internet Gateway
20
21
  */
@@ -145,12 +146,15 @@ async function waitForInternetGatewayDeleted(
145
146
  * 1. Provide a target in your VPC route tables for internet-routable traffic
146
147
  * 2. Perform network address translation (NAT) for instances with public IPv4 addresses
147
148
  *
149
+ * Supports AWS credential overrides at the resource level, allowing you to deploy Internet Gateways
150
+ * to different AWS accounts or regions than the default scope configuration.
151
+ *
148
152
  * @example
149
153
  * ```typescript
150
154
  * // Create a basic Internet Gateway
151
- * const igw = new InternetGateway({
155
+ * const igw = await InternetGateway("main-igw", {
152
156
  * tags: {
153
- * Name: "my-internet-gateway",
157
+ * Name: "main-internet-gateway",
154
158
  * Environment: "production"
155
159
  * }
156
160
  * });
@@ -158,59 +162,49 @@ async function waitForInternetGatewayDeleted(
158
162
  *
159
163
  * @example
160
164
  * ```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
165
+ * // Create Internet Gateway with AWS credential overrides
166
+ * const crossAccountIgw = await InternetGateway("cross-account-igw", {
167
+ * // Override AWS credentials for this specific resource
168
+ * region: "us-east-1",
169
+ * profile: "production-account",
170
+ * tags: {
171
+ * Name: "cross-account-internet-gateway",
172
+ * Environment: "production"
167
173
  * }
168
174
  * });
169
175
  * ```
170
176
  *
171
177
  * @example
172
178
  * ```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", {
179
+ * // Create Internet Gateway in different region with role assumption
180
+ * const multiRegionIgw = await InternetGateway("multi-region-igw", {
181
+ * region: "eu-west-1",
182
+ * roleArn: "arn:aws:iam::123456789012:role/CrossRegionRole",
183
+ * roleSessionName: "internet-gateway-deployment",
196
184
  * tags: {
197
- * Name: "main-internet-gateway",
198
- * Environment: "production"
185
+ * Name: "eu-internet-gateway",
186
+ * Region: "europe"
199
187
  * }
200
188
  * });
189
+ * ```
201
190
  *
202
191
  * @example
203
- * // Create an Internet Gateway for development environment
204
- * const devIgw = await InternetGateway("dev-igw", {
192
+ * ```typescript
193
+ * // Create Internet Gateway with explicit credentials
194
+ * const explicitCredsIgw = await InternetGateway("explicit-creds-igw", {
195
+ * accessKeyId: alchemy.secret("AKIAIOSFODNN7EXAMPLE"),
196
+ * secretAccessKey: alchemy.secret("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
197
+ * region: "us-west-2",
205
198
  * tags: {
206
- * Name: "dev-internet-gateway",
207
- * Environment: "development",
208
- * Team: "backend"
199
+ * Name: "explicit-credentials-igw",
200
+ * Purpose: "testing"
209
201
  * }
210
202
  * });
203
+ * ```
211
204
  *
212
205
  * @example
213
- * // Create an Internet Gateway with custom timeout configuration
206
+ * ```typescript
207
+ * // Create Internet Gateway with custom timeout configuration
214
208
  * const customIgw = await InternetGateway("custom-igw", {
215
209
  * timeout: {
216
210
  * maxAttempts: 90,
@@ -221,6 +215,40 @@ async function waitForInternetGatewayDeleted(
221
215
  * Purpose: "high-availability"
222
216
  * }
223
217
  * });
218
+ * ```
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Create Internet Gateway and attach to VPC
223
+ * const vpc = await VPC("main-vpc", { cidrBlock: "10.0.0.0/16" });
224
+ * const igw = await InternetGateway("vpc-igw", {
225
+ * tags: { Name: "vpc-internet-gateway" }
226
+ * });
227
+ * const attachment = await InternetGatewayAttachment("igw-attachment", {
228
+ * internetGatewayId: igw.internetGatewayId,
229
+ * vpcId: vpc.vpcId
230
+ * });
231
+ * ```
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * // Multi-account deployment with scope-level and resource-level overrides
236
+ * await alchemy.run("production", {
237
+ * aws: { region: "us-west-2", profile: "main-account" }
238
+ * }, async () => {
239
+ * // This IGW uses scope credentials (main-account, us-west-2)
240
+ * const mainIgw = await InternetGateway("main-igw", {
241
+ * tags: { Name: "main-account-igw" }
242
+ * });
243
+ *
244
+ * // This IGW overrides to use different account
245
+ * const crossAccountIgw = await InternetGateway("cross-account-igw", {
246
+ * profile: "secondary-account",
247
+ * region: "us-east-1", // Also override region
248
+ * tags: { Name: "secondary-account-igw" }
249
+ * });
250
+ * });
251
+ * ```
224
252
  */
225
253
  export const InternetGateway = Resource(
226
254
  "aws::InternetGateway",
@@ -229,7 +257,8 @@ export const InternetGateway = Resource(
229
257
  _id: string,
230
258
  props: InternetGatewayProps,
231
259
  ): Promise<InternetGateway> {
232
- const client = await createEC2Client();
260
+ // Create EC2 client with credential resolution handled internally
261
+ const client = await createEC2Client(props);
233
262
  const timeoutConfig = mergeTimeoutConfig(
234
263
  INTERNET_GATEWAY_TIMEOUT,
235
264
  props.timeout,