-
Notifications
You must be signed in to change notification settings - Fork 731
/
r2.ts
131 lines (121 loc) · 2.88 KB
/
r2.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { Readable } from "node:stream";
import { fetchResult } from "./cfetch";
import { fetchR2Objects } from "./cfetch/internal";
import type { HeadersInit } from "undici";
/**
* Information about a bucket, returned from `listR2Buckets()`.
*/
export interface R2BucketInfo {
name: string;
creation_date: string;
}
/**
* Fetch a list of all the buckets under the given `accountId`.
*/
export async function listR2Buckets(
accountId: string
): Promise<R2BucketInfo[]> {
const results = await fetchResult<{
buckets: R2BucketInfo[];
}>(`/accounts/${accountId}/r2/buckets`);
return results.buckets;
}
/**
* Create a bucket with the given `bucketName` within the account given by `accountId`.
*
* A 400 is returned if the account already owns a bucket with this name.
* A bucket must be explicitly deleted to be replaced.
*/
export async function createR2Bucket(
accountId: string,
bucketName: string
): Promise<void> {
return await fetchResult<void>(
`/accounts/${accountId}/r2/buckets/${bucketName}`,
{ method: "PUT" }
);
}
/**
* Delete a bucket with the given name
*/
export async function deleteR2Bucket(
accountId: string,
bucketName: string
): Promise<void> {
return await fetchResult<void>(
`/accounts/${accountId}/r2/buckets/${bucketName}`,
{ method: "DELETE" }
);
}
export function bucketAndKeyFromObjectPath(objectPath = ""): {
bucket: string;
key: string;
} {
const match = /^([^/]+)\/(.*)/.exec(objectPath);
if (match === null) {
throw new Error(
`The object path must be in the form of {bucket}/{key} you provided ${objectPath}`
);
}
return { bucket: match[1], key: match[2] };
}
/**
* Downloads an object
*/
export async function getR2Object(
accountId: string,
bucketName: string,
objectName: string
): Promise<Readable> {
const response = await fetchR2Objects(
`/accounts/${accountId}/r2/buckets/${bucketName}/objects/${objectName}`,
{ method: "GET" }
);
return Readable.from(response.body);
}
/**
* Uploads an object
*/
export async function putR2Object(
accountId: string,
bucketName: string,
objectName: string,
object: Readable | Buffer,
options: Record<string, unknown>
): Promise<void> {
const headerKeys = [
"content-length",
"content-type",
"content-disposition",
"content-encoding",
"content-language",
"cache-control",
"expires",
];
const headers: HeadersInit = {};
for (const key of headerKeys) {
const value = options[key] || "";
if (value && typeof value === "string") headers[key] = value;
}
await fetchR2Objects(
`/accounts/${accountId}/r2/buckets/${bucketName}/objects/${objectName}`,
{
body: object,
headers,
method: "PUT",
}
);
}
/**
* Delete an Object
*/
export async function deleteR2Object(
accountId: string,
bucketName: string,
objectName: string
): Promise<void> {
await fetchR2Objects(
`/accounts/${accountId}/r2/buckets/${bucketName}/objects/${objectName}`,
{ method: "DELETE" }
);
}