alchemy 0.56.0 → 0.57.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/bin/alchemy.js +14223 -14180
- package/bin/commands/create.ts +15 -17
- package/bin/commands/deploy.ts +3 -3
- package/bin/commands/destroy.ts +3 -3
- package/bin/commands/dev.ts +3 -4
- package/bin/commands/init.ts +9 -9
- package/bin/commands/login.ts +6 -6
- package/bin/commands/run.ts +3 -4
- package/bin/constants.ts +1 -1
- package/bin/services/execute-alchemy.ts +4 -6
- 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/assets.js +5 -4
- package/lib/cloudflare/assets.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 +44 -6
- package/src/apply.ts +3 -7
- package/src/cloudflare/assets.ts +7 -4
- 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/astro/package.json +1 -1
- package/templates/nuxt/alchemy.run.ts +1 -3
- package/templates/nuxt/nuxt.config.ts +4 -5
- package/templates/nuxt/package.json +1 -2
- 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 +1 -3
- package/templates/rwsdk/vite.config.mts +2 -2
- package/templates/sveltekit/alchemy.run.ts +1 -3
- package/templates/sveltekit/package.json +1 -1
- package/templates/sveltekit/svelte.config.js +2 -2
- package/templates/tanstack-start/package.json +1 -1
- package/templates/tanstack-start/vite.config.ts +2 -2
- package/templates/typescript/package.json +1 -1
- package/templates/vite/alchemy.run.ts +1 -1
- package/templates/vite/package.json +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
|
@@ -1,114 +1,110 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { once } from "node:events";
|
|
4
|
+
import fs from "node:fs/promises";
|
|
1
5
|
import path from "node:path";
|
|
2
6
|
import { alchemy } from "../alchemy.ts";
|
|
3
|
-
import { Exec } from "../os/
|
|
7
|
+
import { Exec } from "../os/index.ts";
|
|
4
8
|
import { Scope } from "../scope.ts";
|
|
5
|
-
import { isSecret } from "../secret.ts";
|
|
6
|
-
import {
|
|
9
|
+
import { isSecret, type Secret } from "../secret.ts";
|
|
10
|
+
import { dedent } from "../util/dedent.ts";
|
|
11
|
+
import { DeferredPromise } from "../util/deferred-promise.ts";
|
|
12
|
+
import { exists } from "../util/exists.ts";
|
|
13
|
+
import { logger } from "../util/logger.ts";
|
|
7
14
|
import { Assets } from "./assets.ts";
|
|
8
15
|
import type { Bindings } from "./bindings.ts";
|
|
9
16
|
import { DEFAULT_COMPATIBILITY_DATE } from "./compatibility-date.gen.ts";
|
|
10
|
-
import {
|
|
17
|
+
import { DEFAULT_PERSIST_PATH } from "./miniflare/paths.ts";
|
|
18
|
+
import { type AssetsConfig, Worker, type WorkerProps } from "./worker.ts";
|
|
11
19
|
import { WranglerJson, type WranglerJsonSpec } from "./wrangler.json.ts";
|
|
12
20
|
|
|
13
21
|
export interface WebsiteProps<B extends Bindings>
|
|
14
|
-
extends Omit<WorkerProps<B>, "
|
|
22
|
+
extends Omit<WorkerProps<B>, "assets" | "dev"> {
|
|
15
23
|
/**
|
|
16
|
-
*
|
|
24
|
+
* Configuration for the build command
|
|
17
25
|
*
|
|
18
|
-
* If
|
|
26
|
+
* If not provided, the build is assumed to have already happened.
|
|
19
27
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Additional environment variables to set when running the command
|
|
24
|
-
*/
|
|
25
|
-
commandEnv?: Record<string, string>;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Whether to memoize the command (only re-run if the command changes)
|
|
29
|
-
*
|
|
30
|
-
* When set to `true`, the command will only be re-executed if the command string changes.
|
|
31
|
-
*
|
|
32
|
-
* When set to an object with `patterns`, the command will be re-executed if either:
|
|
33
|
-
* 1. The command string changes, or
|
|
34
|
-
* 2. The contents of any files matching the glob patterns change
|
|
35
|
-
*
|
|
36
|
-
* ⚠️ **Important Note**: When using memoization with build commands, the build outputs
|
|
37
|
-
* will not be produced if the command is memoized. This is because the command is not
|
|
38
|
-
* actually executed when memoized. Consider disabling memoization in CI environments:
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* // Disable memoization in CI to ensure build outputs are always produced
|
|
42
|
-
* await Website("my-website", {
|
|
43
|
-
* command: "vite build",
|
|
44
|
-
* memoize: process.env.CI ? false : {
|
|
45
|
-
* patterns: ["./src/**"]
|
|
46
|
-
* }
|
|
47
|
-
* });
|
|
48
|
-
*
|
|
49
|
-
* @default false
|
|
50
|
-
*/
|
|
51
|
-
memoize?: boolean | { patterns: string[] };
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* The name of the worker
|
|
55
|
-
*
|
|
56
|
-
* @default id
|
|
57
|
-
*/
|
|
58
|
-
name?: string;
|
|
59
|
-
/**
|
|
60
|
-
* The entrypoint to your server
|
|
61
|
-
*
|
|
62
|
-
* @default - a simple server that serves static assets is generated
|
|
63
|
-
*/
|
|
64
|
-
main?: string;
|
|
65
|
-
/**
|
|
66
|
-
* The directory containing your static assets
|
|
67
|
-
*
|
|
68
|
-
* @default "./dist"
|
|
69
|
-
*/
|
|
70
|
-
assets?:
|
|
28
|
+
build?:
|
|
71
29
|
| string
|
|
72
|
-
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
30
|
+
| {
|
|
31
|
+
/**
|
|
32
|
+
* The command to run to build the site
|
|
33
|
+
*/
|
|
34
|
+
command: string;
|
|
35
|
+
/**
|
|
36
|
+
* Additional environment variables to set when running the build command
|
|
37
|
+
*/
|
|
38
|
+
env?: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to memoize the command (only re-run if the command changes)
|
|
41
|
+
*
|
|
42
|
+
* When set to `true`, the command will only be re-executed if the command string changes.
|
|
43
|
+
*
|
|
44
|
+
* When set to an object with `patterns`, the command will be re-executed if either:
|
|
45
|
+
* 1. The command string changes, or
|
|
46
|
+
* 2. The contents of any files matching the glob patterns change
|
|
47
|
+
*
|
|
48
|
+
* ⚠️ **Important Note**: When using memoization with build commands, the build outputs
|
|
49
|
+
* will not be produced if the command is memoized. This is because the command is not
|
|
50
|
+
* actually executed when memoized. Consider disabling memoization in CI environments:
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Disable memoization in CI to ensure build outputs are always produced
|
|
54
|
+
* await Website("my-website", {
|
|
55
|
+
* command: "vite build",
|
|
56
|
+
* memoize: process.env.CI ? false : {
|
|
57
|
+
* patterns: ["./src/**"]
|
|
58
|
+
* }
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
memoize?: boolean | { patterns: string[] };
|
|
64
|
+
};
|
|
80
65
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* @default - no wrangler.jsonc file is written
|
|
66
|
+
* Configuration for the dev command
|
|
84
67
|
*/
|
|
85
|
-
|
|
86
|
-
| boolean
|
|
68
|
+
dev?:
|
|
87
69
|
| string
|
|
88
70
|
| {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The command to run to start the dev server
|
|
73
|
+
*/
|
|
74
|
+
command: string;
|
|
75
|
+
/**
|
|
76
|
+
* Additional environment variables to set when running the dev command
|
|
77
|
+
*/
|
|
78
|
+
env?: Record<string, string>;
|
|
92
79
|
};
|
|
93
|
-
|
|
80
|
+
/**
|
|
81
|
+
* The directory containing static assets
|
|
82
|
+
*
|
|
83
|
+
* @default dist
|
|
84
|
+
*/
|
|
85
|
+
assets?: string | ({ directory?: string } & AssetsConfig);
|
|
94
86
|
/**
|
|
95
87
|
* Configures default routing to support client-side routing for Single Page Applications (SPA)
|
|
96
88
|
*
|
|
97
89
|
* @default false
|
|
98
90
|
*/
|
|
99
91
|
spa?: boolean;
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Configure the command to use in development mode
|
|
103
|
-
*/
|
|
104
|
-
dev?: {
|
|
105
|
-
command: string;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
92
|
/**
|
|
109
|
-
*
|
|
93
|
+
* Configuration for the wrangler.json file
|
|
110
94
|
*/
|
|
111
|
-
|
|
95
|
+
wrangler?: {
|
|
96
|
+
/**
|
|
97
|
+
* Path to the wrangler.json file
|
|
98
|
+
*
|
|
99
|
+
* @default .alchemy/local/wrangler.jsonc
|
|
100
|
+
*/
|
|
101
|
+
path?: string;
|
|
102
|
+
/**
|
|
103
|
+
* The main entry point for the worker
|
|
104
|
+
*
|
|
105
|
+
* @default worker.entrypoint
|
|
106
|
+
*/
|
|
107
|
+
main?: string;
|
|
112
108
|
/**
|
|
113
109
|
* Hook to modify the wrangler.json object before it's written
|
|
114
110
|
*
|
|
@@ -119,20 +115,33 @@ export interface WebsiteProps<B extends Bindings>
|
|
|
119
115
|
* @param spec - The generated wrangler.json specification
|
|
120
116
|
* @returns The modified wrangler.json specification
|
|
121
117
|
*/
|
|
122
|
-
|
|
118
|
+
transform?: (
|
|
123
119
|
spec: WranglerJsonSpec,
|
|
124
120
|
) => WranglerJsonSpec | Promise<WranglerJsonSpec>;
|
|
121
|
+
/**
|
|
122
|
+
* Whether to include secrets in the wrangler.json file
|
|
123
|
+
*
|
|
124
|
+
* @default true if no path is specified, false otherwise
|
|
125
|
+
*/
|
|
126
|
+
secrets?: boolean;
|
|
125
127
|
};
|
|
126
|
-
}
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
129
|
+
/**
|
|
130
|
+
* The command to run to build the site.
|
|
131
|
+
* @deprecated Use `build` or `build.command` instead
|
|
132
|
+
*/
|
|
133
|
+
command?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Additional environment variables to set when running the build command.
|
|
136
|
+
* @deprecated Use `build.env` instead
|
|
137
|
+
*/
|
|
138
|
+
commandEnv?: Record<string, string>;
|
|
139
|
+
/**
|
|
140
|
+
* Whether to memoize the command (only re-run if the command changes)
|
|
141
|
+
* @deprecated Use `build.memoize` instead
|
|
142
|
+
*/
|
|
143
|
+
memoize?: boolean | { patterns: string[] };
|
|
144
|
+
}
|
|
136
145
|
|
|
137
146
|
export type Website<B extends Bindings> = B extends { ASSETS: any }
|
|
138
147
|
? never
|
|
@@ -141,128 +150,294 @@ export type Website<B extends Bindings> = B extends { ASSETS: any }
|
|
|
141
150
|
export async function Website<B extends Bindings>(
|
|
142
151
|
id: string,
|
|
143
152
|
props: WebsiteProps<B>,
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
) {
|
|
154
|
+
const {
|
|
155
|
+
name = id,
|
|
156
|
+
build: buildProps,
|
|
157
|
+
assets,
|
|
158
|
+
dev,
|
|
159
|
+
script,
|
|
160
|
+
spa = true,
|
|
161
|
+
command,
|
|
162
|
+
commandEnv,
|
|
163
|
+
memoize,
|
|
164
|
+
...workerProps
|
|
165
|
+
} = props;
|
|
166
|
+
|
|
167
|
+
assert(
|
|
168
|
+
!workerProps.bindings?.ASSETS,
|
|
169
|
+
"ASSETS binding is reserved for internal use",
|
|
170
|
+
);
|
|
171
|
+
if (command) {
|
|
172
|
+
logger.warnOnce(
|
|
173
|
+
"[website] The `command` prop is deprecated. Use `build.command` instead.",
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
if (commandEnv) {
|
|
177
|
+
logger.warnOnce(
|
|
178
|
+
"[website] The `commandEnv` prop is deprecated. Use `build.env` instead.",
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (memoize) {
|
|
182
|
+
logger.warnOnce(
|
|
183
|
+
"[website] The `memoize` prop is deprecated. Use `build.memoize` instead.",
|
|
184
|
+
);
|
|
147
185
|
}
|
|
148
|
-
const wrangler = props.wrangler ?? true;
|
|
149
186
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
187
|
+
const build = (() => {
|
|
188
|
+
if (typeof buildProps === "string") {
|
|
189
|
+
return { command: buildProps, env: commandEnv, memoize };
|
|
190
|
+
}
|
|
191
|
+
if (buildProps) {
|
|
192
|
+
return buildProps;
|
|
193
|
+
}
|
|
194
|
+
if (command) {
|
|
195
|
+
return {
|
|
196
|
+
command,
|
|
197
|
+
env: commandEnv,
|
|
198
|
+
memoize,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return undefined;
|
|
202
|
+
})();
|
|
203
|
+
const paths = (() => {
|
|
204
|
+
const cwd = props.cwd ?? process.cwd();
|
|
205
|
+
return {
|
|
206
|
+
cwd,
|
|
207
|
+
assets: path.resolve(
|
|
208
|
+
cwd,
|
|
209
|
+
typeof assets === "string" ? assets : (assets?.directory ?? "dist"),
|
|
210
|
+
),
|
|
211
|
+
local: path.resolve(cwd, ".alchemy/local"),
|
|
212
|
+
entrypoint: path.resolve(
|
|
213
|
+
cwd,
|
|
214
|
+
props.entrypoint ?? ".alchemy/local/worker.js",
|
|
215
|
+
),
|
|
216
|
+
get wrangler() {
|
|
217
|
+
return {
|
|
218
|
+
path: path.resolve(
|
|
219
|
+
cwd,
|
|
220
|
+
props.wrangler?.path ?? ".alchemy/local/wrangler.jsonc",
|
|
221
|
+
),
|
|
222
|
+
main: props.wrangler?.main
|
|
223
|
+
? path.resolve(cwd, props.wrangler.main)
|
|
224
|
+
: this.entrypoint,
|
|
225
|
+
};
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
})();
|
|
229
|
+
const secrets = props.wrangler?.secrets ?? !props.wrangler?.path;
|
|
230
|
+
const env = {
|
|
231
|
+
...(process.env ?? {}),
|
|
232
|
+
...(props.env ?? {}),
|
|
233
|
+
...Object.fromEntries(
|
|
234
|
+
Object.entries(props.bindings ?? {}).flatMap(([key, value]) => {
|
|
235
|
+
if (typeof value === "string" || (isSecret(value) && secrets)) {
|
|
236
|
+
return [[key, value]];
|
|
237
|
+
}
|
|
238
|
+
return [];
|
|
239
|
+
}),
|
|
240
|
+
),
|
|
241
|
+
};
|
|
242
|
+
const worker = {
|
|
243
|
+
...workerProps,
|
|
244
|
+
name,
|
|
245
|
+
cwd: path.relative(process.cwd(), paths.cwd),
|
|
246
|
+
compatibilityDate:
|
|
247
|
+
workerProps.compatibilityDate ?? DEFAULT_COMPATIBILITY_DATE,
|
|
248
|
+
assets: {
|
|
249
|
+
html_handling: "auto-trailing-slash",
|
|
250
|
+
not_found_handling: spa ? "single-page-application" : "none",
|
|
251
|
+
run_worker_first: false,
|
|
252
|
+
...(typeof props.assets === "string" ? {} : props.assets),
|
|
154
253
|
},
|
|
155
|
-
|
|
156
|
-
|
|
254
|
+
entrypoint: path.relative(paths.cwd, paths.entrypoint),
|
|
255
|
+
} as WorkerProps<B> & { name: string };
|
|
157
256
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
257
|
+
return await alchemy.run(id, { parent: Scope.current }, async (scope) => {
|
|
258
|
+
if (!workerProps.entrypoint) {
|
|
259
|
+
await fs.mkdir(path.dirname(paths.entrypoint), { recursive: true });
|
|
260
|
+
const content =
|
|
261
|
+
script ??
|
|
262
|
+
dedent`
|
|
263
|
+
export default {
|
|
264
|
+
async fetch(request, env) {
|
|
265
|
+
return new Response("Not Found", { status: 404 });
|
|
266
|
+
},
|
|
267
|
+
};`;
|
|
268
|
+
await fs.writeFile(paths.entrypoint, content);
|
|
269
|
+
}
|
|
163
270
|
|
|
164
|
-
|
|
165
|
-
const assetsDirPath = resolveAbsPath(
|
|
166
|
-
typeof props.assets === "string"
|
|
167
|
-
? props.assets
|
|
168
|
-
: (props.assets?.dist ?? "dist"),
|
|
169
|
-
);
|
|
170
|
-
const wranglerJsonPath = resolveAbsPath(
|
|
171
|
-
typeof wrangler === "boolean"
|
|
172
|
-
? "wrangler.jsonc"
|
|
173
|
-
: typeof wrangler === "string"
|
|
174
|
-
? wrangler
|
|
175
|
-
: (wrangler?.path ?? "wrangler.jsonc"),
|
|
176
|
-
);
|
|
271
|
+
await writeMiniflareSymlink(paths.cwd);
|
|
177
272
|
|
|
178
|
-
|
|
273
|
+
await WranglerJson("wrangler.jsonc", {
|
|
274
|
+
path: path.relative(paths.cwd, paths.wrangler.path),
|
|
275
|
+
worker,
|
|
276
|
+
assets: {
|
|
277
|
+
binding: "ASSETS",
|
|
278
|
+
directory: path.relative(paths.cwd, paths.assets),
|
|
279
|
+
},
|
|
280
|
+
main: path.relative(paths.cwd, paths.wrangler.main),
|
|
281
|
+
secrets,
|
|
282
|
+
transform: {
|
|
283
|
+
wrangler: props.wrangler?.transform,
|
|
284
|
+
},
|
|
285
|
+
});
|
|
179
286
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
html_handling: "auto-trailing-slash",
|
|
189
|
-
not_found_handling: props.spa ? "single-page-application" : "none",
|
|
190
|
-
run_worker_first: false,
|
|
191
|
-
...(typeof props.assets === "string" ? {} : props.assets),
|
|
287
|
+
if (build && !scope.local) {
|
|
288
|
+
await Exec("build", {
|
|
289
|
+
cwd: path.relative(process.cwd(), paths.cwd),
|
|
290
|
+
command: build.command,
|
|
291
|
+
env: {
|
|
292
|
+
...env,
|
|
293
|
+
...(typeof build === "object" ? build.env : {}),
|
|
294
|
+
NODE_ENV: "production",
|
|
192
295
|
},
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
296
|
+
memoize: typeof build === "object" ? build.memoize : undefined,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let url: string | undefined;
|
|
301
|
+
if (dev && scope.local) {
|
|
302
|
+
url = await runDevCommand(scope, {
|
|
303
|
+
id,
|
|
304
|
+
command: typeof dev === "string" ? dev : dev.command,
|
|
305
|
+
env: {
|
|
306
|
+
...env,
|
|
307
|
+
...(typeof dev === "object" ? dev.env : {}),
|
|
205
308
|
},
|
|
206
|
-
|
|
309
|
+
cwd: paths.cwd,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
207
312
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
313
|
+
return (await Worker("worker", {
|
|
314
|
+
...worker,
|
|
315
|
+
bindings: {
|
|
316
|
+
...worker.bindings,
|
|
317
|
+
...(!scope.local
|
|
318
|
+
? {
|
|
319
|
+
ASSETS: await Assets("assets", {
|
|
320
|
+
path: path.relative(process.cwd(), paths.assets),
|
|
321
|
+
}),
|
|
322
|
+
}
|
|
323
|
+
: {}),
|
|
324
|
+
},
|
|
325
|
+
dev: url ? { url } : undefined,
|
|
326
|
+
})) as Website<B>;
|
|
327
|
+
});
|
|
328
|
+
}
|
|
211
329
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
// @ts-expect-error - props.wrangler can be string | object, this is fine
|
|
216
|
-
main: props.wrangler?.main ?? props.main,
|
|
217
|
-
// hard-code the assets directory because we haven't yet included the assets binding
|
|
218
|
-
assets: {
|
|
219
|
-
binding: "ASSETS",
|
|
220
|
-
// path must be relative to the wrangler.jsonc file
|
|
221
|
-
directory: path.relative(wranglerAbsDir, assetsDirPath),
|
|
222
|
-
},
|
|
223
|
-
transform: props.transform,
|
|
224
|
-
});
|
|
225
|
-
}
|
|
330
|
+
async function writeMiniflareSymlink(cwd: string) {
|
|
331
|
+
const target = path.resolve(DEFAULT_PERSIST_PATH);
|
|
332
|
+
await fs.mkdir(target, { recursive: true });
|
|
226
333
|
|
|
227
|
-
|
|
334
|
+
if (cwd === process.cwd()) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
228
337
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
...Object.fromEntries(
|
|
238
|
-
Object.entries(props.bindings ?? {}).flatMap(([key, value]) => {
|
|
239
|
-
if (isSecret(value)) {
|
|
240
|
-
return [[key, value.unencrypted]];
|
|
241
|
-
} else if (typeof value === "string") {
|
|
242
|
-
return [[key, value]];
|
|
243
|
-
}
|
|
244
|
-
return [];
|
|
245
|
-
}),
|
|
246
|
-
),
|
|
247
|
-
},
|
|
248
|
-
memoize: props.memoize,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
338
|
+
const persistPath = path.resolve(cwd, DEFAULT_PERSIST_PATH);
|
|
339
|
+
await fs.mkdir(path.dirname(persistPath), { recursive: true });
|
|
340
|
+
await fs.symlink(target, persistPath).catch((e) => {
|
|
341
|
+
if (e.code !== "EEXIST") {
|
|
342
|
+
throw e;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
251
346
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
347
|
+
async function runDevCommand(
|
|
348
|
+
scope: Scope,
|
|
349
|
+
props: {
|
|
350
|
+
id: string;
|
|
351
|
+
command: string;
|
|
352
|
+
env: Record<string, string | Secret<string> | undefined>;
|
|
353
|
+
cwd?: string;
|
|
354
|
+
},
|
|
355
|
+
) {
|
|
356
|
+
const persistFile = path.join(process.cwd(), ".alchemy", `${props.id}.pid`);
|
|
357
|
+
if (await exists(persistFile)) {
|
|
358
|
+
const pid = Number.parseInt(await fs.readFile(persistFile, "utf8"));
|
|
359
|
+
try {
|
|
360
|
+
// Actually kill the process if it's alive
|
|
361
|
+
process.kill(pid, "SIGTERM");
|
|
362
|
+
} catch {
|
|
363
|
+
// ignore
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
await fs.unlink(persistFile);
|
|
367
|
+
} catch {
|
|
368
|
+
// ignore
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const command = props.command.split(" ");
|
|
372
|
+
const [cmd, ...args] = command;
|
|
373
|
+
|
|
374
|
+
const childProcess = spawn(cmd, args, {
|
|
375
|
+
cwd: props.cwd,
|
|
376
|
+
shell: true,
|
|
377
|
+
env: {
|
|
378
|
+
FORCE_COLOR: "1",
|
|
379
|
+
...process.env,
|
|
380
|
+
...Object.fromEntries(
|
|
381
|
+
Object.entries(props.env ?? {}).flatMap(([key, value]) => {
|
|
382
|
+
if (isSecret(value)) {
|
|
383
|
+
return [[key, value.unencrypted]];
|
|
384
|
+
}
|
|
385
|
+
if (typeof value === "string") {
|
|
386
|
+
return [[key, value]];
|
|
387
|
+
}
|
|
388
|
+
return [];
|
|
389
|
+
}),
|
|
390
|
+
),
|
|
266
391
|
},
|
|
267
|
-
|
|
392
|
+
stdio: "pipe",
|
|
393
|
+
});
|
|
394
|
+
await once(childProcess, "spawn");
|
|
395
|
+
scope.onCleanup(async () => {
|
|
396
|
+
if (childProcess.exitCode === null && !childProcess.killed) {
|
|
397
|
+
childProcess.kill("SIGTERM");
|
|
398
|
+
await Promise.any([
|
|
399
|
+
once(childProcess, "exit"),
|
|
400
|
+
new Promise((resolve) => setTimeout(resolve, 5000)),
|
|
401
|
+
]);
|
|
402
|
+
if (!childProcess.killed) {
|
|
403
|
+
childProcess.kill("SIGKILL");
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
try {
|
|
407
|
+
await fs.unlink(persistFile);
|
|
408
|
+
} catch {
|
|
409
|
+
// ignore
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
if (childProcess.pid) {
|
|
413
|
+
await fs.mkdir(path.dirname(persistFile), { recursive: true });
|
|
414
|
+
await fs.writeFile(persistFile, childProcess.pid.toString());
|
|
415
|
+
}
|
|
416
|
+
const URL_REGEX =
|
|
417
|
+
/http:\/\/(?:(?:localhost|0\.0\.0\.0|127\.0\.0\.1)|(?:\d{1,3}\.){3}\d{1,3}):\d+(?:\/)?/;
|
|
418
|
+
const promise = new DeferredPromise<string>();
|
|
419
|
+
childProcess.stdout.on("data", (data) => {
|
|
420
|
+
if (promise.status === "pending") {
|
|
421
|
+
const match = data
|
|
422
|
+
.toString()
|
|
423
|
+
.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "")
|
|
424
|
+
.match(URL_REGEX);
|
|
425
|
+
if (match) {
|
|
426
|
+
promise.resolve(match[0]);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
process.stdout.write(data);
|
|
430
|
+
});
|
|
431
|
+
childProcess.stderr.on("data", (data) => {
|
|
432
|
+
process.stderr.write(data);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
return await Promise.race([
|
|
436
|
+
promise.value,
|
|
437
|
+
once(childProcess, "exit").then(([code, signal]) => {
|
|
438
|
+
throw new Error(
|
|
439
|
+
`Dev command "${props.command}" for "${props.id}" failed to start (code: ${code}, signal: ${signal})`,
|
|
440
|
+
);
|
|
441
|
+
}),
|
|
442
|
+
]);
|
|
268
443
|
}
|