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.
- package/README.md +1 -2
- package/bin/alchemy.js +1406 -1464
- package/bin/commands/init.ts +29 -2
- package/bin/services/execute-alchemy.ts +1 -2
- package/lib/alchemy.d.ts +2 -2
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js.map +1 -1
- package/lib/aws/client-props.d.ts +149 -0
- package/lib/aws/client-props.d.ts.map +1 -0
- package/lib/aws/client-props.js +1 -0
- package/lib/aws/client-props.js.map +1 -0
- package/lib/aws/credentials.d.ts +68 -5
- package/lib/aws/credentials.d.ts.map +1 -1
- package/lib/aws/credentials.js +148 -0
- package/lib/aws/credentials.js.map +1 -1
- package/lib/aws/ec2/internet-gateway-attachment.d.ts +57 -3
- package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -1
- package/lib/aws/ec2/internet-gateway-attachment.js +57 -3
- package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -1
- package/lib/aws/ec2/internet-gateway.d.ts +68 -40
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -1
- package/lib/aws/ec2/internet-gateway.js +68 -40
- package/lib/aws/ec2/internet-gateway.js.map +1 -1
- package/lib/aws/ec2/nat-gateway.d.ts +99 -18
- package/lib/aws/ec2/nat-gateway.d.ts.map +1 -1
- package/lib/aws/ec2/nat-gateway.js +113 -37
- package/lib/aws/ec2/nat-gateway.js.map +1 -1
- package/lib/aws/ec2/route-table-association.d.ts +1 -1
- package/lib/aws/ec2/route-table-association.js +1 -1
- package/lib/aws/ec2/route-table.d.ts +64 -1
- package/lib/aws/ec2/route-table.d.ts.map +1 -1
- package/lib/aws/ec2/route-table.js +64 -1
- package/lib/aws/ec2/route-table.js.map +1 -1
- package/lib/aws/ec2/route.d.ts +60 -1
- package/lib/aws/ec2/route.d.ts.map +1 -1
- package/lib/aws/ec2/route.js +60 -1
- package/lib/aws/ec2/route.js.map +1 -1
- package/lib/aws/ec2/security-group.d.ts +96 -3
- package/lib/aws/ec2/security-group.d.ts.map +1 -1
- package/lib/aws/ec2/security-group.js +96 -3
- package/lib/aws/ec2/security-group.js.map +1 -1
- package/lib/aws/ec2/subnet.d.ts +61 -3
- package/lib/aws/ec2/subnet.d.ts.map +1 -1
- package/lib/aws/ec2/subnet.js +61 -3
- package/lib/aws/ec2/subnet.js.map +1 -1
- package/lib/aws/ec2/utils.d.ts +10 -2
- package/lib/aws/ec2/utils.d.ts.map +1 -1
- package/lib/aws/ec2/utils.js +68 -7
- package/lib/aws/ec2/utils.js.map +1 -1
- package/lib/aws/ec2/vpc.d.ts +50 -2
- package/lib/aws/ec2/vpc.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.js +50 -2
- package/lib/aws/ec2/vpc.js.map +1 -1
- package/lib/aws/index.d.ts +2 -0
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +2 -0
- package/lib/aws/index.js.map +1 -1
- package/lib/cloudflare/api-response.js +2 -2
- package/lib/cloudflare/api-response.js.map +1 -1
- package/lib/cloudflare/api.d.ts +19 -0
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +4 -0
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/assets.d.ts.map +1 -1
- package/lib/cloudflare/assets.js +3 -4
- package/lib/cloudflare/assets.js.map +1 -1
- package/lib/cloudflare/bucket.d.ts +5 -3
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +22 -18
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-compat-warning.js +7 -7
- package/lib/cloudflare/bundle/plugin-compat-warning.js.map +1 -1
- package/lib/cloudflare/cloudflare-env-proxy.js.map +1 -1
- package/lib/cloudflare/kv-namespace.d.ts +2 -2
- package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
- package/lib/cloudflare/kv-namespace.js.map +1 -1
- package/lib/cloudflare/oauth.js +3 -3
- package/lib/cloudflare/oauth.js.map +1 -1
- package/lib/cloudflare/quick-tunnel.d.ts +1 -1
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +26 -97
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
- package/lib/cloudflare/worker-bundle.js +9 -8
- package/lib/cloudflare/worker-bundle.js.map +1 -1
- package/lib/cloudflare/worker-tail.d.ts.map +1 -1
- package/lib/cloudflare/worker-tail.js +6 -6
- package/lib/cloudflare/worker-tail.js.map +1 -1
- package/lib/resource.d.ts +1 -0
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js +13 -2
- package/lib/resource.js.map +1 -1
- package/lib/scope.d.ts +24 -23
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +25 -20
- package/lib/scope.js.map +1 -1
- package/lib/state/cloudflare-state-store.d.ts.map +1 -1
- package/lib/state/cloudflare-state-store.js +2 -1
- package/lib/state/cloudflare-state-store.js.map +1 -1
- package/lib/util/idempotent-spawn.d.ts +10 -8
- package/lib/util/idempotent-spawn.d.ts.map +1 -1
- package/lib/util/idempotent-spawn.js +97 -78
- package/lib/util/idempotent-spawn.js.map +1 -1
- package/lib/util/index.d.ts +2 -0
- package/lib/util/index.d.ts.map +1 -0
- package/lib/util/index.js +2 -0
- package/lib/util/index.js.map +1 -0
- package/lib/util/safe-fetch.d.ts +24 -0
- package/lib/util/safe-fetch.d.ts.map +1 -1
- package/lib/util/safe-fetch.js +72 -0
- package/lib/util/safe-fetch.js.map +1 -1
- package/package.json +8 -5
- package/src/alchemy.ts +2 -2
- package/src/aws/client-props.ts +156 -0
- package/src/aws/credentials.ts +165 -4
- package/src/aws/ec2/internet-gateway-attachment.ts +59 -4
- package/src/aws/ec2/internet-gateway.ts +70 -41
- package/src/aws/ec2/nat-gateway.ts +123 -33
- package/src/aws/ec2/route-table-association.ts +1 -1
- package/src/aws/ec2/route-table.ts +66 -2
- package/src/aws/ec2/route.ts +62 -2
- package/src/aws/ec2/security-group.ts +98 -4
- package/src/aws/ec2/subnet.ts +63 -4
- package/src/aws/ec2/utils.ts +73 -7
- package/src/aws/ec2/vpc.ts +52 -3
- package/src/aws/index.ts +2 -0
- package/src/cloudflare/api-response.ts +2 -2
- package/src/cloudflare/api.ts +23 -0
- package/src/cloudflare/assets.ts +3 -4
- package/src/cloudflare/bucket.ts +27 -25
- package/src/cloudflare/bundle/plugin-compat-warning.ts +7 -7
- package/src/cloudflare/cloudflare-env-proxy.ts +2 -2
- package/src/cloudflare/kv-namespace.ts +26 -27
- package/src/cloudflare/oauth.ts +3 -3
- package/src/cloudflare/website.ts +30 -111
- package/src/cloudflare/worker-bundle.ts +9 -8
- package/src/cloudflare/worker-tail.ts +6 -8
- package/src/resource.ts +19 -2
- package/src/scope.ts +73 -43
- package/src/state/cloudflare-state-store.ts +2 -1
- package/src/util/idempotent-spawn.ts +117 -100
- package/src/util/index.ts +1 -0
- package/src/util/safe-fetch.ts +114 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import find from "find-process";
|
|
2
1
|
import { spawn } from "node:child_process";
|
|
3
2
|
import fs from "node:fs";
|
|
4
3
|
import fsp from "node:fs/promises";
|
|
5
4
|
import path from "node:path";
|
|
5
|
+
import { AsyncMutex } from "./mutex.js";
|
|
6
6
|
/**
|
|
7
7
|
* Idempotently ensure a long-lived child is running with stdout/stderr -> files,
|
|
8
8
|
* and mirror those logs to THIS process's console with persisted offsets.
|
|
9
9
|
*
|
|
10
10
|
* Use: await ensureLoggedChildAndMirror({ cmd: "vite dev" })
|
|
11
11
|
*/
|
|
12
|
-
export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", overlapBytes = 0, resume = false, log = "log.txt", processName, extract, isSameProcess, quiet = false, }) {
|
|
12
|
+
export async function idempotentSpawn({ cmd, cwd, env, stateFile = "state.json", overlapBytes = 0, resume = false, log = "log.txt", processName, extract, isSameProcess, quiet = false, }) {
|
|
13
13
|
if (!processName && !isSameProcess) {
|
|
14
|
-
|
|
14
|
+
processName = cmd.split(" ")[0];
|
|
15
15
|
}
|
|
16
16
|
const outPath = log;
|
|
17
17
|
await Promise.all([
|
|
@@ -20,10 +20,18 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
20
20
|
]);
|
|
21
21
|
const { promise: extracted, resolve: resolveExtracted } = Promise.withResolvers();
|
|
22
22
|
if (!extract) {
|
|
23
|
-
console.warn("No extract function provided, will not return a value. This is probably a bug.");
|
|
24
23
|
resolveExtracted(undefined);
|
|
25
24
|
}
|
|
26
|
-
|
|
25
|
+
await ensureChildRunning();
|
|
26
|
+
const write = quiet
|
|
27
|
+
? () => false
|
|
28
|
+
: (buf) => process.stdout.write(buf);
|
|
29
|
+
// Start followers (stdout/stderr) and mirror to this process
|
|
30
|
+
await followFilePersisted(outPath, {
|
|
31
|
+
stateKey: `${path.resolve(outPath)}::stdout`,
|
|
32
|
+
write,
|
|
33
|
+
});
|
|
34
|
+
return extracted;
|
|
27
35
|
function isPidAlive(pid) {
|
|
28
36
|
if (!pid || Number.isNaN(pid))
|
|
29
37
|
return false;
|
|
@@ -56,7 +64,7 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
56
64
|
shell: true,
|
|
57
65
|
cwd,
|
|
58
66
|
stdio: ["ignore", out.fd, out.fd], // stdout/stderr -> files (OS-level)
|
|
59
|
-
env
|
|
67
|
+
env,
|
|
60
68
|
detached: false,
|
|
61
69
|
});
|
|
62
70
|
// Child now owns dup'd fds; close our handles.
|
|
@@ -76,12 +84,15 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
76
84
|
if (await isSameProcess?.(pid))
|
|
77
85
|
return pid;
|
|
78
86
|
if (processName) {
|
|
87
|
+
const { default: find } = await import("find-process");
|
|
79
88
|
const processes = await find("pid", pid);
|
|
80
89
|
if (processes.length > 1) {
|
|
81
90
|
console.warn(`Found multiple processes with PID ${pid}, using the first one`);
|
|
82
91
|
}
|
|
83
92
|
if (processes.length > 0) {
|
|
84
|
-
|
|
93
|
+
if (processes[0].name.startsWith(processName)) {
|
|
94
|
+
return pid;
|
|
95
|
+
}
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
98
|
}
|
|
@@ -93,7 +104,9 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
93
104
|
return (await spawnLoggedChild()).pid;
|
|
94
105
|
}
|
|
95
106
|
// Follow a file from persisted offset and mirror to a sink (stdout/stderr)
|
|
96
|
-
async function followFilePersisted(logPath, { write
|
|
107
|
+
async function followFilePersisted(logPath, { write, chunkSize = 64 * 1024,
|
|
108
|
+
// tickMs = 100,
|
|
109
|
+
}) {
|
|
97
110
|
logPath = path.resolve(logPath);
|
|
98
111
|
let state = (await readJson(stateFile)) ?? {};
|
|
99
112
|
let fh = await fsp.open(logPath, "r");
|
|
@@ -108,62 +121,21 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
108
121
|
? Math.max(0, Math.min(st.size, state.offset - overlapBytes))
|
|
109
122
|
: st.size;
|
|
110
123
|
let closed = false;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
async function drain() {
|
|
129
|
-
while (true) {
|
|
130
|
-
const cur = await fh.stat().catch(() => null);
|
|
131
|
-
if (!cur)
|
|
132
|
-
break;
|
|
133
|
-
if (cur.size < offset)
|
|
134
|
-
offset = 0; // truncated
|
|
135
|
-
if (offset > 0 && extract) {
|
|
136
|
-
// read from start to offset
|
|
137
|
-
const fullBuffer = Buffer.allocUnsafe(offset);
|
|
138
|
-
await fh.read({
|
|
139
|
-
position: 0,
|
|
140
|
-
buffer: fullBuffer,
|
|
141
|
-
length: offset,
|
|
142
|
-
});
|
|
143
|
-
const content = fullBuffer.toString("utf8");
|
|
144
|
-
const lines = content.split("\n");
|
|
145
|
-
for (const line of lines) {
|
|
146
|
-
const extracted = extract(line);
|
|
147
|
-
if (extracted) {
|
|
148
|
-
resolveExtracted(extracted);
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
const toRead = Math.min(chunkSize, cur.size - offset);
|
|
154
|
-
if (toRead <= 0)
|
|
155
|
-
break;
|
|
156
|
-
const { bytesRead, buffer } = await fh.read({
|
|
157
|
-
position: offset,
|
|
158
|
-
buffer: Buffer.allocUnsafe(toRead),
|
|
159
|
-
length: toRead,
|
|
160
|
-
});
|
|
161
|
-
if (!bytesRead)
|
|
162
|
-
break;
|
|
163
|
-
offset += bytesRead;
|
|
164
|
-
write(buffer.subarray(0, bytesRead));
|
|
165
|
-
}
|
|
166
|
-
await persist();
|
|
124
|
+
const drainMutex = new AsyncMutex();
|
|
125
|
+
// we read the log file and stream in chunks, not lines
|
|
126
|
+
// so we need to keep track of the remainder of the last line
|
|
127
|
+
let remainder;
|
|
128
|
+
// if we are resuming, then re-parse the log lines to extract the value
|
|
129
|
+
if (offset > 0) {
|
|
130
|
+
// read from start to offset
|
|
131
|
+
const fullBuffer = Buffer.allocUnsafe(offset);
|
|
132
|
+
await fh.read({
|
|
133
|
+
position: 0,
|
|
134
|
+
buffer: fullBuffer,
|
|
135
|
+
length: offset,
|
|
136
|
+
});
|
|
137
|
+
const content = fullBuffer.toString("utf8");
|
|
138
|
+
parse(content);
|
|
167
139
|
}
|
|
168
140
|
await drain();
|
|
169
141
|
const watcher = fs.watch(logPath, async () => {
|
|
@@ -199,20 +171,67 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
199
171
|
await fh.close().catch(() => { });
|
|
200
172
|
await persist();
|
|
201
173
|
};
|
|
174
|
+
async function persist() {
|
|
175
|
+
try {
|
|
176
|
+
const cur = await fh.stat();
|
|
177
|
+
state = {
|
|
178
|
+
...state,
|
|
179
|
+
offset,
|
|
180
|
+
ino: Number(cur.ino ?? ino),
|
|
181
|
+
dev: Number(cur.dev ?? dev),
|
|
182
|
+
size: cur.size,
|
|
183
|
+
mtimeMs: cur.mtimeMs,
|
|
184
|
+
};
|
|
185
|
+
await writeJsonAtomic(stateFile, state);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// If the file vanished mid-rotation, we'll catch up on the next event.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function parse(content) {
|
|
192
|
+
const lines = content.split("\n");
|
|
193
|
+
if (extract) {
|
|
194
|
+
if (lines.length > 0) {
|
|
195
|
+
remainder = lines[lines.length - 1];
|
|
196
|
+
}
|
|
197
|
+
// parse all lines except the last one (which may be a partial line)
|
|
198
|
+
for (const line of lines.slice(0, -1)) {
|
|
199
|
+
const extracted = extract(line);
|
|
200
|
+
if (extracted) {
|
|
201
|
+
resolveExtracted(extracted);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function drain() {
|
|
208
|
+
return drainMutex.lock(async () => {
|
|
209
|
+
while (true) {
|
|
210
|
+
const cur = await fh.stat().catch(() => null);
|
|
211
|
+
if (!cur)
|
|
212
|
+
break;
|
|
213
|
+
if (cur.size < offset)
|
|
214
|
+
offset = 0; // truncated
|
|
215
|
+
const toRead = Math.min(chunkSize, cur.size - offset);
|
|
216
|
+
if (toRead <= 0)
|
|
217
|
+
break;
|
|
218
|
+
const { bytesRead, buffer } = await fh.read({
|
|
219
|
+
position: offset,
|
|
220
|
+
buffer: Buffer.allocUnsafe(toRead),
|
|
221
|
+
length: toRead,
|
|
222
|
+
});
|
|
223
|
+
if (!bytesRead)
|
|
224
|
+
break;
|
|
225
|
+
const chunk = buffer.subarray(0, bytesRead);
|
|
226
|
+
// write the newly read content to the stream
|
|
227
|
+
write(chunk);
|
|
228
|
+
// parse the previous remainder and the new chunk
|
|
229
|
+
parse(`${remainder || ""}${chunk.toString("utf8")}`);
|
|
230
|
+
offset += bytesRead;
|
|
231
|
+
}
|
|
232
|
+
await persist();
|
|
233
|
+
});
|
|
234
|
+
}
|
|
202
235
|
}
|
|
203
|
-
// ------------------------ main flow ------------------------
|
|
204
|
-
await ensureChildRunning();
|
|
205
|
-
if (!quiet) {
|
|
206
|
-
const write = quiet
|
|
207
|
-
? () => false
|
|
208
|
-
: (buf) => process.stdout.write(buf);
|
|
209
|
-
// Start followers (stdout/stderr) and mirror to this process
|
|
210
|
-
await followFilePersisted(outPath, {
|
|
211
|
-
stateKey: `${path.resolve(outPath)}::stdout`,
|
|
212
|
-
write,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
// Return a stopper for this instance's mirroring (child keeps running)
|
|
216
|
-
return extracted;
|
|
217
236
|
}
|
|
218
237
|
//# sourceMappingURL=idempotent-spawn.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotent-spawn.js","sourceRoot":"","sources":["../../src/util/idempotent-spawn.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"idempotent-spawn.js","sourceRoot":"","sources":["../../src/util/idempotent-spawn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
|
package/lib/util/safe-fetch.d.ts
CHANGED
|
@@ -1,2 +1,26 @@
|
|
|
1
1
|
export declare function safeFetch(url: string | URL | Request, options?: RequestInit, retries?: number): Promise<Response>;
|
|
2
|
+
/**
|
|
3
|
+
* Fetch with exponential backoff retry logic for 404 responses, expecting 200 OK.
|
|
4
|
+
* This is a convenience wrapper around fetchAndExpectStatus with expectedStatus=200.
|
|
5
|
+
*
|
|
6
|
+
* @param input URL or Request object
|
|
7
|
+
* @param init RequestInit options
|
|
8
|
+
* @param maxAttempts Maximum number of retry attempts (default: 10)
|
|
9
|
+
* @param maxWaitTime Maximum total wait time in milliseconds (default: 30000)
|
|
10
|
+
* @returns The successful Response
|
|
11
|
+
*/
|
|
12
|
+
export declare function fetchAndExpectOK(input: string | URL | Request, init?: RequestInit, maxAttempts?: number, maxWaitTime?: number): Promise<Response>;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch and expect a specific status code with retry logic.
|
|
15
|
+
* Cloudflare's control plane is eventually consistent, so resources may
|
|
16
|
+
* return 404 immediately after creation before becoming available.
|
|
17
|
+
*
|
|
18
|
+
* @param input URL or Request object
|
|
19
|
+
* @param init RequestInit options
|
|
20
|
+
* @param expectedStatus Expected HTTP status code (default: 200)
|
|
21
|
+
* @param maxAttempts Maximum number of retry attempts (default: 10)
|
|
22
|
+
* @param maxWaitTime Maximum total wait time in milliseconds (default: 30000)
|
|
23
|
+
* @returns The successful Response
|
|
24
|
+
*/
|
|
25
|
+
export declare function fetchAndExpectStatus(input: string | URL | Request, init?: RequestInit, expectedStatus?: number, maxAttempts?: number, maxWaitTime?: number): Promise<Response>;
|
|
2
26
|
//# sourceMappingURL=safe-fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-fetch.d.ts","sourceRoot":"","sources":["../../src/util/safe-fetch.ts"],"names":[],"mappings":"AAGA,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC3B,OAAO,GAAE,WAAgB,EACzB,OAAO,SAAK,qBAyBb"}
|
|
1
|
+
{"version":3,"file":"safe-fetch.d.ts","sourceRoot":"","sources":["../../src/util/safe-fetch.ts"],"names":[],"mappings":"AAGA,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC3B,OAAO,GAAE,WAAgB,EACzB,OAAO,SAAK,qBAyBb;AAyCD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,EAClB,WAAW,SAAK,EAChB,WAAW,SAAQ,GAClB,OAAO,CAAC,QAAQ,CAAC,CAEnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,EAClB,cAAc,SAAM,EACpB,WAAW,SAAK,EAChB,WAAW,SAAQ,GAClB,OAAO,CAAC,QAAQ,CAAC,CA2EnB"}
|
package/lib/util/safe-fetch.js
CHANGED
|
@@ -52,4 +52,76 @@ async function dispatcher() {
|
|
|
52
52
|
}
|
|
53
53
|
return agent.value;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Fetch with exponential backoff retry logic for 404 responses, expecting 200 OK.
|
|
57
|
+
* This is a convenience wrapper around fetchAndExpectStatus with expectedStatus=200.
|
|
58
|
+
*
|
|
59
|
+
* @param input URL or Request object
|
|
60
|
+
* @param init RequestInit options
|
|
61
|
+
* @param maxAttempts Maximum number of retry attempts (default: 10)
|
|
62
|
+
* @param maxWaitTime Maximum total wait time in milliseconds (default: 30000)
|
|
63
|
+
* @returns The successful Response
|
|
64
|
+
*/
|
|
65
|
+
export async function fetchAndExpectOK(input, init, maxAttempts = 10, maxWaitTime = 30000) {
|
|
66
|
+
return fetchAndExpectStatus(input, init, 200, maxAttempts, maxWaitTime);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Fetch and expect a specific status code with retry logic.
|
|
70
|
+
* Cloudflare's control plane is eventually consistent, so resources may
|
|
71
|
+
* return 404 immediately after creation before becoming available.
|
|
72
|
+
*
|
|
73
|
+
* @param input URL or Request object
|
|
74
|
+
* @param init RequestInit options
|
|
75
|
+
* @param expectedStatus Expected HTTP status code (default: 200)
|
|
76
|
+
* @param maxAttempts Maximum number of retry attempts (default: 10)
|
|
77
|
+
* @param maxWaitTime Maximum total wait time in milliseconds (default: 30000)
|
|
78
|
+
* @returns The successful Response
|
|
79
|
+
*/
|
|
80
|
+
export async function fetchAndExpectStatus(input, init, expectedStatus = 200, maxAttempts = 20, maxWaitTime = 30000) {
|
|
81
|
+
let attempt = 0;
|
|
82
|
+
let lastError;
|
|
83
|
+
while (attempt < maxAttempts) {
|
|
84
|
+
try {
|
|
85
|
+
const response = await safeFetch(input, init);
|
|
86
|
+
// If we get the expected status, return it
|
|
87
|
+
if (response.status === expectedStatus) {
|
|
88
|
+
return response;
|
|
89
|
+
}
|
|
90
|
+
// If we get a 500, 404 when expecting something else, retry with backoff
|
|
91
|
+
if (response.status >= 500 ||
|
|
92
|
+
(response.status === 404 && expectedStatus !== 404)) {
|
|
93
|
+
attempt++;
|
|
94
|
+
if (attempt >= maxAttempts) {
|
|
95
|
+
throw new Error(`Expected status ${expectedStatus} but got 404 after ${maxAttempts} attempts. This may indicate eventual consistency issues.`);
|
|
96
|
+
}
|
|
97
|
+
const backoffTime = Math.min(attempt * 1500, maxWaitTime / maxAttempts);
|
|
98
|
+
console.log(`Expected status ${expectedStatus} but got 404, retrying in ${backoffTime}ms (attempt ${attempt}/${maxAttempts})...`);
|
|
99
|
+
await new Promise((resolve) => setTimeout(resolve, backoffTime));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// For other status codes, throw immediately
|
|
103
|
+
throw new Error(`Expected status ${expectedStatus} but got ${response.status}: ${response.statusText}`);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error instanceof Error) {
|
|
107
|
+
lastError = error;
|
|
108
|
+
// If it's not an HTTP error, retry with backoff
|
|
109
|
+
if (!error.message.startsWith("Expected status") &&
|
|
110
|
+
!error.message.startsWith("HTTP ")) {
|
|
111
|
+
attempt++;
|
|
112
|
+
if (attempt >= maxAttempts) {
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
const backoffTime = Math.min(attempt * 1500, maxWaitTime / maxAttempts);
|
|
116
|
+
console.log(`Network error, retrying in ${backoffTime}ms (attempt ${attempt}/${maxAttempts}): ${error.message}`);
|
|
117
|
+
await new Promise((resolve) => setTimeout(resolve, backoffTime));
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// For status code mismatches, throw immediately
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
throw lastError || new Error(`Failed after ${maxAttempts} attempts`);
|
|
126
|
+
}
|
|
55
127
|
//# sourceMappingURL=safe-fetch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-fetch.js","sourceRoot":"","sources":["../../src/util/safe-fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAA2B,EAC3B,UAAuB,EAAE,EACzB,OAAO,GAAG,EAAE;IAEZ,IAAI,SAAc,CAAC;IACnB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE;gBACtB,GAAG,OAAO;gBACV,oEAAoE;gBACpE,UAAU,EAAE,MAAM,UAAU,EAAE;aAChB,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACxB,SAAS,GAAG,GAAG,CAAC;YAChB,MAAM,WAAW,GACf,uBAAuB,CAAC,GAAG,CAAC,IAAI,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAErE,IAAI,CAAC,WAAW,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;gBACxC,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,SAAS,OAAO,IAAI,OAAO,QAAQ,GAAG,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACnE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,sBAAsB;QAChF,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,uBAAuB,CAAC,GAAQ;IACvC,OAAO,CACL,GAAG,EAAE,IAAI,KAAK,gBAAgB;QAC9B,GAAG,EAAE,IAAI,KAAK,YAAY;QAC1B,GAAG,EAAE,IAAI,KAAK,yBAAyB;QACvC,GAAG,EAAE,IAAI,KAAK,OAAO;QACrB,GAAG,EAAE,IAAI,KAAK,YAAY,CAC3B,CAAC;AACJ,CAAC;AAED,IAAI,KAIS,CAAC;AAEd,KAAK,UAAU,UAAU;IACvB,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IACD,IAAI,CAAC;QACH,uCAAuC;QACvC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,gEAAgE;YAChE,KAAK,GAAG;gBACN,KAAK,EAAE,IAAI,KAAK,CAAC;oBACf,UAAU,EAAE,CAAC,EAAE,gDAAgD;oBAC/D,2DAA2D;iBAC5D,CAAC;aACH,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC"}
|
|
1
|
+
{"version":3,"file":"safe-fetch.js","sourceRoot":"","sources":["../../src/util/safe-fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAA2B,EAC3B,UAAuB,EAAE,EACzB,OAAO,GAAG,EAAE;IAEZ,IAAI,SAAc,CAAC;IACnB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE;gBACtB,GAAG,OAAO;gBACV,oEAAoE;gBACpE,UAAU,EAAE,MAAM,UAAU,EAAE;aAChB,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACxB,SAAS,GAAG,GAAG,CAAC;YAChB,MAAM,WAAW,GACf,uBAAuB,CAAC,GAAG,CAAC,IAAI,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAErE,IAAI,CAAC,WAAW,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;gBACxC,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,SAAS,OAAO,IAAI,OAAO,QAAQ,GAAG,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACnE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,sBAAsB;QAChF,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,uBAAuB,CAAC,GAAQ;IACvC,OAAO,CACL,GAAG,EAAE,IAAI,KAAK,gBAAgB;QAC9B,GAAG,EAAE,IAAI,KAAK,YAAY;QAC1B,GAAG,EAAE,IAAI,KAAK,yBAAyB;QACvC,GAAG,EAAE,IAAI,KAAK,OAAO;QACrB,GAAG,EAAE,IAAI,KAAK,YAAY,CAC3B,CAAC;AACJ,CAAC;AAED,IAAI,KAIS,CAAC;AAEd,KAAK,UAAU,UAAU;IACvB,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IACD,IAAI,CAAC;QACH,uCAAuC;QACvC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,gEAAgE;YAChE,KAAK,GAAG;gBACN,KAAK,EAAE,IAAI,KAAK,CAAC;oBACf,UAAU,EAAE,CAAC,EAAE,gDAAgD;oBAC/D,2DAA2D;iBAC5D,CAAC;aACH,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAA6B,EAC7B,IAAkB,EAClB,WAAW,GAAG,EAAE,EAChB,WAAW,GAAG,KAAK;IAEnB,OAAO,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAA6B,EAC7B,IAAkB,EAClB,cAAc,GAAG,GAAG,EACpB,WAAW,GAAG,EAAE,EAChB,WAAW,GAAG,KAAK;IAEnB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,SAA4B,CAAC;IAEjC,OAAO,OAAO,GAAG,WAAW,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAE9C,2CAA2C;YAC3C,IAAI,QAAQ,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;gBACvC,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,yEAAyE;YACzE,IACE,QAAQ,CAAC,MAAM,IAAI,GAAG;gBACtB,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,cAAc,KAAK,GAAG,CAAC,EACnD,CAAC;gBACD,OAAO,EAAE,CAAC;gBAEV,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;oBAC3B,MAAM,IAAI,KAAK,CACb,mBAAmB,cAAc,sBAAsB,WAAW,2DAA2D,CAC9H,CAAC;gBACJ,CAAC;gBAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC;gBAExE,OAAO,CAAC,GAAG,CACT,mBAAmB,cAAc,6BAA6B,WAAW,eAAe,OAAO,IAAI,WAAW,MAAM,CACrH,CAAC;gBAEF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;gBACjE,SAAS;YACX,CAAC;YAED,4CAA4C;YAC5C,MAAM,IAAI,KAAK,CACb,mBAAmB,cAAc,YAAY,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CACvF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,SAAS,GAAG,KAAK,CAAC;gBAElB,gDAAgD;gBAChD,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC;oBAC5C,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAClC,CAAC;oBACD,OAAO,EAAE,CAAC;oBAEV,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;wBAC3B,MAAM;oBACR,CAAC;oBAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC1B,OAAO,GAAG,IAAI,EACd,WAAW,GAAG,WAAW,CAC1B,CAAC;oBAEF,OAAO,CAAC,GAAG,CACT,8BAA8B,WAAW,eAAe,OAAO,IAAI,WAAW,MAAM,KAAK,CAAC,OAAO,EAAE,CACpG,CAAC;oBAEF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;oBACjE,SAAS;gBACX,CAAC;YACH,CAAC;YAED,gDAAgD;YAChD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,gBAAgB,WAAW,WAAW,CAAC,CAAC;AACvE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
6
6
|
"homepage": "https://alchemy.run",
|
|
@@ -149,6 +149,10 @@
|
|
|
149
149
|
"bun": "./src/state/index.ts",
|
|
150
150
|
"import": "./lib/state/index.js"
|
|
151
151
|
},
|
|
152
|
+
"./util": {
|
|
153
|
+
"bun": "./src/util/index.ts",
|
|
154
|
+
"import": "./lib/util/index.js"
|
|
155
|
+
},
|
|
152
156
|
"./web/astro": {
|
|
153
157
|
"bun": "./src/web/astro.ts",
|
|
154
158
|
"import": "./lib/web/astro.js"
|
|
@@ -168,7 +172,7 @@
|
|
|
168
172
|
},
|
|
169
173
|
"dependencies": {
|
|
170
174
|
"@aws-sdk/credential-providers": "^3.0.0",
|
|
171
|
-
"@cloudflare/unenv-preset": "^2.
|
|
175
|
+
"@cloudflare/unenv-preset": "^2.6.1",
|
|
172
176
|
"@cloudflare/workers-shared": "^0.17.5",
|
|
173
177
|
"@iarna/toml": "^2.2.5",
|
|
174
178
|
"@smithy/node-config-provider": "^4.0.0",
|
|
@@ -182,8 +186,8 @@
|
|
|
182
186
|
"fast-xml-parser": "^5.2.5",
|
|
183
187
|
"find-process": "^2.0.0",
|
|
184
188
|
"glob": "^10.0.0",
|
|
189
|
+
"picocolors": "^1.1.1",
|
|
185
190
|
"jszip": "^3.0.0",
|
|
186
|
-
"kleur": "^4.1.5",
|
|
187
191
|
"libsodium-wrappers": "^0.7.15",
|
|
188
192
|
"miniflare": "^4.20250712.0",
|
|
189
193
|
"neverthrow": "^8.2.0",
|
|
@@ -192,7 +196,7 @@
|
|
|
192
196
|
"pathe": "^2.0.3",
|
|
193
197
|
"signal-exit": "^4.1.0",
|
|
194
198
|
"turndown": "^7.0.0",
|
|
195
|
-
"unenv": "2.0.0-rc.
|
|
199
|
+
"unenv": "2.0.0-rc.19",
|
|
196
200
|
"ws": "^8.18.3",
|
|
197
201
|
"yaml": "^2.0.0"
|
|
198
202
|
},
|
|
@@ -260,7 +264,6 @@
|
|
|
260
264
|
"nitro-cloudflare-dev": "^0.2.2",
|
|
261
265
|
"nitropack": "^2.12.4",
|
|
262
266
|
"openpgp": "^6.1.0",
|
|
263
|
-
"picocolors": "^1.1.1",
|
|
264
267
|
"prettier": "^3.5.3",
|
|
265
268
|
"rwsdk": "^0.1.28",
|
|
266
269
|
"trpc-cli": "^0.10.2",
|
package/src/alchemy.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
type PendingResource,
|
|
16
16
|
} from "./resource.ts";
|
|
17
17
|
import { isRuntime } from "./runtime/global.ts";
|
|
18
|
-
import { DEFAULT_STAGE, Scope } from "./scope.ts";
|
|
18
|
+
import { DEFAULT_STAGE, Scope, type ProviderCredentials } from "./scope.ts";
|
|
19
19
|
import { secret } from "./secret.ts";
|
|
20
20
|
import type { StateStoreType } from "./state.ts";
|
|
21
21
|
import type { LoggerApi } from "./util/cli.ts";
|
|
@@ -420,7 +420,7 @@ export interface ScopeOptions extends AlchemyOptions {
|
|
|
420
420
|
enter: boolean;
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
export interface RunOptions extends AlchemyOptions {
|
|
423
|
+
export interface RunOptions extends AlchemyOptions, ProviderCredentials {
|
|
424
424
|
/**
|
|
425
425
|
* @default false
|
|
426
426
|
*/
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { Secret } from "../secret.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AWS client properties for credential configuration.
|
|
5
|
+
*
|
|
6
|
+
* This interface defines the properties that can be used to configure AWS credentials
|
|
7
|
+
* at different levels of your application. It supports the three-tier credential resolution
|
|
8
|
+
* system (global → scope → resource) and enables multi-account and multi-region deployments.
|
|
9
|
+
*
|
|
10
|
+
* These properties can be specified at:
|
|
11
|
+
* 1. Resource level - directly in resource creation parameters
|
|
12
|
+
* 2. Scope level - in alchemy.run() options with `aws` property
|
|
13
|
+
* 3. Global level - through environment variables (AWS_REGION, AWS_PROFILE, etc.)
|
|
14
|
+
*
|
|
15
|
+
* The credential resolution follows a precedence order where resource-level credentials
|
|
16
|
+
* override scope-level credentials, which override global environment variables.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Resource-level credential overrides
|
|
21
|
+
* const vpc = await Vpc("main-vpc", {
|
|
22
|
+
* cidrBlock: "10.0.0.0/16",
|
|
23
|
+
* region: "us-west-2", // Override region
|
|
24
|
+
* profile: "production", // Override profile
|
|
25
|
+
* tags: { Name: "main-vpc" }
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Scope-level credential configuration
|
|
32
|
+
* await alchemy.run("production", {
|
|
33
|
+
* aws: {
|
|
34
|
+
* region: "us-west-2",
|
|
35
|
+
* profile: "production",
|
|
36
|
+
* }
|
|
37
|
+
* }, async () => {
|
|
38
|
+
* // Resources created here will use the scope credentials by default
|
|
39
|
+
* const vpc = await Vpc("main-vpc", {
|
|
40
|
+
* cidrBlock: "10.0.0.0/16"
|
|
41
|
+
* });
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export interface AwsClientProps {
|
|
46
|
+
/**
|
|
47
|
+
* AWS access key ID for authentication.
|
|
48
|
+
*
|
|
49
|
+
* This corresponds to the AWS_ACCESS_KEY_ID environment variable.
|
|
50
|
+
* When provided at the resource or scope level, it overrides the environment variable.
|
|
51
|
+
*/
|
|
52
|
+
accessKeyId?: Secret<string>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* AWS secret access key for authentication.
|
|
56
|
+
*
|
|
57
|
+
* This corresponds to the AWS_SECRET_ACCESS_KEY environment variable.
|
|
58
|
+
* When provided at the resource or scope level, it overrides the environment variable.
|
|
59
|
+
*/
|
|
60
|
+
secretAccessKey?: Secret<string>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* AWS session token for temporary credentials.
|
|
64
|
+
*
|
|
65
|
+
* This corresponds to the AWS_SESSION_TOKEN environment variable.
|
|
66
|
+
* Used with temporary credentials from STS or when assuming a role.
|
|
67
|
+
*/
|
|
68
|
+
sessionToken?: Secret<string>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* AWS region to use for API calls.
|
|
72
|
+
*
|
|
73
|
+
* This corresponds to the AWS_REGION or AWS_DEFAULT_REGION environment variables.
|
|
74
|
+
* When provided at the resource or scope level, it overrides the environment variables.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* // Resource in a specific region
|
|
79
|
+
* const euVpc = await Vpc("eu-vpc", {
|
|
80
|
+
* cidrBlock: "10.0.0.0/16",
|
|
81
|
+
* region: "eu-west-1",
|
|
82
|
+
* tags: { Name: "eu-vpc" }
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
region?: string;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* AWS profile name to use from credentials file.
|
|
90
|
+
*
|
|
91
|
+
* This corresponds to the AWS_PROFILE environment variable.
|
|
92
|
+
* Profiles are defined in ~/.aws/credentials or ~/.aws/config files.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Resource using a specific profile
|
|
97
|
+
* const prodVpc = await Vpc("prod-vpc", {
|
|
98
|
+
* cidrBlock: "10.0.0.0/16",
|
|
99
|
+
* profile: "production-account",
|
|
100
|
+
* tags: { Name: "prod-vpc" }
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
profile?: string;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* AWS role ARN to assume for authentication.
|
|
108
|
+
*
|
|
109
|
+
* This corresponds to the AWS_ROLE_ARN environment variable.
|
|
110
|
+
* Used for cross-account access or for assuming roles with specific permissions.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* // Resource using role assumption
|
|
115
|
+
* const crossAccountVpc = await Vpc("cross-account-vpc", {
|
|
116
|
+
* cidrBlock: "10.0.0.0/16",
|
|
117
|
+
* roleArn: "arn:aws:iam::123456789012:role/DeploymentRole",
|
|
118
|
+
* roleSessionName: "alchemy-deployment",
|
|
119
|
+
* tags: { Name: "cross-account-vpc" }
|
|
120
|
+
* });
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
roleArn?: string;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* External ID to use when assuming a role.
|
|
127
|
+
*
|
|
128
|
+
* This corresponds to the AWS_EXTERNAL_ID environment variable.
|
|
129
|
+
* Used as an additional security measure when assuming roles across accounts.
|
|
130
|
+
*/
|
|
131
|
+
externalId?: string;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Session name to use when assuming a role.
|
|
135
|
+
*
|
|
136
|
+
* This corresponds to the AWS_ROLE_SESSION_NAME environment variable.
|
|
137
|
+
* Helps identify who/what is using the assumed role in AWS CloudTrail logs.
|
|
138
|
+
*/
|
|
139
|
+
roleSessionName?: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* AWS scope extensions - adds AWS credential support to scope options.
|
|
143
|
+
* This uses TypeScript module augmentation to extend the ProviderCredentials interface.
|
|
144
|
+
* Since ScopeOptions and RunOptions both extend ProviderCredentials,
|
|
145
|
+
* they automatically inherit these properties.
|
|
146
|
+
*/
|
|
147
|
+
declare module "../scope.ts" {
|
|
148
|
+
interface ProviderCredentials {
|
|
149
|
+
/**
|
|
150
|
+
* AWS credentials configuration for this scope.
|
|
151
|
+
* All AWS resources created within this scope will inherit these credentials
|
|
152
|
+
* unless overridden at the resource level.
|
|
153
|
+
*/
|
|
154
|
+
aws?: AwsClientProps;
|
|
155
|
+
}
|
|
156
|
+
}
|