alchemy 0.54.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/lib/aws/ec2/index.d.ts +10 -0
  2. package/lib/aws/ec2/index.d.ts.map +1 -0
  3. package/lib/aws/ec2/index.js +10 -0
  4. package/lib/aws/ec2/index.js.map +1 -0
  5. package/lib/aws/ec2/internet-gateway-attachment.d.ts +150 -0
  6. package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -0
  7. package/lib/aws/ec2/internet-gateway-attachment.js +248 -0
  8. package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -0
  9. package/lib/aws/ec2/internet-gateway.d.ts +132 -0
  10. package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
  11. package/lib/aws/ec2/internet-gateway.js +311 -0
  12. package/lib/aws/ec2/internet-gateway.js.map +1 -0
  13. package/lib/aws/ec2/nat-gateway.d.ts +145 -0
  14. package/lib/aws/ec2/nat-gateway.d.ts.map +1 -0
  15. package/lib/aws/ec2/nat-gateway.js +618 -0
  16. package/lib/aws/ec2/nat-gateway.js.map +1 -0
  17. package/lib/aws/ec2/route-table-association.d.ts +134 -0
  18. package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
  19. package/lib/aws/ec2/route-table-association.js +364 -0
  20. package/lib/aws/ec2/route-table-association.js.map +1 -0
  21. package/lib/aws/ec2/route-table.d.ts +94 -0
  22. package/lib/aws/ec2/route-table.d.ts.map +1 -0
  23. package/lib/aws/ec2/route-table.js +253 -0
  24. package/lib/aws/ec2/route-table.js.map +1 -0
  25. package/lib/aws/ec2/route.d.ts +130 -0
  26. package/lib/aws/ec2/route.d.ts.map +1 -0
  27. package/lib/aws/ec2/route.js +253 -0
  28. package/lib/aws/ec2/route.js.map +1 -0
  29. package/lib/aws/ec2/security-group-rule.d.ts +84 -0
  30. package/lib/aws/ec2/security-group-rule.d.ts.map +1 -0
  31. package/lib/aws/ec2/security-group-rule.js +123 -0
  32. package/lib/aws/ec2/security-group-rule.js.map +1 -0
  33. package/lib/aws/ec2/security-group.d.ts +84 -0
  34. package/lib/aws/ec2/security-group.d.ts.map +1 -0
  35. package/lib/aws/ec2/security-group.js +207 -0
  36. package/lib/aws/ec2/security-group.js.map +1 -0
  37. package/lib/aws/ec2/subnet.d.ts +110 -0
  38. package/lib/aws/ec2/subnet.d.ts.map +1 -0
  39. package/lib/aws/ec2/subnet.js +336 -0
  40. package/lib/aws/ec2/subnet.js.map +1 -0
  41. package/lib/aws/ec2/utils.d.ts +15 -0
  42. package/lib/aws/ec2/utils.d.ts.map +1 -0
  43. package/lib/aws/ec2/utils.js +79 -0
  44. package/lib/aws/ec2/utils.js.map +1 -0
  45. package/lib/aws/ec2/vpc.d.ts +160 -0
  46. package/lib/aws/ec2/vpc.d.ts.map +1 -0
  47. package/lib/aws/ec2/vpc.js +453 -0
  48. package/lib/aws/ec2/vpc.js.map +1 -0
  49. package/lib/aws/index.d.ts +7 -0
  50. package/lib/aws/index.d.ts.map +1 -1
  51. package/lib/aws/index.js +8 -0
  52. package/lib/aws/index.js.map +1 -1
  53. package/lib/aws/utils.d.ts +25 -0
  54. package/lib/aws/utils.d.ts.map +1 -0
  55. package/lib/aws/utils.js +89 -0
  56. package/lib/aws/utils.js.map +1 -0
  57. package/lib/build-date.d.ts +6 -0
  58. package/lib/build-date.d.ts.map +1 -0
  59. package/lib/build-date.js +8 -0
  60. package/lib/build-date.js.map +1 -0
  61. package/lib/util/params.d.ts +5 -0
  62. package/lib/util/params.d.ts.map +1 -0
  63. package/lib/util/params.js +30 -0
  64. package/lib/util/params.js.map +1 -0
  65. package/lib/util/timeout.d.ts +31 -0
  66. package/lib/util/timeout.d.ts.map +1 -0
  67. package/lib/util/timeout.js +109 -0
  68. package/lib/util/timeout.js.map +1 -0
  69. package/lib/util/xml.d.ts +5 -0
  70. package/lib/util/xml.d.ts.map +1 -0
  71. package/lib/util/xml.js +8 -0
  72. package/lib/util/xml.js.map +1 -0
  73. package/package.json +3 -1
  74. package/src/aws/ec2/index.ts +9 -0
  75. package/src/aws/ec2/internet-gateway-attachment.ts +468 -0
  76. package/src/aws/ec2/internet-gateway.ts +557 -0
  77. package/src/aws/ec2/nat-gateway.ts +1123 -0
  78. package/src/aws/ec2/route-table-association.ts +747 -0
  79. package/src/aws/ec2/route-table.ts +452 -0
  80. package/src/aws/ec2/route.ts +447 -0
  81. package/src/aws/ec2/security-group-rule.ts +229 -0
  82. package/src/aws/ec2/security-group.ts +418 -0
  83. package/src/aws/ec2/subnet.ts +625 -0
  84. package/src/aws/ec2/utils.ts +102 -0
  85. package/src/aws/ec2/vpc.ts +969 -0
  86. package/src/aws/index.ts +9 -0
  87. package/src/aws/utils.ts +137 -0
  88. package/src/build-date.ts +8 -0
  89. package/src/util/params.ts +33 -0
  90. package/src/util/timeout.ts +178 -0
  91. package/src/util/xml.ts +7 -0
package/src/aws/index.ts CHANGED
@@ -9,3 +9,12 @@ export * from "./s3-state-store.ts";
9
9
  export * from "./ses.ts";
10
10
  export * from "./ssm-parameter.ts";
11
11
  export * from "./table.ts";
12
+
13
+ // EC2 Resources
14
+ export * from "./ec2/internet-gateway.ts";
15
+ export * from "./ec2/nat-gateway.ts";
16
+ export * from "./ec2/route-table.ts";
17
+ export * from "./ec2/route.ts";
18
+ export * from "./ec2/security-group.ts";
19
+ export * from "./ec2/subnet.ts";
20
+ export * from "./ec2/vpc.ts";
@@ -0,0 +1,137 @@
1
+ import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
2
+ import { loadConfig } from "@smithy/node-config-provider";
3
+ import { AwsClient } from "aws4fetch";
4
+ import { flattenParams } from "../util/params.ts";
5
+
6
+ /**
7
+ * Get AWS region from configuration
8
+ */
9
+ export const getRegion = loadConfig({
10
+ environmentVariableSelector: (env: any) =>
11
+ env.AWS_REGION || env.AWS_DEFAULT_REGION,
12
+ configFileSelector: (profile: any) => profile.region,
13
+ default: "us-east-1",
14
+ });
15
+
16
+ /**
17
+ * AWS Service Configuration
18
+ */
19
+ export interface AwsServiceConfig {
20
+ service: string;
21
+ version: string;
22
+ endpoint: (region: string) => string;
23
+ }
24
+
25
+ /**
26
+ * AWS API Caller interface
27
+ */
28
+ export interface AwsApiCaller<T = any> {
29
+ createClient(): Promise<AwsClient>;
30
+ callApi<R = T>(
31
+ client: AwsClient,
32
+ action: string,
33
+ params?: Record<string, any>,
34
+ ): Promise<R>;
35
+ }
36
+
37
+ /**
38
+ * Create an AWS API caller for a specific service
39
+ */
40
+ export function getAwsApiCaller<T = any>(
41
+ config: AwsServiceConfig,
42
+ responseParser: (xmlText: string) => T,
43
+ ): AwsApiCaller<T> {
44
+ return {
45
+ async createClient(): Promise<AwsClient> {
46
+ const credentials = await fromNodeProviderChain()();
47
+ const region = await getRegion();
48
+
49
+ return new AwsClient({
50
+ ...credentials,
51
+ service: config.service,
52
+ region,
53
+ });
54
+ },
55
+
56
+ async callApi<R = T>(
57
+ client: AwsClient,
58
+ action: string,
59
+ params: Record<string, any> = {},
60
+ ): Promise<R> {
61
+ // Try the API call, and retry once with fresh credentials on auth failure
62
+ for (let attempt = 1; attempt <= 2; attempt++) {
63
+ try {
64
+ const region = await getRegion();
65
+ const url = config.endpoint(region);
66
+
67
+ const body = new URLSearchParams({
68
+ Action: action,
69
+ Version: config.version,
70
+ ...flattenParams(params),
71
+ });
72
+
73
+ const signedRequest = await client.sign(url, {
74
+ method: "POST",
75
+ headers: {
76
+ "Content-Type": "application/x-www-form-urlencoded",
77
+ },
78
+ body: body.toString(),
79
+ });
80
+
81
+ const response = await fetch(signedRequest);
82
+
83
+ if (!response.ok) {
84
+ const errorText = await response.text();
85
+
86
+ // Parse AWS error code from XML response
87
+ const errorCodeMatch = errorText.match(/<Code>([^<]+)<\/Code>/);
88
+ const errorCode = errorCodeMatch ? errorCodeMatch[1] : null;
89
+
90
+ // If this is an auth failure and we haven't retried yet, create a fresh client and retry
91
+ if (errorCode === "AuthFailure" && attempt === 1) {
92
+ console.log(
93
+ `🔄 Auth failure detected, refreshing credentials and retrying ${action}...`,
94
+ );
95
+ // Create a fresh client with new credentials
96
+ const freshCredentials = await fromNodeProviderChain()();
97
+ const region = await getRegion();
98
+ client = new AwsClient({
99
+ ...freshCredentials,
100
+ service: config.service,
101
+ region,
102
+ });
103
+ continue; // Retry with fresh client
104
+ }
105
+
106
+ const error = new Error(
107
+ `${config.service.toUpperCase()} API error: ${response.status} ${response.statusText}\n${errorText}`,
108
+ );
109
+
110
+ // Set the error code for the ignore function
111
+ if (errorCode) {
112
+ (error as any).code = errorCode;
113
+ }
114
+
115
+ throw error;
116
+ }
117
+
118
+ const xmlText = await response.text();
119
+ const parsed = responseParser(xmlText);
120
+ return parsed as unknown as R;
121
+ } catch (error) {
122
+ // If it's not an auth failure or we've already retried, throw the error
123
+ if (
124
+ attempt === 2 ||
125
+ !(error as any)?.message?.includes("AuthFailure")
126
+ ) {
127
+ throw error;
128
+ }
129
+ // Otherwise, continue to retry
130
+ }
131
+ }
132
+
133
+ // This should never be reached, but TypeScript needs it
134
+ throw new Error("Unexpected error in API call retry logic");
135
+ },
136
+ };
137
+ }
@@ -0,0 +1,8 @@
1
+ // This file is auto-generated during build
2
+ // Do not edit manually
3
+
4
+ /**
5
+ * The build date used as the default worker compatibility date.
6
+ * This is set to the date when the package was built.
7
+ */
8
+ export const BUILD_DATE = "2025-07-13";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Flatten nested parameters for API calls
3
+ */
4
+ export function flattenParams(
5
+ params: Record<string, any>,
6
+ prefix = "",
7
+ ): Record<string, string> {
8
+ const result: Record<string, string> = {};
9
+
10
+ for (const [key, value] of Object.entries(params)) {
11
+ const fullKey = prefix ? `${prefix}.${key}` : key;
12
+
13
+ if (value === null || value === undefined) {
14
+ continue;
15
+ }
16
+
17
+ if (Array.isArray(value)) {
18
+ value.forEach((item, index) => {
19
+ if (typeof item === "object") {
20
+ Object.assign(result, flattenParams(item, `${fullKey}.${index + 1}`));
21
+ } else {
22
+ result[`${fullKey}.${index + 1}`] = String(item);
23
+ }
24
+ });
25
+ } else if (typeof value === "object") {
26
+ Object.assign(result, flattenParams(value, fullKey));
27
+ } else {
28
+ result[fullKey] = String(value);
29
+ }
30
+ }
31
+
32
+ return result;
33
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Timeout configuration interface
3
+ */
4
+ export interface TimeoutConfig {
5
+ maxAttempts: number;
6
+ delayMs: number;
7
+ }
8
+
9
+ /**
10
+ * Resource timeout error class
11
+ */
12
+ export class ResourceTimeoutError extends Error {
13
+ constructor(
14
+ resourceType: string,
15
+ resourceId: string,
16
+ timeoutMs: number,
17
+ operation: string,
18
+ ) {
19
+ super(
20
+ `${resourceType} ${resourceId} did not complete ${operation} within ${timeoutMs}ms`,
21
+ );
22
+ this.name = "ResourceTimeoutError";
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Validate timeout configuration
28
+ */
29
+ export function validateTimeoutConfig(config: TimeoutConfig): void {
30
+ if (config.maxAttempts <= 0) {
31
+ throw new Error("maxAttempts must be greater than 0");
32
+ }
33
+ if (config.delayMs <= 0) {
34
+ throw new Error("delayMs must be greater than 0");
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Merge default timeout configuration with optional overrides
40
+ */
41
+ export function mergeTimeoutConfig(
42
+ defaultConfig: TimeoutConfig,
43
+ override?: Partial<TimeoutConfig>,
44
+ ): TimeoutConfig {
45
+ if (!override) {
46
+ return defaultConfig;
47
+ }
48
+
49
+ const merged = {
50
+ maxAttempts: override.maxAttempts ?? defaultConfig.maxAttempts,
51
+ delayMs: override.delayMs ?? defaultConfig.delayMs,
52
+ };
53
+
54
+ validateTimeoutConfig(merged);
55
+ return merged;
56
+ }
57
+
58
+ /**
59
+ * Wait for a resource to reach a desired state with configurable timeout
60
+ */
61
+ export async function waitForResourceState<T>(
62
+ checkFunction: () => Promise<T>,
63
+ isReady: (result: T) => boolean,
64
+ config: TimeoutConfig,
65
+ resourceId: string,
66
+ resourceType: string,
67
+ operation = "become ready",
68
+ ): Promise<void> {
69
+ validateTimeoutConfig(config);
70
+ const { maxAttempts, delayMs } = config;
71
+
72
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
73
+ try {
74
+ const result = await checkFunction();
75
+ if (isReady(result)) {
76
+ return;
77
+ }
78
+
79
+ console.log(
80
+ `${resourceType} ${resourceId} not ready, waiting... (attempt ${attempt}/${maxAttempts})`,
81
+ );
82
+
83
+ if (attempt < maxAttempts) {
84
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
85
+ }
86
+ } catch (error) {
87
+ console.log(
88
+ `Error checking ${resourceType} status (attempt ${attempt}/${maxAttempts}):`,
89
+ error,
90
+ );
91
+
92
+ // Check if this is a non-retryable error (contains "NonRetryableError" in the name)
93
+ if (error instanceof Error && error.name.includes("NonRetryableError")) {
94
+ throw error;
95
+ }
96
+
97
+ if (attempt === maxAttempts) {
98
+ throw error;
99
+ }
100
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
101
+ }
102
+ }
103
+
104
+ const totalTimeMs = maxAttempts * delayMs;
105
+ throw new ResourceTimeoutError(
106
+ resourceType,
107
+ resourceId,
108
+ totalTimeMs,
109
+ operation,
110
+ );
111
+ }
112
+ /**
113
+ * Generic function to wait for an operation to complete
114
+ * This is the most flexible version that can handle any type of operation
115
+ */
116
+ export async function waitForOperation<T>(
117
+ checkFunction: () => Promise<T>,
118
+ isComplete: (result: T) => boolean,
119
+ config: TimeoutConfig,
120
+ resourceId: string,
121
+ resourceType: string,
122
+ operation = "complete",
123
+ onError?: (error: any, attempt: number, maxAttempts: number) => boolean, // Return true to continue retrying
124
+ ): Promise<void> {
125
+ validateTimeoutConfig(config);
126
+ const { maxAttempts, delayMs } = config;
127
+
128
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
129
+ try {
130
+ const result = await checkFunction();
131
+
132
+ if (isComplete(result)) {
133
+ console.log(`${resourceType} ${resourceId} ${operation} completed`);
134
+ return;
135
+ }
136
+
137
+ console.log(
138
+ `${resourceType} ${resourceId} ${operation} in progress... (attempt ${attempt}/${maxAttempts})`,
139
+ );
140
+
141
+ if (attempt < maxAttempts) {
142
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
143
+ }
144
+ } catch (error) {
145
+ // Allow custom error handling
146
+ if (onError) {
147
+ const shouldContinue = onError(error, attempt, maxAttempts);
148
+ if (!shouldContinue) {
149
+ // If onError returns false, it means the operation completed successfully
150
+ // (e.g., resource was deleted and not found)
151
+ console.log(
152
+ `${resourceType} ${resourceId} ${operation} completed (via error handling)`,
153
+ );
154
+ return;
155
+ }
156
+ } else {
157
+ console.log(
158
+ `Error checking ${resourceType} ${operation} status (attempt ${attempt}/${maxAttempts}):`,
159
+ error,
160
+ );
161
+ }
162
+
163
+ if (attempt === maxAttempts) {
164
+ throw error;
165
+ }
166
+
167
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
168
+ }
169
+ }
170
+
171
+ const totalTimeMs = maxAttempts * delayMs;
172
+ throw new ResourceTimeoutError(
173
+ resourceType,
174
+ resourceId,
175
+ totalTimeMs,
176
+ operation,
177
+ );
178
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Extract value from XML string
3
+ */
4
+ export function extractXmlValue(xml: string, tagName: string): string {
5
+ const match = xml.match(new RegExp(`<${tagName}>(.*?)<\/${tagName}>`));
6
+ return match ? match[1] : "";
7
+ }