wrangler 0.0.0-e7a0cd5b → 0.0.0-e87ad068

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 (255) hide show
  1. package/README.md +3 -3
  2. package/bin/wrangler.js +30 -10
  3. package/miniflare-dist/index.mjs +254 -128
  4. package/package.json +27 -19
  5. package/src/__tests__/api-dev.test.ts +65 -36
  6. package/src/__tests__/api-devregistry.test.ts +121 -0
  7. package/src/__tests__/api.test.ts +27 -5
  8. package/src/__tests__/configuration.test.ts +797 -98
  9. package/src/__tests__/constellation.test.ts +371 -0
  10. package/src/__tests__/d1/d1.test.ts +82 -0
  11. package/src/__tests__/d1/execute.test.ts +66 -0
  12. package/src/__tests__/d1/migrate.test.ts +257 -0
  13. package/src/__tests__/d1/splitter.test.ts +255 -0
  14. package/src/__tests__/delete.test.ts +91 -49
  15. package/src/__tests__/deployments.test.ts +330 -56
  16. package/src/__tests__/dev.test.tsx +198 -90
  17. package/src/__tests__/generate.test.ts +12 -10
  18. package/src/__tests__/guess-worker-format.test.ts +35 -0
  19. package/src/__tests__/helpers/end-event-loop.ts +6 -0
  20. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  21. package/src/__tests__/helpers/mock-console.ts +6 -0
  22. package/src/__tests__/helpers/mock-dialogs.ts +71 -85
  23. package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
  24. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -5
  25. package/src/__tests__/helpers/mock-known-routes.ts +7 -2
  26. package/src/__tests__/helpers/mock-kv.ts +29 -16
  27. package/src/__tests__/helpers/mock-oauth-flow.ts +103 -92
  28. package/src/__tests__/helpers/mock-process.ts +8 -13
  29. package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
  30. package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
  31. package/src/__tests__/helpers/msw/handlers/deployments.ts +128 -27
  32. package/src/__tests__/helpers/msw/handlers/namespaces.ts +18 -41
  33. package/src/__tests__/helpers/msw/handlers/oauth.ts +13 -18
  34. package/src/__tests__/helpers/msw/handlers/r2.ts +14 -34
  35. package/src/__tests__/helpers/msw/handlers/script.ts +9 -28
  36. package/src/__tests__/helpers/msw/handlers/user.ts +13 -24
  37. package/src/__tests__/helpers/msw/handlers/zones.ts +6 -8
  38. package/src/__tests__/helpers/msw/index.ts +32 -1
  39. package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
  40. package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
  41. package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
  42. package/src/__tests__/index.test.ts +92 -72
  43. package/src/__tests__/init.test.ts +1033 -631
  44. package/src/__tests__/jest.setup.ts +19 -42
  45. package/src/__tests__/kv.test.ts +355 -231
  46. package/src/__tests__/logger.test.ts +68 -2
  47. package/src/__tests__/logout.test.ts +47 -0
  48. package/src/__tests__/metrics.test.ts +94 -51
  49. package/src/__tests__/middleware.scheduled.test.ts +42 -32
  50. package/src/__tests__/middleware.test.ts +212 -122
  51. package/src/__tests__/mtls-certificates.test.ts +589 -0
  52. package/src/__tests__/pages/deployment-list.test.ts +80 -0
  53. package/src/__tests__/pages/functions-build.test.ts +529 -0
  54. package/src/__tests__/pages/pages.test.ts +81 -0
  55. package/src/__tests__/pages/project-create.test.ts +63 -0
  56. package/src/__tests__/pages/project-list.test.ts +110 -0
  57. package/src/__tests__/pages/project-upload.test.ts +500 -0
  58. package/src/__tests__/pages/publish.test.ts +2864 -0
  59. package/src/__tests__/pages-deployment-tail.test.ts +957 -0
  60. package/src/__tests__/parse.test.ts +106 -0
  61. package/src/__tests__/publish.test.ts +2227 -1005
  62. package/src/__tests__/pubsub.test.ts +226 -100
  63. package/src/__tests__/queues.test.ts +238 -77
  64. package/src/__tests__/r2.test.ts +55 -57
  65. package/src/__tests__/secret.test.ts +179 -130
  66. package/src/__tests__/tail.test.ts +313 -113
  67. package/src/__tests__/test-old-node-version.js +3 -3
  68. package/src/__tests__/traverse-module-graph.test.ts +220 -0
  69. package/src/__tests__/tsconfig-sanity.ts +12 -0
  70. package/src/__tests__/tsconfig.json +8 -0
  71. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  72. package/src/__tests__/type-generation.test.ts +43 -26
  73. package/src/__tests__/unstableDev.test.ts +61 -0
  74. package/src/__tests__/user.test.ts +35 -72
  75. package/src/__tests__/whoami.test.tsx +8 -114
  76. package/src/__tests__/worker-namespace.test.ts +83 -69
  77. package/src/api/dev.ts +180 -60
  78. package/src/api/index.ts +10 -1
  79. package/src/api/mtls-certificate.ts +148 -0
  80. package/src/api/pages/create-worker-bundle-contents.ts +80 -0
  81. package/src/api/pages/index.ts +5 -0
  82. package/src/api/pages/publish.tsx +371 -0
  83. package/src/bundle.ts +315 -148
  84. package/src/cfetch/index.ts +0 -2
  85. package/src/cfetch/internal.ts +33 -33
  86. package/src/cli.ts +4 -4
  87. package/src/config/config.ts +14 -7
  88. package/src/config/environment.ts +120 -24
  89. package/src/config/index.ts +117 -35
  90. package/src/config/validation-helpers.ts +1 -1
  91. package/src/config/validation.ts +430 -19
  92. package/src/constellation/createProject.tsx +51 -0
  93. package/src/constellation/deleteProject.ts +51 -0
  94. package/src/constellation/deleteProjectModel.ts +76 -0
  95. package/src/constellation/index.ts +75 -0
  96. package/src/constellation/listCatalog.tsx +35 -0
  97. package/src/constellation/listModel.tsx +49 -0
  98. package/src/constellation/listProject.tsx +28 -0
  99. package/src/constellation/listRuntime.tsx +28 -0
  100. package/src/constellation/options.ts +17 -0
  101. package/src/constellation/types.ts +17 -0
  102. package/src/constellation/uploadModel.tsx +84 -0
  103. package/src/constellation/utils.ts +90 -0
  104. package/src/create-worker-preview.ts +19 -8
  105. package/src/create-worker-upload-form.ts +81 -18
  106. package/src/d1/backups.tsx +47 -46
  107. package/src/d1/constants.ts +5 -0
  108. package/src/d1/create.tsx +85 -37
  109. package/src/d1/{delete.tsx → delete.ts} +12 -15
  110. package/src/d1/execute.tsx +228 -156
  111. package/src/d1/index.ts +31 -7
  112. package/src/d1/list.tsx +27 -13
  113. package/src/d1/migrations/apply.tsx +235 -0
  114. package/src/d1/migrations/create.tsx +79 -0
  115. package/src/d1/migrations/helpers.ts +171 -0
  116. package/src/d1/migrations/index.ts +3 -0
  117. package/src/d1/migrations/list.tsx +95 -0
  118. package/src/d1/migrations/options.ts +23 -0
  119. package/src/d1/options.ts +12 -2
  120. package/src/d1/splitter.ts +161 -0
  121. package/src/d1/types.ts +32 -0
  122. package/src/d1/utils.ts +12 -2
  123. package/src/delete.ts +8 -16
  124. package/src/deployments.ts +340 -46
  125. package/src/deprecated/index.ts +8 -302
  126. package/src/dev/dev.tsx +66 -46
  127. package/src/dev/local.tsx +339 -104
  128. package/src/dev/remote.tsx +36 -3
  129. package/src/dev/start-server.ts +146 -101
  130. package/src/dev/use-esbuild.ts +82 -56
  131. package/src/dev/validate-dev-props.ts +9 -0
  132. package/src/{dev-registry.tsx → dev-registry.ts} +13 -1
  133. package/src/dev.tsx +202 -125
  134. package/src/dialogs.ts +136 -0
  135. package/src/dispatch-namespace.ts +21 -17
  136. package/src/docs/helpers.ts +50 -0
  137. package/src/docs/index.ts +54 -0
  138. package/src/entry.ts +26 -11
  139. package/src/environment-variables/factory.ts +89 -0
  140. package/src/environment-variables/misc-variables.ts +30 -0
  141. package/src/generate/index.ts +303 -0
  142. package/src/git-client.ts +15 -4
  143. package/src/{index.tsx → index.ts} +148 -63
  144. package/src/init.ts +301 -197
  145. package/src/inspect.ts +122 -6
  146. package/src/jest.d.ts +4 -0
  147. package/src/kv/helpers.ts +7 -4
  148. package/src/kv/index.ts +15 -17
  149. package/src/logger.ts +36 -5
  150. package/src/metrics/metrics-config.ts +3 -3
  151. package/src/metrics/send-event.ts +6 -1
  152. package/src/miniflare-cli/assets.ts +64 -28
  153. package/src/miniflare-cli/index.ts +6 -9
  154. package/src/miniflare-cli/tsconfig.json +9 -0
  155. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  156. package/src/miniflare-cli/types.ts +11 -0
  157. package/src/module-collection.ts +92 -26
  158. package/src/mtls-certificate/cli.ts +155 -0
  159. package/src/pages/build.ts +423 -0
  160. package/src/pages/buildFunctions.ts +140 -0
  161. package/src/pages/deployment-tails.ts +281 -0
  162. package/src/pages/deployments.tsx +11 -33
  163. package/src/pages/{dev.tsx → dev.ts} +192 -126
  164. package/src/pages/errors.ts +1 -0
  165. package/src/pages/functions/buildPlugin.ts +73 -69
  166. package/src/pages/functions/buildWorker.ts +342 -117
  167. package/src/pages/functions/tsconfig.json +8 -0
  168. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  169. package/src/pages/{functions.tsx → functions.ts} +8 -4
  170. package/src/pages/{index.tsx → index.ts} +11 -3
  171. package/src/pages/projects.tsx +12 -22
  172. package/src/pages/prompt-select-project.tsx +31 -0
  173. package/src/pages/publish.tsx +45 -214
  174. package/src/pages/types.ts +6 -9
  175. package/src/pages/upload.tsx +58 -14
  176. package/src/pages/utils.ts +14 -3
  177. package/src/parse.ts +23 -1
  178. package/src/paths.ts +1 -1
  179. package/src/proxy.ts +5 -0
  180. package/src/publish/index.ts +20 -16
  181. package/src/publish/publish.ts +81 -48
  182. package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +19 -20
  183. package/src/queues/cli/commands/consumer/add.ts +24 -24
  184. package/src/queues/cli/commands/consumer/index.ts +3 -6
  185. package/src/queues/cli/commands/consumer/remove.ts +11 -18
  186. package/src/queues/cli/commands/create.ts +8 -8
  187. package/src/queues/cli/commands/delete.ts +8 -8
  188. package/src/queues/cli/commands/index.ts +6 -4
  189. package/src/queues/cli/commands/list.ts +8 -8
  190. package/src/queues/client.ts +1 -0
  191. package/src/queues/utils.ts +18 -0
  192. package/src/r2/constants.ts +4 -0
  193. package/src/r2/helpers.ts +1 -0
  194. package/src/r2/index.ts +40 -28
  195. package/src/secret/index.ts +18 -17
  196. package/src/{sites.tsx → sites.ts} +165 -53
  197. package/src/tail/createTail.ts +103 -3
  198. package/src/tail/filters.ts +1 -1
  199. package/src/tail/index.ts +8 -11
  200. package/src/tail/printing.ts +27 -0
  201. package/src/traverse-module-graph.ts +54 -0
  202. package/src/tsconfig-sanity.ts +16 -0
  203. package/src/type-generation.ts +85 -57
  204. package/src/user/access.ts +0 -1
  205. package/src/user/auth-variables.ts +113 -0
  206. package/src/user/choose-account.tsx +1 -31
  207. package/src/user/index.ts +0 -1
  208. package/src/user/{user.tsx → user.ts} +124 -82
  209. package/src/utils/render.ts +93 -0
  210. package/src/{whoami.tsx → whoami.ts} +37 -71
  211. package/src/worker.ts +61 -3
  212. package/src/yargs-types.ts +22 -5
  213. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  214. package/templates/__tests__/tsconfig.json +8 -0
  215. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  216. package/templates/checked-fetch.js +9 -3
  217. package/templates/d1-beta-facade.js +95 -25
  218. package/templates/facade.d.ts +14 -0
  219. package/templates/first-party-worker-module-facade.ts +4 -3
  220. package/templates/format-dev-errors.ts +8 -6
  221. package/templates/gitignore +1 -0
  222. package/templates/init-tests/test-jest-new-worker.js +3 -5
  223. package/templates/init-tests/test-vitest-new-worker.js +3 -5
  224. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  225. package/templates/middleware/loader-modules.ts +2 -2
  226. package/templates/middleware/loader-sw.ts +51 -31
  227. package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
  228. package/templates/new-worker.ts +3 -0
  229. package/templates/pages-dev-pipeline.ts +4 -1
  230. package/templates/pages-dev-util.ts +4 -1
  231. package/templates/pages-shim.ts +4 -1
  232. package/templates/pages-template-plugin.ts +19 -10
  233. package/templates/serve-static-assets.ts +17 -14
  234. package/templates/service-bindings-module-facade.js +1 -0
  235. package/templates/tsconfig-sanity.ts +11 -0
  236. package/templates/tsconfig.init.json +105 -0
  237. package/templates/tsconfig.json +5 -103
  238. package/templates/tsconfig.tsbuildinfo +1 -0
  239. package/wrangler-dist/cli.d.ts +902 -77
  240. package/wrangler-dist/cli.js +131685 -140615
  241. package/wrangler-dist/wasm-sync.wasm +0 -0
  242. package/src/__tests__/api-devregistry.test.js +0 -57
  243. package/src/__tests__/d1.test.ts +0 -72
  244. package/src/__tests__/dialogs.test.tsx +0 -40
  245. package/src/__tests__/helpers/mock-cfetch.ts +0 -333
  246. package/src/__tests__/pages.test.ts +0 -2223
  247. package/src/d1/types.tsx +0 -14
  248. package/src/dialogs.tsx +0 -163
  249. package/src/environment-variables.ts +0 -50
  250. package/src/pages/build.tsx +0 -238
  251. package/src/user/env-vars.ts +0 -46
  252. package/templates/experimental-local-cache-stubs.js +0 -27
  253. /package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
  254. /package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
  255. /package/src/pages/{hash.tsx → hash.ts} +0 -0
package/src/bundle.ts CHANGED
@@ -7,19 +7,28 @@ import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
7
7
  import * as esbuild from "esbuild";
8
8
  import tmp from "tmp-promise";
9
9
  import createModuleCollector from "./module-collection";
10
- import { getBasePath, toUrlPath } from "./paths";
10
+ import { getBasePath } from "./paths";
11
11
  import type { Config } from "./config";
12
+ import type { DurableObjectBindings } from "./config/environment";
12
13
  import type { WorkerRegistry } from "./dev-registry";
13
14
  import type { Entry } from "./entry";
15
+ import type { SourceMapMetadata } from "./inspect";
14
16
  import type { CfModule } from "./worker";
15
17
 
16
- type BundleResult = {
18
+ export const COMMON_ESBUILD_OPTIONS = {
19
+ // Our workerd runtime uses the same V8 version as recent Chrome, which is highly ES2022 compliant: https://kangax.github.io/compat-table/es2016plus/
20
+ target: "es2022",
21
+ loader: { ".js": "jsx", ".mjs": "jsx", ".cjs": "jsx" },
22
+ } as const;
23
+
24
+ export type BundleResult = {
17
25
  modules: CfModule[];
18
26
  dependencies: esbuild.Metafile["outputs"][string]["inputs"];
19
27
  resolvedEntryPointPath: string;
20
28
  bundleType: "esm" | "commonjs";
21
29
  stop: (() => void) | undefined;
22
30
  sourceMapPath?: string | undefined;
31
+ sourceMapMetadata?: SourceMapMetadata | undefined;
23
32
  };
24
33
 
25
34
  type StaticAssetsConfig =
@@ -28,6 +37,19 @@ type StaticAssetsConfig =
28
37
  })
29
38
  | undefined;
30
39
 
40
+ /**
41
+ * When applying the middleware facade for service workers, we need to inject
42
+ * some code at the top of the final output bundle. Applying an inject too early
43
+ * will allow esbuild to reorder the code. Additionally, we need to make sure
44
+ * user code is bundled in the final esbuild step with `watch` correctly
45
+ * configured, so code changes are detected.
46
+ *
47
+ * This type is used as the return type for the `MiddlewareFn` type representing
48
+ * a facade-applying function. Returned injects should be injected with the
49
+ * final esbuild step.
50
+ */
51
+ type EntryWithInject = Entry & { inject?: string[] };
52
+
31
53
  /**
32
54
  * RegExp matching against esbuild's error text when it is unable to resolve
33
55
  * a Node built-in module. If we detect this when node_compat is disabled,
@@ -57,21 +79,49 @@ export function isBuildFailure(err: unknown): err is esbuild.BuildFailure {
57
79
  * Rewrites esbuild BuildFailures for failing to resolve Node built-in modules
58
80
  * to suggest enabling Node compat as opposed to `platform: "node"`.
59
81
  */
60
- export function rewriteNodeCompatBuildFailure(err: esbuild.BuildFailure) {
82
+ export function rewriteNodeCompatBuildFailure(
83
+ err: esbuild.BuildFailure,
84
+ forPages = false
85
+ ) {
61
86
  for (const error of err.errors) {
62
87
  const match = nodeBuiltinResolveErrorText.exec(error.text);
63
88
  if (match !== null) {
89
+ const issue = `The package "${match[1]}" wasn't found on the file system but is built into node.`;
90
+
91
+ const instructionForUser = `${
92
+ forPages
93
+ ? 'Add the "nodejs_compat" compatibility flag to your Pages project'
94
+ : 'Add "node_compat = true" to your wrangler.toml file'
95
+ } to enable Node.js compatibility.`;
96
+
64
97
  error.notes = [
65
98
  {
66
99
  location: null,
67
- text: `The package "${match[1]}" wasn't found on the file system but is built into node.
68
- Add "node_compat = true" to your wrangler.toml file to enable Node compatibility.`,
100
+ text: `${issue}\n${instructionForUser}`,
69
101
  },
70
102
  ];
71
103
  }
72
104
  }
73
105
  }
74
106
 
107
+ const nodejsCompatPlugin: esbuild.Plugin = {
108
+ name: "nodejs_compat Plugin",
109
+ setup(pluginBuild) {
110
+ pluginBuild.onResolve({ filter: /node:.*/ }, () => {
111
+ return { external: true };
112
+ });
113
+ },
114
+ };
115
+
116
+ const cloudflareJsPlugin: esbuild.Plugin = {
117
+ name: "cloudflare javascript Plugin",
118
+ setup(pluginBuild) {
119
+ pluginBuild.onResolve({ filter: /^cloudflare:.*/ }, () => {
120
+ return { external: true };
121
+ });
122
+ },
123
+ };
124
+
75
125
  /**
76
126
  * Generate a bundle for the worker identified by the arguments passed in.
77
127
  */
@@ -79,37 +129,55 @@ export async function bundleWorker(
79
129
  entry: Entry,
80
130
  destination: string,
81
131
  options: {
132
+ // When `bundle` is set to false, we apply shims to the Worker, but won't pull in any imports
133
+ bundle?: boolean;
82
134
  serveAssetsFromWorker: boolean;
83
- assets: StaticAssetsConfig;
135
+ assets?: StaticAssetsConfig;
84
136
  betaD1Shims?: string[];
85
- jsxFactory: string | undefined;
86
- jsxFragment: string | undefined;
137
+ doBindings: DurableObjectBindings;
138
+ jsxFactory?: string;
139
+ jsxFragment?: string;
140
+ entryName?: string;
87
141
  rules: Config["rules"];
88
- watch?: esbuild.WatchMode;
89
- tsconfig: string | undefined;
90
- minify: boolean | undefined;
91
- nodeCompat: boolean | undefined;
142
+ watch?: esbuild.WatchMode | boolean;
143
+ tsconfig?: string;
144
+ minify?: boolean;
145
+ legacyNodeCompat?: boolean;
146
+ nodejsCompat?: boolean;
92
147
  define: Config["define"];
93
148
  checkFetch: boolean;
94
- services: Config["services"] | undefined;
95
- workerDefinitions: WorkerRegistry | undefined;
96
- firstPartyWorkerDevFacade: boolean | undefined;
149
+ services?: Config["services"];
150
+ workerDefinitions?: WorkerRegistry;
151
+ firstPartyWorkerDevFacade?: boolean;
97
152
  targetConsumer: "dev" | "publish";
98
153
  local: boolean;
99
- testScheduled?: boolean | undefined;
100
- experimentalLocalStubCache: boolean | undefined;
154
+ testScheduled?: boolean;
155
+ experimentalLocal?: boolean;
156
+ inject?: string[];
157
+ loader?: Record<string, string>;
158
+ sourcemap?: esbuild.CommonOptions["sourcemap"];
159
+ plugins?: esbuild.Plugin[];
160
+ additionalModules?: CfModule[];
161
+ // TODO: Rip these out https://github.com/cloudflare/workers-sdk/issues/2153
162
+ disableModuleCollection?: boolean;
163
+ isOutfile?: boolean;
164
+ forPages?: boolean;
101
165
  }
102
166
  ): Promise<BundleResult> {
103
167
  const {
168
+ bundle = true,
104
169
  serveAssetsFromWorker,
105
170
  betaD1Shims,
171
+ doBindings,
106
172
  jsxFactory,
107
173
  jsxFragment,
174
+ entryName,
108
175
  rules,
109
176
  watch,
110
177
  tsconfig,
111
178
  minify,
112
- nodeCompat,
179
+ legacyNodeCompat,
180
+ nodejsCompat,
113
181
  checkFetch,
114
182
  local,
115
183
  assets,
@@ -118,7 +186,15 @@ export async function bundleWorker(
118
186
  firstPartyWorkerDevFacade,
119
187
  targetConsumer,
120
188
  testScheduled,
121
- experimentalLocalStubCache,
189
+ experimentalLocal,
190
+ inject: injectOption,
191
+ loader,
192
+ sourcemap,
193
+ plugins,
194
+ disableModuleCollection,
195
+ isOutfile,
196
+ forPages,
197
+ additionalModules = [],
122
198
  } = options;
123
199
 
124
200
  // We create a temporary directory for any oneoff files we
@@ -127,7 +203,7 @@ export async function bundleWorker(
127
203
  const tmpDir = await tmp.dir({ unsafeCleanup: true });
128
204
 
129
205
  const entryDirectory = path.dirname(entry.file);
130
- const moduleCollector = createModuleCollector({
206
+ let moduleCollector = createModuleCollector({
131
207
  wrangler1xlegacyModuleReferences: {
132
208
  rootDirectory: entryDirectory,
133
209
  fileNames: new Set(
@@ -143,6 +219,15 @@ export async function bundleWorker(
143
219
  format: entry.format,
144
220
  rules,
145
221
  });
222
+ if (disableModuleCollection) {
223
+ moduleCollector = {
224
+ modules: [],
225
+ plugin: {
226
+ name: moduleCollector.plugin.name,
227
+ setup: () => {},
228
+ },
229
+ };
230
+ }
146
231
 
147
232
  // In dev, we want to patch `fetch()` with a special version that looks
148
233
  // for bad usages and can warn the user about them; so we inject
@@ -177,8 +262,29 @@ export async function bundleWorker(
177
262
  path: "templates/middleware/middleware-scheduled.ts",
178
263
  });
179
264
  }
265
+ if (experimentalLocal) {
266
+ // In Miniflare 3, we bind the user's worker as a service binding in a
267
+ // special entry worker that handles things like injecting `Request.cf`,
268
+ // live-reload, and the pretty-error page.
269
+ //
270
+ // Unfortunately, due to a bug in `workerd`, errors thrown asynchronously by
271
+ // native APIs don't have `stack`s. This means Miniflare can't extract the
272
+ // `stack` trace from dispatching to the user worker service binding by
273
+ // `try/catch`.
274
+ //
275
+ // As a stop-gap solution, if the `MF-Experimental-Error-Stack` header is
276
+ // truthy on responses, the body will be interpreted as a JSON-error of the
277
+ // form `{ message?: string, name?: string, stack?: string }`.
278
+ //
279
+ // This middleware wraps the user's worker in a `try/catch`, and rewrites
280
+ // errors in this format so a pretty-error page can be shown.
281
+ middlewareToLoad.push({
282
+ path: "templates/middleware/middleware-miniflare3-json-error.ts",
283
+ dev: true,
284
+ });
285
+ }
180
286
 
181
- type MiddlewareFn = (arg0: Entry) => Promise<Entry>;
287
+ type MiddlewareFn = (currentEntry: Entry) => Promise<EntryWithInject>;
182
288
  const middleware: (false | undefined | MiddlewareFn)[] = [
183
289
  // serve static assets
184
290
  serveAssetsFromWorker &&
@@ -215,7 +321,13 @@ export async function bundleWorker(
215
321
  Array.isArray(betaD1Shims) &&
216
322
  betaD1Shims.length > 0 &&
217
323
  ((currentEntry: Entry) => {
218
- return applyD1BetaFacade(currentEntry, tmpDir.path, betaD1Shims, local);
324
+ return applyD1BetaFacade(
325
+ currentEntry,
326
+ tmpDir.path,
327
+ betaD1Shims,
328
+ local && !experimentalLocal,
329
+ doBindings
330
+ );
219
331
  }),
220
332
 
221
333
  // Middleware loader: to add middleware, we add the path to the middleware
@@ -239,68 +351,68 @@ export async function bundleWorker(
239
351
  (m) =>
240
352
  (targetConsumer === "dev" && m.dev !== false) ||
241
353
  (m.publish && targetConsumer === "publish")
242
- ),
243
- moduleCollector.plugin
354
+ )
244
355
  );
245
356
  }),
246
357
  ].filter(Boolean);
247
358
 
248
- let inputEntry = entry;
359
+ const inject: string[] = injectOption ?? [];
360
+ if (checkFetch) inject.push(checkedFetchFileToInject);
249
361
 
362
+ let inputEntry: EntryWithInject = entry;
250
363
  for (const middlewareFn of middleware as MiddlewareFn[]) {
251
364
  inputEntry = await middlewareFn(inputEntry);
365
+ if (inputEntry.inject !== undefined) inject.push(...inputEntry.inject);
252
366
  }
253
367
 
254
368
  // At this point, inputEntry points to the entry point we want to build.
255
369
 
256
- const inject: string[] = [];
257
- if (checkFetch) inject.push(checkedFetchFileToInject);
258
- if (experimentalLocalStubCache) {
259
- inject.push(
260
- path.resolve(getBasePath(), "templates/experimental-local-cache-stubs.js")
261
- );
262
- }
263
-
264
370
  const buildOptions: esbuild.BuildOptions & { metafile: true } = {
265
371
  entryPoints: [inputEntry.file],
266
- bundle: true,
372
+ bundle,
267
373
  absWorkingDir: entry.directory,
268
374
  outdir: destination,
375
+ entryNames: entryName || path.parse(entry.file).name,
376
+ ...(isOutfile
377
+ ? {
378
+ outdir: undefined,
379
+ outfile: destination,
380
+ entryNames: undefined,
381
+ }
382
+ : {}),
269
383
  inject,
270
- external: ["__STATIC_CONTENT_MANIFEST"],
384
+ external: bundle ? ["__STATIC_CONTENT_MANIFEST"] : undefined,
271
385
  format: entry.format === "modules" ? "esm" : "iife",
272
- target: "es2020",
273
- sourcemap: true,
386
+ target: COMMON_ESBUILD_OPTIONS.target,
387
+ sourcemap: sourcemap ?? true,
274
388
  // Include a reference to the output folder in the sourcemap.
275
389
  // This is omitted by default, but we need it to properly resolve source paths in error output.
276
390
  sourceRoot: destination,
277
391
  minify,
278
392
  metafile: true,
279
- conditions: ["worker", "browser"],
393
+ conditions: ["workerd", "worker", "browser"],
280
394
  ...(process.env.NODE_ENV && {
281
395
  define: {
282
396
  // use process.env["NODE_ENV" + ""] so that esbuild doesn't replace it
283
- // when we do a build of wrangler. (re: https://github.com/cloudflare/wrangler2/issues/1477)
397
+ // when we do a build of wrangler. (re: https://github.com/cloudflare/workers-sdk/issues/1477)
284
398
  "process.env.NODE_ENV": `"${process.env["NODE_ENV" + ""]}"`,
285
- ...(nodeCompat ? { global: "globalThis" } : {}),
399
+ ...(legacyNodeCompat ? { global: "globalThis" } : {}),
286
400
  ...(checkFetch ? { fetch: "checkedFetch" } : {}),
287
401
  ...options.define,
288
402
  },
289
403
  }),
290
404
  loader: {
291
- ".js": "jsx",
292
- ".mjs": "jsx",
293
- ".cjs": "jsx",
405
+ ...COMMON_ESBUILD_OPTIONS.loader,
406
+ ...(loader || {}),
294
407
  },
295
408
  plugins: [
296
- // We run the moduleCollector plugin for service workers as part of the middleware loader
297
- // so we only run here for modules or with no middleware to load
298
- ...(entry.format === "modules" || middlewareToLoad.length === 0
299
- ? [moduleCollector.plugin]
300
- : []),
301
- ...(nodeCompat
409
+ moduleCollector.plugin,
410
+ ...(legacyNodeCompat
302
411
  ? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
303
412
  : []),
413
+ ...(nodejsCompat ? [nodejsCompatPlugin] : []),
414
+ ...[cloudflareJsPlugin],
415
+ ...(plugins || []),
304
416
  ],
305
417
  ...(jsxFactory && { jsxFactory }),
306
418
  ...(jsxFragment && { jsxFragment }),
@@ -315,7 +427,8 @@ export async function bundleWorker(
315
427
  try {
316
428
  result = await esbuild.build(buildOptions);
317
429
  } catch (e) {
318
- if (!nodeCompat && isBuildFailure(e)) rewriteNodeCompatBuildFailure(e);
430
+ if (!legacyNodeCompat && isBuildFailure(e))
431
+ rewriteNodeCompatBuildFailure(e, forPages);
319
432
  throw e;
320
433
  }
321
434
 
@@ -341,16 +454,39 @@ export async function bundleWorker(
341
454
  _path.includes(".map")
342
455
  )[0];
343
456
 
457
+ const resolvedEntryPointPath = path.resolve(
458
+ entry.directory,
459
+ entryPointOutputs[0][0]
460
+ );
461
+
462
+ // A collision between additionalModules and moduleCollector.modules is incredibly unlikely because moduleCollector hashes the modules it collects.
463
+ // However, if it happens, let's trust the explicitly provided additionalModules over the ones we discovered.
464
+ const modules = dedupeModulesByName([
465
+ ...moduleCollector.modules,
466
+ ...additionalModules,
467
+ ]);
468
+
469
+ // copy all referenced modules into the output bundle directory
470
+ for (const module of modules) {
471
+ const modulePath = path.join(
472
+ path.dirname(resolvedEntryPointPath),
473
+ module.name
474
+ );
475
+ fs.mkdirSync(path.dirname(modulePath), { recursive: true });
476
+ fs.writeFileSync(modulePath, module.content);
477
+ }
478
+
344
479
  return {
345
- modules: moduleCollector.modules,
480
+ modules,
346
481
  dependencies,
347
- resolvedEntryPointPath: path.resolve(
348
- entry.directory,
349
- entryPointOutputs[0][0]
350
- ),
482
+ resolvedEntryPointPath,
351
483
  bundleType,
352
484
  stop: result.stop,
353
485
  sourceMapPath,
486
+ sourceMapMetadata: {
487
+ tmpDir: tmpDir.path,
488
+ entryDirectory: entry.directory,
489
+ },
354
490
  };
355
491
  }
356
492
 
@@ -433,14 +569,16 @@ interface MiddlewareLoader {
433
569
  async function applyMiddlewareLoaderFacade(
434
570
  entry: Entry,
435
571
  tmpDirPath: string,
436
- middleware: MiddlewareLoader[], // a list of paths to middleware files
437
- moduleCollectorPlugin: esbuild.Plugin
438
- ): Promise<Entry> {
572
+ middleware: MiddlewareLoader[] // a list of paths to middleware files
573
+ ): Promise<EntryWithInject> {
439
574
  // Firstly we need to insert the middleware array into the project,
440
575
  // and then we load the middleware - this insertion and loading is
441
576
  // different for each format.
442
577
 
443
- // STEP 1: Insert the middleware
578
+ // Make sure we resolve all files relative to the actual temporary directory,
579
+ // otherwise we'll have issues with source maps
580
+ tmpDirPath = fs.realpathSync(tmpDirPath);
581
+
444
582
  const targetPathInsertion = path.join(
445
583
  tmpDirPath,
446
584
  "middleware-insertion.entry.js"
@@ -483,7 +621,7 @@ async function applyMiddlewareLoaderFacade(
483
621
  );
484
622
 
485
623
  await esbuild.build({
486
- entryPoints: [path.resolve(getBasePath(), dynamicFacadePath)],
624
+ entryPoints: [dynamicFacadePath],
487
625
  bundle: true,
488
626
  sourcemap: true,
489
627
  format: "esm",
@@ -493,105 +631,88 @@ async function applyMiddlewareLoaderFacade(
493
631
  ...Object.fromEntries(
494
632
  middleware.map((val, index) => [
495
633
  middlewareIdentifiers[index],
496
- toUrlPath(path.resolve(getBasePath(), val.path)),
634
+ path.resolve(getBasePath(), val.path),
497
635
  ])
498
636
  ),
499
637
  }),
500
638
  ],
501
639
  outfile: targetPathInsertion,
502
640
  });
503
- } else {
504
- // We handle service workers slightly differently as we have to overwrite
505
- // the event listeners and reimplement them
506
-
641
+ const targetPathLoader = path.join(
642
+ tmpDirPath,
643
+ "middleware-loader.entry.js"
644
+ );
645
+ const loaderPath = path.resolve(
646
+ getBasePath(),
647
+ "templates/middleware/loader-modules.ts"
648
+ );
507
649
  await esbuild.build({
508
- entryPoints: [entry.file],
650
+ entryPoints: [loaderPath],
509
651
  bundle: true,
510
652
  sourcemap: true,
511
- define: {
512
- "process.env.NODE_ENV": `"${process.env["NODE_ENV" + ""]}"`,
513
- },
514
653
  format: "esm",
515
- outfile: targetPathInsertion,
516
- plugins: [moduleCollectorPlugin],
654
+ plugins: [
655
+ esbuildAliasExternalPlugin({
656
+ __ENTRY_POINT__: targetPathInsertion,
657
+ "./common": path.resolve(
658
+ getBasePath(),
659
+ "templates/middleware/common.ts"
660
+ ),
661
+ }),
662
+ ],
663
+ outfile: targetPathLoader,
517
664
  });
518
-
665
+ return {
666
+ ...entry,
667
+ file: targetPathLoader,
668
+ };
669
+ } else {
519
670
  const imports = middlewareIdentifiers
520
- .map(
521
- (m, i) =>
522
- `import ${m} from "${toUrlPath(
523
- path.resolve(getBasePath(), middleware[i].path)
524
- )}";`
525
- )
671
+ .map((m) => `import ${m} from "${m}";`)
526
672
  .join("\n");
527
-
528
- // We add the new modules with imports and then register using the
529
- // addMiddleware function (which gets rewritten in the next build step)
530
-
531
- // We choose to run middleware inserted in wrangler before user inserted
532
- // middleware in the stack
533
- // To do this, we either need to execute the addMiddleware function first
534
- // before any user middleware, or use a separate handling function.
535
- // We choose to do the latter as to prepend, we would have to load the entire
536
- // script into memory as a prepend function doesn't exist or work in the same
537
- // way that an append function does.
538
-
539
- fs.copyFileSync(targetPathInsertion, dynamicFacadePath);
540
- fs.appendFileSync(
541
- dynamicFacadePath,
542
- `
673
+ const contents = `import { __facade_registerInternal__ } from "__LOADER__";
543
674
  ${imports}
544
- addMiddlewareInternal([${middlewareIdentifiers.join(",")}])
545
- `
546
- );
547
- }
675
+ __facade_registerInternal__([${middlewareIdentifiers.join(",")}]);`;
676
+ fs.writeFileSync(dynamicFacadePath, contents);
548
677
 
549
- // STEP 2: Load the middleware
550
- // We want to get the filename of the orginal entry point
551
- let targetPathLoader = path.join(tmpDirPath, path.basename(entry.file));
552
- if (path.extname(entry.file) === "") targetPathLoader += ".js";
553
-
554
- const loaderPath =
555
- entry.format === "modules"
556
- ? path.resolve(getBasePath(), "templates/middleware/loader-modules.ts")
557
- : dynamicFacadePath;
558
-
559
- await esbuild.build({
560
- entryPoints: [loaderPath],
561
- bundle: true,
562
- sourcemap: true,
563
- format: "esm",
564
- ...(entry.format === "service-worker"
565
- ? {
566
- inject: [
567
- path.resolve(getBasePath(), "templates/middleware/loader-sw.ts"),
568
- ],
569
- define: {
570
- addEventListener: "__facade_addEventListener__",
571
- removeEventListener: "__facade_removeEventListener__",
572
- dispatchEvent: "__facade_dispatchEvent__",
573
- addMiddleware: "__facade_register__",
574
- addMiddlewareInternal: "__facade_registerInternal__",
575
- },
576
- }
577
- : {
578
- plugins: [
579
- esbuildAliasExternalPlugin({
580
- __ENTRY_POINT__: targetPathInsertion,
581
- "./common": path.resolve(
678
+ await esbuild.build({
679
+ entryPoints: [dynamicFacadePath],
680
+ bundle: true,
681
+ sourcemap: true,
682
+ format: "iife",
683
+ plugins: [
684
+ {
685
+ name: "dynamic-facade-imports",
686
+ setup(build) {
687
+ build.onResolve({ filter: /^__LOADER__$/ }, () => {
688
+ const loaderPath = path.resolve(
582
689
  getBasePath(),
583
- "templates/middleware/common.ts"
584
- ),
585
- }),
586
- ],
587
- }),
588
- outfile: targetPathLoader,
589
- });
590
-
591
- return {
592
- ...entry,
593
- file: targetPathLoader,
594
- };
690
+ "templates/middleware/loader-sw.ts"
691
+ );
692
+ return { path: loaderPath };
693
+ });
694
+ const middlewareFilter = /^__MIDDLEWARE_(\d+)__$/;
695
+ build.onResolve({ filter: middlewareFilter }, (args) => {
696
+ const match = middlewareFilter.exec(args.path);
697
+ assert(match !== null);
698
+ const middlewareIndex = parseInt(match[1]);
699
+ return {
700
+ path: path.resolve(
701
+ getBasePath(),
702
+ middleware[middlewareIndex].path
703
+ ),
704
+ };
705
+ });
706
+ },
707
+ },
708
+ ],
709
+ outfile: targetPathInsertion,
710
+ });
711
+ return {
712
+ ...entry,
713
+ inject: [targetPathInsertion],
714
+ };
715
+ }
595
716
  }
596
717
 
597
718
  /**
@@ -741,17 +862,51 @@ async function applyFirstPartyWorkerDevFacade(
741
862
  * This code be removed from here when the API is in Workers core,
742
863
  * but moved inside Miniflare for simulating D1.
743
864
  */
744
-
745
865
  async function applyD1BetaFacade(
746
866
  entry: Entry,
747
867
  tmpDirPath: string,
748
868
  betaD1Shims: string[],
749
- local: boolean
869
+ miniflare2: boolean,
870
+ doBindings: DurableObjectBindings
750
871
  ): Promise<Entry> {
872
+ let entrypointPath = path.resolve(
873
+ getBasePath(),
874
+ "templates/d1-beta-facade.js"
875
+ );
876
+ if (Array.isArray(doBindings) && doBindings.length > 0) {
877
+ //we have DO bindings, so we need to shim them
878
+ const maskedDoBindings = doBindings
879
+ // Don't shim anything not local to this worker
880
+ .filter((b) => !b.script_name)
881
+ // Reexport the DO classnames
882
+ .map(
883
+ (b) =>
884
+ `export const ${b.class_name} = maskDurableObjectDefinition(OTHER_EXPORTS.${b.class_name});`
885
+ )
886
+ .join("\n");
887
+ const baseFile = fs.readFileSync(
888
+ path.resolve(getBasePath(), "templates/d1-beta-facade.js"),
889
+ "utf8"
890
+ );
891
+ //getMaskedEnv is already used to shim regular Workers
892
+ const contents = `
893
+ ${baseFile}
894
+
895
+ var maskDurableObjectDefinition = (cls) =>
896
+ class extends cls {
897
+ constructor(state, env) {
898
+ super(state, getMaskedEnv(env));
899
+ }
900
+ };
901
+ ${maskedDoBindings}`;
902
+ const doD1FacadePath = path.join(tmpDirPath, "d1-do-facade.js");
903
+ //write our shim so we can build it
904
+ fs.writeFileSync(doD1FacadePath, contents);
905
+ entrypointPath = doD1FacadePath;
906
+ }
751
907
  const targetPath = path.join(tmpDirPath, "d1-beta-facade.entry.js");
752
-
753
908
  await esbuild.build({
754
- entryPoints: [path.resolve(getBasePath(), "templates/d1-beta-facade.js")],
909
+ entryPoints: [entrypointPath],
755
910
  bundle: true,
756
911
  format: "esm",
757
912
  sourcemap: true,
@@ -762,7 +917,7 @@ async function applyD1BetaFacade(
762
917
  ],
763
918
  define: {
764
919
  __D1_IMPORTS__: JSON.stringify(betaD1Shims),
765
- __LOCAL_MODE__: JSON.stringify(local),
920
+ __LOCAL_MODE__: JSON.stringify(miniflare2),
766
921
  },
767
922
  outfile: targetPath,
768
923
  });
@@ -782,4 +937,16 @@ function listEntryPoints(
782
937
  return outputs.map(([_input, output]) => output.entryPoint).join("\n");
783
938
  }
784
939
 
940
+ /**
941
+ * Prefer modules towards the end of the array in the case of a collision by name.
942
+ */
943
+ export function dedupeModulesByName(modules: CfModule[]): CfModule[] {
944
+ return Object.values(
945
+ modules.reduce((moduleMap, module) => {
946
+ moduleMap[module.name] = module;
947
+ return moduleMap;
948
+ }, {} as Record<string, CfModule>)
949
+ );
950
+ }
951
+
785
952
  type ValueOf<T> = T[keyof T];
@@ -6,8 +6,6 @@ import type { RequestInit } from "undici";
6
6
 
7
7
  // Check out https://api.cloudflare.com/ for API docs.
8
8
 
9
- export { getCloudflareAPIBaseURL as getCloudflareApiBaseUrl } from "./internal";
10
-
11
9
  export interface FetchError {
12
10
  code: number;
13
11
  message: string;