wrangler 0.0.0-e7a0cd5b → 0.0.0-e7cf0caa
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 +3 -3
- package/bin/wrangler.js +30 -10
- package/miniflare-dist/index.mjs +126 -74
- package/package.json +27 -19
- package/src/__tests__/api-dev.test.ts +65 -36
- package/src/__tests__/api-devregistry.test.ts +121 -0
- package/src/__tests__/api.test.ts +27 -5
- package/src/__tests__/configuration.test.ts +567 -86
- package/src/__tests__/d1/d1.test.ts +82 -0
- package/src/__tests__/d1/execute.test.ts +66 -0
- package/src/__tests__/d1/migrate.test.ts +157 -0
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +91 -49
- package/src/__tests__/deployments.test.ts +330 -56
- package/src/__tests__/dev.test.tsx +198 -90
- package/src/__tests__/generate.test.ts +12 -10
- package/src/__tests__/guess-worker-format.test.ts +35 -0
- package/src/__tests__/helpers/end-event-loop.ts +6 -0
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-console.ts +6 -0
- package/src/__tests__/helpers/mock-dialogs.ts +71 -85
- package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -5
- package/src/__tests__/helpers/mock-known-routes.ts +7 -2
- package/src/__tests__/helpers/mock-kv.ts +29 -16
- package/src/__tests__/helpers/mock-oauth-flow.ts +103 -92
- package/src/__tests__/helpers/mock-process.ts +8 -13
- package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +128 -27
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +18 -41
- package/src/__tests__/helpers/msw/handlers/oauth.ts +13 -18
- package/src/__tests__/helpers/msw/handlers/r2.ts +14 -34
- package/src/__tests__/helpers/msw/handlers/script.ts +9 -28
- package/src/__tests__/helpers/msw/handlers/user.ts +13 -24
- package/src/__tests__/helpers/msw/handlers/zones.ts +6 -8
- package/src/__tests__/helpers/msw/index.ts +32 -1
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
- package/src/__tests__/index.test.ts +90 -72
- package/src/__tests__/init.test.ts +927 -631
- package/src/__tests__/jest.setup.ts +19 -42
- package/src/__tests__/kv.test.ts +355 -231
- package/src/__tests__/logger.test.ts +68 -2
- package/src/__tests__/logout.test.ts +47 -0
- package/src/__tests__/metrics.test.ts +94 -51
- package/src/__tests__/middleware.scheduled.test.ts +42 -32
- package/src/__tests__/middleware.test.ts +212 -122
- package/src/__tests__/mtls-certificates.test.ts +588 -0
- package/src/__tests__/pages/deployment-list.test.ts +80 -0
- package/src/__tests__/pages/functions-build.test.ts +452 -0
- package/src/__tests__/pages/pages.test.ts +81 -0
- package/src/__tests__/pages/project-create.test.ts +63 -0
- package/src/__tests__/pages/project-list.test.ts +110 -0
- package/src/__tests__/pages/project-upload.test.ts +500 -0
- package/src/__tests__/pages/publish.test.ts +2864 -0
- package/src/__tests__/pages-deployment-tail.test.ts +955 -0
- package/src/__tests__/parse.test.ts +106 -0
- package/src/__tests__/publish.test.ts +1615 -852
- package/src/__tests__/pubsub.test.ts +226 -100
- package/src/__tests__/queues.test.ts +238 -77
- package/src/__tests__/r2.test.ts +55 -57
- package/src/__tests__/secret.test.ts +179 -130
- package/src/__tests__/tail.test.ts +267 -109
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/traverse-module-graph.test.ts +220 -0
- package/src/__tests__/tsconfig-sanity.ts +12 -0
- package/src/__tests__/tsconfig.json +8 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/type-generation.test.ts +43 -26
- package/src/__tests__/user.test.ts +35 -72
- package/src/__tests__/whoami.test.tsx +8 -114
- package/src/__tests__/worker-namespace.test.ts +83 -69
- package/src/api/dev.ts +168 -60
- package/src/api/index.ts +10 -1
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +76 -0
- package/src/api/pages/index.ts +5 -0
- package/src/api/pages/publish.tsx +355 -0
- package/src/bundle.ts +263 -140
- package/src/cfetch/index.ts +0 -2
- package/src/cfetch/internal.ts +16 -21
- package/src/cli.ts +4 -4
- package/src/config/config.ts +14 -7
- package/src/config/environment.ts +79 -24
- package/src/config/index.ts +99 -38
- package/src/config/validation-helpers.ts +1 -1
- package/src/config/validation.ts +248 -19
- package/src/create-worker-preview.ts +19 -8
- package/src/create-worker-upload-form.ts +60 -22
- package/src/d1/backups.tsx +43 -42
- package/src/d1/constants.ts +2 -0
- package/src/d1/create.tsx +44 -30
- package/src/d1/{delete.tsx → delete.ts} +11 -14
- package/src/d1/execute.tsx +209 -151
- package/src/d1/index.ts +31 -7
- package/src/d1/list.tsx +22 -10
- package/src/d1/migrations/apply.tsx +212 -0
- package/src/d1/migrations/create.tsx +79 -0
- package/src/d1/migrations/helpers.ts +172 -0
- package/src/d1/migrations/index.ts +3 -0
- package/src/d1/migrations/list.tsx +95 -0
- package/src/d1/migrations/options.ts +23 -0
- package/src/d1/options.ts +12 -2
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +11 -0
- package/src/d1/utils.ts +12 -2
- package/src/delete.ts +8 -16
- package/src/deployments.ts +340 -46
- package/src/deprecated/index.ts +8 -302
- package/src/dev/dev.tsx +57 -44
- package/src/dev/local.tsx +294 -91
- package/src/dev/remote.tsx +32 -3
- package/src/dev/start-server.ts +89 -68
- package/src/dev/use-esbuild.ts +17 -18
- package/src/dev/validate-dev-props.ts +9 -0
- package/src/{dev-registry.tsx → dev-registry.ts} +2 -1
- package/src/dev.tsx +178 -118
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +21 -17
- package/src/docs/index.ts +97 -0
- package/src/entry.ts +19 -11
- package/src/environment-variables/factory.ts +88 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/generate/index.ts +298 -0
- package/src/git-client.ts +15 -4
- package/src/{index.tsx → index.ts} +137 -63
- package/src/init.ts +249 -187
- package/src/inspect.ts +16 -1
- package/src/jest.d.ts +4 -0
- package/src/kv/index.ts +15 -17
- package/src/logger.ts +32 -5
- package/src/metrics/metrics-config.ts +3 -3
- package/src/metrics/send-event.ts +6 -1
- package/src/miniflare-cli/assets.ts +64 -28
- package/src/miniflare-cli/index.ts +4 -7
- package/src/miniflare-cli/tsconfig.json +9 -0
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
- package/src/miniflare-cli/types.ts +11 -0
- package/src/module-collection.ts +91 -25
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/pages/build.ts +410 -0
- package/src/pages/buildFunctions.ts +140 -0
- package/src/pages/deployment-tails.ts +281 -0
- package/src/pages/deployments.tsx +11 -33
- package/src/pages/{dev.tsx → dev.ts} +147 -124
- package/src/pages/errors.ts +1 -0
- package/src/pages/functions/buildPlugin.ts +72 -69
- package/src/pages/functions/buildWorker.ts +249 -114
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/{functions.tsx → functions.ts} +8 -4
- package/src/pages/{index.tsx → index.ts} +11 -3
- package/src/pages/projects.tsx +12 -22
- package/src/pages/prompt-select-project.tsx +31 -0
- package/src/pages/publish.tsx +45 -214
- package/src/pages/types.ts +6 -9
- package/src/pages/upload.tsx +58 -14
- package/src/pages/utils.ts +14 -3
- package/src/parse.ts +23 -1
- package/src/paths.ts +1 -1
- package/src/proxy.ts +5 -0
- package/src/publish/index.ts +20 -16
- package/src/publish/publish.ts +72 -47
- package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +19 -20
- package/src/queues/cli/commands/consumer/add.ts +24 -24
- package/src/queues/cli/commands/consumer/index.ts +3 -6
- package/src/queues/cli/commands/consumer/remove.ts +11 -18
- package/src/queues/cli/commands/create.ts +8 -8
- package/src/queues/cli/commands/delete.ts +8 -8
- package/src/queues/cli/commands/index.ts +6 -4
- package/src/queues/cli/commands/list.ts +8 -8
- package/src/queues/client.ts +1 -0
- package/src/queues/utils.ts +18 -0
- package/src/r2/constants.ts +4 -0
- package/src/r2/helpers.ts +1 -0
- package/src/r2/index.ts +40 -28
- package/src/secret/index.ts +14 -17
- package/src/{sites.tsx → sites.ts} +1 -1
- package/src/tail/createTail.ts +94 -3
- package/src/tail/filters.ts +1 -1
- package/src/tail/index.ts +8 -11
- package/src/tail/printing.ts +15 -0
- package/src/traverse-module-graph.ts +53 -0
- package/src/tsconfig-sanity.ts +16 -0
- package/src/type-generation.ts +79 -57
- package/src/user/access.ts +0 -1
- package/src/user/auth-variables.ts +113 -0
- package/src/user/choose-account.tsx +1 -31
- package/src/user/index.ts +0 -1
- package/src/user/{user.tsx → user.ts} +123 -82
- package/src/utils/render.ts +93 -0
- package/src/{whoami.tsx → whoami.ts} +37 -71
- package/src/worker.ts +35 -3
- package/src/yargs-types.ts +22 -5
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/checked-fetch.js +9 -3
- package/templates/d1-beta-facade.js +95 -25
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +4 -3
- package/templates/format-dev-errors.ts +8 -6
- package/templates/gitignore +1 -0
- package/templates/init-tests/test-jest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/loader-modules.ts +2 -2
- package/templates/middleware/loader-sw.ts +51 -31
- package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
- package/templates/new-worker.ts +3 -0
- package/templates/pages-dev-pipeline.ts +4 -1
- package/templates/pages-shim.ts +4 -1
- package/templates/pages-template-plugin.ts +19 -10
- package/templates/serve-static-assets.ts +17 -14
- package/templates/service-bindings-module-facade.js +1 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +105 -0
- package/templates/tsconfig.json +5 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +826 -77
- package/wrangler-dist/cli.js +130734 -140838
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/api-devregistry.test.js +0 -57
- package/src/__tests__/d1.test.ts +0 -72
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/__tests__/helpers/mock-cfetch.ts +0 -333
- package/src/__tests__/pages.test.ts +0 -2223
- package/src/dialogs.tsx +0 -163
- package/src/environment-variables.ts +0 -50
- package/src/pages/build.tsx +0 -238
- package/src/user/env-vars.ts +0 -46
- package/templates/experimental-local-cache-stubs.js +0 -27
- /package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
- /package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
- /package/src/pages/{hash.tsx → hash.ts} +0 -0
package/src/dev/local.tsx
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { fork } from "node:child_process";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
|
-
import { readFile
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import chalk from "chalk";
|
|
7
|
+
import getPort from "get-port";
|
|
7
8
|
import { npxImport } from "npx-import";
|
|
8
9
|
import { useState, useEffect, useRef } from "react";
|
|
9
10
|
import onExit from "signal-exit";
|
|
11
|
+
import { fetch } from "undici";
|
|
12
|
+
import { performApiFetch } from "../cfetch/internal";
|
|
10
13
|
import { registerWorker } from "../dev-registry";
|
|
11
14
|
import useInspector from "../inspect";
|
|
12
15
|
import { logger } from "../logger";
|
|
@@ -16,9 +19,11 @@ import {
|
|
|
16
19
|
} from "../module-collection";
|
|
17
20
|
import { getBasePath } from "../paths";
|
|
18
21
|
import { waitForPortToBeAvailable } from "../proxy";
|
|
22
|
+
import { requireAuth } from "../user";
|
|
19
23
|
import type { Config } from "../config";
|
|
20
24
|
import type { WorkerRegistry } from "../dev-registry";
|
|
21
|
-
import type {
|
|
25
|
+
import type { LoggerLevel } from "../logger";
|
|
26
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli/types";
|
|
22
27
|
import type { AssetPaths } from "../sites";
|
|
23
28
|
import type {
|
|
24
29
|
CfWorkerInit,
|
|
@@ -37,6 +42,8 @@ import type { EsbuildBundle } from "./use-esbuild";
|
|
|
37
42
|
import type {
|
|
38
43
|
Miniflare as Miniflare3Type,
|
|
39
44
|
MiniflareOptions as Miniflare3Options,
|
|
45
|
+
Log as Miniflare3LogType,
|
|
46
|
+
CloudflareFetch,
|
|
40
47
|
} from "@miniflare/tre";
|
|
41
48
|
import type { MiniflareOptions } from "miniflare";
|
|
42
49
|
import type { ChildProcess } from "node:child_process";
|
|
@@ -51,8 +58,8 @@ export interface LocalProps {
|
|
|
51
58
|
bindings: CfWorkerInit["bindings"];
|
|
52
59
|
workerDefinitions: WorkerRegistry | undefined;
|
|
53
60
|
assetPaths: AssetPaths | undefined;
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
initialPort: number;
|
|
62
|
+
initialIp: string;
|
|
56
63
|
rules: Config["rules"];
|
|
57
64
|
inspectorPort: number;
|
|
58
65
|
localPersistencePath: string | null;
|
|
@@ -63,18 +70,31 @@ export interface LocalProps {
|
|
|
63
70
|
localUpstream: string | undefined;
|
|
64
71
|
inspect: boolean;
|
|
65
72
|
onReady: ((ip: string, port: number) => void) | undefined;
|
|
66
|
-
logPrefix?: string;
|
|
67
73
|
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
68
74
|
testScheduled?: boolean;
|
|
69
|
-
experimentalLocal
|
|
75
|
+
experimentalLocal: boolean | undefined;
|
|
76
|
+
accountId: string | undefined; // Account ID? In local mode??? :exploding_head:
|
|
77
|
+
experimentalLocalRemoteKv: boolean | undefined;
|
|
70
78
|
}
|
|
71
79
|
|
|
80
|
+
type InspectorJSON = {
|
|
81
|
+
id: string;
|
|
82
|
+
title: string;
|
|
83
|
+
type: "node";
|
|
84
|
+
description: string;
|
|
85
|
+
webSocketDebuggerUrl: string;
|
|
86
|
+
devtoolsFrontendUrl: string;
|
|
87
|
+
devtoolsFrontendUrlCompat: string;
|
|
88
|
+
faviconUrl: string;
|
|
89
|
+
url: string;
|
|
90
|
+
}[];
|
|
91
|
+
|
|
72
92
|
export function Local(props: LocalProps) {
|
|
73
93
|
const { inspectorUrl } = useLocalWorker(props);
|
|
74
94
|
useInspector({
|
|
75
95
|
inspectorUrl,
|
|
76
96
|
port: props.inspectorPort,
|
|
77
|
-
logToTerminal: false,
|
|
97
|
+
logToTerminal: props.experimentalLocal ?? false,
|
|
78
98
|
});
|
|
79
99
|
return null;
|
|
80
100
|
}
|
|
@@ -89,28 +109,34 @@ function useLocalWorker({
|
|
|
89
109
|
bindings,
|
|
90
110
|
workerDefinitions,
|
|
91
111
|
assetPaths,
|
|
92
|
-
|
|
93
|
-
inspectorPort,
|
|
112
|
+
initialPort,
|
|
94
113
|
rules,
|
|
95
114
|
localPersistencePath,
|
|
96
115
|
liveReload,
|
|
97
|
-
|
|
116
|
+
initialIp,
|
|
98
117
|
crons,
|
|
99
118
|
queueConsumers,
|
|
100
119
|
localProtocol,
|
|
101
120
|
localUpstream,
|
|
102
121
|
inspect,
|
|
103
122
|
onReady,
|
|
104
|
-
logPrefix,
|
|
105
123
|
enablePagesAssetsServiceBinding,
|
|
106
124
|
experimentalLocal,
|
|
125
|
+
accountId,
|
|
126
|
+
experimentalLocalRemoteKv,
|
|
107
127
|
}: LocalProps) {
|
|
108
128
|
// TODO: pass vars via command line
|
|
109
129
|
const local = useRef<ChildProcess>();
|
|
110
130
|
const experimentalLocalRef = useRef<Miniflare3Type>();
|
|
111
131
|
const removeSignalExitListener = useRef<() => void>();
|
|
132
|
+
const removeExperimentalLocalSignalExitListener = useRef<() => void>();
|
|
112
133
|
const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
|
|
113
134
|
|
|
135
|
+
// Our inspector proxy server will be binding to `LocalProps`'s `inspectorPort`.
|
|
136
|
+
// If we attempted to bind Node.js/workerd to the same inspector port, we'd get a port already in use error.
|
|
137
|
+
// Therefore, generate a new random port for our runtime's to bind their inspector service to.
|
|
138
|
+
const runtimeInspectorPortRef = useRef<number>();
|
|
139
|
+
|
|
114
140
|
useEffect(() => {
|
|
115
141
|
if (bindings.services && bindings.services.length > 0) {
|
|
116
142
|
logger.warn(
|
|
@@ -136,22 +162,6 @@ function useLocalWorker({
|
|
|
136
162
|
async function startLocalWorker() {
|
|
137
163
|
if (!bundle || !format) return;
|
|
138
164
|
|
|
139
|
-
// port for the worker
|
|
140
|
-
await waitForPortToBeAvailable(port, {
|
|
141
|
-
retryPeriod: 200,
|
|
142
|
-
timeout: 2000,
|
|
143
|
-
abortSignal: abortController.signal,
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// In local mode, we want to copy all referenced modules into
|
|
147
|
-
// the output bundle directory before starting up
|
|
148
|
-
for (const module of bundle.modules) {
|
|
149
|
-
await writeFile(
|
|
150
|
-
path.join(path.dirname(bundle.path), module.name),
|
|
151
|
-
module.content
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
165
|
const scriptPath = realpathSync(bundle.path);
|
|
156
166
|
|
|
157
167
|
const upstream =
|
|
@@ -174,12 +184,15 @@ function useLocalWorker({
|
|
|
174
184
|
bundle,
|
|
175
185
|
});
|
|
176
186
|
|
|
177
|
-
|
|
187
|
+
runtimeInspectorPortRef.current ??= await getPort();
|
|
188
|
+
const runtimeInspectorPort = runtimeInspectorPortRef.current;
|
|
189
|
+
|
|
190
|
+
const { forkOptions, miniflareCLIPath, options } = setupMiniflareOptions({
|
|
178
191
|
workerName,
|
|
179
|
-
port,
|
|
192
|
+
port: initialPort,
|
|
180
193
|
scriptPath,
|
|
181
194
|
localProtocol,
|
|
182
|
-
ip,
|
|
195
|
+
ip: initialIp,
|
|
183
196
|
format,
|
|
184
197
|
rules,
|
|
185
198
|
compatibilityDate,
|
|
@@ -201,35 +214,102 @@ function useLocalWorker({
|
|
|
201
214
|
dataBlobBindings,
|
|
202
215
|
crons,
|
|
203
216
|
upstream,
|
|
204
|
-
logPrefix,
|
|
205
217
|
workerDefinitions,
|
|
206
218
|
enablePagesAssetsServiceBinding,
|
|
207
219
|
});
|
|
208
220
|
|
|
209
221
|
if (experimentalLocal) {
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
222
|
+
const log = await buildMiniflare3Logger();
|
|
223
|
+
const mf3Options = await transformMf2OptionsToMf3Options({
|
|
224
|
+
miniflare2Options: options,
|
|
225
|
+
format,
|
|
226
|
+
bundle,
|
|
227
|
+
log,
|
|
228
|
+
enablePagesAssetsServiceBinding,
|
|
229
|
+
kvNamespaces: bindings?.kv_namespaces,
|
|
230
|
+
r2Buckets: bindings?.r2_buckets,
|
|
231
|
+
d1Databases: bindings?.d1_databases,
|
|
232
|
+
authenticatedAccountId: accountId,
|
|
233
|
+
kvRemote: experimentalLocalRemoteKv,
|
|
234
|
+
inspectorPort: runtimeInspectorPort,
|
|
219
235
|
});
|
|
236
|
+
|
|
237
|
+
const current = experimentalLocalRef.current;
|
|
238
|
+
|
|
239
|
+
if (current === undefined) {
|
|
240
|
+
// If we don't have an active Miniflare instance, create a new one
|
|
241
|
+
const { Miniflare } = await getMiniflare3();
|
|
242
|
+
if (abortController.signal.aborted) return;
|
|
243
|
+
const mf = new Miniflare(mf3Options);
|
|
244
|
+
experimentalLocalRef.current = mf;
|
|
245
|
+
removeExperimentalLocalSignalExitListener.current = onExit(() => {
|
|
246
|
+
logger.log("⎔ Shutting down experimental local server.");
|
|
247
|
+
void mf.dispose();
|
|
248
|
+
experimentalLocalRef.current = undefined;
|
|
249
|
+
});
|
|
250
|
+
await mf.ready;
|
|
251
|
+
} else {
|
|
252
|
+
// Otherwise, reuse the existing instance with its loopback server
|
|
253
|
+
// and just update the options
|
|
254
|
+
if (abortController.signal.aborted) return;
|
|
255
|
+
logger.log("⎔ Reloading experimental local server.");
|
|
256
|
+
await current.setOptions(mf3Options);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
// fetch the inspector JSON response from the DevTools Inspector protocol
|
|
261
|
+
const inspectorJSONArr = (await (
|
|
262
|
+
await fetch(`http://127.0.0.1:${runtimeInspectorPort}/json`)
|
|
263
|
+
).json()) as InspectorJSON;
|
|
264
|
+
|
|
265
|
+
const foundInspectorURL = inspectorJSONArr?.find((inspectorJSON) =>
|
|
266
|
+
inspectorJSON.id.startsWith("core:user")
|
|
267
|
+
)?.webSocketDebuggerUrl;
|
|
268
|
+
if (foundInspectorURL === undefined) {
|
|
269
|
+
setInspectorUrl(undefined);
|
|
270
|
+
} else {
|
|
271
|
+
const url = new URL(foundInspectorURL);
|
|
272
|
+
// Force inspector URL to be different on each reload so `useEffect`
|
|
273
|
+
// in `useInspector` is re-run to connect to newly restarted
|
|
274
|
+
// `workerd` server when updating options. Can't use a query param
|
|
275
|
+
// here as that seems to cause an infinite connection loop, can't
|
|
276
|
+
// use a hash as those are forbidden by `ws`, so username it is.
|
|
277
|
+
url.username = `${Date.now()}-${Math.floor(
|
|
278
|
+
Math.random() * Number.MAX_SAFE_INTEGER
|
|
279
|
+
)}`;
|
|
280
|
+
setInspectorUrl(url.toString());
|
|
281
|
+
}
|
|
282
|
+
} catch (error: unknown) {
|
|
283
|
+
logger.error("Error attempting to retrieve Debugger URL:", error);
|
|
284
|
+
}
|
|
285
|
+
|
|
220
286
|
return;
|
|
221
287
|
}
|
|
222
288
|
|
|
223
|
-
|
|
289
|
+
// Wait for the Worker port to be available. We don't want to do this in experimental local
|
|
290
|
+
// mode, as we only `dispose()` the Miniflare 3 instance, and shutdown the server when
|
|
291
|
+
// unmounting the component, not when props change. If we did, we'd just timeout every time.
|
|
292
|
+
await waitForPortToBeAvailable(initialPort, {
|
|
293
|
+
retryPeriod: 200,
|
|
294
|
+
timeout: 2000,
|
|
295
|
+
abortSignal: abortController.signal,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const nodeOptions = setupNodeOptions({
|
|
299
|
+
inspect,
|
|
300
|
+
inspectorPort: runtimeInspectorPort,
|
|
301
|
+
});
|
|
224
302
|
logger.log("⎔ Starting a local server...");
|
|
225
303
|
|
|
304
|
+
const hasColourSupport =
|
|
305
|
+
chalk.supportsColor.hasBasic && process.env.FORCE_COLOR !== "0";
|
|
226
306
|
const child = (local.current = fork(miniflareCLIPath, forkOptions, {
|
|
227
307
|
cwd: path.dirname(scriptPath),
|
|
228
308
|
execArgv: nodeOptions,
|
|
229
309
|
stdio: "pipe",
|
|
230
310
|
env: {
|
|
231
311
|
...process.env,
|
|
232
|
-
FORCE_COLOR:
|
|
312
|
+
FORCE_COLOR: hasColourSupport ? "1" : undefined,
|
|
233
313
|
},
|
|
234
314
|
}));
|
|
235
315
|
|
|
@@ -241,21 +321,21 @@ function useLocalWorker({
|
|
|
241
321
|
await registerWorker(workerName, {
|
|
242
322
|
protocol: localProtocol,
|
|
243
323
|
mode: "local",
|
|
244
|
-
port,
|
|
245
|
-
host:
|
|
324
|
+
port: message.port,
|
|
325
|
+
host: initialIp,
|
|
246
326
|
durableObjects: internalDurableObjects.map((binding) => ({
|
|
247
327
|
name: binding.name,
|
|
248
328
|
className: binding.class_name,
|
|
249
329
|
})),
|
|
250
330
|
...(message.durableObjectsPort
|
|
251
331
|
? {
|
|
252
|
-
durableObjectsHost:
|
|
332
|
+
durableObjectsHost: initialIp,
|
|
253
333
|
durableObjectsPort: message.durableObjectsPort,
|
|
254
334
|
}
|
|
255
335
|
: {}),
|
|
256
336
|
});
|
|
257
337
|
}
|
|
258
|
-
onReady?.(
|
|
338
|
+
onReady?.(initialIp, message.port);
|
|
259
339
|
}
|
|
260
340
|
});
|
|
261
341
|
|
|
@@ -307,7 +387,13 @@ function useLocalWorker({
|
|
|
307
387
|
}
|
|
308
388
|
|
|
309
389
|
startLocalWorker().catch((err) => {
|
|
310
|
-
|
|
390
|
+
if (err.code === "ERR_RUNTIME_FAILURE") {
|
|
391
|
+
// Don't log a full verbose stack-trace when Miniflare 3's workerd instance fails to start.
|
|
392
|
+
// workerd will log its own errors, and our stack trace won't have any useful information.
|
|
393
|
+
logger.error(err.message);
|
|
394
|
+
} else {
|
|
395
|
+
logger.error("local worker:", err);
|
|
396
|
+
}
|
|
311
397
|
});
|
|
312
398
|
|
|
313
399
|
return () => {
|
|
@@ -317,13 +403,6 @@ function useLocalWorker({
|
|
|
317
403
|
local.current?.kill();
|
|
318
404
|
local.current = undefined;
|
|
319
405
|
}
|
|
320
|
-
if (experimentalLocalRef.current) {
|
|
321
|
-
logger.log("⎔ Shutting down experimental local server.");
|
|
322
|
-
// Initialisation errors are also thrown asynchronously by dispose().
|
|
323
|
-
// The catch() above should've caught them though.
|
|
324
|
-
experimentalLocalRef.current?.dispose().catch(() => {});
|
|
325
|
-
experimentalLocalRef.current = undefined;
|
|
326
|
-
}
|
|
327
406
|
removeSignalExitListener.current?.();
|
|
328
407
|
removeSignalExitListener.current = undefined;
|
|
329
408
|
};
|
|
@@ -331,9 +410,8 @@ function useLocalWorker({
|
|
|
331
410
|
bundle,
|
|
332
411
|
workerName,
|
|
333
412
|
format,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
ip,
|
|
413
|
+
initialPort,
|
|
414
|
+
initialIp,
|
|
337
415
|
queueConsumers,
|
|
338
416
|
bindings.queues,
|
|
339
417
|
bindings.durable_objects,
|
|
@@ -357,11 +435,32 @@ function useLocalWorker({
|
|
|
357
435
|
localProtocol,
|
|
358
436
|
localUpstream,
|
|
359
437
|
inspect,
|
|
360
|
-
logPrefix,
|
|
361
438
|
onReady,
|
|
362
439
|
enablePagesAssetsServiceBinding,
|
|
363
440
|
experimentalLocal,
|
|
441
|
+
accountId,
|
|
442
|
+
experimentalLocalRemoteKv,
|
|
364
443
|
]);
|
|
444
|
+
|
|
445
|
+
// Rather than disposing the Miniflare instance on every reload, only dispose
|
|
446
|
+
// it if local mode is disabled and the `Local` component is unmounted. This
|
|
447
|
+
// allows us to use the more efficient `Miniflare#setOptions` on reload which
|
|
448
|
+
// retains internal state (e.g. the Miniflare loopback server).
|
|
449
|
+
useEffect(
|
|
450
|
+
() => () => {
|
|
451
|
+
if (experimentalLocalRef.current) {
|
|
452
|
+
logger.log("⎔ Shutting down experimental local server.");
|
|
453
|
+
// Initialisation errors are also thrown asynchronously by dispose().
|
|
454
|
+
// The catch() above should've caught them though.
|
|
455
|
+
experimentalLocalRef.current?.dispose().catch(() => {});
|
|
456
|
+
experimentalLocalRef.current = undefined;
|
|
457
|
+
}
|
|
458
|
+
removeExperimentalLocalSignalExitListener.current?.();
|
|
459
|
+
removeExperimentalLocalSignalExitListener.current = undefined;
|
|
460
|
+
},
|
|
461
|
+
[]
|
|
462
|
+
);
|
|
463
|
+
|
|
365
464
|
return { inspectorUrl };
|
|
366
465
|
}
|
|
367
466
|
|
|
@@ -474,7 +573,6 @@ interface SetupMiniflareOptionsProps {
|
|
|
474
573
|
dataBlobBindings: Record<string, string>;
|
|
475
574
|
crons: Config["triggers"]["crons"];
|
|
476
575
|
upstream: string | undefined;
|
|
477
|
-
logPrefix: string | undefined;
|
|
478
576
|
workerDefinitions: WorkerRegistry | undefined;
|
|
479
577
|
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
480
578
|
}
|
|
@@ -506,15 +604,15 @@ export function setupMiniflareOptions({
|
|
|
506
604
|
dataBlobBindings,
|
|
507
605
|
crons,
|
|
508
606
|
upstream,
|
|
509
|
-
logPrefix,
|
|
510
607
|
workerDefinitions,
|
|
511
608
|
enablePagesAssetsServiceBinding,
|
|
512
609
|
}: SetupMiniflareOptionsProps): {
|
|
513
610
|
miniflareCLIPath: string;
|
|
514
611
|
forkOptions: string[];
|
|
612
|
+
options: MiniflareOptions;
|
|
515
613
|
} {
|
|
516
614
|
// It's now getting _really_ messy now with Pages ASSETS binding outside and the external Durable Objects inside.
|
|
517
|
-
const options = {
|
|
615
|
+
const options: MiniflareOptions = {
|
|
518
616
|
name: workerName,
|
|
519
617
|
port,
|
|
520
618
|
scriptPath,
|
|
@@ -618,7 +716,6 @@ export function setupMiniflareOptions({
|
|
|
618
716
|
crons,
|
|
619
717
|
upstream,
|
|
620
718
|
logLevel: logger.loggerLevel,
|
|
621
|
-
logOptions: logPrefix ? { prefix: logPrefix } : undefined,
|
|
622
719
|
enablePagesAssetsServiceBinding,
|
|
623
720
|
};
|
|
624
721
|
// The path to the Miniflare CLI assumes that this file is being run from
|
|
@@ -633,16 +730,14 @@ export function setupMiniflareOptions({
|
|
|
633
730
|
if (enablePagesAssetsServiceBinding) {
|
|
634
731
|
forkOptions.push(JSON.stringify(enablePagesAssetsServiceBinding));
|
|
635
732
|
}
|
|
636
|
-
return { miniflareCLIPath, forkOptions };
|
|
733
|
+
return { miniflareCLIPath, forkOptions, options };
|
|
637
734
|
}
|
|
638
735
|
|
|
639
736
|
export function setupNodeOptions({
|
|
640
737
|
inspect,
|
|
641
|
-
ip,
|
|
642
738
|
inspectorPort,
|
|
643
739
|
}: {
|
|
644
740
|
inspect: boolean;
|
|
645
|
-
ip: string;
|
|
646
741
|
inspectorPort: number;
|
|
647
742
|
}) {
|
|
648
743
|
const nodeOptions = [
|
|
@@ -651,33 +746,123 @@ export function setupNodeOptions({
|
|
|
651
746
|
// "--log=VERBOSE", // uncomment this to Miniflare to log "everything"!
|
|
652
747
|
];
|
|
653
748
|
if (inspect) {
|
|
654
|
-
nodeOptions.push("--inspect=" +
|
|
749
|
+
nodeOptions.push("--inspect=" + `127.0.0.1:${inspectorPort}`); // start Miniflare listening for a debugger to attach
|
|
655
750
|
}
|
|
656
751
|
return nodeOptions;
|
|
657
752
|
}
|
|
658
753
|
|
|
659
|
-
|
|
660
|
-
//
|
|
661
|
-
|
|
754
|
+
export interface SetupMiniflare3Options {
|
|
755
|
+
// Regular Miniflare 2 options to transform
|
|
756
|
+
miniflare2Options: MiniflareOptions;
|
|
757
|
+
// Miniflare 3 requires all modules to be manually specified
|
|
758
|
+
format: CfScriptFormat;
|
|
759
|
+
bundle: EsbuildBundle;
|
|
760
|
+
|
|
761
|
+
// Miniflare's logger
|
|
762
|
+
log: Miniflare3LogType;
|
|
763
|
+
|
|
764
|
+
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
765
|
+
|
|
766
|
+
// Miniflare 3 accepts namespace/bucket names in addition to binding names.
|
|
767
|
+
// This means multiple workers persisting to the same location can have
|
|
768
|
+
// different binding names for the same namespace/bucket. Therefore, we need
|
|
769
|
+
// the full KV/R2 arrays. This is also required for remote KV storage, as
|
|
770
|
+
// we need actual namespace IDs to connect to.
|
|
771
|
+
kvNamespaces: CfKvNamespace[] | undefined;
|
|
772
|
+
r2Buckets: CfR2Bucket[] | undefined;
|
|
773
|
+
d1Databases: CfD1Database[] | undefined;
|
|
774
|
+
|
|
775
|
+
// Account ID to use for authenticated Cloudflare fetch. If true, prompt
|
|
776
|
+
// user for ID if multiple available.
|
|
777
|
+
authenticatedAccountId: string | true | undefined;
|
|
778
|
+
// Whether to read/write from/to real KV namespaces
|
|
779
|
+
kvRemote: boolean | undefined;
|
|
780
|
+
|
|
781
|
+
// Port to start DevTools inspector server on
|
|
782
|
+
inspectorPort: number;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
export async function buildMiniflare3Logger(): Promise<Miniflare3LogType> {
|
|
786
|
+
const { Log, NoOpLog, LogLevel } = await getMiniflare3();
|
|
662
787
|
|
|
663
|
-
|
|
664
|
-
|
|
788
|
+
let level = logger.loggerLevel.toUpperCase() as Uppercase<LoggerLevel>;
|
|
789
|
+
if (level === "LOG") level = "INFO";
|
|
790
|
+
const logLevel = LogLevel[level];
|
|
791
|
+
|
|
792
|
+
return logLevel === LogLevel.NONE ? new NoOpLog() : new Log(logLevel);
|
|
665
793
|
}
|
|
666
794
|
|
|
667
|
-
export async function
|
|
668
|
-
|
|
669
|
-
format
|
|
670
|
-
bundle
|
|
671
|
-
|
|
795
|
+
export async function transformMf2OptionsToMf3Options({
|
|
796
|
+
miniflare2Options,
|
|
797
|
+
format,
|
|
798
|
+
bundle,
|
|
799
|
+
log,
|
|
800
|
+
enablePagesAssetsServiceBinding,
|
|
801
|
+
kvNamespaces,
|
|
802
|
+
r2Buckets,
|
|
803
|
+
d1Databases,
|
|
804
|
+
authenticatedAccountId,
|
|
805
|
+
kvRemote,
|
|
806
|
+
inspectorPort,
|
|
807
|
+
}: SetupMiniflare3Options): Promise<Miniflare3Options> {
|
|
808
|
+
// Build authenticated Cloudflare API fetch function if required
|
|
809
|
+
let cloudflareFetch: CloudflareFetch | undefined;
|
|
810
|
+
if (kvRemote && authenticatedAccountId !== undefined) {
|
|
811
|
+
const { Response: Miniflare3Response } = await getMiniflare3();
|
|
812
|
+
const preferredAccountId =
|
|
813
|
+
authenticatedAccountId === true ? undefined : authenticatedAccountId;
|
|
814
|
+
const accountId = await requireAuth({ account_id: preferredAccountId });
|
|
815
|
+
cloudflareFetch = async (resource, searchParams, init) => {
|
|
816
|
+
resource = `/accounts/${accountId}/${resource}`;
|
|
817
|
+
const response = await performApiFetch(resource, init, searchParams);
|
|
818
|
+
return new Miniflare3Response(response.body, response);
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
672
822
|
const options: Miniflare3Options = {
|
|
673
|
-
...
|
|
823
|
+
...miniflare2Options,
|
|
674
824
|
// Miniflare 3 distinguishes between binding name and namespace/bucket IDs.
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
r2Buckets:
|
|
825
|
+
kvNamespaces: Object.fromEntries(
|
|
826
|
+
kvNamespaces?.map(({ binding, id }) => [binding, id]) ?? []
|
|
827
|
+
),
|
|
828
|
+
r2Buckets: Object.fromEntries(
|
|
829
|
+
r2Buckets?.map(({ binding, bucket_name }) => [binding, bucket_name]) ?? []
|
|
830
|
+
),
|
|
831
|
+
d1Databases: Object.fromEntries(
|
|
832
|
+
d1Databases?.map(({ binding, database_id, preview_database_id }) => [
|
|
833
|
+
binding,
|
|
834
|
+
preview_database_id ?? database_id,
|
|
835
|
+
]) ?? []
|
|
836
|
+
),
|
|
837
|
+
inspectorPort,
|
|
838
|
+
verbose: true,
|
|
839
|
+
cloudflareFetch,
|
|
840
|
+
log,
|
|
679
841
|
};
|
|
680
842
|
|
|
843
|
+
if (enablePagesAssetsServiceBinding !== undefined) {
|
|
844
|
+
// `../miniflare-cli/assets` dynamically imports`@cloudflare/pages-shared/environment-polyfills`.
|
|
845
|
+
// `@cloudflare/pages-shared/environment-polyfills/types.ts` defines `global`
|
|
846
|
+
// augmentations that pollute the `import`-site's typing environment.
|
|
847
|
+
//
|
|
848
|
+
// We `require` instead of `import`ing here to avoid polluting the main
|
|
849
|
+
// `wrangler` TypeScript project with the `global` augmentations. This
|
|
850
|
+
// relies on the fact that `require` is untyped.
|
|
851
|
+
//
|
|
852
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
853
|
+
const generateASSETSBinding = require("../miniflare-cli/assets").default;
|
|
854
|
+
options.serviceBindings = {
|
|
855
|
+
...options.serviceBindings,
|
|
856
|
+
ASSETS: (await generateASSETSBinding({
|
|
857
|
+
log,
|
|
858
|
+
...enablePagesAssetsServiceBinding,
|
|
859
|
+
tre: true,
|
|
860
|
+
// We can get rid of this `any` easily once we do experimental-local/tre by default
|
|
861
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
862
|
+
})) as any,
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
|
|
681
866
|
if (format === "modules") {
|
|
682
867
|
// Manually specify all modules from the bundle. If we didn't do this,
|
|
683
868
|
// Miniflare 3 would try collect them automatically again itself.
|
|
@@ -688,30 +873,48 @@ export async function setupExperimentalLocal(
|
|
|
688
873
|
const root = path.dirname(bundle.path);
|
|
689
874
|
|
|
690
875
|
assert.strictEqual(bundle.type, "esm");
|
|
876
|
+
// Required for source mapped paths to resolve correctly
|
|
877
|
+
options.modulesRoot = root;
|
|
691
878
|
options.modules = [
|
|
692
879
|
// Entrypoint
|
|
693
880
|
{
|
|
694
881
|
type: "ESModule",
|
|
695
|
-
path:
|
|
882
|
+
path: bundle.path,
|
|
696
883
|
contents: await readFile(bundle.path, "utf-8"),
|
|
697
884
|
},
|
|
698
885
|
// Misc (WebAssembly, etc, ...)
|
|
699
886
|
...bundle.modules.map((module) => ({
|
|
700
887
|
type: ModuleTypeToRuleType[module.type ?? "esm"],
|
|
701
|
-
path: module.name,
|
|
888
|
+
path: path.resolve(root, module.name),
|
|
702
889
|
contents: module.content,
|
|
703
890
|
})),
|
|
704
891
|
];
|
|
705
892
|
}
|
|
706
893
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
894
|
+
if (kvRemote) {
|
|
895
|
+
// `kvPersist` is always assigned a truthy value in `setupMiniflareOptions`
|
|
896
|
+
assert(options.kvPersist);
|
|
897
|
+
const kvRemoteCache =
|
|
898
|
+
options.kvPersist === true
|
|
899
|
+
? // If storing in temporary directory, find this path from the bundle
|
|
900
|
+
// output path
|
|
901
|
+
path.join(path.dirname(bundle.path), ".mf", "kv-remote")
|
|
902
|
+
: // Otherwise, `kvPersist` looks like `.../kv`, so rewrite it to
|
|
903
|
+
// `kv-remote` since the expected metadata format for remote storage
|
|
904
|
+
// is different to local
|
|
905
|
+
path.join(path.dirname(options.kvPersist), "kv-remote");
|
|
906
|
+
options.kvPersist = `remote:?cache=${encodeURIComponent(kvRemoteCache)}`;
|
|
714
907
|
}
|
|
715
908
|
|
|
716
|
-
return
|
|
909
|
+
return options;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// Caching of the `npx-import`ed `@miniflare/tre` package
|
|
913
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
914
|
+
let miniflare3Module: typeof import("@miniflare/tre");
|
|
915
|
+
export async function getMiniflare3(): Promise<
|
|
916
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
917
|
+
typeof import("@miniflare/tre")
|
|
918
|
+
> {
|
|
919
|
+
return (miniflare3Module ??= await npxImport("@miniflare/tre@3.0.0-next.12"));
|
|
717
920
|
}
|