wrangler 2.0.24 → 2.0.25
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/miniflare-dist/index.mjs +130 -16
- package/package.json +1 -1
- package/src/__tests__/configuration.test.ts +1 -1
- package/src/__tests__/dev.test.tsx +26 -4
- package/src/__tests__/helpers/mock-cfetch.ts +2 -2
- package/src/__tests__/r2.test.ts +18 -0
- package/src/__tests__/tail.test.ts +93 -39
- package/src/api/dev.ts +6 -0
- package/src/bundle.ts +3 -2
- package/src/config/config.ts +1 -1
- package/src/config/validation.ts +1 -1
- package/src/dev/dev.tsx +12 -2
- package/src/dev/local.tsx +69 -5
- package/src/dev/use-esbuild.ts +3 -0
- package/src/dev-registry.tsx +3 -0
- package/src/dev.tsx +26 -17
- package/src/index.tsx +51 -21
- package/src/inspect.ts +1 -4
- package/src/miniflare-cli/assets.ts +19 -16
- package/src/miniflare-cli/index.ts +121 -2
- package/src/pages/build.tsx +36 -28
- package/src/pages/constants.ts +3 -0
- package/src/pages/deployments.tsx +9 -9
- package/src/pages/dev.tsx +85 -27
- package/src/pages/functions/buildPlugin.ts +4 -0
- package/src/pages/functions/buildWorker.ts +4 -0
- package/src/pages/functions/routes-consolidation.test.ts +66 -0
- package/src/pages/functions/routes-consolidation.ts +29 -0
- package/src/pages/functions/routes-transformation.test.ts +271 -0
- package/src/pages/functions/routes-transformation.ts +125 -0
- package/src/pages/projects.tsx +9 -3
- package/src/pages/publish.tsx +56 -14
- package/src/pages/types.ts +9 -0
- package/src/pages/upload.tsx +6 -8
- package/src/r2.ts +13 -0
- package/src/tail/index.ts +15 -2
- package/src/tail/printing.ts +41 -3
- package/wrangler-dist/cli.d.ts +6 -0
- package/wrangler-dist/cli.js +385 -89
package/src/dev/dev.tsx
CHANGED
|
@@ -40,6 +40,7 @@ import type { CfWorkerInit } from "../worker";
|
|
|
40
40
|
function useDevRegistry(
|
|
41
41
|
name: string | undefined,
|
|
42
42
|
services: Config["services"] | undefined,
|
|
43
|
+
durableObjects: Config["durable_objects"] | undefined,
|
|
43
44
|
mode: "local" | "remote"
|
|
44
45
|
): WorkerRegistry {
|
|
45
46
|
const [workers, setWorkers] = useState<WorkerRegistry>({});
|
|
@@ -55,6 +56,9 @@ function useDevRegistry(
|
|
|
55
56
|
const serviceNames = (services || []).map(
|
|
56
57
|
(serviceBinding) => serviceBinding.service
|
|
57
58
|
);
|
|
59
|
+
const durableObjectServices = (
|
|
60
|
+
durableObjects || { bindings: [] }
|
|
61
|
+
).bindings.map((durableObjectBinding) => durableObjectBinding.script_name);
|
|
58
62
|
|
|
59
63
|
const interval =
|
|
60
64
|
// TODO: enable this for remote mode as well
|
|
@@ -67,7 +71,9 @@ function useDevRegistry(
|
|
|
67
71
|
// so let's filter out the others
|
|
68
72
|
const filteredWorkers = Object.fromEntries(
|
|
69
73
|
Object.entries(workerDefinitions || {}).filter(
|
|
70
|
-
([key, _value]) =>
|
|
74
|
+
([key, _value]) =>
|
|
75
|
+
serviceNames.includes(key) ||
|
|
76
|
+
durableObjectServices.includes(key)
|
|
71
77
|
)
|
|
72
78
|
);
|
|
73
79
|
setWorkers((prevWorkers) => {
|
|
@@ -109,7 +115,7 @@ function useDevRegistry(
|
|
|
109
115
|
}
|
|
110
116
|
);
|
|
111
117
|
};
|
|
112
|
-
}, [name, services, mode]);
|
|
118
|
+
}, [name, services, durableObjects, mode]);
|
|
113
119
|
|
|
114
120
|
return workers;
|
|
115
121
|
}
|
|
@@ -228,6 +234,7 @@ function DevSession(props: DevSessionProps) {
|
|
|
228
234
|
const workerDefinitions = useDevRegistry(
|
|
229
235
|
props.name,
|
|
230
236
|
props.bindings.services,
|
|
237
|
+
props.bindings.durable_objects,
|
|
231
238
|
props.local ? "local" : "remote"
|
|
232
239
|
);
|
|
233
240
|
|
|
@@ -248,6 +255,7 @@ function DevSession(props: DevSessionProps) {
|
|
|
248
255
|
assets: props.assetsConfig,
|
|
249
256
|
workerDefinitions,
|
|
250
257
|
services: props.bindings.services,
|
|
258
|
+
durableObjects: props.bindings.durable_objects || { bindings: [] },
|
|
251
259
|
firstPartyWorkerDevFacade: props.firstPartyWorker,
|
|
252
260
|
});
|
|
253
261
|
|
|
@@ -258,7 +266,9 @@ function DevSession(props: DevSessionProps) {
|
|
|
258
266
|
format={props.entry.format}
|
|
259
267
|
compatibilityDate={props.compatibilityDate}
|
|
260
268
|
compatibilityFlags={props.compatibilityFlags}
|
|
269
|
+
usageModel={props.usageModel}
|
|
261
270
|
bindings={props.bindings}
|
|
271
|
+
workerDefinitions={workerDefinitions}
|
|
262
272
|
assetPaths={props.assetPaths}
|
|
263
273
|
port={props.port}
|
|
264
274
|
ip={props.ip}
|
package/src/dev/local.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import { logger } from "../logger";
|
|
|
10
10
|
import { DEFAULT_MODULE_RULES } from "../module-collection";
|
|
11
11
|
import { waitForPortToBeAvailable } from "../proxy";
|
|
12
12
|
import type { Config } from "../config";
|
|
13
|
+
import type { WorkerRegistry } from "../dev-registry";
|
|
13
14
|
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
14
15
|
import type { AssetPaths } from "../sites";
|
|
15
16
|
import type { CfWorkerInit, CfScriptFormat } from "../worker";
|
|
@@ -22,7 +23,9 @@ interface LocalProps {
|
|
|
22
23
|
format: CfScriptFormat | undefined;
|
|
23
24
|
compatibilityDate: string;
|
|
24
25
|
compatibilityFlags: string[] | undefined;
|
|
26
|
+
usageModel: "bundled" | "unbound" | undefined;
|
|
25
27
|
bindings: CfWorkerInit["bindings"];
|
|
28
|
+
workerDefinitions: WorkerRegistry;
|
|
26
29
|
assetPaths: AssetPaths | undefined;
|
|
27
30
|
port: number;
|
|
28
31
|
ip: string;
|
|
@@ -56,7 +59,9 @@ function useLocalWorker({
|
|
|
56
59
|
format,
|
|
57
60
|
compatibilityDate,
|
|
58
61
|
compatibilityFlags,
|
|
62
|
+
usageModel,
|
|
59
63
|
bindings,
|
|
64
|
+
workerDefinitions,
|
|
60
65
|
assetPaths,
|
|
61
66
|
port,
|
|
62
67
|
inspectorPort,
|
|
@@ -96,6 +101,18 @@ function useLocalWorker({
|
|
|
96
101
|
}
|
|
97
102
|
}, [bindings.services]);
|
|
98
103
|
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const externalDurableObjects = (
|
|
106
|
+
bindings.durable_objects?.bindings || []
|
|
107
|
+
).filter((binding) => binding.script_name);
|
|
108
|
+
|
|
109
|
+
if (externalDurableObjects.length > 0) {
|
|
110
|
+
logger.warn(
|
|
111
|
+
"⎔ Support for external Durable Objects in local mode is experimental and may change."
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}, [bindings.durable_objects?.bindings]);
|
|
115
|
+
|
|
99
116
|
useEffect(() => {
|
|
100
117
|
const abortController = new AbortController();
|
|
101
118
|
async function startLocalWorker() {
|
|
@@ -180,6 +197,15 @@ function useLocalWorker({
|
|
|
180
197
|
? `${localProtocol}://${localUpstream}`
|
|
181
198
|
: undefined;
|
|
182
199
|
|
|
200
|
+
const internalDurableObjects = (
|
|
201
|
+
bindings.durable_objects?.bindings || []
|
|
202
|
+
).filter((binding) => !binding.script_name);
|
|
203
|
+
const externalDurableObjects = (
|
|
204
|
+
bindings.durable_objects?.bindings || []
|
|
205
|
+
).filter((binding) => binding.script_name);
|
|
206
|
+
|
|
207
|
+
// TODO: This was already messy with the custom `disableLogs` and `logOptions`.
|
|
208
|
+
// It's now getting _really_ messy now with Pages ASSETS binding outside and the external Durable Objects inside.
|
|
183
209
|
const options: MiniflareOptions = {
|
|
184
210
|
name: workerName,
|
|
185
211
|
port,
|
|
@@ -196,12 +222,37 @@ function useLocalWorker({
|
|
|
196
222
|
})),
|
|
197
223
|
compatibilityDate,
|
|
198
224
|
compatibilityFlags,
|
|
225
|
+
usageModel,
|
|
199
226
|
kvNamespaces: bindings.kv_namespaces?.map((kv) => kv.binding),
|
|
200
227
|
r2Buckets: bindings.r2_buckets?.map((r2) => r2.binding),
|
|
201
228
|
durableObjects: Object.fromEntries(
|
|
202
|
-
(
|
|
203
|
-
|
|
204
|
-
|
|
229
|
+
internalDurableObjects.map((binding) => [
|
|
230
|
+
binding.name,
|
|
231
|
+
binding.class_name,
|
|
232
|
+
])
|
|
233
|
+
),
|
|
234
|
+
externalDurableObjects: Object.fromEntries(
|
|
235
|
+
externalDurableObjects
|
|
236
|
+
.map((binding) => {
|
|
237
|
+
const service = workerDefinitions[binding.script_name as string];
|
|
238
|
+
if (!service) return [binding.name, undefined];
|
|
239
|
+
|
|
240
|
+
const name = service.durableObjects.find(
|
|
241
|
+
(durableObject) =>
|
|
242
|
+
durableObject.className === binding.class_name
|
|
243
|
+
)?.name;
|
|
244
|
+
if (!name) return [binding.name, undefined];
|
|
245
|
+
|
|
246
|
+
return [
|
|
247
|
+
binding.name,
|
|
248
|
+
{
|
|
249
|
+
name,
|
|
250
|
+
host: service.durableObjectsHost,
|
|
251
|
+
port: service.durableObjectsPort,
|
|
252
|
+
},
|
|
253
|
+
];
|
|
254
|
+
})
|
|
255
|
+
.filter(([_, details]) => !!details)
|
|
205
256
|
),
|
|
206
257
|
...(localPersistencePath
|
|
207
258
|
? {
|
|
@@ -275,8 +326,9 @@ function useLocalWorker({
|
|
|
275
326
|
stdio: "pipe",
|
|
276
327
|
}));
|
|
277
328
|
|
|
278
|
-
child.on("message", async (
|
|
279
|
-
|
|
329
|
+
child.on("message", async (messageString) => {
|
|
330
|
+
const message = JSON.parse(messageString as string);
|
|
331
|
+
if (message.ready) {
|
|
280
332
|
// Let's register our presence in the dev registry
|
|
281
333
|
if (workerName) {
|
|
282
334
|
await registerWorker(workerName, {
|
|
@@ -284,6 +336,16 @@ function useLocalWorker({
|
|
|
284
336
|
mode: "local",
|
|
285
337
|
port,
|
|
286
338
|
host: ip,
|
|
339
|
+
durableObjects: internalDurableObjects.map((binding) => ({
|
|
340
|
+
name: binding.name,
|
|
341
|
+
className: binding.class_name,
|
|
342
|
+
})),
|
|
343
|
+
...(message.durableObjectsPort
|
|
344
|
+
? {
|
|
345
|
+
durableObjectsHost: ip,
|
|
346
|
+
durableObjectsPort: message.durableObjectsPort,
|
|
347
|
+
}
|
|
348
|
+
: {}),
|
|
287
349
|
});
|
|
288
350
|
}
|
|
289
351
|
onReady?.();
|
|
@@ -363,8 +425,10 @@ function useLocalWorker({
|
|
|
363
425
|
bindings.r2_buckets,
|
|
364
426
|
bindings.vars,
|
|
365
427
|
bindings.services,
|
|
428
|
+
workerDefinitions,
|
|
366
429
|
compatibilityDate,
|
|
367
430
|
compatibilityFlags,
|
|
431
|
+
usageModel,
|
|
368
432
|
localPersistencePath,
|
|
369
433
|
liveReload,
|
|
370
434
|
assetPaths,
|
package/src/dev/use-esbuild.ts
CHANGED
|
@@ -34,6 +34,7 @@ export function useEsbuild({
|
|
|
34
34
|
noBundle,
|
|
35
35
|
workerDefinitions,
|
|
36
36
|
services,
|
|
37
|
+
durableObjects,
|
|
37
38
|
firstPartyWorkerDevFacade,
|
|
38
39
|
}: {
|
|
39
40
|
entry: Entry;
|
|
@@ -50,6 +51,7 @@ export function useEsbuild({
|
|
|
50
51
|
nodeCompat: boolean | undefined;
|
|
51
52
|
noBundle: boolean;
|
|
52
53
|
workerDefinitions: WorkerRegistry;
|
|
54
|
+
durableObjects: Config["durable_objects"];
|
|
53
55
|
firstPartyWorkerDevFacade: boolean | undefined;
|
|
54
56
|
}): EsbuildBundle | undefined {
|
|
55
57
|
const [bundle, setBundle] = useState<EsbuildBundle>();
|
|
@@ -168,6 +170,7 @@ export function useEsbuild({
|
|
|
168
170
|
define,
|
|
169
171
|
assets,
|
|
170
172
|
services,
|
|
173
|
+
durableObjects,
|
|
171
174
|
workerDefinitions,
|
|
172
175
|
firstPartyWorkerDevFacade,
|
|
173
176
|
]);
|
package/src/dev-registry.tsx
CHANGED
|
@@ -22,6 +22,9 @@ type WorkerDefinition = {
|
|
|
22
22
|
host: string | undefined;
|
|
23
23
|
mode: "local" | "remote";
|
|
24
24
|
headers?: Record<string, string>;
|
|
25
|
+
durableObjects: { name: string; className: string }[];
|
|
26
|
+
durableObjectsHost?: string;
|
|
27
|
+
durableObjectsPort?: number;
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
/**
|
package/src/dev.tsx
CHANGED
|
@@ -127,9 +127,9 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
|
|
|
127
127
|
default: true,
|
|
128
128
|
})
|
|
129
129
|
.option("ip", {
|
|
130
|
-
describe: "IP address to listen on
|
|
130
|
+
describe: "IP address to listen on",
|
|
131
131
|
type: "string",
|
|
132
|
-
|
|
132
|
+
default: "0.0.0.0",
|
|
133
133
|
})
|
|
134
134
|
.option("port", {
|
|
135
135
|
describe: "Port to listen on",
|
|
@@ -275,6 +275,11 @@ export type AdditionalDevProps = {
|
|
|
275
275
|
script_name?: string | undefined;
|
|
276
276
|
environment?: string | undefined;
|
|
277
277
|
}[];
|
|
278
|
+
r2?: {
|
|
279
|
+
binding: string;
|
|
280
|
+
bucket_name: string;
|
|
281
|
+
preview_bucket_name?: string;
|
|
282
|
+
}[];
|
|
278
283
|
};
|
|
279
284
|
type StartDevOptions = ArgumentsCamelCase<DevArgs> &
|
|
280
285
|
// These options can be passed in directly when called with the `wrangler.dev()` API.
|
|
@@ -429,6 +434,7 @@ export async function startDev(args: StartDevOptions) {
|
|
|
429
434
|
kv: args.kv,
|
|
430
435
|
vars: args.vars,
|
|
431
436
|
durableObjects: args.durableObjects,
|
|
437
|
+
r2: args.r2,
|
|
432
438
|
});
|
|
433
439
|
|
|
434
440
|
// mask anything that was overridden in .dev.vars
|
|
@@ -489,7 +495,7 @@ export async function startDev(args: StartDevOptions) {
|
|
|
489
495
|
port={args.port || config.dev.port || (await getLocalPort())}
|
|
490
496
|
ip={args.ip || config.dev.ip}
|
|
491
497
|
inspectorPort={
|
|
492
|
-
args
|
|
498
|
+
args.inspectorPort ||
|
|
493
499
|
config.dev.inspector_port ||
|
|
494
500
|
(await getInspectorPort())
|
|
495
501
|
}
|
|
@@ -591,21 +597,24 @@ async function getBindings(
|
|
|
591
597
|
...(args.durableObjects || []),
|
|
592
598
|
],
|
|
593
599
|
},
|
|
594
|
-
r2_buckets:
|
|
595
|
-
(
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
600
|
+
r2_buckets: [
|
|
601
|
+
...(configParam.r2_buckets?.map(
|
|
602
|
+
({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
|
|
603
|
+
// same idea as kv namespace preview id,
|
|
604
|
+
// same copy-on-write TODO
|
|
605
|
+
if (!preview_bucket_name) {
|
|
606
|
+
throw new Error(
|
|
607
|
+
`In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
binding,
|
|
612
|
+
bucket_name: preview_bucket_name,
|
|
613
|
+
};
|
|
602
614
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
),
|
|
615
|
+
) || []),
|
|
616
|
+
...(args.r2 || []),
|
|
617
|
+
],
|
|
609
618
|
worker_namespaces: configParam.worker_namespaces,
|
|
610
619
|
services: configParam.services,
|
|
611
620
|
unsafe: configParam.unsafe?.bindings,
|
package/src/index.tsx
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
bucketAndKeyFromObjectPath,
|
|
52
52
|
createR2Bucket,
|
|
53
53
|
deleteR2Bucket,
|
|
54
|
+
deleteR2Object,
|
|
54
55
|
getR2Object,
|
|
55
56
|
listR2Buckets,
|
|
56
57
|
putR2Object,
|
|
@@ -1731,6 +1732,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1731
1732
|
);
|
|
1732
1733
|
}
|
|
1733
1734
|
}
|
|
1735
|
+
|
|
1734
1736
|
if (errors.length > 0) {
|
|
1735
1737
|
throw new Error(
|
|
1736
1738
|
`Unexpected JSON input from "${filename}".\n` +
|
|
@@ -1768,13 +1770,12 @@ function createCLIParser(argv: string[]) {
|
|
|
1768
1770
|
.command(
|
|
1769
1771
|
"get <objectPath>",
|
|
1770
1772
|
"Fetch an object from an R2 bucket",
|
|
1771
|
-
(
|
|
1772
|
-
return
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
})
|
|
1773
|
+
(Objectyargs) => {
|
|
1774
|
+
return Objectyargs.positional("objectPath", {
|
|
1775
|
+
describe:
|
|
1776
|
+
"The source object path in the form of {bucket}/{key}",
|
|
1777
|
+
type: "string",
|
|
1778
|
+
})
|
|
1778
1779
|
.option("file", {
|
|
1779
1780
|
describe: "The destination file to create",
|
|
1780
1781
|
alias: "f",
|
|
@@ -1790,13 +1791,16 @@ function createCLIParser(argv: string[]) {
|
|
|
1790
1791
|
type: "boolean",
|
|
1791
1792
|
});
|
|
1792
1793
|
},
|
|
1793
|
-
async (
|
|
1794
|
-
const config = readConfig(
|
|
1794
|
+
async (objectGetYargs) => {
|
|
1795
|
+
const config = readConfig(
|
|
1796
|
+
objectGetYargs.config as ConfigPath,
|
|
1797
|
+
objectGetYargs
|
|
1798
|
+
);
|
|
1795
1799
|
const accountId = await requireAuth(config);
|
|
1796
|
-
const { objectPath, pipe } =
|
|
1800
|
+
const { objectPath, pipe } = objectGetYargs;
|
|
1797
1801
|
const { bucket, key } = bucketAndKeyFromObjectPath(objectPath);
|
|
1798
1802
|
|
|
1799
|
-
let file =
|
|
1803
|
+
let file = objectGetYargs.file;
|
|
1800
1804
|
if (!file && !pipe) {
|
|
1801
1805
|
file = key;
|
|
1802
1806
|
}
|
|
@@ -1817,13 +1821,12 @@ function createCLIParser(argv: string[]) {
|
|
|
1817
1821
|
.command(
|
|
1818
1822
|
"put <objectPath>",
|
|
1819
1823
|
"Create an object in an R2 bucket",
|
|
1820
|
-
(
|
|
1821
|
-
return
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
})
|
|
1824
|
+
(Objectyargs) => {
|
|
1825
|
+
return Objectyargs.positional("objectPath", {
|
|
1826
|
+
describe:
|
|
1827
|
+
"The destination object path in the form of {bucket}/{key}",
|
|
1828
|
+
type: "string",
|
|
1829
|
+
})
|
|
1827
1830
|
.option("file", {
|
|
1828
1831
|
describe: "The path of the file to upload",
|
|
1829
1832
|
alias: "f",
|
|
@@ -1880,12 +1883,15 @@ function createCLIParser(argv: string[]) {
|
|
|
1880
1883
|
type: "string",
|
|
1881
1884
|
});
|
|
1882
1885
|
},
|
|
1883
|
-
async (
|
|
1886
|
+
async (objectPutYargs) => {
|
|
1884
1887
|
await printWranglerBanner();
|
|
1885
1888
|
|
|
1886
|
-
const config = readConfig(
|
|
1889
|
+
const config = readConfig(
|
|
1890
|
+
objectPutYargs.config as ConfigPath,
|
|
1891
|
+
objectPutYargs
|
|
1892
|
+
);
|
|
1887
1893
|
const accountId = await requireAuth(config);
|
|
1888
|
-
const { objectPath, file, pipe, ...options } =
|
|
1894
|
+
const { objectPath, file, pipe, ...options } = objectPutYargs;
|
|
1889
1895
|
const { bucket, key } = bucketAndKeyFromObjectPath(objectPath);
|
|
1890
1896
|
if (!file && !pipe) {
|
|
1891
1897
|
throw new CommandLineArgsError(
|
|
@@ -1922,8 +1928,32 @@ function createCLIParser(argv: string[]) {
|
|
|
1922
1928
|
});
|
|
1923
1929
|
logger.log("Upload complete.");
|
|
1924
1930
|
}
|
|
1931
|
+
)
|
|
1932
|
+
.command(
|
|
1933
|
+
"delete <objectPath>",
|
|
1934
|
+
"Delete an object in an R2 bucket",
|
|
1935
|
+
(objectDeleteYargs) => {
|
|
1936
|
+
return objectDeleteYargs.positional("objectPath", {
|
|
1937
|
+
describe:
|
|
1938
|
+
"The destination object path in the form of {bucket}/{key}",
|
|
1939
|
+
type: "string",
|
|
1940
|
+
});
|
|
1941
|
+
},
|
|
1942
|
+
async (args) => {
|
|
1943
|
+
const { objectPath } = args;
|
|
1944
|
+
await printWranglerBanner();
|
|
1945
|
+
|
|
1946
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1947
|
+
const accountId = await requireAuth(config);
|
|
1948
|
+
const { bucket, key } = bucketAndKeyFromObjectPath(objectPath);
|
|
1949
|
+
logger.log(`Deleting object "${key}" from bucket "${bucket}".`);
|
|
1950
|
+
|
|
1951
|
+
await deleteR2Object(accountId, bucket, key);
|
|
1952
|
+
logger.log("Delete complete.");
|
|
1953
|
+
}
|
|
1925
1954
|
);
|
|
1926
1955
|
})
|
|
1956
|
+
|
|
1927
1957
|
.command("bucket", "Manage R2 buckets", (r2BucketYargs) => {
|
|
1928
1958
|
r2BucketYargs.command(
|
|
1929
1959
|
"create <name>",
|
package/src/inspect.ts
CHANGED
|
@@ -320,10 +320,7 @@ export default function useInspector(props: InspectorProps) {
|
|
|
320
320
|
const convertedFnName =
|
|
321
321
|
pos.name || functionName || "";
|
|
322
322
|
exceptionLines.push(
|
|
323
|
-
` at ${convertedFnName} (${pos.source
|
|
324
|
-
`${mapContent.sourceRoot}/`,
|
|
325
|
-
""
|
|
326
|
-
)}:${pos.line}:${pos.column})`
|
|
323
|
+
` at ${convertedFnName} (${pos.source}:${pos.line}:${pos.column})`
|
|
327
324
|
);
|
|
328
325
|
}
|
|
329
326
|
}
|
|
@@ -335,6 +335,11 @@ async function generateAssetsFetch(
|
|
|
335
335
|
|
|
336
336
|
const generateResponse = (request: MiniflareRequest) => {
|
|
337
337
|
const url = new URL(request.url);
|
|
338
|
+
let assetName = url.pathname;
|
|
339
|
+
try {
|
|
340
|
+
//it's possible for someone to send a URL like http://fakehost/abc%2 which would fail to decode
|
|
341
|
+
assetName = decodeURIComponent(url.pathname);
|
|
342
|
+
} catch {}
|
|
338
343
|
|
|
339
344
|
const deconstructedResponse: {
|
|
340
345
|
status: number;
|
|
@@ -377,7 +382,7 @@ async function generateAssetsFetch(
|
|
|
377
382
|
}
|
|
378
383
|
|
|
379
384
|
const notFound = () => {
|
|
380
|
-
let cwd =
|
|
385
|
+
let cwd = assetName;
|
|
381
386
|
while (cwd) {
|
|
382
387
|
cwd = cwd.slice(0, cwd.lastIndexOf("/"));
|
|
383
388
|
|
|
@@ -407,38 +412,36 @@ async function generateAssetsFetch(
|
|
|
407
412
|
|
|
408
413
|
let asset;
|
|
409
414
|
|
|
410
|
-
if (
|
|
411
|
-
if ((asset = getAsset(`${
|
|
415
|
+
if (assetName.endsWith("/")) {
|
|
416
|
+
if ((asset = getAsset(`${assetName}/index.html`))) {
|
|
412
417
|
deconstructedResponse.body = serveAsset(asset);
|
|
413
418
|
deconstructedResponse.headers.set(
|
|
414
419
|
"Content-Type",
|
|
415
420
|
getType(asset) || "application/octet-stream"
|
|
416
421
|
);
|
|
417
422
|
return deconstructedResponse;
|
|
418
|
-
} else if (
|
|
419
|
-
(asset = getAsset(`${url.pathname.replace(/\/$/, ".html")}`))
|
|
420
|
-
) {
|
|
423
|
+
} else if ((asset = getAsset(`${assetName.replace(/\/$/, ".html")}`))) {
|
|
421
424
|
deconstructedResponse.status = 301;
|
|
422
425
|
deconstructedResponse.headers.set(
|
|
423
426
|
"Location",
|
|
424
|
-
`${
|
|
427
|
+
`${assetName.slice(0, -1)}${url.search}`
|
|
425
428
|
);
|
|
426
429
|
return deconstructedResponse;
|
|
427
430
|
}
|
|
428
431
|
}
|
|
429
432
|
|
|
430
|
-
if (
|
|
433
|
+
if (assetName.endsWith("/index")) {
|
|
431
434
|
deconstructedResponse.status = 301;
|
|
432
435
|
deconstructedResponse.headers.set(
|
|
433
436
|
"Location",
|
|
434
|
-
`${
|
|
437
|
+
`${assetName.slice(0, -"index".length)}${url.search}`
|
|
435
438
|
);
|
|
436
439
|
return deconstructedResponse;
|
|
437
440
|
}
|
|
438
441
|
|
|
439
|
-
if ((asset = getAsset(
|
|
440
|
-
if (
|
|
441
|
-
const extensionlessPath =
|
|
442
|
+
if ((asset = getAsset(assetName))) {
|
|
443
|
+
if (assetName.endsWith(".html")) {
|
|
444
|
+
const extensionlessPath = assetName.slice(0, -".html".length);
|
|
442
445
|
if (getAsset(extensionlessPath) || extensionlessPath === "/") {
|
|
443
446
|
deconstructedResponse.body = serveAsset(asset);
|
|
444
447
|
deconstructedResponse.headers.set(
|
|
@@ -462,12 +465,12 @@ async function generateAssetsFetch(
|
|
|
462
465
|
);
|
|
463
466
|
return deconstructedResponse;
|
|
464
467
|
}
|
|
465
|
-
} else if (hasFileExtension(
|
|
468
|
+
} else if (hasFileExtension(assetName)) {
|
|
466
469
|
notFound();
|
|
467
470
|
return deconstructedResponse;
|
|
468
471
|
}
|
|
469
472
|
|
|
470
|
-
if ((asset = getAsset(`${
|
|
473
|
+
if ((asset = getAsset(`${assetName}.html`))) {
|
|
471
474
|
deconstructedResponse.body = serveAsset(asset);
|
|
472
475
|
deconstructedResponse.headers.set(
|
|
473
476
|
"Content-Type",
|
|
@@ -476,11 +479,11 @@ async function generateAssetsFetch(
|
|
|
476
479
|
return deconstructedResponse;
|
|
477
480
|
}
|
|
478
481
|
|
|
479
|
-
if ((asset = getAsset(`${
|
|
482
|
+
if ((asset = getAsset(`${assetName}/index.html`))) {
|
|
480
483
|
deconstructedResponse.status = 301;
|
|
481
484
|
deconstructedResponse.headers.set(
|
|
482
485
|
"Location",
|
|
483
|
-
`${
|
|
486
|
+
`${assetName}/${url.search}`
|
|
484
487
|
);
|
|
485
488
|
return deconstructedResponse;
|
|
486
489
|
} else {
|