@vercel/kv2 0.0.17 → 0.0.19

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.
Files changed (40) hide show
  1. package/dist/blob-format.d.ts +1 -0
  2. package/dist/blob-format.d.ts.map +1 -1
  3. package/dist/blob-format.js +1 -1
  4. package/dist/blob-format.js.map +1 -1
  5. package/dist/blob-stores/disk-blob-store.d.ts +20 -0
  6. package/dist/blob-stores/disk-blob-store.d.ts.map +1 -0
  7. package/dist/blob-stores/disk-blob-store.js +270 -0
  8. package/dist/blob-stores/disk-blob-store.js.map +1 -0
  9. package/dist/blob-stores/in-memory-blob-store.d.ts +30 -0
  10. package/dist/blob-stores/in-memory-blob-store.d.ts.map +1 -0
  11. package/dist/blob-stores/in-memory-blob-store.js +187 -0
  12. package/dist/blob-stores/in-memory-blob-store.js.map +1 -0
  13. package/dist/blob-stores/index.d.ts +4 -0
  14. package/dist/blob-stores/index.d.ts.map +1 -0
  15. package/dist/blob-stores/index.js +4 -0
  16. package/dist/blob-stores/index.js.map +1 -0
  17. package/dist/blob-stores/vercel-blob-store.d.ts +11 -0
  18. package/dist/blob-stores/vercel-blob-store.d.ts.map +1 -0
  19. package/dist/blob-stores/vercel-blob-store.js +34 -0
  20. package/dist/blob-stores/vercel-blob-store.js.map +1 -0
  21. package/dist/cached-kv.d.ts +11 -0
  22. package/dist/cached-kv.d.ts.map +1 -1
  23. package/dist/cached-kv.js +33 -1
  24. package/dist/cached-kv.js.map +1 -1
  25. package/dist/testing/test-index.d.ts +1 -0
  26. package/dist/testing/test-index.d.ts.map +1 -1
  27. package/dist/testing/test-index.js +2 -0
  28. package/dist/testing/test-index.js.map +1 -1
  29. package/dist/typed-kv.d.ts +33 -3
  30. package/dist/typed-kv.d.ts.map +1 -1
  31. package/dist/typed-kv.js +116 -26
  32. package/dist/typed-kv.js.map +1 -1
  33. package/dist/types.d.ts +1 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/types.js +2 -1
  36. package/dist/types.js.map +1 -1
  37. package/dist/upstream-kv.d.ts.map +1 -1
  38. package/dist/upstream-kv.js +2 -6
  39. package/dist/upstream-kv.js.map +1 -1
  40. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import type { StoredEntry } from "./types.js";
2
+ export declare const MAX_HEADER_SIZE: number;
2
3
  export interface ParsedBlob<M> {
3
4
  header: StoredEntry<M>;
4
5
  payload: Buffer | null;
@@ -1 +1 @@
1
- {"version":3,"file":"blob-format.d.ts","sourceRoot":"","sources":["../src/blob-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAS9C,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAuC1D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CA+BR;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAE7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAE7D"}
1
+ {"version":3,"file":"blob-format.d.ts","sourceRoot":"","sources":["../src/blob-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAK9C,eAAO,MAAM,eAAe,QAAoB,CAAC;AAIjD,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAuC1D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CA+BR;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAE7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAE7D"}
@@ -1,7 +1,7 @@
1
1
  const HEADER_LENGTH_BYTES = 4;
2
2
  // Max header size ensures uint32 BE first byte < 0x7B ('{'), preventing format ambiguity
3
3
  // 0x7B000000 = 2,063,597,568 bytes; we use 100MB as a practical limit
4
- const MAX_HEADER_SIZE = 100 * 1024 * 1024;
4
+ export const MAX_HEADER_SIZE = 100 * 1024 * 1024;
5
5
  // ASCII code for '{'
6
6
  const OPEN_BRACE = 0x7b;
7
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"blob-format.js","sourceRoot":"","sources":["../src/blob-format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blob-format.js","sourceRoot":"","sources":["../src/blob-format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type GetBlobResult, type GetCommandOptions, type ListBlobResult, type ListCommandOptions, type PutBlobResult, type PutCommandOptions } from "@vercel/blob";
2
+ import type { BlobStore, PutBody } from "../types.js";
3
+ export declare class DiskBlobStore implements BlobStore {
4
+ private rootDir;
5
+ private locks;
6
+ constructor(rootDir: string);
7
+ private filePath;
8
+ private metaPath;
9
+ private withLock;
10
+ private readMeta;
11
+ get(pathname: string, _options: GetCommandOptions): Promise<GetBlobResult | null>;
12
+ put(pathname: string, body: PutBody, options: PutCommandOptions): Promise<PutBlobResult>;
13
+ del(urlOrPathname: string | string[]): Promise<void>;
14
+ list(options?: ListCommandOptions): Promise<ListBlobResult>;
15
+ private walkDir;
16
+ clear(): Promise<void>;
17
+ has(pathname: string): Promise<boolean>;
18
+ getContent(pathname: string): Promise<Buffer | undefined>;
19
+ }
20
+ //# sourceMappingURL=disk-blob-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk-blob-store.d.ts","sourceRoot":"","sources":["../../src/blob-stores/disk-blob-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AA4CtD,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAoC;gBAErC,OAAO,EAAE,MAAM;IAI3B,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,QAAQ;YAIF,QAAQ;YAsBR,QAAQ;IAUhB,GAAG,CACP,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAwC1B,GAAG,CACP,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC;IA6CnB,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpD,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC;YA8CnD,OAAO;IA+Bf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASvC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAOhE"}
@@ -0,0 +1,270 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { BlobPreconditionFailedError, } from "@vercel/blob";
4
+ let etagCounter = 0;
5
+ function generateEtag() {
6
+ return `"disk-etag-${++etagCounter}-${Date.now()}"`;
7
+ }
8
+ async function toBuffer(body) {
9
+ if (typeof body === "string") {
10
+ return Buffer.from(body, "utf-8");
11
+ }
12
+ if (body instanceof Buffer) {
13
+ return body;
14
+ }
15
+ if (body instanceof Blob) {
16
+ const arrayBuffer = await body.arrayBuffer();
17
+ return Buffer.from(arrayBuffer);
18
+ }
19
+ if (body instanceof ArrayBuffer) {
20
+ return Buffer.from(body);
21
+ }
22
+ if (ArrayBuffer.isView(body)) {
23
+ return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
24
+ }
25
+ if (body instanceof ReadableStream) {
26
+ const chunks = [];
27
+ const reader = body.getReader();
28
+ while (true) {
29
+ const { done, value } = await reader.read();
30
+ if (done)
31
+ break;
32
+ chunks.push(value);
33
+ }
34
+ return Buffer.concat(chunks);
35
+ }
36
+ throw new Error("Unsupported body type");
37
+ }
38
+ export class DiskBlobStore {
39
+ rootDir;
40
+ locks = new Map();
41
+ constructor(rootDir) {
42
+ this.rootDir = rootDir;
43
+ }
44
+ filePath(pathname) {
45
+ return path.join(this.rootDir, pathname);
46
+ }
47
+ metaPath(pathname) {
48
+ return `${path.join(this.rootDir, pathname)}.meta`;
49
+ }
50
+ async withLock(pathname, fn) {
51
+ while (this.locks.has(pathname)) {
52
+ await this.locks.get(pathname);
53
+ }
54
+ let resolve;
55
+ const lock = new Promise((r) => {
56
+ resolve = r;
57
+ });
58
+ this.locks.set(pathname, lock);
59
+ try {
60
+ return await fn();
61
+ }
62
+ finally {
63
+ this.locks.delete(pathname);
64
+ resolve();
65
+ }
66
+ }
67
+ async readMeta(pathname) {
68
+ try {
69
+ const raw = await fs.readFile(this.metaPath(pathname), "utf-8");
70
+ return JSON.parse(raw);
71
+ }
72
+ catch (e) {
73
+ if (e.code === "ENOENT")
74
+ return null;
75
+ throw e;
76
+ }
77
+ }
78
+ async get(pathname, _options) {
79
+ const meta = await this.readMeta(pathname);
80
+ if (!meta)
81
+ return null;
82
+ let content;
83
+ try {
84
+ content = await fs.readFile(this.filePath(pathname));
85
+ }
86
+ catch (e) {
87
+ if (e.code === "ENOENT")
88
+ return null;
89
+ throw e;
90
+ }
91
+ const stream = new ReadableStream({
92
+ start(controller) {
93
+ controller.enqueue(new Uint8Array(content));
94
+ controller.close();
95
+ },
96
+ });
97
+ return {
98
+ stream,
99
+ blob: {
100
+ url: `disk://${pathname}`,
101
+ downloadUrl: `disk://${pathname}?download=1`,
102
+ pathname,
103
+ contentType: meta.contentType,
104
+ contentDisposition: `attachment; filename="${pathname.split("/").pop()}"`,
105
+ cacheControl: "public, max-age=31536000, immutable",
106
+ size: meta.size,
107
+ uploadedAt: new Date(meta.uploadedAt),
108
+ etag: meta.etag,
109
+ },
110
+ headers: new Headers({
111
+ "content-type": meta.contentType,
112
+ "content-length": String(meta.size),
113
+ etag: meta.etag,
114
+ }),
115
+ };
116
+ }
117
+ async put(pathname, body, options) {
118
+ const content = await toBuffer(body);
119
+ return this.withLock(pathname, async () => {
120
+ const existingMeta = await this.readMeta(pathname);
121
+ const allowOverwrite = options.allowOverwrite ?? true;
122
+ if (!allowOverwrite && existingMeta) {
123
+ throw new BlobPreconditionFailedError();
124
+ }
125
+ if (options.ifMatch !== undefined) {
126
+ if (!existingMeta) {
127
+ throw new BlobPreconditionFailedError();
128
+ }
129
+ if (existingMeta.etag !== options.ifMatch) {
130
+ throw new BlobPreconditionFailedError();
131
+ }
132
+ }
133
+ const etag = generateEtag();
134
+ const contentType = options.contentType ?? "application/octet-stream";
135
+ const meta = {
136
+ etag,
137
+ contentType,
138
+ uploadedAt: new Date().toISOString(),
139
+ size: content.length,
140
+ };
141
+ const fp = this.filePath(pathname);
142
+ await fs.mkdir(path.dirname(fp), { recursive: true });
143
+ await fs.writeFile(fp, content);
144
+ await fs.writeFile(this.metaPath(pathname), JSON.stringify(meta));
145
+ return {
146
+ url: `disk://${pathname}`,
147
+ downloadUrl: `disk://${pathname}?download=1`,
148
+ pathname,
149
+ contentType,
150
+ contentDisposition: `attachment; filename="${pathname.split("/").pop()}"`,
151
+ etag,
152
+ };
153
+ });
154
+ }
155
+ async del(urlOrPathname) {
156
+ const paths = Array.isArray(urlOrPathname)
157
+ ? urlOrPathname
158
+ : [urlOrPathname];
159
+ for (const p of paths) {
160
+ const pathname = p.startsWith("disk://") ? p.slice(7) : p;
161
+ try {
162
+ await fs.unlink(this.filePath(pathname));
163
+ }
164
+ catch (e) {
165
+ if (e.code !== "ENOENT")
166
+ throw e;
167
+ }
168
+ try {
169
+ await fs.unlink(this.metaPath(pathname));
170
+ }
171
+ catch (e) {
172
+ if (e.code !== "ENOENT")
173
+ throw e;
174
+ }
175
+ }
176
+ }
177
+ async list(options) {
178
+ // Scope the walk to the deepest directory implied by the prefix
179
+ // e.g. prefix "users/posts/" walks <rootDir>/users/posts/ instead of <rootDir>/
180
+ const prefix = options?.prefix ?? "";
181
+ const prefixDir = prefix.includes("/")
182
+ ? prefix.slice(0, prefix.lastIndexOf("/") + 1)
183
+ : "";
184
+ const walkRoot = prefixDir
185
+ ? path.join(this.rootDir, prefixDir)
186
+ : this.rootDir;
187
+ const allFiles = await this.walkDir(walkRoot);
188
+ // Filter to content files (skip .meta), compute relative pathnames
189
+ const entries = [];
190
+ for (const absPath of allFiles) {
191
+ if (absPath.endsWith(".meta"))
192
+ continue;
193
+ const pathname = path.relative(this.rootDir, absPath);
194
+ if (prefix && !pathname.startsWith(prefix))
195
+ continue;
196
+ const meta = await this.readMeta(pathname);
197
+ if (meta)
198
+ entries.push({ pathname, meta });
199
+ }
200
+ entries.sort((a, b) => a.pathname.localeCompare(b.pathname));
201
+ const limit = options?.limit ?? 1000;
202
+ const cursorIndex = options?.cursor
203
+ ? Number.parseInt(options.cursor, 10)
204
+ : 0;
205
+ const slice = entries.slice(cursorIndex, cursorIndex + limit);
206
+ const hasMore = cursorIndex + limit < entries.length;
207
+ return {
208
+ blobs: slice.map((e) => ({
209
+ url: `disk://${e.pathname}`,
210
+ downloadUrl: `disk://${e.pathname}?download=1`,
211
+ pathname: e.pathname,
212
+ size: e.meta.size,
213
+ uploadedAt: new Date(e.meta.uploadedAt),
214
+ etag: e.meta.etag,
215
+ })),
216
+ hasMore,
217
+ cursor: hasMore ? String(cursorIndex + limit) : undefined,
218
+ };
219
+ }
220
+ async walkDir(dir, concurrency = 16) {
221
+ let names;
222
+ try {
223
+ names = await fs.readdir(dir);
224
+ }
225
+ catch (e) {
226
+ if (e.code === "ENOENT")
227
+ return [];
228
+ throw e;
229
+ }
230
+ const results = [];
231
+ // Process entries in batches to limit open file descriptors
232
+ for (let i = 0; i < names.length; i += concurrency) {
233
+ const batch = names.slice(i, i + concurrency);
234
+ const settled = await Promise.all(batch.map(async (name) => {
235
+ const full = path.join(dir, name);
236
+ const stat = await fs.stat(full);
237
+ if (stat.isDirectory()) {
238
+ return this.walkDir(full, concurrency);
239
+ }
240
+ return [full];
241
+ }));
242
+ for (const files of settled) {
243
+ results.push(...files);
244
+ }
245
+ }
246
+ return results;
247
+ }
248
+ // Test helpers
249
+ async clear() {
250
+ await fs.rm(this.rootDir, { recursive: true, force: true });
251
+ }
252
+ async has(pathname) {
253
+ try {
254
+ await fs.access(this.filePath(pathname));
255
+ return true;
256
+ }
257
+ catch {
258
+ return false;
259
+ }
260
+ }
261
+ async getContent(pathname) {
262
+ try {
263
+ return await fs.readFile(this.filePath(pathname));
264
+ }
265
+ catch {
266
+ return undefined;
267
+ }
268
+ }
269
+ }
270
+ //# sourceMappingURL=disk-blob-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk-blob-store.js","sourceRoot":"","sources":["../../src/blob-stores/disk-blob-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { type GetBlobResult, type GetCommandOptions, type ListBlobResult, type ListCommandOptions, type PutBlobResult, type PutCommandOptions } from "@vercel/blob";
2
+ import type { BlobStore, PutBody } from "../types.js";
3
+ interface StoredBlob {
4
+ pathname: string;
5
+ content: Buffer;
6
+ contentType: string;
7
+ uploadedAt: Date;
8
+ size: number;
9
+ etag: string;
10
+ }
11
+ export declare class InMemoryBlobStore implements BlobStore {
12
+ private blobs;
13
+ private locks;
14
+ /**
15
+ * Serialize writes to the same key to prevent race conditions
16
+ * where concurrent callers all pass precondition checks before
17
+ * any write lands.
18
+ */
19
+ private withLock;
20
+ get(pathname: string, _options: GetCommandOptions): Promise<GetBlobResult | null>;
21
+ put(pathname: string, body: PutBody, options: PutCommandOptions): Promise<PutBlobResult>;
22
+ del(urlOrPathname: string | string[]): Promise<void>;
23
+ list(options?: ListCommandOptions): Promise<ListBlobResult>;
24
+ clear(): void;
25
+ has(pathname: string): boolean;
26
+ getContent(pathname: string): Buffer | undefined;
27
+ getAll(): Map<string, StoredBlob>;
28
+ }
29
+ export {};
30
+ //# sourceMappingURL=in-memory-blob-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-blob-store.d.ts","sourceRoot":"","sources":["../../src/blob-stores/in-memory-blob-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtD,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAqCD,qBAAa,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,KAAK,CAAoC;IAEjD;;;;OAIG;YACW,QAAQ;IAuBhB,GAAG,CACP,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAmC1B,GAAG,CACP,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC;IA+CnB,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpD,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC;IAoCjE,KAAK,IAAI,IAAI;IAIb,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI9B,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;CAGlC"}
@@ -0,0 +1,187 @@
1
+ import { BlobPreconditionFailedError, } from "@vercel/blob";
2
+ let etagCounter = 0;
3
+ function generateEtag() {
4
+ return `"fake-etag-${++etagCounter}-${Date.now()}"`;
5
+ }
6
+ async function toBuffer(body) {
7
+ if (typeof body === "string") {
8
+ return Buffer.from(body, "utf-8");
9
+ }
10
+ if (body instanceof Buffer) {
11
+ return body;
12
+ }
13
+ if (body instanceof Blob) {
14
+ const arrayBuffer = await body.arrayBuffer();
15
+ return Buffer.from(arrayBuffer);
16
+ }
17
+ if (body instanceof ArrayBuffer) {
18
+ return Buffer.from(body);
19
+ }
20
+ if (ArrayBuffer.isView(body)) {
21
+ return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
22
+ }
23
+ if (body instanceof ReadableStream) {
24
+ const chunks = [];
25
+ const reader = body.getReader();
26
+ while (true) {
27
+ const { done, value } = await reader.read();
28
+ if (done)
29
+ break;
30
+ chunks.push(value);
31
+ }
32
+ return Buffer.concat(chunks);
33
+ }
34
+ throw new Error("Unsupported body type");
35
+ }
36
+ export class InMemoryBlobStore {
37
+ blobs = new Map();
38
+ locks = new Map();
39
+ /**
40
+ * Serialize writes to the same key to prevent race conditions
41
+ * where concurrent callers all pass precondition checks before
42
+ * any write lands.
43
+ */
44
+ async withLock(pathname, fn) {
45
+ // Wait for any in-flight write to this key
46
+ while (this.locks.has(pathname)) {
47
+ await this.locks.get(pathname);
48
+ }
49
+ let resolve;
50
+ const lock = new Promise((r) => {
51
+ resolve = r;
52
+ });
53
+ this.locks.set(pathname, lock);
54
+ try {
55
+ return await fn();
56
+ }
57
+ finally {
58
+ this.locks.delete(pathname);
59
+ resolve();
60
+ }
61
+ }
62
+ async get(pathname, _options) {
63
+ const blob = this.blobs.get(pathname);
64
+ if (!blob) {
65
+ return null;
66
+ }
67
+ const content = blob.content;
68
+ const stream = new ReadableStream({
69
+ start(controller) {
70
+ controller.enqueue(new Uint8Array(content));
71
+ controller.close();
72
+ },
73
+ });
74
+ return {
75
+ stream,
76
+ blob: {
77
+ url: `fake://${pathname}`,
78
+ downloadUrl: `fake://${pathname}?download=1`,
79
+ pathname,
80
+ contentType: blob.contentType,
81
+ contentDisposition: `attachment; filename="${pathname.split("/").pop()}"`,
82
+ cacheControl: "public, max-age=31536000, immutable",
83
+ size: blob.size,
84
+ uploadedAt: blob.uploadedAt,
85
+ etag: blob.etag,
86
+ },
87
+ headers: new Headers({
88
+ "content-type": blob.contentType,
89
+ "content-length": String(blob.size),
90
+ etag: blob.etag,
91
+ }),
92
+ };
93
+ }
94
+ async put(pathname, body, options) {
95
+ // Buffer the body outside the lock to avoid holding the lock
96
+ // during potentially slow stream reads, matching real blob store
97
+ // behavior where the server handles serialization.
98
+ const content = await toBuffer(body);
99
+ return this.withLock(pathname, () => {
100
+ const existingBlob = this.blobs.get(pathname);
101
+ // Check allowOverwrite option (default: true based on @vercel/blob behavior)
102
+ const allowOverwrite = options.allowOverwrite ?? true;
103
+ if (!allowOverwrite && existingBlob) {
104
+ throw new BlobPreconditionFailedError();
105
+ }
106
+ // Check ifMatch (optimistic locking)
107
+ if (options.ifMatch !== undefined) {
108
+ if (!existingBlob) {
109
+ // Real @vercel/blob throws "The specified key does not exist"
110
+ throw new BlobPreconditionFailedError();
111
+ }
112
+ if (existingBlob.etag !== options.ifMatch) {
113
+ throw new BlobPreconditionFailedError();
114
+ }
115
+ }
116
+ const etag = generateEtag();
117
+ this.blobs.set(pathname, {
118
+ pathname,
119
+ content,
120
+ contentType: options.contentType ?? "application/octet-stream",
121
+ uploadedAt: new Date(),
122
+ size: content.length,
123
+ etag,
124
+ });
125
+ return {
126
+ url: `fake://${pathname}`,
127
+ downloadUrl: `fake://${pathname}?download=1`,
128
+ pathname,
129
+ contentType: options.contentType ?? "application/octet-stream",
130
+ contentDisposition: `attachment; filename="${pathname.split("/").pop()}"`,
131
+ etag,
132
+ };
133
+ });
134
+ }
135
+ async del(urlOrPathname) {
136
+ const paths = Array.isArray(urlOrPathname)
137
+ ? urlOrPathname
138
+ : [urlOrPathname];
139
+ for (const p of paths) {
140
+ // Handle both URLs and pathnames
141
+ const pathname = p.startsWith("fake://") ? p.slice(7) : p;
142
+ this.blobs.delete(pathname);
143
+ }
144
+ }
145
+ async list(options) {
146
+ let entries = [...this.blobs.values()];
147
+ // Filter by prefix
148
+ if (options?.prefix) {
149
+ entries = entries.filter((b) => b.pathname.startsWith(options.prefix));
150
+ }
151
+ // Sort by pathname for consistent ordering
152
+ entries.sort((a, b) => a.pathname.localeCompare(b.pathname));
153
+ // Handle pagination
154
+ const limit = options?.limit ?? 1000;
155
+ const cursorIndex = options?.cursor
156
+ ? Number.parseInt(options.cursor, 10)
157
+ : 0;
158
+ const slice = entries.slice(cursorIndex, cursorIndex + limit);
159
+ const hasMore = cursorIndex + limit < entries.length;
160
+ return {
161
+ blobs: slice.map((b) => ({
162
+ url: `fake://${b.pathname}`,
163
+ downloadUrl: `fake://${b.pathname}?download=1`,
164
+ pathname: b.pathname,
165
+ size: b.size,
166
+ uploadedAt: b.uploadedAt,
167
+ etag: b.etag,
168
+ })),
169
+ hasMore,
170
+ cursor: hasMore ? String(cursorIndex + limit) : undefined,
171
+ };
172
+ }
173
+ // Test helpers
174
+ clear() {
175
+ this.blobs.clear();
176
+ }
177
+ has(pathname) {
178
+ return this.blobs.has(pathname);
179
+ }
180
+ getContent(pathname) {
181
+ return this.blobs.get(pathname)?.content;
182
+ }
183
+ getAll() {
184
+ return new Map(this.blobs);
185
+ }
186
+ }
187
+ //# sourceMappingURL=in-memory-blob-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-blob-store.js","sourceRoot":"","sources":["../../src/blob-stores/in-memory-blob-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { InMemoryBlobStore } from "./in-memory-blob-store.js";
2
+ export { VercelBlobStore } from "./vercel-blob-store.js";
3
+ export { DiskBlobStore } from "./disk-blob-store.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blob-stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { InMemoryBlobStore } from "./in-memory-blob-store.js";
2
+ export { VercelBlobStore } from "./vercel-blob-store.js";
3
+ export { DiskBlobStore } from "./disk-blob-store.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blob-stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type GetBlobResult, type GetCommandOptions, type ListBlobResult, type ListCommandOptions, type PutBlobResult, type PutCommandOptions } from "@vercel/blob";
2
+ import type { BlobStore, PutBody } from "../types.js";
3
+ export declare class VercelBlobStore implements BlobStore {
4
+ private token?;
5
+ constructor(token?: string);
6
+ get(pathname: string, options: GetCommandOptions): Promise<GetBlobResult | null>;
7
+ put(pathname: string, body: PutBody, options: PutCommandOptions): Promise<PutBlobResult>;
8
+ del(urlOrPathname: string | string[]): Promise<void>;
9
+ list(options?: ListCommandOptions): Promise<ListBlobResult>;
10
+ }
11
+ //# sourceMappingURL=vercel-blob-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel-blob-store.d.ts","sourceRoot":"","sources":["../../src/blob-stores/vercel-blob-store.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAKvB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtD,qBAAa,eAAgB,YAAW,SAAS;IAC/C,OAAO,CAAC,KAAK,CAAC,CAAS;gBAEX,KAAK,CAAC,EAAE,MAAM;IAIpB,GAAG,CACP,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAQ1B,GAAG,CACP,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC;IAOnB,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC;CAMlE"}
@@ -0,0 +1,34 @@
1
+ import { del, get, list, put, } from "@vercel/blob";
2
+ /* c8 ignore start -- thin wrapper over @vercel/blob SDK, tested via integration tests */
3
+ export class VercelBlobStore {
4
+ token;
5
+ constructor(token) {
6
+ this.token = token;
7
+ }
8
+ async get(pathname, options) {
9
+ return get(pathname, {
10
+ useCache: false,
11
+ ...options,
12
+ token: this.token,
13
+ });
14
+ }
15
+ async put(pathname, body, options) {
16
+ return put(pathname, body, {
17
+ ...options,
18
+ token: this.token,
19
+ });
20
+ }
21
+ async del(urlOrPathname) {
22
+ return del(urlOrPathname, {
23
+ token: this.token,
24
+ });
25
+ }
26
+ async list(options) {
27
+ return list({
28
+ ...options,
29
+ token: this.token,
30
+ });
31
+ }
32
+ }
33
+ /* c8 ignore stop */
34
+ //# sourceMappingURL=vercel-blob-store.js.map