wrangler 2.0.26 → 2.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +54 -46
- package/package.json +6 -4
- package/src/__tests__/api-dev.test.ts +19 -0
- package/src/__tests__/configuration.test.ts +33 -29
- package/src/__tests__/dev.test.tsx +8 -6
- package/src/__tests__/generate.test.ts +2 -4
- package/src/__tests__/helpers/hello-world-worker.js +5 -0
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
- package/src/__tests__/helpers/mock-known-routes.ts +7 -0
- package/src/__tests__/index.test.ts +30 -30
- package/src/__tests__/jest.setup.ts +17 -0
- package/src/__tests__/metrics.test.ts +1 -1
- package/src/__tests__/pages.test.ts +829 -103
- package/src/__tests__/paths.test.ts +17 -0
- package/src/__tests__/publish.test.ts +59 -18
- package/src/__tests__/r2.test.ts +4 -3
- package/src/__tests__/tail.test.ts +34 -0
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/user.test.ts +11 -0
- package/src/__tests__/worker-namespace.test.ts +37 -35
- package/src/api/dev.ts +74 -28
- package/src/bundle.ts +14 -11
- package/src/cfetch/internal.ts +81 -3
- package/src/cli.ts +1 -1
- package/src/config/environment.ts +1 -1
- package/src/config/index.ts +4 -4
- package/src/config/validation-helpers.ts +19 -6
- package/src/config/validation.ts +11 -5
- package/src/config-cache.ts +2 -1
- package/src/create-worker-upload-form.ts +29 -26
- package/src/dev/local.tsx +317 -169
- package/src/dev/remote.tsx +10 -1
- package/src/dev/start-server.ts +412 -0
- package/src/dev.tsx +341 -157
- package/src/{worker-namespace.ts → dispatch-namespace.ts} +18 -18
- package/src/entry.ts +2 -1
- package/src/generate.ts +1 -1
- package/src/index.tsx +54 -8
- package/src/init.ts +5 -5
- package/src/{metrics/is-ci.ts → is-ci.ts} +0 -0
- package/src/metrics/metrics-config.ts +1 -1
- package/src/metrics/send-event.ts +6 -5
- package/src/miniflare-cli/assets.ts +4 -65
- package/src/miniflare-cli/index.ts +36 -32
- package/src/pages/constants.ts +3 -0
- package/src/pages/dev.tsx +10 -15
- package/src/pages/functions/buildPlugin.ts +2 -1
- package/src/pages/functions/buildWorker.ts +2 -1
- package/src/pages/functions/routes-transformation.test.ts +12 -1
- package/src/pages/functions/routes-transformation.ts +7 -1
- package/src/pages/publish.tsx +82 -38
- package/src/paths.ts +20 -1
- package/src/proxy.ts +10 -0
- package/src/publish.ts +19 -4
- package/src/r2.ts +4 -4
- package/src/user/user.tsx +6 -4
- package/src/whoami.tsx +5 -5
- package/src/worker.ts +10 -9
- package/src/zones.ts +91 -0
- package/wrangler-dist/cli.d.ts +22 -8
- package/wrangler-dist/cli.js +7757 -2315
|
@@ -34,7 +34,7 @@ async function createWorkerNamespace(accountId: string, name: string) {
|
|
|
34
34
|
}
|
|
35
35
|
);
|
|
36
36
|
logger.log(
|
|
37
|
-
`Created
|
|
37
|
+
`Created dispatch namespace "${name}" with ID "${namespace.namespace_id}"`
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -46,7 +46,7 @@ async function deleteWorkerNamespace(accountId: string, name: string) {
|
|
|
46
46
|
`/accounts/${accountId}/workers/dispatch/namespaces/${name}`,
|
|
47
47
|
{ method: "DELETE" }
|
|
48
48
|
);
|
|
49
|
-
logger.log(`Deleted
|
|
49
|
+
logger.log(`Deleted dispatch namespace "${name}"`);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -101,7 +101,7 @@ async function renameWorkerNamespace(
|
|
|
101
101
|
body: JSON.stringify({ name: newName }),
|
|
102
102
|
}
|
|
103
103
|
);
|
|
104
|
-
logger.log(`Renamed
|
|
104
|
+
logger.log(`Renamed dispatch namespace "${oldName}" to "${newName}"`);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
export function workerNamespaceCommands(
|
|
@@ -110,20 +110,20 @@ export function workerNamespaceCommands(
|
|
|
110
110
|
): Argv {
|
|
111
111
|
return workerNamespaceYargs
|
|
112
112
|
.command(subHelp)
|
|
113
|
-
.command("list", "List all
|
|
113
|
+
.command("list", "List all dispatch namespaces", {}, async (args) => {
|
|
114
114
|
const config = readConfig(args.config as ConfigPath, args);
|
|
115
115
|
const accountId = await requireAuth(config);
|
|
116
116
|
await listWorkerNamespaces(accountId);
|
|
117
|
-
await metrics.sendMetricsEvent("list
|
|
117
|
+
await metrics.sendMetricsEvent("list dispatch namespaces", {
|
|
118
118
|
sendMetrics: config.send_metrics,
|
|
119
119
|
});
|
|
120
120
|
})
|
|
121
121
|
.command(
|
|
122
122
|
"get <name>",
|
|
123
|
-
"Get information about a
|
|
123
|
+
"Get information about a dispatch namespace",
|
|
124
124
|
(yargs) => {
|
|
125
125
|
return yargs.positional("name", {
|
|
126
|
-
describe: "Name of the
|
|
126
|
+
describe: "Name of the dispatch namespace",
|
|
127
127
|
type: "string",
|
|
128
128
|
demandOption: true,
|
|
129
129
|
});
|
|
@@ -132,17 +132,17 @@ export function workerNamespaceCommands(
|
|
|
132
132
|
const config = readConfig(args.config as ConfigPath, args);
|
|
133
133
|
const accountId = await requireAuth(config);
|
|
134
134
|
await getWorkerNamespaceInfo(accountId, args.name);
|
|
135
|
-
await metrics.sendMetricsEvent("view
|
|
135
|
+
await metrics.sendMetricsEvent("view dispatch namespace", {
|
|
136
136
|
sendMetrics: config.send_metrics,
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
)
|
|
140
140
|
.command(
|
|
141
141
|
"create <name>",
|
|
142
|
-
"Create a
|
|
142
|
+
"Create a dispatch namespace",
|
|
143
143
|
(yargs) => {
|
|
144
144
|
return yargs.positional("name", {
|
|
145
|
-
describe: "Name of the
|
|
145
|
+
describe: "Name of the dispatch namespace",
|
|
146
146
|
type: "string",
|
|
147
147
|
demandOption: true,
|
|
148
148
|
});
|
|
@@ -152,17 +152,17 @@ export function workerNamespaceCommands(
|
|
|
152
152
|
const config = readConfig(args.config as ConfigPath, args);
|
|
153
153
|
const accountId = await requireAuth(config);
|
|
154
154
|
await createWorkerNamespace(accountId, args.name);
|
|
155
|
-
await metrics.sendMetricsEvent("create
|
|
155
|
+
await metrics.sendMetricsEvent("create dispatch namespace", {
|
|
156
156
|
sendMetrics: config.send_metrics,
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
)
|
|
160
160
|
.command(
|
|
161
161
|
"delete <name>",
|
|
162
|
-
"Delete a
|
|
162
|
+
"Delete a dispatch namespace",
|
|
163
163
|
(yargs) => {
|
|
164
164
|
return yargs.positional("name", {
|
|
165
|
-
describe: "Name of the
|
|
165
|
+
describe: "Name of the dispatch namespace",
|
|
166
166
|
type: "string",
|
|
167
167
|
demandOption: true,
|
|
168
168
|
});
|
|
@@ -172,23 +172,23 @@ export function workerNamespaceCommands(
|
|
|
172
172
|
const config = readConfig(args.config as ConfigPath, args);
|
|
173
173
|
const accountId = await requireAuth(config);
|
|
174
174
|
await deleteWorkerNamespace(accountId, args.name);
|
|
175
|
-
await metrics.sendMetricsEvent("delete
|
|
175
|
+
await metrics.sendMetricsEvent("delete dispatch namespace", {
|
|
176
176
|
sendMetrics: config.send_metrics,
|
|
177
177
|
});
|
|
178
178
|
}
|
|
179
179
|
)
|
|
180
180
|
.command(
|
|
181
181
|
"rename <old-name> <new-name>",
|
|
182
|
-
"Rename a
|
|
182
|
+
"Rename a dispatch namespace",
|
|
183
183
|
(yargs) => {
|
|
184
184
|
return yargs
|
|
185
185
|
.positional("old-name", {
|
|
186
|
-
describe: "Name of the
|
|
186
|
+
describe: "Name of the dispatch namespace",
|
|
187
187
|
type: "string",
|
|
188
188
|
demandOption: true,
|
|
189
189
|
})
|
|
190
190
|
.positional("new-name", {
|
|
191
|
-
describe: "New name of the
|
|
191
|
+
describe: "New name of the dispatch namespace",
|
|
192
192
|
type: "string",
|
|
193
193
|
demandOption: true,
|
|
194
194
|
});
|
|
@@ -198,7 +198,7 @@ export function workerNamespaceCommands(
|
|
|
198
198
|
const config = readConfig(args.config as ConfigPath, args);
|
|
199
199
|
const accountId = await requireAuth(config);
|
|
200
200
|
await renameWorkerNamespace(accountId, args.oldName, args.newName);
|
|
201
|
-
await metrics.sendMetricsEvent("rename
|
|
201
|
+
await metrics.sendMetricsEvent("rename dispatch namespace", {
|
|
202
202
|
sendMetrics: config.send_metrics,
|
|
203
203
|
});
|
|
204
204
|
}
|
package/src/entry.ts
CHANGED
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import * as esbuild from "esbuild";
|
|
5
5
|
import { execaCommand } from "execa";
|
|
6
6
|
import { logger } from "./logger";
|
|
7
|
+
import { getBasePath } from "./paths";
|
|
7
8
|
import type { Config } from "./config";
|
|
8
9
|
import type { CfScriptFormat } from "./worker";
|
|
9
10
|
import type { Metafile } from "esbuild";
|
|
@@ -40,7 +41,7 @@ export async function getEntry(
|
|
|
40
41
|
: // site.entry-point could be a directory
|
|
41
42
|
path.resolve(config.site?.["entry-point"], "index.js");
|
|
42
43
|
} else if (args.assets || config.assets) {
|
|
43
|
-
file = path.resolve(
|
|
44
|
+
file = path.resolve(getBasePath(), "templates/no-op-worker.js");
|
|
44
45
|
} else {
|
|
45
46
|
throw new Error(
|
|
46
47
|
`Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler ${command} path/to/script\`) or the \`main\` config field.`
|
package/src/generate.ts
CHANGED
|
@@ -88,7 +88,7 @@ export async function generateHandler({
|
|
|
88
88
|
`Creating a worker in ${path.basename(creationDirectory)} from ${template}`
|
|
89
89
|
);
|
|
90
90
|
|
|
91
|
-
await createCloudflare(creationDirectory, template, {
|
|
91
|
+
await createCloudflare(path.basename(creationDirectory), template, {
|
|
92
92
|
init: true, // initialize a git repository
|
|
93
93
|
debug: logger.loggerLevel === "debug",
|
|
94
94
|
force: false, // do not overwrite an existing directory
|
package/src/index.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { findWranglerToml, readConfig } from "./config";
|
|
|
15
15
|
import { createWorkerUploadForm } from "./create-worker-upload-form";
|
|
16
16
|
import { devHandler, devOptions } from "./dev";
|
|
17
17
|
import { confirm, prompt } from "./dialogs";
|
|
18
|
+
import { workerNamespaceCommands } from "./dispatch-namespace";
|
|
18
19
|
import { getEntry } from "./entry";
|
|
19
20
|
import { DeprecationError } from "./errors";
|
|
20
21
|
import { generateHandler, generateOptions } from "./generate";
|
|
@@ -73,7 +74,7 @@ import {
|
|
|
73
74
|
} from "./user";
|
|
74
75
|
import { whoami } from "./whoami";
|
|
75
76
|
|
|
76
|
-
import {
|
|
77
|
+
import { getWorkerForZone } from "./zones";
|
|
77
78
|
import type { Config } from "./config";
|
|
78
79
|
import type { KeyValue } from "./kv";
|
|
79
80
|
import type { TailCLIFilters } from "./tail";
|
|
@@ -469,6 +470,19 @@ function createCLIParser(argv: string[]) {
|
|
|
469
470
|
requiresArg: true,
|
|
470
471
|
array: true,
|
|
471
472
|
})
|
|
473
|
+
.option("var", {
|
|
474
|
+
describe:
|
|
475
|
+
"A key-value pair to be injected into the script as a variable",
|
|
476
|
+
type: "string",
|
|
477
|
+
requiresArg: true,
|
|
478
|
+
array: true,
|
|
479
|
+
})
|
|
480
|
+
.option("define", {
|
|
481
|
+
describe: "A key-value pair to be substituted in the script",
|
|
482
|
+
type: "string",
|
|
483
|
+
requiresArg: true,
|
|
484
|
+
array: true,
|
|
485
|
+
})
|
|
472
486
|
.option("triggers", {
|
|
473
487
|
describe: "cron schedules to attach",
|
|
474
488
|
alias: ["schedule", "schedules"],
|
|
@@ -562,6 +576,20 @@ function createCLIParser(argv: string[]) {
|
|
|
562
576
|
);
|
|
563
577
|
}
|
|
564
578
|
|
|
579
|
+
const cliVars =
|
|
580
|
+
args.var?.reduce<Record<string, string>>((collectVars, v) => {
|
|
581
|
+
const [key, ...value] = v.split(":");
|
|
582
|
+
collectVars[key] = value.join("");
|
|
583
|
+
return collectVars;
|
|
584
|
+
}, {}) || {};
|
|
585
|
+
|
|
586
|
+
const cliDefines =
|
|
587
|
+
args.define?.reduce<Record<string, string>>((collectDefines, d) => {
|
|
588
|
+
const [key, ...value] = d.split(":");
|
|
589
|
+
collectDefines[key] = value.join("");
|
|
590
|
+
return collectDefines;
|
|
591
|
+
}, {}) || {};
|
|
592
|
+
|
|
565
593
|
const accountId = args.dryRun ? undefined : await requireAuth(config);
|
|
566
594
|
|
|
567
595
|
const assetPaths =
|
|
@@ -585,6 +613,8 @@ function createCLIParser(argv: string[]) {
|
|
|
585
613
|
? new Date().toISOString().substring(0, 10)
|
|
586
614
|
: args["compatibility-date"],
|
|
587
615
|
compatibilityFlags: args["compatibility-flags"],
|
|
616
|
+
vars: cliVars,
|
|
617
|
+
defines: cliDefines,
|
|
588
618
|
triggers: args.triggers,
|
|
589
619
|
jsxFactory: args["jsx-factory"],
|
|
590
620
|
jsxFragment: args["jsx-fragment"],
|
|
@@ -604,12 +634,12 @@ function createCLIParser(argv: string[]) {
|
|
|
604
634
|
|
|
605
635
|
// tail
|
|
606
636
|
wrangler.command(
|
|
607
|
-
"tail [
|
|
637
|
+
"tail [worker]",
|
|
608
638
|
"🦚 Starts a log tailing session for a published Worker.",
|
|
609
639
|
(yargs) => {
|
|
610
640
|
return yargs
|
|
611
|
-
.positional("
|
|
612
|
-
describe: "Name of the worker",
|
|
641
|
+
.positional("worker", {
|
|
642
|
+
describe: "Name or route of the worker to tail",
|
|
613
643
|
type: "string",
|
|
614
644
|
})
|
|
615
645
|
.option("format", {
|
|
@@ -677,7 +707,22 @@ function createCLIParser(argv: string[]) {
|
|
|
677
707
|
sendMetrics: config.send_metrics,
|
|
678
708
|
});
|
|
679
709
|
|
|
680
|
-
|
|
710
|
+
let scriptName;
|
|
711
|
+
|
|
712
|
+
// Worker names can't contain "." (and most routes should), so use that as a discriminator
|
|
713
|
+
if (args.worker?.includes(".")) {
|
|
714
|
+
scriptName = await getWorkerForZone(args.worker);
|
|
715
|
+
if (args.format === "pretty") {
|
|
716
|
+
logger.log(
|
|
717
|
+
`Connecting to worker ${scriptName} at route ${args.worker}`
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
} else {
|
|
721
|
+
scriptName = getLegacyScriptName(
|
|
722
|
+
{ name: args.worker, ...args },
|
|
723
|
+
config
|
|
724
|
+
);
|
|
725
|
+
}
|
|
681
726
|
|
|
682
727
|
if (!scriptName) {
|
|
683
728
|
throw new Error(
|
|
@@ -966,7 +1011,7 @@ function createCLIParser(argv: string[]) {
|
|
|
966
1011
|
wasm_modules: {},
|
|
967
1012
|
text_blobs: {},
|
|
968
1013
|
data_blobs: {},
|
|
969
|
-
|
|
1014
|
+
dispatch_namespaces: [],
|
|
970
1015
|
logfwdr: { schema: undefined, bindings: [] },
|
|
971
1016
|
unsafe: [],
|
|
972
1017
|
},
|
|
@@ -975,6 +1020,7 @@ function createCLIParser(argv: string[]) {
|
|
|
975
1020
|
compatibility_date: undefined,
|
|
976
1021
|
compatibility_flags: undefined,
|
|
977
1022
|
usage_model: undefined,
|
|
1023
|
+
keep_bindings: false, // this doesn't matter since it's a new script anyway
|
|
978
1024
|
}),
|
|
979
1025
|
}
|
|
980
1026
|
);
|
|
@@ -2022,8 +2068,8 @@ function createCLIParser(argv: string[]) {
|
|
|
2022
2068
|
});
|
|
2023
2069
|
|
|
2024
2070
|
wrangler.command(
|
|
2025
|
-
"
|
|
2026
|
-
"📦 Interact with a
|
|
2071
|
+
"dispatch-namespace",
|
|
2072
|
+
"📦 Interact with a dispatch namespace",
|
|
2027
2073
|
(workerNamespaceYargs) => {
|
|
2028
2074
|
return workerNamespaceCommands(workerNamespaceYargs, subHelp);
|
|
2029
2075
|
}
|
package/src/init.ts
CHANGED
|
@@ -12,10 +12,10 @@ import { initializeGit, isGitInstalled, isInsideGitRepo } from "./git-client";
|
|
|
12
12
|
import { logger } from "./logger";
|
|
13
13
|
import { getPackageManager } from "./package-manager";
|
|
14
14
|
import { parsePackageJSON, parseTOML, readFileSync } from "./parse";
|
|
15
|
+
import { getBasePath } from "./paths";
|
|
15
16
|
import { requireAuth } from "./user";
|
|
16
17
|
import { CommandLineArgsError, printWranglerBanner } from "./index";
|
|
17
18
|
import type { ConfigPath } from "./index";
|
|
18
|
-
|
|
19
19
|
import type { Argv, ArgumentsCamelCase } from "yargs";
|
|
20
20
|
|
|
21
21
|
export async function initOptions(yargs: Argv) {
|
|
@@ -162,7 +162,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
162
162
|
await initializeGit(creationDirectory);
|
|
163
163
|
await writeFile(
|
|
164
164
|
path.join(creationDirectory, ".gitignore"),
|
|
165
|
-
readFileSync(path.join(
|
|
165
|
+
readFileSync(path.join(getBasePath(), "templates/gitignore"))
|
|
166
166
|
);
|
|
167
167
|
logger.log(
|
|
168
168
|
args.name && args.name !== "."
|
|
@@ -254,7 +254,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
254
254
|
isTypescriptProject = true;
|
|
255
255
|
await writeFile(
|
|
256
256
|
path.join(creationDirectory, "./tsconfig.json"),
|
|
257
|
-
readFileSync(path.join(
|
|
257
|
+
readFileSync(path.join(getBasePath(), "templates/tsconfig.json"))
|
|
258
258
|
);
|
|
259
259
|
devDepsToInstall.push("@cloudflare/workers-types");
|
|
260
260
|
devDepsToInstall.push("typescript");
|
|
@@ -495,7 +495,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
495
495
|
});
|
|
496
496
|
await writeFile(
|
|
497
497
|
path.join(creationDirectory, "./src/index.ts"),
|
|
498
|
-
readFileSync(path.join(
|
|
498
|
+
readFileSync(path.join(getBasePath(), `templates/${template}`))
|
|
499
499
|
);
|
|
500
500
|
|
|
501
501
|
logger.log(
|
|
@@ -561,7 +561,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
561
561
|
});
|
|
562
562
|
await writeFile(
|
|
563
563
|
path.join(creationDirectory, "./src/index.js"),
|
|
564
|
-
readFileSync(path.join(
|
|
564
|
+
readFileSync(path.join(getBasePath(), `templates/${template}`))
|
|
565
565
|
);
|
|
566
566
|
|
|
567
567
|
logger.log(
|
|
File without changes
|
|
@@ -6,10 +6,10 @@ import { fetchResult } from "../cfetch";
|
|
|
6
6
|
import { getConfigCache, saveToConfigCache } from "../config-cache";
|
|
7
7
|
import { confirm } from "../dialogs";
|
|
8
8
|
import { getEnvironmentVariableFactory } from "../environment-variables";
|
|
9
|
+
import { CI } from "../is-ci";
|
|
9
10
|
import isInteractive from "../is-interactive";
|
|
10
11
|
import { logger } from "../logger";
|
|
11
12
|
import { getAPIToken } from "../user";
|
|
12
|
-
import { CI } from "./is-ci";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* The date that the metrics being gathered was last updated in a way that would require
|
|
@@ -40,17 +40,18 @@ export type EventNames =
|
|
|
40
40
|
| "unrevoke pubsub broker credentials"
|
|
41
41
|
| "list pubsub broker revoked credentials"
|
|
42
42
|
| "list pubsub broker public-keys"
|
|
43
|
-
| "list
|
|
44
|
-
| "view
|
|
45
|
-
| "create
|
|
46
|
-
| "delete
|
|
47
|
-
| "rename
|
|
43
|
+
| "list dispatch namespaces"
|
|
44
|
+
| "view dispatch namespace"
|
|
45
|
+
| "create dispatch namespace"
|
|
46
|
+
| "delete dispatch namespace"
|
|
47
|
+
| "rename dispatch namespace"
|
|
48
48
|
| "create pages project"
|
|
49
49
|
| "list pages projects"
|
|
50
50
|
| "create pages deployment"
|
|
51
51
|
| "list pages deployments"
|
|
52
52
|
| "build pages functions"
|
|
53
53
|
| "run dev"
|
|
54
|
+
| "run dev (api)"
|
|
54
55
|
| "run pages dev";
|
|
55
56
|
|
|
56
57
|
/**
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
generateRulesMatcher,
|
|
5
|
+
replacer,
|
|
6
|
+
} from "@cloudflare/pages-shared/src/asset-server/rulesEngine";
|
|
3
7
|
import { fetch as miniflareFetch } from "@miniflare/core";
|
|
4
8
|
import { watch } from "chokidar";
|
|
5
9
|
import { getType } from "mime";
|
|
@@ -54,71 +58,6 @@ export default async function generateASSETSBinding(options: Options) {
|
|
|
54
58
|
};
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
function escapeRegex(str: string) {
|
|
58
|
-
return str.replace(/[-/\\^$*+?.()|[]{}]/g, "\\$&");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
type Replacements = Record<string, string>;
|
|
62
|
-
|
|
63
|
-
function replacer(str: string, replacements: Replacements) {
|
|
64
|
-
for (const [replacement, value] of Object.entries(replacements)) {
|
|
65
|
-
str = str.replace(`:${replacement}`, value);
|
|
66
|
-
}
|
|
67
|
-
return str;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function generateRulesMatcher<T>(
|
|
71
|
-
rules?: Record<string, T>,
|
|
72
|
-
replacerFn: (match: T, replacements: Replacements) => T = (match) => match
|
|
73
|
-
) {
|
|
74
|
-
// TODO: How can you test cross-host rules?
|
|
75
|
-
if (!rules) return () => [];
|
|
76
|
-
|
|
77
|
-
const compiledRules = Object.entries(rules)
|
|
78
|
-
.map(([rule, match]) => {
|
|
79
|
-
const crossHost = rule.startsWith("https://");
|
|
80
|
-
|
|
81
|
-
rule = rule.split("*").map(escapeRegex).join("(?<splat>.*)");
|
|
82
|
-
|
|
83
|
-
const host_matches = rule.matchAll(
|
|
84
|
-
/(?<=^https:\\\/\\\/[^/]*?):([^\\]+)(?=\\)/g
|
|
85
|
-
);
|
|
86
|
-
for (const hostMatch of host_matches) {
|
|
87
|
-
rule = rule.split(hostMatch[0]).join(`(?<${hostMatch[1]}>[^/.]+)`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const path_matches = rule.matchAll(/:(\w+)/g);
|
|
91
|
-
for (const pathMatch of path_matches) {
|
|
92
|
-
rule = rule.split(pathMatch[0]).join(`(?<${pathMatch[1]}>[^/]+)`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
rule = "^" + rule + "$";
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
const regExp = new RegExp(rule);
|
|
99
|
-
return [{ crossHost, regExp }, match];
|
|
100
|
-
} catch {}
|
|
101
|
-
})
|
|
102
|
-
.filter((value) => value !== undefined) as [
|
|
103
|
-
{ crossHost: boolean; regExp: RegExp },
|
|
104
|
-
T
|
|
105
|
-
][];
|
|
106
|
-
|
|
107
|
-
return ({ request }: { request: MiniflareRequest }) => {
|
|
108
|
-
const { pathname, host } = new URL(request.url);
|
|
109
|
-
|
|
110
|
-
return compiledRules
|
|
111
|
-
.map(([{ crossHost, regExp }, match]) => {
|
|
112
|
-
const test = crossHost ? `https://${host}${pathname}` : pathname;
|
|
113
|
-
const result = regExp.exec(test);
|
|
114
|
-
if (result) {
|
|
115
|
-
return replacerFn(match, result.groups || {});
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
.filter((value) => value !== undefined) as T[];
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
61
|
function generateHeadersMatcher(headersFile: string) {
|
|
123
62
|
if (existsSync(headersFile)) {
|
|
124
63
|
const contents = readFileSync(headersFile).toString();
|
|
@@ -59,41 +59,45 @@ async function main() {
|
|
|
59
59
|
|
|
60
60
|
config.bindings = {
|
|
61
61
|
...config.bindings,
|
|
62
|
-
...
|
|
63
|
-
Object.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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 requestFromArgs = new MiniflareRequest(...reqArgs);
|
|
80
|
-
const url = new URL(requestFromArgs.url);
|
|
81
|
-
url.host = host;
|
|
82
|
-
if (port !== undefined) url.port = port.toString();
|
|
83
|
-
const request = new MiniflareRequest(
|
|
84
|
-
url.toString(),
|
|
85
|
-
requestFromArgs
|
|
62
|
+
...(config.externalDurableObjects &&
|
|
63
|
+
Object.fromEntries(
|
|
64
|
+
Object.entries(
|
|
65
|
+
config.externalDurableObjects as Record<
|
|
66
|
+
string,
|
|
67
|
+
{ name: string; host: string; port: number }
|
|
68
|
+
>
|
|
69
|
+
).map(([binding, { name, host, port }]) => {
|
|
70
|
+
const factory = () => {
|
|
71
|
+
throw new FatalError(
|
|
72
|
+
"An external Durable Object instance's state has somehow been attempted to be accessed.",
|
|
73
|
+
1
|
|
86
74
|
);
|
|
87
|
-
|
|
88
|
-
|
|
75
|
+
};
|
|
76
|
+
const namespace = new DurableObjectNamespace(name as string, factory);
|
|
77
|
+
namespace.get = (id) => {
|
|
78
|
+
const stub = new DurableObjectStub(factory, id);
|
|
79
|
+
stub.fetch = (...reqArgs) => {
|
|
80
|
+
const requestFromArgs = new MiniflareRequest(...reqArgs);
|
|
81
|
+
const url = new URL(requestFromArgs.url);
|
|
82
|
+
url.host = host;
|
|
83
|
+
if (port !== undefined) url.port = port.toString();
|
|
84
|
+
const request = new MiniflareRequest(
|
|
85
|
+
url.toString(),
|
|
86
|
+
requestFromArgs
|
|
87
|
+
);
|
|
88
|
+
request.headers.set("x-miniflare-durable-object-name", name);
|
|
89
|
+
request.headers.set(
|
|
90
|
+
"x-miniflare-durable-object-id",
|
|
91
|
+
id.toString()
|
|
92
|
+
);
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
return fetch(request);
|
|
95
|
+
};
|
|
96
|
+
return stub;
|
|
91
97
|
};
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
})
|
|
96
|
-
),
|
|
98
|
+
return [binding, namespace];
|
|
99
|
+
})
|
|
100
|
+
)),
|
|
97
101
|
};
|
|
98
102
|
|
|
99
103
|
let mf: Miniflare | undefined;
|
package/src/pages/constants.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { version as wranglerVersion } from "../../package.json";
|
|
2
|
+
|
|
1
3
|
export const PAGES_CONFIG_CACHE_FILENAME = "pages.json";
|
|
2
4
|
export const MAX_BUCKET_SIZE = 50 * 1024 * 1024;
|
|
3
5
|
export const MAX_BUCKET_FILE_COUNT = 5000;
|
|
@@ -10,3 +12,4 @@ export const isInPagesCI = !!process.env.CF_PAGES;
|
|
|
10
12
|
export const MAX_FUNCTIONS_ROUTES_RULES = 100;
|
|
11
13
|
export const MAX_FUNCTIONS_ROUTES_RULE_LENGTH = 100;
|
|
12
14
|
export const ROUTES_SPEC_VERSION = 1;
|
|
15
|
+
export const ROUTES_SPEC_DESCRIPTION = `Generated by wrangler@${wranglerVersion}`;
|
package/src/pages/dev.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { unstable_dev } from "../api";
|
|
|
8
8
|
import { FatalError } from "../errors";
|
|
9
9
|
import { logger } from "../logger";
|
|
10
10
|
import * as metrics from "../metrics";
|
|
11
|
+
import { getBasePath } from "../paths";
|
|
11
12
|
import { buildFunctions } from "./build";
|
|
12
13
|
import { SECONDS_TO_WAIT_FOR_PROXY } from "./constants";
|
|
13
14
|
import { FunctionsNoRoutesError, getFunctionsNoRoutesWarning } from "./errors";
|
|
@@ -274,7 +275,7 @@ export const Handler = async ({
|
|
|
274
275
|
|
|
275
276
|
if (!existsSync(scriptPath)) {
|
|
276
277
|
logger.log("No functions. Shimming...");
|
|
277
|
-
scriptPath = resolve(
|
|
278
|
+
scriptPath = resolve(getBasePath(), "templates/pages-shim.ts");
|
|
278
279
|
} else {
|
|
279
280
|
const runBuild = async () => {
|
|
280
281
|
try {
|
|
@@ -363,28 +364,20 @@ export const Handler = async ({
|
|
|
363
364
|
logLevel: "error",
|
|
364
365
|
logPrefix: "pages",
|
|
365
366
|
},
|
|
366
|
-
true
|
|
367
|
+
{ testMode: false, disableExperimentalWarning: true }
|
|
367
368
|
);
|
|
368
369
|
await metrics.sendMetricsEvent("run pages dev");
|
|
369
370
|
|
|
371
|
+
CLEANUP_CALLBACKS.push(stop);
|
|
372
|
+
|
|
370
373
|
waitUntilExit().then(() => {
|
|
371
374
|
CLEANUP();
|
|
372
|
-
stop();
|
|
373
375
|
process.exit(0);
|
|
374
376
|
});
|
|
375
377
|
|
|
376
|
-
process.on("exit",
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
});
|
|
380
|
-
process.on("SIGINT", () => {
|
|
381
|
-
CLEANUP();
|
|
382
|
-
stop();
|
|
383
|
-
});
|
|
384
|
-
process.on("SIGTERM", () => {
|
|
385
|
-
CLEANUP();
|
|
386
|
-
stop();
|
|
387
|
-
});
|
|
378
|
+
process.on("exit", CLEANUP);
|
|
379
|
+
process.on("SIGINT", CLEANUP);
|
|
380
|
+
process.on("SIGTERM", CLEANUP);
|
|
388
381
|
};
|
|
389
382
|
|
|
390
383
|
function isWindows() {
|
|
@@ -491,6 +484,8 @@ async function spawnProxyProcess({
|
|
|
491
484
|
|
|
492
485
|
proxy.on("close", (code) => {
|
|
493
486
|
logger.error(`Proxy exited with status ${code}.`);
|
|
487
|
+
CLEANUP();
|
|
488
|
+
process.exitCode = code ?? 0;
|
|
494
489
|
});
|
|
495
490
|
|
|
496
491
|
// Wait for proxy process to start...
|
|
@@ -3,6 +3,7 @@ import { dirname, relative, resolve } from "node:path";
|
|
|
3
3
|
import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
|
|
4
4
|
import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
|
|
5
5
|
import { build } from "esbuild";
|
|
6
|
+
import { getBasePath } from "../../paths";
|
|
6
7
|
|
|
7
8
|
type Options = {
|
|
8
9
|
routesModule: string;
|
|
@@ -24,7 +25,7 @@ export function buildPlugin({
|
|
|
24
25
|
onEnd = () => {},
|
|
25
26
|
}: Options) {
|
|
26
27
|
return build({
|
|
27
|
-
entryPoints: [resolve(
|
|
28
|
+
entryPoints: [resolve(getBasePath(), "templates/pages-template-plugin.ts")],
|
|
28
29
|
inject: [routesModule],
|
|
29
30
|
bundle: true,
|
|
30
31
|
format: "esm",
|
|
@@ -4,6 +4,7 @@ import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
|
|
|
4
4
|
import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
|
|
5
5
|
import { build } from "esbuild";
|
|
6
6
|
import { nanoid } from "nanoid";
|
|
7
|
+
import { getBasePath } from "../../paths";
|
|
7
8
|
|
|
8
9
|
type Options = {
|
|
9
10
|
routesModule: string;
|
|
@@ -29,7 +30,7 @@ export function buildWorker({
|
|
|
29
30
|
nodeCompat,
|
|
30
31
|
}: Options) {
|
|
31
32
|
return build({
|
|
32
|
-
entryPoints: [resolve(
|
|
33
|
+
entryPoints: [resolve(getBasePath(), "templates/pages-template-worker.ts")],
|
|
33
34
|
inject: [routesModule],
|
|
34
35
|
bundle: true,
|
|
35
36
|
format: "esm",
|