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.
- package/Cloudflare_CA.pem +18 -0
- package/README.md +3 -1
- package/bin/wrangler.js +36 -4
- package/package.json +12 -7
- package/pages/functions/buildPlugin.ts +13 -0
- package/pages/functions/buildWorker.ts +14 -1
- package/pages/functions/template-plugin.ts +3 -2
- package/src/__tests__/configuration.test.ts +370 -87
- package/src/__tests__/dev.test.tsx +298 -77
- package/src/__tests__/helpers/mock-dialogs.ts +43 -2
- package/src/__tests__/index.test.ts +79 -72
- package/src/__tests__/init.test.ts +718 -123
- package/src/__tests__/jest.setup.ts +8 -0
- package/src/__tests__/kv.test.ts +173 -146
- package/src/__tests__/package-manager.test.ts +154 -7
- package/src/__tests__/pages.test.ts +478 -53
- package/src/__tests__/parse.test.ts +8 -0
- package/src/__tests__/publish.test.ts +1094 -215
- package/src/__tests__/r2.test.ts +55 -36
- package/src/__tests__/secret.test.ts +39 -4
- package/src/__tests__/whoami.test.tsx +34 -0
- package/src/abort.d.ts +3 -0
- package/src/bundle.ts +34 -6
- package/src/cfetch/index.ts +21 -4
- package/src/cfetch/internal.ts +23 -18
- package/src/config/config.ts +2 -2
- package/src/config/environment.ts +40 -14
- package/src/config/index.ts +162 -0
- package/src/config/validation-helpers.ts +10 -1
- package/src/config/validation.ts +180 -65
- package/src/create-worker-preview.ts +32 -22
- package/src/create-worker-upload-form.ts +22 -8
- package/src/dev/dev.tsx +12 -18
- package/src/dev/local.tsx +10 -0
- package/src/dev/remote.tsx +40 -16
- package/src/dialogs.tsx +48 -0
- package/src/durable.ts +102 -0
- package/src/entry.ts +64 -9
- package/src/index.tsx +548 -317
- package/src/inspect.ts +39 -0
- package/src/kv.ts +114 -25
- package/src/open-in-browser.ts +5 -12
- package/src/package-manager.ts +50 -3
- package/src/pages.tsx +434 -207
- package/src/parse.ts +23 -4
- package/src/proxy.ts +59 -35
- package/src/publish.ts +374 -127
- package/src/sites.tsx +61 -28
- package/src/user.tsx +23 -2
- package/src/whoami.tsx +3 -2
- package/src/worker.ts +10 -1
- package/src/zones.ts +73 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.ts +16 -1
- package/templates/static-asset-facade.js +0 -4
- package/wrangler-dist/cli.js +96965 -83414
- package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
- package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
- package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
- package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
- package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
- package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
- package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
- package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
- package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
- package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
- package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
- package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
- package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
- package/vendor/wrangler-mime/CHANGELOG.md +0 -289
- package/vendor/wrangler-mime/LICENSE +0 -21
- package/vendor/wrangler-mime/Mime.js +0 -97
- package/vendor/wrangler-mime/README.md +0 -187
- package/vendor/wrangler-mime/cli.js +0 -46
- package/vendor/wrangler-mime/index.js +0 -4
- package/vendor/wrangler-mime/lite.js +0 -4
- package/vendor/wrangler-mime/package.json +0 -52
- package/vendor/wrangler-mime/types/other.js +0 -1
- 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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
//
|
|
199
|
+
// Remove the key from the set so we know what we've already uploaded
|
|
177
200
|
namespaceKeys.delete(assetKey);
|
|
178
|
-
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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:
|
|
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
|
+
};
|
package/templates/new-worker.ts
CHANGED
|
@@ -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(
|
|
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 = {
|