wrangler 2.0.23 → 2.0.26
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 +235 -47
- package/package.json +11 -6
- package/src/__tests__/configuration.test.ts +89 -17
- package/src/__tests__/dev.test.tsx +29 -4
- package/src/__tests__/generate.test.ts +93 -0
- package/src/__tests__/helpers/mock-cfetch.ts +87 -2
- package/src/__tests__/index.test.ts +10 -27
- package/src/__tests__/init.test.ts +537 -359
- package/src/__tests__/jest.setup.ts +34 -1
- package/src/__tests__/kv.test.ts +2 -2
- package/src/__tests__/metrics.test.ts +5 -0
- package/src/__tests__/pages.test.ts +14 -0
- package/src/__tests__/publish.test.ts +497 -254
- package/src/__tests__/r2.test.ts +173 -71
- package/src/__tests__/tail.test.ts +112 -42
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/validate-dev-props.test.ts +56 -0
- package/src/__tests__/whoami.test.tsx +60 -1
- package/src/api/dev.ts +7 -0
- package/src/bundle.ts +279 -44
- package/src/cfetch/internal.ts +73 -2
- package/src/config/config.ts +8 -3
- package/src/config/environment.ts +40 -8
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +102 -8
- package/src/create-worker-upload-form.ts +25 -0
- package/src/dev/dev.tsx +121 -28
- package/src/dev/local.tsx +88 -14
- package/src/dev/remote.tsx +39 -8
- 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 +107 -80
- package/src/generate.ts +112 -14
- package/src/index.tsx +212 -4
- package/src/init.ts +111 -38
- 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 +27 -16
- package/src/miniflare-cli/index.ts +124 -2
- package/src/module-collection.ts +3 -3
- package/src/pages/build.tsx +75 -41
- package/src/pages/constants.ts +5 -0
- package/src/pages/deployments.tsx +10 -10
- package/src/pages/dev.tsx +177 -52
- package/src/pages/errors.ts +22 -0
- package/src/pages/functions/buildPlugin.ts +4 -0
- package/src/pages/functions/buildWorker.ts +4 -0
- package/src/pages/functions/routes-consolidation.test.ts +250 -0
- package/src/pages/functions/routes-consolidation.ts +73 -0
- package/src/pages/functions/routes-transformation.test.ts +271 -0
- package/src/pages/functions/routes-transformation.ts +122 -0
- package/src/pages/functions.tsx +96 -0
- package/src/pages/index.tsx +65 -55
- package/src/pages/projects.tsx +9 -3
- package/src/pages/publish.tsx +76 -23
- package/src/pages/types.ts +9 -0
- package/src/pages/upload.tsx +38 -21
- package/src/publish.ts +126 -112
- package/src/r2.ts +81 -0
- package/src/tail/filters.ts +3 -1
- package/src/tail/index.ts +15 -2
- package/src/tail/printing.ts +43 -3
- 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-template-plugin.ts +16 -4
- package/templates/pages-template-worker.ts +16 -5
- package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
- package/templates/service-bindings-module-facade.js +54 -0
- package/templates/service-bindings-sw-facade.js +42 -0
- package/wrangler-dist/cli.d.ts +7 -0
- package/wrangler-dist/cli.js +40851 -15332
package/src/pages/build.tsx
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
+
import { FatalError } from "../errors";
|
|
4
5
|
import { logger } from "../logger";
|
|
5
6
|
import * as metrics from "../metrics";
|
|
6
7
|
import { toUrlPath } from "../paths";
|
|
7
8
|
import { isInPagesCI } from "./constants";
|
|
9
|
+
import {
|
|
10
|
+
EXIT_CODE_FUNCTIONS_NO_ROUTES_ERROR,
|
|
11
|
+
FunctionsNoRoutesError,
|
|
12
|
+
getFunctionsNoRoutesWarning,
|
|
13
|
+
} from "./errors";
|
|
8
14
|
import { buildPlugin } from "./functions/buildPlugin";
|
|
9
15
|
import { buildWorker } from "./functions/buildWorker";
|
|
10
16
|
import { generateConfigFromFileTree } from "./functions/filepath-routing";
|
|
11
17
|
import { writeRoutesModule } from "./functions/routes";
|
|
18
|
+
import { convertRoutesToRoutesJSONSpec } from "./functions/routes-transformation";
|
|
12
19
|
import { pagesBetaWarning, RUNNING_BUILDERS } from "./utils";
|
|
13
20
|
import type { Config } from "./functions/routes";
|
|
14
|
-
import type {
|
|
21
|
+
import type { YargsOptionsToInterface } from "./types";
|
|
22
|
+
import type { Argv } from "yargs";
|
|
15
23
|
|
|
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
|
-
};
|
|
24
|
+
type PagesBuildArgs = YargsOptionsToInterface<typeof Options>;
|
|
28
25
|
|
|
29
|
-
export function Options(yargs: Argv)
|
|
26
|
+
export function Options(yargs: Argv) {
|
|
30
27
|
return yargs
|
|
31
28
|
.positional("directory", {
|
|
32
29
|
type: "string",
|
|
@@ -43,6 +40,10 @@ export function Options(yargs: Argv): Argv<PagesBuildArgs> {
|
|
|
43
40
|
type: "string",
|
|
44
41
|
description: "The location for the output config file",
|
|
45
42
|
},
|
|
43
|
+
"output-routes-path": {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "The location for the output _routes.json file",
|
|
46
|
+
},
|
|
46
47
|
minify: {
|
|
47
48
|
type: "boolean",
|
|
48
49
|
default: false,
|
|
@@ -87,15 +88,16 @@ export function Options(yargs: Argv): Argv<PagesBuildArgs> {
|
|
|
87
88
|
export const Handler = async ({
|
|
88
89
|
directory,
|
|
89
90
|
outfile,
|
|
90
|
-
|
|
91
|
+
outputConfigPath,
|
|
92
|
+
outputRoutesPath: routesOutputPath,
|
|
91
93
|
minify,
|
|
92
94
|
sourcemap,
|
|
93
95
|
fallbackService,
|
|
94
96
|
watch,
|
|
95
97
|
plugin,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}:
|
|
98
|
+
buildOutputDirectory,
|
|
99
|
+
nodeCompat,
|
|
100
|
+
}: PagesBuildArgs) => {
|
|
99
101
|
if (!isInPagesCI) {
|
|
100
102
|
// Beta message for `wrangler pages <commands>` usage
|
|
101
103
|
logger.log(pagesBetaWarning);
|
|
@@ -108,22 +110,37 @@ export const Handler = async ({
|
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
buildOutputDirectory ??= dirname(outfile);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
113
|
+
try {
|
|
114
|
+
await buildFunctions({
|
|
115
|
+
outfile,
|
|
116
|
+
outputConfigPath,
|
|
117
|
+
functionsDirectory: directory,
|
|
118
|
+
minify,
|
|
119
|
+
sourcemap,
|
|
120
|
+
fallbackService,
|
|
121
|
+
watch,
|
|
122
|
+
plugin,
|
|
123
|
+
buildOutputDirectory,
|
|
124
|
+
nodeCompat,
|
|
125
|
+
routesOutputPath,
|
|
126
|
+
});
|
|
127
|
+
} catch (e) {
|
|
128
|
+
if (e instanceof FunctionsNoRoutesError) {
|
|
129
|
+
throw new FatalError(
|
|
130
|
+
getFunctionsNoRoutesWarning(directory),
|
|
131
|
+
EXIT_CODE_FUNCTIONS_NO_ROUTES_ERROR
|
|
132
|
+
);
|
|
133
|
+
} else {
|
|
134
|
+
throw e;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
124
137
|
await metrics.sendMetricsEvent("build pages functions");
|
|
125
138
|
};
|
|
126
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Builds a Functions worker based on the functions directory, with filepath and handler based routing.
|
|
142
|
+
* @throws FunctionsNoRoutesError when there are no routes found in the functions directory
|
|
143
|
+
*/
|
|
127
144
|
export async function buildFunctions({
|
|
128
145
|
outfile,
|
|
129
146
|
outputConfigPath,
|
|
@@ -135,19 +152,25 @@ export async function buildFunctions({
|
|
|
135
152
|
onEnd,
|
|
136
153
|
plugin = false,
|
|
137
154
|
buildOutputDirectory,
|
|
155
|
+
routesOutputPath,
|
|
138
156
|
nodeCompat,
|
|
139
|
-
}:
|
|
140
|
-
|
|
141
|
-
|
|
157
|
+
}: Partial<
|
|
158
|
+
Pick<
|
|
159
|
+
PagesBuildArgs,
|
|
160
|
+
| "outputConfigPath"
|
|
161
|
+
| "minify"
|
|
162
|
+
| "sourcemap"
|
|
163
|
+
| "fallbackService"
|
|
164
|
+
| "watch"
|
|
165
|
+
| "plugin"
|
|
166
|
+
| "buildOutputDirectory"
|
|
167
|
+
| "nodeCompat"
|
|
168
|
+
>
|
|
169
|
+
> & {
|
|
142
170
|
functionsDirectory: string;
|
|
143
|
-
minify?: boolean;
|
|
144
|
-
sourcemap?: boolean;
|
|
145
|
-
fallbackService?: string;
|
|
146
|
-
watch?: boolean;
|
|
147
171
|
onEnd?: () => void;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
nodeCompat?: boolean;
|
|
172
|
+
outfile: Required<PagesBuildArgs>["outfile"];
|
|
173
|
+
routesOutputPath?: PagesBuildArgs["outputRoutesPath"];
|
|
151
174
|
}) {
|
|
152
175
|
RUNNING_BUILDERS.forEach(
|
|
153
176
|
(runningBuilder) => runningBuilder.stop && runningBuilder.stop()
|
|
@@ -161,6 +184,17 @@ export async function buildFunctions({
|
|
|
161
184
|
baseURL,
|
|
162
185
|
});
|
|
163
186
|
|
|
187
|
+
if (!config.routes || config.routes.length === 0) {
|
|
188
|
+
throw new FunctionsNoRoutesError(
|
|
189
|
+
`Failed to find any routes while compiling Functions in: ${functionsDirectory}`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (routesOutputPath) {
|
|
194
|
+
const routesJSON = convertRoutesToRoutesJSONSpec(config.routes);
|
|
195
|
+
writeFileSync(routesOutputPath, JSON.stringify(routesJSON, null, 2));
|
|
196
|
+
}
|
|
197
|
+
|
|
164
198
|
if (outputConfigPath) {
|
|
165
199
|
writeFileSync(
|
|
166
200
|
outputConfigPath,
|
package/src/pages/constants.ts
CHANGED
|
@@ -3,5 +3,10 @@ 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 MAX_FUNCTIONS_ROUTES_RULE_LENGTH = 100;
|
|
12
|
+
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
|
}
|
package/src/pages/dev.tsx
CHANGED
|
@@ -1,34 +1,29 @@
|
|
|
1
1
|
import { execSync, spawn } from "node:child_process";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
3
|
+
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { watch } from "chokidar";
|
|
6
|
+
import { build as workerJsBuild } from "esbuild";
|
|
6
7
|
import { unstable_dev } from "../api";
|
|
7
8
|
import { FatalError } from "../errors";
|
|
8
9
|
import { logger } from "../logger";
|
|
9
10
|
import * as metrics from "../metrics";
|
|
10
11
|
import { buildFunctions } from "./build";
|
|
11
12
|
import { SECONDS_TO_WAIT_FOR_PROXY } from "./constants";
|
|
13
|
+
import { FunctionsNoRoutesError, getFunctionsNoRoutesWarning } from "./errors";
|
|
12
14
|
import { CLEANUP, CLEANUP_CALLBACKS, pagesBetaWarning } from "./utils";
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
type
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
kv?: (string | number)[];
|
|
24
|
-
do?: (string | number)[];
|
|
25
|
-
"live-reload": boolean;
|
|
26
|
-
"local-protocol"?: "https" | "http";
|
|
27
|
-
"experimental-enable-local-persistence": boolean;
|
|
28
|
-
"node-compat": boolean;
|
|
29
|
-
};
|
|
15
|
+
import type { AdditionalDevProps } from "../dev";
|
|
16
|
+
import type { YargsOptionsToInterface } from "./types";
|
|
17
|
+
import type { Plugin } from "esbuild";
|
|
18
|
+
import type { Argv } from "yargs";
|
|
19
|
+
|
|
20
|
+
const DURABLE_OBJECTS_BINDING_REGEXP = new RegExp(
|
|
21
|
+
/^(?<binding>[^=]+)=(?<className>[^@\s]+)(@(?<scriptName>.*)$)?$/
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
type PagesDevArgs = YargsOptionsToInterface<typeof Options>;
|
|
30
25
|
|
|
31
|
-
export function Options(yargs: Argv)
|
|
26
|
+
export function Options(yargs: Argv) {
|
|
32
27
|
return yargs
|
|
33
28
|
.positional("directory", {
|
|
34
29
|
type: "string",
|
|
@@ -46,11 +41,41 @@ export function Options(yargs: Argv): Argv<PagesDevArgs> {
|
|
|
46
41
|
default: true,
|
|
47
42
|
description: "Run on my machine",
|
|
48
43
|
},
|
|
44
|
+
"compatibility-date": {
|
|
45
|
+
describe: "Date to use for compatibility checks",
|
|
46
|
+
type: "string",
|
|
47
|
+
},
|
|
48
|
+
"compatibility-flags": {
|
|
49
|
+
describe: "Flags to use for compatibility checks",
|
|
50
|
+
alias: "compatibility-flag",
|
|
51
|
+
type: "string",
|
|
52
|
+
array: true,
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// TODO
|
|
56
|
+
// For now, all Pages projects are set to 2021-11-02. We're adding compat date soon, and we can then adopt `wrangler dev`'s `default: true`.
|
|
57
|
+
// However, it looks like it isn't actually connected up properly in `wrangler dev` at the moment, hence commenting this out for now.
|
|
58
|
+
|
|
59
|
+
// latest: {
|
|
60
|
+
// describe: "Use the latest version of the worker runtime",
|
|
61
|
+
// type: "boolean",
|
|
62
|
+
// default: false,
|
|
63
|
+
// },
|
|
64
|
+
|
|
65
|
+
ip: {
|
|
66
|
+
type: "string",
|
|
67
|
+
default: "0.0.0.0",
|
|
68
|
+
description: "The IP address to listen on",
|
|
69
|
+
},
|
|
49
70
|
port: {
|
|
50
71
|
type: "number",
|
|
51
72
|
default: 8788,
|
|
52
73
|
description: "The port to listen on (serve from)",
|
|
53
74
|
},
|
|
75
|
+
"inspector-port": {
|
|
76
|
+
type: "number",
|
|
77
|
+
describe: "Port for devtools to connect to",
|
|
78
|
+
},
|
|
54
79
|
proxy: {
|
|
55
80
|
type: "number",
|
|
56
81
|
description: "The port to proxy (where the static assets are served)",
|
|
@@ -68,14 +93,18 @@ export function Options(yargs: Argv): Argv<PagesDevArgs> {
|
|
|
68
93
|
},
|
|
69
94
|
kv: {
|
|
70
95
|
type: "array",
|
|
71
|
-
description: "KV namespace to bind",
|
|
96
|
+
description: "KV namespace to bind (--kv KV_BINDING)",
|
|
72
97
|
alias: "k",
|
|
73
98
|
},
|
|
74
99
|
do: {
|
|
75
100
|
type: "array",
|
|
76
|
-
description: "Durable Object to bind (NAME=CLASS)",
|
|
101
|
+
description: "Durable Object to bind (--do NAME=CLASS)",
|
|
77
102
|
alias: "o",
|
|
78
103
|
},
|
|
104
|
+
r2: {
|
|
105
|
+
type: "array",
|
|
106
|
+
description: "R2 bucket to bind (--r2 R2_BINDING)",
|
|
107
|
+
},
|
|
79
108
|
"live-reload": {
|
|
80
109
|
type: "boolean",
|
|
81
110
|
default: false,
|
|
@@ -108,19 +137,24 @@ export function Options(yargs: Argv): Argv<PagesDevArgs> {
|
|
|
108
137
|
export const Handler = async ({
|
|
109
138
|
local,
|
|
110
139
|
directory,
|
|
140
|
+
"compatibility-date": compatibilityDate = "2021-11-02",
|
|
141
|
+
"compatibility-flags": compatibilityFlags,
|
|
142
|
+
ip,
|
|
111
143
|
port,
|
|
144
|
+
"inspector-port": inspectorPort,
|
|
112
145
|
proxy: requestedProxyPort,
|
|
113
146
|
"script-path": singleWorkerScriptPath,
|
|
114
147
|
binding: bindings = [],
|
|
115
148
|
kv: kvs = [],
|
|
116
149
|
do: durableObjects = [],
|
|
150
|
+
r2: r2s = [],
|
|
117
151
|
"live-reload": liveReload,
|
|
118
152
|
"local-protocol": localProtocol,
|
|
119
153
|
"experimental-enable-local-persistence": experimentalEnableLocalPersistence,
|
|
120
154
|
"node-compat": nodeCompat,
|
|
121
155
|
config: config,
|
|
122
156
|
_: [_pages, _dev, ...remaining],
|
|
123
|
-
}:
|
|
157
|
+
}: PagesDevArgs) => {
|
|
124
158
|
// Beta message for `wrangler pages <commands>` usage
|
|
125
159
|
logger.log(pagesBetaWarning);
|
|
126
160
|
|
|
@@ -133,13 +167,18 @@ export const Handler = async ({
|
|
|
133
167
|
}
|
|
134
168
|
|
|
135
169
|
const functionsDirectory = "./functions";
|
|
136
|
-
|
|
170
|
+
let usingFunctions = existsSync(functionsDirectory);
|
|
137
171
|
|
|
138
172
|
const command = remaining;
|
|
139
173
|
|
|
140
174
|
let proxyPort: number | undefined;
|
|
141
175
|
|
|
142
|
-
if (directory
|
|
176
|
+
if (directory !== undefined && command.length > 0) {
|
|
177
|
+
throw new FatalError(
|
|
178
|
+
"Specify either a directory OR a proxy command, not both.",
|
|
179
|
+
1
|
|
180
|
+
);
|
|
181
|
+
} else if (directory === undefined) {
|
|
143
182
|
proxyPort = await spawnProxyProcess({
|
|
144
183
|
port: requestedProxyPort,
|
|
145
184
|
command,
|
|
@@ -154,8 +193,9 @@ export const Handler = async ({
|
|
|
154
193
|
(promiseResolve) => (scriptReadyResolve = promiseResolve)
|
|
155
194
|
);
|
|
156
195
|
|
|
157
|
-
let scriptPath
|
|
196
|
+
let scriptPath = "";
|
|
158
197
|
|
|
198
|
+
// Try to use Functions
|
|
159
199
|
if (usingFunctions) {
|
|
160
200
|
const outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.js`);
|
|
161
201
|
scriptPath = outfile;
|
|
@@ -167,36 +207,63 @@ export const Handler = async ({
|
|
|
167
207
|
}
|
|
168
208
|
|
|
169
209
|
logger.log(`Compiling worker to "${outfile}"...`);
|
|
170
|
-
|
|
210
|
+
const onEnd = () => scriptReadyResolve();
|
|
171
211
|
try {
|
|
172
212
|
await buildFunctions({
|
|
173
213
|
outfile,
|
|
174
214
|
functionsDirectory,
|
|
175
215
|
sourcemap: true,
|
|
176
216
|
watch: true,
|
|
177
|
-
onEnd
|
|
217
|
+
onEnd,
|
|
178
218
|
buildOutputDirectory: directory,
|
|
179
219
|
nodeCompat,
|
|
180
220
|
});
|
|
181
221
|
await metrics.sendMetricsEvent("build pages functions");
|
|
182
|
-
} catch {}
|
|
183
222
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
223
|
+
// If Functions found routes, continue using Functions
|
|
224
|
+
watch([functionsDirectory], {
|
|
225
|
+
persistent: true,
|
|
226
|
+
ignoreInitial: true,
|
|
227
|
+
}).on("all", async () => {
|
|
228
|
+
try {
|
|
229
|
+
await buildFunctions({
|
|
230
|
+
outfile,
|
|
231
|
+
functionsDirectory,
|
|
232
|
+
sourcemap: true,
|
|
233
|
+
watch: true,
|
|
234
|
+
onEnd,
|
|
235
|
+
buildOutputDirectory: directory,
|
|
236
|
+
nodeCompat,
|
|
237
|
+
});
|
|
238
|
+
await metrics.sendMetricsEvent("build pages functions");
|
|
239
|
+
} catch (e) {
|
|
240
|
+
if (e instanceof FunctionsNoRoutesError) {
|
|
241
|
+
logger.warn(
|
|
242
|
+
getFunctionsNoRoutesWarning(functionsDirectory, "skipping")
|
|
243
|
+
);
|
|
244
|
+
} else {
|
|
245
|
+
throw e;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
196
248
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
249
|
+
} catch (e) {
|
|
250
|
+
// If there are no Functions, then Pages will only serve assets.
|
|
251
|
+
if (e instanceof FunctionsNoRoutesError) {
|
|
252
|
+
logger.warn(
|
|
253
|
+
getFunctionsNoRoutesWarning(functionsDirectory, "skipping")
|
|
254
|
+
);
|
|
255
|
+
// Resolve anyway and run without Functions
|
|
256
|
+
onEnd();
|
|
257
|
+
// Turn off Functions
|
|
258
|
+
usingFunctions = false;
|
|
259
|
+
} else {
|
|
260
|
+
throw e;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Depending on the result of building Functions, we may not actually be using
|
|
265
|
+
// Functions even if the directory exists.
|
|
266
|
+
if (!usingFunctions) {
|
|
200
267
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
201
268
|
scriptReadyResolve!();
|
|
202
269
|
|
|
@@ -208,20 +275,48 @@ export const Handler = async ({
|
|
|
208
275
|
if (!existsSync(scriptPath)) {
|
|
209
276
|
logger.log("No functions. Shimming...");
|
|
210
277
|
scriptPath = resolve(__dirname, "../templates/pages-shim.ts");
|
|
278
|
+
} else {
|
|
279
|
+
const runBuild = async () => {
|
|
280
|
+
try {
|
|
281
|
+
await workerJsBuild({
|
|
282
|
+
entryPoints: [scriptPath],
|
|
283
|
+
write: false,
|
|
284
|
+
plugins: [blockWorkerJsImports],
|
|
285
|
+
});
|
|
286
|
+
} catch {}
|
|
287
|
+
};
|
|
288
|
+
await runBuild();
|
|
289
|
+
watch([scriptPath], {
|
|
290
|
+
persistent: true,
|
|
291
|
+
ignoreInitial: true,
|
|
292
|
+
}).on("all", async () => {
|
|
293
|
+
await runBuild();
|
|
294
|
+
});
|
|
211
295
|
}
|
|
212
296
|
}
|
|
213
297
|
|
|
214
298
|
await scriptReadyPromise;
|
|
215
299
|
|
|
300
|
+
if (scriptPath === "") {
|
|
301
|
+
// Failed to get a script with or without Functions,
|
|
302
|
+
// something really bad must have happend.
|
|
303
|
+
throw new FatalError(
|
|
304
|
+
"Failed to start wrangler pages dev due to an unknown error",
|
|
305
|
+
1
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
216
309
|
const { stop, waitUntilExit } = await unstable_dev(
|
|
217
310
|
scriptPath,
|
|
218
311
|
{
|
|
312
|
+
ip,
|
|
219
313
|
port,
|
|
314
|
+
inspectorPort,
|
|
220
315
|
watch: true,
|
|
221
316
|
localProtocol,
|
|
222
317
|
liveReload,
|
|
223
|
-
|
|
224
|
-
|
|
318
|
+
compatibilityDate,
|
|
319
|
+
compatibilityFlags,
|
|
225
320
|
nodeCompat,
|
|
226
321
|
vars: Object.fromEntries(
|
|
227
322
|
bindings
|
|
@@ -232,12 +327,29 @@ export const Handler = async ({
|
|
|
232
327
|
binding: val.toString(),
|
|
233
328
|
id: "",
|
|
234
329
|
})),
|
|
235
|
-
durableObjects: durableObjects
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
330
|
+
durableObjects: durableObjects
|
|
331
|
+
.map((durableObject) => {
|
|
332
|
+
const { binding, className, scriptName } =
|
|
333
|
+
DURABLE_OBJECTS_BINDING_REGEXP.exec(durableObject.toString())
|
|
334
|
+
?.groups || {};
|
|
335
|
+
|
|
336
|
+
if (!binding || !className) {
|
|
337
|
+
logger.warn(
|
|
338
|
+
"Could not parse Durable Object binding:",
|
|
339
|
+
durableObject.toString()
|
|
340
|
+
);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
name: binding,
|
|
346
|
+
class_name: className,
|
|
347
|
+
script_name: scriptName,
|
|
348
|
+
};
|
|
349
|
+
})
|
|
350
|
+
.filter(Boolean) as AdditionalDevProps["durableObjects"],
|
|
351
|
+
r2: r2s.map((binding) => {
|
|
352
|
+
return { binding: binding.toString(), bucket_name: "" };
|
|
241
353
|
}),
|
|
242
354
|
|
|
243
355
|
enablePagesAssetsServiceBinding: {
|
|
@@ -314,7 +426,8 @@ function getPort(pid: number) {
|
|
|
314
426
|
let command: string, regExp: RegExp;
|
|
315
427
|
|
|
316
428
|
if (isWindows()) {
|
|
317
|
-
|
|
429
|
+
const drive = homedir().split(":\\")[0];
|
|
430
|
+
command = drive + ":\\windows\\system32\\netstat.exe -nao";
|
|
318
431
|
regExp = new RegExp(`TCP\\s+.*:(\\d+)\\s+.*:\\d+\\s+LISTENING\\s+${pid}`);
|
|
319
432
|
} else {
|
|
320
433
|
command = "lsof -nPi";
|
|
@@ -407,3 +520,15 @@ async function spawnProxyProcess({
|
|
|
407
520
|
|
|
408
521
|
return port;
|
|
409
522
|
}
|
|
523
|
+
|
|
524
|
+
const blockWorkerJsImports: Plugin = {
|
|
525
|
+
name: "block-worker-js-imports",
|
|
526
|
+
setup(build) {
|
|
527
|
+
build.onResolve({ filter: /.*/g }, (_args) => {
|
|
528
|
+
logger.error(
|
|
529
|
+
`_worker.js is importing from another file. This will throw an error if deployed.\nYou should bundle your Worker or remove the import if it is unused.`
|
|
530
|
+
);
|
|
531
|
+
return null;
|
|
532
|
+
});
|
|
533
|
+
},
|
|
534
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pages error when no routes are found in the functions directory
|
|
3
|
+
*/
|
|
4
|
+
export class FunctionsNoRoutesError extends Error {
|
|
5
|
+
constructor(message: string) {
|
|
6
|
+
super(message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Exit code for `pages functions build` when no routes are found.
|
|
11
|
+
*/
|
|
12
|
+
export const EXIT_CODE_FUNCTIONS_NO_ROUTES_ERROR = 156;
|
|
13
|
+
|
|
14
|
+
/** Warning message for when buildFunctions throws FunctionsNoRoutesError */
|
|
15
|
+
export function getFunctionsNoRoutesWarning(
|
|
16
|
+
functionsDirectory: string,
|
|
17
|
+
suffix?: string
|
|
18
|
+
) {
|
|
19
|
+
return `No routes found when building Functions directory: ${functionsDirectory}${
|
|
20
|
+
suffix ? " - " + suffix : ""
|
|
21
|
+
}`;
|
|
22
|
+
}
|