alchemy 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/alchemy.js +14201 -14162
- package/bin/commands/create.ts +7 -7
- package/bin/commands/deploy.ts +2 -2
- package/bin/commands/destroy.ts +2 -2
- package/bin/commands/dev.ts +2 -2
- package/bin/commands/init.ts +6 -6
- package/bin/commands/login.ts +3 -3
- package/bin/commands/run.ts +2 -2
- package/bin/services/execute-alchemy.ts +3 -3
- package/bin/trpc.ts +49 -0
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +3 -4
- package/lib/apply.js.map +1 -1
- package/lib/cloudflare/{astro.d.ts → astro/astro.d.ts} +6 -5
- package/lib/cloudflare/astro/astro.d.ts.map +1 -0
- package/lib/cloudflare/astro/astro.js +91 -0
- package/lib/cloudflare/astro/astro.js.map +1 -0
- package/lib/cloudflare/astro/plugin.d.ts +4 -0
- package/lib/cloudflare/astro/plugin.d.ts.map +1 -0
- package/lib/cloudflare/astro/plugin.js +10 -0
- package/lib/cloudflare/astro/plugin.js.map +1 -0
- package/lib/cloudflare/cloudflare-env-proxy.d.ts +4 -0
- package/lib/cloudflare/cloudflare-env-proxy.d.ts.map +1 -0
- package/lib/cloudflare/cloudflare-env-proxy.js +34 -0
- package/lib/cloudflare/cloudflare-env-proxy.js.map +1 -0
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/d1-local-migrations.js +1 -1
- package/lib/cloudflare/d1-local-migrations.js.map +1 -1
- package/lib/cloudflare/index.d.ts +8 -8
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +8 -8
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js +2 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
- package/lib/cloudflare/miniflare/paths.d.ts +5 -0
- package/lib/cloudflare/miniflare/paths.d.ts.map +1 -0
- package/lib/cloudflare/miniflare/paths.js +35 -0
- package/lib/cloudflare/miniflare/paths.js.map +1 -0
- package/lib/cloudflare/{nuxt.d.ts → nuxt/nuxt.d.ts} +4 -4
- package/lib/cloudflare/nuxt/nuxt.d.ts.map +1 -0
- package/lib/cloudflare/{nuxt.js → nuxt/nuxt.js} +8 -13
- package/lib/cloudflare/nuxt/nuxt.js.map +1 -0
- package/lib/cloudflare/nuxt/plugin.d.ts +4 -0
- package/lib/cloudflare/nuxt/plugin.d.ts.map +1 -0
- package/lib/cloudflare/nuxt/plugin.js +14 -0
- package/lib/cloudflare/nuxt/plugin.js.map +1 -0
- package/lib/cloudflare/oauth.js +2 -2
- package/lib/cloudflare/oauth.js.map +1 -1
- package/lib/cloudflare/orange.d.ts +3 -3
- package/lib/cloudflare/orange.d.ts.map +1 -1
- package/lib/cloudflare/orange.js +11 -21
- package/lib/cloudflare/orange.js.map +1 -1
- package/lib/cloudflare/react-router/plugin.d.ts +4 -0
- package/lib/cloudflare/react-router/plugin.d.ts.map +1 -0
- package/lib/cloudflare/react-router/plugin.js +11 -0
- package/lib/cloudflare/react-router/plugin.js.map +1 -0
- package/lib/cloudflare/react-router/react-router.d.ts +17 -0
- package/lib/cloudflare/react-router/react-router.d.ts.map +1 -0
- package/lib/cloudflare/react-router/react-router.js +21 -0
- package/lib/cloudflare/react-router/react-router.js.map +1 -0
- package/lib/cloudflare/redwood/plugin.d.ts +4 -0
- package/lib/cloudflare/redwood/plugin.d.ts.map +1 -0
- package/lib/cloudflare/redwood/plugin.js +19 -0
- package/lib/cloudflare/redwood/plugin.js.map +1 -0
- package/lib/cloudflare/{redwood.d.ts → redwood/redwood.d.ts} +5 -5
- package/lib/cloudflare/redwood/redwood.d.ts.map +1 -0
- package/lib/cloudflare/{redwood.js → redwood/redwood.js} +12 -13
- package/lib/cloudflare/redwood/redwood.js.map +1 -0
- package/lib/cloudflare/sveltekit/plugin.d.ts +4 -0
- package/lib/cloudflare/sveltekit/plugin.d.ts.map +1 -0
- package/lib/cloudflare/sveltekit/plugin.js +11 -0
- package/lib/cloudflare/sveltekit/plugin.js.map +1 -0
- package/lib/cloudflare/{sveltekit.d.ts → sveltekit/sveltekit.d.ts} +5 -5
- package/lib/cloudflare/sveltekit/sveltekit.d.ts.map +1 -0
- package/lib/cloudflare/{sveltekit.js → sveltekit/sveltekit.js} +4 -4
- package/lib/cloudflare/sveltekit/sveltekit.js.map +1 -0
- package/lib/cloudflare/{local-dev-cloudflare-shim.d.ts → tanstack-start/plugin.d.ts} +3 -2
- package/lib/cloudflare/tanstack-start/plugin.d.ts.map +1 -0
- package/lib/cloudflare/{local-dev-cloudflare-shim.js → tanstack-start/plugin.js} +6 -9
- package/lib/cloudflare/tanstack-start/plugin.js.map +1 -0
- package/lib/cloudflare/{tanstack-start.d.ts → tanstack-start/tanstack-start.d.ts} +5 -5
- package/lib/cloudflare/tanstack-start/tanstack-start.d.ts.map +1 -0
- package/lib/cloudflare/tanstack-start/tanstack-start.js +11 -0
- package/lib/cloudflare/tanstack-start/tanstack-start.js.map +1 -0
- package/lib/cloudflare/vite/plugin.d.ts +4 -0
- package/lib/cloudflare/vite/plugin.d.ts.map +1 -0
- package/lib/cloudflare/vite/plugin.js +23 -0
- package/lib/cloudflare/vite/plugin.js.map +1 -0
- package/lib/cloudflare/{vite.d.ts → vite/vite.d.ts} +4 -4
- package/lib/cloudflare/vite/vite.d.ts.map +1 -0
- package/lib/cloudflare/vite/vite.js +19 -0
- package/lib/cloudflare/vite/vite.js.map +1 -0
- package/lib/cloudflare/website.d.ts +92 -70
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +225 -94
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-bundle.d.ts +1 -1
- package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
- package/lib/cloudflare/worker-bundle.js +23 -13
- package/lib/cloudflare/worker-bundle.js.map +1 -1
- package/lib/cloudflare/worker-stub.d.ts.map +1 -1
- package/lib/cloudflare/worker-stub.js +3 -6
- package/lib/cloudflare/worker-stub.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +2 -7
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +5 -124
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts +6 -0
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +23 -6
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/env.d.ts +2 -2
- package/lib/env.d.ts.map +1 -1
- package/lib/env.js +5 -6
- package/lib/env.js.map +1 -1
- package/lib/random/index.d.ts +2 -0
- package/lib/random/index.d.ts.map +1 -0
- package/lib/random/index.js +2 -0
- package/lib/random/index.js.map +1 -0
- package/lib/random/random-string.d.ts +87 -0
- package/lib/random/random-string.d.ts.map +1 -0
- package/lib/random/random-string.js +72 -0
- package/lib/random/random-string.js.map +1 -0
- package/lib/runtime/bind.d.ts +1 -1
- package/lib/runtime/bind.d.ts.map +1 -1
- package/lib/runtime/bind.js.map +1 -1
- package/lib/scope.d.ts +0 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +1 -2
- package/lib/scope.js.map +1 -1
- package/lib/secret.d.ts +2 -2
- package/lib/secret.d.ts.map +1 -1
- package/lib/secret.js +2 -2
- package/lib/secret.js.map +1 -1
- package/lib/state/cloudflare-state-store.js +1 -1
- package/lib/state/cloudflare-state-store.js.map +1 -1
- package/lib/state/dofs-state-store/index.js +1 -1
- package/lib/state/dofs-state-store/index.js.map +1 -1
- package/lib/util/detect-package-manager.d.ts +1 -0
- package/lib/util/detect-package-manager.d.ts.map +1 -1
- package/lib/util/detect-package-manager.js +10 -0
- package/lib/util/detect-package-manager.js.map +1 -1
- package/lib/util/telemetry/client.d.ts +1 -1
- package/lib/util/telemetry/client.d.ts.map +1 -1
- package/lib/util/telemetry/client.js +22 -1
- package/lib/util/telemetry/client.js.map +1 -1
- package/lib/util/telemetry/constants.d.ts.map +1 -1
- package/lib/util/telemetry/constants.js +2 -3
- package/lib/util/telemetry/constants.js.map +1 -1
- package/lib/util/telemetry/context.d.ts +1 -1
- package/lib/util/telemetry/context.d.ts.map +1 -1
- package/lib/util/telemetry/types.d.ts +7 -3
- package/lib/util/telemetry/types.d.ts.map +1 -1
- package/lib/vercel/api.d.ts.map +1 -1
- package/lib/vercel/api.js +1 -1
- package/lib/vercel/api.js.map +1 -1
- package/package.json +41 -3
- package/src/apply.ts +3 -7
- package/src/cloudflare/{astro.ts → astro/astro.ts} +46 -29
- package/src/cloudflare/astro/plugin.ts +11 -0
- package/src/cloudflare/cloudflare-env-proxy.ts +50 -0
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/d1-local-migrations.ts +1 -1
- package/src/cloudflare/index.ts +8 -8
- package/src/cloudflare/miniflare/miniflare-controller.ts +2 -1
- package/src/cloudflare/miniflare/paths.ts +52 -0
- package/src/cloudflare/{nuxt.ts → nuxt/nuxt.ts} +11 -16
- package/src/cloudflare/nuxt/plugin.ts +18 -0
- package/src/cloudflare/oauth.ts +2 -2
- package/src/cloudflare/orange.ts +13 -23
- package/src/cloudflare/react-router/plugin.ts +13 -0
- package/src/cloudflare/react-router/react-router.ts +41 -0
- package/src/cloudflare/redwood/plugin.ts +20 -0
- package/src/cloudflare/{redwood.ts → redwood/redwood.ts} +16 -19
- package/src/cloudflare/sveltekit/plugin.ts +12 -0
- package/src/cloudflare/{sveltekit.ts → sveltekit/sveltekit.ts} +9 -8
- package/src/cloudflare/{local-dev-cloudflare-shim.ts → tanstack-start/plugin.ts} +8 -9
- package/src/cloudflare/tanstack-start/tanstack-start.ts +24 -0
- package/src/cloudflare/vite/plugin.ts +30 -0
- package/src/cloudflare/vite/vite.ts +34 -0
- package/src/cloudflare/website.ts +379 -204
- package/src/cloudflare/worker-bundle.ts +27 -13
- package/src/cloudflare/worker-stub.ts +11 -14
- package/src/cloudflare/worker.ts +8 -155
- package/src/cloudflare/wrangler.json.ts +32 -4
- package/src/env.ts +8 -9
- package/src/random/index.ts +1 -0
- package/src/random/random-string.ts +126 -0
- package/src/runtime/bind.ts +2 -2
- package/src/scope.ts +1 -3
- package/src/secret.ts +4 -8
- package/src/state/cloudflare-state-store.ts +2 -2
- package/src/state/dofs-state-store/index.ts +1 -1
- package/src/util/detect-package-manager.ts +11 -0
- package/src/util/telemetry/client.ts +25 -2
- package/src/util/telemetry/constants.ts +2 -4
- package/src/util/telemetry/context.ts +1 -1
- package/src/util/telemetry/types.ts +8 -2
- package/src/vercel/api.ts +2 -4
- package/templates/astro/alchemy.run.ts +1 -3
- package/templates/astro/astro.config.mjs +2 -2
- package/templates/nuxt/alchemy.run.ts +1 -3
- package/templates/nuxt/nuxt.config.ts +4 -5
- package/templates/nuxt/package.json +0 -1
- package/templates/react-router/alchemy.run.ts +1 -4
- package/templates/react-router/vite.config.ts +2 -2
- package/templates/rwsdk/alchemy.run.ts +0 -1
- package/templates/rwsdk/package.json +0 -2
- package/templates/rwsdk/vite.config.mts +2 -2
- package/templates/sveltekit/alchemy.run.ts +1 -3
- package/templates/sveltekit/svelte.config.js +2 -2
- package/templates/tanstack-start/vite.config.ts +2 -2
- package/templates/vite/alchemy.run.ts +1 -1
- package/templates/vite/vite.config.ts +4 -5
- package/workers/cloudflare-state-store.js +12 -14
- package/lib/cloudflare/astro.d.ts.map +0 -1
- package/lib/cloudflare/astro.js +0 -69
- package/lib/cloudflare/astro.js.map +0 -1
- package/lib/cloudflare/local-dev-cloudflare-shim.d.ts.map +0 -1
- package/lib/cloudflare/local-dev-cloudflare-shim.js.map +0 -1
- package/lib/cloudflare/nuxt.d.ts.map +0 -1
- package/lib/cloudflare/nuxt.js.map +0 -1
- package/lib/cloudflare/react-router.d.ts +0 -17
- package/lib/cloudflare/react-router.d.ts.map +0 -1
- package/lib/cloudflare/react-router.js +0 -35
- package/lib/cloudflare/react-router.js.map +0 -1
- package/lib/cloudflare/redwood.d.ts.map +0 -1
- package/lib/cloudflare/redwood.js.map +0 -1
- package/lib/cloudflare/sveltekit.d.ts.map +0 -1
- package/lib/cloudflare/sveltekit.js.map +0 -1
- package/lib/cloudflare/tanstack-start.d.ts.map +0 -1
- package/lib/cloudflare/tanstack-start.js +0 -21
- package/lib/cloudflare/tanstack-start.js.map +0 -1
- package/lib/cloudflare/vite.d.ts.map +0 -1
- package/lib/cloudflare/vite.js +0 -20
- package/lib/cloudflare/vite.js.map +0 -1
- package/src/cloudflare/react-router.ts +0 -56
- package/src/cloudflare/tanstack-start.ts +0 -35
- package/src/cloudflare/vite.ts +0 -35
- package/templates/react-router/wrangler.jsonc +0 -6
- package/templates/rwsdk/wrangler.jsonc +0 -31
- package/templates/sveltekit/wrangler.jsonc +0 -7
- package/templates/tanstack-start/wrangler.jsonc +0 -7
- package/templates/typescript/index.ts +0 -1
- package/templates/vite/wrangler.jsonc +0 -6
|
@@ -74,7 +74,7 @@ export function normalizeWorkerBundle(props: {
|
|
|
74
74
|
nodeCompat,
|
|
75
75
|
cwd: props.cwd,
|
|
76
76
|
outdir: props.outdir,
|
|
77
|
-
sourcemap: props.sourceMap !== false ?
|
|
77
|
+
sourcemap: props.sourceMap !== false ? true : undefined,
|
|
78
78
|
...props.bundle,
|
|
79
79
|
}),
|
|
80
80
|
);
|
|
@@ -128,7 +128,8 @@ export namespace WorkerBundle {
|
|
|
128
128
|
(await fs.readFile(path.join(bundle.root!, module.path)));
|
|
129
129
|
form.append(
|
|
130
130
|
module.path,
|
|
131
|
-
|
|
131
|
+
// TODO(sam): tsc -b geting a weird error about SharedArrayBuffer
|
|
132
|
+
new Blob([content as any as BlobPart], {
|
|
132
133
|
type: types[module.type],
|
|
133
134
|
}),
|
|
134
135
|
module.path,
|
|
@@ -266,7 +267,7 @@ export namespace WorkerBundleSource {
|
|
|
266
267
|
const wasmPlugin = createWasmPlugin();
|
|
267
268
|
const options = this.buildOptions([wasmPlugin.plugin]);
|
|
268
269
|
const result = await esbuild.build(options);
|
|
269
|
-
const { entrypoint, root, modules } = this.
|
|
270
|
+
const { entrypoint, root, modules } = await this.formatBuildOutput(
|
|
270
271
|
result.metafile,
|
|
271
272
|
);
|
|
272
273
|
return {
|
|
@@ -300,7 +301,7 @@ export namespace WorkerBundleSource {
|
|
|
300
301
|
|
|
301
302
|
for await (const result of hotReload.iterator) {
|
|
302
303
|
count++;
|
|
303
|
-
const { entrypoint, root, modules } = this.
|
|
304
|
+
const { entrypoint, root, modules } = await this.formatBuildOutput(
|
|
304
305
|
result.metafile!,
|
|
305
306
|
);
|
|
306
307
|
yield {
|
|
@@ -330,20 +331,27 @@ export namespace WorkerBundleSource {
|
|
|
330
331
|
return {
|
|
331
332
|
entryPoints: [entrypoint],
|
|
332
333
|
absWorkingDir: cwd,
|
|
334
|
+
target: "es2022",
|
|
335
|
+
loader: {
|
|
336
|
+
".js": "jsx",
|
|
337
|
+
".mjs": "jsx",
|
|
338
|
+
".cjs": "jsx",
|
|
339
|
+
},
|
|
333
340
|
format,
|
|
334
|
-
|
|
341
|
+
sourceRoot: this.props.outdir,
|
|
342
|
+
jsxFactory: "React.createElement",
|
|
343
|
+
jsxFragment: "React.Fragment",
|
|
344
|
+
keepNames: true,
|
|
335
345
|
...props,
|
|
336
346
|
metafile: true,
|
|
337
347
|
write: true,
|
|
338
348
|
bundle: true,
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
".json": "json",
|
|
344
|
-
".wasm": "binary",
|
|
345
|
-
...props.loader,
|
|
349
|
+
define: {
|
|
350
|
+
"navigator.userAgent": '"Cloudflare-Workers"',
|
|
351
|
+
"process.env.NODE_ENV": '"undefined"',
|
|
352
|
+
...props.define,
|
|
346
353
|
},
|
|
354
|
+
conditions: props.conditions ?? ["workerd", "worker", "browser"],
|
|
347
355
|
plugins: [
|
|
348
356
|
esbuildPluginAlias(props.alias ?? {}, this.props.cwd),
|
|
349
357
|
nodeCompat === "v2"
|
|
@@ -359,8 +367,14 @@ export namespace WorkerBundleSource {
|
|
|
359
367
|
} satisfies esbuild.BuildOptions;
|
|
360
368
|
}
|
|
361
369
|
|
|
362
|
-
private
|
|
370
|
+
private async formatBuildOutput(
|
|
371
|
+
metafile: esbuild.Metafile,
|
|
372
|
+
): Promise<WorkerBundle> {
|
|
363
373
|
const outdir = path.resolve(this.props.cwd, this.props.outdir);
|
|
374
|
+
await fs.writeFile(
|
|
375
|
+
path.join(outdir, "metafile.json"),
|
|
376
|
+
JSON.stringify(metafile, null, 2),
|
|
377
|
+
);
|
|
364
378
|
const paths: string[] = [];
|
|
365
379
|
let entrypoint: string | undefined;
|
|
366
380
|
for (const [key, value] of Object.entries(metafile.outputs)) {
|
|
@@ -2,6 +2,7 @@ import type { Context } from "../context.ts";
|
|
|
2
2
|
import { Resource, ResourceKind } from "../resource.ts";
|
|
3
3
|
import type { type } from "../type.ts";
|
|
4
4
|
import { handleApiError } from "./api-error.ts";
|
|
5
|
+
import { extractCloudflareResult } from "./api-response.ts";
|
|
5
6
|
import {
|
|
6
7
|
createCloudflareApi,
|
|
7
8
|
type CloudflareApi,
|
|
@@ -185,20 +186,16 @@ async function createEmptyWorker(
|
|
|
185
186
|
);
|
|
186
187
|
|
|
187
188
|
// Upload worker script
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
189
|
+
await extractCloudflareResult(
|
|
190
|
+
`create empty worker "${workerName}"`,
|
|
191
|
+
api.put(
|
|
192
|
+
`/accounts/${api.accountId}/workers/scripts/${workerName}`,
|
|
193
|
+
formData,
|
|
194
|
+
{
|
|
195
|
+
headers: {
|
|
196
|
+
"Content-Type": "multipart/form-data",
|
|
197
|
+
},
|
|
194
198
|
},
|
|
195
|
-
|
|
199
|
+
),
|
|
196
200
|
);
|
|
197
|
-
|
|
198
|
-
// Check if the upload was successful
|
|
199
|
-
if (!uploadResponse.ok) {
|
|
200
|
-
throw new Error(
|
|
201
|
-
`Failed to create empty worker: ${uploadResponse.status} ${uploadResponse.statusText}`,
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
201
|
}
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
1
|
import { isDeepStrictEqual } from "node:util";
|
|
4
2
|
import path from "pathe";
|
|
5
3
|
import type { Context } from "../context.ts";
|
|
6
4
|
import type { BundleProps } from "../esbuild/bundle.ts";
|
|
7
5
|
import { Resource, ResourceKind } from "../resource.ts";
|
|
8
|
-
import { isSecret } from "../secret.ts";
|
|
9
6
|
import type { type } from "../type.ts";
|
|
10
7
|
import { DeferredPromise } from "../util/deferred-promise.ts";
|
|
11
|
-
import { exists } from "../util/exists.ts";
|
|
12
8
|
import { logger } from "../util/logger.ts";
|
|
13
9
|
import { withExponentialBackoff } from "../util/retry.ts";
|
|
14
10
|
import { CloudflareApiError, handleApiError } from "./api-error.ts";
|
|
@@ -331,15 +327,10 @@ export interface BaseWorkerProps<
|
|
|
331
327
|
* @default false
|
|
332
328
|
*/
|
|
333
329
|
remote?: boolean;
|
|
334
|
-
|
|
335
|
-
command?: undefined;
|
|
330
|
+
url?: undefined;
|
|
336
331
|
}
|
|
337
332
|
| {
|
|
338
|
-
|
|
339
|
-
cwd?: string;
|
|
340
|
-
/** @internal */
|
|
341
|
-
port?: undefined;
|
|
342
|
-
/** @internal */
|
|
333
|
+
url: string;
|
|
343
334
|
remote?: undefined;
|
|
344
335
|
};
|
|
345
336
|
|
|
@@ -740,8 +731,7 @@ const _Worker = Resource(
|
|
|
740
731
|
compatibilityDate,
|
|
741
732
|
compatibilityFlags,
|
|
742
733
|
outdir:
|
|
743
|
-
props.bundle?.outdir ??
|
|
744
|
-
path.join(cwd, ".alchemy", ...this.scope.chain, id),
|
|
734
|
+
props.bundle?.outdir ?? path.join(cwd, ".alchemy", "out", workerName),
|
|
745
735
|
sourceMap: "sourceMap" in props ? props.sourceMap : undefined,
|
|
746
736
|
});
|
|
747
737
|
|
|
@@ -755,30 +745,11 @@ const _Worker = Resource(
|
|
|
755
745
|
throw bundleSourceResult.error;
|
|
756
746
|
}
|
|
757
747
|
|
|
758
|
-
if (props.dev
|
|
759
|
-
|
|
760
|
-
id,
|
|
761
|
-
command: props.dev.command,
|
|
762
|
-
cwd: props.dev.cwd || props.cwd || process.cwd(),
|
|
763
|
-
env: {
|
|
764
|
-
...(process.env ?? {}),
|
|
765
|
-
...props.env,
|
|
766
|
-
...Object.fromEntries(
|
|
767
|
-
Object.entries(props.bindings ?? {}).flatMap(([key, value]) =>
|
|
768
|
-
typeof value === "string"
|
|
769
|
-
? [[key, value]]
|
|
770
|
-
: isSecret(value)
|
|
771
|
-
? [[key, value.unencrypted]]
|
|
772
|
-
: [],
|
|
773
|
-
),
|
|
774
|
-
),
|
|
775
|
-
},
|
|
776
|
-
});
|
|
777
|
-
url = result.url;
|
|
778
|
-
this.onCleanup(() => result.cleanup());
|
|
748
|
+
if (props.dev && "url" in props.dev) {
|
|
749
|
+
url = props.dev.url;
|
|
779
750
|
} else {
|
|
780
751
|
const { MiniflareController } = await import(
|
|
781
|
-
"./miniflare/miniflare-controller.
|
|
752
|
+
"./miniflare/miniflare-controller.js"
|
|
782
753
|
);
|
|
783
754
|
const controller = MiniflareController.singleton;
|
|
784
755
|
url = await controller.add({
|
|
@@ -790,7 +761,7 @@ const _Worker = Resource(
|
|
|
790
761
|
eventSources: props.eventSources,
|
|
791
762
|
assets: props.assets,
|
|
792
763
|
bundle: bundleSourceResult.value,
|
|
793
|
-
port: props.dev?.port,
|
|
764
|
+
port: props.dev?.port ?? undefined,
|
|
794
765
|
});
|
|
795
766
|
this.onCleanup(() => controller.dispose());
|
|
796
767
|
}
|
|
@@ -849,7 +820,7 @@ const _Worker = Resource(
|
|
|
849
820
|
const oldName = this.output.name ?? this.output.id;
|
|
850
821
|
const newName = workerName;
|
|
851
822
|
|
|
852
|
-
if (oldName !== newName) {
|
|
823
|
+
if (oldName && oldName !== newName) {
|
|
853
824
|
if (dispatchNamespace) {
|
|
854
825
|
this.replace(true);
|
|
855
826
|
} else {
|
|
@@ -1319,124 +1290,6 @@ async function provisionSubdomain(
|
|
|
1319
1290
|
}
|
|
1320
1291
|
}
|
|
1321
1292
|
|
|
1322
|
-
async function createDevCommand(props: {
|
|
1323
|
-
id: string;
|
|
1324
|
-
command: string;
|
|
1325
|
-
cwd: string;
|
|
1326
|
-
env: Record<string, string | undefined>;
|
|
1327
|
-
}) {
|
|
1328
|
-
const persistFile = path.join(process.cwd(), ".alchemy", `${props.id}.pid`);
|
|
1329
|
-
if (await exists(persistFile)) {
|
|
1330
|
-
const pid = Number.parseInt(await fs.readFile(persistFile, "utf8"));
|
|
1331
|
-
try {
|
|
1332
|
-
// Actually kill the process if it's alive
|
|
1333
|
-
process.kill(pid, "SIGTERM");
|
|
1334
|
-
} catch {
|
|
1335
|
-
// ignore
|
|
1336
|
-
}
|
|
1337
|
-
try {
|
|
1338
|
-
await fs.unlink(persistFile);
|
|
1339
|
-
} catch {
|
|
1340
|
-
// ignore
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
const command = props.command.split(" ");
|
|
1344
|
-
const [cmd, ...args] = command;
|
|
1345
|
-
|
|
1346
|
-
const promise = new DeferredPromise<string>();
|
|
1347
|
-
const childProcess = spawn(cmd, args, {
|
|
1348
|
-
cwd: props.cwd,
|
|
1349
|
-
shell: true,
|
|
1350
|
-
env: {
|
|
1351
|
-
...process.env,
|
|
1352
|
-
...props.env,
|
|
1353
|
-
ALCHEMY_CLOUDFLARE_PERSIST_PATH: path.join(
|
|
1354
|
-
process.cwd(),
|
|
1355
|
-
".alchemy",
|
|
1356
|
-
"miniflare",
|
|
1357
|
-
),
|
|
1358
|
-
// Force colors in the child process since we're piping output
|
|
1359
|
-
// FORCE_COLOR: "1",
|
|
1360
|
-
},
|
|
1361
|
-
stdio: ["inherit", "pipe", "pipe"],
|
|
1362
|
-
});
|
|
1363
|
-
|
|
1364
|
-
// Clean up the pid file when the process exits
|
|
1365
|
-
childProcess.once("exit", async () => {
|
|
1366
|
-
try {
|
|
1367
|
-
await fs.unlink(persistFile);
|
|
1368
|
-
} catch {
|
|
1369
|
-
// ignore
|
|
1370
|
-
}
|
|
1371
|
-
});
|
|
1372
|
-
|
|
1373
|
-
let urlFound = false;
|
|
1374
|
-
let stdout = "";
|
|
1375
|
-
let stderr = "";
|
|
1376
|
-
const urlRegex =
|
|
1377
|
-
/http:\/\/(?:(?:localhost|0\.0\.0\.0|127\.0\.0\.1)|(?:\d{1,3}\.){3}\d{1,3}):\d+(?:\/)?/;
|
|
1378
|
-
|
|
1379
|
-
const parseOutput = (data: string) => {
|
|
1380
|
-
if (!urlFound) {
|
|
1381
|
-
const match = data.match(urlRegex);
|
|
1382
|
-
if (match) {
|
|
1383
|
-
urlFound = true;
|
|
1384
|
-
promise.resolve(match[0]);
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
};
|
|
1388
|
-
|
|
1389
|
-
// Handle stdout - parse for URL and write through with colors preserved
|
|
1390
|
-
childProcess.stdout?.on("data", (data) => {
|
|
1391
|
-
parseOutput(
|
|
1392
|
-
(stdout += data.toString().replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "")),
|
|
1393
|
-
);
|
|
1394
|
-
process.stdout.write(data);
|
|
1395
|
-
});
|
|
1396
|
-
|
|
1397
|
-
childProcess.stderr?.on("data", (data) => {
|
|
1398
|
-
parseOutput(
|
|
1399
|
-
(stderr += data.toString().replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "")),
|
|
1400
|
-
);
|
|
1401
|
-
process.stderr.write(data);
|
|
1402
|
-
});
|
|
1403
|
-
|
|
1404
|
-
childProcess.on("error", (error) => {
|
|
1405
|
-
promise.reject(error);
|
|
1406
|
-
});
|
|
1407
|
-
if (childProcess.pid) {
|
|
1408
|
-
await fs.mkdir(path.dirname(persistFile), { recursive: true });
|
|
1409
|
-
await fs.writeFile(persistFile, childProcess.pid.toString());
|
|
1410
|
-
}
|
|
1411
|
-
return {
|
|
1412
|
-
url: await promise.value,
|
|
1413
|
-
cleanup: async () => {
|
|
1414
|
-
try {
|
|
1415
|
-
await fs.unlink(persistFile);
|
|
1416
|
-
} catch {
|
|
1417
|
-
// ignore
|
|
1418
|
-
}
|
|
1419
|
-
if (!childProcess.killed) {
|
|
1420
|
-
childProcess.kill("SIGTERM");
|
|
1421
|
-
// Give it time to exit gracefully
|
|
1422
|
-
await new Promise<void>((resolve) => {
|
|
1423
|
-
const timeout = setTimeout(() => {
|
|
1424
|
-
if (!childProcess.killed) {
|
|
1425
|
-
childProcess.kill("SIGKILL");
|
|
1426
|
-
}
|
|
1427
|
-
resolve();
|
|
1428
|
-
}, 5000);
|
|
1429
|
-
|
|
1430
|
-
childProcess.once("exit", () => {
|
|
1431
|
-
clearTimeout(timeout);
|
|
1432
|
-
resolve();
|
|
1433
|
-
});
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
},
|
|
1437
|
-
};
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
1293
|
type PutWorkerOptions = Omit<WorkerProps, "entrypoint"> & {
|
|
1441
1294
|
dispatchNamespace?: string;
|
|
1442
1295
|
migrationTag?: string;
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import type { Context } from "../context.ts";
|
|
4
4
|
import { formatJson } from "../fs/static-json-file.ts";
|
|
5
5
|
import { Resource } from "../resource.ts";
|
|
6
|
+
import { isSecret } from "../secret.ts";
|
|
6
7
|
import { assertNever } from "../util/assert-never.ts";
|
|
7
8
|
import {
|
|
8
9
|
Self,
|
|
@@ -56,6 +57,13 @@ export interface WranglerJsonProps {
|
|
|
56
57
|
directory: string;
|
|
57
58
|
};
|
|
58
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Whether to include secrets in the wrangler.json file
|
|
62
|
+
*
|
|
63
|
+
* @default true
|
|
64
|
+
*/
|
|
65
|
+
secrets?: boolean;
|
|
66
|
+
|
|
59
67
|
/**
|
|
60
68
|
* Transform hooks to modify generated configuration files
|
|
61
69
|
*/
|
|
@@ -169,6 +177,7 @@ export const WranglerJson = Resource(
|
|
|
169
177
|
worker.eventSources,
|
|
170
178
|
worker.name,
|
|
171
179
|
cwd,
|
|
180
|
+
props.secrets ?? false,
|
|
172
181
|
);
|
|
173
182
|
}
|
|
174
183
|
|
|
@@ -191,7 +200,24 @@ export const WranglerJson = Resource(
|
|
|
191
200
|
: spec;
|
|
192
201
|
|
|
193
202
|
await fs.mkdir(dirname, { recursive: true });
|
|
194
|
-
|
|
203
|
+
if (props.secrets) {
|
|
204
|
+
// If secrets are enabled, decrypt them in the wrangler.json file,
|
|
205
|
+
// but do not modify `finalSpec` so that way secrets aren't written to state unencrypted.
|
|
206
|
+
const withSecretsUnwrapped = {
|
|
207
|
+
...finalSpec,
|
|
208
|
+
vars: {
|
|
209
|
+
...finalSpec.vars,
|
|
210
|
+
...Object.fromEntries(
|
|
211
|
+
Object.entries(finalSpec.vars ?? {}).map(([key, value]) =>
|
|
212
|
+
isSecret(value) ? [key, value.unencrypted] : [key, value],
|
|
213
|
+
),
|
|
214
|
+
),
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
await fs.writeFile(filePath, await formatJson(withSecretsUnwrapped));
|
|
218
|
+
} else {
|
|
219
|
+
await fs.writeFile(filePath, await formatJson(finalSpec));
|
|
220
|
+
}
|
|
195
221
|
|
|
196
222
|
// Return the resource
|
|
197
223
|
return this({
|
|
@@ -473,6 +499,7 @@ function processBindings(
|
|
|
473
499
|
eventSources: EventSource[] | undefined,
|
|
474
500
|
workerName: string,
|
|
475
501
|
workerCwd: string,
|
|
502
|
+
writeSecrets: boolean,
|
|
476
503
|
): void {
|
|
477
504
|
// Arrays to collect different binding types
|
|
478
505
|
const kvNamespaces: {
|
|
@@ -578,10 +605,11 @@ function processBindings(
|
|
|
578
605
|
}
|
|
579
606
|
if (typeof binding === "string") {
|
|
580
607
|
// Plain text binding - add to vars
|
|
581
|
-
|
|
582
|
-
spec.vars = {};
|
|
583
|
-
}
|
|
608
|
+
spec.vars ??= {};
|
|
584
609
|
spec.vars[bindingName] = binding;
|
|
610
|
+
} else if (writeSecrets && isSecret(binding)) {
|
|
611
|
+
spec.vars ??= {};
|
|
612
|
+
spec.vars[bindingName] = binding as any;
|
|
585
613
|
} else if (binding === Self) {
|
|
586
614
|
// Self(service) binding
|
|
587
615
|
services.push({
|
package/src/env.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface Env {
|
|
2
|
-
[key: string]:
|
|
3
|
-
<T = string>(name: string, value?: T | undefined, error?: string):
|
|
2
|
+
[key: string]: string;
|
|
3
|
+
<T = string>(name: string, value?: T | undefined, error?: string): T;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
export const env = new Proxy(_env, {
|
|
@@ -8,22 +8,21 @@ export const env = new Proxy(_env, {
|
|
|
8
8
|
apply: (_, __, args: [string, any?, string?]) => _env(...args),
|
|
9
9
|
}) as Env;
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
function _env<T = string>(
|
|
12
12
|
name: string,
|
|
13
13
|
value?: T | undefined,
|
|
14
14
|
error?: string,
|
|
15
|
-
):
|
|
15
|
+
): T {
|
|
16
16
|
if (value !== undefined) {
|
|
17
17
|
return value;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return env[name] as T;
|
|
19
|
+
if (name in environment) {
|
|
20
|
+
return environment[name] as T;
|
|
22
21
|
}
|
|
23
22
|
throw new Error(error ?? `Environment variable ${name} is not set`);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
const environment = await (async (): Promise<Record<string, any>> => {
|
|
27
26
|
if (typeof process !== "undefined") {
|
|
28
27
|
return process.env;
|
|
29
28
|
}
|
|
@@ -35,4 +34,4 @@ async function resolveEnv(): Promise<Record<string, any>> {
|
|
|
35
34
|
return import.meta.env;
|
|
36
35
|
}
|
|
37
36
|
throw new Error("No environment found");
|
|
38
|
-
}
|
|
37
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./random-string.ts";
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { alchemy } from "../alchemy.ts";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import type { Secret } from "../secret.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Properties for configuring a random string generation
|
|
7
|
+
*/
|
|
8
|
+
export interface RandomStringProps {
|
|
9
|
+
/**
|
|
10
|
+
* The number of random bytes to generate.
|
|
11
|
+
* The actual string length will depend on the encoding:
|
|
12
|
+
* - hex: length * 2 characters
|
|
13
|
+
* - base64: approximately length * 1.33 characters
|
|
14
|
+
* @default 32
|
|
15
|
+
*/
|
|
16
|
+
length?: number;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The encoding format for the random string.
|
|
20
|
+
* - "hex": Hexadecimal encoding (0-9, a-f)
|
|
21
|
+
* - "base64": Base64 encoding (A-Z, a-z, 0-9, +, /)
|
|
22
|
+
* @default "hex"
|
|
23
|
+
*/
|
|
24
|
+
encoding?: "hex" | "base64";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A cryptographically secure random string resource
|
|
29
|
+
*/
|
|
30
|
+
export interface RandomString extends Resource<"random::String"> {
|
|
31
|
+
/**
|
|
32
|
+
* The generated random string value, stored as a secret
|
|
33
|
+
*/
|
|
34
|
+
value: Secret;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The length of the random string
|
|
38
|
+
*/
|
|
39
|
+
length: number;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The encoding format of the random string
|
|
43
|
+
*/
|
|
44
|
+
encoding: "hex" | "base64";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generates a cryptographically secure random string that can be used
|
|
49
|
+
* for API keys, tokens, passwords, or other security-sensitive values.
|
|
50
|
+
* The generated value is automatically wrapped as a secret to prevent
|
|
51
|
+
* accidental exposure in logs or console output.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Generate a default random string (32 bytes, hex encoded)
|
|
55
|
+
* const apiKey = await RandomString("api-key");
|
|
56
|
+
* // Result: 64 character hex string (e.g., "a1b2c3d4...")
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Generate a shorter random string for a verification code
|
|
60
|
+
* const verificationCode = await RandomString("email-verification", {
|
|
61
|
+
* length: 8,
|
|
62
|
+
* encoding: "hex"
|
|
63
|
+
* });
|
|
64
|
+
* // Result: 16 character hex string
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Generate a base64-encoded random string for a session token
|
|
68
|
+
* const sessionToken = await RandomString("session-token", {
|
|
69
|
+
* length: 48,
|
|
70
|
+
* encoding: "base64"
|
|
71
|
+
* });
|
|
72
|
+
* // Result: ~64 character base64 string
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* // Use with other resources that require secrets
|
|
76
|
+
* const database = await PostgresDatabase("mydb", {
|
|
77
|
+
* name: "production",
|
|
78
|
+
* password: (await RandomString("db-password")).value
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // Generate multiple unique secrets
|
|
83
|
+
* const jwtSecret = await RandomString("jwt-secret", { length: 64 });
|
|
84
|
+
* const encryptionKey = await RandomString("encryption-key", {
|
|
85
|
+
* length: 32,
|
|
86
|
+
* encoding: "base64"
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* @param id - Unique identifier for this random string resource
|
|
90
|
+
* @param props - Configuration options for the random string generation
|
|
91
|
+
* @returns A RandomString resource containing the generated secret value
|
|
92
|
+
*/
|
|
93
|
+
export const RandomString = Resource(
|
|
94
|
+
"random::String",
|
|
95
|
+
async function (
|
|
96
|
+
_id: string,
|
|
97
|
+
props: RandomStringProps = {},
|
|
98
|
+
): Promise<RandomString> {
|
|
99
|
+
if (this.phase === "delete") {
|
|
100
|
+
return this.destroy();
|
|
101
|
+
}
|
|
102
|
+
const length = props.length ?? 32;
|
|
103
|
+
const encoding = props.encoding ?? "hex";
|
|
104
|
+
|
|
105
|
+
if (
|
|
106
|
+
this.phase === "update" &&
|
|
107
|
+
this.props.length === length &&
|
|
108
|
+
this.props.encoding === encoding
|
|
109
|
+
) {
|
|
110
|
+
// this is an update (input props changed)
|
|
111
|
+
// but the length and encoding did not change
|
|
112
|
+
// so, we can just return the existing output (no-op)
|
|
113
|
+
return this(this.output);
|
|
114
|
+
}
|
|
115
|
+
const crypto = await import("node:crypto");
|
|
116
|
+
return this({
|
|
117
|
+
length,
|
|
118
|
+
encoding,
|
|
119
|
+
value: alchemy.secret(
|
|
120
|
+
crypto
|
|
121
|
+
.randomBytes(props.length ?? 32)
|
|
122
|
+
.toString(props.encoding ?? "hex"),
|
|
123
|
+
),
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
);
|
package/src/runtime/bind.ts
CHANGED
|
@@ -10,8 +10,8 @@ import { isRuntime } from "./global.ts";
|
|
|
10
10
|
/**
|
|
11
11
|
* Get a Resource's Binding from the Environment.
|
|
12
12
|
*/
|
|
13
|
-
export function getBinding<T extends Resource>(resource: T):
|
|
14
|
-
return env[getBindKey(resource)] as
|
|
13
|
+
export function getBinding<T extends Resource>(resource: T): Bound<T> {
|
|
14
|
+
return env[getBindKey(resource)] as Bound<T>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function tryGetBinding<T extends Resource>(
|
package/src/scope.ts
CHANGED
|
@@ -100,8 +100,6 @@ export class Scope {
|
|
|
100
100
|
new AsyncLocalStorage<Scope>());
|
|
101
101
|
public static globals: Scope[] = (globalThis.__ALCHEMY_GLOBALS__ ??= []);
|
|
102
102
|
|
|
103
|
-
private static exitHandlerInstalled = false;
|
|
104
|
-
|
|
105
103
|
public static getScope(): Scope | undefined {
|
|
106
104
|
const scope = Scope.storage.getStore();
|
|
107
105
|
if (!scope) {
|
|
@@ -547,7 +545,7 @@ export class Scope {
|
|
|
547
545
|
* This should only be called on the root scope.
|
|
548
546
|
*/
|
|
549
547
|
public async cleanup() {
|
|
550
|
-
if (this.parent) return;
|
|
548
|
+
if (this.parent || this.cleanups.length === 0) return;
|
|
551
549
|
this.logger.log(kleur.gray("Exiting..."));
|
|
552
550
|
await Promise.allSettled(this.cleanups.map((cleanup) => cleanup()));
|
|
553
551
|
}
|
package/src/secret.ts
CHANGED
|
@@ -123,8 +123,8 @@ export function secret<S = string>(
|
|
|
123
123
|
|
|
124
124
|
export namespace secret {
|
|
125
125
|
export interface Env {
|
|
126
|
-
[key: string]:
|
|
127
|
-
(name: string, value?: string, error?: string):
|
|
126
|
+
[key: string]: Secret;
|
|
127
|
+
(name: string, value?: string, error?: string): Secret;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
export const env = new Proxy(_env, {
|
|
@@ -132,12 +132,8 @@ export namespace secret {
|
|
|
132
132
|
apply: (_, __, args: [string, any?, string?]) => _env(...args),
|
|
133
133
|
}) as Env;
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
name
|
|
137
|
-
value?: string,
|
|
138
|
-
error?: string,
|
|
139
|
-
): Promise<Secret> {
|
|
140
|
-
const result = await alchemy.env(name, value, error);
|
|
135
|
+
function _env(name: string, value?: string, error?: string): Secret {
|
|
136
|
+
const result = alchemy.env(name, value, error);
|
|
141
137
|
if (typeof result === "string") {
|
|
142
138
|
return secret(result, name);
|
|
143
139
|
}
|
|
@@ -105,11 +105,11 @@ const provision = memoize(
|
|
|
105
105
|
const scriptName = options.scriptName ?? "alchemy-state-service";
|
|
106
106
|
const token =
|
|
107
107
|
options.stateToken ??
|
|
108
|
-
|
|
108
|
+
alchemy.secret.env(
|
|
109
109
|
"ALCHEMY_STATE_TOKEN",
|
|
110
110
|
undefined,
|
|
111
111
|
"Missing token for DOStateStore. Please set ALCHEMY_STATE_TOKEN in the environment or set the `stateToken` option in the DOStateStore constructor.",
|
|
112
|
-
)
|
|
112
|
+
);
|
|
113
113
|
|
|
114
114
|
const api = await createCloudflareApi(options);
|
|
115
115
|
const [bundle, settings, subdomain] = await Promise.all([
|
|
@@ -66,7 +66,7 @@ export class DOFSStateStore implements StateStore {
|
|
|
66
66
|
private async createClient() {
|
|
67
67
|
const token =
|
|
68
68
|
this.options.worker?.token ??
|
|
69
|
-
|
|
69
|
+
alchemy.secret.env.ALCHEMY_STATE_TOKEN.unencrypted;
|
|
70
70
|
if (this.options.worker && "url" in this.options.worker) {
|
|
71
71
|
const client = new DOFSStateStoreClient({
|
|
72
72
|
app: this.scope.appName ?? "alchemy",
|
|
@@ -34,3 +34,14 @@ export async function detectPackageManager(
|
|
|
34
34
|
|
|
35
35
|
return "npm";
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
export async function getPackageManagerRunner(): Promise<string> {
|
|
39
|
+
const packageManager = await detectPackageManager();
|
|
40
|
+
return {
|
|
41
|
+
bun: "bun run",
|
|
42
|
+
pnpm: "pnpm",
|
|
43
|
+
yarn: "yarn",
|
|
44
|
+
npm: "npx",
|
|
45
|
+
deno: "deno run",
|
|
46
|
+
}[packageManager];
|
|
47
|
+
}
|