wrangler 0.0.0-e30d1013 → 0.0.0-e311bbbf
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 +26 -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 -39
- 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 -52
- package/src/__tests__/dev.test.tsx +198 -90
- package/src/__tests__/generate.test.ts +8 -5
- 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 +127 -26
- 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 +1620 -830
- package/src/__tests__/pubsub.test.ts +226 -100
- package/src/__tests__/queues.test.ts +237 -76
- package/src/__tests__/r2.test.ts +37 -56
- 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 +11 -2
- 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 +221 -128
- 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 +73 -16
- package/src/config/index.ts +99 -30
- package/src/config/validation-helpers.ts +1 -1
- package/src/config/validation.ts +248 -9
- package/src/create-worker-preview.ts +19 -8
- package/src/create-worker-upload-form.ts +48 -5
- package/src/d1/backups.tsx +43 -42
- package/src/d1/create.tsx +26 -21
- package/src/d1/{delete.tsx → delete.ts} +11 -14
- package/src/d1/execute.tsx +183 -170
- package/src/d1/index.ts +7 -6
- 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 +3 -3
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +1 -0
- package/src/d1/utils.ts +2 -1
- package/src/delete.ts +8 -16
- package/src/deployments.ts +333 -42
- package/src/deprecated/index.ts +8 -302
- package/src/dev/dev.tsx +57 -44
- package/src/dev/local.tsx +248 -74
- package/src/dev/remote.tsx +32 -3
- package/src/dev/start-server.ts +81 -66
- 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 -117
- 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} +134 -59
- 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 -139
- package/src/pages/errors.ts +1 -0
- package/src/pages/functions/buildPlugin.ts +61 -54
- package/src/pages/functions/buildWorker.ts +159 -33
- 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 +46 -225
- package/src/pages/types.ts +6 -9
- package/src/pages/upload.tsx +58 -14
- package/src/pages/utils.ts +12 -1
- 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 +71 -46
- 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/helpers.ts +1 -0
- package/src/r2/index.ts +28 -28
- package/src/secret/index.ts +14 -16
- 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 +28 -20
- 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 +30 -1
- 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 +51 -3
- 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 +820 -70
- package/wrangler-dist/cli.js +68161 -78780
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/api-devregistry.test.js +0 -56
- package/src/__tests__/d1.test.ts +0 -74
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/__tests__/helpers/mock-cfetch.ts +0 -333
- package/src/__tests__/pages.test.ts +0 -2387
- package/src/d1/migrations.tsx +0 -446
- package/src/dialogs.tsx +0 -169
- package/src/environment-variables.ts +0 -50
- package/src/pages/build.tsx +0 -270
- 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,13 +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
7
|
import getPort from "get-port";
|
|
8
8
|
import { npxImport } from "npx-import";
|
|
9
9
|
import { useState, useEffect, useRef } from "react";
|
|
10
10
|
import onExit from "signal-exit";
|
|
11
|
+
import { fetch } from "undici";
|
|
12
|
+
import { performApiFetch } from "../cfetch/internal";
|
|
11
13
|
import { registerWorker } from "../dev-registry";
|
|
12
14
|
import useInspector from "../inspect";
|
|
13
15
|
import { logger } from "../logger";
|
|
@@ -17,9 +19,11 @@ import {
|
|
|
17
19
|
} from "../module-collection";
|
|
18
20
|
import { getBasePath } from "../paths";
|
|
19
21
|
import { waitForPortToBeAvailable } from "../proxy";
|
|
22
|
+
import { requireAuth } from "../user";
|
|
20
23
|
import type { Config } from "../config";
|
|
21
24
|
import type { WorkerRegistry } from "../dev-registry";
|
|
22
|
-
import type {
|
|
25
|
+
import type { LoggerLevel } from "../logger";
|
|
26
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli/types";
|
|
23
27
|
import type { AssetPaths } from "../sites";
|
|
24
28
|
import type {
|
|
25
29
|
CfWorkerInit,
|
|
@@ -38,6 +42,8 @@ import type { EsbuildBundle } from "./use-esbuild";
|
|
|
38
42
|
import type {
|
|
39
43
|
Miniflare as Miniflare3Type,
|
|
40
44
|
MiniflareOptions as Miniflare3Options,
|
|
45
|
+
Log as Miniflare3LogType,
|
|
46
|
+
CloudflareFetch,
|
|
41
47
|
} from "@miniflare/tre";
|
|
42
48
|
import type { MiniflareOptions } from "miniflare";
|
|
43
49
|
import type { ChildProcess } from "node:child_process";
|
|
@@ -52,8 +58,8 @@ export interface LocalProps {
|
|
|
52
58
|
bindings: CfWorkerInit["bindings"];
|
|
53
59
|
workerDefinitions: WorkerRegistry | undefined;
|
|
54
60
|
assetPaths: AssetPaths | undefined;
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
initialPort: number;
|
|
62
|
+
initialIp: string;
|
|
57
63
|
rules: Config["rules"];
|
|
58
64
|
inspectorPort: number;
|
|
59
65
|
localPersistencePath: string | null;
|
|
@@ -64,18 +70,31 @@ export interface LocalProps {
|
|
|
64
70
|
localUpstream: string | undefined;
|
|
65
71
|
inspect: boolean;
|
|
66
72
|
onReady: ((ip: string, port: number) => void) | undefined;
|
|
67
|
-
logPrefix?: string;
|
|
68
73
|
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
69
74
|
testScheduled?: boolean;
|
|
70
|
-
experimentalLocal
|
|
75
|
+
experimentalLocal: boolean | undefined;
|
|
76
|
+
accountId: string | undefined; // Account ID? In local mode??? :exploding_head:
|
|
77
|
+
experimentalLocalRemoteKv: boolean | undefined;
|
|
71
78
|
}
|
|
72
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
|
+
|
|
73
92
|
export function Local(props: LocalProps) {
|
|
74
93
|
const { inspectorUrl } = useLocalWorker(props);
|
|
75
94
|
useInspector({
|
|
76
95
|
inspectorUrl,
|
|
77
96
|
port: props.inspectorPort,
|
|
78
|
-
logToTerminal: false,
|
|
97
|
+
logToTerminal: props.experimentalLocal ?? false,
|
|
79
98
|
});
|
|
80
99
|
return null;
|
|
81
100
|
}
|
|
@@ -90,21 +109,21 @@ function useLocalWorker({
|
|
|
90
109
|
bindings,
|
|
91
110
|
workerDefinitions,
|
|
92
111
|
assetPaths,
|
|
93
|
-
|
|
94
|
-
inspectorPort,
|
|
112
|
+
initialPort,
|
|
95
113
|
rules,
|
|
96
114
|
localPersistencePath,
|
|
97
115
|
liveReload,
|
|
98
|
-
|
|
116
|
+
initialIp,
|
|
99
117
|
crons,
|
|
100
118
|
queueConsumers,
|
|
101
119
|
localProtocol,
|
|
102
120
|
localUpstream,
|
|
103
121
|
inspect,
|
|
104
122
|
onReady,
|
|
105
|
-
logPrefix,
|
|
106
123
|
enablePagesAssetsServiceBinding,
|
|
107
124
|
experimentalLocal,
|
|
125
|
+
accountId,
|
|
126
|
+
experimentalLocalRemoteKv,
|
|
108
127
|
}: LocalProps) {
|
|
109
128
|
// TODO: pass vars via command line
|
|
110
129
|
const local = useRef<ChildProcess>();
|
|
@@ -113,6 +132,11 @@ function useLocalWorker({
|
|
|
113
132
|
const removeExperimentalLocalSignalExitListener = useRef<() => void>();
|
|
114
133
|
const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
|
|
115
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
|
+
|
|
116
140
|
useEffect(() => {
|
|
117
141
|
if (bindings.services && bindings.services.length > 0) {
|
|
118
142
|
logger.warn(
|
|
@@ -138,22 +162,6 @@ function useLocalWorker({
|
|
|
138
162
|
async function startLocalWorker() {
|
|
139
163
|
if (!bundle || !format) return;
|
|
140
164
|
|
|
141
|
-
// port for the worker
|
|
142
|
-
await waitForPortToBeAvailable(port, {
|
|
143
|
-
retryPeriod: 200,
|
|
144
|
-
timeout: 2000,
|
|
145
|
-
abortSignal: abortController.signal,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// In local mode, we want to copy all referenced modules into
|
|
149
|
-
// the output bundle directory before starting up
|
|
150
|
-
for (const module of bundle.modules) {
|
|
151
|
-
await writeFile(
|
|
152
|
-
path.join(path.dirname(bundle.path), module.name),
|
|
153
|
-
module.content
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
165
|
const scriptPath = realpathSync(bundle.path);
|
|
158
166
|
|
|
159
167
|
const upstream =
|
|
@@ -176,12 +184,15 @@ function useLocalWorker({
|
|
|
176
184
|
bundle,
|
|
177
185
|
});
|
|
178
186
|
|
|
187
|
+
runtimeInspectorPortRef.current ??= await getPort();
|
|
188
|
+
const runtimeInspectorPort = runtimeInspectorPortRef.current;
|
|
189
|
+
|
|
179
190
|
const { forkOptions, miniflareCLIPath, options } = setupMiniflareOptions({
|
|
180
191
|
workerName,
|
|
181
|
-
port,
|
|
192
|
+
port: initialPort,
|
|
182
193
|
scriptPath,
|
|
183
194
|
localProtocol,
|
|
184
|
-
ip,
|
|
195
|
+
ip: initialIp,
|
|
185
196
|
format,
|
|
186
197
|
rules,
|
|
187
198
|
compatibilityDate,
|
|
@@ -203,23 +214,37 @@ function useLocalWorker({
|
|
|
203
214
|
dataBlobBindings,
|
|
204
215
|
crons,
|
|
205
216
|
upstream,
|
|
206
|
-
logPrefix,
|
|
207
217
|
workerDefinitions,
|
|
208
218
|
enablePagesAssetsServiceBinding,
|
|
209
219
|
});
|
|
210
220
|
|
|
211
221
|
if (experimentalLocal) {
|
|
212
|
-
const
|
|
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,
|
|
235
|
+
});
|
|
236
|
+
|
|
213
237
|
const current = experimentalLocalRef.current;
|
|
238
|
+
|
|
214
239
|
if (current === undefined) {
|
|
215
240
|
// If we don't have an active Miniflare instance, create a new one
|
|
216
|
-
const Miniflare = await
|
|
241
|
+
const { Miniflare } = await getMiniflare3();
|
|
217
242
|
if (abortController.signal.aborted) return;
|
|
218
243
|
const mf = new Miniflare(mf3Options);
|
|
219
244
|
experimentalLocalRef.current = mf;
|
|
220
245
|
removeExperimentalLocalSignalExitListener.current = onExit(() => {
|
|
221
246
|
logger.log("⎔ Shutting down experimental local server.");
|
|
222
|
-
mf.dispose();
|
|
247
|
+
void mf.dispose();
|
|
223
248
|
experimentalLocalRef.current = undefined;
|
|
224
249
|
});
|
|
225
250
|
await mf.ready;
|
|
@@ -230,19 +255,61 @@ function useLocalWorker({
|
|
|
230
255
|
logger.log("⎔ Reloading experimental local server.");
|
|
231
256
|
await current.setOptions(mf3Options);
|
|
232
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
|
+
|
|
233
286
|
return;
|
|
234
287
|
}
|
|
235
288
|
|
|
236
|
-
|
|
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
|
+
});
|
|
237
302
|
logger.log("⎔ Starting a local server...");
|
|
238
303
|
|
|
304
|
+
const hasColourSupport =
|
|
305
|
+
chalk.supportsColor.hasBasic && process.env.FORCE_COLOR !== "0";
|
|
239
306
|
const child = (local.current = fork(miniflareCLIPath, forkOptions, {
|
|
240
307
|
cwd: path.dirname(scriptPath),
|
|
241
308
|
execArgv: nodeOptions,
|
|
242
309
|
stdio: "pipe",
|
|
243
310
|
env: {
|
|
244
311
|
...process.env,
|
|
245
|
-
FORCE_COLOR:
|
|
312
|
+
FORCE_COLOR: hasColourSupport ? "1" : undefined,
|
|
246
313
|
},
|
|
247
314
|
}));
|
|
248
315
|
|
|
@@ -254,21 +321,21 @@ function useLocalWorker({
|
|
|
254
321
|
await registerWorker(workerName, {
|
|
255
322
|
protocol: localProtocol,
|
|
256
323
|
mode: "local",
|
|
257
|
-
port,
|
|
258
|
-
host:
|
|
324
|
+
port: message.port,
|
|
325
|
+
host: initialIp,
|
|
259
326
|
durableObjects: internalDurableObjects.map((binding) => ({
|
|
260
327
|
name: binding.name,
|
|
261
328
|
className: binding.class_name,
|
|
262
329
|
})),
|
|
263
330
|
...(message.durableObjectsPort
|
|
264
331
|
? {
|
|
265
|
-
durableObjectsHost:
|
|
332
|
+
durableObjectsHost: initialIp,
|
|
266
333
|
durableObjectsPort: message.durableObjectsPort,
|
|
267
334
|
}
|
|
268
335
|
: {}),
|
|
269
336
|
});
|
|
270
337
|
}
|
|
271
|
-
onReady?.(
|
|
338
|
+
onReady?.(initialIp, message.port);
|
|
272
339
|
}
|
|
273
340
|
});
|
|
274
341
|
|
|
@@ -320,7 +387,13 @@ function useLocalWorker({
|
|
|
320
387
|
}
|
|
321
388
|
|
|
322
389
|
startLocalWorker().catch((err) => {
|
|
323
|
-
|
|
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
|
+
}
|
|
324
397
|
});
|
|
325
398
|
|
|
326
399
|
return () => {
|
|
@@ -337,9 +410,8 @@ function useLocalWorker({
|
|
|
337
410
|
bundle,
|
|
338
411
|
workerName,
|
|
339
412
|
format,
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
ip,
|
|
413
|
+
initialPort,
|
|
414
|
+
initialIp,
|
|
343
415
|
queueConsumers,
|
|
344
416
|
bindings.queues,
|
|
345
417
|
bindings.durable_objects,
|
|
@@ -363,10 +435,11 @@ function useLocalWorker({
|
|
|
363
435
|
localProtocol,
|
|
364
436
|
localUpstream,
|
|
365
437
|
inspect,
|
|
366
|
-
logPrefix,
|
|
367
438
|
onReady,
|
|
368
439
|
enablePagesAssetsServiceBinding,
|
|
369
440
|
experimentalLocal,
|
|
441
|
+
accountId,
|
|
442
|
+
experimentalLocalRemoteKv,
|
|
370
443
|
]);
|
|
371
444
|
|
|
372
445
|
// Rather than disposing the Miniflare instance on every reload, only dispose
|
|
@@ -500,7 +573,6 @@ interface SetupMiniflareOptionsProps {
|
|
|
500
573
|
dataBlobBindings: Record<string, string>;
|
|
501
574
|
crons: Config["triggers"]["crons"];
|
|
502
575
|
upstream: string | undefined;
|
|
503
|
-
logPrefix: string | undefined;
|
|
504
576
|
workerDefinitions: WorkerRegistry | undefined;
|
|
505
577
|
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
506
578
|
}
|
|
@@ -532,7 +604,6 @@ export function setupMiniflareOptions({
|
|
|
532
604
|
dataBlobBindings,
|
|
533
605
|
crons,
|
|
534
606
|
upstream,
|
|
535
|
-
logPrefix,
|
|
536
607
|
workerDefinitions,
|
|
537
608
|
enablePagesAssetsServiceBinding,
|
|
538
609
|
}: SetupMiniflareOptionsProps): {
|
|
@@ -645,7 +716,6 @@ export function setupMiniflareOptions({
|
|
|
645
716
|
crons,
|
|
646
717
|
upstream,
|
|
647
718
|
logLevel: logger.loggerLevel,
|
|
648
|
-
logOptions: logPrefix ? { prefix: logPrefix } : undefined,
|
|
649
719
|
enablePagesAssetsServiceBinding,
|
|
650
720
|
};
|
|
651
721
|
// The path to the Miniflare CLI assumes that this file is being run from
|
|
@@ -665,11 +735,9 @@ export function setupMiniflareOptions({
|
|
|
665
735
|
|
|
666
736
|
export function setupNodeOptions({
|
|
667
737
|
inspect,
|
|
668
|
-
ip,
|
|
669
738
|
inspectorPort,
|
|
670
739
|
}: {
|
|
671
740
|
inspect: boolean;
|
|
672
|
-
ip: string;
|
|
673
741
|
inspectorPort: number;
|
|
674
742
|
}) {
|
|
675
743
|
const nodeOptions = [
|
|
@@ -678,31 +746,123 @@ export function setupNodeOptions({
|
|
|
678
746
|
// "--log=VERBOSE", // uncomment this to Miniflare to log "everything"!
|
|
679
747
|
];
|
|
680
748
|
if (inspect) {
|
|
681
|
-
nodeOptions.push("--inspect=" +
|
|
749
|
+
nodeOptions.push("--inspect=" + `127.0.0.1:${inspectorPort}`); // start Miniflare listening for a debugger to attach
|
|
682
750
|
}
|
|
683
751
|
return nodeOptions;
|
|
684
752
|
}
|
|
685
753
|
|
|
686
|
-
|
|
687
|
-
|
|
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;
|
|
688
783
|
}
|
|
689
784
|
|
|
690
|
-
export async function
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
)
|
|
785
|
+
export async function buildMiniflare3Logger(): Promise<Miniflare3LogType> {
|
|
786
|
+
const { Log, NoOpLog, LogLevel } = await getMiniflare3();
|
|
787
|
+
|
|
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);
|
|
793
|
+
}
|
|
794
|
+
|
|
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
|
+
|
|
695
822
|
const options: Miniflare3Options = {
|
|
696
|
-
...
|
|
823
|
+
...miniflare2Options,
|
|
697
824
|
// Miniflare 3 distinguishes between binding name and namespace/bucket IDs.
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
r2Buckets:
|
|
702
|
-
|
|
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,
|
|
703
838
|
verbose: true,
|
|
839
|
+
cloudflareFetch,
|
|
840
|
+
log,
|
|
704
841
|
};
|
|
705
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
|
+
|
|
706
866
|
if (format === "modules") {
|
|
707
867
|
// Manually specify all modules from the bundle. If we didn't do this,
|
|
708
868
|
// Miniflare 3 would try collect them automatically again itself.
|
|
@@ -713,34 +873,48 @@ export async function transformLocalOptions(
|
|
|
713
873
|
const root = path.dirname(bundle.path);
|
|
714
874
|
|
|
715
875
|
assert.strictEqual(bundle.type, "esm");
|
|
876
|
+
// Required for source mapped paths to resolve correctly
|
|
877
|
+
options.modulesRoot = root;
|
|
716
878
|
options.modules = [
|
|
717
879
|
// Entrypoint
|
|
718
880
|
{
|
|
719
881
|
type: "ESModule",
|
|
720
|
-
path:
|
|
882
|
+
path: bundle.path,
|
|
721
883
|
contents: await readFile(bundle.path, "utf-8"),
|
|
722
884
|
},
|
|
723
885
|
// Misc (WebAssembly, etc, ...)
|
|
724
886
|
...bundle.modules.map((module) => ({
|
|
725
887
|
type: ModuleTypeToRuleType[module.type ?? "esm"],
|
|
726
|
-
path: module.name,
|
|
888
|
+
path: path.resolve(root, module.name),
|
|
727
889
|
contents: module.content,
|
|
728
890
|
})),
|
|
729
891
|
];
|
|
730
892
|
}
|
|
731
893
|
|
|
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)}`;
|
|
907
|
+
}
|
|
908
|
+
|
|
732
909
|
return options;
|
|
733
910
|
}
|
|
734
911
|
|
|
735
912
|
// Caching of the `npx-import`ed `@miniflare/tre` package
|
|
736
913
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
737
|
-
let
|
|
738
|
-
export async function
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
>("@miniflare/tre@3.0.0-next.5"));
|
|
744
|
-
}
|
|
745
|
-
return Miniflare;
|
|
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"));
|
|
746
920
|
}
|
package/src/dev/remote.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { Text } from "ink";
|
|
4
|
+
import SelectInput from "ink-select-input";
|
|
3
5
|
import React, { useState, useEffect, useRef } from "react";
|
|
4
6
|
import { useErrorHandler } from "react-error-boundary";
|
|
5
7
|
import { printBundleSize } from "../bundle-reporter";
|
|
@@ -10,9 +12,9 @@ import {
|
|
|
10
12
|
import useInspector from "../inspect";
|
|
11
13
|
import { logger } from "../logger";
|
|
12
14
|
import { startPreviewServer, usePreviewServer } from "../proxy";
|
|
15
|
+
import { helpIfErrorIsSizeOrScriptStartup } from "../publish/publish";
|
|
13
16
|
import { syncAssets } from "../sites";
|
|
14
17
|
import {
|
|
15
|
-
ChooseAccount,
|
|
16
18
|
getAccountChoices,
|
|
17
19
|
requireApiToken,
|
|
18
20
|
saveAccountToCache,
|
|
@@ -302,13 +304,13 @@ export function useWorker(
|
|
|
302
304
|
// TODO: Once we get service bindings working in the
|
|
303
305
|
// edge preview server, we can define remote dev service bindings
|
|
304
306
|
// and you can uncomment this code.
|
|
305
|
-
// https://github.com/cloudflare/
|
|
307
|
+
// https://github.com/cloudflare/workers-sdk/issues/1182
|
|
306
308
|
|
|
307
309
|
/*
|
|
308
310
|
if (name) {
|
|
309
311
|
await registerWorker(name, {
|
|
310
312
|
mode: "remote",
|
|
311
|
-
// upstream protocol is always https (https://github.com/cloudflare/
|
|
313
|
+
// upstream protocol is always https (https://github.com/cloudflare/workers-sdk/issues/583)
|
|
312
314
|
protocol: "https",
|
|
313
315
|
port: undefined,
|
|
314
316
|
host: workerPreviewToken.host,
|
|
@@ -493,6 +495,7 @@ export async function getRemotePreviewToken(props: RemoteProps) {
|
|
|
493
495
|
// code 10049 happens when the preview token expires
|
|
494
496
|
logger.log("Preview token expired, restart server to fetch a new one");
|
|
495
497
|
} else {
|
|
498
|
+
helpIfErrorIsSizeOrScriptStartup(err, props.bundle?.dependencies || {});
|
|
496
499
|
logger.error("Error on remote worker:", err);
|
|
497
500
|
}
|
|
498
501
|
}
|
|
@@ -601,3 +604,29 @@ function getWorkerAccountAndContext(props: {
|
|
|
601
604
|
|
|
602
605
|
return { workerAccount, workerContext };
|
|
603
606
|
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* A component that allows the user to select from a list of available accounts.
|
|
610
|
+
*/
|
|
611
|
+
function ChooseAccount(props: {
|
|
612
|
+
accounts: ChooseAccountItem[];
|
|
613
|
+
onSelect: (account: { name: string; id: string }) => void;
|
|
614
|
+
onError: (error: Error) => void;
|
|
615
|
+
}) {
|
|
616
|
+
return (
|
|
617
|
+
<>
|
|
618
|
+
<Text bold>Select an account from below:</Text>
|
|
619
|
+
<SelectInput
|
|
620
|
+
items={props.accounts.map((item) => ({
|
|
621
|
+
key: item.id,
|
|
622
|
+
label: item.name,
|
|
623
|
+
value: item,
|
|
624
|
+
}))}
|
|
625
|
+
onSelect={(item) => {
|
|
626
|
+
logger.log(`Using account: "${item.value.name} - ${item.value.id}"`);
|
|
627
|
+
props.onSelect({ id: item.value.id, name: item.value.name });
|
|
628
|
+
}}
|
|
629
|
+
/>
|
|
630
|
+
</>
|
|
631
|
+
);
|
|
632
|
+
}
|