wrangler 4.11.1 → 4.12.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "4.11.1",
3
+ "version": "4.12.1",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -55,14 +55,14 @@
55
55
  "esbuild": "0.25.2",
56
56
  "path-to-regexp": "6.3.0",
57
57
  "unenv": "2.0.0-rc.15",
58
- "workerd": "1.20250410.0",
59
- "miniflare": "4.20250410.1",
58
+ "workerd": "1.20250417.0",
59
+ "miniflare": "4.20250417.0",
60
60
  "@cloudflare/kv-asset-handler": "0.4.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@aws-sdk/client-s3": "^3.721.0",
64
64
  "@cloudflare/types": "6.18.4",
65
- "@cloudflare/workers-types": "^4.20250410.0",
65
+ "@cloudflare/workers-types": "^4.20250417.0",
66
66
  "@cspotcode/source-map-support": "0.8.1",
67
67
  "@iarna/toml": "^3.0.0",
68
68
  "@microsoft/api-extractor": "^7.47.0",
@@ -84,7 +84,7 @@
84
84
  "@types/supports-color": "^8.1.1",
85
85
  "@types/ws": "^8.5.7",
86
86
  "@types/yargs": "^17.0.22",
87
- "@vitest/ui": "~3.0.8",
87
+ "@vitest/ui": "~3.1.1",
88
88
  "@webcontainer/env": "^1.1.0",
89
89
  "chalk": "^5.2.0",
90
90
  "chokidar": "^4.0.1",
@@ -129,20 +129,20 @@
129
129
  "typescript": "^5.7.2",
130
130
  "undici": "^5.28.5",
131
131
  "update-check": "^1.5.4",
132
- "vitest": "~3.0.8",
132
+ "vitest": "~3.1.1",
133
133
  "vitest-websocket-mock": "^0.4.0",
134
134
  "ws": "8.18.0",
135
135
  "xdg-app-paths": "^8.3.0",
136
136
  "xxhash-wasm": "^1.0.1",
137
137
  "yargs": "^17.7.2",
138
- "@cloudflare/cli": "1.1.1",
139
138
  "@cloudflare/eslint-config-worker": "1.1.0",
140
- "@cloudflare/pages-shared": "^0.13.28",
139
+ "@cloudflare/pages-shared": "^0.13.30",
140
+ "@cloudflare/cli": "1.1.1",
141
141
  "@cloudflare/workers-shared": "0.17.2",
142
142
  "@cloudflare/workers-tsconfig": "0.0.0"
143
143
  },
144
144
  "peerDependencies": {
145
- "@cloudflare/workers-types": "^4.20250410.0"
145
+ "@cloudflare/workers-types": "^4.20250417.0"
146
146
  },
147
147
  "peerDependenciesMeta": {
148
148
  "@cloudflare/workers-types": {
@@ -81185,7 +81185,7 @@ var import_undici3 = __toESM(require_undici());
81185
81185
 
81186
81186
  // package.json
81187
81187
  var name = "wrangler";
81188
- var version = "4.11.1";
81188
+ var version = "4.12.1";
81189
81189
 
81190
81190
  // src/environment-variables/misc-variables.ts
81191
81191
  init_import_meta_url();
@@ -90797,7 +90797,12 @@ async function getOauthToken(options33) {
90797
90797
  }
90798
90798
  }
90799
90799
  });
90800
- server.listen(8976, "localhost");
90800
+ if (options33.callbackHost !== "localhost" || options33.callbackPort !== 8976) {
90801
+ logger.log(
90802
+ `Temporary login server listening on ${options33.callbackHost}:${options33.callbackPort}`
90803
+ );
90804
+ }
90805
+ server.listen(options33.callbackPort, options33.callbackHost);
90801
90806
  });
90802
90807
  if (options33.browser) {
90803
90808
  logger.log(`Opening a link in your default browser: ${urlToOpen}`);
@@ -90808,7 +90813,11 @@ async function getOauthToken(options33) {
90808
90813
  return Promise.race([timerPromise, loginPromise]);
90809
90814
  }
90810
90815
  __name(getOauthToken, "getOauthToken");
90811
- async function login(props = { browser: true }) {
90816
+ async function login(props = {
90817
+ browser: true,
90818
+ callbackHost: "localhost",
90819
+ callbackPort: 8976
90820
+ }) {
90812
90821
  const authFromEnv = getAuthFromEnv();
90813
90822
  if (authFromEnv) {
90814
90823
  logger.error(
@@ -90827,7 +90836,9 @@ async function login(props = { browser: true }) {
90827
90836
  },
90828
90837
  granted: {
90829
90838
  url: "https://welcome.developers.workers.dev/wrangler-oauth-consent-granted"
90830
- }
90839
+ },
90840
+ callbackHost: props.callbackHost,
90841
+ callbackPort: props.callbackPort
90831
90842
  });
90832
90843
  writeAuthConfigFile({
90833
90844
  oauth_token: oauth.token?.value ?? "",
@@ -92940,6 +92951,12 @@ function buildMiniflareBindingOptions(config) {
92940
92951
  hyperdrives: Object.fromEntries(
92941
92952
  bindings.hyperdrive?.map(hyperdriveEntry) ?? []
92942
92953
  ),
92954
+ analyticsEngineDatasets: Object.fromEntries(
92955
+ bindings.analytics_engine_datasets?.map((binding) => [
92956
+ binding.binding,
92957
+ { dataset: binding.dataset ?? "dataset" }
92958
+ ]) ?? []
92959
+ ),
92943
92960
  workflows: Object.fromEntries(bindings.workflows?.map(workflowEntry) ?? []),
92944
92961
  secretsStoreSecrets: Object.fromEntries(
92945
92962
  bindings.secrets_store_secrets?.map((binding) => [
@@ -93009,7 +93026,8 @@ function buildPersistOptions(localPersistencePath) {
93009
93026
  r2Persist: import_node_path15.default.join(v3Path, "r2"),
93010
93027
  d1Persist: import_node_path15.default.join(v3Path, "d1"),
93011
93028
  workflowsPersist: import_node_path15.default.join(v3Path, "workflows"),
93012
- secretsStorePersist: import_node_path15.default.join(v3Path, "secrets-store")
93029
+ secretsStorePersist: import_node_path15.default.join(v3Path, "secrets-store"),
93030
+ analyticsEngineDatasetsPersist: import_node_path15.default.join(v3Path, "analytics-engine")
93013
93031
  };
93014
93032
  }
93015
93033
  }
@@ -103485,7 +103503,6 @@ async function bundleWorker(entry, destination, {
103485
103503
  alias,
103486
103504
  define,
103487
103505
  checkFetch,
103488
- mockAnalyticsEngineDatasets,
103489
103506
  targetConsumer,
103490
103507
  testScheduled,
103491
103508
  inject: injectOption,
@@ -103500,16 +103517,6 @@ async function bundleWorker(entry, destination, {
103500
103517
  const tmpDir = getWranglerTmpDir(projectRoot, "bundle");
103501
103518
  const entryFile = entry.file;
103502
103519
  const middlewareToLoad = [];
103503
- if (targetConsumer === "dev" && mockAnalyticsEngineDatasets && mockAnalyticsEngineDatasets.length > 0) {
103504
- middlewareToLoad.push({
103505
- name: "mock-analytics-engine",
103506
- path: "templates/middleware/middleware-mock-analytics-engine.ts",
103507
- config: {
103508
- bindings: mockAnalyticsEngineDatasets.map(({ binding }) => binding)
103509
- },
103510
- supports: ["modules", "service-worker"]
103511
- });
103512
- }
103513
103520
  if (targetConsumer === "dev" && !process.env.WRANGLER_DISABLE_REQUEST_BODY_DRAINING) {
103514
103521
  middlewareToLoad.push({
103515
103522
  name: "ensure-req-body-drained",
@@ -110657,7 +110664,7 @@ function handleFailure(cb2) {
110657
110664
  await fillOpenAPIConfiguration(config, args.json);
110658
110665
  await cb2(args, config);
110659
110666
  } catch (err) {
110660
- if (!args.json) {
110667
+ if (!args.json || !isNonInteractiveOrCI()) {
110661
110668
  throw err;
110662
110669
  }
110663
110670
  if (err instanceof ApiError) {
@@ -114002,6 +114009,208 @@ var cloudchamber = /* @__PURE__ */ __name((yargs, subHelp) => {
114002
114009
 
114003
114010
  // src/containers/index.ts
114004
114011
  init_import_meta_url();
114012
+
114013
+ // src/containers/containers.ts
114014
+ init_import_meta_url();
114015
+ function deleteYargs(args) {
114016
+ return args.positional("ID", {
114017
+ describe: "id of the containers to delete",
114018
+ type: "string"
114019
+ });
114020
+ }
114021
+ __name(deleteYargs, "deleteYargs");
114022
+ async function deleteCommand2(deleteArgs, _config) {
114023
+ await loadAccountSpinner(deleteArgs);
114024
+ if (!deleteArgs.ID) {
114025
+ throw new Error(
114026
+ "You must provide an ID. Use 'wrangler containers list` to view your containers."
114027
+ );
114028
+ }
114029
+ if (deleteArgs.json || !isInteractive2()) {
114030
+ const container = await ApplicationsService.deleteApplication(
114031
+ deleteArgs.ID
114032
+ );
114033
+ console.log(JSON.stringify(container, null, 4));
114034
+ return;
114035
+ }
114036
+ startSection("Delete your container");
114037
+ const yes = await inputPrompt({
114038
+ question: "Are you sure that you want to delete these containers? The associated DO container will lose access to the containers.",
114039
+ type: "confirm",
114040
+ label: ""
114041
+ });
114042
+ if (!yes) {
114043
+ cancel("The operation has been cancelled");
114044
+ return;
114045
+ }
114046
+ const [, err] = await wrap2(
114047
+ ApplicationsService.deleteApplication(deleteArgs.ID)
114048
+ );
114049
+ if (err) {
114050
+ crash(
114051
+ `There has been an internal error deleting your containers.
114052
+ ${err.message}`
114053
+ );
114054
+ return;
114055
+ }
114056
+ endSection("Your container has been deleted");
114057
+ }
114058
+ __name(deleteCommand2, "deleteCommand");
114059
+ function infoYargs(args) {
114060
+ return args.positional("ID", {
114061
+ describe: "id of the containers to view",
114062
+ type: "string"
114063
+ });
114064
+ }
114065
+ __name(infoYargs, "infoYargs");
114066
+ async function infoCommand(infoArgs, _config) {
114067
+ if (!infoArgs.ID) {
114068
+ throw new Error(
114069
+ "You must provide an ID. Use 'wrangler containers list` to view your containers."
114070
+ );
114071
+ }
114072
+ if (infoArgs.json || !isInteractive2()) {
114073
+ const application2 = ApplicationsService.getApplication(infoArgs.ID);
114074
+ console.log(JSON.stringify(application2, null, 4));
114075
+ return;
114076
+ }
114077
+ await loadAccountSpinner(infoArgs);
114078
+ const [application, err] = await wrap2(
114079
+ ApplicationsService.getApplication(infoArgs.ID)
114080
+ );
114081
+ if (err) {
114082
+ crash(
114083
+ `There has been an internal error requesting your containers.
114084
+ ${err.message}`
114085
+ );
114086
+ return;
114087
+ }
114088
+ const details = flatDetails(application);
114089
+ const applicationDetails = {
114090
+ label: `${application.name} (${application.created_at})`,
114091
+ details,
114092
+ value: application.id
114093
+ };
114094
+ await inputPrompt({
114095
+ type: "list",
114096
+ question: "Container",
114097
+ options: [applicationDetails],
114098
+ label: "Exiting"
114099
+ });
114100
+ }
114101
+ __name(infoCommand, "infoCommand");
114102
+ function listYargs(args) {
114103
+ return args;
114104
+ }
114105
+ __name(listYargs, "listYargs");
114106
+ async function listCommand2(listArgs, config) {
114107
+ if (listArgs.json || !isInteractive2()) {
114108
+ const applications = await ApplicationsService.listApplications();
114109
+ console.log(JSON.stringify(applications, null, 4));
114110
+ return;
114111
+ }
114112
+ await listCommandHandle2(listArgs, config);
114113
+ }
114114
+ __name(listCommand2, "listCommand");
114115
+ function flatDetails(obj, indentLevel = 0) {
114116
+ const indent = " ".repeat(indentLevel);
114117
+ return Object.entries(obj).reduce((acc, [key, value]) => {
114118
+ if (value !== void 0 && value !== null && typeof value === "object" && !Array.isArray(value)) {
114119
+ acc.push(`${indent}${key}:`);
114120
+ acc.push(
114121
+ ...flatDetails(value, indentLevel + 1)
114122
+ );
114123
+ } else if (value !== void 0) {
114124
+ acc.push(`${indent}${key}: ${value}`);
114125
+ }
114126
+ return acc;
114127
+ }, []);
114128
+ }
114129
+ __name(flatDetails, "flatDetails");
114130
+ async function listCommandHandle2(_args, _config) {
114131
+ const keepListIter = true;
114132
+ while (keepListIter) {
114133
+ logRaw(gray(shapes.bar));
114134
+ const { start, stop } = spinner();
114135
+ start("Loading Containers");
114136
+ const [applications, err] = await wrap2(
114137
+ ApplicationsService.listApplications()
114138
+ );
114139
+ stop();
114140
+ if (err) {
114141
+ crash(
114142
+ `There has been an internal error listing your containers.
114143
+ ${err.message}`
114144
+ );
114145
+ return;
114146
+ }
114147
+ const applicationDetails = /* @__PURE__ */ __name((a5) => {
114148
+ const details = flatDetails(a5);
114149
+ return {
114150
+ label: `${a5.name} (${a5.created_at})`,
114151
+ details,
114152
+ value: a5.id
114153
+ };
114154
+ }, "applicationDetails");
114155
+ const application = await listContainersAndChoose(applications);
114156
+ let refresh = false;
114157
+ await inputPrompt({
114158
+ type: "list",
114159
+ question: "Containers",
114160
+ helpText: "Hit enter to return to your containers or 'r' to refresh",
114161
+ options: [applicationDetails(application)],
114162
+ label: "going back",
114163
+ onRefresh: /* @__PURE__ */ __name(async () => {
114164
+ start("Refreshing application");
114165
+ const app = await ApplicationsService.getApplication(application.id);
114166
+ if (refresh) {
114167
+ return [];
114168
+ }
114169
+ stop();
114170
+ if (app) {
114171
+ const details = applicationDetails(app);
114172
+ details.label += ", last refresh: " + (/* @__PURE__ */ new Date()).toLocaleString();
114173
+ return [details];
114174
+ }
114175
+ return app;
114176
+ }, "onRefresh")
114177
+ });
114178
+ refresh = true;
114179
+ stop();
114180
+ }
114181
+ }
114182
+ __name(listCommandHandle2, "listCommandHandle");
114183
+ async function listContainersAndChoose(applications) {
114184
+ const getLabels = /* @__PURE__ */ __name((a5) => {
114185
+ const labels = a5.configuration.labels ?? [];
114186
+ if (!labels || labels.length == 0) {
114187
+ return [];
114188
+ }
114189
+ const out = labels.map((l6) => ` ${dim(l6.name)}: ${dim(l6.value)}`);
114190
+ return `Labels:
114191
+ ` + out.join(",\n");
114192
+ }, "getLabels");
114193
+ const application = await processArgument({}, "applicationId", {
114194
+ type: "list",
114195
+ question: "Your Containers",
114196
+ helpText: "Get more information by selecting a container with the enter/return key",
114197
+ options: applications.map((i5) => ({
114198
+ label: i5.name,
114199
+ value: i5.id,
114200
+ details: [
114201
+ `Id: ${dim(`${i5.id}`)}`,
114202
+ `Instances: ${dim(`${i5.instances}`)}`,
114203
+ `Image: ${dim(i5.configuration.image)}`,
114204
+ ...getLabels(i5) ?? []
114205
+ ]
114206
+ })),
114207
+ label: "container"
114208
+ });
114209
+ return applications.find((a5) => a5.id === application);
114210
+ }
114211
+ __name(listContainersAndChoose, "listContainersAndChoose");
114212
+
114213
+ // src/containers/index.ts
114005
114214
  var containers = /* @__PURE__ */ __name((yargs, subHelp) => {
114006
114215
  return yargs.command(
114007
114216
  "build [PATH]",
@@ -114017,6 +114226,21 @@ var containers = /* @__PURE__ */ __name((yargs, subHelp) => {
114017
114226
  "images",
114018
114227
  "perform operations on images in your Cloudflare managed registry",
114019
114228
  (args) => imagesCommand(args).command(subHelp)
114229
+ ).command(
114230
+ "info [ID]",
114231
+ "get information about a specific container",
114232
+ (args) => infoYargs(args),
114233
+ (args) => handleFailure(infoCommand)(args)
114234
+ ).command(
114235
+ "list",
114236
+ "list containers",
114237
+ (args) => listYargs(args),
114238
+ (args) => handleFailure(listCommand2)(args)
114239
+ ).command(
114240
+ "delete [ID]",
114241
+ "delete a container",
114242
+ (args) => deleteYargs(args),
114243
+ (args) => handleFailure(deleteCommand2)(args)
114020
114244
  );
114021
114245
  }, "containers");
114022
114246
 
@@ -119835,8 +120059,6 @@ function buildWorkerFromFunctions({
119835
120059
  sourcemap,
119836
120060
  watch: watch2,
119837
120061
  nodejsCompatMode,
119838
- // TODO: mock AE datasets in Pages functions for dev
119839
- mockAnalyticsEngineDatasets: [],
119840
120062
  define: {
119841
120063
  __FALLBACK_SERVICE__: JSON.stringify(fallbackService)
119842
120064
  },
@@ -119896,8 +120118,6 @@ function buildRawWorker({
119896
120118
  sourcemap,
119897
120119
  watch: watch2,
119898
120120
  nodejsCompatMode,
119899
- // TODO: mock AE datasets in Pages functions for dev
119900
- mockAnalyticsEngineDatasets: [],
119901
120121
  define: {},
119902
120122
  alias: {},
119903
120123
  doBindings: [],
@@ -120221,8 +120441,6 @@ function buildPluginFromFunctions({
120221
120441
  }
120222
120442
  ],
120223
120443
  checkFetch: local && checkFetch,
120224
- // TODO: mock AE datasets in Pages functions for dev
120225
- mockAnalyticsEngineDatasets: [],
120226
120444
  targetConsumer: local ? "dev" : "deploy",
120227
120445
  local,
120228
120446
  projectRoot: getPagesProjectRoot(),
@@ -144685,6 +144903,18 @@ var loginCommand = createCommand({
144685
144903
  array: true,
144686
144904
  type: "string",
144687
144905
  requiresArg: true
144906
+ },
144907
+ "callback-host": {
144908
+ describe: "Use the ip or host address for the temporary login callback server.",
144909
+ type: "string",
144910
+ requiresArg: false,
144911
+ default: "localhost"
144912
+ },
144913
+ "callback-port": {
144914
+ describe: "Use the port for the temporary login callback server.",
144915
+ type: "number",
144916
+ requiresArg: false,
144917
+ default: 8976
144688
144918
  }
144689
144919
  },
144690
144920
  async handler(args, { config }) {
@@ -144702,10 +144932,19 @@ var loginCommand = createCommand({
144702
144932
  `One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --scopes-list" to see the valid scopes.`
144703
144933
  );
144704
144934
  }
144705
- await login({ scopes: args.scopes, browser: args.browser });
144935
+ await login({
144936
+ scopes: args.scopes,
144937
+ browser: args.browser,
144938
+ callbackHost: args.callbackHost,
144939
+ callbackPort: args.callbackPort
144940
+ });
144706
144941
  return;
144707
144942
  }
144708
- await login({ browser: args.browser });
144943
+ await login({
144944
+ browser: args.browser,
144945
+ callbackHost: args.callbackHost,
144946
+ callbackPort: args.callbackPort
144947
+ });
144709
144948
  sendMetricsEvent("login user", {
144710
144949
  sendMetrics: config.send_metrics
144711
144950
  });
@@ -144753,6 +144992,12 @@ var whoamiCommand = createCommand({
144753
144992
  // src/utils/logPossibleBugMessage.ts
144754
144993
  init_import_meta_url();
144755
144994
  async function logPossibleBugMessage() {
144995
+ if (process.versions.bun) {
144996
+ logger.warn(
144997
+ `Wrangler does not support the Bun runtime. Please try this command again using Node.js via \`npm\` or \`pnpm\`. Alternatively, make sure you're not passing the \`--bun\` flag when running \`bun run wrangler ...\``
144998
+ );
144999
+ return;
145000
+ }
144756
145001
  logger.log(
144757
145002
  `${fgGreenColor}%s${resetColor}`,
144758
145003
  "If you think this is a bug then please create an issue at https://github.com/cloudflare/workers-sdk/issues/new/choose"
@@ -147854,7 +148099,6 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
147854
148099
  define: { ...config.define, ...props.defines },
147855
148100
  alias: { ...config.alias, ...props.alias },
147856
148101
  checkFetch: false,
147857
- mockAnalyticsEngineDatasets: [],
147858
148102
  // We want to know if the build is for development or publishing
147859
148103
  // This could potentially cause issues as we no longer have identical behaviour between dev and deploy?
147860
148104
  targetConsumer: "deploy",
@@ -151161,8 +151405,6 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
151161
151405
  define: { ...config.define, ...props.defines },
151162
151406
  checkFetch: false,
151163
151407
  alias: config.alias,
151164
- // We do not mock AE datasets when deploying
151165
- mockAnalyticsEngineDatasets: [],
151166
151408
  // We want to know if the build is for development or publishing
151167
151409
  // This could potentially cause issues as we no longer have identical behaviour between dev and deploy?
151168
151410
  targetConsumer: "deploy",
@@ -153421,7 +153663,6 @@ function runBuild({
153421
153663
  alias,
153422
153664
  noBundle,
153423
153665
  findAdditionalModules: findAdditionalModules2,
153424
- mockAnalyticsEngineDatasets,
153425
153666
  durableObjects,
153426
153667
  workflows,
153427
153668
  local,
@@ -153488,7 +153729,6 @@ function runBuild({
153488
153729
  workflowBindings: workflows,
153489
153730
  alias,
153490
153731
  define,
153491
- mockAnalyticsEngineDatasets,
153492
153732
  targetConsumer,
153493
153733
  testScheduled,
153494
153734
  plugins: [logBuildOutput(nodejsCompatMode, onStart, updateBundle)],
@@ -153619,7 +153859,6 @@ var BundlerController = class extends Controller {
153619
153859
  config.compatibilityDate,
153620
153860
  config.compatibilityFlags
153621
153861
  ),
153622
- mockAnalyticsEngineDatasets: bindings.analytics_engine_datasets ?? [],
153623
153862
  alias: config.build.alias,
153624
153863
  // We want to know if the build is for development or publishing
153625
153864
  // This could potentially cause issues as we no longer have identical behaviour between dev and deploy?
@@ -153731,7 +153970,6 @@ var BundlerController = class extends Controller {
153731
153970
  findAdditionalModules: config.build?.findAdditionalModules,
153732
153971
  durableObjects: bindings?.durable_objects ?? { bindings: [] },
153733
153972
  workflows: bindings?.workflows ?? [],
153734
- mockAnalyticsEngineDatasets: bindings.analytics_engine_datasets ?? [],
153735
153973
  local: !config.dev?.remote,
153736
153974
  // startDevWorker only applies to "dev"
153737
153975
  targetConsumer: "dev",
@@ -1,3 +0,0 @@
1
- declare module "config:middleware/mock-analytics-engine" {
2
- export const bindings: string[];
3
- }
@@ -1,30 +0,0 @@
1
- /// <reference path="middleware-mock-analytics-engine.d.ts"/>
2
-
3
- import { bindings } from "config:middleware/mock-analytics-engine";
4
- import type { Middleware } from "./common";
5
-
6
- const bindingsEnv = Object.fromEntries(
7
- bindings.map((binding) => [
8
- binding,
9
- {
10
- writeDataPoint() {
11
- // no op in dev
12
- },
13
- },
14
- ])
15
- ) satisfies Record<string, AnalyticsEngineDataset>;
16
-
17
- const analyticsEngine: Middleware = async (
18
- request,
19
- env,
20
- _ctx,
21
- middlewareCtx
22
- ) => {
23
- // we're going to directly modify env so it maintains referential equality
24
- for (const binding of bindings) {
25
- env[binding] ??= bindingsEnv[binding];
26
- }
27
- return await middlewareCtx.next(request, env);
28
- };
29
-
30
- export default analyticsEngine;