wrangler 2.0.22 → 2.0.25
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 +20 -2
- package/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +643 -7
- package/package.json +17 -5
- package/src/__tests__/configuration.test.ts +89 -17
- package/src/__tests__/dev.test.tsx +121 -8
- package/src/__tests__/generate.test.ts +93 -0
- package/src/__tests__/helpers/mock-cfetch.ts +54 -2
- package/src/__tests__/index.test.ts +10 -27
- package/src/__tests__/jest.setup.ts +31 -1
- package/src/__tests__/kv.test.ts +82 -61
- package/src/__tests__/metrics.test.ts +5 -0
- package/src/__tests__/publish.test.ts +573 -254
- package/src/__tests__/r2.test.ts +173 -71
- package/src/__tests__/tail.test.ts +93 -39
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/validate-dev-props.test.ts +56 -0
- package/src/__tests__/version.test.ts +35 -0
- package/src/__tests__/whoami.test.tsx +60 -1
- package/src/api/dev.ts +49 -9
- package/src/bundle.ts +298 -37
- package/src/cfetch/internal.ts +34 -2
- package/src/config/config.ts +15 -3
- package/src/config/environment.ts +40 -8
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +111 -9
- package/src/create-worker-preview.ts +3 -1
- package/src/create-worker-upload-form.ts +25 -0
- package/src/dev/dev.tsx +145 -31
- package/src/dev/local.tsx +116 -24
- package/src/dev/remote.tsx +39 -12
- package/src/dev/use-esbuild.ts +28 -0
- package/src/dev/validate-dev-props.ts +31 -0
- package/src/dev-registry.tsx +160 -0
- package/src/dev.tsx +148 -67
- package/src/generate.ts +112 -14
- package/src/index.tsx +252 -7
- package/src/inspect.ts +90 -5
- package/src/metrics/index.ts +1 -0
- package/src/metrics/metrics-dispatcher.ts +1 -0
- package/src/metrics/metrics-usage-headers.ts +24 -0
- package/src/metrics/send-event.ts +2 -2
- package/src/miniflare-cli/assets.ts +546 -0
- package/src/miniflare-cli/index.ts +157 -6
- package/src/module-collection.ts +3 -3
- package/src/pages/build.tsx +36 -28
- package/src/pages/constants.ts +4 -0
- package/src/pages/deployments.tsx +10 -10
- package/src/pages/dev.tsx +155 -651
- package/src/pages/functions/buildPlugin.ts +4 -0
- package/src/pages/functions/buildWorker.ts +4 -0
- package/src/pages/functions/routes-consolidation.test.ts +66 -0
- package/src/pages/functions/routes-consolidation.ts +29 -0
- package/src/pages/functions/routes-transformation.test.ts +271 -0
- package/src/pages/functions/routes-transformation.ts +125 -0
- package/src/pages/projects.tsx +9 -3
- package/src/pages/publish.tsx +57 -15
- package/src/pages/types.ts +9 -0
- package/src/pages/upload.tsx +38 -21
- package/src/publish.ts +139 -112
- package/src/r2.ts +81 -0
- package/src/tail/index.ts +15 -2
- package/src/tail/printing.ts +41 -3
- package/src/user/choose-account.tsx +20 -11
- package/src/user/user.tsx +20 -2
- package/src/whoami.tsx +79 -1
- package/src/worker.ts +12 -0
- package/templates/first-party-worker-module-facade.ts +18 -0
- package/templates/format-dev-errors.ts +32 -0
- package/templates/pages-shim.ts +9 -0
- package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
- package/templates/service-bindings-module-facade.js +51 -0
- package/templates/service-bindings-sw-facade.js +39 -0
- package/wrangler-dist/cli.d.ts +38 -3
- package/wrangler-dist/cli.js +45244 -25199
|
@@ -1,8 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fetch } from "@miniflare/core";
|
|
2
|
+
import {
|
|
3
|
+
DurableObjectNamespace,
|
|
4
|
+
DurableObjectStub,
|
|
5
|
+
} from "@miniflare/durable-objects";
|
|
6
|
+
import {
|
|
7
|
+
Log,
|
|
8
|
+
LogLevel,
|
|
9
|
+
Miniflare,
|
|
10
|
+
Response as MiniflareResponse,
|
|
11
|
+
Request as MiniflareRequest,
|
|
12
|
+
} from "miniflare";
|
|
2
13
|
import yargs from "yargs";
|
|
3
14
|
import { hideBin } from "yargs/helpers";
|
|
15
|
+
import { FatalError } from "../errors";
|
|
16
|
+
import generateASSETSBinding from "./assets";
|
|
4
17
|
import { enumKeys } from "./enum-keys";
|
|
5
18
|
import { getRequestContextCheckOptions } from "./request-context";
|
|
19
|
+
import type { Options } from "./assets";
|
|
20
|
+
import type { AddressInfo } from "net";
|
|
21
|
+
|
|
22
|
+
export interface EnablePagesAssetsServiceBindingOptions {
|
|
23
|
+
proxyPort?: number;
|
|
24
|
+
directory?: string;
|
|
25
|
+
}
|
|
6
26
|
|
|
7
27
|
// miniflare defines this but importing it throws:
|
|
8
28
|
// Dynamic require of "path" is not supported
|
|
@@ -29,24 +49,155 @@ async function main() {
|
|
|
29
49
|
...requestContextCheckOptions,
|
|
30
50
|
};
|
|
31
51
|
//miniflare's logLevel 0 still logs routes, so lets override the logger
|
|
32
|
-
config.log = config.disableLogs
|
|
52
|
+
config.log = config.disableLogs
|
|
53
|
+
? new NoOpLog()
|
|
54
|
+
: new Log(logLevel, config.logOptions);
|
|
33
55
|
|
|
34
56
|
if (logLevel > LogLevel.INFO) {
|
|
35
57
|
console.log("OPTIONS:\n", JSON.stringify(config, null, 2));
|
|
36
58
|
}
|
|
37
59
|
|
|
38
|
-
|
|
60
|
+
config.bindings = {
|
|
61
|
+
...config.bindings,
|
|
62
|
+
...Object.fromEntries(
|
|
63
|
+
Object.entries(
|
|
64
|
+
config.externalDurableObjects as Record<
|
|
65
|
+
string,
|
|
66
|
+
{ name: string; host: string; port: number }
|
|
67
|
+
>
|
|
68
|
+
).map(([binding, { name, host, port }]) => {
|
|
69
|
+
const factory = () => {
|
|
70
|
+
throw new FatalError(
|
|
71
|
+
"An external Durable Object instance's state has somehow been attempted to be accessed.",
|
|
72
|
+
1
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
const namespace = new DurableObjectNamespace(name as string, factory);
|
|
76
|
+
namespace.get = (id) => {
|
|
77
|
+
const stub = new DurableObjectStub(factory, id);
|
|
78
|
+
stub.fetch = (...reqArgs) => {
|
|
79
|
+
const url = `http://${host}${port ? `:${port}` : ""}`;
|
|
80
|
+
const request = new MiniflareRequest(
|
|
81
|
+
url,
|
|
82
|
+
new MiniflareRequest(...reqArgs)
|
|
83
|
+
);
|
|
84
|
+
request.headers.set("x-miniflare-durable-object-name", name);
|
|
85
|
+
request.headers.set("x-miniflare-durable-object-id", id.toString());
|
|
86
|
+
|
|
87
|
+
return fetch(request);
|
|
88
|
+
};
|
|
89
|
+
return stub;
|
|
90
|
+
};
|
|
91
|
+
return [binding, namespace];
|
|
92
|
+
})
|
|
93
|
+
),
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
let mf: Miniflare | undefined;
|
|
97
|
+
let durableObjectsMf: Miniflare | undefined = undefined;
|
|
98
|
+
let durableObjectsMfPort: number | undefined = undefined;
|
|
39
99
|
|
|
40
100
|
try {
|
|
101
|
+
if (args._[1]) {
|
|
102
|
+
const opts: EnablePagesAssetsServiceBindingOptions = JSON.parse(
|
|
103
|
+
args._[1] as string
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
if (isNaN(opts.proxyPort || NaN) && !opts.directory) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
"MiniflareCLIOptions: built in service bindings set to true, but no port or directory provided"
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const options: Options = {
|
|
113
|
+
log: config.log,
|
|
114
|
+
proxyPort: opts.proxyPort,
|
|
115
|
+
directory: opts.directory,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
config.serviceBindings = {
|
|
119
|
+
...config.serviceBindings,
|
|
120
|
+
ASSETS: await generateASSETSBinding(options),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
mf = new Miniflare(config);
|
|
41
124
|
// Start Miniflare development server
|
|
42
125
|
await mf.startServer();
|
|
43
126
|
await mf.startScheduler();
|
|
44
|
-
|
|
127
|
+
|
|
128
|
+
const internalDurableObjectClassNames = Object.values(
|
|
129
|
+
config.durableObjects as Record<string, string>
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (internalDurableObjectClassNames.length > 0) {
|
|
133
|
+
durableObjectsMf = new Miniflare({
|
|
134
|
+
host: config.host,
|
|
135
|
+
port: 0,
|
|
136
|
+
script: `
|
|
137
|
+
export default {
|
|
138
|
+
fetch(request, env) {
|
|
139
|
+
return env.DO.fetch(request)
|
|
140
|
+
}
|
|
141
|
+
}`,
|
|
142
|
+
serviceBindings: {
|
|
143
|
+
DO: async (request: MiniflareRequest) => {
|
|
144
|
+
request = new MiniflareRequest(request);
|
|
145
|
+
|
|
146
|
+
const name = request.headers.get("x-miniflare-durable-object-name");
|
|
147
|
+
const idString = request.headers.get(
|
|
148
|
+
"x-miniflare-durable-object-id"
|
|
149
|
+
);
|
|
150
|
+
request.headers.delete("x-miniflare-durable-object-name");
|
|
151
|
+
request.headers.delete("x-miniflare-durable-object-id");
|
|
152
|
+
|
|
153
|
+
if (!name || !idString) {
|
|
154
|
+
return new MiniflareResponse(
|
|
155
|
+
"[durable-object-proxy-err] Missing `x-miniflare-durable-object-name` or `x-miniflare-durable-object-id` headers.",
|
|
156
|
+
{ status: 400 }
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const namespace = await mf?.getDurableObjectNamespace(name);
|
|
161
|
+
const id = namespace?.idFromString(idString);
|
|
162
|
+
|
|
163
|
+
if (!id) {
|
|
164
|
+
return new MiniflareResponse(
|
|
165
|
+
"[durable-object-proxy-err] Could not generate an ID. Possibly due to a mismatched DO name and ID?",
|
|
166
|
+
{ status: 500 }
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const stub = namespace?.get(id);
|
|
171
|
+
|
|
172
|
+
if (!stub) {
|
|
173
|
+
return new MiniflareResponse(
|
|
174
|
+
"[durable-object-proxy-err] Could not generate a stub. Possibly due to a mismatched DO name and ID?",
|
|
175
|
+
{ status: 500 }
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return stub.fetch(request);
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
modules: true,
|
|
183
|
+
});
|
|
184
|
+
const server = await durableObjectsMf.startServer();
|
|
185
|
+
durableObjectsMfPort = (server.address() as AddressInfo).port;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
process.send &&
|
|
189
|
+
process.send(
|
|
190
|
+
JSON.stringify({
|
|
191
|
+
ready: true,
|
|
192
|
+
durableObjectsPort: durableObjectsMfPort,
|
|
193
|
+
})
|
|
194
|
+
);
|
|
45
195
|
} catch (e) {
|
|
46
|
-
mf
|
|
196
|
+
mf?.log.error(e as Error);
|
|
47
197
|
process.exitCode = 1;
|
|
48
198
|
// Unmount any mounted workers
|
|
49
|
-
await mf
|
|
199
|
+
await mf?.dispose();
|
|
200
|
+
await durableObjectsMf?.dispose();
|
|
50
201
|
}
|
|
51
202
|
}
|
|
52
203
|
|
package/src/module-collection.ts
CHANGED
|
@@ -123,9 +123,9 @@ export default function createModuleCollector(props: {
|
|
|
123
123
|
{
|
|
124
124
|
filter: new RegExp(
|
|
125
125
|
"^(" +
|
|
126
|
-
[...props.wrangler1xlegacyModuleReferences.fileNames]
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
[...props.wrangler1xlegacyModuleReferences.fileNames]
|
|
127
|
+
.map((name) => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
128
|
+
.join("|") +
|
|
129
129
|
")$"
|
|
130
130
|
),
|
|
131
131
|
},
|
package/src/pages/build.tsx
CHANGED
|
@@ -9,24 +9,15 @@ import { buildPlugin } from "./functions/buildPlugin";
|
|
|
9
9
|
import { buildWorker } from "./functions/buildWorker";
|
|
10
10
|
import { generateConfigFromFileTree } from "./functions/filepath-routing";
|
|
11
11
|
import { writeRoutesModule } from "./functions/routes";
|
|
12
|
+
import { convertRoutesToRoutesJSONSpec } from "./functions/routes-transformation";
|
|
12
13
|
import { pagesBetaWarning, RUNNING_BUILDERS } from "./utils";
|
|
13
14
|
import type { Config } from "./functions/routes";
|
|
14
|
-
import type {
|
|
15
|
+
import type { YargsOptionsToInterface } from "./types";
|
|
16
|
+
import type { Argv } from "yargs";
|
|
15
17
|
|
|
16
|
-
type PagesBuildArgs =
|
|
17
|
-
directory: string;
|
|
18
|
-
outfile: string;
|
|
19
|
-
"output-config-path"?: string;
|
|
20
|
-
minify: boolean;
|
|
21
|
-
sourcemap: boolean;
|
|
22
|
-
"fallback-service": string;
|
|
23
|
-
watch: boolean;
|
|
24
|
-
plugin: boolean;
|
|
25
|
-
"build-output-directory"?: string;
|
|
26
|
-
"node-compat": boolean;
|
|
27
|
-
};
|
|
18
|
+
type PagesBuildArgs = YargsOptionsToInterface<typeof Options>;
|
|
28
19
|
|
|
29
|
-
export function Options(yargs: Argv)
|
|
20
|
+
export function Options(yargs: Argv) {
|
|
30
21
|
return yargs
|
|
31
22
|
.positional("directory", {
|
|
32
23
|
type: "string",
|
|
@@ -43,6 +34,10 @@ export function Options(yargs: Argv): Argv<PagesBuildArgs> {
|
|
|
43
34
|
type: "string",
|
|
44
35
|
description: "The location for the output config file",
|
|
45
36
|
},
|
|
37
|
+
"output-routes-path": {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "The location for the output _routes.json file",
|
|
40
|
+
},
|
|
46
41
|
minify: {
|
|
47
42
|
type: "boolean",
|
|
48
43
|
default: false,
|
|
@@ -87,15 +82,16 @@ export function Options(yargs: Argv): Argv<PagesBuildArgs> {
|
|
|
87
82
|
export const Handler = async ({
|
|
88
83
|
directory,
|
|
89
84
|
outfile,
|
|
90
|
-
|
|
85
|
+
outputConfigPath,
|
|
86
|
+
outputRoutesPath: routesOutputPath,
|
|
91
87
|
minify,
|
|
92
88
|
sourcemap,
|
|
93
89
|
fallbackService,
|
|
94
90
|
watch,
|
|
95
91
|
plugin,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}:
|
|
92
|
+
buildOutputDirectory,
|
|
93
|
+
nodeCompat,
|
|
94
|
+
}: PagesBuildArgs) => {
|
|
99
95
|
if (!isInPagesCI) {
|
|
100
96
|
// Beta message for `wrangler pages <commands>` usage
|
|
101
97
|
logger.log(pagesBetaWarning);
|
|
@@ -120,6 +116,7 @@ export const Handler = async ({
|
|
|
120
116
|
plugin,
|
|
121
117
|
buildOutputDirectory,
|
|
122
118
|
nodeCompat,
|
|
119
|
+
routesOutputPath,
|
|
123
120
|
});
|
|
124
121
|
await metrics.sendMetricsEvent("build pages functions");
|
|
125
122
|
};
|
|
@@ -135,19 +132,25 @@ export async function buildFunctions({
|
|
|
135
132
|
onEnd,
|
|
136
133
|
plugin = false,
|
|
137
134
|
buildOutputDirectory,
|
|
135
|
+
routesOutputPath,
|
|
138
136
|
nodeCompat,
|
|
139
|
-
}:
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
}: Partial<
|
|
138
|
+
Pick<
|
|
139
|
+
PagesBuildArgs,
|
|
140
|
+
| "outputConfigPath"
|
|
141
|
+
| "minify"
|
|
142
|
+
| "sourcemap"
|
|
143
|
+
| "fallbackService"
|
|
144
|
+
| "watch"
|
|
145
|
+
| "plugin"
|
|
146
|
+
| "buildOutputDirectory"
|
|
147
|
+
| "nodeCompat"
|
|
148
|
+
>
|
|
149
|
+
> & {
|
|
142
150
|
functionsDirectory: string;
|
|
143
|
-
minify?: boolean;
|
|
144
|
-
sourcemap?: boolean;
|
|
145
|
-
fallbackService?: string;
|
|
146
|
-
watch?: boolean;
|
|
147
151
|
onEnd?: () => void;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
nodeCompat?: boolean;
|
|
152
|
+
outfile: Required<PagesBuildArgs>["outfile"];
|
|
153
|
+
routesOutputPath?: PagesBuildArgs["outputRoutesPath"];
|
|
151
154
|
}) {
|
|
152
155
|
RUNNING_BUILDERS.forEach(
|
|
153
156
|
(runningBuilder) => runningBuilder.stop && runningBuilder.stop()
|
|
@@ -161,6 +164,11 @@ export async function buildFunctions({
|
|
|
161
164
|
baseURL,
|
|
162
165
|
});
|
|
163
166
|
|
|
167
|
+
if (config.routes && routesOutputPath) {
|
|
168
|
+
const routesJSON = convertRoutesToRoutesJSONSpec(config.routes);
|
|
169
|
+
writeFileSync(routesOutputPath, JSON.stringify(routesJSON, null, 2));
|
|
170
|
+
}
|
|
171
|
+
|
|
164
172
|
if (outputConfigPath) {
|
|
165
173
|
writeFileSync(
|
|
166
174
|
outputConfigPath,
|
package/src/pages/constants.ts
CHANGED
|
@@ -3,5 +3,9 @@ export const MAX_BUCKET_SIZE = 50 * 1024 * 1024;
|
|
|
3
3
|
export const MAX_BUCKET_FILE_COUNT = 5000;
|
|
4
4
|
export const BULK_UPLOAD_CONCURRENCY = 3;
|
|
5
5
|
export const MAX_UPLOAD_ATTEMPTS = 5;
|
|
6
|
+
export const MAX_CHECK_MISSING_ATTEMPTS = 5;
|
|
6
7
|
export const SECONDS_TO_WAIT_FOR_PROXY = 5;
|
|
7
8
|
export const isInPagesCI = !!process.env.CF_PAGES;
|
|
9
|
+
/** The max number of rules in _routes.json */
|
|
10
|
+
export const MAX_FUNCTIONS_ROUTES_RULES = 100;
|
|
11
|
+
export const ROUTES_SPEC_VERSION = 1;
|
|
@@ -11,14 +11,16 @@ import { requireAuth } from "../user";
|
|
|
11
11
|
import { PAGES_CONFIG_CACHE_FILENAME } from "./constants";
|
|
12
12
|
import { listProjects } from "./projects";
|
|
13
13
|
import { pagesBetaWarning } from "./utils";
|
|
14
|
-
import type {
|
|
15
|
-
|
|
14
|
+
import type {
|
|
15
|
+
Deployment,
|
|
16
|
+
PagesConfigCache,
|
|
17
|
+
YargsOptionsToInterface,
|
|
18
|
+
} from "./types";
|
|
19
|
+
import type { Argv } from "yargs";
|
|
16
20
|
|
|
17
|
-
type ListArgs =
|
|
18
|
-
"project-name"?: string;
|
|
19
|
-
};
|
|
21
|
+
type ListArgs = YargsOptionsToInterface<typeof ListOptions>;
|
|
20
22
|
|
|
21
|
-
export function ListOptions(yargs: Argv)
|
|
23
|
+
export function ListOptions(yargs: Argv) {
|
|
22
24
|
return yargs
|
|
23
25
|
.options({
|
|
24
26
|
"project-name": {
|
|
@@ -30,9 +32,7 @@ export function ListOptions(yargs: Argv): Argv<ListArgs> {
|
|
|
30
32
|
.epilogue(pagesBetaWarning);
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
export async function ListHandler({
|
|
34
|
-
projectName,
|
|
35
|
-
}: ArgumentsCamelCase<ListArgs>) {
|
|
35
|
+
export async function ListHandler({ projectName }: ListArgs) {
|
|
36
36
|
const config = getConfigCache<PagesConfigCache>(PAGES_CONFIG_CACHE_FILENAME);
|
|
37
37
|
const accountId = await requireAuth(config);
|
|
38
38
|
|
|
@@ -102,5 +102,5 @@ export async function ListHandler({
|
|
|
102
102
|
patchConsole: false,
|
|
103
103
|
});
|
|
104
104
|
unmount();
|
|
105
|
-
await metrics.sendMetricsEvent("list pages
|
|
105
|
+
await metrics.sendMetricsEvent("list pages deployments");
|
|
106
106
|
}
|