alchemy 0.61.0 → 0.62.1
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 +1916 -1934
- package/bin/commands/init.ts +29 -2
- package/bin/services/execute-alchemy.ts +1 -2
- package/bin/services/github-workflow.ts +204 -142
- 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/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +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/sveltekit/plugin.d.ts +2 -1
- package/lib/cloudflare/sveltekit/plugin.d.ts.map +1 -1
- package/lib/cloudflare/sveltekit/plugin.js +9 -0
- package/lib/cloudflare/sveltekit/plugin.js.map +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 +28 -22
- 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 +13 -8
- package/lib/util/idempotent-spawn.d.ts.map +1 -1
- package/lib/util/idempotent-spawn.js +120 -77
- 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/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/kv-namespace.ts +26 -27
- package/src/cloudflare/oauth.ts +3 -3
- package/src/cloudflare/sveltekit/plugin.ts +14 -1
- 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 +77 -46
- package/src/state/cloudflare-state-store.ts +2 -1
- package/src/util/idempotent-spawn.ts +142 -99
- package/src/util/index.ts +1 -0
- package/src/util/safe-fetch.ts +114 -0
- package/templates/astro/alchemy.run.ts +4 -2
- package/templates/nuxt/alchemy.run.ts +4 -2
- package/templates/react-router/alchemy.run.ts +4 -2
- package/templates/rwsdk/alchemy.run.ts +3 -3
- package/templates/sveltekit/alchemy.run.ts +4 -2
- package/templates/tanstack-start/alchemy.run.ts +4 -2
- package/templates/typescript/alchemy.run.ts +2 -2
- package/templates/vite/alchemy.run.ts +3 -2
- package/templates/vite/src/worker.ts +13 -0
- package/templates/vite/tsconfig.json +0 -1
- package/templates/vite/worker/index.ts +0 -12
|
@@ -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,21 @@ 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
|
+
const pid = 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 {
|
|
35
|
+
extracted,
|
|
36
|
+
stop: async () => (pid ? await kill(pid) : undefined),
|
|
37
|
+
};
|
|
27
38
|
function isPidAlive(pid) {
|
|
28
39
|
if (!pid || Number.isNaN(pid))
|
|
29
40
|
return false;
|
|
@@ -56,7 +67,7 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
56
67
|
shell: true,
|
|
57
68
|
cwd,
|
|
58
69
|
stdio: ["ignore", out.fd, out.fd], // stdout/stderr -> files (OS-level)
|
|
59
|
-
env
|
|
70
|
+
env,
|
|
60
71
|
detached: false,
|
|
61
72
|
});
|
|
62
73
|
// Child now owns dup'd fds; close our handles.
|
|
@@ -76,12 +87,15 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
76
87
|
if (await isSameProcess?.(pid))
|
|
77
88
|
return pid;
|
|
78
89
|
if (processName) {
|
|
90
|
+
const { default: find } = await import("find-process");
|
|
79
91
|
const processes = await find("pid", pid);
|
|
80
92
|
if (processes.length > 1) {
|
|
81
93
|
console.warn(`Found multiple processes with PID ${pid}, using the first one`);
|
|
82
94
|
}
|
|
83
95
|
if (processes.length > 0) {
|
|
84
|
-
|
|
96
|
+
if (processes[0].name.startsWith(processName)) {
|
|
97
|
+
return pid;
|
|
98
|
+
}
|
|
85
99
|
}
|
|
86
100
|
}
|
|
87
101
|
}
|
|
@@ -93,7 +107,9 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
93
107
|
return (await spawnLoggedChild()).pid;
|
|
94
108
|
}
|
|
95
109
|
// Follow a file from persisted offset and mirror to a sink (stdout/stderr)
|
|
96
|
-
async function followFilePersisted(logPath, { write
|
|
110
|
+
async function followFilePersisted(logPath, { write, chunkSize = 64 * 1024,
|
|
111
|
+
// tickMs = 100,
|
|
112
|
+
}) {
|
|
97
113
|
logPath = path.resolve(logPath);
|
|
98
114
|
let state = (await readJson(stateFile)) ?? {};
|
|
99
115
|
let fh = await fsp.open(logPath, "r");
|
|
@@ -108,62 +124,21 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
108
124
|
? Math.max(0, Math.min(st.size, state.offset - overlapBytes))
|
|
109
125
|
: st.size;
|
|
110
126
|
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();
|
|
127
|
+
const drainMutex = new AsyncMutex();
|
|
128
|
+
// we read the log file and stream in chunks, not lines
|
|
129
|
+
// so we need to keep track of the remainder of the last line
|
|
130
|
+
let remainder;
|
|
131
|
+
// if we are resuming, then re-parse the log lines to extract the value
|
|
132
|
+
if (offset > 0) {
|
|
133
|
+
// read from start to offset
|
|
134
|
+
const fullBuffer = Buffer.allocUnsafe(offset);
|
|
135
|
+
await fh.read({
|
|
136
|
+
position: 0,
|
|
137
|
+
buffer: fullBuffer,
|
|
138
|
+
length: offset,
|
|
139
|
+
});
|
|
140
|
+
const content = fullBuffer.toString("utf8");
|
|
141
|
+
parse(content);
|
|
167
142
|
}
|
|
168
143
|
await drain();
|
|
169
144
|
const watcher = fs.watch(logPath, async () => {
|
|
@@ -199,20 +174,88 @@ export async function idempotentSpawn({ cmd, cwd, stateFile = "state.json", over
|
|
|
199
174
|
await fh.close().catch(() => { });
|
|
200
175
|
await persist();
|
|
201
176
|
};
|
|
177
|
+
async function persist() {
|
|
178
|
+
try {
|
|
179
|
+
const cur = await fh.stat();
|
|
180
|
+
state = {
|
|
181
|
+
...state,
|
|
182
|
+
offset,
|
|
183
|
+
ino: Number(cur.ino ?? ino),
|
|
184
|
+
dev: Number(cur.dev ?? dev),
|
|
185
|
+
size: cur.size,
|
|
186
|
+
mtimeMs: cur.mtimeMs,
|
|
187
|
+
};
|
|
188
|
+
await writeJsonAtomic(stateFile, state);
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// If the file vanished mid-rotation, we'll catch up on the next event.
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function parse(content) {
|
|
195
|
+
const lines = content.split("\n");
|
|
196
|
+
if (extract) {
|
|
197
|
+
if (lines.length > 0) {
|
|
198
|
+
remainder = lines[lines.length - 1];
|
|
199
|
+
}
|
|
200
|
+
// parse all lines except the last one (which may be a partial line)
|
|
201
|
+
for (const line of lines.slice(0, -1)) {
|
|
202
|
+
const extracted = extract(line);
|
|
203
|
+
if (extracted) {
|
|
204
|
+
resolveExtracted(extracted);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function drain() {
|
|
211
|
+
return drainMutex.lock(async () => {
|
|
212
|
+
while (true) {
|
|
213
|
+
const cur = await fh.stat().catch(() => null);
|
|
214
|
+
if (!cur)
|
|
215
|
+
break;
|
|
216
|
+
if (cur.size < offset)
|
|
217
|
+
offset = 0; // truncated
|
|
218
|
+
const toRead = Math.min(chunkSize, cur.size - offset);
|
|
219
|
+
if (toRead <= 0)
|
|
220
|
+
break;
|
|
221
|
+
const { bytesRead, buffer } = await fh.read({
|
|
222
|
+
position: offset,
|
|
223
|
+
buffer: Buffer.allocUnsafe(toRead),
|
|
224
|
+
length: toRead,
|
|
225
|
+
});
|
|
226
|
+
if (!bytesRead)
|
|
227
|
+
break;
|
|
228
|
+
const chunk = buffer.subarray(0, bytesRead);
|
|
229
|
+
// write the newly read content to the stream
|
|
230
|
+
write(chunk);
|
|
231
|
+
// parse the previous remainder and the new chunk
|
|
232
|
+
parse(`${remainder || ""}${chunk.toString("utf8")}`);
|
|
233
|
+
offset += bytesRead;
|
|
234
|
+
}
|
|
235
|
+
await persist();
|
|
236
|
+
});
|
|
237
|
+
}
|
|
202
238
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
239
|
+
async function kill(pid) {
|
|
240
|
+
// 1. Kill with SIGTERM
|
|
241
|
+
try {
|
|
242
|
+
process.kill(pid, "SIGTERM");
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
// 2. Detect if it's still running.
|
|
248
|
+
// The process appears to remain in the process table even after it's exited, so `isPidAlive` will return true.
|
|
249
|
+
// However, if it's in the table, `find-process` will return it with a name of "<defunct>", so we can detect that instead.
|
|
250
|
+
const { default: find } = await import("find-process");
|
|
251
|
+
const processes = await find("pid", pid);
|
|
252
|
+
if (processes.some((p) => p.name !== "<defunct>")) {
|
|
253
|
+
// 3. If it's still running, kill with SIGKILL
|
|
254
|
+
try {
|
|
255
|
+
process.kill(pid, "SIGKILL");
|
|
256
|
+
}
|
|
257
|
+
catch { }
|
|
258
|
+
}
|
|
214
259
|
}
|
|
215
|
-
// Return a stopper for this instance's mirroring (child keeps running)
|
|
216
|
-
return extracted;
|
|
217
260
|
}
|
|
218
261
|
//# 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":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.1",
|
|
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
|
*/
|