@visulima/storage 1.0.9 → 1.0.10
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/CHANGELOG.md +7 -0
- package/dist/adapter/nuxt/module.d.ts +8 -8
- package/dist/ai/ai-sdk/index.d.ts +51 -59
- package/dist/ai/claude/index.d.ts +104 -119
- package/dist/ai/openai/index.d.ts +86 -99
- package/dist/ai/tanstack/index.d.ts +53 -61
- package/dist/handler/http/fetch/index.d.ts +201 -201
- package/dist/handler/http/hono/index.d.ts +59 -59
- package/dist/handler/http/nextjs/index.d.ts +54 -54
- package/dist/handler/http/node/index.d.ts +233 -246
- package/dist/handler/http/solid-start/index.d.ts +54 -54
- package/dist/index.d.ts +70 -70
- package/dist/index.js +1 -1
- package/dist/packem_shared/{AwsLightStorage-BK-WPL0h.js → AwsLightStorage-EsqkAtU5.js} +1 -1
- package/dist/packem_shared/{AzureStorage-1UvDIQZd.js → AzureStorage-DL-U7qFG.js} +1 -1
- package/dist/packem_shared/BoxMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{BoxStorage-DbGqBLux.js → BoxStorage-B8_oCz27.js} +1 -1
- package/dist/packem_shared/BunS3MetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{BunS3Storage-DNvimm9e.js → BunS3Storage-_PVXu_na.js} +1 -1
- package/dist/packem_shared/BunnyMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{BunnyStorage-C7d0opLL.js → BunnyStorage-BsoWjScH.js} +1 -1
- package/dist/packem_shared/CloudinaryMetaStorage-BI9YXcwU.js +1 -0
- package/dist/packem_shared/{CloudinaryStorage-Dc3XA2lP.js → CloudinaryStorage-BNwiLF9V.js} +1 -1
- package/dist/packem_shared/{DiskStorage-CI07TVNu.js → DiskStorage-D-NtQDms.js} +1 -1
- package/dist/packem_shared/{DiskStorageWithChecksum-vFCubS6K.js → DiskStorageWithChecksum-UnCtyEvs.js} +1 -1
- package/dist/packem_shared/DropboxMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{DropboxStorage-CY9Ggu3m.js → DropboxStorage-BS9kj0nH.js} +1 -1
- package/dist/packem_shared/FirebaseMetaStorage-BI9YXcwU.js +1 -0
- package/dist/packem_shared/{FirebaseStorage-D6O9CJXN.js → FirebaseStorage-DNquii2p.js} +1 -1
- package/dist/packem_shared/FtpMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{FtpStorage-DbEjbq8z.js → FtpStorage-Bd004--s.js} +1 -1
- package/dist/packem_shared/{GCSMetaStorage-DT8K6zdm.js → GCSMetaStorage-Bf4qDFB1.js} +1 -1
- package/dist/packem_shared/{GCStorage-6BHkFlEs.js → GCStorage-ChqEpgqR.js} +1 -1
- package/dist/packem_shared/GoogleDriveMetaStorage-xlHfKwmR.js +1 -0
- package/dist/packem_shared/{GoogleDriveStorage-Bklsz7Bh.js → GoogleDriveStorage-v1glykjd.js} +1 -1
- package/dist/packem_shared/{LocalMetaStorage-BhicZnNl.js → LocalMetaStorage-YWPBYEe7.js} +1 -1
- package/dist/packem_shared/NetlifyBlobMetaStorage-BI9YXcwU.js +1 -0
- package/dist/packem_shared/{NetlifyBlobStorage-CkpCCoN1.js → NetlifyBlobStorage-BPyEWSnx.js} +1 -1
- package/dist/packem_shared/OneDriveMetaStorage-xlHfKwmR.js +1 -0
- package/dist/packem_shared/{OneDriveStorage-CP6MvGAa.js → OneDriveStorage-BJ3Kzxc5.js} +1 -1
- package/dist/packem_shared/PocketBaseMetaStorage-DnrxOQhO.js +1 -0
- package/dist/packem_shared/{PocketBaseStorage-2qhbI2PW.js → PocketBaseStorage-DqKHbbvn.js} +1 -1
- package/dist/packem_shared/{S3Storage-YGeNk3Tt.js → S3Storage-BiI2k6d1.js} +1 -1
- package/dist/packem_shared/SftpMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{SftpStorage-2Hz396Xr.js → SftpStorage-w8XdtZtw.js} +1 -1
- package/dist/packem_shared/SharePointMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{SharePointStorage-CrX2Pk6C.js → SharePointStorage-DpDpI7Ln.js} +1 -1
- package/dist/packem_shared/SupabaseMetaStorage-xlHfKwmR.js +1 -0
- package/dist/packem_shared/{SupabaseStorage-Dc_DBX29.js → SupabaseStorage-B_ugUCs7.js} +1 -1
- package/dist/packem_shared/UploadThingMetaStorage-BI9YXcwU.js +1 -0
- package/dist/packem_shared/{UploadThingStorage-BChykYSe.js → UploadThingStorage-_H45IVqX.js} +1 -1
- package/dist/packem_shared/VercelBlobMetaStorage-CHWrhgg2.js +1 -0
- package/dist/packem_shared/{VercelBlobStorage-CsRyPfw3.js → VercelBlobStorage-U1YMKeHs.js} +1 -1
- package/dist/packem_shared/{approval.d-CMAYH9GF.d.ts → approval.d-C-d-t94D.d.ts} +6 -6
- package/dist/packem_shared/disk-storage-BwPk2IRa.js +1 -0
- package/dist/packem_shared/disk-storage-with-checksum.d-CQucFacO.d.ts +146 -0
- package/dist/packem_shared/{executors.d-BZP2rWo3.d.ts → executors.d-DeDH3Ilt.d.ts} +2 -2
- package/dist/packem_shared/files.d-D8H_ge9Y.d.ts +655 -0
- package/dist/packem_shared/{gcs-meta-storage-B7BnctnV.js → gcs-meta-storage-DQGu_cHq.js} +1 -1
- package/dist/packem_shared/local-meta-storage-DJDcuxf1.js +11 -0
- package/dist/packem_shared/{local-meta-storage.d-D9PBfkn6.d.ts → local-meta-storage.d-DuTEzyii.d.ts} +7 -7
- package/dist/packem_shared/media-transformer.d-CvMFjINm.d.ts +331 -0
- package/dist/packem_shared/{memory-storage.d-4EU1cMt1.d.ts → memory-storage.d-BRdTiY8y.d.ts} +32 -40
- package/dist/packem_shared/{s3-base-storage-BoTyhuzO.js → s3-base-storage-CMUui93V.js} +1 -1
- package/dist/packem_shared/{s3-base-storage.d-BQgP5B-t.d.ts → s3-base-storage.d-Cg7m4FuH.d.ts} +64 -70
- package/dist/packem_shared/storage.d-DIav_lF1.d.ts +1163 -0
- package/dist/packem_shared/tus-base.d-BiEg5t4t.d.ts +102 -0
- package/dist/packem_shared/{types.d-CrUWY4On.d.ts → types.d-CAAzKiI6.d.ts} +134 -134
- package/dist/packem_shared/types.d-DgHhkCAl.d.ts +104 -0
- package/dist/packem_shared/{types.d-CggTCgXr.d.ts → types.d-jAs_Rp_v.d.ts} +3 -3
- package/dist/storage/aws/clients/index.d.ts +388 -388
- package/dist/storage/aws/index.d.ts +109 -113
- package/dist/storage/aws/index.js +1 -1
- package/dist/storage/aws-light/index.d.ts +63 -67
- package/dist/storage/aws-light/index.js +1 -1
- package/dist/storage/azure/index.d.ts +133 -139
- package/dist/storage/azure/index.js +1 -1
- package/dist/storage/box/index.d.ts +88 -92
- package/dist/storage/box/index.js +1 -1
- package/dist/storage/bun-s3/index.d.ts +70 -76
- package/dist/storage/bun-s3/index.js +1 -1
- package/dist/storage/bunny/index.d.ts +51 -55
- package/dist/storage/bunny/index.js +1 -1
- package/dist/storage/cloudinary/index.d.ts +53 -59
- package/dist/storage/cloudinary/index.js +1 -1
- package/dist/storage/dropbox/index.d.ts +58 -62
- package/dist/storage/dropbox/index.js +1 -1
- package/dist/storage/firebase/index.d.ts +73 -79
- package/dist/storage/firebase/index.js +1 -1
- package/dist/storage/ftp/index.d.ts +37 -43
- package/dist/storage/ftp/index.js +1 -1
- package/dist/storage/gcs/index.d.ts +89 -95
- package/dist/storage/gcs/index.js +1 -1
- package/dist/storage/google-drive/index.d.ts +68 -72
- package/dist/storage/google-drive/index.js +1 -1
- package/dist/storage/local/index.d.ts +3 -3
- package/dist/storage/local/index.js +1 -1
- package/dist/storage/memory/index.d.ts +2 -2
- package/dist/storage/netlify-blob/index.d.ts +85 -93
- package/dist/storage/netlify-blob/index.js +1 -1
- package/dist/storage/onedrive/index.d.ts +43 -53
- package/dist/storage/onedrive/index.js +1 -1
- package/dist/storage/pocketbase/index.d.ts +66 -72
- package/dist/storage/pocketbase/index.js +1 -1
- package/dist/storage/sftp/index.d.ts +39 -45
- package/dist/storage/sftp/index.js +1 -1
- package/dist/storage/sharepoint/index.d.ts +95 -95
- package/dist/storage/sharepoint/index.js +1 -1
- package/dist/storage/supabase/index.d.ts +49 -55
- package/dist/storage/supabase/index.js +1 -1
- package/dist/storage/uploadthing/index.d.ts +33 -37
- package/dist/storage/uploadthing/index.js +1 -1
- package/dist/storage/vercel-blob/index.d.ts +109 -115
- package/dist/storage/vercel-blob/index.js +1 -1
- package/dist/transformer/audio-transformer.d.ts +96 -96
- package/dist/transformer/image-transformer.d.ts +422 -422
- package/dist/transformer/index.d.ts +34 -34
- package/dist/transformer/video-transformer.d.ts +111 -111
- package/package.json +1 -1
- package/dist/packem_shared/BoxMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/BunS3MetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/BunnyMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/CloudinaryMetaStorage-DPVnmNe5.js +0 -1
- package/dist/packem_shared/DropboxMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/FirebaseMetaStorage-DPVnmNe5.js +0 -1
- package/dist/packem_shared/FtpMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/GoogleDriveMetaStorage-Cbwa1CHV.js +0 -1
- package/dist/packem_shared/NetlifyBlobMetaStorage-DPVnmNe5.js +0 -1
- package/dist/packem_shared/OneDriveMetaStorage-Cbwa1CHV.js +0 -1
- package/dist/packem_shared/PocketBaseMetaStorage-DOTLwVE7.js +0 -1
- package/dist/packem_shared/SftpMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/SharePointMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/SupabaseMetaStorage-Cbwa1CHV.js +0 -1
- package/dist/packem_shared/UploadThingMetaStorage-DPVnmNe5.js +0 -1
- package/dist/packem_shared/VercelBlobMetaStorage-BSn6Qfnf.js +0 -1
- package/dist/packem_shared/disk-storage-CsQcYW3s.js +0 -1
- package/dist/packem_shared/disk-storage-with-checksum.d-B-VGEsfl.d.ts +0 -156
- package/dist/packem_shared/files.d-CH0iLBNC.d.ts +0 -655
- package/dist/packem_shared/local-meta-storage-iuJnu90B.js +0 -11
- package/dist/packem_shared/media-transformer.d-Quf4ai47.d.ts +0 -331
- package/dist/packem_shared/storage.d-CEM1upWM.d.ts +0 -1176
- package/dist/packem_shared/tus-base.d-DLzKE54M.d.ts +0 -106
- package/dist/packem_shared/types.d-Bon9GVVe.d.ts +0 -104
|
@@ -0,0 +1,1163 @@
|
|
|
1
|
+
import { Transform, Readable } from 'node:stream';
|
|
2
|
+
import { BinaryToTextEncoding, Hash } from 'node:crypto';
|
|
3
|
+
import { IncomingMessage } from 'node:http';
|
|
4
|
+
import { LRUCache } from 'lru-cache';
|
|
5
|
+
/**
|
|
6
|
+
* Simple cache interface that any cache implementation can follow
|
|
7
|
+
*/
|
|
8
|
+
interface Cache<K = string, V = unknown> {
|
|
9
|
+
/** Clear all cache entries */
|
|
10
|
+
clear: () => void | Promise<void>;
|
|
11
|
+
/** Delete a value from cache */
|
|
12
|
+
delete: (key: K) => boolean | Promise<boolean>;
|
|
13
|
+
/** Get a value from cache */
|
|
14
|
+
get: (key: K) => V | undefined | Promise<V | undefined>;
|
|
15
|
+
/** Check if a key exists in cache */
|
|
16
|
+
has: (key: K) => boolean | Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Optional. Iterate over the cache's current keys. Required for prefix-based
|
|
19
|
+
* eviction (`clearCache(fileId)` in transformers) — when absent, per-file
|
|
20
|
+
* clear falls back to a full `clear()`. `LRUCache` from `lru-cache`
|
|
21
|
+
* satisfies this out of the box.
|
|
22
|
+
*/
|
|
23
|
+
keys?: () => Iterable<K>;
|
|
24
|
+
/** Set a value in cache */
|
|
25
|
+
set: (key: K, value: V, options?: CacheOptions) => boolean | Promise<boolean>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for cache operations
|
|
29
|
+
*/
|
|
30
|
+
interface CacheOptions {
|
|
31
|
+
/** TTL in milliseconds */
|
|
32
|
+
ttl?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Transform that computes a rolling checksum for a stream while passing
|
|
36
|
+
* data through unchanged.
|
|
37
|
+
*/
|
|
38
|
+
interface RangeChecksum extends Transform {
|
|
39
|
+
/** Return the current digest in the selected encoding. */
|
|
40
|
+
digest: (encoding: BinaryToTextEncoding) => string;
|
|
41
|
+
hash: Hash;
|
|
42
|
+
path: string;
|
|
43
|
+
reset: () => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* LRU-backed map of rolling hashers keyed by file path. Used to compute
|
|
47
|
+
* hex/base64 digests and resume hashing from an offset.
|
|
48
|
+
*/
|
|
49
|
+
interface RangeHasher extends LRUCache<string, Hash> {
|
|
50
|
+
algorithm: "md5" | "sha1";
|
|
51
|
+
base64: (path: string) => string;
|
|
52
|
+
digester: (path: string) => RangeChecksum;
|
|
53
|
+
hex: (path: string) => string;
|
|
54
|
+
init: (path: string, start: number) => Promise<Hash>;
|
|
55
|
+
updateFromFs: (path: string, start: number, initial?: Hash) => Promise<Hash>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Normalized HTTP error payload returned by handlers and storage backends.
|
|
59
|
+
*/
|
|
60
|
+
interface HttpErrorBody {
|
|
61
|
+
code: string;
|
|
62
|
+
detail?: Record<string, unknown> | string;
|
|
63
|
+
message: string;
|
|
64
|
+
name?: string;
|
|
65
|
+
retryable?: boolean;
|
|
66
|
+
UploadErrorCode?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Rich HTTP error including status code and optional headers/body.
|
|
70
|
+
*/
|
|
71
|
+
interface HttpError<T = HttpErrorBody> extends UploadResponse<T> {
|
|
72
|
+
statusCode: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Node.js IncomingMessage with an optional parsed body attached.
|
|
76
|
+
*/
|
|
77
|
+
interface IncomingMessageWithBody<T = unknown> extends IncomingMessage {
|
|
78
|
+
_body?: boolean;
|
|
79
|
+
body?: T;
|
|
80
|
+
}
|
|
81
|
+
type Header = string[] | number | string;
|
|
82
|
+
type Headers = Record<string, Header>;
|
|
83
|
+
type ResponseBody = Record<string, unknown> | string | Buffer | Uint8Array;
|
|
84
|
+
type ResponseBodyType = "json" | "text";
|
|
85
|
+
/**
|
|
86
|
+
* Tuple form for quick response definitions: [status, body, headers].
|
|
87
|
+
*/
|
|
88
|
+
type ResponseTuple<T = ResponseBody> = [statusCode: number, body?: T, headers?: Headers];
|
|
89
|
+
/**
|
|
90
|
+
* Structured response used across handlers and storage operations.
|
|
91
|
+
*/
|
|
92
|
+
interface UploadResponse<T = ResponseBody> extends Record<string, unknown> {
|
|
93
|
+
body?: T;
|
|
94
|
+
headers?: Headers;
|
|
95
|
+
statusCode?: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Declarative validator configuration for a single rule.
|
|
99
|
+
*/
|
|
100
|
+
interface ValidatorConfig<T> {
|
|
101
|
+
isValid?: (t: T) => Promise<boolean> | boolean;
|
|
102
|
+
response?: HttpError | ResponseTuple;
|
|
103
|
+
value?: unknown;
|
|
104
|
+
}
|
|
105
|
+
/** Map of rule-name -> validator configuration. */
|
|
106
|
+
type Validation<T> = Record<string, ValidatorConfig<T>>;
|
|
107
|
+
/** Narrowed error response shape for validation failures. */
|
|
108
|
+
interface ValidationError extends HttpError {
|
|
109
|
+
code: string;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Metrics interface for observability.
|
|
113
|
+
* Provides counters, timers, and gauges for tracking storage operations.
|
|
114
|
+
*/
|
|
115
|
+
interface Metrics {
|
|
116
|
+
/**
|
|
117
|
+
* Set a gauge metric value.
|
|
118
|
+
* @param name Metric name (e.g., "storage.files.size")
|
|
119
|
+
* @param value Gauge value
|
|
120
|
+
* @param attributes Optional attributes/labels
|
|
121
|
+
*/
|
|
122
|
+
gauge: (name: string, value: number, attributes?: Record<string, string | number>) => void;
|
|
123
|
+
/**
|
|
124
|
+
* Increment a counter metric.
|
|
125
|
+
* @param name Metric name (e.g., "storage.operations.create.count")
|
|
126
|
+
* @param value Increment value (default: 1)
|
|
127
|
+
* @param attributes Optional attributes/labels (e.g., { storage: "s3", operation: "create" })
|
|
128
|
+
*/
|
|
129
|
+
increment: (name: string, value?: number, attributes?: Record<string, string | number>) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Record a duration/timing metric in milliseconds.
|
|
132
|
+
* @param name Metric name (e.g., "storage.operations.write.duration")
|
|
133
|
+
* @param duration Duration in milliseconds
|
|
134
|
+
* @param attributes Optional attributes/labels
|
|
135
|
+
*/
|
|
136
|
+
timing: (name: string, duration: number, attributes?: Record<string, string | number>) => void;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Canonical error codes used across handlers and storage adapters.
|
|
140
|
+
* These codes map to standardized HTTP status codes and error messages.
|
|
141
|
+
*/
|
|
142
|
+
declare enum ERRORS {
|
|
143
|
+
BAD_REQUEST = "BadRequest",
|
|
144
|
+
CHECKSUM_MISMATCH = "ChecksumMismatch",
|
|
145
|
+
FILE_CONFLICT = "FileConflict",
|
|
146
|
+
FILE_ERROR = "FileError",
|
|
147
|
+
FILE_LOCKED = "FileLocked",
|
|
148
|
+
FILE_NOT_ALLOWED = "FileNotAllowed",
|
|
149
|
+
FILE_NOT_FOUND = "FileNotFound",
|
|
150
|
+
FORBIDDEN = "Forbidden",
|
|
151
|
+
GONE = "Gone",
|
|
152
|
+
INVALID_FILE_NAME = "InvalidFileName",
|
|
153
|
+
INVALID_FILE_SIZE = "InvalidFileSize",
|
|
154
|
+
INVALID_RANGE = "InvalidRange",
|
|
155
|
+
INVALID_TYPE = "Invalidtype",
|
|
156
|
+
METHOD_NOT_ALLOWED = "MethodNotAllowed",
|
|
157
|
+
READ_ONLY = "ReadOnly",
|
|
158
|
+
REQUEST_ABORTED = "RequestAborted",
|
|
159
|
+
REQUEST_ENTITY_TOO_LARGE = "RequestEntityTooLarge",
|
|
160
|
+
STORAGE_BUSY = "StorageBusy",
|
|
161
|
+
STORAGE_ERROR = "StorageError",
|
|
162
|
+
TOO_MANY_REQUESTS = "TooManyRequests",
|
|
163
|
+
UNKNOWN_ERROR = "UnknownError",
|
|
164
|
+
UNPROCESSABLE_ENTITY = "UnprocessableEntity",
|
|
165
|
+
UNSUPPORTED_CHECKSUM_ALGORITHM = "UnsupportedChecksumAlgorithm",
|
|
166
|
+
UNSUPPORTED_MEDIA_TYPE = "UnsupportedMediaType"
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Type mapping of error codes to standardized HTTP error responses.
|
|
170
|
+
* @template T - The error code type (defaults to string)
|
|
171
|
+
*/
|
|
172
|
+
type ErrorResponses<T extends string = string> = { [K in T]: HttpError; };
|
|
173
|
+
/**
|
|
174
|
+
* Mapping of error codes to HttpError response objects.
|
|
175
|
+
* @returns Map of error codes to standardized HTTP error responses
|
|
176
|
+
*/
|
|
177
|
+
declare const ErrorMap: ErrorResponses<ERRORS>;
|
|
178
|
+
/**
|
|
179
|
+
* Error subclass carrying a stable error code and optional detail.
|
|
180
|
+
* Provides structured error information for upload operations.
|
|
181
|
+
*/
|
|
182
|
+
declare class UploadError extends Error {
|
|
183
|
+
override name: string;
|
|
184
|
+
/** The standardized error code from the ERRORS enum */
|
|
185
|
+
UploadErrorCode: ERRORS;
|
|
186
|
+
/** Optional additional error details */
|
|
187
|
+
detail?: unknown;
|
|
188
|
+
/**
|
|
189
|
+
* Creates a new UploadError instance.
|
|
190
|
+
* @param code Standardized error code (defaults to UNKNOWN_ERROR)
|
|
191
|
+
* @param message Human-readable error message (defaults to the code)
|
|
192
|
+
* @param detail Optional additional error details
|
|
193
|
+
*/
|
|
194
|
+
constructor(code?: ERRORS, message?: string, detail?: unknown);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Type guard to check if an error is an UploadError instance.
|
|
198
|
+
* @param error Error to check
|
|
199
|
+
* @returns True if the error is an UploadError with a valid error code
|
|
200
|
+
*/
|
|
201
|
+
declare const isUploadError: (error: unknown) => error is UploadError;
|
|
202
|
+
/**
|
|
203
|
+
* Best-effort extraction of an HTTP status from a native SDK error.
|
|
204
|
+
*
|
|
205
|
+
* Covers the shapes used by the consumer-provider SDKs:
|
|
206
|
+
* - Dropbox `DropboxResponseError` → `error.status`
|
|
207
|
+
* - Box `BoxAPIError` / Microsoft Graph errors → `error.statusCode`
|
|
208
|
+
* - googleapis errors → `error.code` (numeric) or `error.response.status`
|
|
209
|
+
* - Supabase / fetch-style errors → `error.status` or `error.response.status`
|
|
210
|
+
*/
|
|
211
|
+
declare const extractHttpStatus: (error: unknown) => number | undefined;
|
|
212
|
+
/**
|
|
213
|
+
* Map an HTTP status code to the closest canonical ERRORS value.
|
|
214
|
+
*
|
|
215
|
+
* Returns STORAGE_ERROR for unknown/5xx and BAD_REQUEST for unmapped 4xx.
|
|
216
|
+
* 401 (unauthenticated) collapses to FORBIDDEN because the ERRORS enum has
|
|
217
|
+
* no dedicated UNAUTHORIZED value; callers needing to distinguish the two
|
|
218
|
+
* should inspect the native error on `UploadError.detail`.
|
|
219
|
+
*/
|
|
220
|
+
declare const mapStatusToErrorCode: (status?: number) => ERRORS;
|
|
221
|
+
/**
|
|
222
|
+
* Normalize a native storage-SDK error into an `UploadError`.
|
|
223
|
+
*
|
|
224
|
+
* The native error is preserved on `.detail` so advanced callers can drop down
|
|
225
|
+
* to provider-specific shapes when needed. Already-wrapped `UploadError`
|
|
226
|
+
* instances pass through unchanged.
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* try {
|
|
230
|
+
* await client.filesCopyV2({ from_path, to_path });
|
|
231
|
+
* } catch (error) {
|
|
232
|
+
* throw wrapStorageError(error, { adapter: "Dropbox", operation: "copy" });
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
declare const wrapStorageError: (error: unknown, options: {
|
|
237
|
+
adapter: string;
|
|
238
|
+
code?: ERRORS;
|
|
239
|
+
message?: string;
|
|
240
|
+
operation: string;
|
|
241
|
+
status?: number;
|
|
242
|
+
}) => UploadError;
|
|
243
|
+
/**
|
|
244
|
+
* Convenience function to throw an UploadError from a string error code.
|
|
245
|
+
* Looks up the appropriate error message from ErrorMap.
|
|
246
|
+
* @param UploadErrorCode String error code to convert to UploadError
|
|
247
|
+
* @param detail Optional additional error details
|
|
248
|
+
* @throws UploadError with the specified code and message
|
|
249
|
+
*/
|
|
250
|
+
declare const throwErrorCode: (UploadErrorCode: ERRORS | string, detail?: string) => never;
|
|
251
|
+
/**
|
|
252
|
+
* A simple lock map keyed by strings, backed by LRUCache. Locks
|
|
253
|
+
* automatically expire according to the configured TTL preventing deadlocks.
|
|
254
|
+
*
|
|
255
|
+
* Each successful `lock()` returns a unique token; the corresponding `unlock(key, token)`
|
|
256
|
+
* call only releases the lock when the token matches the current holder. This prevents a
|
|
257
|
+
* stale lock owner (e.g. one whose entry TTL'd out and was re-acquired by another caller)
|
|
258
|
+
* from releasing another caller's lock by accident.
|
|
259
|
+
*/
|
|
260
|
+
declare class Locker<K extends string = string> extends LRUCache<K, string, number> {
|
|
261
|
+
constructor(options?: LRUCache.Options<K, string, number>);
|
|
262
|
+
/**
|
|
263
|
+
* Acquires a lock for the specified key.
|
|
264
|
+
* @returns A unique token identifying the lock holder.
|
|
265
|
+
* @throws Error if the key is already locked.
|
|
266
|
+
*/
|
|
267
|
+
lock(key: K): string;
|
|
268
|
+
/**
|
|
269
|
+
* Releases the lock for the specified key, but only if the token matches the current holder.
|
|
270
|
+
* Silently no-ops when the lock has expired or is owned by someone else — releasing somebody
|
|
271
|
+
* else's lock is worse than leaving a stale entry to TTL out on its own.
|
|
272
|
+
* @returns true if the lock was released, false if it was already gone or owned by another caller.
|
|
273
|
+
*/
|
|
274
|
+
unlock(key: K, token: string): boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Retry configuration options for storage operations
|
|
278
|
+
*/
|
|
279
|
+
interface RetryConfig {
|
|
280
|
+
/**
|
|
281
|
+
* Multiplier for exponential backoff (e.g., 2 means delays double each retry)
|
|
282
|
+
* @default 2
|
|
283
|
+
*/
|
|
284
|
+
backoffMultiplier?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Custom function to calculate delay for a specific retry attempt
|
|
287
|
+
* @param attempt The current retry attempt (0-indexed)
|
|
288
|
+
* @param error The error that occurred
|
|
289
|
+
* @returns Delay in milliseconds, or undefined to use default exponential backoff
|
|
290
|
+
*/
|
|
291
|
+
calculateDelay?: (attempt: number, error: unknown) => number | undefined;
|
|
292
|
+
/**
|
|
293
|
+
* Initial delay in milliseconds before first retry
|
|
294
|
+
* @default 1000
|
|
295
|
+
*/
|
|
296
|
+
initialDelay?: number;
|
|
297
|
+
/**
|
|
298
|
+
* Maximum delay in milliseconds between retries
|
|
299
|
+
* @default 30000
|
|
300
|
+
*/
|
|
301
|
+
maxDelay?: number;
|
|
302
|
+
/**
|
|
303
|
+
* Maximum number of retry attempts
|
|
304
|
+
* @default 3
|
|
305
|
+
*/
|
|
306
|
+
maxRetries?: number;
|
|
307
|
+
/**
|
|
308
|
+
* Fire-and-forget hook invoked **before** each retry attempt's backoff sleep.
|
|
309
|
+
* `attempt` is 1-based (1 = first retry, i.e. after the initial call failed).
|
|
310
|
+
* Exceptions thrown by this callback are swallowed so an observability hook
|
|
311
|
+
* can never fail the underlying operation.
|
|
312
|
+
*/
|
|
313
|
+
onRetry?: (attempt: number, error: unknown) => void;
|
|
314
|
+
/**
|
|
315
|
+
* HTTP status codes that should trigger a retry
|
|
316
|
+
* @default [408, 429, 500, 502, 503, 504]
|
|
317
|
+
*/
|
|
318
|
+
retryableStatusCodes?: number[];
|
|
319
|
+
/**
|
|
320
|
+
* Custom function to determine if an error should be retried
|
|
321
|
+
* @param error The error that occurred
|
|
322
|
+
* @returns true if the error should be retried, false otherwise
|
|
323
|
+
*/
|
|
324
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Determines if an error is retryable based on common patterns
|
|
328
|
+
* @param error The error to check
|
|
329
|
+
* @param retryableStatusCodes HTTP status codes that should trigger retry
|
|
330
|
+
* @returns true if the error is retryable
|
|
331
|
+
*/
|
|
332
|
+
declare const isRetryableError: (error: unknown, retryableStatusCodes?: number[]) => boolean;
|
|
333
|
+
/**
|
|
334
|
+
* Retry an async operation with exponential backoff
|
|
335
|
+
* @param fn The async function to retry
|
|
336
|
+
* @param config Retry configuration
|
|
337
|
+
* @returns The result of the function
|
|
338
|
+
* @throws The last error if all retries are exhausted
|
|
339
|
+
*/
|
|
340
|
+
declare const retry: <T>(function_: () => Promise<T>, config?: RetryConfig) => Promise<T>;
|
|
341
|
+
/**
|
|
342
|
+
* Create a retry wrapper function with pre-configured settings.
|
|
343
|
+
* @param config Retry configuration
|
|
344
|
+
* @returns A function that wraps async operations with retry logic
|
|
345
|
+
*/
|
|
346
|
+
declare const createRetryWrapper: (config?: RetryConfig) => <T>(function_: () => Promise<T>) => Promise<T>;
|
|
347
|
+
/**
|
|
348
|
+
* Configurable validation system for file upload constraints.
|
|
349
|
+
* Supports multiple validation rules with custom error responses.
|
|
350
|
+
* @template T - The type being validated
|
|
351
|
+
*/
|
|
352
|
+
declare class Validator<T> {
|
|
353
|
+
private prefix;
|
|
354
|
+
private validators;
|
|
355
|
+
/**
|
|
356
|
+
* Creates a new Validator instance.
|
|
357
|
+
* @param prefix Prefix for generated error codes (default: "ValidationError")
|
|
358
|
+
*/
|
|
359
|
+
constructor(prefix?: string);
|
|
360
|
+
/**
|
|
361
|
+
* Adds validation rules to the validator.
|
|
362
|
+
* Each rule must include an `isValid` function.
|
|
363
|
+
* @param config Validation configuration object
|
|
364
|
+
* @throws TypeError if any validator is missing the isValid function
|
|
365
|
+
*/
|
|
366
|
+
add(config: Validation<T>): void;
|
|
367
|
+
/**
|
|
368
|
+
* Verifies an object against all configured validation rules.
|
|
369
|
+
* Throws ValidationError on first validation failure.
|
|
370
|
+
* @param t Object to validate
|
|
371
|
+
* @throws ValidationError if validation fails
|
|
372
|
+
*/
|
|
373
|
+
verify(t: T): Promise<never | void>;
|
|
374
|
+
}
|
|
375
|
+
interface MetaStorageOptions {
|
|
376
|
+
logger?: Console;
|
|
377
|
+
prefix?: string;
|
|
378
|
+
suffix?: string;
|
|
379
|
+
}
|
|
380
|
+
interface LocalMetaStorageOptions extends MetaStorageOptions {
|
|
381
|
+
/**
|
|
382
|
+
* Where the upload metadata should be stored
|
|
383
|
+
*/
|
|
384
|
+
directory?: string;
|
|
385
|
+
}
|
|
386
|
+
declare class Metadata {
|
|
387
|
+
[key: string]: unknown;
|
|
388
|
+
psize?: number | string;
|
|
389
|
+
pname?: string;
|
|
390
|
+
pfiletype?: string;
|
|
391
|
+
ptype?: string;
|
|
392
|
+
pmimeType?: string;
|
|
393
|
+
pcontentType?: string;
|
|
394
|
+
ptitle?: string;
|
|
395
|
+
pfilename?: string;
|
|
396
|
+
poriginalName?: string;
|
|
397
|
+
plastModified?: number | string;
|
|
398
|
+
}
|
|
399
|
+
interface FileInit {
|
|
400
|
+
contentType?: string;
|
|
401
|
+
expiredAt?: Date | number | string;
|
|
402
|
+
/**
|
|
403
|
+
* Explicit identifier. When provided, the File constructor uses it directly
|
|
404
|
+
* instead of deriving an id from originalName/size/mtime. Lets callers map a
|
|
405
|
+
* user-chosen storage key (e.g. `"avatars/abc.png"`) onto the metadata id.
|
|
406
|
+
*/
|
|
407
|
+
id?: string;
|
|
408
|
+
metadata: Metadata;
|
|
409
|
+
originalName?: string;
|
|
410
|
+
size?: number | string;
|
|
411
|
+
storageClass?: string;
|
|
412
|
+
ttl?: number | string;
|
|
413
|
+
}
|
|
414
|
+
interface FileReturn extends Omit<Required<FileInit>, "id" | "storageClass" | "ttl" | "expiredAt"> {
|
|
415
|
+
content: Buffer;
|
|
416
|
+
ETag?: string;
|
|
417
|
+
expiredAt?: Date | number | string;
|
|
418
|
+
id: string;
|
|
419
|
+
modifiedAt?: Date | number | string;
|
|
420
|
+
name: string;
|
|
421
|
+
storageClass?: string;
|
|
422
|
+
}
|
|
423
|
+
type UploadEventTypeValue = "completed" | "created" | "deleted" | "part" | "updated";
|
|
424
|
+
type UploadEventType = UploadEventTypeValue;
|
|
425
|
+
interface FileQuery {
|
|
426
|
+
id: string;
|
|
427
|
+
name?: string;
|
|
428
|
+
size?: number;
|
|
429
|
+
}
|
|
430
|
+
interface Checksum {
|
|
431
|
+
checksum?: string;
|
|
432
|
+
checksumAlgorithm?: string;
|
|
433
|
+
}
|
|
434
|
+
interface FilePart extends Checksum, FileQuery {
|
|
435
|
+
body: Readable;
|
|
436
|
+
contentLength?: number;
|
|
437
|
+
start: number;
|
|
438
|
+
}
|
|
439
|
+
type DateType = Date | number | string;
|
|
440
|
+
declare class File implements FileInit {
|
|
441
|
+
bytesWritten: number;
|
|
442
|
+
contentType: string;
|
|
443
|
+
originalName: string;
|
|
444
|
+
id: string;
|
|
445
|
+
metadata: Metadata;
|
|
446
|
+
name: string;
|
|
447
|
+
size?: number;
|
|
448
|
+
status?: UploadEventType;
|
|
449
|
+
expiredAt?: DateType;
|
|
450
|
+
createdAt?: DateType;
|
|
451
|
+
modifiedAt?: DateType;
|
|
452
|
+
hash?: {
|
|
453
|
+
algorithm: string;
|
|
454
|
+
value: string;
|
|
455
|
+
};
|
|
456
|
+
content?: Buffer;
|
|
457
|
+
ETag?: string;
|
|
458
|
+
constructor({ contentType, expiredAt, id, metadata, originalName, size }: FileInit);
|
|
459
|
+
}
|
|
460
|
+
type UploadFile = Readonly<File>;
|
|
461
|
+
/**
|
|
462
|
+
* Stores upload metadata.
|
|
463
|
+
*/
|
|
464
|
+
declare class MetaStorage<T extends File = File> {
|
|
465
|
+
prefix: string;
|
|
466
|
+
suffix: string;
|
|
467
|
+
protected readonly logger?: Console;
|
|
468
|
+
constructor(config?: MetaStorageOptions);
|
|
469
|
+
/**
|
|
470
|
+
* Saves upload metadata.
|
|
471
|
+
*/
|
|
472
|
+
save(_id: string, file: T): Promise<T>;
|
|
473
|
+
/**
|
|
474
|
+
* Deletes an upload metadata.
|
|
475
|
+
*/
|
|
476
|
+
delete(_id: string): Promise<void>;
|
|
477
|
+
/**
|
|
478
|
+
* Retrieves upload metadata.
|
|
479
|
+
*/
|
|
480
|
+
get(_id: string): Promise<T>;
|
|
481
|
+
/**
|
|
482
|
+
* Marks upload active.
|
|
483
|
+
*/
|
|
484
|
+
touch(_id: string, _file: T): Promise<T>;
|
|
485
|
+
getMetaName(id: string): string;
|
|
486
|
+
getIdFromMetaName(name: string): string;
|
|
487
|
+
}
|
|
488
|
+
type OnCreate<TFile extends File = File> = (file: TFile) => Promise<void> | void;
|
|
489
|
+
type OnUpdate<TFile extends File = File> = (file: TFile) => Promise<void> | void;
|
|
490
|
+
type OnComplete<TFile extends File = File, TResponse = unknown, TRequest = unknown> = (file: TFile, response: TResponse, request?: TRequest) => Promise<void> | void;
|
|
491
|
+
type OnDelete<TFile extends File = File> = (file: TFile) => Promise<void> | void;
|
|
492
|
+
type OnError<TBody = HttpErrorBody> = (error: HttpError<TBody>) => Promise<void> | void;
|
|
493
|
+
interface PurgeList {
|
|
494
|
+
items: UploadFile[];
|
|
495
|
+
maxAgeMs: number;
|
|
496
|
+
}
|
|
497
|
+
interface ExpirationOptions {
|
|
498
|
+
/**
|
|
499
|
+
* Age of the upload, after which it is considered expired and can be deleted
|
|
500
|
+
*/
|
|
501
|
+
maxAge: number | string;
|
|
502
|
+
/**
|
|
503
|
+
* Auto purging interval for expired upload
|
|
504
|
+
*/
|
|
505
|
+
purgeInterval?: number | string;
|
|
506
|
+
/**
|
|
507
|
+
* Auto prolong expiring upload
|
|
508
|
+
*/
|
|
509
|
+
rolling?: boolean;
|
|
510
|
+
}
|
|
511
|
+
interface BaseStorageOptions<T extends File = File> extends GenericStorageConfig {
|
|
512
|
+
/** Allowed MIME types */
|
|
513
|
+
allowMIME?: string[];
|
|
514
|
+
/** The full path of the folder where the uploaded asset will be stored. */
|
|
515
|
+
assetFolder?: string;
|
|
516
|
+
/** Cache instance to use for caching */
|
|
517
|
+
cache?: Cache;
|
|
518
|
+
/**
|
|
519
|
+
* Automatic cleaning of abandoned and completed upload
|
|
520
|
+
* @example
|
|
521
|
+
* ```ts
|
|
522
|
+
* app.use(
|
|
523
|
+
* '/upload',
|
|
524
|
+
* Upload.upload({
|
|
525
|
+
* directory: 'upload',
|
|
526
|
+
* expiration: { maxAge: '6h', purgeInterval: '30min' },
|
|
527
|
+
* onComplete
|
|
528
|
+
* })
|
|
529
|
+
* );
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
expiration?: ExpirationOptions;
|
|
533
|
+
/** File naming function */
|
|
534
|
+
filename?: (file: T) => string;
|
|
535
|
+
/**
|
|
536
|
+
* File name validation function.
|
|
537
|
+
* Returns true if the filename is valid, false otherwise.
|
|
538
|
+
* @default Cloud storage platforms: permissive (only blocks path traversal and null bytes)
|
|
539
|
+
* @default DiskStorage: strict (blocks filesystem-incompatible characters)
|
|
540
|
+
* @example
|
|
541
|
+
* ```ts
|
|
542
|
+
* fileNameValidation: (name: string) => {
|
|
543
|
+
* // Custom validation logic
|
|
544
|
+
* return name.length > 0 && !name.includes('../');
|
|
545
|
+
* }
|
|
546
|
+
* ```
|
|
547
|
+
*/
|
|
548
|
+
fileNameValidation?: (name: string) => boolean;
|
|
549
|
+
/** Logger injection */
|
|
550
|
+
logger?: Console;
|
|
551
|
+
/** Limiting the size of custom metadata */
|
|
552
|
+
maxMetadataSize?: number | string;
|
|
553
|
+
/** File size limit */
|
|
554
|
+
maxUploadSize?: number | string;
|
|
555
|
+
/** Provide custom meta storage */
|
|
556
|
+
metaStorage?: MetaStorage<T>;
|
|
557
|
+
/** Metrics injection for observability */
|
|
558
|
+
metrics?: Metrics;
|
|
559
|
+
/** Callback function that is called when an upload is completed */
|
|
560
|
+
onComplete?: OnComplete<T>;
|
|
561
|
+
/** Callback function that is called when a new upload is created */
|
|
562
|
+
onCreate?: OnCreate<T>;
|
|
563
|
+
/** Callback function that is called when an upload is cancelled */
|
|
564
|
+
onDelete?: OnDelete<T>;
|
|
565
|
+
/** Customize error response */
|
|
566
|
+
onError?: OnError;
|
|
567
|
+
/** Callback function that is called when an upload is updated */
|
|
568
|
+
onUpdate?: OnUpdate<T>;
|
|
569
|
+
/** Force relative URI in Location header */
|
|
570
|
+
useRelativeLocation?: boolean;
|
|
571
|
+
/** Upload validation options */
|
|
572
|
+
validation?: Validation<T>;
|
|
573
|
+
}
|
|
574
|
+
type DiskStorageOptions<T extends File> = BaseStorageOptions<T> & {
|
|
575
|
+
/**
|
|
576
|
+
* Uploads directory.
|
|
577
|
+
*/
|
|
578
|
+
directory: string;
|
|
579
|
+
/**
|
|
580
|
+
* Configuring metafile storage on the local disk
|
|
581
|
+
* @example
|
|
582
|
+
* ```ts
|
|
583
|
+
* const storage = new DiskStorage({
|
|
584
|
+
* directory: 'upload',
|
|
585
|
+
* metaStorageConfig: { directory: '/tmp/upload-metafiles', prefix: '.' }
|
|
586
|
+
* });
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
metaStorageConfig?: LocalMetaStorageOptions;
|
|
590
|
+
};
|
|
591
|
+
type DiskStorageWithChecksumOptions<T extends File> = DiskStorageOptions<T> & {
|
|
592
|
+
/**
|
|
593
|
+
* Enable/disable file/range checksum calculation
|
|
594
|
+
*/
|
|
595
|
+
checksum?: boolean | "md5" | "sha1";
|
|
596
|
+
};
|
|
597
|
+
/**
|
|
598
|
+
* Unified storage configuration
|
|
599
|
+
*/
|
|
600
|
+
interface GenericStorageConfig {
|
|
601
|
+
/** Allow additional properties for specific storage backends */
|
|
602
|
+
[key: string]: unknown;
|
|
603
|
+
/** Base path/prefix for all operations */
|
|
604
|
+
basePath?: string;
|
|
605
|
+
/** Cache TTL */
|
|
606
|
+
cacheTTL?: number;
|
|
607
|
+
/** Supported checksum algorithms */
|
|
608
|
+
checksumTypes?: string[];
|
|
609
|
+
/**
|
|
610
|
+
* Default abort signal merged into every operation. A per-call
|
|
611
|
+
* `OperationOptions.signal` is combined with this, not replaced — either
|
|
612
|
+
* one aborts the call. Note this signal lives for the storage instance's
|
|
613
|
+
* lifetime: once it aborts, every subsequent operation fails fast.
|
|
614
|
+
*/
|
|
615
|
+
defaultSignal?: AbortSignal;
|
|
616
|
+
/**
|
|
617
|
+
* Default per-operation timeout in milliseconds, applied per retry
|
|
618
|
+
* attempt when a call omits `OperationOptions.timeout`. A per-call
|
|
619
|
+
* `timeout` (including `0` to explicitly disable) takes precedence.
|
|
620
|
+
*/
|
|
621
|
+
defaultTimeout?: number;
|
|
622
|
+
/** Logger instance */
|
|
623
|
+
logger?: Console;
|
|
624
|
+
/** Maximum file size */
|
|
625
|
+
maxFileSize?: number | string;
|
|
626
|
+
/** Metrics instance for observability */
|
|
627
|
+
metrics?: Metrics;
|
|
628
|
+
/** Retry configuration for transient failures */
|
|
629
|
+
retryConfig?: RetryConfig;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Per-operation overrides for cancellation, deadlines and retries.
|
|
633
|
+
*
|
|
634
|
+
* Threaded through the public storage operations down to the backend SDK call.
|
|
635
|
+
* Backends that wrap an SDK with native cancellation honour `signal`/`timeout`
|
|
636
|
+
* directly; backends without a cancellation primitive still fail fast at the
|
|
637
|
+
* storage layer, but the provider request may continue in the background.
|
|
638
|
+
*/
|
|
639
|
+
interface OperationOptions {
|
|
640
|
+
/**
|
|
641
|
+
* Retry override for this call. A number is treated as `maxRetries`; an
|
|
642
|
+
* object is shallow-merged over the backend's configured `RetryConfig`.
|
|
643
|
+
* Aborted and timed-out operations are never retried regardless of this.
|
|
644
|
+
*/
|
|
645
|
+
retries?: number | RetryConfig;
|
|
646
|
+
/**
|
|
647
|
+
* Abort the operation when this signal fires. Merged with any
|
|
648
|
+
* per-call `timeout` via `AbortSignal.any`.
|
|
649
|
+
*/
|
|
650
|
+
signal?: AbortSignal;
|
|
651
|
+
/**
|
|
652
|
+
* Per-operation timeout in milliseconds. `0` or a negative value
|
|
653
|
+
* disables the timeout. Applied per retry attempt.
|
|
654
|
+
*/
|
|
655
|
+
timeout?: number;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Batch operation result for a single file
|
|
659
|
+
*/
|
|
660
|
+
interface BatchOperationResult<T extends File = File> {
|
|
661
|
+
/** Error message if operation failed */
|
|
662
|
+
error?: string;
|
|
663
|
+
/** File that was successfully operated on */
|
|
664
|
+
file?: T;
|
|
665
|
+
/** File ID */
|
|
666
|
+
id: string;
|
|
667
|
+
/** Whether the operation was successful */
|
|
668
|
+
success: boolean;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Response from batch operations (deleteBatch, copyBatch, moveBatch)
|
|
672
|
+
*/
|
|
673
|
+
interface BatchOperationResponse<T extends File = File> {
|
|
674
|
+
/** Failed operations with error details */
|
|
675
|
+
failed: {
|
|
676
|
+
error: string;
|
|
677
|
+
id: string;
|
|
678
|
+
}[];
|
|
679
|
+
/** Total number of failed operations */
|
|
680
|
+
failedCount: number;
|
|
681
|
+
/** Successfully processed files */
|
|
682
|
+
successful: T[];
|
|
683
|
+
/** Total number of successful operations */
|
|
684
|
+
successfulCount: number;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Default filename validation for cloud storage platforms.
|
|
688
|
+
* Permissive validation that only blocks dangerous patterns (path traversal, null bytes).
|
|
689
|
+
* Cloud storage platforms (S3, Azure, GCS) accept most special characters and handle URL encoding automatically.
|
|
690
|
+
*/
|
|
691
|
+
declare const defaultCloudStorageFileNameValidation: (name: string) => boolean;
|
|
692
|
+
/**
|
|
693
|
+
* Default filename validation for local filesystems.
|
|
694
|
+
* Stricter validation that blocks filesystem-incompatible characters.
|
|
695
|
+
*/
|
|
696
|
+
declare const defaultFilesystemFileNameValidation: (name: string) => boolean;
|
|
697
|
+
/**
|
|
698
|
+
* Abstract base class for all storage backends.
|
|
699
|
+
* @template TFile The file type used by this storage backend.
|
|
700
|
+
* @template TFileReturn The return type for file retrieval operations.
|
|
701
|
+
* @remarks
|
|
702
|
+
* ## Error Handling
|
|
703
|
+
*
|
|
704
|
+
* All storage operations follow consistent error handling patterns:
|
|
705
|
+
* - Operations throw `UploadError` with specific error codes (see ERRORS enum)
|
|
706
|
+
* - Common error codes: FILE_NOT_FOUND, GONE (expired), FILE_LOCKED, STORAGE_BUSY
|
|
707
|
+
* - Errors are normalized with storage class context via `normalizeError()`
|
|
708
|
+
* - Batch operations capture individual failures without stopping the batch
|
|
709
|
+
*
|
|
710
|
+
* ## Retry Behavior
|
|
711
|
+
*
|
|
712
|
+
* Storage implementations handle retries differently:
|
|
713
|
+
*
|
|
714
|
+
* ### Cloud Storage (S3, GCS, Azure, Netlify Blob)
|
|
715
|
+
* - Use configurable retry wrappers via `retryConfig` option
|
|
716
|
+
* - Default retryable status codes: 408, 429, 500, 502, 503, 504
|
|
717
|
+
* - Retry logic handles transient network errors and rate limiting
|
|
718
|
+
* - Custom `shouldRetry` functions can be provided for advanced retry logic
|
|
719
|
+
*
|
|
720
|
+
* ### Local Storage (DiskStorage)
|
|
721
|
+
* - No automatic retries (filesystem operations are typically immediate)
|
|
722
|
+
* - Errors are thrown directly for immediate feedback
|
|
723
|
+
*
|
|
724
|
+
* ## Operation Instrumentation
|
|
725
|
+
*
|
|
726
|
+
* All public operations are automatically instrumented via `instrumentOperation()`:
|
|
727
|
+
* - Metrics are recorded for operation count, duration, and errors
|
|
728
|
+
* - File sizes are tracked for operations that return file objects
|
|
729
|
+
* - Error metrics include error messages for debugging
|
|
730
|
+
*
|
|
731
|
+
* ## Metadata Caching
|
|
732
|
+
*
|
|
733
|
+
* File metadata is automatically cached to reduce storage API calls:
|
|
734
|
+
* - Cache is updated on save, delete, and get operations
|
|
735
|
+
* - Cache is invalidated when metadata is deleted
|
|
736
|
+
* - Implementations can override caching behavior if needed
|
|
737
|
+
*/
|
|
738
|
+
declare abstract class BaseStorage<TFile extends File = File, TFileReturn extends FileReturn = FileReturn> {
|
|
739
|
+
/**
|
|
740
|
+
* Hook called when a new file is created.
|
|
741
|
+
* @param file The newly created file object.
|
|
742
|
+
* @remarks This hook is called after file metadata is saved but before returning the file.
|
|
743
|
+
* Can be used for side effects like logging, notifications, or custom processing.
|
|
744
|
+
*/
|
|
745
|
+
onCreate: (file: TFile) => Promise<void> | void;
|
|
746
|
+
/**
|
|
747
|
+
* Hook called when file metadata is updated.
|
|
748
|
+
* @param file The updated file object.
|
|
749
|
+
* @remarks This hook is called after metadata is updated and saved.
|
|
750
|
+
* Can be used for side effects like logging or custom processing.
|
|
751
|
+
*/
|
|
752
|
+
onUpdate: (file: TFile) => Promise<void> | void;
|
|
753
|
+
/**
|
|
754
|
+
* Hook called when a file upload is completed.
|
|
755
|
+
* @param file The completed file object.
|
|
756
|
+
* @param response The response object that can be modified in place (headers, statusCode, body).
|
|
757
|
+
* @param request Optional request object for additional context.
|
|
758
|
+
* @remarks This hook is called when file status becomes "completed".
|
|
759
|
+
* The response object can be modified directly to add headers or change the status code.
|
|
760
|
+
*/
|
|
761
|
+
onComplete: (file: TFile, response: unknown, request?: unknown) => Promise<void> | void;
|
|
762
|
+
/**
|
|
763
|
+
* Hook called when a file is deleted.
|
|
764
|
+
* @param file The deleted file object.
|
|
765
|
+
* @remarks This hook is called after the file is deleted but before returning.
|
|
766
|
+
* Can be used for side effects like cleanup or logging.
|
|
767
|
+
*/
|
|
768
|
+
onDelete: (file: TFile) => Promise<void> | void;
|
|
769
|
+
/**
|
|
770
|
+
* Hook called when an error occurs during storage operations.
|
|
771
|
+
* @param error The HTTP error object that can be modified in place.
|
|
772
|
+
* @remarks This hook allows customizing error responses by modifying the error object.
|
|
773
|
+
* The error object can be modified to change headers, statusCode, or body properties.
|
|
774
|
+
* Error formatting happens in handlers after this hook is called.
|
|
775
|
+
*/
|
|
776
|
+
onError: (error: HttpError) => Promise<void> | void;
|
|
777
|
+
isReady: boolean;
|
|
778
|
+
errorResponses: ErrorResponses;
|
|
779
|
+
cache: Cache<string, TFile>;
|
|
780
|
+
readonly logger?: Console;
|
|
781
|
+
readonly metrics: Metrics;
|
|
782
|
+
readonly genericConfig: BaseStorageOptions<TFile>;
|
|
783
|
+
maxMetadataSize: number;
|
|
784
|
+
checksumTypes: string[];
|
|
785
|
+
/**
|
|
786
|
+
* Adapter capability flag: when `true`, the adapter honours
|
|
787
|
+
* `OperationOptions.range` on {@link BaseStorage.get} and
|
|
788
|
+
* {@link BaseStorage.getStream}, returning only the requested byte slice.
|
|
789
|
+
* The `Files` facade gates `download({ range })` on this flag and throws
|
|
790
|
+
* `METHOD_NOT_ALLOWED` for adapters that haven't opted in.
|
|
791
|
+
*/
|
|
792
|
+
readonly supportsRange: boolean;
|
|
793
|
+
/**
|
|
794
|
+
* Adapter capability flag: when `true`, the adapter persists user-supplied
|
|
795
|
+
* key/value metadata alongside the object and returns it on `get`/`head`.
|
|
796
|
+
* Defaults to `true` — most backends carry metadata. Adapters that drop or
|
|
797
|
+
* ignore custom metadata override this to `false`; the `Files` facade reads
|
|
798
|
+
* it via {@link Files.capabilities} so callers can fail fast instead of
|
|
799
|
+
* silently losing metadata.
|
|
800
|
+
*/
|
|
801
|
+
readonly supportsMetadata: boolean;
|
|
802
|
+
/**
|
|
803
|
+
* Adapter capability flag: when `true`, the adapter honours an object
|
|
804
|
+
* `cacheControl` directive on write. Defaults to `false` — most backends
|
|
805
|
+
* have no cache-control concept. Exposed through {@link Files.capabilities}.
|
|
806
|
+
*/
|
|
807
|
+
readonly supportsCacheControl: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* Adapter capability flag: when `true`, the adapter implements
|
|
810
|
+
* {@link BaseStorage.listDirectory} so the provider collapses keys into
|
|
811
|
+
* common prefixes server-side. The `Files` facade prefers this native path
|
|
812
|
+
* for `list({ delimiter })`; adapters that leave it `false` fall back to
|
|
813
|
+
* synthesizing the directory view from a full listing in the facade.
|
|
814
|
+
*/
|
|
815
|
+
readonly supportsDelimiter: boolean;
|
|
816
|
+
/**
|
|
817
|
+
* Adapter capability flag: when `true`, the adapter reports its own
|
|
818
|
+
* byte-level `onProgress` events during `write`. The `Files` facade skips
|
|
819
|
+
* its coarse "start/done" emission for adapters that report progress
|
|
820
|
+
* natively, so callers see one consistent stream of events.
|
|
821
|
+
*/
|
|
822
|
+
readonly reportsUploadProgress: boolean;
|
|
823
|
+
maxUploadSize: number;
|
|
824
|
+
protected expiration?: {
|
|
825
|
+
maxAge?: string | number;
|
|
826
|
+
purgeInterval?: string | number;
|
|
827
|
+
rolling?: boolean;
|
|
828
|
+
};
|
|
829
|
+
protected locker: Locker;
|
|
830
|
+
protected namingFunction: (file: TFile) => string;
|
|
831
|
+
protected validation: Validator<TFile>;
|
|
832
|
+
protected abstract meta: MetaStorage<TFile>;
|
|
833
|
+
protected assetFolder: string | undefined;
|
|
834
|
+
/**
|
|
835
|
+
* Limits the number of concurrent upload requests
|
|
836
|
+
*/
|
|
837
|
+
protected concurrency?: number;
|
|
838
|
+
protected constructor(config: BaseStorageOptions<TFile>);
|
|
839
|
+
/**
|
|
840
|
+
* Escape hatch returning the underlying native client (S3Client, BlobServiceClient, etc.)
|
|
841
|
+
* for provider-specific operations not covered by the unified API.
|
|
842
|
+
* Returns `undefined` when no native client is available (e.g. DiskStorage).
|
|
843
|
+
*/
|
|
844
|
+
get raw(): unknown;
|
|
845
|
+
/**
|
|
846
|
+
* Returns a presigned URL for downloading the object at `key`.
|
|
847
|
+
* Throws `ERRORS.METHOD_NOT_ALLOWED` when the adapter has no native presign support.
|
|
848
|
+
* @param _key Storage key.
|
|
849
|
+
* @param _options Optional expiry and response overrides.
|
|
850
|
+
*/
|
|
851
|
+
getReadUrl(_key: string, _options?: OperationOptions & {
|
|
852
|
+
expiresIn?: number;
|
|
853
|
+
responseContentDisposition?: string;
|
|
854
|
+
responseContentType?: string;
|
|
855
|
+
}): Promise<string>;
|
|
856
|
+
/**
|
|
857
|
+
* Returns a presigned URL for uploading a single object to `key`.
|
|
858
|
+
* Throws `ERRORS.METHOD_NOT_ALLOWED` when the adapter has no native presign support.
|
|
859
|
+
* @param _key Storage key.
|
|
860
|
+
* @param _options Optional content type, expiry, and content length hints, plus per-call signal/timeout/retries.
|
|
861
|
+
*/
|
|
862
|
+
getUploadUrl(_key: string, _options?: OperationOptions & {
|
|
863
|
+
contentLength?: number;
|
|
864
|
+
contentType?: string;
|
|
865
|
+
expiresIn?: number;
|
|
866
|
+
}): Promise<string>;
|
|
867
|
+
get tusExtension(): string[];
|
|
868
|
+
/**
|
|
869
|
+
* Validates a file against configured validation rules.
|
|
870
|
+
* @param file File object to validate.
|
|
871
|
+
* @returns Promise resolving to undefined if file is valid, throws ValidationError otherwise.
|
|
872
|
+
* @throws {ValidationError} If validation fails
|
|
873
|
+
*/
|
|
874
|
+
validate(file: TFile): Promise<void>;
|
|
875
|
+
/**
|
|
876
|
+
* Checks if a file exists by querying its metadata.
|
|
877
|
+
* @param query File query containing the file ID to check.
|
|
878
|
+
* @param query.id File ID to check.
|
|
879
|
+
* @returns Promise resolving to true if file exists, false otherwise.
|
|
880
|
+
* @remarks This method does not throw errors - it returns false if the file is not found.
|
|
881
|
+
*/
|
|
882
|
+
exists(query: FileQuery, options?: OperationOptions): Promise<boolean>;
|
|
883
|
+
/**
|
|
884
|
+
* Normalizes errors with storage-specific context.
|
|
885
|
+
* @param error The error to normalize.
|
|
886
|
+
* @returns Normalized HTTP error with storage class context added to the message.
|
|
887
|
+
* @remarks Errors are enhanced with the storage class name for better debugging.
|
|
888
|
+
*/
|
|
889
|
+
normalizeError(error: Error): HttpError;
|
|
890
|
+
/**
|
|
891
|
+
* Gets the storage configuration.
|
|
892
|
+
* @returns The current storage configuration options.
|
|
893
|
+
*/
|
|
894
|
+
get config(): BaseStorageOptions<TFile>;
|
|
895
|
+
/**
|
|
896
|
+
* Saves upload metadata to the metadata storage.
|
|
897
|
+
* @param file File object containing metadata to save.
|
|
898
|
+
* @returns Promise resolving to the saved file object.
|
|
899
|
+
* @remarks Updates timestamps and caches the file metadata.
|
|
900
|
+
* @throws {UploadError} If `file.id` contains path-traversal sequences, null bytes, or is an absolute path — patterns that could let a local MetaStorage implementation write outside its directory.
|
|
901
|
+
*/
|
|
902
|
+
saveMeta(file: TFile): Promise<TFile>;
|
|
903
|
+
/**
|
|
904
|
+
* Rejects ids containing `..` segments, null bytes, or absolute paths — defense-in-depth
|
|
905
|
+
* so any MetaStorage / facade / handler that uses `id` as part of a filesystem path or
|
|
906
|
+
* cross-bucket lookup can't be escaped. Public so the `Files` facade and Fetch handlers
|
|
907
|
+
* can validate user-supplied keys before any adapter call.
|
|
908
|
+
*/
|
|
909
|
+
static assertSafeId(id: string): void;
|
|
910
|
+
/**
|
|
911
|
+
* Deletes upload metadata from the metadata storage.
|
|
912
|
+
* @param id File ID whose metadata should be deleted.
|
|
913
|
+
* @returns Promise resolving when metadata is deleted.
|
|
914
|
+
* @remarks Also removes the file from the cache.
|
|
915
|
+
*/
|
|
916
|
+
deleteMeta(id: string): Promise<void>;
|
|
917
|
+
/**
|
|
918
|
+
* Retrieves upload metadata by file ID.
|
|
919
|
+
* @param id File ID to retrieve metadata for.
|
|
920
|
+
* @returns Promise resolving to the file metadata object.
|
|
921
|
+
* @throws {UploadError} If the file metadata cannot be found (ERRORS.FILE_NOT_FOUND).
|
|
922
|
+
* @remarks Caches the retrieved metadata for faster subsequent access.
|
|
923
|
+
*/
|
|
924
|
+
getMeta(id: string, _options?: OperationOptions): Promise<TFile>;
|
|
925
|
+
/**
|
|
926
|
+
* Checks if a file has expired and deletes it if so.
|
|
927
|
+
* @param file File object to check for expiration.
|
|
928
|
+
* @returns Promise resolving to the file object if not expired.
|
|
929
|
+
* @throws {UploadError} If the file has expired (ERRORS.GONE).
|
|
930
|
+
* @remarks If the file is expired, it is automatically deleted and the metadata is removed.
|
|
931
|
+
*/
|
|
932
|
+
checkIfExpired(file: TFile): Promise<TFile>;
|
|
933
|
+
/**
|
|
934
|
+
* Searches for and purges expired uploads.
|
|
935
|
+
* @param maxAge Maximum age of files to keep (files older than this will be purged).
|
|
936
|
+
* Can be a number (milliseconds) or string (e.g., "1h", "30m", "7d").
|
|
937
|
+
* If not provided, uses the expiration.maxAge from configuration.
|
|
938
|
+
* @returns Promise resolving to a list of purged files.
|
|
939
|
+
* @remarks
|
|
940
|
+
* Errors during individual file deletions are logged but do not stop the purge process.
|
|
941
|
+
* Files with corrupted metadata are skipped with a warning.
|
|
942
|
+
* Uses rolling expiration if configured (based on modifiedAt) or fixed expiration (based on createdAt).
|
|
943
|
+
*/
|
|
944
|
+
purge(maxAge?: number | string): Promise<PurgeList>;
|
|
945
|
+
/**
|
|
946
|
+
* Gets an uploaded file by ID.
|
|
947
|
+
* @param query File query containing the file ID to retrieve.
|
|
948
|
+
* @param query.id File ID to retrieve.
|
|
949
|
+
* @param options Optional per-call signal/timeout/retries.
|
|
950
|
+
* @returns Promise resolving to the file data including content.
|
|
951
|
+
* @throws {UploadError} If the file cannot be found (ERRORS.FILE_NOT_FOUND) or has expired (ERRORS.GONE).
|
|
952
|
+
* @remarks This method loads the entire file content into memory. For large files, use getStream() instead.
|
|
953
|
+
*/
|
|
954
|
+
abstract get({ id }: FileQuery, options?: OperationOptions): Promise<TFileReturn>;
|
|
955
|
+
/**
|
|
956
|
+
* Gets an uploaded file as a readable stream for efficient large file handling.
|
|
957
|
+
* @param query File query containing the file ID to stream.
|
|
958
|
+
* @param query.id File ID to stream.
|
|
959
|
+
* @param options Optional per-call signal/timeout/retries (and, on range-capable adapters, a `range`).
|
|
960
|
+
* @returns Promise resolving to an object containing the stream, headers, and size.
|
|
961
|
+
* @throws {UploadError} If the file cannot be found (ERRORS.FILE_NOT_FOUND) or has expired (ERRORS.GONE).
|
|
962
|
+
* @remarks
|
|
963
|
+
* Default implementation falls back to get() and creates a stream from the buffer.
|
|
964
|
+
* Storage implementations should override this for better streaming performance.
|
|
965
|
+
* Headers include Content-Type, Content-Length, ETag, and Last-Modified.
|
|
966
|
+
*/
|
|
967
|
+
getStream({ id }: FileQuery, options?: OperationOptions): Promise<{
|
|
968
|
+
headers?: Record<string, string>;
|
|
969
|
+
size?: number;
|
|
970
|
+
stream: Readable;
|
|
971
|
+
}>;
|
|
972
|
+
/**
|
|
973
|
+
* Retrieves a list of uploaded files.
|
|
974
|
+
* @param _limit Maximum number of files to return (default: 1000).
|
|
975
|
+
* @returns Promise resolving to an array of file metadata objects.
|
|
976
|
+
* @throws {Error} If not implemented by the storage backend.
|
|
977
|
+
* @remarks Storage implementations must override this method.
|
|
978
|
+
*/
|
|
979
|
+
list(_limit?: number, _options?: OperationOptions): Promise<TFile[]>;
|
|
980
|
+
/**
|
|
981
|
+
* Directory-style listing: collapse keys that share a path segment into common prefixes,
|
|
982
|
+
* server-side, instead of returning every object. Adapters that can push the `delimiter` down to
|
|
983
|
+
* the provider (S3 family, GCS, Azure) override this and set
|
|
984
|
+
* {@link BaseStorage.supportsDelimiter} to `true`; the default throws so the `Files` facade knows
|
|
985
|
+
* to fall back to synthesizing the view from {@link BaseStorage.list}.
|
|
986
|
+
* @param _options Listing options — `delimiter` (required), plus optional `prefix`/`limit` and the usual per-call signal/timeout/retries.
|
|
987
|
+
* @returns Direct-child files and the common prefixes one delimiter level below `prefix`.
|
|
988
|
+
* @throws {UploadError} `METHOD_NOT_ALLOWED` when the adapter has no native delimiter support.
|
|
989
|
+
*/
|
|
990
|
+
listDirectory(_options?: OperationOptions & {
|
|
991
|
+
delimiter: string;
|
|
992
|
+
limit?: number;
|
|
993
|
+
prefix?: string;
|
|
994
|
+
}): Promise<{
|
|
995
|
+
files: TFile[];
|
|
996
|
+
prefixes: string[];
|
|
997
|
+
}>;
|
|
998
|
+
/**
|
|
999
|
+
* Updates file metadata with user-provided key-value pairs.
|
|
1000
|
+
* @param query File query containing the file ID to update.
|
|
1001
|
+
* @param query.id File ID to update.
|
|
1002
|
+
* @param metadata Partial file object containing fields to update.
|
|
1003
|
+
* @returns Promise resolving to the updated file object.
|
|
1004
|
+
* @throws {UploadError} If the file cannot be found (ERRORS.FILE_NOT_FOUND).
|
|
1005
|
+
* @remarks
|
|
1006
|
+
* Supports TTL (time-to-live) option: if metadata contains a 'ttl' field,
|
|
1007
|
+
* it will be converted to an 'expiredAt' timestamp.
|
|
1008
|
+
* TTL can be a number (milliseconds) or string (e.g., "1h", "30m", "7d").
|
|
1009
|
+
*/
|
|
1010
|
+
update({ id }: FileQuery, metadata: Partial<File>): Promise<TFile>;
|
|
1011
|
+
/**
|
|
1012
|
+
* Creates a new upload and saves its metadata.
|
|
1013
|
+
* @param file File initialization configuration.
|
|
1014
|
+
* @param options Optional per-call signal/timeout/retries.
|
|
1015
|
+
* @returns Promise resolving to the created file object.
|
|
1016
|
+
*/
|
|
1017
|
+
abstract create(file: FileInit, options?: OperationOptions): Promise<TFile>;
|
|
1018
|
+
/**
|
|
1019
|
+
* Writes part and/or returns status of an upload.
|
|
1020
|
+
* @param part File part, query, or full file object to write.
|
|
1021
|
+
* @param options Optional per-call signal/timeout/retries.
|
|
1022
|
+
* @returns Promise resolving to the updated file object.
|
|
1023
|
+
*/
|
|
1024
|
+
abstract write(part: FilePart | FileQuery | TFile, options?: OperationOptions): Promise<TFile>;
|
|
1025
|
+
/**
|
|
1026
|
+
* Deletes an upload and its metadata.
|
|
1027
|
+
* @param query File query containing the file ID to delete.
|
|
1028
|
+
* @param query.id File ID to delete.
|
|
1029
|
+
* @param options Optional per-call signal/timeout/retries.
|
|
1030
|
+
* @returns Promise resolving to the deleted file object with status: "deleted".
|
|
1031
|
+
* @throws {UploadError} If the file metadata cannot be found.
|
|
1032
|
+
*/
|
|
1033
|
+
abstract delete(query: FileQuery, options?: OperationOptions): Promise<TFile>;
|
|
1034
|
+
/**
|
|
1035
|
+
* Copies an upload file to a new location.
|
|
1036
|
+
* @param name Source file name/ID.
|
|
1037
|
+
* @param destination Destination file name/ID.
|
|
1038
|
+
* @param options Optional copy options including storage class plus per-call signal/timeout/retries.
|
|
1039
|
+
* @returns Promise resolving to the copied file object.
|
|
1040
|
+
* @throws {UploadError} If the source file cannot be found.
|
|
1041
|
+
*/
|
|
1042
|
+
abstract copy(name: string, destination: string, options?: OperationOptions & {
|
|
1043
|
+
storageClass?: string;
|
|
1044
|
+
}): Promise<TFile>;
|
|
1045
|
+
/**
|
|
1046
|
+
* Moves an upload file to a new location.
|
|
1047
|
+
* @param name Source file name/ID.
|
|
1048
|
+
* @param destination Destination file name/ID.
|
|
1049
|
+
* @param options Optional per-call signal/timeout/retries.
|
|
1050
|
+
* @returns Promise resolving to the moved file object.
|
|
1051
|
+
* @throws {UploadError} If the source file cannot be found.
|
|
1052
|
+
*/
|
|
1053
|
+
abstract move(name: string, destination: string, options?: OperationOptions): Promise<TFile>;
|
|
1054
|
+
/**
|
|
1055
|
+
* Deletes multiple files in a single batch operation.
|
|
1056
|
+
* @param ids Array of file IDs to delete.
|
|
1057
|
+
* @returns Promise resolving to batch operation response with successful and failed deletions.
|
|
1058
|
+
* @remarks
|
|
1059
|
+
* Processes all deletions in parallel using Promise.allSettled.
|
|
1060
|
+
* Individual failures do not stop the batch operation.
|
|
1061
|
+
* Each deletion is wrapped in error handling to capture failures.
|
|
1062
|
+
* Metrics are recorded for the batch operation and individual failures.
|
|
1063
|
+
* Returns both successful and failed operations with detailed error information.
|
|
1064
|
+
*/
|
|
1065
|
+
deleteBatch(ids: string[], options?: OperationOptions): Promise<BatchOperationResponse<TFile>>;
|
|
1066
|
+
/**
|
|
1067
|
+
* Copies multiple files in a single batch operation.
|
|
1068
|
+
* @param operations Array of copy operations, each containing:
|
|
1069
|
+
* source: Source file ID.
|
|
1070
|
+
* destination: Destination file ID or path.
|
|
1071
|
+
* options: Optional copy options including storage class.
|
|
1072
|
+
* @returns Promise resolving to batch operation response with successful and failed copies.
|
|
1073
|
+
* @remarks
|
|
1074
|
+
* Processes all copies in parallel using Promise.allSettled.
|
|
1075
|
+
* Individual failures do not stop the batch operation.
|
|
1076
|
+
* Each copy operation is wrapped in error handling to capture failures.
|
|
1077
|
+
* Metrics are recorded for the batch operation and individual failures.
|
|
1078
|
+
* Returns both successful and failed operations with detailed error information.
|
|
1079
|
+
*/
|
|
1080
|
+
copyBatch(operations: {
|
|
1081
|
+
destination: string;
|
|
1082
|
+
options?: {
|
|
1083
|
+
storageClass?: string;
|
|
1084
|
+
};
|
|
1085
|
+
source: string;
|
|
1086
|
+
}[]): Promise<BatchOperationResponse<TFile>>;
|
|
1087
|
+
/**
|
|
1088
|
+
* Moves multiple files in a single batch operation.
|
|
1089
|
+
* @param operations Array of move operations, each containing:
|
|
1090
|
+
* source: Source file ID.
|
|
1091
|
+
* destination: Destination file ID or path.
|
|
1092
|
+
* @returns Promise resolving to batch operation response with successful and failed moves.
|
|
1093
|
+
* @remarks
|
|
1094
|
+
* Processes all moves in parallel using Promise.allSettled.
|
|
1095
|
+
* Individual failures do not stop the batch operation.
|
|
1096
|
+
* Each move operation is wrapped in error handling to capture failures.
|
|
1097
|
+
* Metrics are recorded for the batch operation and individual failures.
|
|
1098
|
+
* Returns both successful and failed operations with detailed error information.
|
|
1099
|
+
*/
|
|
1100
|
+
moveBatch(operations: {
|
|
1101
|
+
destination: string;
|
|
1102
|
+
source: string;
|
|
1103
|
+
}[]): Promise<BatchOperationResponse<TFile>>;
|
|
1104
|
+
/**
|
|
1105
|
+
* Prevent upload from being accessed by multiple requests.
|
|
1106
|
+
* Returns a unique token that must be passed back to `unlock()` so a caller whose lock TTL'd
|
|
1107
|
+
* out cannot accidentally release a newly-acquired lock held by another request.
|
|
1108
|
+
*/
|
|
1109
|
+
protected lock(key: string): Promise<string>;
|
|
1110
|
+
protected unlock(key: string, token?: string): Promise<void>;
|
|
1111
|
+
/**
|
|
1112
|
+
* Run a function while holding the lock for `key`. The lock is released even if `fn` throws,
|
|
1113
|
+
* and only released when the caller still owns the lock (token-verified). Public so that
|
|
1114
|
+
* handlers can serialize cross-call read-modify-write sequences on the same upload (e.g.
|
|
1115
|
+
* appending to `_chunks` during chunked PATCH).
|
|
1116
|
+
*/
|
|
1117
|
+
withLock<R>(key: string, function_: () => Promise<R>): Promise<R>;
|
|
1118
|
+
protected isUnsupportedChecksum(algorithm?: string): boolean;
|
|
1119
|
+
protected startAutoPurge(purgeInterval: number): void;
|
|
1120
|
+
protected updateTimestamps(file: TFile): TFile;
|
|
1121
|
+
/**
|
|
1122
|
+
* Backend-resolved retry configuration that {@link runOperation} layers
|
|
1123
|
+
* per-call overrides on top of. Subclasses that build a `RetryConfig`
|
|
1124
|
+
* (S3, Azure, Netlify, …) override this; the default (`undefined`) makes
|
|
1125
|
+
* `runOperation` fall back to the retry engine's own defaults.
|
|
1126
|
+
*/
|
|
1127
|
+
protected getRetryConfig(): RetryConfig | undefined;
|
|
1128
|
+
/**
|
|
1129
|
+
* Runs a backend SDK call with per-operation cancellation, timeout and
|
|
1130
|
+
* retry handling.
|
|
1131
|
+
*
|
|
1132
|
+
* The provided `signal` is the merge of the caller's `options.signal` and
|
|
1133
|
+
* a fresh per-attempt `options.timeout` deadline (via `AbortSignal.any` /
|
|
1134
|
+
* `AbortSignal.timeout`). Pass it to the underlying SDK so the provider
|
|
1135
|
+
* request is actually cancelled rather than merely abandoned.
|
|
1136
|
+
*
|
|
1137
|
+
* Aborted or timed-out calls are never retried. Pass
|
|
1138
|
+
* `{ replayable: false }` for operations whose body is a one-shot stream —
|
|
1139
|
+
* a consumed `Readable`/`ReadableStream` cannot be safely re-sent, so the
|
|
1140
|
+
* retry count is forced to zero.
|
|
1141
|
+
* @param options Per-call overrides (`signal`, `timeout`, `retries`).
|
|
1142
|
+
* @param function_ Receives the merged abort signal for the attempt.
|
|
1143
|
+
* @param operationConfig `replayable: false` disables retries for non-replayable bodies.
|
|
1144
|
+
*/
|
|
1145
|
+
protected runOperation<T>(options: OperationOptions | undefined, function_: (signal: AbortSignal | undefined) => Promise<T>, operationConfig?: {
|
|
1146
|
+
replayable?: boolean;
|
|
1147
|
+
}): Promise<T>;
|
|
1148
|
+
/**
|
|
1149
|
+
* Instruments a storage operation with metrics and error tracking.
|
|
1150
|
+
* @param operation Operation name (e.g., "create", "delete", "copy").
|
|
1151
|
+
* @param function_ The operation function to execute.
|
|
1152
|
+
* @param attributes Additional attributes to include in metrics.
|
|
1153
|
+
* @returns Promise resolving to the operation result.
|
|
1154
|
+
* @throws Re-throws any errors from the operation function.
|
|
1155
|
+
* @remarks
|
|
1156
|
+
* Records operation count, duration, and error metrics.
|
|
1157
|
+
* Tracks file sizes for operations returning file objects.
|
|
1158
|
+
* Error metrics include error messages for debugging.
|
|
1159
|
+
* All public methods should use this wrapper for consistent instrumentation.
|
|
1160
|
+
*/
|
|
1161
|
+
protected instrumentOperation<T>(operation: string, function_: () => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
|
|
1162
|
+
}
|
|
1163
|
+
export { retry as $, OnUpdate as A, BaseStorage as B, Cache as C, DiskStorageOptions as D, ErrorResponses as E, File as F, RangeChecksum as G, HttpError as H, IncomingMessageWithBody as I, RangeHasher as J, ResponseBody as K, LocalMetaStorageOptions as L, MetaStorage as M, ResponseTuple as N, OperationOptions as O, PurgeList as P, ValidationError as Q, RetryConfig as R, ValidatorConfig as S, defaultCloudStorageFileNameValidation as T, UploadFile as U, Validation as V, defaultFilesystemFileNameValidation as W, extractHttpStatus as X, isRetryableError as Y, isUploadError as Z, mapStatusToErrorCode as _, UploadError as a, throwErrorCode as a0, wrapStorageError as a1, UploadEventType as b, createRetryWrapper as c, FileInit as d, FilePart as e, FileQuery as f, FileReturn as g, ResponseBodyType as h, ERRORS as i, DiskStorageWithChecksumOptions as j, MetaStorageOptions as k, BaseStorageOptions as l, UploadResponse as m, Metrics as n, BatchOperationResponse as o, BatchOperationResult as p, ErrorMap as q, ExpirationOptions as r, Header as s, Headers as t, HttpErrorBody as u, Metadata as v, OnComplete as w, OnCreate as x, OnDelete as y, OnError as z };
|