wrangler 2.0.25 → 2.0.28

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.
Files changed (66) hide show
  1. package/bin/wrangler.js +1 -1
  2. package/miniflare-dist/index.mjs +15 -3
  3. package/package.json +8 -6
  4. package/src/__tests__/configuration.test.ts +33 -29
  5. package/src/__tests__/dev.test.tsx +8 -6
  6. package/src/__tests__/generate.test.ts +2 -4
  7. package/src/__tests__/helpers/mock-cfetch.ts +33 -0
  8. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  9. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  10. package/src/__tests__/index.test.ts +30 -30
  11. package/src/__tests__/init.test.ts +537 -359
  12. package/src/__tests__/jest.setup.ts +7 -0
  13. package/src/__tests__/metrics.test.ts +1 -1
  14. package/src/__tests__/pages.test.ts +14 -0
  15. package/src/__tests__/publish.test.ts +59 -18
  16. package/src/__tests__/r2.test.ts +4 -3
  17. package/src/__tests__/tail.test.ts +53 -3
  18. package/src/__tests__/test-old-node-version.js +3 -3
  19. package/src/__tests__/user.test.ts +11 -0
  20. package/src/__tests__/worker-namespace.test.ts +37 -35
  21. package/src/api/dev.ts +1 -0
  22. package/src/bundle.ts +1 -1
  23. package/src/cfetch/internal.ts +118 -1
  24. package/src/config/environment.ts +1 -1
  25. package/src/config/index.ts +4 -4
  26. package/src/config/validation-helpers.ts +19 -6
  27. package/src/config/validation.ts +11 -5
  28. package/src/config-cache.ts +2 -1
  29. package/src/create-worker-upload-form.ts +29 -26
  30. package/src/dev/dev.tsx +4 -0
  31. package/src/dev/remote.tsx +10 -1
  32. package/src/dev.tsx +36 -8
  33. package/src/{worker-namespace.ts → dispatch-namespace.ts} +18 -18
  34. package/src/generate.ts +1 -1
  35. package/src/index.tsx +54 -8
  36. package/src/init.ts +111 -38
  37. package/src/{metrics/is-ci.ts → is-ci.ts} +0 -0
  38. package/src/metrics/metrics-config.ts +1 -1
  39. package/src/metrics/send-event.ts +5 -5
  40. package/src/miniflare-cli/assets.ts +8 -0
  41. package/src/miniflare-cli/index.ts +6 -3
  42. package/src/pages/build.tsx +41 -15
  43. package/src/pages/constants.ts +1 -0
  44. package/src/pages/dev.tsx +93 -37
  45. package/src/pages/errors.ts +22 -0
  46. package/src/pages/functions/routes-consolidation.test.ts +185 -1
  47. package/src/pages/functions/routes-consolidation.ts +46 -2
  48. package/src/pages/functions/routes-transformation.ts +0 -3
  49. package/src/pages/functions.tsx +96 -0
  50. package/src/pages/index.tsx +65 -55
  51. package/src/pages/publish.tsx +27 -16
  52. package/src/proxy.ts +10 -0
  53. package/src/publish.ts +19 -4
  54. package/src/r2.ts +4 -4
  55. package/src/tail/filters.ts +3 -1
  56. package/src/tail/printing.ts +2 -0
  57. package/src/user/user.tsx +6 -4
  58. package/src/whoami.tsx +5 -5
  59. package/src/worker.ts +3 -2
  60. package/src/zones.ts +91 -0
  61. package/templates/pages-template-plugin.ts +16 -4
  62. package/templates/pages-template-worker.ts +16 -5
  63. package/templates/service-bindings-module-facade.js +10 -7
  64. package/templates/service-bindings-sw-facade.js +10 -7
  65. package/wrangler-dist/cli.d.ts +8 -3
  66. package/wrangler-dist/cli.js +6757 -1639
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 { workerNamespaceCommands } from "./worker-namespace";
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 [name]",
637
+ "tail [worker]",
608
638
  "🦚 Starts a log tailing session for a published Worker.",
609
639
  (yargs) => {
610
640
  return yargs
611
- .positional("name", {
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
- const scriptName = getLegacyScriptName(args, config);
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
- worker_namespaces: [],
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
- "worker-namespace",
2026
- "📦 Interact with a worker namespace",
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
@@ -5,12 +5,16 @@ import TOML from "@iarna/toml";
5
5
  import { findUp } from "find-up";
6
6
  import { version as wranglerVersion } from "../package.json";
7
7
 
8
+ import { fetchDashboardScript } from "./cfetch/internal";
9
+ import { readConfig } from "./config";
8
10
  import { confirm, select } from "./dialogs";
9
11
  import { initializeGit, isGitInstalled, isInsideGitRepo } from "./git-client";
10
12
  import { logger } from "./logger";
11
13
  import { getPackageManager } from "./package-manager";
12
14
  import { parsePackageJSON, parseTOML, readFileSync } from "./parse";
15
+ import { requireAuth } from "./user";
13
16
  import { CommandLineArgsError, printWranglerBanner } from "./index";
17
+ import type { ConfigPath } from "./index";
14
18
 
15
19
  import type { Argv, ArgumentsCamelCase } from "yargs";
16
20
 
@@ -36,6 +40,12 @@ export async function initOptions(yargs: Argv) {
36
40
  describe: 'Answer "yes" to any prompts for new projects',
37
41
  type: "boolean",
38
42
  alias: "y",
43
+ })
44
+ .option("from-dash", {
45
+ describe: "Download script from the dashboard for local development",
46
+ type: "string",
47
+ requiresArg: true,
48
+ hidden: true,
39
49
  });
40
50
  }
41
51
 
@@ -61,7 +71,11 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
61
71
  const devDepsToInstall: string[] = [];
62
72
  const instructions: string[] = [];
63
73
  let shouldRunPackageManagerInstall = false;
64
- const creationDirectory = path.resolve(process.cwd(), args.name ?? "");
74
+ const fromDashScriptName = args["from-dash"] as string;
75
+ const creationDirectory = path.resolve(
76
+ process.cwd(),
77
+ (args.name ? args.name : fromDashScriptName) ?? ""
78
+ );
65
79
 
66
80
  if (args.site) {
67
81
  const gitDirectory =
@@ -90,6 +104,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
90
104
 
91
105
  // TODO: ask which directory to make the worker in (defaults to args.name)
92
106
  // TODO: if args.name isn't provided, ask what to name the worker
107
+ // Note: `--from-dash` will be a fallback creationDir/Worker name if none is provided.
93
108
 
94
109
  const wranglerTomlDestination = path.join(
95
110
  creationDirectory,
@@ -98,12 +113,15 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
98
113
  let justCreatedWranglerToml = false;
99
114
 
100
115
  if (fs.existsSync(wranglerTomlDestination)) {
116
+ let shouldContinue = false;
101
117
  logger.warn(
102
118
  `${path.relative(process.cwd(), wranglerTomlDestination)} already exists!`
103
119
  );
104
- const shouldContinue = await confirm(
105
- "Do you want to continue initializing this project?"
106
- );
120
+ if (!fromDashScriptName) {
121
+ shouldContinue = await confirm(
122
+ "Do you want to continue initializing this project?"
123
+ );
124
+ }
107
125
  if (!shouldContinue) {
108
126
  return;
109
127
  }
@@ -438,27 +456,23 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
438
456
  process.cwd(),
439
457
  path.join(creationDirectory, "./src/index.ts")
440
458
  );
441
-
442
- const newWorkerType = yesFlag
443
- ? "fetch"
444
- : await getNewWorkerType(newWorkerFilename);
445
-
446
- if (newWorkerType !== "none") {
447
- const template = getNewWorkerTemplate("ts", newWorkerType);
448
-
459
+ if (fromDashScriptName) {
460
+ const config = readConfig(args.config as ConfigPath, args);
461
+ const accountId = await requireAuth(config);
449
462
  await mkdir(path.join(creationDirectory, "./src"), {
450
463
  recursive: true,
451
464
  });
452
- await writeFile(
453
- path.join(creationDirectory, "./src/index.ts"),
454
- readFileSync(path.join(__dirname, `../templates/${template}`))
465
+
466
+ const dashScript = await fetchDashboardScript(
467
+ `/accounts/${accountId}/workers/scripts/${fromDashScriptName}`,
468
+ {
469
+ method: "GET",
470
+ }
455
471
  );
456
472
 
457
- logger.log(
458
- `✨ Created ${path.relative(
459
- process.cwd(),
460
- path.join(creationDirectory, "./src/index.ts")
461
- )}`
473
+ await writeFile(
474
+ path.join(creationDirectory, "./src/index.ts"),
475
+ dashScript
462
476
  );
463
477
 
464
478
  await writePackageJsonScriptsAndUpdateWranglerToml(
@@ -466,8 +480,39 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
466
480
  justCreatedWranglerToml,
467
481
  pathToPackageJson,
468
482
  "src/index.ts",
469
- getNewWorkerToml(newWorkerType)
483
+ {}
470
484
  );
485
+ } else {
486
+ const newWorkerType = yesFlag
487
+ ? "fetch"
488
+ : await getNewWorkerType(newWorkerFilename);
489
+
490
+ if (newWorkerType !== "none") {
491
+ const template = getNewWorkerTemplate("ts", newWorkerType);
492
+
493
+ await mkdir(path.join(creationDirectory, "./src"), {
494
+ recursive: true,
495
+ });
496
+ await writeFile(
497
+ path.join(creationDirectory, "./src/index.ts"),
498
+ readFileSync(path.join(__dirname, `../templates/${template}`))
499
+ );
500
+
501
+ logger.log(
502
+ `✨ Created ${path.relative(
503
+ process.cwd(),
504
+ path.join(creationDirectory, "./src/index.ts")
505
+ )}`
506
+ );
507
+
508
+ await writePackageJsonScriptsAndUpdateWranglerToml(
509
+ shouldWritePackageJsonScripts,
510
+ justCreatedWranglerToml,
511
+ pathToPackageJson,
512
+ "src/index.ts",
513
+ getNewWorkerToml(newWorkerType)
514
+ );
515
+ }
471
516
  }
472
517
  }
473
518
  } else {
@@ -477,35 +522,63 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
477
522
  path.join(creationDirectory, "./src/index.js")
478
523
  );
479
524
 
480
- const newWorkerType = yesFlag
481
- ? "fetch"
482
- : await getNewWorkerType(newWorkerFilename);
483
-
484
- if (newWorkerType !== "none") {
485
- const template = getNewWorkerTemplate("js", newWorkerType);
486
-
525
+ if (fromDashScriptName) {
526
+ const config = readConfig(args.config as ConfigPath, args);
527
+ const accountId = await requireAuth(config);
487
528
  await mkdir(path.join(creationDirectory, "./src"), {
488
529
  recursive: true,
489
530
  });
490
- await writeFile(
491
- path.join(creationDirectory, "./src/index.js"),
492
- readFileSync(path.join(__dirname, `../templates/${template}`))
531
+
532
+ const dashScript = await fetchDashboardScript(
533
+ `/accounts/${accountId}/workers/scripts/${fromDashScriptName}`,
534
+ {
535
+ method: "GET",
536
+ }
493
537
  );
494
538
 
495
- logger.log(
496
- `✨ Created ${path.relative(
497
- process.cwd(),
498
- path.join(creationDirectory, "./src/index.js")
499
- )}`
539
+ await writeFile(
540
+ path.join(creationDirectory, "./src/index.js"),
541
+ dashScript
500
542
  );
501
543
 
502
544
  await writePackageJsonScriptsAndUpdateWranglerToml(
503
545
  shouldWritePackageJsonScripts,
504
546
  justCreatedWranglerToml,
505
547
  pathToPackageJson,
506
- "src/index.js",
507
- getNewWorkerToml(newWorkerType)
548
+ "src/index.ts",
549
+ {}
508
550
  );
551
+ } else {
552
+ const newWorkerType = yesFlag
553
+ ? "fetch"
554
+ : await getNewWorkerType(newWorkerFilename);
555
+
556
+ if (newWorkerType !== "none") {
557
+ const template = getNewWorkerTemplate("js", newWorkerType);
558
+
559
+ await mkdir(path.join(creationDirectory, "./src"), {
560
+ recursive: true,
561
+ });
562
+ await writeFile(
563
+ path.join(creationDirectory, "./src/index.js"),
564
+ readFileSync(path.join(__dirname, `../templates/${template}`))
565
+ );
566
+
567
+ logger.log(
568
+ `✨ Created ${path.relative(
569
+ process.cwd(),
570
+ path.join(creationDirectory, "./src/index.js")
571
+ )}`
572
+ );
573
+
574
+ await writePackageJsonScriptsAndUpdateWranglerToml(
575
+ shouldWritePackageJsonScripts,
576
+ justCreatedWranglerToml,
577
+ pathToPackageJson,
578
+ "src/index.js",
579
+ getNewWorkerToml(newWorkerType)
580
+ );
581
+ }
509
582
  }
510
583
  }
511
584
  }
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,11 +40,11 @@ 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 worker namespaces"
44
- | "view worker namespace"
45
- | "create worker namespace"
46
- | "delete worker namespace"
47
- | "rename worker namespace"
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"
@@ -466,6 +466,14 @@ async function generateAssetsFetch(
466
466
  return deconstructedResponse;
467
467
  }
468
468
  } else if (hasFileExtension(assetName)) {
469
+ if ((asset = getAsset(assetName + ".html"))) {
470
+ deconstructedResponse.body = serveAsset(asset);
471
+ deconstructedResponse.headers.set(
472
+ "Content-Type",
473
+ getType(asset) || "application/octet-stream"
474
+ );
475
+ return deconstructedResponse;
476
+ }
469
477
  notFound();
470
478
  return deconstructedResponse;
471
479
  }
@@ -76,10 +76,13 @@ async function main() {
76
76
  namespace.get = (id) => {
77
77
  const stub = new DurableObjectStub(factory, id);
78
78
  stub.fetch = (...reqArgs) => {
79
- const url = `http://${host}${port ? `:${port}` : ""}`;
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();
80
83
  const request = new MiniflareRequest(
81
- url,
82
- new MiniflareRequest(...reqArgs)
84
+ url.toString(),
85
+ requestFromArgs
83
86
  );
84
87
  request.headers.set("x-miniflare-durable-object-name", name);
85
88
  request.headers.set("x-miniflare-durable-object-id", id.toString());
@@ -1,10 +1,16 @@
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";
@@ -104,23 +110,37 @@ export const Handler = async ({
104
110
  }
105
111
 
106
112
  buildOutputDirectory ??= dirname(outfile);
107
-
108
- await buildFunctions({
109
- outfile,
110
- outputConfigPath,
111
- functionsDirectory: directory,
112
- minify,
113
- sourcemap,
114
- fallbackService,
115
- watch,
116
- plugin,
117
- buildOutputDirectory,
118
- nodeCompat,
119
- routesOutputPath,
120
- });
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
+ }
121
137
  await metrics.sendMetricsEvent("build pages functions");
122
138
  };
123
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
+ */
124
144
  export async function buildFunctions({
125
145
  outfile,
126
146
  outputConfigPath,
@@ -164,7 +184,13 @@ export async function buildFunctions({
164
184
  baseURL,
165
185
  });
166
186
 
167
- if (config.routes && routesOutputPath) {
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) {
168
194
  const routesJSON = convertRoutesToRoutesJSONSpec(config.routes);
169
195
  writeFileSync(routesOutputPath, JSON.stringify(routesJSON, null, 2));
170
196
  }
@@ -8,4 +8,5 @@ export const SECONDS_TO_WAIT_FOR_PROXY = 5;
8
8
  export const isInPagesCI = !!process.env.CF_PAGES;
9
9
  /** The max number of rules in _routes.json */
10
10
  export const MAX_FUNCTIONS_ROUTES_RULES = 100;
11
+ export const MAX_FUNCTIONS_ROUTES_RULE_LENGTH = 100;
11
12
  export const ROUTES_SPEC_VERSION = 1;