wrangler 0.0.0-e2f9bb2 → 0.0.0-e3278fa

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 (90) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +3 -1
  3. package/bin/wrangler.js +36 -4
  4. package/package.json +12 -7
  5. package/pages/functions/buildPlugin.ts +13 -0
  6. package/pages/functions/buildWorker.ts +14 -1
  7. package/pages/functions/template-plugin.ts +3 -2
  8. package/src/__tests__/configuration.test.ts +370 -87
  9. package/src/__tests__/dev.test.tsx +298 -77
  10. package/src/__tests__/helpers/mock-dialogs.ts +43 -2
  11. package/src/__tests__/index.test.ts +79 -72
  12. package/src/__tests__/init.test.ts +718 -123
  13. package/src/__tests__/jest.setup.ts +8 -0
  14. package/src/__tests__/kv.test.ts +173 -146
  15. package/src/__tests__/package-manager.test.ts +154 -7
  16. package/src/__tests__/pages.test.ts +478 -53
  17. package/src/__tests__/parse.test.ts +8 -0
  18. package/src/__tests__/publish.test.ts +1094 -215
  19. package/src/__tests__/r2.test.ts +55 -36
  20. package/src/__tests__/secret.test.ts +39 -4
  21. package/src/__tests__/whoami.test.tsx +34 -0
  22. package/src/abort.d.ts +3 -0
  23. package/src/bundle.ts +34 -6
  24. package/src/cfetch/index.ts +21 -4
  25. package/src/cfetch/internal.ts +23 -18
  26. package/src/config/config.ts +2 -2
  27. package/src/config/environment.ts +40 -14
  28. package/src/config/index.ts +162 -0
  29. package/src/config/validation-helpers.ts +10 -1
  30. package/src/config/validation.ts +180 -65
  31. package/src/create-worker-preview.ts +32 -22
  32. package/src/create-worker-upload-form.ts +22 -8
  33. package/src/dev/dev.tsx +12 -18
  34. package/src/dev/local.tsx +10 -0
  35. package/src/dev/remote.tsx +40 -16
  36. package/src/dialogs.tsx +48 -0
  37. package/src/durable.ts +102 -0
  38. package/src/entry.ts +64 -9
  39. package/src/index.tsx +548 -317
  40. package/src/inspect.ts +39 -0
  41. package/src/kv.ts +114 -25
  42. package/src/open-in-browser.ts +5 -12
  43. package/src/package-manager.ts +50 -3
  44. package/src/pages.tsx +434 -207
  45. package/src/parse.ts +23 -4
  46. package/src/proxy.ts +59 -35
  47. package/src/publish.ts +374 -127
  48. package/src/sites.tsx +61 -28
  49. package/src/user.tsx +23 -2
  50. package/src/whoami.tsx +3 -2
  51. package/src/worker.ts +10 -1
  52. package/src/zones.ts +73 -0
  53. package/templates/new-worker-scheduled.js +17 -0
  54. package/templates/new-worker-scheduled.ts +32 -0
  55. package/templates/new-worker.ts +16 -1
  56. package/templates/static-asset-facade.js +0 -4
  57. package/wrangler-dist/cli.js +96965 -83414
  58. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  59. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  60. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  61. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  62. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  63. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  64. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  65. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  66. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  67. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  68. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  69. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  70. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  71. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  72. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  73. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  74. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  75. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  76. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  77. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  78. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  79. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  80. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  81. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  82. package/vendor/wrangler-mime/LICENSE +0 -21
  83. package/vendor/wrangler-mime/Mime.js +0 -97
  84. package/vendor/wrangler-mime/README.md +0 -187
  85. package/vendor/wrangler-mime/cli.js +0 -46
  86. package/vendor/wrangler-mime/index.js +0 -4
  87. package/vendor/wrangler-mime/lite.js +0 -4
  88. package/vendor/wrangler-mime/package.json +0 -52
  89. package/vendor/wrangler-mime/types/other.js +0 -1
  90. package/vendor/wrangler-mime/types/standard.js +0 -1
package/src/sites.tsx CHANGED
@@ -1,13 +1,14 @@
1
+ import assert from "node:assert";
1
2
  import { readdir, readFile, stat } from "node:fs/promises";
2
3
  import * as path from "node:path";
3
4
  import ignore from "ignore";
4
5
  import xxhash from "xxhash-wasm";
5
6
  import {
6
- createNamespace,
7
- listNamespaceKeys,
8
- listNamespaces,
9
- putBulkKeyValue,
10
- deleteBulkKeyValue,
7
+ createKVNamespace,
8
+ listKVNamespaceKeys,
9
+ listKVNamespaces,
10
+ putKVBulkKeyValue,
11
+ deleteKVBulkKeyValue,
11
12
  } from "./kv";
12
13
  import { logger } from "./logger";
13
14
  import type { Config } from "./config";
@@ -75,14 +76,14 @@ async function createKVNamespaceIfNotAlreadyExisting(
75
76
  ) {
76
77
  // check if it already exists
77
78
  // TODO: this is super inefficient, should be made better
78
- const namespaces = await listNamespaces(accountId);
79
+ const namespaces = await listKVNamespaces(accountId);
79
80
  const found = namespaces.find((x) => x.title === title);
80
81
  if (found) {
81
82
  return { created: false, id: found.id };
82
83
  }
83
84
 
84
85
  // else we make the namespace
85
- const id = await createNamespace(accountId, title);
86
+ const id = await createKVNamespace(accountId, title);
86
87
  logger.log(`🌀 Created namespace for Workers Site "${title}"`);
87
88
 
88
89
  return {
@@ -103,7 +104,7 @@ async function createKVNamespaceIfNotAlreadyExisting(
103
104
  * asset in the KV namespace.
104
105
  */
105
106
  export async function syncAssets(
106
- accountId: string,
107
+ accountId: string | undefined,
107
108
  scriptName: string,
108
109
  siteAssets: AssetPaths | undefined,
109
110
  preview: boolean,
@@ -120,6 +121,7 @@ export async function syncAssets(
120
121
  logger.log("(Note: doing a dry run, not uploading or deleting anything.)");
121
122
  return { manifest: undefined, namespace: undefined };
122
123
  }
124
+ assert(accountId, "Missing accountId");
123
125
 
124
126
  const title = `__${scriptName}-workers_sites_assets${
125
127
  preview ? "_preview" : ""
@@ -131,11 +133,17 @@ export async function syncAssets(
131
133
  );
132
134
 
133
135
  // let's get all the keys in this namespace
134
- const namespaceKeysResponse = await listNamespaceKeys(accountId, namespace);
136
+ const namespaceKeysResponse = await listKVNamespaceKeys(accountId, namespace);
135
137
  const namespaceKeys = new Set(namespaceKeysResponse.map((x) => x.name));
136
138
 
137
139
  const manifest: Record<string, string> = {};
138
- const toUpload: KeyValue[] = [];
140
+
141
+ // A batch of uploads where each bucket has to be less than 100mb
142
+ const uploadBuckets: KeyValue[][] = [];
143
+ // The "live" bucket that we'll keep filling until it's just below 100mb
144
+ let uploadBucket: KeyValue[] = [];
145
+ // A size counter for the live bucket
146
+ let uploadBucketSize = 0;
139
147
 
140
148
  const include = createPatternMatcher(siteAssets.includePatterns, false);
141
149
  const exclude = createPatternMatcher(siteAssets.excludePatterns, true);
@@ -146,7 +154,7 @@ export async function syncAssets(
146
154
  siteAssets.assetDirectory
147
155
  );
148
156
  for await (const absAssetFile of getFilesInFolder(assetDirectory)) {
149
- const assetFile = path.relative(siteAssets.baseDirectory, absAssetFile);
157
+ const assetFile = path.relative(assetDirectory, absAssetFile);
150
158
  if (!include(assetFile)) {
151
159
  continue;
152
160
  }
@@ -154,17 +162,32 @@ export async function syncAssets(
154
162
  continue;
155
163
  }
156
164
 
157
- await validateAssetSize(absAssetFile, assetFile);
158
165
  logger.log(`Reading ${assetFile}...`);
159
166
  const content = await readFile(absAssetFile, "base64");
160
-
167
+ await validateAssetSize(absAssetFile, assetFile);
168
+ // while KV accepts files that are 25 MiB **before** b64 encoding
169
+ // the overall bucket size must be below 100 MiB **after** b64 encoding
170
+ const assetSize = Buffer.from(content).length;
161
171
  const assetKey = hashAsset(hasher, assetFile, content);
162
172
  validateAssetKey(assetKey);
163
173
 
164
174
  // now put each of the files into kv
165
175
  if (!namespaceKeys.has(assetKey)) {
166
176
  logger.log(`Uploading as ${assetKey}...`);
167
- toUpload.push({
177
+
178
+ // Check if adding this asset to the bucket would
179
+ // push it over the 100 MiB limit KV bulk API limit
180
+ if (uploadBucketSize + assetSize > 100 * 1024 * 1024) {
181
+ // If so, move the current bucket into the batch,
182
+ // and reset the counter/bucket
183
+ uploadBuckets.push(uploadBucket);
184
+ uploadBucketSize = 0;
185
+ uploadBucket = [];
186
+ }
187
+
188
+ // Update the bucket and the size counter
189
+ uploadBucketSize += assetSize;
190
+ uploadBucket.push({
168
191
  key: assetKey,
169
192
  value: content,
170
193
  base64: true,
@@ -173,27 +196,31 @@ export async function syncAssets(
173
196
  logger.log(`Skipping - already uploaded.`);
174
197
  }
175
198
 
176
- // remove the key from the set so we know what we've already uploaded
199
+ // Remove the key from the set so we know what we've already uploaded
177
200
  namespaceKeys.delete(assetKey);
178
- manifest[path.relative(siteAssets.assetDirectory, absAssetFile)] = assetKey;
201
+
202
+ // Prevent different manifest keys on windows
203
+ const manifestKey = urlSafe(path.relative(assetDirectory, absAssetFile));
204
+ manifest[manifestKey] = assetKey;
179
205
  }
180
206
 
207
+ // Add the last (potentially only) bucket to the batch
208
+ uploadBuckets.push(uploadBucket);
209
+
181
210
  // keys now contains all the files we're deleting
182
211
  for (const key of namespaceKeys) {
183
212
  logger.log(`Deleting ${key} from the asset store...`);
184
213
  }
185
214
 
186
- await Promise.all([
187
- // upload all the new assets
188
- putBulkKeyValue(accountId, namespace, toUpload, () => {}),
189
- // delete all the unused assets
190
- deleteBulkKeyValue(
191
- accountId,
192
- namespace,
193
- Array.from(namespaceKeys),
194
- () => {}
195
- ),
196
- ]);
215
+ // upload each bucket in parallel
216
+ const bucketsToPut = [];
217
+ for (const bucket of uploadBuckets) {
218
+ bucketsToPut.push(putKVBulkKeyValue(accountId, namespace, bucket));
219
+ }
220
+ await Promise.all(bucketsToPut);
221
+
222
+ // then delete all the assets that aren't used anymore
223
+ await deleteKVBulkKeyValue(accountId, namespace, Array.from(namespaceKeys));
197
224
 
198
225
  logger.log("↗️ Done syncing assets");
199
226
 
@@ -212,10 +239,16 @@ function createPatternMatcher(
212
239
  }
213
240
  }
214
241
 
242
+ /**
243
+ * validate that the passed-in file is below 25 MiB
244
+ * **PRIOR** to base64 encoding. 25 MiB is a KV limit
245
+ * @param absFilePath
246
+ * @param relativeFilePath
247
+ */
215
248
  async function validateAssetSize(
216
249
  absFilePath: string,
217
250
  relativeFilePath: string
218
- ) {
251
+ ): Promise<void> {
219
252
  const { size } = await stat(absFilePath);
220
253
  if (size > 25 * 1024 * 1024) {
221
254
  throw new Error(
package/src/user.tsx CHANGED
@@ -214,6 +214,7 @@ import path from "node:path";
214
214
  import url from "node:url";
215
215
  import { TextEncoder } from "node:util";
216
216
  import TOML from "@iarna/toml";
217
+ import { HostURL } from "@webcontainer/env";
217
218
  import { render, Text } from "ink";
218
219
  import SelectInput from "ink-select-input";
219
220
  import Table from "ink-table";
@@ -232,7 +233,7 @@ import type { Response } from "undici";
232
233
  /**
233
234
  * Try to read the API token from the environment.
234
235
  */
235
- const getCloudflareAPITokenFromEnv = getEnvironmentVariableFactory({
236
+ export const getCloudflareAPITokenFromEnv = getEnvironmentVariableFactory({
236
237
  variableName: "CLOUDFLARE_API_TOKEN",
237
238
  deprecatedName: "CF_API_TOKEN",
238
239
  });
@@ -339,9 +340,18 @@ export function validateScopeKeys(
339
340
  const CLIENT_ID = "54d11594-84e4-41aa-b438-e81b8fa78ee7";
340
341
  const AUTH_URL = "https://dash.cloudflare.com/oauth2/auth";
341
342
  const TOKEN_URL = "https://dash.cloudflare.com/oauth2/token";
342
- const CALLBACK_URL = "http://localhost:8976/oauth/callback";
343
343
  const REVOKE_URL = "https://dash.cloudflare.com/oauth2/revoke";
344
344
 
345
+ /**
346
+ * To allow OAuth callbacks in environments such as WebContainer we need to
347
+ * create a host URL which only resolves `localhost` to a WebContainer
348
+ * hostname if the process is running in a WebContainer. On local this will
349
+ * be a no-op and it leaves the URL unmodified.
350
+ *
351
+ * @see https://www.npmjs.com/package/@webcontainer/env
352
+ */
353
+ const CALLBACK_URL = HostURL.parse("http://localhost:8976/oauth/callback").href;
354
+
345
355
  let LocalState: State = getAuthTokens();
346
356
 
347
357
  /**
@@ -1191,3 +1201,14 @@ export async function requireAuth(config: {
1191
1201
 
1192
1202
  return accountId;
1193
1203
  }
1204
+
1205
+ /**
1206
+ * Throw an error if there is no API token available.
1207
+ */
1208
+ export function requireApiToken(): string {
1209
+ const authToken = getAPIToken();
1210
+ if (!authToken) {
1211
+ throw new Error("No API token found.");
1212
+ }
1213
+ return authToken;
1214
+ }
package/src/whoami.tsx CHANGED
@@ -3,7 +3,7 @@ import Table from "ink-table";
3
3
  import React from "react";
4
4
  import { fetchListResult, fetchResult } from "./cfetch";
5
5
  import { logger } from "./logger";
6
- import { getAPIToken } from "./user";
6
+ import { getAPIToken, getCloudflareAPITokenFromEnv } from "./user";
7
7
 
8
8
  export async function whoami() {
9
9
  logger.log("Getting User settings...");
@@ -48,10 +48,11 @@ export interface UserInfo {
48
48
 
49
49
  export async function getUserInfo(): Promise<UserInfo | undefined> {
50
50
  const apiToken = getAPIToken();
51
+ const apiTokenFromEnv = getCloudflareAPITokenFromEnv();
51
52
  return apiToken
52
53
  ? {
53
54
  apiToken,
54
- authType: "OAuth",
55
+ authType: apiTokenFromEnv ? "API" : "OAuth",
55
56
  email: await getEmail(),
56
57
  accounts: await getAccounts(),
57
58
  }
package/src/worker.ts CHANGED
@@ -105,6 +105,7 @@ interface CfDurableObject {
105
105
  name: string;
106
106
  class_name: string;
107
107
  script_name?: string;
108
+ environment?: string;
108
109
  }
109
110
 
110
111
  interface CfR2Bucket {
@@ -112,6 +113,12 @@ interface CfR2Bucket {
112
113
  bucket_name: string;
113
114
  }
114
115
 
116
+ interface CfService {
117
+ binding: string;
118
+ service: string;
119
+ environment?: string;
120
+ }
121
+
115
122
  interface CfUnsafeBinding {
116
123
  name: string;
117
124
  type: string;
@@ -157,6 +164,7 @@ export interface CfWorkerInit {
157
164
  data_blobs: CfDataBlobBindings | undefined;
158
165
  durable_objects: { bindings: CfDurableObject[] } | undefined;
159
166
  r2_buckets: CfR2Bucket[] | undefined;
167
+ services: CfService[] | undefined;
160
168
  unsafe: CfUnsafeBinding[] | undefined;
161
169
  };
162
170
  migrations: CfDurableObjectMigrations | undefined;
@@ -168,5 +176,6 @@ export interface CfWorkerInit {
168
176
  export interface CfWorkerContext {
169
177
  env: string | undefined;
170
178
  legacyEnv: boolean | undefined;
171
- zone: { id: string; host: string } | undefined;
179
+ zone: string | undefined;
180
+ host: string | undefined;
172
181
  }
package/src/zones.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { fetchListResult } from "./cfetch";
2
+ import type { Route } from "./config/environment";
3
+
4
+ /**
5
+ * An object holding information about a zone for publishing.
6
+ */
7
+ export interface Zone {
8
+ id: string;
9
+ host: string;
10
+ }
11
+
12
+ /**
13
+ * Try to compute the a zone ID and host name for one or more routes.
14
+ *
15
+ * When we're given a route, we do 2 things:
16
+ * - We try to extract a host from it
17
+ * - We try to get a zone id from the host
18
+ */
19
+ export async function getZoneForRoute(route: Route): Promise<Zone | undefined> {
20
+ const host =
21
+ typeof route === "string"
22
+ ? getHostFromUrl(route)
23
+ : typeof route === "object"
24
+ ? "zone_name" in route
25
+ ? getHostFromUrl(route.zone_name)
26
+ : getHostFromUrl(route.pattern)
27
+ : undefined;
28
+ const id =
29
+ typeof route === "object" && "zone_id" in route
30
+ ? route.zone_id
31
+ : host
32
+ ? await getZoneIdFromHost(host)
33
+ : undefined;
34
+ return id && host ? { id, host } : undefined;
35
+ }
36
+
37
+ /**
38
+ * Given something that resembles a URL, try to extract a host from it.
39
+ */
40
+ function getHostFromUrl(urlLike: string): string | undefined {
41
+ // strip leading * / *.
42
+ urlLike = urlLike.replace(/^\*(\.)?/g, "");
43
+
44
+ if (!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))) {
45
+ urlLike = "http://" + urlLike;
46
+ }
47
+ return new URL(urlLike).host;
48
+ }
49
+
50
+ /**
51
+ * Given something that resembles a host, try to infer a zone id from it.
52
+ *
53
+ * It's hard to get a 'valid' domain from a string, so we don't even try to validate TLDs, etc.
54
+ * For each domain-like part of the host (e.g. w.x.y.z) try to get a zone id for it by
55
+ * lopping off subdomains until we get a hit from the API.
56
+ */
57
+ export async function getZoneIdFromHost(host: string): Promise<string> {
58
+ const hostPieces = host.split(".");
59
+
60
+ while (hostPieces.length > 1) {
61
+ const zones = await fetchListResult<{ id: string }>(
62
+ `/zones`,
63
+ {},
64
+ new URLSearchParams({ name: hostPieces.join(".") })
65
+ );
66
+ if (zones.length > 0) {
67
+ return zones[0].id;
68
+ }
69
+ hostPieces.shift();
70
+ }
71
+
72
+ throw new Error(`Could not find zone for ${host}`);
73
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Welcome to Cloudflare Workers! This is your first scheduled worker.
3
+ *
4
+ * - Run `wrangler dev --local` in your terminal to start a development server
5
+ * - Run `curl "http://localhost:8787/cdn-cgi/mf/scheduled"` to trigger the scheduled event
6
+ * - Go back to the console to see what your worker has logged
7
+ * - Update the Cron trigger in wrangler.toml (see https://developers.cloudflare.com/workers/wrangler/configuration/#triggers)
8
+ * - Run `wrangler publish --name my-worker` to publish your worker
9
+ *
10
+ * Learn more at https://developers.cloudflare.com/workers/runtime-apis/scheduled-event/
11
+ */
12
+
13
+ export default {
14
+ async scheduled(controller, env, ctx) {
15
+ console.log(`Hello World!`);
16
+ },
17
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Welcome to Cloudflare Workers! This is your first scheduled worker.
3
+ *
4
+ * - Run `wrangler dev --local` in your terminal to start a development server
5
+ * - Run `curl "http://localhost:8787/cdn-cgi/mf/scheduled"` to trigger the scheduled event
6
+ * - Go back to the console to see what your worker has logged
7
+ * - Update the Cron trigger in wrangler.toml (see https://developers.cloudflare.com/workers/wrangler/configuration/#triggers)
8
+ * - Run `wrangler publish --name my-worker` to publish your worker
9
+ *
10
+ * Learn more at https://developers.cloudflare.com/workers/runtime-apis/scheduled-event/
11
+ */
12
+
13
+ export interface Env {
14
+ // Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
15
+ // MY_KV_NAMESPACE: KVNamespace;
16
+ //
17
+ // Example binding to Durable Object. Learn more at https://developers.cloudflare.com/workers/runtime-apis/durable-objects/
18
+ // MY_DURABLE_OBJECT: DurableObjectNamespace;
19
+ //
20
+ // Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
21
+ // MY_BUCKET: R2Bucket;
22
+ }
23
+
24
+ export default {
25
+ async scheduled(
26
+ controller: ScheduledController,
27
+ env: Env,
28
+ ctx: ExecutionContext
29
+ ): Promise<void> {
30
+ console.log(`Hello World!`);
31
+ },
32
+ };
@@ -8,8 +8,23 @@
8
8
  * Learn more at https://developers.cloudflare.com/workers/
9
9
  */
10
10
 
11
+ export interface Env {
12
+ // Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
13
+ // MY_KV_NAMESPACE: KVNamespace;
14
+ //
15
+ // Example binding to Durable Object. Learn more at https://developers.cloudflare.com/workers/runtime-apis/durable-objects/
16
+ // MY_DURABLE_OBJECT: DurableObjectNamespace;
17
+ //
18
+ // Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
19
+ // MY_BUCKET: R2Bucket;
20
+ }
21
+
11
22
  export default {
12
- async fetch(request: Request): Promise<Response> {
23
+ async fetch(
24
+ request: Request,
25
+ env: Env,
26
+ ctx: ExecutionContext
27
+ ): Promise<Response> {
13
28
  return new Response("Hello World!");
14
29
  },
15
30
  };
@@ -4,10 +4,6 @@ import { getAssetFromKV } from "@cloudflare/kv-asset-handler";
4
4
  import manifest from "__STATIC_CONTENT_MANIFEST";
5
5
  const ASSET_MANIFEST = JSON.parse(manifest);
6
6
 
7
- // TODO: remove this
8
- globalThis.__STATIC_CONTENT = undefined;
9
- globalThis.__STATIC_CONTENT_MANIFEST = undefined;
10
-
11
7
  export default {
12
8
  async fetch(request, env, ctx) {
13
9
  let options = {