@ustorage/sdk 0.1.0

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.
@@ -0,0 +1,483 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/browser/index.ts
21
+ var browser_exports = {};
22
+ __export(browser_exports, {
23
+ BrowserHttpClient: () => FetchHttpClient,
24
+ BrowserResumeStore: () => BrowserResumeStore,
25
+ BrowserUploadSource: () => BrowserUploadSource,
26
+ FetchHttpClient: () => FetchHttpClient,
27
+ MemoryResumeStore: () => MemoryResumeStore,
28
+ UStorageBrowserClient: () => UStorageBrowserClient,
29
+ UStorageCoreClient: () => UStorageCoreClient,
30
+ UStorageError: () => UStorageError,
31
+ UploadApi: () => UploadApi,
32
+ Uploader: () => Uploader,
33
+ resolveToken: () => resolveToken,
34
+ toUStorageError: () => toUStorageError
35
+ });
36
+ module.exports = __toCommonJS(browser_exports);
37
+
38
+ // src/core/auth/index.ts
39
+ async function resolveToken(value) {
40
+ return typeof value === "function" ? value() : value;
41
+ }
42
+
43
+ // src/core/errors/index.ts
44
+ var UStorageError = class extends Error {
45
+ code;
46
+ status;
47
+ requestId;
48
+ details;
49
+ constructor(message, options) {
50
+ super(message);
51
+ this.name = "UStorageError";
52
+ this.code = options.code;
53
+ this.status = options.status;
54
+ this.requestId = options.requestId;
55
+ this.details = options.details;
56
+ }
57
+ };
58
+ function toUStorageError(status, body) {
59
+ const parsed = body;
60
+ if (parsed?.error?.code && parsed.error.message) {
61
+ return new UStorageError(parsed.error.message, {
62
+ code: parsed.error.code,
63
+ status,
64
+ requestId: parsed.request_id,
65
+ details: parsed.error.details
66
+ });
67
+ }
68
+ return new UStorageError(`UStorage request failed with status ${status}`, { code: "REQUEST_FAILED", status });
69
+ }
70
+
71
+ // src/core/http/index.ts
72
+ var FetchHttpClient = class {
73
+ baseUrl;
74
+ authHeaders;
75
+ fetchImpl;
76
+ constructor(options) {
77
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
78
+ this.authHeaders = options.authHeaders;
79
+ this.fetchImpl = options.fetchImpl ?? fetch;
80
+ }
81
+ async request(options) {
82
+ const headers = new Headers();
83
+ for (const [key, value] of Object.entries(options.headers ?? {})) {
84
+ if (value !== void 0 && value !== null) headers.set(key, value);
85
+ }
86
+ let body;
87
+ if (options.body !== void 0) {
88
+ if (isBodyInit(options.body)) {
89
+ body = options.body;
90
+ } else {
91
+ headers.set("content-type", headers.get("content-type") ?? "application/json");
92
+ body = JSON.stringify(options.body);
93
+ }
94
+ }
95
+ const path = this.pathWithQuery(options.path, options.query);
96
+ const authHeaders = this.authHeaders ? await this.authHeaders({ method: options.method, path, body }) : {};
97
+ for (const [key, value] of Object.entries(authHeaders)) headers.set(key, value);
98
+ const response = await this.fetchImpl(this.url(path), {
99
+ method: options.method,
100
+ headers,
101
+ body,
102
+ signal: options.signal
103
+ });
104
+ if (response.status === 204) return void 0;
105
+ const text = await response.text();
106
+ const parsed = text ? parseJson(text) : void 0;
107
+ if (!response.ok) throw toUStorageError(response.status, parsed);
108
+ return parsed;
109
+ }
110
+ url(path) {
111
+ return new URL(path.startsWith("/") ? path : `/${path}`, `${this.baseUrl}/`).toString();
112
+ }
113
+ pathWithQuery(path, query) {
114
+ const url = new URL(path.startsWith("/") ? path : `/${path}`, "http://sdk.local");
115
+ for (const [key, value] of Object.entries(query ?? {})) {
116
+ if (value !== void 0 && value !== null) url.searchParams.set(key, String(value));
117
+ }
118
+ return `${url.pathname}${url.search}`;
119
+ }
120
+ };
121
+ function parseJson(value) {
122
+ try {
123
+ return JSON.parse(value);
124
+ } catch {
125
+ return value;
126
+ }
127
+ }
128
+ function isBodyInit(value) {
129
+ return typeof Blob !== "undefined" && value instanceof Blob || typeof FormData !== "undefined" && value instanceof FormData || typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams || typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer || ArrayBuffer.isView(value) || typeof ReadableStream !== "undefined" && value instanceof ReadableStream;
130
+ }
131
+
132
+ // src/core/upload/api.ts
133
+ var UploadApi = class {
134
+ constructor(http) {
135
+ this.http = http;
136
+ }
137
+ http;
138
+ createUploadToken(request) {
139
+ return this.http.request({ method: "POST", path: "/uploads/tokens", body: request });
140
+ }
141
+ createSession(request) {
142
+ return this.http.request({ method: "POST", path: "/uploads/sessions", body: request });
143
+ }
144
+ createFileUrl(request) {
145
+ return this.http.request({ method: "POST", path: "/files/url", body: request });
146
+ }
147
+ uploadChunk(uploadId, index, body, checksum, signal) {
148
+ return this.http.request({ method: "PUT", path: `/uploads/${uploadId}/chunks/${index}`, headers: { "x-chunk-checksum": checksum }, body, signal });
149
+ }
150
+ getStatus(uploadId) {
151
+ return this.http.request({ method: "GET", path: `/uploads/${uploadId}/status` });
152
+ }
153
+ complete(uploadId, request = {}) {
154
+ return this.http.request({ method: "POST", path: `/uploads/${uploadId}/complete`, body: request });
155
+ }
156
+ cancel(uploadId) {
157
+ return this.http.request({ method: "DELETE", path: `/uploads/${uploadId}` });
158
+ }
159
+ };
160
+
161
+ // src/core/upload/checksum.ts
162
+ async function sha256Hex(data) {
163
+ const bytes = await toBytes(data);
164
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
165
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
166
+ }
167
+ async function toBytes(data) {
168
+ if (data instanceof ArrayBuffer) return data;
169
+ if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength).slice().buffer;
170
+ if (typeof Blob !== "undefined" && data instanceof Blob) return data.arrayBuffer();
171
+ if (typeof data === "string") return new TextEncoder().encode(data).buffer;
172
+ return new Response(data).arrayBuffer();
173
+ }
174
+
175
+ // src/core/upload/file-metadata.ts
176
+ var mimeTypesByExtension = {
177
+ jpg: "image/jpeg",
178
+ jpeg: "image/jpeg",
179
+ png: "image/png",
180
+ gif: "image/gif",
181
+ webp: "image/webp",
182
+ bmp: "image/bmp",
183
+ svg: "image/svg+xml",
184
+ heic: "image/heic",
185
+ mp4: "video/mp4",
186
+ mpeg: "video/mpeg",
187
+ mov: "video/quicktime",
188
+ avi: "video/x-msvideo",
189
+ webm: "video/webm",
190
+ ogg: "video/ogg",
191
+ "3gp": "video/3gpp",
192
+ flv: "video/x-flv",
193
+ mp3: "audio/mpeg",
194
+ wav: "audio/wav",
195
+ aac: "audio/aac",
196
+ m4a: "audio/x-m4a",
197
+ flac: "audio/flac",
198
+ amr: "audio/amr",
199
+ pdf: "application/pdf",
200
+ txt: "text/plain",
201
+ json: "application/json",
202
+ zip: "application/zip",
203
+ tar: "application/x-tar",
204
+ rar: "application/vnd.rar",
205
+ doc: "application/msword",
206
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
207
+ xls: "application/vnd.ms-excel",
208
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
209
+ ppt: "application/vnd.ms-powerpoint",
210
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
211
+ };
212
+ function extensionFromName(nameOrKey) {
213
+ const filename = nameOrKey.split(/[\\/]/).filter(Boolean).at(-1) ?? nameOrKey;
214
+ const dot = filename.lastIndexOf(".");
215
+ if (dot <= 0 || dot === filename.length - 1) {
216
+ return null;
217
+ }
218
+ return filename.slice(dot + 1).toLowerCase();
219
+ }
220
+ function mimeTypeFromExtension(extension) {
221
+ return extension ? mimeTypesByExtension[extension.toLowerCase()] ?? null : null;
222
+ }
223
+ function resolveUploadContentType(explicit, sourceType, ...names) {
224
+ const normalizedExplicit = normalizeContentType(explicit);
225
+ if (normalizedExplicit) {
226
+ return normalizedExplicit;
227
+ }
228
+ const normalizedSourceType = normalizeContentType(sourceType);
229
+ if (normalizedSourceType) {
230
+ return normalizedSourceType;
231
+ }
232
+ for (const name of names) {
233
+ if (!name) continue;
234
+ const inferred = mimeTypeFromExtension(extensionFromName(name));
235
+ if (inferred) {
236
+ return inferred;
237
+ }
238
+ }
239
+ return null;
240
+ }
241
+ function normalizeContentType(value) {
242
+ const normalized = value?.trim();
243
+ return normalized ? normalized : null;
244
+ }
245
+
246
+ // src/core/upload/uploader.ts
247
+ var Uploader = class {
248
+ constructor(uploads, resumeStore) {
249
+ this.uploads = uploads;
250
+ this.resumeStore = resumeStore;
251
+ }
252
+ uploads;
253
+ resumeStore;
254
+ async putObject(source, options) {
255
+ const chunkSize = options.chunkSize ?? 8 * 1024 * 1024;
256
+ if (chunkSize <= 0) throw new Error("chunkSize must be positive");
257
+ const totalChunks = source.size === 0 ? 1 : Math.ceil(source.size / chunkSize);
258
+ const useResume = options.resume === true || Boolean(options.resumeKey);
259
+ const resumeKey = useResume ? options.resumeKey ?? await source.fingerprint(options.key) : void 0;
260
+ let uploadId = resumeKey && this.resumeStore ? await this.resumeStore.get(resumeKey) : void 0;
261
+ let missingChunks;
262
+ if (uploadId) {
263
+ try {
264
+ const status = await this.uploads.getStatus(uploadId);
265
+ missingChunks = status.missing_chunks;
266
+ options.onProgress?.(statusToProgress(status));
267
+ } catch {
268
+ uploadId = void 0;
269
+ if (resumeKey) await this.resumeStore?.delete(resumeKey);
270
+ }
271
+ }
272
+ if (!uploadId) {
273
+ const session = await this.uploads.createSession({
274
+ bucket_name: options.bucketName,
275
+ key: options.key,
276
+ workspace_name: options.workspaceName ?? null,
277
+ mime_type: resolveUploadContentType(
278
+ options.contentType,
279
+ source.type,
280
+ options.key,
281
+ source.name
282
+ ),
283
+ file_size: source.size,
284
+ chunk_size: chunkSize,
285
+ total_chunks: totalChunks,
286
+ checksum: typeof options.checksum === "object" ? options.checksum.file ?? null : null,
287
+ metadata: options.metadata,
288
+ overwrite: options.overwrite ?? true,
289
+ visibility: options.visibility ?? null
290
+ });
291
+ uploadId = session.upload_id;
292
+ missingChunks = Array.from({ length: totalChunks }, (_, index) => index);
293
+ if (resumeKey) await this.resumeStore?.set(resumeKey, uploadId);
294
+ }
295
+ for (const index of missingChunks ?? []) {
296
+ const start = index * chunkSize;
297
+ const end = source.size === 0 ? 0 : Math.min(source.size, start + chunkSize);
298
+ const chunk = await source.slice(start, end);
299
+ const checksum = await this.chunkChecksum(options.checksum, index, chunk.body);
300
+ const response = await this.uploads.uploadChunk(uploadId, index, chunk.body, checksum, options.signal);
301
+ options.onProgress?.(chunkResponseToProgress(response));
302
+ }
303
+ const complete = await this.uploads.complete(uploadId, { checksum: typeof options.checksum === "object" ? options.checksum.file : void 0 });
304
+ if (resumeKey) await this.resumeStore?.delete(resumeKey);
305
+ return {
306
+ ...complete,
307
+ uploadId: complete.upload_id,
308
+ fileId: complete.file_id,
309
+ publicId: complete.public_id,
310
+ visibility: complete.visibility,
311
+ url: complete.url,
312
+ expiresAt: complete.expires_at ?? null
313
+ };
314
+ }
315
+ async chunkChecksum(checksum, index, body) {
316
+ if (!checksum) return void 0;
317
+ if (checksum === "sha256") return sha256Hex(body);
318
+ return checksum.chunks?.[index];
319
+ }
320
+ };
321
+ function chunkResponseToProgress(response) {
322
+ return {
323
+ uploadId: response.upload_id,
324
+ chunkIndex: response.chunk_index,
325
+ uploadedChunks: response.uploaded_chunks,
326
+ totalChunks: response.total_chunks,
327
+ uploadedSize: response.uploaded_size,
328
+ fileSize: response.file_size,
329
+ progress: response.progress
330
+ };
331
+ }
332
+ function statusToProgress(response) {
333
+ return {
334
+ uploadId: response.upload_id,
335
+ uploadedChunks: response.uploaded_chunks.length,
336
+ totalChunks: response.total_chunks,
337
+ uploadedSize: response.uploaded_size,
338
+ fileSize: response.file_size,
339
+ progress: response.progress
340
+ };
341
+ }
342
+
343
+ // src/core/client/index.ts
344
+ var UStorageCoreClient = class {
345
+ uploads;
346
+ uploader;
347
+ constructor(options) {
348
+ const uploadHttp = options.uploadHttpClient ?? new FetchHttpClient({ baseUrl: options.uploadBaseUrl, authHeaders: options.authHeaders });
349
+ this.uploads = new UploadApi(uploadHttp);
350
+ this.uploader = new Uploader(this.uploads, options.resumeStore);
351
+ }
352
+ async getObjectUrl(input) {
353
+ const response = await this.uploads.createFileUrl({
354
+ file_id: input.fileId ?? null,
355
+ bucket: input.bucket ?? null,
356
+ bucket_id: input.bucketId ?? null,
357
+ key: input.key ?? null,
358
+ path: input.path ?? null,
359
+ expires_in: input.expiresIn ?? null
360
+ });
361
+ return {
362
+ fileId: response.file_id,
363
+ publicId: response.public_id,
364
+ visibility: response.visibility,
365
+ url: response.url,
366
+ expiresAt: response.expires_at
367
+ };
368
+ }
369
+ getSignedUrl(input) {
370
+ return this.getObjectUrl(input);
371
+ }
372
+ uploadSource(source, options) {
373
+ return this.uploader.putObject(source, options);
374
+ }
375
+ };
376
+
377
+ // src/core/upload/source.ts
378
+ var MemoryResumeStore = class {
379
+ values = /* @__PURE__ */ new Map();
380
+ get(key) {
381
+ return this.values.get(key);
382
+ }
383
+ set(key, uploadId) {
384
+ this.values.set(key, uploadId);
385
+ }
386
+ delete(key) {
387
+ this.values.delete(key);
388
+ }
389
+ };
390
+
391
+ // src/browser/browser-resume-store.ts
392
+ var BrowserResumeStore = class {
393
+ constructor(prefix = "ustorage:upload:") {
394
+ this.prefix = prefix;
395
+ }
396
+ prefix;
397
+ memory = new MemoryResumeStore();
398
+ get(key) {
399
+ const storage = this.storage();
400
+ return storage?.getItem(this.prefix + key) ?? this.memory.get(key);
401
+ }
402
+ set(key, uploadId) {
403
+ const storage = this.storage();
404
+ if (storage) storage.setItem(this.prefix + key, uploadId);
405
+ else this.memory.set(key, uploadId);
406
+ }
407
+ delete(key) {
408
+ const storage = this.storage();
409
+ if (storage) storage.removeItem(this.prefix + key);
410
+ else this.memory.delete(key);
411
+ }
412
+ storage() {
413
+ try {
414
+ return typeof localStorage === "undefined" ? void 0 : localStorage;
415
+ } catch {
416
+ return void 0;
417
+ }
418
+ }
419
+ };
420
+
421
+ // src/browser/browser-upload-source.ts
422
+ var BrowserUploadSource = class {
423
+ constructor(file, name) {
424
+ this.file = file;
425
+ this.name = name ?? ("name" in file ? file.name : "blob");
426
+ this.size = file.size;
427
+ this.type = file.type || void 0;
428
+ this.lastModified = "lastModified" in file ? file.lastModified : void 0;
429
+ }
430
+ file;
431
+ name;
432
+ size;
433
+ type;
434
+ lastModified;
435
+ fingerprint(key) {
436
+ return ["browser", key ?? "", this.name, this.size, this.type ?? "", this.lastModified ?? ""].join(":");
437
+ }
438
+ slice(start, end) {
439
+ const body = this.file.slice(start, end);
440
+ return { body, size: body.size };
441
+ }
442
+ };
443
+
444
+ // src/browser/browser-client.ts
445
+ var UStorageBrowserClient = class extends UStorageCoreClient {
446
+ constructor(options) {
447
+ super({
448
+ uploadBaseUrl: options.uploadBaseUrl,
449
+ resumeStore: options.resumeStore ?? new BrowserResumeStore(),
450
+ authHeaders: async () => {
451
+ if (options.bearerToken !== void 0) return { Authorization: `Bearer ${await resolveToken(options.bearerToken)}` };
452
+ if (options.uploadToken !== void 0) return { "x-upload-token": await resolveToken(options.uploadToken) };
453
+ throw new Error("browser auth requires bearerToken or uploadToken");
454
+ }
455
+ });
456
+ }
457
+ putObject(options) {
458
+ return this.uploadSource(new BrowserUploadSource(options.body, objectName(options.key)), options);
459
+ }
460
+ uploadFile(file, options) {
461
+ const key = options.key ?? ("name" in file ? file.name : "blob");
462
+ return this.uploadSource(new BrowserUploadSource(file, objectName(key)), { ...options, key });
463
+ }
464
+ };
465
+ function objectName(key) {
466
+ return key.split("/").filter(Boolean).at(-1) ?? key;
467
+ }
468
+ // Annotate the CommonJS export names for ESM import in node:
469
+ 0 && (module.exports = {
470
+ BrowserHttpClient,
471
+ BrowserResumeStore,
472
+ BrowserUploadSource,
473
+ FetchHttpClient,
474
+ MemoryResumeStore,
475
+ UStorageBrowserClient,
476
+ UStorageCoreClient,
477
+ UStorageError,
478
+ UploadApi,
479
+ Uploader,
480
+ resolveToken,
481
+ toUStorageError
482
+ });
483
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/browser/index.ts","../../src/core/auth/index.ts","../../src/core/errors/index.ts","../../src/core/http/index.ts","../../src/core/upload/api.ts","../../src/core/upload/checksum.ts","../../src/core/upload/file-metadata.ts","../../src/core/upload/uploader.ts","../../src/core/client/index.ts","../../src/core/upload/source.ts","../../src/browser/browser-resume-store.ts","../../src/browser/browser-upload-source.ts","../../src/browser/browser-client.ts"],"sourcesContent":["export * from '../core';\nexport * from './browser-client';\nexport * from './browser-http-client';\nexport * from './browser-resume-store';\nexport * from './browser-upload-source';\n","export type BrowserAuth =\n | { bearerToken: string | (() => string | Promise<string>); uploadToken?: never }\n | { uploadToken: string | (() => string | Promise<string>); bearerToken?: never };\n\nexport interface NodeCredentialAuth {\n accessKey: string;\n secretKey: string;\n}\n\nexport interface BearerAuth {\n bearerToken: string | (() => string | Promise<string>);\n}\n\nexport async function resolveToken(value: string | (() => string | Promise<string>)): Promise<string> {\n return typeof value === 'function' ? value() : value;\n}\n","import type { ErrorResponse } from '../types';\n\nexport class UStorageError extends Error {\n readonly code: string;\n readonly status: number;\n readonly requestId?: string;\n readonly details?: unknown;\n\n constructor(message: string, options: { code: string; status: number; requestId?: string; details?: unknown }) {\n super(message);\n this.name = 'UStorageError';\n this.code = options.code;\n this.status = options.status;\n this.requestId = options.requestId;\n this.details = options.details;\n }\n}\n\nexport function toUStorageError(status: number, body: unknown): UStorageError {\n const parsed = body as Partial<ErrorResponse>;\n if (parsed?.error?.code && parsed.error.message) {\n return new UStorageError(parsed.error.message, {\n code: parsed.error.code,\n status,\n requestId: parsed.request_id,\n details: parsed.error.details,\n });\n }\n return new UStorageError(`UStorage request failed with status ${status}`, { code: 'REQUEST_FAILED', status });\n}\n","import { toUStorageError } from '../errors';\n\nexport type HeaderValue = string | undefined | null;\n\nexport interface HttpRequestOptions {\n method: string;\n path: string;\n headers?: Record<string, HeaderValue>;\n query?: Record<string, string | number | boolean | undefined | null>;\n body?: unknown;\n signal?: AbortSignal;\n}\n\nexport interface HttpClient {\n request<T>(options: HttpRequestOptions): Promise<T>;\n}\n\nexport type AuthHeadersProvider = (request?: { method: string; path: string; body?: BodyInit }) => Record<string, string> | Promise<Record<string, string>>;\n\nexport class FetchHttpClient implements HttpClient {\n private readonly baseUrl: string;\n private readonly authHeaders?: AuthHeadersProvider;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: { baseUrl: string; authHeaders?: AuthHeadersProvider; fetchImpl?: typeof fetch }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\n this.authHeaders = options.authHeaders;\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async request<T>(options: HttpRequestOptions): Promise<T> {\n const headers = new Headers();\n for (const [key, value] of Object.entries(options.headers ?? {})) {\n if (value !== undefined && value !== null) headers.set(key, value);\n }\n let body: BodyInit | undefined;\n if (options.body !== undefined) {\n if (isBodyInit(options.body)) {\n body = options.body;\n } else {\n headers.set('content-type', headers.get('content-type') ?? 'application/json');\n body = JSON.stringify(options.body);\n }\n }\n const path = this.pathWithQuery(options.path, options.query);\n const authHeaders = this.authHeaders ? await this.authHeaders({ method: options.method, path, body }) : {};\n for (const [key, value] of Object.entries(authHeaders)) headers.set(key, value);\n const response = await this.fetchImpl(this.url(path), {\n method: options.method,\n headers,\n body,\n signal: options.signal,\n });\n if (response.status === 204) return undefined as T;\n const text = await response.text();\n const parsed = text ? parseJson(text) : undefined;\n if (!response.ok) throw toUStorageError(response.status, parsed);\n return parsed as T;\n }\n\n private url(path: string): string {\n return new URL(path.startsWith('/') ? path : `/${path}`, `${this.baseUrl}/`).toString();\n }\n\n private pathWithQuery(path: string, query?: HttpRequestOptions['query']): string {\n const url = new URL(path.startsWith('/') ? path : `/${path}`, 'http://sdk.local');\n for (const [key, value] of Object.entries(query ?? {})) {\n if (value !== undefined && value !== null) url.searchParams.set(key, String(value));\n }\n return `${url.pathname}${url.search}`;\n }\n}\n\nfunction parseJson(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction isBodyInit(value: unknown): value is BodyInit {\n return typeof Blob !== 'undefined' && value instanceof Blob ||\n typeof FormData !== 'undefined' && value instanceof FormData ||\n typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams ||\n typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer ||\n ArrayBuffer.isView(value) ||\n typeof ReadableStream !== 'undefined' && value instanceof ReadableStream;\n}\n","import type { HttpClient } from '../http';\nimport type { UploadBody } from './source';\nimport type {\n CompleteUploadRequest,\n CompleteUploadResponse,\n CreateFileUrlRequest,\n CreateFileUrlResponse,\n CreateUploadSessionRequest,\n CreateUploadSessionResponse,\n CreateUploadTokenRequest,\n CreateUploadTokenResponse,\n UploadChunkResponse,\n UploadStatusResponse,\n} from '../types';\n\nexport class UploadApi {\n constructor(private readonly http: HttpClient) {}\n\n createUploadToken(request: CreateUploadTokenRequest): Promise<CreateUploadTokenResponse> {\n return this.http.request({ method: 'POST', path: '/uploads/tokens', body: request });\n }\n\n createSession(request: CreateUploadSessionRequest): Promise<CreateUploadSessionResponse> {\n return this.http.request({ method: 'POST', path: '/uploads/sessions', body: request });\n }\n\n createFileUrl(request: CreateFileUrlRequest): Promise<CreateFileUrlResponse> {\n return this.http.request({ method: 'POST', path: '/files/url', body: request });\n }\n\n uploadChunk(uploadId: string, index: number, body: UploadBody, checksum?: string, signal?: AbortSignal): Promise<UploadChunkResponse> {\n return this.http.request({ method: 'PUT', path: `/uploads/${uploadId}/chunks/${index}`, headers: { 'x-chunk-checksum': checksum }, body, signal });\n }\n\n getStatus(uploadId: string): Promise<UploadStatusResponse> {\n return this.http.request({ method: 'GET', path: `/uploads/${uploadId}/status` });\n }\n\n complete(uploadId: string, request: CompleteUploadRequest = {}): Promise<CompleteUploadResponse> {\n return this.http.request({ method: 'POST', path: `/uploads/${uploadId}/complete`, body: request });\n }\n\n cancel(uploadId: string): Promise<void> {\n return this.http.request({ method: 'DELETE', path: `/uploads/${uploadId}` });\n }\n}\n","import type { UploadBody } from './source';\n\nexport async function sha256Hex(data: UploadBody): Promise<string> {\n const bytes = await toBytes(data);\n const digest = await crypto.subtle.digest('SHA-256', bytes);\n return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nasync function toBytes(data: UploadBody): Promise<ArrayBuffer> {\n if (data instanceof ArrayBuffer) return data;\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength).slice().buffer;\n if (typeof Blob !== 'undefined' && data instanceof Blob) return data.arrayBuffer();\n if (typeof data === 'string') return new TextEncoder().encode(data).buffer;\n return new Response(data).arrayBuffer();\n}\n","const mimeTypesByExtension: Record<string, string> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n svg: 'image/svg+xml',\n heic: 'image/heic',\n mp4: 'video/mp4',\n mpeg: 'video/mpeg',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n webm: 'video/webm',\n ogg: 'video/ogg',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n aac: 'audio/aac',\n m4a: 'audio/x-m4a',\n flac: 'audio/flac',\n amr: 'audio/amr',\n pdf: 'application/pdf',\n txt: 'text/plain',\n json: 'application/json',\n zip: 'application/zip',\n tar: 'application/x-tar',\n rar: 'application/vnd.rar',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n xls: 'application/vnd.ms-excel',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n ppt: 'application/vnd.ms-powerpoint',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n};\n\nexport function extensionFromName(nameOrKey: string): string | null {\n const filename = nameOrKey.split(/[\\\\/]/).filter(Boolean).at(-1) ?? nameOrKey;\n const dot = filename.lastIndexOf('.');\n if (dot <= 0 || dot === filename.length - 1) {\n return null;\n }\n return filename.slice(dot + 1).toLowerCase();\n}\n\nexport function mimeTypeFromExtension(extension: string | null): string | null {\n return extension ? mimeTypesByExtension[extension.toLowerCase()] ?? null : null;\n}\n\nexport function resolveUploadContentType(\n explicit: string | null | undefined,\n sourceType: string | null | undefined,\n ...names: Array<string | null | undefined>\n): string | null {\n const normalizedExplicit = normalizeContentType(explicit);\n if (normalizedExplicit) {\n return normalizedExplicit;\n }\n\n const normalizedSourceType = normalizeContentType(sourceType);\n if (normalizedSourceType) {\n return normalizedSourceType;\n }\n\n for (const name of names) {\n if (!name) continue;\n const inferred = mimeTypeFromExtension(extensionFromName(name));\n if (inferred) {\n return inferred;\n }\n }\n\n return null;\n}\n\nfunction normalizeContentType(value: string | null | undefined): string | null {\n const normalized = value?.trim();\n return normalized ? normalized : null;\n}\n","import { sha256Hex } from './checksum';\nimport { resolveUploadContentType } from './file-metadata';\nimport type { UploadApi } from './api';\nimport type { JsonValue, UploadChunkResponse, CompleteUploadResponse } from '../types';\nimport type { ResumeStore, UploadBody, UploadSource } from './source';\n\nexport interface PutObjectOptions {\n bucketName: string;\n key: string;\n workspaceName?: string;\n contentType?: string | null;\n metadata?: JsonValue;\n checksum?: false | 'sha256' | { file?: string; chunks?: Record<number, string> };\n resume?: boolean;\n resumeKey?: string;\n overwrite?: boolean;\n visibility?: 'public' | 'private';\n chunkSize?: number;\n signal?: AbortSignal;\n onProgress?: (event: UploadProgressEvent) => void;\n}\n\nexport interface UploadFileOptions extends Omit<PutObjectOptions, 'key'> {\n key?: string;\n}\n\nexport interface UploadProgressEvent {\n uploadId: string;\n chunkIndex?: number;\n uploadedChunks: number;\n totalChunks: number;\n uploadedSize: number;\n fileSize: number;\n progress: number;\n}\n\nexport interface UploadObjectResult extends CompleteUploadResponse {\n uploadId: string;\n fileId: string;\n publicId?: string;\n visibility?: 'public' | 'private' | string;\n url?: string;\n expiresAt?: string | null;\n}\n\nexport class Uploader {\n constructor(\n private readonly uploads: UploadApi,\n private readonly resumeStore?: ResumeStore,\n ) {}\n\n async putObject(source: UploadSource, options: PutObjectOptions): Promise<UploadObjectResult> {\n const chunkSize = options.chunkSize ?? 8 * 1024 * 1024;\n if (chunkSize <= 0) throw new Error('chunkSize must be positive');\n const totalChunks = source.size === 0 ? 1 : Math.ceil(source.size / chunkSize);\n const useResume = options.resume === true || Boolean(options.resumeKey);\n const resumeKey = useResume ? options.resumeKey ?? await source.fingerprint(options.key) : undefined;\n let uploadId = resumeKey && this.resumeStore ? await this.resumeStore.get(resumeKey) : undefined;\n let missingChunks: number[] | undefined;\n if (uploadId) {\n try {\n const status = await this.uploads.getStatus(uploadId);\n missingChunks = status.missing_chunks;\n options.onProgress?.(statusToProgress(status));\n } catch {\n uploadId = undefined;\n if (resumeKey) await this.resumeStore?.delete(resumeKey);\n }\n }\n if (!uploadId) {\n const session = await this.uploads.createSession({\n bucket_name: options.bucketName,\n key: options.key,\n workspace_name: options.workspaceName ?? null,\n mime_type: resolveUploadContentType(\n options.contentType,\n source.type,\n options.key,\n source.name,\n ),\n file_size: source.size,\n chunk_size: chunkSize,\n total_chunks: totalChunks,\n checksum: typeof options.checksum === 'object' ? options.checksum.file ?? null : null,\n metadata: options.metadata,\n overwrite: options.overwrite ?? true,\n visibility: options.visibility ?? null,\n });\n uploadId = session.upload_id;\n missingChunks = Array.from({ length: totalChunks }, (_, index) => index);\n if (resumeKey) await this.resumeStore?.set(resumeKey, uploadId);\n }\n for (const index of missingChunks ?? []) {\n const start = index * chunkSize;\n const end = source.size === 0 ? 0 : Math.min(source.size, start + chunkSize);\n const chunk = await source.slice(start, end);\n const checksum = await this.chunkChecksum(options.checksum, index, chunk.body);\n const response = await this.uploads.uploadChunk(uploadId, index, chunk.body, checksum, options.signal);\n options.onProgress?.(chunkResponseToProgress(response));\n }\n const complete = await this.uploads.complete(uploadId, { checksum: typeof options.checksum === 'object' ? options.checksum.file : undefined });\n if (resumeKey) await this.resumeStore?.delete(resumeKey);\n return {\n ...complete,\n uploadId: complete.upload_id,\n fileId: complete.file_id,\n publicId: complete.public_id,\n visibility: complete.visibility,\n url: complete.url,\n expiresAt: complete.expires_at ?? null,\n };\n }\n\n private async chunkChecksum(checksum: PutObjectOptions['checksum'], index: number, body: UploadBody): Promise<string | undefined> {\n if (!checksum) return undefined;\n if (checksum === 'sha256') return sha256Hex(body);\n return checksum.chunks?.[index];\n }\n}\n\nfunction chunkResponseToProgress(response: UploadChunkResponse): UploadProgressEvent {\n return {\n uploadId: response.upload_id,\n chunkIndex: response.chunk_index,\n uploadedChunks: response.uploaded_chunks,\n totalChunks: response.total_chunks,\n uploadedSize: response.uploaded_size,\n fileSize: response.file_size,\n progress: response.progress,\n };\n}\n\nfunction statusToProgress(response: { upload_id: string; uploaded_chunks: number[]; total_chunks: number; uploaded_size: number; file_size: number; progress: number }): UploadProgressEvent {\n return {\n uploadId: response.upload_id,\n uploadedChunks: response.uploaded_chunks.length,\n totalChunks: response.total_chunks,\n uploadedSize: response.uploaded_size,\n fileSize: response.file_size,\n progress: response.progress,\n };\n}\n","import { FetchHttpClient, type AuthHeadersProvider, type HttpClient } from '../http';\nimport { UploadApi } from '../upload/api';\nimport { Uploader } from '../upload/uploader';\nimport type { ResumeStore, UploadSource } from '../upload/source';\nimport type { GetObjectUrlInput, GetObjectUrlResult } from '../types';\nimport type { PutObjectOptions } from '../upload/uploader';\n\nexport interface UStorageClientOptions {\n uploadBaseUrl: string;\n authHeaders?: AuthHeadersProvider;\n uploadHttpClient?: HttpClient;\n resumeStore?: ResumeStore;\n}\n\nexport class UStorageCoreClient {\n readonly uploads: UploadApi;\n private readonly uploader: Uploader;\n\n constructor(options: UStorageClientOptions) {\n const uploadHttp = options.uploadHttpClient ?? new FetchHttpClient({ baseUrl: options.uploadBaseUrl, authHeaders: options.authHeaders });\n this.uploads = new UploadApi(uploadHttp);\n this.uploader = new Uploader(this.uploads, options.resumeStore);\n }\n\n async getObjectUrl(input: GetObjectUrlInput): Promise<GetObjectUrlResult> {\n const response = await this.uploads.createFileUrl({\n file_id: input.fileId ?? null,\n bucket: input.bucket ?? null,\n bucket_id: input.bucketId ?? null,\n key: input.key ?? null,\n path: input.path ?? null,\n expires_in: input.expiresIn ?? null,\n });\n return {\n fileId: response.file_id,\n publicId: response.public_id,\n visibility: response.visibility,\n url: response.url,\n expiresAt: response.expires_at,\n };\n }\n\n getSignedUrl(input: GetObjectUrlInput): Promise<GetObjectUrlResult> {\n return this.getObjectUrl(input);\n }\n\n protected uploadSource(source: UploadSource, options: PutObjectOptions) {\n return this.uploader.putObject(source, options);\n }\n}\n","export type UploadBody = BodyInit | ArrayBufferView;\n\nexport interface UploadChunk {\n body: UploadBody;\n size: number;\n}\n\nexport interface UploadSource {\n readonly name: string;\n readonly size: number;\n readonly type?: string;\n fingerprint(key?: string): string | Promise<string>;\n slice(start: number, end: number): UploadChunk | Promise<UploadChunk>;\n}\n\nexport interface ResumeStore {\n get(key: string): Promise<string | undefined> | string | undefined;\n set(key: string, uploadId: string): Promise<void> | void;\n delete(key: string): Promise<void> | void;\n}\n\nexport class MemoryResumeStore implements ResumeStore {\n private readonly values = new Map<string, string>();\n\n get(key: string): string | undefined {\n return this.values.get(key);\n }\n\n set(key: string, uploadId: string): void {\n this.values.set(key, uploadId);\n }\n\n delete(key: string): void {\n this.values.delete(key);\n }\n}\n","import { MemoryResumeStore, type ResumeStore } from '../core/upload/source';\n\nexport class BrowserResumeStore implements ResumeStore {\n private readonly memory = new MemoryResumeStore();\n\n constructor(private readonly prefix = 'ustorage:upload:') {}\n\n get(key: string): string | undefined {\n const storage = this.storage();\n return storage?.getItem(this.prefix + key) ?? this.memory.get(key);\n }\n\n set(key: string, uploadId: string): void {\n const storage = this.storage();\n if (storage) storage.setItem(this.prefix + key, uploadId);\n else this.memory.set(key, uploadId);\n }\n\n delete(key: string): void {\n const storage = this.storage();\n if (storage) storage.removeItem(this.prefix + key);\n else this.memory.delete(key);\n }\n\n private storage(): Storage | undefined {\n try {\n return typeof localStorage === 'undefined' ? undefined : localStorage;\n } catch {\n return undefined;\n }\n }\n}\n","import type { UploadChunk, UploadSource } from '../core/upload/source';\n\nexport class BrowserUploadSource implements UploadSource {\n readonly name: string;\n readonly size: number;\n readonly type?: string;\n private readonly lastModified?: number;\n\n constructor(private readonly file: Blob | File, name?: string) {\n this.name = name ?? ('name' in file ? file.name : 'blob');\n this.size = file.size;\n this.type = file.type || undefined;\n this.lastModified = 'lastModified' in file ? file.lastModified : undefined;\n }\n\n fingerprint(key?: string): string {\n return ['browser', key ?? '', this.name, this.size, this.type ?? '', this.lastModified ?? ''].join(':');\n }\n\n slice(start: number, end: number): UploadChunk {\n const body = this.file.slice(start, end);\n return { body, size: body.size };\n }\n}\n","import { resolveToken, type BrowserAuth } from '../core/auth';\nimport { UStorageCoreClient } from '../core/client';\nimport type { PutObjectOptions, UploadFileOptions } from '../core/upload/uploader';\nimport { BrowserResumeStore } from './browser-resume-store';\nimport { BrowserUploadSource } from './browser-upload-source';\n\nexport type UStorageBrowserClientOptions = BrowserAuth & {\n uploadBaseUrl: string;\n resumeStore?: BrowserResumeStore;\n};\n\nexport class UStorageBrowserClient extends UStorageCoreClient {\n constructor(options: UStorageBrowserClientOptions) {\n super({\n uploadBaseUrl: options.uploadBaseUrl,\n resumeStore: options.resumeStore ?? new BrowserResumeStore(),\n authHeaders: async (): Promise<Record<string, string>> => {\n if (options.bearerToken !== undefined) return { Authorization: `Bearer ${await resolveToken(options.bearerToken)}` };\n if (options.uploadToken !== undefined) return { 'x-upload-token': await resolveToken(options.uploadToken) };\n throw new Error('browser auth requires bearerToken or uploadToken');\n },\n });\n }\n\n putObject(options: PutObjectOptions & { body: Blob | File }) {\n return this.uploadSource(new BrowserUploadSource(options.body, objectName(options.key)), options);\n }\n\n uploadFile(file: File | Blob, options: UploadFileOptions) {\n const key = options.key ?? ('name' in file ? file.name : 'blob');\n return this.uploadSource(new BrowserUploadSource(file, objectName(key)), { ...options, key });\n }\n}\n\nfunction objectName(key: string): string {\n return key.split('/').filter(Boolean).at(-1) ?? key;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,37 @@
1
+ import { ResumeStore, UStorageCoreClient, BrowserAuth, PutObjectOptions, UploadObjectResult, UploadFileOptions, UploadSource, UploadChunk } from '../core/index.cjs';
2
+ export { AuthHeadersProvider, BearerAuth, FetchHttpClient as BrowserHttpClient, CompleteUploadRequest, CompleteUploadResponse, CreateFileUrlRequest, CreateFileUrlResponse, CreateUploadSessionRequest, CreateUploadSessionResponse, CreateUploadTokenRequest, CreateUploadTokenResponse, ErrorResponse, FetchHttpClient, GetObjectUrlInput, GetObjectUrlResult, HeaderValue, HttpClient, HttpRequestOptions, JsonValue, MemoryResumeStore, NodeCredentialAuth, UStorageClientOptions, UStorageError, UploadApi, UploadBody, UploadChunkResponse, UploadProgressEvent, UploadStatus, UploadStatusResponse, Uploader, resolveToken, toUStorageError } from '../core/index.cjs';
3
+
4
+ declare class BrowserResumeStore implements ResumeStore {
5
+ private readonly prefix;
6
+ private readonly memory;
7
+ constructor(prefix?: string);
8
+ get(key: string): string | undefined;
9
+ set(key: string, uploadId: string): void;
10
+ delete(key: string): void;
11
+ private storage;
12
+ }
13
+
14
+ type UStorageBrowserClientOptions = BrowserAuth & {
15
+ uploadBaseUrl: string;
16
+ resumeStore?: BrowserResumeStore;
17
+ };
18
+ declare class UStorageBrowserClient extends UStorageCoreClient {
19
+ constructor(options: UStorageBrowserClientOptions);
20
+ putObject(options: PutObjectOptions & {
21
+ body: Blob | File;
22
+ }): Promise<UploadObjectResult>;
23
+ uploadFile(file: File | Blob, options: UploadFileOptions): Promise<UploadObjectResult>;
24
+ }
25
+
26
+ declare class BrowserUploadSource implements UploadSource {
27
+ private readonly file;
28
+ readonly name: string;
29
+ readonly size: number;
30
+ readonly type?: string;
31
+ private readonly lastModified?;
32
+ constructor(file: Blob | File, name?: string);
33
+ fingerprint(key?: string): string;
34
+ slice(start: number, end: number): UploadChunk;
35
+ }
36
+
37
+ export { BrowserAuth, BrowserResumeStore, BrowserUploadSource, PutObjectOptions, ResumeStore, UStorageBrowserClient, type UStorageBrowserClientOptions, UStorageCoreClient, UploadChunk, UploadFileOptions, UploadObjectResult, UploadSource };
@@ -0,0 +1,37 @@
1
+ import { ResumeStore, UStorageCoreClient, BrowserAuth, PutObjectOptions, UploadObjectResult, UploadFileOptions, UploadSource, UploadChunk } from '../core/index.js';
2
+ export { AuthHeadersProvider, BearerAuth, FetchHttpClient as BrowserHttpClient, CompleteUploadRequest, CompleteUploadResponse, CreateFileUrlRequest, CreateFileUrlResponse, CreateUploadSessionRequest, CreateUploadSessionResponse, CreateUploadTokenRequest, CreateUploadTokenResponse, ErrorResponse, FetchHttpClient, GetObjectUrlInput, GetObjectUrlResult, HeaderValue, HttpClient, HttpRequestOptions, JsonValue, MemoryResumeStore, NodeCredentialAuth, UStorageClientOptions, UStorageError, UploadApi, UploadBody, UploadChunkResponse, UploadProgressEvent, UploadStatus, UploadStatusResponse, Uploader, resolveToken, toUStorageError } from '../core/index.js';
3
+
4
+ declare class BrowserResumeStore implements ResumeStore {
5
+ private readonly prefix;
6
+ private readonly memory;
7
+ constructor(prefix?: string);
8
+ get(key: string): string | undefined;
9
+ set(key: string, uploadId: string): void;
10
+ delete(key: string): void;
11
+ private storage;
12
+ }
13
+
14
+ type UStorageBrowserClientOptions = BrowserAuth & {
15
+ uploadBaseUrl: string;
16
+ resumeStore?: BrowserResumeStore;
17
+ };
18
+ declare class UStorageBrowserClient extends UStorageCoreClient {
19
+ constructor(options: UStorageBrowserClientOptions);
20
+ putObject(options: PutObjectOptions & {
21
+ body: Blob | File;
22
+ }): Promise<UploadObjectResult>;
23
+ uploadFile(file: File | Blob, options: UploadFileOptions): Promise<UploadObjectResult>;
24
+ }
25
+
26
+ declare class BrowserUploadSource implements UploadSource {
27
+ private readonly file;
28
+ readonly name: string;
29
+ readonly size: number;
30
+ readonly type?: string;
31
+ private readonly lastModified?;
32
+ constructor(file: Blob | File, name?: string);
33
+ fingerprint(key?: string): string;
34
+ slice(start: number, end: number): UploadChunk;
35
+ }
36
+
37
+ export { BrowserAuth, BrowserResumeStore, BrowserUploadSource, PutObjectOptions, ResumeStore, UStorageBrowserClient, type UStorageBrowserClientOptions, UStorageCoreClient, UploadChunk, UploadFileOptions, UploadObjectResult, UploadSource };