@vercel/blob 2.1.0-704ff70-20260123180156 → 2.1.0-73e660a-20260202164138
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/dist/{chunk-7TB5OCQA.cjs → chunk-JBMWRYVF.cjs} +9 -2
- package/dist/chunk-JBMWRYVF.cjs.map +1 -0
- package/dist/{chunk-IMAXVSQW.js → chunk-TNFJU7CU.js} +9 -2
- package/dist/{chunk-IMAXVSQW.js.map → chunk-TNFJU7CU.js.map} +1 -1
- package/dist/client.cjs +22 -22
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/{create-folder-BvLlL5az.d.cts → create-folder-BN0ETvwT.d.cts} +4 -3
- package/dist/{create-folder-BvLlL5az.d.ts → create-folder-BN0ETvwT.d.ts} +4 -3
- package/dist/index.cjs +51 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -26
- package/dist/index.d.ts +27 -26
- package/dist/index.js +27 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-7TB5OCQA.cjs.map +0 -1
package/dist/client.cjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkJBMWRYVFcjs = require('./chunk-JBMWRYVF.cjs');
|
|
11
11
|
|
|
12
12
|
// src/client.ts
|
|
13
13
|
var _crypto = require('crypto'); var crypto = _interopRequireWildcard(_crypto);
|
|
@@ -15,7 +15,7 @@ var _undici = require('undici');
|
|
|
15
15
|
function createPutExtraChecks(methodName) {
|
|
16
16
|
return function extraChecks(options) {
|
|
17
17
|
if (!options.token.startsWith("vercel_blob_client_")) {
|
|
18
|
-
throw new (0,
|
|
18
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(`${methodName} must be called with a client token`);
|
|
19
19
|
}
|
|
20
20
|
if (
|
|
21
21
|
// @ts-expect-error -- Runtime check for DX.
|
|
@@ -23,41 +23,41 @@ function createPutExtraChecks(methodName) {
|
|
|
23
23
|
options.allowOverwrite !== void 0 || // @ts-expect-error -- Runtime check for DX.
|
|
24
24
|
options.cacheControlMaxAge !== void 0
|
|
25
25
|
) {
|
|
26
|
-
throw new (0,
|
|
26
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
27
27
|
`${methodName} doesn't allow \`addRandomSuffix\`, \`cacheControlMaxAge\` or \`allowOverwrite\`. Configure these options at the server side when generating client tokens.`
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
var put =
|
|
32
|
+
var put = _chunkJBMWRYVFcjs.createPutMethod.call(void 0, {
|
|
33
33
|
allowedOptions: ["contentType"],
|
|
34
34
|
extraChecks: createPutExtraChecks("client/`put`")
|
|
35
35
|
});
|
|
36
|
-
var createMultipartUpload =
|
|
36
|
+
var createMultipartUpload = _chunkJBMWRYVFcjs.createCreateMultipartUploadMethod.call(void 0, {
|
|
37
37
|
allowedOptions: ["contentType"],
|
|
38
38
|
extraChecks: createPutExtraChecks("client/`createMultipartUpload`")
|
|
39
39
|
});
|
|
40
|
-
var createMultipartUploader =
|
|
40
|
+
var createMultipartUploader = _chunkJBMWRYVFcjs.createCreateMultipartUploaderMethod.call(void 0,
|
|
41
41
|
{
|
|
42
42
|
allowedOptions: ["contentType"],
|
|
43
43
|
extraChecks: createPutExtraChecks("client/`createMultipartUpload`")
|
|
44
44
|
}
|
|
45
45
|
);
|
|
46
|
-
var uploadPart =
|
|
46
|
+
var uploadPart = _chunkJBMWRYVFcjs.createUploadPartMethod.call(void 0, {
|
|
47
47
|
allowedOptions: ["contentType"],
|
|
48
48
|
extraChecks: createPutExtraChecks("client/`multipartUpload`")
|
|
49
49
|
});
|
|
50
|
-
var completeMultipartUpload =
|
|
50
|
+
var completeMultipartUpload = _chunkJBMWRYVFcjs.createCompleteMultipartUploadMethod.call(void 0,
|
|
51
51
|
{
|
|
52
52
|
allowedOptions: ["contentType"],
|
|
53
53
|
extraChecks: createPutExtraChecks("client/`completeMultipartUpload`")
|
|
54
54
|
}
|
|
55
55
|
);
|
|
56
|
-
var upload =
|
|
56
|
+
var upload = _chunkJBMWRYVFcjs.createPutMethod.call(void 0, {
|
|
57
57
|
allowedOptions: ["contentType"],
|
|
58
58
|
extraChecks(options) {
|
|
59
59
|
if (options.handleUploadUrl === void 0) {
|
|
60
|
-
throw new (0,
|
|
60
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
61
61
|
"client/`upload` requires the 'handleUploadUrl' parameter"
|
|
62
62
|
);
|
|
63
63
|
}
|
|
@@ -67,7 +67,7 @@ var upload = _chunk7TB5OCQAcjs.createPutMethod.call(void 0, {
|
|
|
67
67
|
options.createPutExtraChecks !== void 0 || // @ts-expect-error -- Runtime check for DX.
|
|
68
68
|
options.cacheControlMaxAge !== void 0
|
|
69
69
|
) {
|
|
70
|
-
throw new (0,
|
|
70
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
71
71
|
"client/`upload` doesn't allow `addRandomSuffix`, `cacheControlMaxAge` or `allowOverwrite`. Configure these options at the server side when generating client tokens."
|
|
72
72
|
);
|
|
73
73
|
}
|
|
@@ -152,7 +152,7 @@ async function handleUpload({
|
|
|
152
152
|
onUploadCompleted
|
|
153
153
|
}) {
|
|
154
154
|
var _a, _b, _c, _d;
|
|
155
|
-
const resolvedToken =
|
|
155
|
+
const resolvedToken = _chunkJBMWRYVFcjs.getTokenFromOptionsOrEnv.call(void 0, { token });
|
|
156
156
|
const type = body.type;
|
|
157
157
|
switch (type) {
|
|
158
158
|
case "blob.generate-client-token": {
|
|
@@ -194,7 +194,7 @@ async function handleUpload({
|
|
|
194
194
|
const signatureHeader = "x-vercel-signature";
|
|
195
195
|
const signature = "credentials" in request ? (_c = request.headers.get(signatureHeader)) != null ? _c : "" : (_d = request.headers[signatureHeader]) != null ? _d : "";
|
|
196
196
|
if (!signature) {
|
|
197
|
-
throw new (0,
|
|
197
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Missing callback signature");
|
|
198
198
|
}
|
|
199
199
|
const isVerified = await verifyCallbackSignature({
|
|
200
200
|
token: resolvedToken,
|
|
@@ -202,7 +202,7 @@ async function handleUpload({
|
|
|
202
202
|
body: JSON.stringify(body)
|
|
203
203
|
});
|
|
204
204
|
if (!isVerified) {
|
|
205
|
-
throw new (0,
|
|
205
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Invalid callback signature");
|
|
206
206
|
}
|
|
207
207
|
if (onUploadCompleted) {
|
|
208
208
|
await onUploadCompleted(body.payload);
|
|
@@ -210,7 +210,7 @@ async function handleUpload({
|
|
|
210
210
|
return { type, response: "ok" };
|
|
211
211
|
}
|
|
212
212
|
default:
|
|
213
|
-
throw new (0,
|
|
213
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Invalid event type");
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
async function retrieveClientToken(options) {
|
|
@@ -234,13 +234,13 @@ async function retrieveClientToken(options) {
|
|
|
234
234
|
signal: options.abortSignal
|
|
235
235
|
});
|
|
236
236
|
if (!res.ok) {
|
|
237
|
-
throw new (0,
|
|
237
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Failed to retrieve the client token");
|
|
238
238
|
}
|
|
239
239
|
try {
|
|
240
240
|
const { clientToken } = await res.json();
|
|
241
241
|
return clientToken;
|
|
242
242
|
} catch (e) {
|
|
243
|
-
throw new (0,
|
|
243
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Failed to retrieve the client token");
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
function toAbsoluteUrl(url) {
|
|
@@ -259,16 +259,16 @@ async function generateClientTokenFromReadWriteToken({
|
|
|
259
259
|
}) {
|
|
260
260
|
var _a;
|
|
261
261
|
if (typeof window !== "undefined") {
|
|
262
|
-
throw new (0,
|
|
262
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
263
263
|
'"generateClientTokenFromReadWriteToken" must be called from a server environment'
|
|
264
264
|
);
|
|
265
265
|
}
|
|
266
266
|
const timestamp = /* @__PURE__ */ new Date();
|
|
267
267
|
timestamp.setSeconds(timestamp.getSeconds() + 30);
|
|
268
|
-
const readWriteToken =
|
|
268
|
+
const readWriteToken = _chunkJBMWRYVFcjs.getTokenFromOptionsOrEnv.call(void 0, { token });
|
|
269
269
|
const [, , , storeId = null] = readWriteToken.split("_");
|
|
270
270
|
if (!storeId) {
|
|
271
|
-
throw new (0,
|
|
271
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
272
272
|
token ? "Invalid `token` parameter" : "Invalid `BLOB_READ_WRITE_TOKEN`"
|
|
273
273
|
);
|
|
274
274
|
}
|
|
@@ -280,7 +280,7 @@ async function generateClientTokenFromReadWriteToken({
|
|
|
280
280
|
).toString("base64");
|
|
281
281
|
const securedKey = await signPayload(payload, readWriteToken);
|
|
282
282
|
if (!securedKey) {
|
|
283
|
-
throw new (0,
|
|
283
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Unable to sign client token");
|
|
284
284
|
}
|
|
285
285
|
return `vercel_blob_client_${storeId}_${Buffer.from(
|
|
286
286
|
`${securedKey}.${payload}`
|
|
@@ -335,5 +335,5 @@ function getPathFromRequestUrl(url) {
|
|
|
335
335
|
|
|
336
336
|
|
|
337
337
|
|
|
338
|
-
exports.completeMultipartUpload = completeMultipartUpload; exports.createFolder =
|
|
338
|
+
exports.completeMultipartUpload = completeMultipartUpload; exports.createFolder = _chunkJBMWRYVFcjs.createFolder; exports.createMultipartUpload = createMultipartUpload; exports.createMultipartUploader = createMultipartUploader; exports.generateClientTokenFromReadWriteToken = generateClientTokenFromReadWriteToken; exports.getPayloadFromClientToken = getPayloadFromClientToken; exports.handleUpload = handleUpload; exports.put = put; exports.upload = upload; exports.uploadPart = uploadPart;
|
|
339
339
|
//# sourceMappingURL=client.cjs.map
|
package/dist/client.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BlobAccessType, W as WithUploadProgress, a as BlobCommandOptions, P as PutBlobResult, b as Part, C as CommonCompleteMultipartUploadOptions, c as PutBody, d as CommonMultipartUploadOptions } from './create-folder-
|
|
2
|
-
export { e as createFolder } from './create-folder-
|
|
1
|
+
import { B as BlobAccessType, W as WithUploadProgress, a as BlobCommandOptions, P as PutBlobResult, b as Part, C as CommonCompleteMultipartUploadOptions, c as PutBody, d as CommonMultipartUploadOptions } from './create-folder-BN0ETvwT.cjs';
|
|
2
|
+
export { e as createFolder } from './create-folder-BN0ETvwT.cjs';
|
|
3
3
|
import { IncomingMessage } from 'node:http';
|
|
4
4
|
import 'stream';
|
|
5
5
|
import 'undici';
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BlobAccessType, W as WithUploadProgress, a as BlobCommandOptions, P as PutBlobResult, b as Part, C as CommonCompleteMultipartUploadOptions, c as PutBody, d as CommonMultipartUploadOptions } from './create-folder-
|
|
2
|
-
export { e as createFolder } from './create-folder-
|
|
1
|
+
import { B as BlobAccessType, W as WithUploadProgress, a as BlobCommandOptions, P as PutBlobResult, b as Part, C as CommonCompleteMultipartUploadOptions, c as PutBody, d as CommonMultipartUploadOptions } from './create-folder-BN0ETvwT.js';
|
|
2
|
+
export { e as createFolder } from './create-folder-BN0ETvwT.js';
|
|
3
3
|
import { IncomingMessage } from 'node:http';
|
|
4
4
|
import 'stream';
|
|
5
5
|
import 'undici';
|
package/dist/client.js
CHANGED
|
@@ -197,6 +197,7 @@ interface CommonMultipartUploadOptions {
|
|
|
197
197
|
}
|
|
198
198
|
type UploadPartCommandOptions = CommonMultipartUploadOptions & CommonCreateBlobOptions;
|
|
199
199
|
|
|
200
|
+
type CreateFolderCommandOptions = Pick<CommonCreateBlobOptions, 'access' | 'token' | 'abortSignal'>;
|
|
200
201
|
interface CreateFolderResult {
|
|
201
202
|
pathname: string;
|
|
202
203
|
url: string;
|
|
@@ -206,8 +207,8 @@ interface CreateFolderResult {
|
|
|
206
207
|
*
|
|
207
208
|
* Use the resulting `url` to delete the folder, just like you would delete a blob.
|
|
208
209
|
* @param pathname - Can be user1/ or user1/avatars/
|
|
209
|
-
* @param options - Additional options
|
|
210
|
+
* @param options - Additional options including required `access` ('public' or 'private') and optional `token`
|
|
210
211
|
*/
|
|
211
|
-
declare function createFolder(pathname: string, options
|
|
212
|
+
declare function createFolder(pathname: string, options: CreateFolderCommandOptions): Promise<CreateFolderResult>;
|
|
212
213
|
|
|
213
|
-
export { type BlobAccessType as B, type CommonCompleteMultipartUploadOptions as C, type OnUploadProgressCallback as O, type PutBlobResult as P, type UploadPartCommandOptions as U, type WithUploadProgress as W, type BlobCommandOptions as a, type Part as b, type PutBody as c, type CommonMultipartUploadOptions as d, createFolder as e, type CommonCreateBlobOptions as f, BlobError as g, type CompleteMultipartUploadCommandOptions as h, type
|
|
214
|
+
export { type BlobAccessType as B, type CommonCompleteMultipartUploadOptions as C, type OnUploadProgressCallback as O, type PutBlobResult as P, type UploadPartCommandOptions as U, type WithUploadProgress as W, type BlobCommandOptions as a, type Part as b, type PutBody as c, type CommonMultipartUploadOptions as d, createFolder as e, type CommonCreateBlobOptions as f, BlobError as g, type CompleteMultipartUploadCommandOptions as h, type CreateFolderCommandOptions as i, type CreateFolderResult as j, type PartInput as k, type UploadProgressEvent as l, getDownloadUrl as m };
|
|
@@ -197,6 +197,7 @@ interface CommonMultipartUploadOptions {
|
|
|
197
197
|
}
|
|
198
198
|
type UploadPartCommandOptions = CommonMultipartUploadOptions & CommonCreateBlobOptions;
|
|
199
199
|
|
|
200
|
+
type CreateFolderCommandOptions = Pick<CommonCreateBlobOptions, 'access' | 'token' | 'abortSignal'>;
|
|
200
201
|
interface CreateFolderResult {
|
|
201
202
|
pathname: string;
|
|
202
203
|
url: string;
|
|
@@ -206,8 +207,8 @@ interface CreateFolderResult {
|
|
|
206
207
|
*
|
|
207
208
|
* Use the resulting `url` to delete the folder, just like you would delete a blob.
|
|
208
209
|
* @param pathname - Can be user1/ or user1/avatars/
|
|
209
|
-
* @param options - Additional options
|
|
210
|
+
* @param options - Additional options including required `access` ('public' or 'private') and optional `token`
|
|
210
211
|
*/
|
|
211
|
-
declare function createFolder(pathname: string, options
|
|
212
|
+
declare function createFolder(pathname: string, options: CreateFolderCommandOptions): Promise<CreateFolderResult>;
|
|
212
213
|
|
|
213
|
-
export { type BlobAccessType as B, type CommonCompleteMultipartUploadOptions as C, type OnUploadProgressCallback as O, type PutBlobResult as P, type UploadPartCommandOptions as U, type WithUploadProgress as W, type BlobCommandOptions as a, type Part as b, type PutBody as c, type CommonMultipartUploadOptions as d, createFolder as e, type CommonCreateBlobOptions as f, BlobError as g, type CompleteMultipartUploadCommandOptions as h, type
|
|
214
|
+
export { type BlobAccessType as B, type CommonCompleteMultipartUploadOptions as C, type OnUploadProgressCallback as O, type PutBlobResult as P, type UploadPartCommandOptions as U, type WithUploadProgress as W, type BlobCommandOptions as a, type Part as b, type PutBody as c, type CommonMultipartUploadOptions as d, createFolder as e, type CommonCreateBlobOptions as f, BlobError as g, type CompleteMultipartUploadCommandOptions as h, type CreateFolderCommandOptions as i, type CreateFolderResult as j, type PartInput as k, type UploadProgressEvent as l, getDownloadUrl as m };
|
package/dist/index.cjs
CHANGED
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
var
|
|
26
|
+
var _chunkJBMWRYVFcjs = require('./chunk-JBMWRYVF.cjs');
|
|
27
27
|
|
|
28
28
|
// src/del.ts
|
|
29
29
|
async function del(urlOrPathname, options) {
|
|
30
|
-
await
|
|
30
|
+
await _chunkJBMWRYVFcjs.requestApi.call(void 0,
|
|
31
31
|
"/delete",
|
|
32
32
|
{
|
|
33
33
|
method: "POST",
|
|
@@ -44,7 +44,7 @@ async function del(urlOrPathname, options) {
|
|
|
44
44
|
// src/head.ts
|
|
45
45
|
async function head(urlOrPathname, options) {
|
|
46
46
|
const searchParams = new URLSearchParams({ url: urlOrPathname });
|
|
47
|
-
const response = await
|
|
47
|
+
const response = await _chunkJBMWRYVFcjs.requestApi.call(void 0,
|
|
48
48
|
`?${searchParams.toString()}`,
|
|
49
49
|
// HEAD can't have body as a response, so we use GET
|
|
50
50
|
{
|
|
@@ -66,6 +66,7 @@ async function head(urlOrPathname, options) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// src/get.ts
|
|
69
|
+
var _undici = require('undici');
|
|
69
70
|
function isUrl(urlOrPathname) {
|
|
70
71
|
return urlOrPathname.startsWith("http://") || urlOrPathname.startsWith("https://");
|
|
71
72
|
}
|
|
@@ -81,63 +82,77 @@ function getStoreIdFromToken(token) {
|
|
|
81
82
|
const [, , , storeId = ""] = token.split("_");
|
|
82
83
|
return storeId;
|
|
83
84
|
}
|
|
84
|
-
function constructBlobUrl(storeId, pathname) {
|
|
85
|
-
return `https://${storeId}.
|
|
85
|
+
function constructBlobUrl(storeId, pathname, access) {
|
|
86
|
+
return `https://${storeId}.${access}.blob.vercel-storage.com/${pathname}`;
|
|
86
87
|
}
|
|
87
88
|
async function get(urlOrPathname, options) {
|
|
88
89
|
if (!urlOrPathname) {
|
|
89
|
-
throw new (0,
|
|
90
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("url or pathname is required");
|
|
90
91
|
}
|
|
91
92
|
if (!options) {
|
|
92
|
-
throw new (0,
|
|
93
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("missing options, see usage");
|
|
93
94
|
}
|
|
94
95
|
if (options.access !== "public" && options.access !== "private") {
|
|
95
|
-
throw new (0,
|
|
96
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)('access must be "public" or "private"');
|
|
96
97
|
}
|
|
97
|
-
const token =
|
|
98
|
+
const token = _chunkJBMWRYVFcjs.getTokenFromOptionsOrEnv.call(void 0, options);
|
|
98
99
|
let blobUrl;
|
|
99
100
|
let pathname;
|
|
101
|
+
const access = options.access;
|
|
100
102
|
if (isUrl(urlOrPathname)) {
|
|
101
103
|
blobUrl = urlOrPathname;
|
|
102
104
|
pathname = extractPathnameFromUrl(urlOrPathname);
|
|
103
105
|
} else {
|
|
104
106
|
const storeId = getStoreIdFromToken(token);
|
|
105
107
|
if (!storeId) {
|
|
106
|
-
throw new (0,
|
|
108
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Invalid token: unable to extract store ID");
|
|
107
109
|
}
|
|
108
110
|
pathname = urlOrPathname;
|
|
109
|
-
blobUrl = constructBlobUrl(storeId, pathname);
|
|
111
|
+
blobUrl = constructBlobUrl(storeId, pathname, access);
|
|
110
112
|
}
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
const requestHeaders = {
|
|
114
|
+
...options.headers,
|
|
115
|
+
authorization: `Bearer ${token}`
|
|
114
116
|
};
|
|
115
|
-
|
|
117
|
+
let fetchUrl = blobUrl;
|
|
118
|
+
if (options.useCache === false) {
|
|
119
|
+
const url = new URL(blobUrl);
|
|
120
|
+
url.searchParams.set("cache", "0");
|
|
121
|
+
fetchUrl = url.toString();
|
|
122
|
+
}
|
|
123
|
+
const response = await _undici.fetch.call(void 0, fetchUrl, {
|
|
116
124
|
method: "GET",
|
|
117
|
-
headers,
|
|
125
|
+
headers: requestHeaders,
|
|
118
126
|
signal: options.abortSignal
|
|
119
127
|
});
|
|
120
128
|
if (!response.ok) {
|
|
121
129
|
if (response.status === 404) {
|
|
122
130
|
return null;
|
|
123
131
|
}
|
|
124
|
-
throw new (0,
|
|
132
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
125
133
|
`Failed to fetch blob: ${response.status} ${response.statusText}`
|
|
126
134
|
);
|
|
127
135
|
}
|
|
128
|
-
const contentLength = response.headers.get("content-length");
|
|
129
|
-
const size = contentLength ? parseInt(contentLength, 10) : 0;
|
|
130
136
|
const stream = response.body;
|
|
131
137
|
if (!stream) {
|
|
132
|
-
throw new (0,
|
|
138
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("Response body is null");
|
|
133
139
|
}
|
|
140
|
+
const contentLength = response.headers.get("content-length");
|
|
141
|
+
const lastModified = response.headers.get("last-modified");
|
|
142
|
+
const downloadUrl = new URL(blobUrl);
|
|
143
|
+
downloadUrl.searchParams.set("download", "1");
|
|
134
144
|
return {
|
|
135
145
|
stream,
|
|
146
|
+
headers: response.headers,
|
|
136
147
|
blob: {
|
|
137
148
|
url: blobUrl,
|
|
149
|
+
downloadUrl: downloadUrl.toString(),
|
|
138
150
|
pathname,
|
|
139
151
|
contentType: response.headers.get("content-type") || "application/octet-stream",
|
|
140
|
-
|
|
152
|
+
contentDisposition: response.headers.get("content-disposition") || "",
|
|
153
|
+
cacheControl: response.headers.get("cache-control") || "",
|
|
154
|
+
size: contentLength ? parseInt(contentLength, 10) : 0,
|
|
155
|
+
uploadedAt: lastModified ? new Date(lastModified) : /* @__PURE__ */ new Date()
|
|
141
156
|
}
|
|
142
157
|
};
|
|
143
158
|
}
|
|
@@ -158,7 +173,7 @@ async function list(options) {
|
|
|
158
173
|
if (options == null ? void 0 : options.mode) {
|
|
159
174
|
searchParams.set("mode", options.mode);
|
|
160
175
|
}
|
|
161
|
-
const response = await
|
|
176
|
+
const response = await _chunkJBMWRYVFcjs.requestApi.call(void 0,
|
|
162
177
|
`?${searchParams.toString()}`,
|
|
163
178
|
{
|
|
164
179
|
method: "GET",
|
|
@@ -193,19 +208,19 @@ function mapBlobResult(blobResult) {
|
|
|
193
208
|
// src/copy.ts
|
|
194
209
|
async function copy(fromUrlOrPathname, toPathname, options) {
|
|
195
210
|
if (!options) {
|
|
196
|
-
throw new (0,
|
|
211
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)("missing options, see usage");
|
|
197
212
|
}
|
|
198
213
|
if (options.access !== "public" && options.access !== "private") {
|
|
199
|
-
throw new (0,
|
|
214
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)('access must be "public" or "private"');
|
|
200
215
|
}
|
|
201
|
-
if (toPathname.length >
|
|
202
|
-
throw new (0,
|
|
203
|
-
`pathname is too long, maximum length is ${
|
|
216
|
+
if (toPathname.length > _chunkJBMWRYVFcjs.MAXIMUM_PATHNAME_LENGTH) {
|
|
217
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
218
|
+
`pathname is too long, maximum length is ${_chunkJBMWRYVFcjs.MAXIMUM_PATHNAME_LENGTH}`
|
|
204
219
|
);
|
|
205
220
|
}
|
|
206
|
-
for (const invalidCharacter of
|
|
221
|
+
for (const invalidCharacter of _chunkJBMWRYVFcjs.disallowedPathnameCharacters) {
|
|
207
222
|
if (toPathname.includes(invalidCharacter)) {
|
|
208
|
-
throw new (0,
|
|
223
|
+
throw new (0, _chunkJBMWRYVFcjs.BlobError)(
|
|
209
224
|
`pathname cannot contain "${invalidCharacter}", please encode it if needed`
|
|
210
225
|
);
|
|
211
226
|
}
|
|
@@ -228,7 +243,7 @@ async function copy(fromUrlOrPathname, toPathname, options) {
|
|
|
228
243
|
pathname: toPathname,
|
|
229
244
|
fromUrl: fromUrlOrPathname
|
|
230
245
|
});
|
|
231
|
-
const response = await
|
|
246
|
+
const response = await _chunkJBMWRYVFcjs.requestApi.call(void 0,
|
|
232
247
|
`?${params.toString()}`,
|
|
233
248
|
{
|
|
234
249
|
method: "PUT",
|
|
@@ -247,7 +262,7 @@ async function copy(fromUrlOrPathname, toPathname, options) {
|
|
|
247
262
|
}
|
|
248
263
|
|
|
249
264
|
// src/index.ts
|
|
250
|
-
var put =
|
|
265
|
+
var put = _chunkJBMWRYVFcjs.createPutMethod.call(void 0, {
|
|
251
266
|
allowedOptions: [
|
|
252
267
|
"cacheControlMaxAge",
|
|
253
268
|
"addRandomSuffix",
|
|
@@ -255,7 +270,7 @@ var put = _chunk7TB5OCQAcjs.createPutMethod.call(void 0, {
|
|
|
255
270
|
"contentType"
|
|
256
271
|
]
|
|
257
272
|
});
|
|
258
|
-
var createMultipartUpload =
|
|
273
|
+
var createMultipartUpload = _chunkJBMWRYVFcjs.createCreateMultipartUploadMethod.call(void 0, {
|
|
259
274
|
allowedOptions: [
|
|
260
275
|
"cacheControlMaxAge",
|
|
261
276
|
"addRandomSuffix",
|
|
@@ -263,7 +278,7 @@ var createMultipartUpload = _chunk7TB5OCQAcjs.createCreateMultipartUploadMethod.
|
|
|
263
278
|
"contentType"
|
|
264
279
|
]
|
|
265
280
|
});
|
|
266
|
-
var createMultipartUploader =
|
|
281
|
+
var createMultipartUploader = _chunkJBMWRYVFcjs.createCreateMultipartUploaderMethod.call(void 0, {
|
|
267
282
|
allowedOptions: [
|
|
268
283
|
"cacheControlMaxAge",
|
|
269
284
|
"addRandomSuffix",
|
|
@@ -271,7 +286,7 @@ var createMultipartUploader = _chunk7TB5OCQAcjs.createCreateMultipartUploaderMet
|
|
|
271
286
|
"contentType"
|
|
272
287
|
]
|
|
273
288
|
});
|
|
274
|
-
var uploadPart =
|
|
289
|
+
var uploadPart = _chunkJBMWRYVFcjs.createUploadPartMethod.call(void 0, {
|
|
275
290
|
allowedOptions: [
|
|
276
291
|
"cacheControlMaxAge",
|
|
277
292
|
"addRandomSuffix",
|
|
@@ -279,7 +294,7 @@ var uploadPart = _chunk7TB5OCQAcjs.createUploadPartMethod.call(void 0, {
|
|
|
279
294
|
"contentType"
|
|
280
295
|
]
|
|
281
296
|
});
|
|
282
|
-
var completeMultipartUpload =
|
|
297
|
+
var completeMultipartUpload = _chunkJBMWRYVFcjs.createCompleteMultipartUploadMethod.call(void 0, {
|
|
283
298
|
allowedOptions: [
|
|
284
299
|
"cacheControlMaxAge",
|
|
285
300
|
"addRandomSuffix",
|
|
@@ -313,5 +328,5 @@ var completeMultipartUpload = _chunk7TB5OCQAcjs.createCompleteMultipartUploadMet
|
|
|
313
328
|
|
|
314
329
|
|
|
315
330
|
|
|
316
|
-
exports.BlobAccessError =
|
|
331
|
+
exports.BlobAccessError = _chunkJBMWRYVFcjs.BlobAccessError; exports.BlobClientTokenExpiredError = _chunkJBMWRYVFcjs.BlobClientTokenExpiredError; exports.BlobContentTypeNotAllowedError = _chunkJBMWRYVFcjs.BlobContentTypeNotAllowedError; exports.BlobError = _chunkJBMWRYVFcjs.BlobError; exports.BlobFileTooLargeError = _chunkJBMWRYVFcjs.BlobFileTooLargeError; exports.BlobNotFoundError = _chunkJBMWRYVFcjs.BlobNotFoundError; exports.BlobPathnameMismatchError = _chunkJBMWRYVFcjs.BlobPathnameMismatchError; exports.BlobRequestAbortedError = _chunkJBMWRYVFcjs.BlobRequestAbortedError; exports.BlobServiceNotAvailable = _chunkJBMWRYVFcjs.BlobServiceNotAvailable; exports.BlobServiceRateLimited = _chunkJBMWRYVFcjs.BlobServiceRateLimited; exports.BlobStoreNotFoundError = _chunkJBMWRYVFcjs.BlobStoreNotFoundError; exports.BlobStoreSuspendedError = _chunkJBMWRYVFcjs.BlobStoreSuspendedError; exports.BlobUnknownError = _chunkJBMWRYVFcjs.BlobUnknownError; exports.completeMultipartUpload = completeMultipartUpload; exports.copy = copy; exports.createFolder = _chunkJBMWRYVFcjs.createFolder; exports.createMultipartUpload = createMultipartUpload; exports.createMultipartUploader = createMultipartUploader; exports.del = del; exports.get = get; exports.getDownloadUrl = _chunkJBMWRYVFcjs.getDownloadUrl; exports.head = head; exports.list = list; exports.put = put; exports.uploadPart = uploadPart;
|
|
317
332
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/storage/storage/packages/blob/dist/index.cjs","../src/del.ts","../src/head.ts","../src/get.ts","../src/list.ts","../src/copy.ts","../src/index.ts"],"names":[],"mappings":"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AAA;AAElB,EAAA;AACF,IAAA;AACV,EAAA;AAEY,EAAA;AACiB,IAAA;AAC7B,EAAA;AAEyB,EAAA;AACK,IAAA;AAC9B,EAAA;AAEY,EAAA;AACF,IAAA;AACV,EAAA;AAEmB,EAAA;AACP,IAAA;AACD,IAAA;AACV,EAAA;AAEsB,EAAA;AACA,IAAA;AACrB,IAAA;AACU,MAAA;AACR,MAAA;AACgB,MAAA;AAClB,IAAA;AACA,IAAA;AACF,EAAA;AAEO,EAAA;AACS,IAAA;AACQ,IAAA;AACH,IAAA;AACG,IAAA;AACF,IAAA;AACtB,EAAA;AACF;AL2JgC;AACA;AM7LsB;AACpC,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAqDC;AACkB,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAsBD;AACkB,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAwBuB;AACR,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAuBC;AACkB,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;ANyE6B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/storage/storage/packages/blob/dist/index.cjs","sourcesContent":[null,"import { requestApi } from './api';\nimport type { BlobCommandOptions } from './helpers';\n\n/**\n * Deletes one or multiple blobs from your store.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#delete-a-blob\n *\n * @param urlOrPathname - Blob url (or pathname) to delete. You can pass either a single value or an array of values. You can only delete blobs that are located in a store, that your 'BLOB_READ_WRITE_TOKEN' has access to.\n * @param options - Additional options for the request.\n */\nexport async function del(\n urlOrPathname: string[] | string,\n options?: BlobCommandOptions,\n): Promise<void> {\n await requestApi(\n '/delete',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n urls: Array.isArray(urlOrPathname) ? urlOrPathname : [urlOrPathname],\n }),\n signal: options?.abortSignal,\n },\n options,\n );\n}\n","import { requestApi } from './api';\nimport type { BlobCommandOptions } from './helpers';\n\n/**\n * Result of the head method containing metadata about a blob.\n */\nexport interface HeadBlobResult {\n /**\n * The size of the blob in bytes.\n */\n size: number;\n\n /**\n * The date when the blob was uploaded.\n */\n uploadedAt: Date;\n\n /**\n * The pathname of the blob within the store.\n */\n pathname: string;\n\n /**\n * The content type of the blob.\n */\n contentType: string;\n\n /**\n * The content disposition header value.\n */\n contentDisposition: string;\n\n /**\n * The URL of the blob.\n */\n url: string;\n\n /**\n * A URL that will cause browsers to download the file instead of displaying it inline.\n */\n downloadUrl: string;\n\n /**\n * The cache control header value.\n */\n cacheControl: string;\n}\n\ninterface HeadBlobApiResponse extends Omit<HeadBlobResult, 'uploadedAt'> {\n uploadedAt: string; // when receiving data from our API, uploadedAt is a string\n}\n\n/**\n * Fetches metadata of a blob object.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#get-blob-metadata\n *\n * @param urlOrPathname - Blob url or pathname to lookup.\n * @param options - Additional options for the request.\n */\nexport async function head(\n urlOrPathname: string,\n options?: BlobCommandOptions,\n): Promise<HeadBlobResult> {\n const searchParams = new URLSearchParams({ url: urlOrPathname });\n\n const response = await requestApi<HeadBlobApiResponse>(\n `?${searchParams.toString()}`,\n // HEAD can't have body as a response, so we use GET\n {\n method: 'GET',\n signal: options?.abortSignal,\n },\n options,\n );\n\n return {\n url: response.url,\n downloadUrl: response.downloadUrl,\n pathname: response.pathname,\n size: response.size,\n contentType: response.contentType,\n contentDisposition: response.contentDisposition,\n cacheControl: response.cacheControl,\n uploadedAt: new Date(response.uploadedAt),\n };\n}\n","import type { BlobAccessType, BlobCommandOptions } from './helpers';\nimport { BlobError, getTokenFromOptionsOrEnv } from './helpers';\n\n/**\n * Options for the get method.\n */\nexport interface GetCommandOptions extends BlobCommandOptions {\n /**\n * Whether the blob is publicly accessible or private.\n * - 'public': The blob is publicly accessible via its URL.\n * - 'private': The blob requires authentication to access.\n */\n access: BlobAccessType;\n}\n\n/**\n * Blob metadata returned by the get method.\n */\nexport interface BlobMetadata {\n /**\n * The URL of the blob.\n */\n url: string;\n\n /**\n * The pathname of the blob within the store.\n */\n pathname: string;\n\n /**\n * The content type of the blob.\n */\n contentType: string;\n\n /**\n * The size of the blob in bytes.\n */\n size: number;\n}\n\n/**\n * Result of the get method containing the stream and blob metadata.\n */\nexport interface GetBlobResult {\n /**\n * The readable stream from the fetch response.\n * This is the raw stream with no automatic buffering, allowing efficient\n * streaming of large files without loading them entirely into memory.\n */\n stream: ReadableStream<Uint8Array>;\n\n /**\n * The blob metadata object containing url, pathname, contentType, and size.\n */\n blob: BlobMetadata;\n}\n\n/**\n * Checks if the input is a URL (starts with http:// or https://).\n */\nfunction isUrl(urlOrPathname: string): boolean {\n return (\n urlOrPathname.startsWith('http://') || urlOrPathname.startsWith('https://')\n );\n}\n\n/**\n * Extracts the pathname from a blob URL.\n */\nfunction extractPathnameFromUrl(url: string): string {\n try {\n const parsedUrl = new URL(url);\n // Remove leading slash from pathname\n return parsedUrl.pathname.slice(1);\n } catch {\n return url;\n }\n}\n\n/**\n * Extracts the store ID from a blob token.\n * Token format: vercel_blob_rw_<storeId>_<rest>\n */\nfunction getStoreIdFromToken(token: string): string {\n const [, , , storeId = ''] = token.split('_');\n return storeId;\n}\n\n/**\n * Constructs the blob URL from storeId and pathname.\n */\nfunction constructBlobUrl(storeId: string, pathname: string): string {\n return `https://${storeId}.public.blob.vercel-storage.com/${pathname}`;\n}\n\n/**\n * Fetches blob content by URL or pathname.\n * - If a URL is provided, fetches the blob directly.\n * - If a pathname is provided, constructs the URL from the token's store ID.\n *\n * Returns a stream (no automatic buffering) and blob metadata.\n *\n * @example\n * ```ts\n * const { stream, blob } = await get('user123/love-letter.txt', { access: 'private' });\n * // stream is the ReadableStream from fetch() - no automatic buffering\n * // blob is the metadata object { url, pathname, contentType, size }\n * ```\n *\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk\n *\n * @param urlOrPathname - The URL or pathname of the blob to fetch.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Determines the access level of the blob.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to { stream, blob } or null if not found.\n */\nexport async function get(\n urlOrPathname: string,\n options: GetCommandOptions,\n): Promise<GetBlobResult | null> {\n if (!urlOrPathname) {\n throw new BlobError('url or pathname is required');\n }\n\n if (!options) {\n throw new BlobError('missing options, see usage');\n }\n\n if (options.access !== 'public' && options.access !== 'private') {\n throw new BlobError('access must be \"public\" or \"private\"');\n }\n\n const token = getTokenFromOptionsOrEnv(options);\n\n let blobUrl: string;\n let pathname: string;\n\n // Check if input is a URL or a pathname\n if (isUrl(urlOrPathname)) {\n blobUrl = urlOrPathname;\n pathname = extractPathnameFromUrl(urlOrPathname);\n } else {\n // Construct the URL from the token's storeId and the pathname\n const storeId = getStoreIdFromToken(token);\n if (!storeId) {\n throw new BlobError('Invalid token: unable to extract store ID');\n }\n pathname = urlOrPathname;\n blobUrl = constructBlobUrl(storeId, pathname);\n }\n\n // Fetch the blob content with authentication headers\n const headers: Record<string, string> = {\n authorization: `Bearer ${token}`,\n 'x-vercel-blob-access': options.access,\n };\n\n const response = await fetch(blobUrl, {\n method: 'GET',\n headers,\n signal: options.abortSignal,\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n return null;\n }\n throw new BlobError(\n `Failed to fetch blob: ${response.status} ${response.statusText}`,\n );\n }\n\n // Get size from content-length header\n const contentLength = response.headers.get('content-length');\n const size = contentLength ? parseInt(contentLength, 10) : 0;\n\n // Return the stream directly without buffering\n const stream = response.body;\n if (!stream) {\n throw new BlobError('Response body is null');\n }\n\n return {\n stream,\n blob: {\n url: blobUrl,\n pathname,\n contentType:\n response.headers.get('content-type') || 'application/octet-stream',\n size,\n },\n };\n}\n","import { requestApi } from './api';\nimport type { BlobCommandOptions } from './helpers';\n\n/**\n * Basic blob object information returned by the list method.\n */\nexport interface ListBlobResultBlob {\n /**\n * The URL of the blob.\n */\n url: string;\n\n /**\n * A URL that will cause browsers to download the file instead of displaying it inline.\n */\n downloadUrl: string;\n\n /**\n * The pathname of the blob within the store.\n */\n pathname: string;\n\n /**\n * The size of the blob in bytes.\n */\n size: number;\n\n /**\n * The date when the blob was uploaded.\n */\n uploadedAt: Date;\n}\n\n/**\n * Result of the list method in expanded mode (default).\n */\nexport interface ListBlobResult {\n /**\n * Array of blob objects in the store.\n */\n blobs: ListBlobResultBlob[];\n\n /**\n * Pagination cursor for the next set of results, if hasMore is true.\n */\n cursor?: string;\n\n /**\n * Indicates if there are more results available.\n */\n hasMore: boolean;\n}\n\n/**\n * Result of the list method in folded mode.\n */\nexport interface ListFoldedBlobResult extends ListBlobResult {\n /**\n * Array of folder paths in the store.\n */\n folders: string[];\n}\n\n/**\n * @internal Internal interface for the API response blob structure.\n * Maps the API response format where uploadedAt is a string, not a Date.\n */\ninterface ListBlobApiResponseBlob\n extends Omit<ListBlobResultBlob, 'uploadedAt'> {\n uploadedAt: string;\n}\n\n/**\n * @internal Internal interface for the API response structure.\n */\ninterface ListBlobApiResponse extends Omit<ListBlobResult, 'blobs'> {\n blobs: ListBlobApiResponseBlob[];\n folders?: string[];\n}\n\n/**\n * Options for the list method.\n */\nexport interface ListCommandOptions<\n M extends 'expanded' | 'folded' | undefined = undefined,\n> extends BlobCommandOptions {\n /**\n * The maximum number of blobs to return.\n * @defaultvalue 1000\n */\n limit?: number;\n\n /**\n * Filters the result to only include blobs that start with this prefix.\n * If used together with `mode: 'folded'`, make sure to include a trailing slash after the foldername.\n */\n prefix?: string;\n\n /**\n * The cursor to use for pagination. Can be obtained from the response of a previous `list` request.\n */\n cursor?: string;\n\n /**\n * Defines how the blobs are listed\n * - `expanded` the blobs property contains all blobs.\n * - `folded` the blobs property contains only the blobs at the root level of your store. Blobs that are located inside a folder get merged into a single entry in the folder response property.\n * @defaultvalue 'expanded'\n */\n mode?: M;\n}\n\n/**\n * @internal Type helper to determine the return type based on the mode parameter.\n */\ntype ListCommandResult<\n M extends 'expanded' | 'folded' | undefined = undefined,\n> = M extends 'folded' ? ListFoldedBlobResult : ListBlobResult;\n\n/**\n * Fetches a paginated list of blob objects from your store.\n *\n * @param options - Configuration options including:\n * - token - (Optional) A string specifying the read-write token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - limit - (Optional) The maximum number of blobs to return. Defaults to 1000.\n * - prefix - (Optional) Filters the result to only include blobs that start with this prefix. If used with mode: 'folded', include a trailing slash after the folder name.\n * - cursor - (Optional) The cursor to use for pagination. Can be obtained from the response of a previous list request.\n * - mode - (Optional) Defines how the blobs are listed. Can be 'expanded' (default) or 'folded'. In folded mode, blobs located inside a folder are merged into a single entry in the folders response property.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to an object containing:\n * - blobs: An array of blob objects with size, uploadedAt, pathname, url, and downloadUrl properties\n * - cursor: A string for pagination (if hasMore is true)\n * - hasMore: A boolean indicating if there are more results available\n * - folders: (Only in 'folded' mode) An array of folder paths\n */\nexport async function list<\n M extends 'expanded' | 'folded' | undefined = undefined,\n>(options?: ListCommandOptions<M>): Promise<ListCommandResult<M>> {\n const searchParams = new URLSearchParams();\n\n if (options?.limit) {\n searchParams.set('limit', options.limit.toString());\n }\n if (options?.prefix) {\n searchParams.set('prefix', options.prefix);\n }\n if (options?.cursor) {\n searchParams.set('cursor', options.cursor);\n }\n if (options?.mode) {\n searchParams.set('mode', options.mode);\n }\n\n const response = await requestApi<ListBlobApiResponse>(\n `?${searchParams.toString()}`,\n {\n method: 'GET',\n signal: options?.abortSignal,\n },\n options,\n );\n\n if (options?.mode === 'folded') {\n return {\n folders: response.folders ?? [],\n cursor: response.cursor,\n hasMore: response.hasMore,\n blobs: response.blobs.map(mapBlobResult),\n } as ListCommandResult<M>;\n }\n\n return {\n cursor: response.cursor,\n hasMore: response.hasMore,\n blobs: response.blobs.map(mapBlobResult),\n } as ListCommandResult<M>;\n}\n\n/**\n * @internal Helper function to map API response blob format to the expected return type.\n * Converts the uploadedAt string into a Date object.\n */\nfunction mapBlobResult(\n blobResult: ListBlobApiResponseBlob,\n): ListBlobResultBlob {\n return {\n url: blobResult.url,\n downloadUrl: blobResult.downloadUrl,\n pathname: blobResult.pathname,\n size: blobResult.size,\n uploadedAt: new Date(blobResult.uploadedAt),\n };\n}\n","import { MAXIMUM_PATHNAME_LENGTH, requestApi } from './api';\nimport type { CommonCreateBlobOptions } from './helpers';\nimport { BlobError, disallowedPathnameCharacters } from './helpers';\n\nexport type CopyCommandOptions = CommonCreateBlobOptions;\n\nexport interface CopyBlobResult {\n url: string;\n downloadUrl: string;\n pathname: string;\n contentType: string;\n contentDisposition: string;\n}\n\n/**\n * Copies a blob to another location in your store.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#copy-a-blob\n *\n * @param fromUrlOrPathname - The blob URL (or pathname) to copy. You can only copy blobs that are in the store, that your 'BLOB_READ_WRITE_TOKEN' has access to.\n * @param toPathname - The pathname to copy the blob to. This includes the filename.\n * @param options - Additional options. The copy method will not preserve any metadata configuration (e.g.: 'cacheControlMaxAge') of the source blob. If you want to copy the metadata, you need to define it here again.\n */\nexport async function copy(\n fromUrlOrPathname: string,\n toPathname: string,\n options: CopyCommandOptions,\n): Promise<CopyBlobResult> {\n if (!options) {\n throw new BlobError('missing options, see usage');\n }\n\n if (options.access !== 'public' && options.access !== 'private') {\n throw new BlobError('access must be \"public\" or \"private\"');\n }\n\n if (toPathname.length > MAXIMUM_PATHNAME_LENGTH) {\n throw new BlobError(\n `pathname is too long, maximum length is ${MAXIMUM_PATHNAME_LENGTH}`,\n );\n }\n\n for (const invalidCharacter of disallowedPathnameCharacters) {\n if (toPathname.includes(invalidCharacter)) {\n throw new BlobError(\n `pathname cannot contain \"${invalidCharacter}\", please encode it if needed`,\n );\n }\n }\n\n const headers: Record<string, string> = {};\n\n // access is always required, so always add it to headers\n headers['x-vercel-blob-access'] = options.access;\n\n if (options.addRandomSuffix !== undefined) {\n headers['x-add-random-suffix'] = options.addRandomSuffix ? '1' : '0';\n }\n\n if (options.allowOverwrite !== undefined) {\n headers['x-allow-overwrite'] = options.allowOverwrite ? '1' : '0';\n }\n\n if (options.contentType) {\n headers['x-content-type'] = options.contentType;\n }\n\n if (options.cacheControlMaxAge !== undefined) {\n headers['x-cache-control-max-age'] = options.cacheControlMaxAge.toString();\n }\n\n const params = new URLSearchParams({\n pathname: toPathname,\n fromUrl: fromUrlOrPathname,\n });\n\n const response = await requestApi<CopyBlobResult>(\n `?${params.toString()}`,\n {\n method: 'PUT',\n headers,\n signal: options.abortSignal,\n },\n options,\n );\n\n return {\n url: response.url,\n downloadUrl: response.downloadUrl,\n pathname: response.pathname,\n contentType: response.contentType,\n contentDisposition: response.contentDisposition,\n };\n}\n","import type { CommonCreateBlobOptions } from './helpers';\nimport type { CompleteMultipartUploadCommandOptions } from './multipart/complete';\nimport { createCompleteMultipartUploadMethod } from './multipart/complete';\nimport { createCreateMultipartUploadMethod } from './multipart/create';\nimport { createCreateMultipartUploaderMethod } from './multipart/create-uploader';\nimport type { UploadPartCommandOptions } from './multipart/upload';\nimport { createUploadPartMethod } from './multipart/upload';\nimport type { PutCommandOptions } from './put';\nimport { createPutMethod } from './put';\n\n// expose api BlobErrors\nexport {\n BlobAccessError,\n BlobClientTokenExpiredError,\n BlobContentTypeNotAllowedError,\n BlobFileTooLargeError,\n BlobNotFoundError,\n BlobPathnameMismatchError,\n BlobRequestAbortedError,\n BlobServiceNotAvailable,\n BlobServiceRateLimited,\n BlobStoreNotFoundError,\n BlobStoreSuspendedError,\n BlobUnknownError,\n} from './api';\n// expose generic BlobError and download url util\nexport {\n type BlobAccessType,\n BlobError,\n getDownloadUrl,\n type OnUploadProgressCallback,\n type UploadProgressEvent,\n} from './helpers';\n\n// vercelBlob.put()\n\nexport type { PutBlobResult } from './put-helpers';\nexport type { PutCommandOptions };\n\n/**\n * Uploads a blob into your store from your server.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#upload-a-blob\n *\n * If you want to upload from the browser directly, or if you're hitting Vercel upload limits, check out the documentation for client uploads: https://vercel.com/docs/vercel-blob/using-blob-sdk#client-uploads\n *\n * @param pathname - The pathname to upload the blob to, including the extension. This will influence the URL of your blob like https://$storeId.public.blob.vercel-storage.com/$pathname.\n * @param body - The content of your blob, can be a: string, File, Blob, Buffer or Stream. We support almost everything fetch supports: https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#body.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to false. We recommend using this option to ensure there are no conflicts in your blob filenames.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs. By default an error will be thrown if you try to overwrite a blob by using the same pathname for multiple blobs.\n * - contentType - (Optional) A string indicating the media type. By default, it's extracted from the pathname's extension.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure how long Blobs are cached. Defaults to one month. Cannot be set to a value lower than 1 minute.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - multipart - (Optional) Whether to use multipart upload for large files. It will split the file into multiple parts, upload them in parallel and retry failed parts.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * - onUploadProgress - (Optional) Callback to track upload progress: onUploadProgress(\\{loaded: number, total: number, percentage: number\\})\n * @returns A promise that resolves to the blob information, including pathname, contentType, contentDisposition, url, and downloadUrl.\n */\nexport const put = createPutMethod<PutCommandOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n});\n\n// vercelBlob.del()\n\nexport { del } from './del';\n\n// vercelBlob.head()\n\nexport type { HeadBlobResult } from './head';\nexport { head } from './head';\n\n// vercelBlob.get()\n\nexport type { BlobMetadata, GetBlobResult, GetCommandOptions } from './get';\nexport { get } from './get';\n\n// vercelBlob.list()\n\nexport type {\n ListBlobResult,\n ListBlobResultBlob,\n ListCommandOptions,\n ListFoldedBlobResult,\n} from './list';\nexport { list } from './list';\n\n// vercelBlob.copy()\n\nexport type { CopyBlobResult, CopyCommandOptions } from './copy';\nexport { copy } from './copy';\n\n// vercelBlob. createMultipartUpload()\n// vercelBlob. uploadPart()\n// vercelBlob. completeMultipartUpload()\n// vercelBlob. createMultipartUploader()\n\n/**\n * Creates a multipart upload. This is the first step in the manual multipart upload process.\n *\n * @param pathname - A string specifying the path inside the blob store. This will be the base value of the return URL and includes the filename and extension.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to true.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs. By default an error will be thrown if you try to overwrite a blob by using the same pathname for multiple blobs.\n * - contentType - (Optional) The media type for the file. If not specified, it's derived from the file extension. Falls back to application/octet-stream when no extension exists or can't be matched.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure the edge and browser cache. Defaults to one year.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to an object containing:\n * - key: A string that identifies the blob object.\n * - uploadId: A string that identifies the multipart upload. Both are needed for subsequent uploadPart calls.\n */\nexport const createMultipartUpload =\n createCreateMultipartUploadMethod<CommonCreateBlobOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n });\n\n/**\n * Creates a multipart uploader that simplifies the multipart upload process.\n * This is a wrapper around the manual multipart upload process that provides a more convenient API.\n *\n * @param pathname - A string specifying the path inside the blob store. This will be the base value of the return URL and includes the filename and extension.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to true.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs. By default an error will be thrown if you try to overwrite a blob by using the same pathname for multiple blobs.\n * - contentType - (Optional) The media type for the file. If not specified, it's derived from the file extension. Falls back to application/octet-stream when no extension exists or can't be matched.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure the edge and browser cache. Defaults to one year.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to an uploader object with the following properties and methods:\n * - key: A string that identifies the blob object.\n * - uploadId: A string that identifies the multipart upload.\n * - uploadPart: A method to upload a part of the file.\n * - complete: A method to complete the multipart upload process.\n */\nexport const createMultipartUploader =\n createCreateMultipartUploaderMethod<CommonCreateBlobOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n });\n\nexport type { UploadPartCommandOptions };\n\n/**\n * Uploads a part of a multipart upload.\n * Used as part of the manual multipart upload process.\n *\n * @param pathname - Same value as the pathname parameter passed to createMultipartUpload. This will influence the final URL of your blob.\n * @param body - A blob object as ReadableStream, String, ArrayBuffer or Blob based on these supported body types. Each part must be a minimum of 5MB, except the last one which can be smaller.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - uploadId - (Required) A string returned from createMultipartUpload which identifies the multipart upload.\n * - key - (Required) A string returned from createMultipartUpload which identifies the blob object.\n * - partNumber - (Required) A number identifying which part is uploaded (1-based index).\n * - contentType - (Optional) The media type for the blob. By default, it's derived from the pathname.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure how long Blobs are cached.\n * - abortSignal - (Optional) AbortSignal to cancel the running request.\n * - onUploadProgress - (Optional) Callback to track upload progress: onUploadProgress(\\{loaded: number, total: number, percentage: number\\})\n * @returns A promise that resolves to the uploaded part information containing etag and partNumber, which will be needed for the completeMultipartUpload call.\n */\nexport const uploadPart = createUploadPartMethod<UploadPartCommandOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n});\n\nexport type { CompleteMultipartUploadCommandOptions };\n\n/**\n * Completes a multipart upload by combining all uploaded parts.\n * This is the final step in the manual multipart upload process.\n *\n * @param pathname - Same value as the pathname parameter passed to createMultipartUpload.\n * @param parts - An array containing all the uploaded parts information from previous uploadPart calls. Each part must have properties etag and partNumber.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - uploadId - (Required) A string returned from createMultipartUpload which identifies the multipart upload.\n * - key - (Required) A string returned from createMultipartUpload which identifies the blob object.\n * - contentType - (Optional) The media type for the file. If not specified, it's derived from the file extension.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to true.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure the edge and browser cache. Defaults to one year.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to the finalized blob information, including pathname, contentType, contentDisposition, url, and downloadUrl.\n */\nexport const completeMultipartUpload =\n createCompleteMultipartUploadMethod<CompleteMultipartUploadCommandOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n });\n\nexport { createFolder } from './create-folder';\nexport type { Part, PartInput } from './multipart/helpers';\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/storage/storage/packages/blob/dist/index.cjs","../src/del.ts","../src/head.ts","../src/get.ts","../src/list.ts","../src/copy.ts","../src/index.ts"],"names":[],"mappings":"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IAAA;AACtB,EAAA;AAEwB,EAAA;AACZ,IAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AAEW,EAAA;AACe,IAAA;AACZ,MAAA;AACR,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AAEyC,EAAA;AAGX,EAAA;AAElB,EAAA;AACF,IAAA;AACV,EAAA;AAEY,EAAA;AACiB,IAAA;AAC7B,EAAA;AAEyB,EAAA;AACK,IAAA;AAC9B,EAAA;AAEY,EAAA;AACF,IAAA;AACV,EAAA;AAEmB,EAAA;AACP,IAAA;AACD,IAAA;AACV,EAAA;AAEsB,EAAA;AACA,IAAA;AACrB,IAAA;AACU,MAAA;AACR,MAAA;AACgB,MAAA;AAClB,IAAA;AACA,IAAA;AACF,EAAA;AAEO,EAAA;AACS,IAAA;AACQ,IAAA;AACH,IAAA;AACG,IAAA;AACF,IAAA;AACtB,EAAA;AACF;AL0KgC;AACA;AM5MsB;AACpC,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAqDC;AACkB,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAsBD;AACkB,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAwBuB;AACR,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;AAuBC;AACkB,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACD;ANwF6B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/storage/storage/packages/blob/dist/index.cjs","sourcesContent":[null,"import { requestApi } from './api';\nimport type { BlobCommandOptions } from './helpers';\n\n/**\n * Deletes one or multiple blobs from your store.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#delete-a-blob\n *\n * @param urlOrPathname - Blob url (or pathname) to delete. You can pass either a single value or an array of values. You can only delete blobs that are located in a store, that your 'BLOB_READ_WRITE_TOKEN' has access to.\n * @param options - Additional options for the request.\n */\nexport async function del(\n urlOrPathname: string[] | string,\n options?: BlobCommandOptions,\n): Promise<void> {\n await requestApi(\n '/delete',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n urls: Array.isArray(urlOrPathname) ? urlOrPathname : [urlOrPathname],\n }),\n signal: options?.abortSignal,\n },\n options,\n );\n}\n","import { requestApi } from './api';\nimport type { BlobCommandOptions } from './helpers';\n\n/**\n * Result of the head method containing metadata about a blob.\n */\nexport interface HeadBlobResult {\n /**\n * The size of the blob in bytes.\n */\n size: number;\n\n /**\n * The date when the blob was uploaded.\n */\n uploadedAt: Date;\n\n /**\n * The pathname of the blob within the store.\n */\n pathname: string;\n\n /**\n * The content type of the blob.\n */\n contentType: string;\n\n /**\n * The content disposition header value.\n */\n contentDisposition: string;\n\n /**\n * The URL of the blob.\n */\n url: string;\n\n /**\n * A URL that will cause browsers to download the file instead of displaying it inline.\n */\n downloadUrl: string;\n\n /**\n * The cache control header value.\n */\n cacheControl: string;\n}\n\ninterface HeadBlobApiResponse extends Omit<HeadBlobResult, 'uploadedAt'> {\n uploadedAt: string; // when receiving data from our API, uploadedAt is a string\n}\n\n/**\n * Fetches metadata of a blob object.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#get-blob-metadata\n *\n * @param urlOrPathname - Blob url or pathname to lookup.\n * @param options - Additional options for the request.\n */\nexport async function head(\n urlOrPathname: string,\n options?: BlobCommandOptions,\n): Promise<HeadBlobResult> {\n const searchParams = new URLSearchParams({ url: urlOrPathname });\n\n const response = await requestApi<HeadBlobApiResponse>(\n `?${searchParams.toString()}`,\n // HEAD can't have body as a response, so we use GET\n {\n method: 'GET',\n signal: options?.abortSignal,\n },\n options,\n );\n\n return {\n url: response.url,\n downloadUrl: response.downloadUrl,\n pathname: response.pathname,\n size: response.size,\n contentType: response.contentType,\n contentDisposition: response.contentDisposition,\n cacheControl: response.cacheControl,\n uploadedAt: new Date(response.uploadedAt),\n };\n}\n","import { fetch, type Headers } from 'undici';\nimport type { HeadBlobResult } from './head';\nimport type { BlobAccessType, BlobCommandOptions } from './helpers';\nimport { BlobError, getTokenFromOptionsOrEnv } from './helpers';\n\n/**\n * Options for the get method.\n */\nexport interface GetCommandOptions extends BlobCommandOptions {\n /**\n * Whether the blob is publicly accessible or private.\n * - 'public': The blob is publicly accessible via its URL.\n * - 'private': The blob requires authentication to access.\n */\n access: BlobAccessType;\n /**\n * Whether to allow the blob to be served from CDN cache.\n * When false, fetches directly from origin storage.\n * Only effective for private blobs (ignored for public blobs).\n * @defaultValue true\n */\n useCache?: boolean;\n /**\n * Advanced: Additional headers to include in the fetch request.\n * You probably don't need this. The authorization header is automatically set.\n */\n headers?: HeadersInit;\n}\n\n/**\n * Result of the get method containing the stream and blob metadata.\n */\nexport interface GetBlobResult {\n /**\n * The readable stream from the fetch response.\n * This is the raw stream with no automatic buffering, allowing efficient\n * streaming of large files without loading them entirely into memory.\n */\n stream: ReadableStream<Uint8Array>;\n\n /**\n * The raw headers from the fetch response.\n * Useful for accessing additional response metadata like ETag, x-vercel-* headers, etc.\n */\n headers: Headers;\n\n /**\n * The blob metadata object containing url, pathname, contentType, size,\n * downloadUrl, contentDisposition, cacheControl, and uploadedAt.\n */\n blob: HeadBlobResult;\n}\n\n/**\n * Checks if the input is a URL (starts with http:// or https://).\n */\nfunction isUrl(urlOrPathname: string): boolean {\n return (\n urlOrPathname.startsWith('http://') || urlOrPathname.startsWith('https://')\n );\n}\n\n/**\n * Extracts the pathname from a blob URL.\n */\nfunction extractPathnameFromUrl(url: string): string {\n try {\n const parsedUrl = new URL(url);\n // Remove leading slash from pathname\n return parsedUrl.pathname.slice(1);\n } catch {\n return url;\n }\n}\n\n/**\n * Extracts the store ID from a blob token.\n * Token format: vercel_blob_rw_<storeId>_<rest>\n */\nfunction getStoreIdFromToken(token: string): string {\n const [, , , storeId = ''] = token.split('_');\n return storeId;\n}\n\n/**\n * Constructs the blob URL from storeId and pathname.\n */\nfunction constructBlobUrl(\n storeId: string,\n pathname: string,\n access: BlobAccessType,\n): string {\n return `https://${storeId}.${access}.blob.vercel-storage.com/${pathname}`;\n}\n\n/**\n * Fetches blob content by URL or pathname.\n * - If a URL is provided, fetches the blob directly.\n * - If a pathname is provided, constructs the URL from the token's store ID.\n *\n * Returns a stream (no automatic buffering) and blob metadata.\n *\n * @example\n * ```ts\n * // Basic usage\n * const { stream, headers, blob } = await get('user123/avatar.png', { access: 'private' });\n *\n * // Bypass cache for private blobs (always fetch fresh from storage)\n * const { stream, headers, blob } = await get('user123/data.json', { access: 'private', useCache: false });\n * ```\n *\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk\n *\n * @param urlOrPathname - The URL or pathname of the blob to fetch.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Determines the access level of the blob.\n * - useCache - (Optional) When false, fetches directly from origin storage instead of CDN cache. Only effective for private blobs. Defaults to true.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * - headers - (Optional, advanced) Additional headers to include in the fetch request. You probably don't need this.\n * @returns A promise that resolves to { stream, blob } or null if not found.\n */\nexport async function get(\n urlOrPathname: string,\n options: GetCommandOptions,\n): Promise<GetBlobResult | null> {\n if (!urlOrPathname) {\n throw new BlobError('url or pathname is required');\n }\n\n if (!options) {\n throw new BlobError('missing options, see usage');\n }\n\n if (options.access !== 'public' && options.access !== 'private') {\n throw new BlobError('access must be \"public\" or \"private\"');\n }\n\n const token = getTokenFromOptionsOrEnv(options);\n\n let blobUrl: string;\n let pathname: string;\n const access = options.access;\n\n // Check if input is a URL or a pathname\n if (isUrl(urlOrPathname)) {\n blobUrl = urlOrPathname;\n pathname = extractPathnameFromUrl(urlOrPathname);\n } else {\n // Construct the URL from the token's storeId and the pathname\n const storeId = getStoreIdFromToken(token);\n if (!storeId) {\n throw new BlobError('Invalid token: unable to extract store ID');\n }\n pathname = urlOrPathname;\n blobUrl = constructBlobUrl(storeId, pathname, access);\n }\n\n // Fetch the blob content with authentication headers\n const requestHeaders: HeadersInit = {\n ...options.headers,\n authorization: `Bearer ${token}`,\n };\n\n // Construct fetch URL with optional cache bypass\n let fetchUrl = blobUrl;\n if (options.useCache === false) {\n const url = new URL(blobUrl);\n url.searchParams.set('cache', '0');\n fetchUrl = url.toString();\n }\n\n const response = await fetch(fetchUrl, {\n method: 'GET',\n headers: requestHeaders,\n signal: options.abortSignal,\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n return null;\n }\n throw new BlobError(\n `Failed to fetch blob: ${response.status} ${response.statusText}`,\n );\n }\n\n // Return the stream directly without buffering\n const stream = response.body as ReadableStream;\n if (!stream) {\n throw new BlobError('Response body is null');\n }\n\n // Extract metadata from response headers\n const contentLength = response.headers.get('content-length');\n const lastModified = response.headers.get('last-modified');\n\n // Build download URL by adding download=1 query param\n const downloadUrl = new URL(blobUrl);\n downloadUrl.searchParams.set('download', '1');\n\n return {\n stream,\n headers: response.headers,\n blob: {\n url: blobUrl,\n downloadUrl: downloadUrl.toString(),\n pathname,\n contentType:\n response.headers.get('content-type') || 'application/octet-stream',\n contentDisposition: response.headers.get('content-disposition') || '',\n cacheControl: response.headers.get('cache-control') || '',\n size: contentLength ? parseInt(contentLength, 10) : 0,\n uploadedAt: lastModified ? new Date(lastModified) : new Date(),\n },\n };\n}\n","import { requestApi } from './api';\nimport type { BlobCommandOptions } from './helpers';\n\n/**\n * Basic blob object information returned by the list method.\n */\nexport interface ListBlobResultBlob {\n /**\n * The URL of the blob.\n */\n url: string;\n\n /**\n * A URL that will cause browsers to download the file instead of displaying it inline.\n */\n downloadUrl: string;\n\n /**\n * The pathname of the blob within the store.\n */\n pathname: string;\n\n /**\n * The size of the blob in bytes.\n */\n size: number;\n\n /**\n * The date when the blob was uploaded.\n */\n uploadedAt: Date;\n}\n\n/**\n * Result of the list method in expanded mode (default).\n */\nexport interface ListBlobResult {\n /**\n * Array of blob objects in the store.\n */\n blobs: ListBlobResultBlob[];\n\n /**\n * Pagination cursor for the next set of results, if hasMore is true.\n */\n cursor?: string;\n\n /**\n * Indicates if there are more results available.\n */\n hasMore: boolean;\n}\n\n/**\n * Result of the list method in folded mode.\n */\nexport interface ListFoldedBlobResult extends ListBlobResult {\n /**\n * Array of folder paths in the store.\n */\n folders: string[];\n}\n\n/**\n * @internal Internal interface for the API response blob structure.\n * Maps the API response format where uploadedAt is a string, not a Date.\n */\ninterface ListBlobApiResponseBlob\n extends Omit<ListBlobResultBlob, 'uploadedAt'> {\n uploadedAt: string;\n}\n\n/**\n * @internal Internal interface for the API response structure.\n */\ninterface ListBlobApiResponse extends Omit<ListBlobResult, 'blobs'> {\n blobs: ListBlobApiResponseBlob[];\n folders?: string[];\n}\n\n/**\n * Options for the list method.\n */\nexport interface ListCommandOptions<\n M extends 'expanded' | 'folded' | undefined = undefined,\n> extends BlobCommandOptions {\n /**\n * The maximum number of blobs to return.\n * @defaultvalue 1000\n */\n limit?: number;\n\n /**\n * Filters the result to only include blobs that start with this prefix.\n * If used together with `mode: 'folded'`, make sure to include a trailing slash after the foldername.\n */\n prefix?: string;\n\n /**\n * The cursor to use for pagination. Can be obtained from the response of a previous `list` request.\n */\n cursor?: string;\n\n /**\n * Defines how the blobs are listed\n * - `expanded` the blobs property contains all blobs.\n * - `folded` the blobs property contains only the blobs at the root level of your store. Blobs that are located inside a folder get merged into a single entry in the folder response property.\n * @defaultvalue 'expanded'\n */\n mode?: M;\n}\n\n/**\n * @internal Type helper to determine the return type based on the mode parameter.\n */\ntype ListCommandResult<\n M extends 'expanded' | 'folded' | undefined = undefined,\n> = M extends 'folded' ? ListFoldedBlobResult : ListBlobResult;\n\n/**\n * Fetches a paginated list of blob objects from your store.\n *\n * @param options - Configuration options including:\n * - token - (Optional) A string specifying the read-write token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - limit - (Optional) The maximum number of blobs to return. Defaults to 1000.\n * - prefix - (Optional) Filters the result to only include blobs that start with this prefix. If used with mode: 'folded', include a trailing slash after the folder name.\n * - cursor - (Optional) The cursor to use for pagination. Can be obtained from the response of a previous list request.\n * - mode - (Optional) Defines how the blobs are listed. Can be 'expanded' (default) or 'folded'. In folded mode, blobs located inside a folder are merged into a single entry in the folders response property.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to an object containing:\n * - blobs: An array of blob objects with size, uploadedAt, pathname, url, and downloadUrl properties\n * - cursor: A string for pagination (if hasMore is true)\n * - hasMore: A boolean indicating if there are more results available\n * - folders: (Only in 'folded' mode) An array of folder paths\n */\nexport async function list<\n M extends 'expanded' | 'folded' | undefined = undefined,\n>(options?: ListCommandOptions<M>): Promise<ListCommandResult<M>> {\n const searchParams = new URLSearchParams();\n\n if (options?.limit) {\n searchParams.set('limit', options.limit.toString());\n }\n if (options?.prefix) {\n searchParams.set('prefix', options.prefix);\n }\n if (options?.cursor) {\n searchParams.set('cursor', options.cursor);\n }\n if (options?.mode) {\n searchParams.set('mode', options.mode);\n }\n\n const response = await requestApi<ListBlobApiResponse>(\n `?${searchParams.toString()}`,\n {\n method: 'GET',\n signal: options?.abortSignal,\n },\n options,\n );\n\n if (options?.mode === 'folded') {\n return {\n folders: response.folders ?? [],\n cursor: response.cursor,\n hasMore: response.hasMore,\n blobs: response.blobs.map(mapBlobResult),\n } as ListCommandResult<M>;\n }\n\n return {\n cursor: response.cursor,\n hasMore: response.hasMore,\n blobs: response.blobs.map(mapBlobResult),\n } as ListCommandResult<M>;\n}\n\n/**\n * @internal Helper function to map API response blob format to the expected return type.\n * Converts the uploadedAt string into a Date object.\n */\nfunction mapBlobResult(\n blobResult: ListBlobApiResponseBlob,\n): ListBlobResultBlob {\n return {\n url: blobResult.url,\n downloadUrl: blobResult.downloadUrl,\n pathname: blobResult.pathname,\n size: blobResult.size,\n uploadedAt: new Date(blobResult.uploadedAt),\n };\n}\n","import { MAXIMUM_PATHNAME_LENGTH, requestApi } from './api';\nimport type { CommonCreateBlobOptions } from './helpers';\nimport { BlobError, disallowedPathnameCharacters } from './helpers';\n\nexport type CopyCommandOptions = CommonCreateBlobOptions;\n\nexport interface CopyBlobResult {\n url: string;\n downloadUrl: string;\n pathname: string;\n contentType: string;\n contentDisposition: string;\n}\n\n/**\n * Copies a blob to another location in your store.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#copy-a-blob\n *\n * @param fromUrlOrPathname - The blob URL (or pathname) to copy. You can only copy blobs that are in the store, that your 'BLOB_READ_WRITE_TOKEN' has access to.\n * @param toPathname - The pathname to copy the blob to. This includes the filename.\n * @param options - Additional options. The copy method will not preserve any metadata configuration (e.g.: 'cacheControlMaxAge') of the source blob. If you want to copy the metadata, you need to define it here again.\n */\nexport async function copy(\n fromUrlOrPathname: string,\n toPathname: string,\n options: CopyCommandOptions,\n): Promise<CopyBlobResult> {\n if (!options) {\n throw new BlobError('missing options, see usage');\n }\n\n if (options.access !== 'public' && options.access !== 'private') {\n throw new BlobError('access must be \"public\" or \"private\"');\n }\n\n if (toPathname.length > MAXIMUM_PATHNAME_LENGTH) {\n throw new BlobError(\n `pathname is too long, maximum length is ${MAXIMUM_PATHNAME_LENGTH}`,\n );\n }\n\n for (const invalidCharacter of disallowedPathnameCharacters) {\n if (toPathname.includes(invalidCharacter)) {\n throw new BlobError(\n `pathname cannot contain \"${invalidCharacter}\", please encode it if needed`,\n );\n }\n }\n\n const headers: Record<string, string> = {};\n\n // access is always required, so always add it to headers\n headers['x-vercel-blob-access'] = options.access;\n\n if (options.addRandomSuffix !== undefined) {\n headers['x-add-random-suffix'] = options.addRandomSuffix ? '1' : '0';\n }\n\n if (options.allowOverwrite !== undefined) {\n headers['x-allow-overwrite'] = options.allowOverwrite ? '1' : '0';\n }\n\n if (options.contentType) {\n headers['x-content-type'] = options.contentType;\n }\n\n if (options.cacheControlMaxAge !== undefined) {\n headers['x-cache-control-max-age'] = options.cacheControlMaxAge.toString();\n }\n\n const params = new URLSearchParams({\n pathname: toPathname,\n fromUrl: fromUrlOrPathname,\n });\n\n const response = await requestApi<CopyBlobResult>(\n `?${params.toString()}`,\n {\n method: 'PUT',\n headers,\n signal: options.abortSignal,\n },\n options,\n );\n\n return {\n url: response.url,\n downloadUrl: response.downloadUrl,\n pathname: response.pathname,\n contentType: response.contentType,\n contentDisposition: response.contentDisposition,\n };\n}\n","import type { CommonCreateBlobOptions } from './helpers';\nimport type { CompleteMultipartUploadCommandOptions } from './multipart/complete';\nimport { createCompleteMultipartUploadMethod } from './multipart/complete';\nimport { createCreateMultipartUploadMethod } from './multipart/create';\nimport { createCreateMultipartUploaderMethod } from './multipart/create-uploader';\nimport type { UploadPartCommandOptions } from './multipart/upload';\nimport { createUploadPartMethod } from './multipart/upload';\nimport type { PutCommandOptions } from './put';\nimport { createPutMethod } from './put';\n\n// expose api BlobErrors\nexport {\n BlobAccessError,\n BlobClientTokenExpiredError,\n BlobContentTypeNotAllowedError,\n BlobFileTooLargeError,\n BlobNotFoundError,\n BlobPathnameMismatchError,\n BlobRequestAbortedError,\n BlobServiceNotAvailable,\n BlobServiceRateLimited,\n BlobStoreNotFoundError,\n BlobStoreSuspendedError,\n BlobUnknownError,\n} from './api';\n// expose generic BlobError and download url util\nexport {\n type BlobAccessType,\n BlobError,\n getDownloadUrl,\n type OnUploadProgressCallback,\n type UploadProgressEvent,\n} from './helpers';\n\n// vercelBlob.put()\n\nexport type { PutBlobResult } from './put-helpers';\nexport type { PutCommandOptions };\n\n/**\n * Uploads a blob into your store from your server.\n * Detailed documentation can be found here: https://vercel.com/docs/vercel-blob/using-blob-sdk#upload-a-blob\n *\n * If you want to upload from the browser directly, or if you're hitting Vercel upload limits, check out the documentation for client uploads: https://vercel.com/docs/vercel-blob/using-blob-sdk#client-uploads\n *\n * @param pathname - The pathname to upload the blob to, including the extension. This will influence the URL of your blob like https://$storeId.public.blob.vercel-storage.com/$pathname.\n * @param body - The content of your blob, can be a: string, File, Blob, Buffer or Stream. We support almost everything fetch supports: https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#body.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to false. We recommend using this option to ensure there are no conflicts in your blob filenames.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs. By default an error will be thrown if you try to overwrite a blob by using the same pathname for multiple blobs.\n * - contentType - (Optional) A string indicating the media type. By default, it's extracted from the pathname's extension.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure how long Blobs are cached. Defaults to one month. Cannot be set to a value lower than 1 minute.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - multipart - (Optional) Whether to use multipart upload for large files. It will split the file into multiple parts, upload them in parallel and retry failed parts.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * - onUploadProgress - (Optional) Callback to track upload progress: onUploadProgress(\\{loaded: number, total: number, percentage: number\\})\n * @returns A promise that resolves to the blob information, including pathname, contentType, contentDisposition, url, and downloadUrl.\n */\nexport const put = createPutMethod<PutCommandOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n});\n\n// vercelBlob.del()\n\nexport { del } from './del';\n\n// vercelBlob.head()\n\nexport type { HeadBlobResult } from './head';\nexport { head } from './head';\n\n// vercelBlob.get()\n\nexport type { GetBlobResult, GetCommandOptions } from './get';\nexport { get } from './get';\n\n// vercelBlob.list()\n\nexport type {\n ListBlobResult,\n ListBlobResultBlob,\n ListCommandOptions,\n ListFoldedBlobResult,\n} from './list';\nexport { list } from './list';\n\n// vercelBlob.copy()\n\nexport type { CopyBlobResult, CopyCommandOptions } from './copy';\nexport { copy } from './copy';\n\n// vercelBlob. createMultipartUpload()\n// vercelBlob. uploadPart()\n// vercelBlob. completeMultipartUpload()\n// vercelBlob. createMultipartUploader()\n\n/**\n * Creates a multipart upload. This is the first step in the manual multipart upload process.\n *\n * @param pathname - A string specifying the path inside the blob store. This will be the base value of the return URL and includes the filename and extension.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to true.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs. By default an error will be thrown if you try to overwrite a blob by using the same pathname for multiple blobs.\n * - contentType - (Optional) The media type for the file. If not specified, it's derived from the file extension. Falls back to application/octet-stream when no extension exists or can't be matched.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure the edge and browser cache. Defaults to one year.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to an object containing:\n * - key: A string that identifies the blob object.\n * - uploadId: A string that identifies the multipart upload. Both are needed for subsequent uploadPart calls.\n */\nexport const createMultipartUpload =\n createCreateMultipartUploadMethod<CommonCreateBlobOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n });\n\n/**\n * Creates a multipart uploader that simplifies the multipart upload process.\n * This is a wrapper around the manual multipart upload process that provides a more convenient API.\n *\n * @param pathname - A string specifying the path inside the blob store. This will be the base value of the return URL and includes the filename and extension.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to true.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs. By default an error will be thrown if you try to overwrite a blob by using the same pathname for multiple blobs.\n * - contentType - (Optional) The media type for the file. If not specified, it's derived from the file extension. Falls back to application/octet-stream when no extension exists or can't be matched.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure the edge and browser cache. Defaults to one year.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to an uploader object with the following properties and methods:\n * - key: A string that identifies the blob object.\n * - uploadId: A string that identifies the multipart upload.\n * - uploadPart: A method to upload a part of the file.\n * - complete: A method to complete the multipart upload process.\n */\nexport const createMultipartUploader =\n createCreateMultipartUploaderMethod<CommonCreateBlobOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n });\n\nexport type { UploadPartCommandOptions };\n\n/**\n * Uploads a part of a multipart upload.\n * Used as part of the manual multipart upload process.\n *\n * @param pathname - Same value as the pathname parameter passed to createMultipartUpload. This will influence the final URL of your blob.\n * @param body - A blob object as ReadableStream, String, ArrayBuffer or Blob based on these supported body types. Each part must be a minimum of 5MB, except the last one which can be smaller.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - uploadId - (Required) A string returned from createMultipartUpload which identifies the multipart upload.\n * - key - (Required) A string returned from createMultipartUpload which identifies the blob object.\n * - partNumber - (Required) A number identifying which part is uploaded (1-based index).\n * - contentType - (Optional) The media type for the blob. By default, it's derived from the pathname.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure how long Blobs are cached.\n * - abortSignal - (Optional) AbortSignal to cancel the running request.\n * - onUploadProgress - (Optional) Callback to track upload progress: onUploadProgress(\\{loaded: number, total: number, percentage: number\\})\n * @returns A promise that resolves to the uploaded part information containing etag and partNumber, which will be needed for the completeMultipartUpload call.\n */\nexport const uploadPart = createUploadPartMethod<UploadPartCommandOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n});\n\nexport type { CompleteMultipartUploadCommandOptions };\n\n/**\n * Completes a multipart upload by combining all uploaded parts.\n * This is the final step in the manual multipart upload process.\n *\n * @param pathname - Same value as the pathname parameter passed to createMultipartUpload.\n * @param parts - An array containing all the uploaded parts information from previous uploadPart calls. Each part must have properties etag and partNumber.\n * @param options - Configuration options including:\n * - access - (Required) Must be 'public' or 'private'. Public blobs are accessible via URL, private blobs require authentication.\n * - uploadId - (Required) A string returned from createMultipartUpload which identifies the multipart upload.\n * - key - (Required) A string returned from createMultipartUpload which identifies the blob object.\n * - contentType - (Optional) The media type for the file. If not specified, it's derived from the file extension.\n * - token - (Optional) A string specifying the token to use when making requests. It defaults to process.env.BLOB_READ_WRITE_TOKEN when deployed on Vercel.\n * - addRandomSuffix - (Optional) A boolean specifying whether to add a random suffix to the pathname. It defaults to true.\n * - allowOverwrite - (Optional) A boolean to allow overwriting blobs.\n * - cacheControlMaxAge - (Optional) A number in seconds to configure the edge and browser cache. Defaults to one year.\n * - abortSignal - (Optional) AbortSignal to cancel the operation.\n * @returns A promise that resolves to the finalized blob information, including pathname, contentType, contentDisposition, url, and downloadUrl.\n */\nexport const completeMultipartUpload =\n createCompleteMultipartUploadMethod<CompleteMultipartUploadCommandOptions>({\n allowedOptions: [\n 'cacheControlMaxAge',\n 'addRandomSuffix',\n 'allowOverwrite',\n 'contentType',\n ],\n });\n\nexport type {\n CreateFolderCommandOptions,\n CreateFolderResult,\n} from './create-folder';\nexport { createFolder } from './create-folder';\nexport type { Part, PartInput } from './multipart/helpers';\n"]}
|