wrangler 2.0.23 → 2.0.24
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/README.md +20 -2
- package/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +96 -34
- package/package.json +9 -4
- package/src/__tests__/configuration.test.ts +88 -16
- package/src/__tests__/dev.test.tsx +3 -0
- package/src/__tests__/generate.test.ts +93 -0
- package/src/__tests__/helpers/mock-cfetch.ts +54 -2
- package/src/__tests__/index.test.ts +10 -27
- package/src/__tests__/jest.setup.ts +31 -1
- package/src/__tests__/kv.test.ts +2 -2
- package/src/__tests__/metrics.test.ts +5 -0
- package/src/__tests__/publish.test.ts +497 -254
- package/src/__tests__/r2.test.ts +155 -71
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/validate-dev-props.test.ts +56 -0
- package/src/__tests__/whoami.test.tsx +60 -1
- package/src/bundle.ts +278 -44
- package/src/cfetch/internal.ts +34 -2
- package/src/config/config.ts +7 -2
- package/src/config/environment.ts +40 -8
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +101 -7
- package/src/create-worker-upload-form.ts +25 -0
- package/src/dev/dev.tsx +107 -28
- package/src/dev/local.tsx +20 -10
- package/src/dev/remote.tsx +39 -8
- package/src/dev/use-esbuild.ts +25 -0
- package/src/dev/validate-dev-props.ts +31 -0
- package/src/dev-registry.tsx +157 -0
- package/src/dev.tsx +93 -75
- package/src/generate.ts +112 -14
- package/src/index.tsx +182 -4
- package/src/inspect.ts +93 -5
- package/src/metrics/index.ts +1 -0
- package/src/metrics/metrics-dispatcher.ts +1 -0
- package/src/metrics/metrics-usage-headers.ts +24 -0
- package/src/metrics/send-event.ts +2 -2
- package/src/module-collection.ts +3 -3
- package/src/pages/constants.ts +1 -0
- package/src/pages/deployments.tsx +1 -1
- package/src/pages/dev.tsx +6 -1
- package/src/pages/publish.tsx +1 -1
- package/src/pages/upload.tsx +32 -13
- package/src/publish.ts +126 -112
- package/src/r2.ts +68 -0
- package/src/user/user.tsx +20 -2
- package/src/whoami.tsx +79 -1
- package/src/worker.ts +12 -0
- package/templates/first-party-worker-module-facade.ts +18 -0
- package/templates/format-dev-errors.ts +32 -0
- package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
- package/templates/service-bindings-module-facade.js +51 -0
- package/templates/service-bindings-sw-facade.js +39 -0
- package/wrangler-dist/cli.js +40192 -15265
package/src/bundle.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import { builtinModules } from "node:module";
|
|
4
|
-
import * as os from "node:os";
|
|
5
4
|
import * as path from "node:path";
|
|
6
5
|
import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
|
|
7
6
|
import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
|
|
8
7
|
import * as esbuild from "esbuild";
|
|
8
|
+
import tmp from "tmp-promise";
|
|
9
9
|
import createModuleCollector from "./module-collection";
|
|
10
10
|
import type { Config } from "./config";
|
|
11
|
+
import type { WorkerRegistry } from "./dev-registry";
|
|
11
12
|
import type { Entry } from "./entry";
|
|
12
13
|
import type { CfModule } from "./worker";
|
|
13
14
|
|
|
@@ -16,8 +17,15 @@ type BundleResult = {
|
|
|
16
17
|
resolvedEntryPointPath: string;
|
|
17
18
|
bundleType: "esm" | "commonjs";
|
|
18
19
|
stop: (() => void) | undefined;
|
|
20
|
+
sourceMapPath?: string | undefined;
|
|
19
21
|
};
|
|
20
22
|
|
|
23
|
+
type StaticAssetsConfig =
|
|
24
|
+
| (Config["assets"] & {
|
|
25
|
+
bypassCache: boolean | undefined;
|
|
26
|
+
})
|
|
27
|
+
| undefined;
|
|
28
|
+
|
|
21
29
|
/**
|
|
22
30
|
* Searches for any uses of node's builtin modules, and throws an error if it
|
|
23
31
|
* finds anything. This plugin is only used when nodeCompat is not enabled.
|
|
@@ -53,6 +61,7 @@ export async function bundleWorker(
|
|
|
53
61
|
destination: string,
|
|
54
62
|
options: {
|
|
55
63
|
serveAssetsFromWorker: boolean;
|
|
64
|
+
assets: StaticAssetsConfig;
|
|
56
65
|
jsxFactory: string | undefined;
|
|
57
66
|
jsxFragment: string | undefined;
|
|
58
67
|
rules: Config["rules"];
|
|
@@ -62,6 +71,9 @@ export async function bundleWorker(
|
|
|
62
71
|
nodeCompat: boolean | undefined;
|
|
63
72
|
define: Config["define"];
|
|
64
73
|
checkFetch: boolean;
|
|
74
|
+
services: Config["services"];
|
|
75
|
+
workerDefinitions: WorkerRegistry | undefined;
|
|
76
|
+
firstPartyWorkerDevFacade: boolean | undefined;
|
|
65
77
|
}
|
|
66
78
|
): Promise<BundleResult> {
|
|
67
79
|
const {
|
|
@@ -74,7 +86,17 @@ export async function bundleWorker(
|
|
|
74
86
|
minify,
|
|
75
87
|
nodeCompat,
|
|
76
88
|
checkFetch,
|
|
89
|
+
assets,
|
|
90
|
+
workerDefinitions,
|
|
91
|
+
services,
|
|
92
|
+
firstPartyWorkerDevFacade,
|
|
77
93
|
} = options;
|
|
94
|
+
|
|
95
|
+
// We create a temporary directory for any oneoff files we
|
|
96
|
+
// need to create. This is separate from the main build
|
|
97
|
+
// directory (`destination`).
|
|
98
|
+
const tmpDir = await tmp.dir({ unsafeCleanup: true });
|
|
99
|
+
|
|
78
100
|
const entryDirectory = path.dirname(entry.file);
|
|
79
101
|
const moduleCollector = createModuleCollector({
|
|
80
102
|
wrangler1xlegacyModuleReferences: {
|
|
@@ -98,15 +120,11 @@ export async function bundleWorker(
|
|
|
98
120
|
// `checked-fetch.js` to do so. However, with yarn 3 style pnp,
|
|
99
121
|
// we need to extract that file to an accessible place before injecting
|
|
100
122
|
// it in, hence this code here.
|
|
101
|
-
|
|
102
|
-
const checkedFetchFileToInject = path.join(
|
|
103
|
-
osTempDir,
|
|
104
|
-
"--temp-wrangler-files--",
|
|
105
|
-
"checked-fetch.js"
|
|
106
|
-
);
|
|
123
|
+
|
|
124
|
+
const checkedFetchFileToInject = path.join(tmpDir.path, "checked-fetch.js");
|
|
107
125
|
|
|
108
126
|
if (checkFetch && !fs.existsSync(checkedFetchFileToInject)) {
|
|
109
|
-
fs.mkdirSync(path
|
|
127
|
+
fs.mkdirSync(tmpDir.path, {
|
|
110
128
|
recursive: true,
|
|
111
129
|
});
|
|
112
130
|
fs.writeFileSync(
|
|
@@ -114,12 +132,58 @@ export async function bundleWorker(
|
|
|
114
132
|
fs.readFileSync(path.resolve(__dirname, "../templates/checked-fetch.js"))
|
|
115
133
|
);
|
|
116
134
|
}
|
|
117
|
-
|
|
118
|
-
//
|
|
119
|
-
//
|
|
135
|
+
|
|
136
|
+
// At this point, we take the opportunity to "wrap" any input workers
|
|
137
|
+
// with any extra functionality we may want to add. This is done by
|
|
138
|
+
// passing the entry point through a pipeline of functions that return
|
|
139
|
+
// a new entry point, that we call "middleware" or "facades".
|
|
140
|
+
// Look at implementations of these functions to learn more.
|
|
141
|
+
|
|
142
|
+
type MiddlewareFn = (arg0: Entry) => Promise<Entry>;
|
|
143
|
+
const middleware: (false | undefined | MiddlewareFn)[] = [
|
|
144
|
+
// serve static assets
|
|
145
|
+
serveAssetsFromWorker &&
|
|
146
|
+
((currentEntry: Entry) => {
|
|
147
|
+
return applyStaticAssetFacade(currentEntry, tmpDir.path, assets);
|
|
148
|
+
}),
|
|
149
|
+
// format errors nicely
|
|
150
|
+
// We use an env var here because we don't actually
|
|
151
|
+
// want to expose this to the user. It's only used internally to
|
|
152
|
+
// experiment with middleware as a teaching exercise.
|
|
153
|
+
process.env.FORMAT_WRANGLER_ERRORS === "true" &&
|
|
154
|
+
((currentEntry: Entry) => {
|
|
155
|
+
return applyFormatDevErrorsFacade(currentEntry, tmpDir.path);
|
|
156
|
+
}),
|
|
157
|
+
// bind to other dev instances/service bindings
|
|
158
|
+
workerDefinitions &&
|
|
159
|
+
Object.keys(workerDefinitions).length > 0 &&
|
|
160
|
+
services &&
|
|
161
|
+
services.length > 0 &&
|
|
162
|
+
((currentEntry: Entry) => {
|
|
163
|
+
return applyMultiWorkerDevFacade(
|
|
164
|
+
currentEntry,
|
|
165
|
+
tmpDir.path,
|
|
166
|
+
services,
|
|
167
|
+
workerDefinitions
|
|
168
|
+
);
|
|
169
|
+
}),
|
|
170
|
+
// Simulate internal environment when using first party workers in dev
|
|
171
|
+
firstPartyWorkerDevFacade === true &&
|
|
172
|
+
((currentEntry: Entry) => {
|
|
173
|
+
return applyFirstPartyWorkerDevFacade(currentEntry, tmpDir.path);
|
|
174
|
+
}),
|
|
175
|
+
].filter(Boolean);
|
|
176
|
+
|
|
177
|
+
let inputEntry = entry;
|
|
178
|
+
|
|
179
|
+
for (const middlewareFn of middleware as MiddlewareFn[]) {
|
|
180
|
+
inputEntry = await middlewareFn(inputEntry);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// At this point, inputEntry points to the entry point we want to build.
|
|
120
184
|
|
|
121
185
|
const result = await esbuild.build({
|
|
122
|
-
|
|
186
|
+
entryPoints: [inputEntry.file],
|
|
123
187
|
bundle: true,
|
|
124
188
|
absWorkingDir: entry.directory,
|
|
125
189
|
outdir: destination,
|
|
@@ -128,6 +192,8 @@ export async function bundleWorker(
|
|
|
128
192
|
format: entry.format === "modules" ? "esm" : "iife",
|
|
129
193
|
target: "es2020",
|
|
130
194
|
sourcemap: true,
|
|
195
|
+
// The root included, as the sources are relative paths to tmpDir
|
|
196
|
+
sourceRoot: entryDirectory,
|
|
131
197
|
minify,
|
|
132
198
|
metafile: true,
|
|
133
199
|
conditions: ["worker", "browser"],
|
|
@@ -177,6 +243,10 @@ export async function bundleWorker(
|
|
|
177
243
|
const entryPointExports = entryPointOutputs[0][1].exports;
|
|
178
244
|
const bundleType = entryPointExports.length > 0 ? "esm" : "commonjs";
|
|
179
245
|
|
|
246
|
+
const sourceMapPath = Object.keys(result.metafile.outputs).filter((_path) =>
|
|
247
|
+
_path.includes(".map")
|
|
248
|
+
)[0];
|
|
249
|
+
|
|
180
250
|
return {
|
|
181
251
|
modules: moduleCollector.modules,
|
|
182
252
|
resolvedEntryPointPath: path.resolve(
|
|
@@ -185,45 +255,209 @@ export async function bundleWorker(
|
|
|
185
255
|
),
|
|
186
256
|
bundleType,
|
|
187
257
|
stop: result.stop,
|
|
258
|
+
sourceMapPath,
|
|
188
259
|
};
|
|
189
260
|
}
|
|
190
261
|
|
|
191
|
-
|
|
262
|
+
/**
|
|
263
|
+
* A simple plugin to alias modules and mark them as external
|
|
264
|
+
*/
|
|
265
|
+
function esbuildAliasExternalPlugin(
|
|
266
|
+
aliases: Record<string, string>
|
|
267
|
+
): esbuild.Plugin {
|
|
268
|
+
return {
|
|
269
|
+
name: "alias",
|
|
270
|
+
setup(build) {
|
|
271
|
+
build.onResolve({ filter: /.*/g }, (args) => {
|
|
272
|
+
// If it's the entrypoint, let it be as is
|
|
273
|
+
if (args.kind === "entry-point") {
|
|
274
|
+
return {
|
|
275
|
+
path: args.path,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
// If it's not a recognised alias, then throw an error
|
|
279
|
+
if (!Object.keys(aliases).includes(args.path)) {
|
|
280
|
+
throw new Error("unrecognized module: " + args.path);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Otherwise, return the alias
|
|
284
|
+
return {
|
|
285
|
+
path: aliases[args.path as keyof typeof aliases],
|
|
286
|
+
external: true,
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
}
|
|
192
292
|
|
|
193
293
|
/**
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* actually a shim worker that will either return an asset from a KV store,
|
|
198
|
-
* or delegate to the actual worker.
|
|
294
|
+
* A middleware that catches any thrown errors, and instead formats
|
|
295
|
+
* them to be rendered in a browser. This middleware is for demonstration
|
|
296
|
+
* purposes only, and is not intended to be used in production (or even dev!)
|
|
199
297
|
*/
|
|
200
|
-
function
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
):
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
298
|
+
async function applyFormatDevErrorsFacade(
|
|
299
|
+
entry: Entry,
|
|
300
|
+
tmpDirPath: string
|
|
301
|
+
): Promise<Entry> {
|
|
302
|
+
const targetPath = path.join(tmpDirPath, "format-dev-errors.entry.js");
|
|
303
|
+
await esbuild.build({
|
|
304
|
+
entryPoints: [path.resolve(__dirname, "../templates/format-dev-errors.ts")],
|
|
305
|
+
bundle: true,
|
|
306
|
+
sourcemap: true,
|
|
307
|
+
format: "esm",
|
|
308
|
+
plugins: [
|
|
309
|
+
esbuildAliasExternalPlugin({
|
|
310
|
+
__ENTRY_POINT__: entry.file,
|
|
311
|
+
}),
|
|
312
|
+
],
|
|
313
|
+
outfile: targetPath,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
...entry,
|
|
318
|
+
file: targetPath,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* A middleware that serves static assets from a worker.
|
|
324
|
+
* This powers --assets / config.assets
|
|
325
|
+
*/
|
|
326
|
+
|
|
327
|
+
async function applyStaticAssetFacade(
|
|
328
|
+
entry: Entry,
|
|
329
|
+
tmpDirPath: string,
|
|
330
|
+
assets: StaticAssetsConfig
|
|
331
|
+
): Promise<Entry> {
|
|
332
|
+
const targetPath = path.join(tmpDirPath, "serve-static-assets.entry.js");
|
|
333
|
+
|
|
334
|
+
await esbuild.build({
|
|
335
|
+
entryPoints: [
|
|
336
|
+
path.resolve(__dirname, "../templates/serve-static-assets.ts"),
|
|
337
|
+
],
|
|
338
|
+
bundle: true,
|
|
339
|
+
format: "esm",
|
|
340
|
+
sourcemap: true,
|
|
341
|
+
plugins: [
|
|
342
|
+
esbuildAliasExternalPlugin({
|
|
343
|
+
__ENTRY_POINT__: entry.file,
|
|
344
|
+
__KV_ASSET_HANDLER__: path.join(__dirname, "../kv-asset-handler.js"),
|
|
345
|
+
__STATIC_CONTENT_MANIFEST: "__STATIC_CONTENT_MANIFEST",
|
|
346
|
+
}),
|
|
347
|
+
],
|
|
348
|
+
define: {
|
|
349
|
+
__CACHE_CONTROL_OPTIONS__: JSON.stringify(
|
|
350
|
+
typeof assets === "object"
|
|
351
|
+
? {
|
|
352
|
+
browserTTL:
|
|
353
|
+
assets.browser_TTL || 172800 /* 2 days: 2* 60 * 60 * 24 */,
|
|
354
|
+
bypassCache: assets.bypassCache,
|
|
355
|
+
}
|
|
356
|
+
: {}
|
|
357
|
+
),
|
|
358
|
+
__SERVE_SINGLE_PAGE_APP__: JSON.stringify(
|
|
359
|
+
typeof assets === "object" ? assets.serve_single_page_app : false
|
|
360
|
+
),
|
|
361
|
+
},
|
|
362
|
+
outfile: targetPath,
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
...entry,
|
|
367
|
+
file: targetPath,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* A middleware that enables service bindings to be used in dev,
|
|
373
|
+
* binding to other love wrangler dev instances
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
async function applyMultiWorkerDevFacade(
|
|
377
|
+
entry: Entry,
|
|
378
|
+
tmpDirPath: string,
|
|
379
|
+
services: Config["services"],
|
|
380
|
+
workerDefinitions: WorkerRegistry
|
|
381
|
+
) {
|
|
382
|
+
const targetPath = path.join(tmpDirPath, "serve-static-assets.entry.js");
|
|
383
|
+
const serviceMap = Object.fromEntries(
|
|
384
|
+
(services || []).map((serviceBinding) => [
|
|
385
|
+
serviceBinding.binding,
|
|
386
|
+
workerDefinitions[serviceBinding.service] || null,
|
|
387
|
+
])
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
await esbuild.build({
|
|
391
|
+
entryPoints: [
|
|
392
|
+
path.join(
|
|
393
|
+
__dirname,
|
|
394
|
+
entry.format === "modules"
|
|
395
|
+
? "../templates/service-bindings-module-facade.js"
|
|
396
|
+
: "../templates/service-bindings-sw-facade.js"
|
|
397
|
+
),
|
|
398
|
+
],
|
|
399
|
+
bundle: true,
|
|
400
|
+
sourcemap: true,
|
|
401
|
+
format: "esm",
|
|
402
|
+
plugins: [
|
|
403
|
+
esbuildAliasExternalPlugin({
|
|
404
|
+
__ENTRY_POINT__: entry.file,
|
|
405
|
+
}),
|
|
406
|
+
],
|
|
407
|
+
define: {
|
|
408
|
+
__WORKERS__: JSON.stringify(serviceMap),
|
|
409
|
+
},
|
|
410
|
+
outfile: targetPath,
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
return {
|
|
414
|
+
...entry,
|
|
415
|
+
file: targetPath,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* A middleware that makes first party workers "work" in
|
|
421
|
+
* our dev environments. Is applied during wrangler dev
|
|
422
|
+
* when config.first_party_worker is true
|
|
423
|
+
*/
|
|
424
|
+
async function applyFirstPartyWorkerDevFacade(
|
|
425
|
+
entry: Entry,
|
|
426
|
+
tmpDirPath: string
|
|
427
|
+
) {
|
|
428
|
+
if (entry.format !== "modules") {
|
|
429
|
+
throw new Error(
|
|
430
|
+
"First party workers must be in the modules format. See https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/"
|
|
431
|
+
);
|
|
226
432
|
}
|
|
433
|
+
|
|
434
|
+
const targetPath = path.join(
|
|
435
|
+
tmpDirPath,
|
|
436
|
+
"first-party-worker-module-facade.entry.js"
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
await esbuild.build({
|
|
440
|
+
entryPoints: [
|
|
441
|
+
path.resolve(
|
|
442
|
+
__dirname,
|
|
443
|
+
"../templates/first-party-worker-module-facade.ts"
|
|
444
|
+
),
|
|
445
|
+
],
|
|
446
|
+
bundle: true,
|
|
447
|
+
format: "esm",
|
|
448
|
+
sourcemap: true,
|
|
449
|
+
plugins: [
|
|
450
|
+
esbuildAliasExternalPlugin({
|
|
451
|
+
__ENTRY_POINT__: entry.file,
|
|
452
|
+
}),
|
|
453
|
+
],
|
|
454
|
+
outfile: targetPath,
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
return {
|
|
458
|
+
...entry,
|
|
459
|
+
file: targetPath,
|
|
460
|
+
};
|
|
227
461
|
}
|
|
228
462
|
|
|
229
463
|
/**
|
package/src/cfetch/internal.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { ParseError, parseJSON } from "../parse";
|
|
|
6
6
|
import { loginOrRefreshIfRequired, requireApiToken } from "../user";
|
|
7
7
|
import type { ApiCredentials } from "../user";
|
|
8
8
|
import type { URLSearchParams } from "node:url";
|
|
9
|
-
import type { RequestInit, HeadersInit } from "undici";
|
|
9
|
+
import type { RequestInit, HeadersInit, Response } from "undici";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Get the URL to use to access the Cloudflare API.
|
|
@@ -124,7 +124,6 @@ function addUserAgent(headers: Record<string, string>): void {
|
|
|
124
124
|
* Note: any calls to fetchKVGetValue must call encodeURIComponent on key
|
|
125
125
|
* before passing it
|
|
126
126
|
*/
|
|
127
|
-
|
|
128
127
|
export async function fetchKVGetValue(
|
|
129
128
|
accountId: string,
|
|
130
129
|
namespaceId: string,
|
|
@@ -147,3 +146,36 @@ export async function fetchKVGetValue(
|
|
|
147
146
|
);
|
|
148
147
|
}
|
|
149
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The implementation for fetching a R2 object from Cloudflare API.
|
|
152
|
+
* We have a special implementation to handle the non-standard API response
|
|
153
|
+
* that doesn't return JSON, likely due to the streaming nature.
|
|
154
|
+
*
|
|
155
|
+
* note: The implementation should be called from light wrappers for
|
|
156
|
+
* different methods (GET, PUT)
|
|
157
|
+
*/
|
|
158
|
+
type ResponseWithBody = Response & { body: NonNullable<Response["body"]> };
|
|
159
|
+
export async function fetchR2Objects(
|
|
160
|
+
resource: string,
|
|
161
|
+
bodyInit: RequestInit = {}
|
|
162
|
+
): Promise<ResponseWithBody> {
|
|
163
|
+
await requireLoggedIn();
|
|
164
|
+
const auth = requireApiToken();
|
|
165
|
+
const headers = cloneHeaders(bodyInit.headers);
|
|
166
|
+
addAuthorizationHeaderIfUnspecified(headers, auth);
|
|
167
|
+
addUserAgent(headers);
|
|
168
|
+
|
|
169
|
+
const response = await fetch(`${getCloudflareAPIBaseURL()}${resource}`, {
|
|
170
|
+
...bodyInit,
|
|
171
|
+
headers,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (response.ok && response.body) {
|
|
175
|
+
return response as ResponseWithBody;
|
|
176
|
+
} else {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Failed to fetch ${resource} - ${response.status}: ${response.statusText});`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
package/src/config/config.ts
CHANGED
|
@@ -127,8 +127,13 @@ export interface ConfigFields<Dev extends RawDevConfig> {
|
|
|
127
127
|
* This can either be a string, or an object with additional config fields.
|
|
128
128
|
*/
|
|
129
129
|
assets:
|
|
130
|
-
|
|
|
131
|
-
|
|
130
|
+
| {
|
|
131
|
+
bucket: string;
|
|
132
|
+
include: string[];
|
|
133
|
+
exclude: string[];
|
|
134
|
+
browser_TTL: number | undefined;
|
|
135
|
+
serve_single_page_app: boolean;
|
|
136
|
+
}
|
|
132
137
|
| undefined;
|
|
133
138
|
|
|
134
139
|
/**
|
|
@@ -217,6 +217,11 @@ interface EnvironmentInheritable {
|
|
|
217
217
|
namespace: string;
|
|
218
218
|
}[];
|
|
219
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Designates this worker as an internal-only "first-party" worker.
|
|
222
|
+
*/
|
|
223
|
+
first_party_worker: boolean | undefined;
|
|
224
|
+
|
|
220
225
|
/**
|
|
221
226
|
* TODO: remove this as it has been deprecated.
|
|
222
227
|
*
|
|
@@ -224,6 +229,24 @@ interface EnvironmentInheritable {
|
|
|
224
229
|
* So we need to include it in this type so it is available.
|
|
225
230
|
*/
|
|
226
231
|
zone_id?: string;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Specify a compiled capnp schema to use
|
|
235
|
+
* Then add a binding per field in the top level message that you will send to logfwdr
|
|
236
|
+
*
|
|
237
|
+
* @default `{schema:undefined,bindings:[]}`
|
|
238
|
+
* @inheritable
|
|
239
|
+
*/
|
|
240
|
+
logfwdr: {
|
|
241
|
+
/** capnp schema filename */
|
|
242
|
+
schema: string | undefined;
|
|
243
|
+
bindings: {
|
|
244
|
+
/** The binding name used to refer to logfwdr */
|
|
245
|
+
name: string;
|
|
246
|
+
/** The destination for this logged message */
|
|
247
|
+
destination: string;
|
|
248
|
+
}[];
|
|
249
|
+
};
|
|
227
250
|
}
|
|
228
251
|
|
|
229
252
|
/**
|
|
@@ -329,14 +352,16 @@ interface EnvironmentNonInheritable {
|
|
|
329
352
|
* @default `[]`
|
|
330
353
|
* @nonInheritable
|
|
331
354
|
*/
|
|
332
|
-
services:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
355
|
+
services:
|
|
356
|
+
| {
|
|
357
|
+
/** The binding name used to refer to the bound service. */
|
|
358
|
+
binding: string;
|
|
359
|
+
/** The name of the service. */
|
|
360
|
+
service: string;
|
|
361
|
+
/** The environment of the service (e.g. production, staging, etc). */
|
|
362
|
+
environment?: string;
|
|
363
|
+
}[]
|
|
364
|
+
| undefined;
|
|
340
365
|
|
|
341
366
|
/**
|
|
342
367
|
* "Unsafe" tables for features that aren't directly supported by wrangler.
|
|
@@ -375,6 +400,13 @@ interface EnvironmentDeprecated {
|
|
|
375
400
|
*/
|
|
376
401
|
zone_id?: string;
|
|
377
402
|
|
|
403
|
+
/**
|
|
404
|
+
* Legacy way of defining KVNamespaces that is no longer supported.
|
|
405
|
+
*
|
|
406
|
+
* @deprecated DO NOT USE. This was a legacy bug from wrangler 1, that we do not want to support.
|
|
407
|
+
*/
|
|
408
|
+
"kv-namespaces"?: string;
|
|
409
|
+
|
|
378
410
|
/**
|
|
379
411
|
* A list of services that your worker should be bound to.
|
|
380
412
|
*
|
package/src/config/index.ts
CHANGED
|
@@ -85,6 +85,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
85
85
|
durable_objects,
|
|
86
86
|
kv_namespaces,
|
|
87
87
|
r2_buckets,
|
|
88
|
+
logfwdr,
|
|
88
89
|
services,
|
|
89
90
|
text_blobs,
|
|
90
91
|
unsafe,
|
|
@@ -149,6 +150,18 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
149
150
|
});
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
if (logfwdr !== undefined && logfwdr.bindings.length > 0) {
|
|
154
|
+
output.push({
|
|
155
|
+
type: "logfwdr",
|
|
156
|
+
entries: logfwdr.bindings.map((binding) => {
|
|
157
|
+
return {
|
|
158
|
+
key: binding.name,
|
|
159
|
+
value: binding.destination,
|
|
160
|
+
};
|
|
161
|
+
}),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
152
165
|
if (services !== undefined && services.length > 0) {
|
|
153
166
|
output.push({
|
|
154
167
|
type: "Services",
|