wrangler 2.1.15 → 2.2.1

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 (77) hide show
  1. package/miniflare-dist/index.mjs +3 -1
  2. package/package.json +2 -1
  3. package/src/__tests__/access.test.ts +25 -0
  4. package/src/__tests__/api-dev.test.ts +1 -1
  5. package/src/__tests__/api-devregistry.test.js +2 -2
  6. package/src/__tests__/configuration.test.ts +119 -2
  7. package/src/__tests__/d1.test.ts +2 -0
  8. package/src/__tests__/deployments.test.ts +22 -22
  9. package/src/__tests__/dev.test.tsx +167 -15
  10. package/src/__tests__/helpers/msw/handlers/access.ts +13 -0
  11. package/src/__tests__/helpers/msw/handlers/deployments.ts +22 -43
  12. package/src/__tests__/helpers/msw/handlers/zones.ts +22 -0
  13. package/src/__tests__/helpers/msw/index.ts +4 -0
  14. package/src/__tests__/index.test.ts +42 -33
  15. package/src/__tests__/init.test.ts +88 -4
  16. package/src/__tests__/jest.setup.ts +11 -0
  17. package/src/__tests__/kv.test.ts +400 -400
  18. package/src/__tests__/pages.test.ts +206 -40
  19. package/src/__tests__/publish.test.ts +1161 -647
  20. package/src/__tests__/pubsub.test.ts +3 -0
  21. package/src/__tests__/queues.test.ts +371 -0
  22. package/src/__tests__/r2.test.ts +57 -52
  23. package/src/__tests__/worker-namespace.test.ts +15 -10
  24. package/src/bundle-reporter.tsx +41 -2
  25. package/src/bundle.ts +105 -46
  26. package/src/cli.ts +0 -1
  27. package/src/config/environment.ts +50 -0
  28. package/src/config/index.ts +41 -0
  29. package/src/config/validation.ts +173 -0
  30. package/src/create-worker-preview.ts +10 -3
  31. package/src/create-worker-upload-form.ts +12 -0
  32. package/src/d1/backups.tsx +11 -5
  33. package/src/d1/execute.tsx +52 -47
  34. package/src/d1/index.ts +2 -1
  35. package/src/delete.ts +7 -10
  36. package/src/deployments.ts +73 -0
  37. package/src/deprecated/index.ts +9 -24
  38. package/src/dev/dev-vars.ts +11 -8
  39. package/src/dev/dev.tsx +12 -0
  40. package/src/dev/local.tsx +26 -0
  41. package/src/dev/remote.tsx +2 -0
  42. package/src/dev/start-server.ts +7 -0
  43. package/src/dev/use-esbuild.ts +12 -5
  44. package/src/dev.tsx +12 -9
  45. package/src/dispatch-namespace.ts +4 -3
  46. package/src/index.tsx +61 -45
  47. package/src/init.ts +4 -4
  48. package/src/inspect.ts +21 -1
  49. package/src/kv/index.ts +5 -54
  50. package/src/logger.ts +12 -0
  51. package/src/pages/build.tsx +33 -1
  52. package/src/pages/dev.tsx +22 -7
  53. package/src/pages/functions/buildPlugin.ts +83 -87
  54. package/src/pages/functions/buildWorker.ts +119 -110
  55. package/src/pages/publish.tsx +16 -6
  56. package/src/pages/upload.tsx +19 -2
  57. package/src/pages/utils.ts +2 -2
  58. package/src/proxy.ts +38 -6
  59. package/src/publish/index.ts +11 -8
  60. package/src/publish/publish.ts +152 -30
  61. package/src/pubsub/pubsub-commands.tsx +3 -2
  62. package/src/queues/cli/commands/consumer/add.ts +71 -0
  63. package/src/queues/cli/commands/consumer/index.ts +22 -0
  64. package/src/queues/cli/commands/consumer/remove.ts +38 -0
  65. package/src/queues/cli/commands/create.ts +25 -0
  66. package/src/queues/cli/commands/delete.ts +26 -0
  67. package/src/queues/cli/commands/index.ts +33 -0
  68. package/src/queues/cli/commands/list.ts +25 -0
  69. package/src/queues/client.ts +135 -0
  70. package/src/secret/index.ts +14 -39
  71. package/src/tail/index.ts +5 -8
  72. package/src/user/access.ts +69 -0
  73. package/src/worker.ts +7 -0
  74. package/src/yargs-types.ts +15 -2
  75. package/src/zones.ts +31 -5
  76. package/wrangler-dist/cli.d.ts +42 -0
  77. package/wrangler-dist/cli.js +4346 -3651
package/src/pages/dev.tsx CHANGED
@@ -256,6 +256,8 @@ export const Handler = async ({
256
256
  await esbuild.build({
257
257
  entryPoints: [scriptPath],
258
258
  write: false,
259
+ // we need it to be bundled so that any imports that are used are affected by the blocker plugin
260
+ bundle: true,
259
261
  plugins: [blockWorkerJsImports],
260
262
  });
261
263
  } catch {}
@@ -270,7 +272,7 @@ export const Handler = async ({
270
272
  });
271
273
  } else if (usingFunctions) {
272
274
  // Try to use Functions
273
- const outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.js`);
275
+ const outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.mjs`);
274
276
  scriptPath = outfile;
275
277
 
276
278
  if (nodeCompat) {
@@ -290,6 +292,8 @@ export const Handler = async ({
290
292
  onEnd,
291
293
  buildOutputDirectory: directory,
292
294
  nodeCompat,
295
+ local: true,
296
+ d1Databases: d1s.map((binding) => binding.toString()),
293
297
  });
294
298
  await metrics.sendMetricsEvent("build pages functions");
295
299
 
@@ -307,6 +311,8 @@ export const Handler = async ({
307
311
  onEnd,
308
312
  buildOutputDirectory: directory,
309
313
  nodeCompat,
314
+ local: true,
315
+ d1Databases: d1s.map((binding) => binding.toString()),
310
316
  });
311
317
  await metrics.sendMetricsEvent("build pages functions");
312
318
  } catch (e) {
@@ -477,8 +483,8 @@ export const Handler = async ({
477
483
  .map((binding) => binding.toString().split("="))
478
484
  .map(([key, ...values]) => [key, values.join("=")])
479
485
  ),
480
- kv: kvs.map((val) => ({
481
- binding: val.toString(),
486
+ kv: kvs.map((binding) => ({
487
+ binding: binding.toString(),
482
488
  id: "",
483
489
  })),
484
490
  durableObjects: durableObjects
@@ -520,7 +526,7 @@ export const Handler = async ({
520
526
  persist,
521
527
  persistTo,
522
528
  showInteractiveDevSession: undefined,
523
- inspect: true,
529
+ inspect: undefined,
524
530
  logPrefix: "pages",
525
531
  logLevel: logLevel ?? "warn",
526
532
  },
@@ -680,14 +686,23 @@ async function spawnProxyProcess({
680
686
  return port;
681
687
  }
682
688
 
689
+ // TODO: Kill this once we have https://github.com/cloudflare/wrangler2/issues/2153
683
690
  const blockWorkerJsImports: esbuild.Plugin = {
684
691
  name: "block-worker-js-imports",
685
- setup(build: esbuild.PluginBuild) {
686
- build.onResolve({ filter: /.*/g }, (_args) => {
692
+ setup(build) {
693
+ build.onResolve({ filter: /.*/g }, (args) => {
694
+ // If it's the entrypoint, let it be as is
695
+ if (args.kind === "entry-point") {
696
+ return {
697
+ path: args.path,
698
+ };
699
+ }
700
+ // Otherwise, block any imports that the file is requesting
687
701
  logger.error(
688
702
  `_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.`
689
703
  );
690
- return null;
704
+ // Miniflare will error with this briefly down the line -- there's no point in continuing.
705
+ process.exit(1);
691
706
  });
692
707
  },
693
708
  };
@@ -1,19 +1,11 @@
1
1
  import { access, lstat } from "node:fs/promises";
2
2
  import { dirname, relative, resolve } from "node:path";
3
- import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
4
- import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
5
- import { build } from "esbuild";
3
+ import { bundleWorker } from "../../bundle";
6
4
  import { getBasePath } from "../../paths";
5
+ import { D1_BETA_PREFIX } from "../../worker";
6
+ import type { Options as WorkerOptions } from "./buildWorker";
7
7
 
8
- type Options = {
9
- routesModule: string;
10
- outfile: string;
11
- minify?: boolean;
12
- sourcemap?: boolean;
13
- watch?: boolean;
14
- nodeCompat?: boolean;
15
- onEnd?: () => void;
16
- };
8
+ type Options = Omit<WorkerOptions, "fallbackService" | "buildOutputDirectory">;
17
9
 
18
10
  export function buildPlugin({
19
11
  routesModule,
@@ -21,90 +13,94 @@ export function buildPlugin({
21
13
  minify = false,
22
14
  sourcemap = false,
23
15
  watch = false,
24
- nodeCompat,
25
16
  onEnd = () => {},
17
+ nodeCompat,
18
+ functionsDirectory,
19
+ local,
20
+ betaD1Shims,
26
21
  }: Options) {
27
- return build({
28
- entryPoints: [resolve(getBasePath(), "templates/pages-template-plugin.ts")],
29
- inject: [routesModule],
30
- bundle: true,
31
- format: "esm",
32
- target: "esnext",
33
- loader: {
34
- ".html": "text",
35
- ".txt": "text",
22
+ return bundleWorker(
23
+ {
24
+ file: resolve(getBasePath(), "templates/pages-template-plugin.ts"),
25
+ directory: functionsDirectory,
26
+ format: "modules",
36
27
  },
37
- outfile,
38
- minify,
39
- sourcemap,
40
- watch,
41
- allowOverwrite: true,
42
- define: { ...(nodeCompat ? { global: "globalThis" } : {}) },
43
- plugins: [
44
- {
45
- name: "wrangler notifier and monitor",
46
- setup(pluginBuild) {
47
- pluginBuild.onEnd((result) => {
48
- if (result.errors.length > 0) {
49
- console.error(
50
- `${result.errors.length} error(s) and ${result.warnings.length} warning(s) when compiling Worker.`
51
- );
52
- } else if (result.warnings.length > 0) {
53
- console.warn(
54
- `${result.warnings.length} warning(s) when compiling Worker.`
55
- );
56
- onEnd();
57
- } else {
58
- console.log("Compiled Worker successfully.");
59
- onEnd();
60
- }
61
- });
28
+ resolve(outfile),
29
+ {
30
+ inject: [routesModule],
31
+ minify,
32
+ sourcemap,
33
+ watch,
34
+ nodeCompat,
35
+ define: {},
36
+ betaD1Shims: (betaD1Shims || []).map(
37
+ (binding) => `${D1_BETA_PREFIX}${binding}`
38
+ ),
39
+ plugins: [
40
+ {
41
+ name: "wrangler notifier and monitor",
42
+ setup(pluginBuild) {
43
+ pluginBuild.onEnd((result) => {
44
+ if (result.errors.length > 0) {
45
+ console.error(
46
+ `${result.errors.length} error(s) and ${result.warnings.length} warning(s) when compiling Worker.`
47
+ );
48
+ } else if (result.warnings.length > 0) {
49
+ console.warn(
50
+ `${result.warnings.length} warning(s) when compiling Worker.`
51
+ );
52
+ onEnd();
53
+ } else {
54
+ console.log("Compiled Worker successfully.");
55
+ onEnd();
56
+ }
57
+ });
58
+ },
62
59
  },
63
- },
64
- {
65
- name: "Assets",
66
- setup(pluginBuild) {
67
- if (pluginBuild.initialOptions.outfile) {
68
- const outdir = dirname(pluginBuild.initialOptions.outfile);
60
+ {
61
+ name: "Assets",
62
+ setup(pluginBuild) {
63
+ if (pluginBuild.initialOptions.outfile) {
64
+ const outdir = dirname(pluginBuild.initialOptions.outfile);
69
65
 
70
- pluginBuild.onResolve({ filter: /^assets:/ }, async (args) => {
71
- const directory = resolve(
72
- args.resolveDir,
73
- args.path.slice("assets:".length)
74
- );
66
+ pluginBuild.onResolve({ filter: /^assets:/ }, async (args) => {
67
+ const directory = resolve(
68
+ args.resolveDir,
69
+ args.path.slice("assets:".length)
70
+ );
75
71
 
76
- const exists = await access(directory)
77
- .then(() => true)
78
- .catch(() => false);
72
+ const exists = await access(directory)
73
+ .then(() => true)
74
+ .catch(() => false);
79
75
 
80
- const isDirectory =
81
- exists && (await lstat(directory)).isDirectory();
76
+ const isDirectory =
77
+ exists && (await lstat(directory)).isDirectory();
82
78
 
83
- if (!isDirectory) {
84
- return {
85
- errors: [
86
- {
87
- text: `'${directory}' does not exist or is not a directory.`,
88
- },
89
- ],
90
- };
91
- }
79
+ if (!isDirectory) {
80
+ return {
81
+ errors: [
82
+ {
83
+ text: `'${directory}' does not exist or is not a directory.`,
84
+ },
85
+ ],
86
+ };
87
+ }
92
88
 
93
- const path = `assets:./${relative(outdir, directory)}`;
89
+ const path = `assets:./${relative(outdir, directory)}`;
94
90
 
95
- return { path, external: true, namespace: "assets" };
96
- });
97
- }
91
+ return { path, external: true, namespace: "assets" };
92
+ });
93
+ }
94
+ },
98
95
  },
99
- },
100
- ...(nodeCompat
101
- ? [
102
- NodeGlobalsPolyfills({
103
- buffer: true,
104
- }),
105
- NodeModulesPolyfills(),
106
- ]
107
- : []),
108
- ],
109
- });
96
+ ],
97
+ isOutfile: true,
98
+ serveAssetsFromWorker: false,
99
+ disableModuleCollection: true,
100
+ rules: [],
101
+ checkFetch: local,
102
+ targetConsumer: local ? "dev" : "publish",
103
+ local,
104
+ }
105
+ );
110
106
  }
@@ -1,12 +1,11 @@
1
1
  import { access, cp, lstat, rm } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
- import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
4
- import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
5
- import { build } from "esbuild";
6
3
  import { nanoid } from "nanoid";
4
+ import { bundleWorker } from "../../bundle";
7
5
  import { getBasePath } from "../../paths";
6
+ import { D1_BETA_PREFIX } from "../../worker";
8
7
 
9
- type Options = {
8
+ export type Options = {
10
9
  routesModule: string;
11
10
  outfile: string;
12
11
  minify?: boolean;
@@ -16,6 +15,9 @@ type Options = {
16
15
  onEnd?: () => void;
17
16
  buildOutputDirectory?: string;
18
17
  nodeCompat?: boolean;
18
+ functionsDirectory: string;
19
+ local: boolean;
20
+ betaD1Shims?: string[];
19
21
  };
20
22
 
21
23
  export function buildWorker({
@@ -28,129 +30,136 @@ export function buildWorker({
28
30
  onEnd = () => {},
29
31
  buildOutputDirectory,
30
32
  nodeCompat,
33
+ functionsDirectory,
34
+ local,
35
+ betaD1Shims,
31
36
  }: Options) {
32
- return build({
33
- entryPoints: [resolve(getBasePath(), "templates/pages-template-worker.ts")],
34
- inject: [routesModule],
35
- bundle: true,
36
- format: "esm",
37
- target: "esnext",
38
- loader: {
39
- ".html": "text",
40
- ".txt": "text",
37
+ return bundleWorker(
38
+ {
39
+ file: resolve(getBasePath(), "templates/pages-template-worker.ts"),
40
+ directory: functionsDirectory,
41
+ format: "modules",
41
42
  },
42
- outfile,
43
- minify,
44
- sourcemap,
45
- watch,
46
- allowOverwrite: true,
47
- define: {
48
- __FALLBACK_SERVICE__: JSON.stringify(fallbackService),
49
- ...(nodeCompat ? { global: "globalThis" } : {}),
50
- },
51
- plugins: [
52
- {
53
- name: "wrangler notifier and monitor",
54
- setup(pluginBuild) {
55
- pluginBuild.onEnd((result) => {
56
- if (result.errors.length > 0) {
57
- console.error(
58
- `${result.errors.length} error(s) and ${result.warnings.length} warning(s) when compiling Worker.`
59
- );
60
- } else if (result.warnings.length > 0) {
61
- console.warn(
62
- `${result.warnings.length} warning(s) when compiling Worker.`
63
- );
64
- onEnd();
65
- } else {
66
- console.log("Compiled Worker successfully.");
67
- onEnd();
68
- }
69
- });
70
- },
43
+ resolve(outfile),
44
+ {
45
+ inject: [routesModule],
46
+ minify,
47
+ sourcemap,
48
+ watch,
49
+ nodeCompat,
50
+ loader: {
51
+ ".txt": "text",
52
+ ".html": "text",
53
+ },
54
+ define: {
55
+ __FALLBACK_SERVICE__: JSON.stringify(fallbackService),
71
56
  },
72
- {
73
- name: "Assets",
74
- setup(pluginBuild) {
75
- const identifiers = new Map<string, string>();
57
+ betaD1Shims: (betaD1Shims || []).map(
58
+ (binding) => `${D1_BETA_PREFIX}${binding}`
59
+ ),
60
+ plugins: [
61
+ {
62
+ name: "wrangler notifier and monitor",
63
+ setup(pluginBuild) {
64
+ pluginBuild.onEnd((result) => {
65
+ if (result.errors.length > 0) {
66
+ console.error(
67
+ `${result.errors.length} error(s) and ${result.warnings.length} warning(s) when compiling Worker.`
68
+ );
69
+ } else if (result.warnings.length > 0) {
70
+ console.warn(
71
+ `${result.warnings.length} warning(s) when compiling Worker.`
72
+ );
73
+ onEnd();
74
+ } else {
75
+ console.log("Compiled Worker successfully.");
76
+ onEnd();
77
+ }
78
+ });
79
+ },
80
+ },
81
+ {
82
+ name: "Assets",
83
+ setup(pluginBuild) {
84
+ const identifiers = new Map<string, string>();
76
85
 
77
- pluginBuild.onResolve({ filter: /^assets:/ }, async (args) => {
78
- const directory = resolve(
79
- args.resolveDir,
80
- args.path.slice("assets:".length)
81
- );
86
+ pluginBuild.onResolve({ filter: /^assets:/ }, async (args) => {
87
+ const directory = resolve(
88
+ args.resolveDir,
89
+ args.path.slice("assets:".length)
90
+ );
82
91
 
83
- const exists = await access(directory)
84
- .then(() => true)
85
- .catch(() => false);
92
+ const exists = await access(directory)
93
+ .then(() => true)
94
+ .catch(() => false);
86
95
 
87
- const isDirectory =
88
- exists && (await lstat(directory)).isDirectory();
96
+ const isDirectory =
97
+ exists && (await lstat(directory)).isDirectory();
89
98
 
90
- if (!isDirectory) {
91
- return {
92
- errors: [
93
- {
94
- text: `'${directory}' does not exist or is not a directory.`,
95
- },
96
- ],
97
- };
98
- }
99
+ if (!isDirectory) {
100
+ return {
101
+ errors: [
102
+ {
103
+ text: `'${directory}' does not exist or is not a directory.`,
104
+ },
105
+ ],
106
+ };
107
+ }
99
108
 
100
- // TODO: Consider hashing the contents rather than using a unique identifier every time?
101
- identifiers.set(directory, nanoid());
102
- if (!buildOutputDirectory) {
103
- console.warn(
104
- "You're attempting to import static assets as part of your Pages Functions, but have not specified a directory in which to put them. You must use 'wrangler pages dev <directory>' rather than 'wrangler pages dev -- <command>' to import static assets in Functions."
105
- );
106
- }
107
- return { path: directory, namespace: "assets" };
108
- });
109
+ // TODO: Consider hashing the contents rather than using a unique identifier every time?
110
+ identifiers.set(directory, nanoid());
111
+ if (!buildOutputDirectory) {
112
+ console.warn(
113
+ "You're attempting to import static assets as part of your Pages Functions, but have not specified a directory in which to put them. You must use 'wrangler pages dev <directory>' rather than 'wrangler pages dev -- <command>' to import static assets in Functions."
114
+ );
115
+ }
116
+ return { path: directory, namespace: "assets" };
117
+ });
109
118
 
110
- pluginBuild.onLoad(
111
- { filter: /.*/, namespace: "assets" },
112
- async (args) => {
113
- const identifier = identifiers.get(args.path);
119
+ pluginBuild.onLoad(
120
+ { filter: /.*/, namespace: "assets" },
121
+ async (args) => {
122
+ const identifier = identifiers.get(args.path);
114
123
 
115
- if (buildOutputDirectory) {
116
- const staticAssetsOutputDirectory = join(
117
- buildOutputDirectory,
118
- "cdn-cgi",
119
- "pages-plugins",
120
- identifier as string
121
- );
122
- await rm(staticAssetsOutputDirectory, {
123
- force: true,
124
- recursive: true,
125
- });
126
- await cp(args.path, staticAssetsOutputDirectory, {
127
- force: true,
128
- recursive: true,
129
- });
124
+ if (buildOutputDirectory) {
125
+ const staticAssetsOutputDirectory = join(
126
+ buildOutputDirectory,
127
+ "cdn-cgi",
128
+ "pages-plugins",
129
+ identifier as string
130
+ );
131
+ await rm(staticAssetsOutputDirectory, {
132
+ force: true,
133
+ recursive: true,
134
+ });
135
+ await cp(args.path, staticAssetsOutputDirectory, {
136
+ force: true,
137
+ recursive: true,
138
+ });
130
139
 
131
- return {
132
- // TODO: Watch args.path for changes and re-copy when updated
133
- contents: `export const onRequest = ({ request, env, functionPath }) => {
140
+ return {
141
+ // TODO: Watch args.path for changes and re-copy when updated
142
+ contents: `export const onRequest = ({ request, env, functionPath }) => {
134
143
  const url = new URL(request.url)
135
144
  const relativePathname = \`/\${url.pathname.split(functionPath)[1] || ''}\`.replace(/^\\/\\//, '/');
136
145
  url.pathname = '/cdn-cgi/pages-plugins/${identifier}' + relativePathname
137
146
  request = new Request(url.toString(), request)
138
147
  return env.ASSETS.fetch(request)
139
148
  }`,
140
- };
149
+ };
150
+ }
141
151
  }
142
- }
143
- );
152
+ );
153
+ },
144
154
  },
145
- },
146
- ...(nodeCompat
147
- ? [
148
- NodeGlobalsPolyfills({
149
- buffer: true,
150
- }),
151
- NodeModulesPolyfills(),
152
- ]
153
- : []),
154
- ],
155
- });
155
+ ],
156
+ isOutfile: true,
157
+ serveAssetsFromWorker: false,
158
+ disableModuleCollection: true,
159
+ rules: [],
160
+ checkFetch: local,
161
+ targetConsumer: local ? "dev" : "publish",
162
+ local,
163
+ }
164
+ );
156
165
  }
@@ -21,12 +21,8 @@ import { validateRoutes } from "./functions/routes-validation";
21
21
  import { listProjects } from "./projects";
22
22
  import { upload } from "./upload";
23
23
  import { pagesBetaWarning } from "./utils";
24
- import type {
25
- Deployment,
26
- PagesConfigCache,
27
- Project,
28
- YargsOptionsToInterface,
29
- } from "./types";
24
+ import type { PagesConfigCache, YargsOptionsToInterface } from "./types";
25
+ import type { Project, Deployment } from "@cloudflare/types";
30
26
  import type { Argv } from "yargs";
31
27
 
32
28
  type PublishArgs = YargsOptionsToInterface<typeof Options>;
@@ -274,6 +270,15 @@ export const Handler = async ({
274
270
  _workerJS = readFileSync(join(directory, "_worker.js"), "utf-8");
275
271
  } catch {}
276
272
 
273
+ // Grab the bindings from the API, we need these for shims and other such hacky inserts
274
+ const project = await fetchResult<Project>(
275
+ `/accounts/${accountId}/pages/projects/${projectName}`
276
+ );
277
+ let isProduction = true;
278
+ if (branch) {
279
+ isProduction = project.production_branch === branch;
280
+ }
281
+
277
282
  /**
278
283
  * Evaluate if this is an Advanced Mode or Pages Functions project. If Advanced Mode, we'll
279
284
  * go ahead and upload `_worker.js` as is, but if Pages Functions, we need to attempt to build
@@ -294,6 +299,11 @@ export const Handler = async ({
294
299
  onEnd: () => {},
295
300
  buildOutputDirectory: dirname(outfile),
296
301
  routesOutputPath,
302
+ local: false,
303
+ d1Databases: Object.keys(
304
+ project.deployment_configs[isProduction ? "production" : "preview"]
305
+ .d1_databases ?? {}
306
+ ),
297
307
  });
298
308
 
299
309
  builtFunctions = readFileSync(outfile, "utf-8");
@@ -297,7 +297,7 @@ export const upload = async (
297
297
  setTimeout(resolvePromise, Math.pow(2, attempts++) * 1000)
298
298
  );
299
299
 
300
- if ((e as { code: number }).code === 8000013) {
300
+ if ((e as { code: number }).code === 8000013 || isJwtExpired(jwt)) {
301
301
  // Looks like the JWT expired, fetch another one
302
302
  jwt = await fetchJwt();
303
303
  }
@@ -358,7 +358,7 @@ export const upload = async (
358
358
  } catch (e) {
359
359
  await new Promise((resolvePromise) => setTimeout(resolvePromise, 1000));
360
360
 
361
- if ((e as { code: number }).code === 8000013) {
361
+ if ((e as { code: number }).code === 8000013 || isJwtExpired(jwt)) {
362
362
  // Looks like the JWT expired, fetch another one
363
363
  jwt = await fetchJwt();
364
364
  }
@@ -392,6 +392,23 @@ export const upload = async (
392
392
  );
393
393
  };
394
394
 
395
+ // Decode and check that the current JWT has not expired
396
+ function isJwtExpired(token: string): boolean | undefined {
397
+ try {
398
+ const decodedJwt = JSON.parse(
399
+ Buffer.from(token.split(".")[1], "base64").toString()
400
+ );
401
+
402
+ const dateNow = new Date().getTime() / 1000;
403
+
404
+ return decodedJwt.exp <= dateNow;
405
+ } catch (e) {
406
+ if (e instanceof Error) {
407
+ throw new Error(`Invalid token: ${e.message}`);
408
+ }
409
+ }
410
+ }
411
+
395
412
  function formatTime(duration: number) {
396
413
  return `(${(duration / 1000).toFixed(2)} sec)`;
397
414
  }
@@ -1,6 +1,6 @@
1
- import type { BuildResult } from "esbuild";
1
+ import type { BundleResult } from "../bundle";
2
2
 
3
- export const RUNNING_BUILDERS: BuildResult[] = [];
3
+ export const RUNNING_BUILDERS: BundleResult[] = [];
4
4
 
5
5
  export const CLEANUP_CALLBACKS: (() => void)[] = [];
6
6
  export const CLEANUP = () => {