@velajs/storage 0.3.1 → 0.3.2
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 +6 -1
- package/dist/body-BMUcBeQ0.js +93 -0
- package/dist/body-BMUcBeQ0.js.map +1 -0
- package/dist/client/index.d.ts +49 -46
- package/dist/client/index.js +207 -228
- package/dist/client/index.js.map +1 -0
- package/dist/drivers/memory/index.d.ts +17 -13
- package/dist/drivers/memory/index.js +190 -197
- package/dist/drivers/memory/index.js.map +1 -0
- package/dist/drivers/r2/index.d.ts +7 -4
- package/dist/drivers/r2/index.js +162 -160
- package/dist/drivers/r2/index.js.map +1 -0
- package/dist/drivers/r2-http/index.d.ts +23 -19
- package/dist/drivers/r2-http/index.js +52 -45
- package/dist/drivers/r2-http/index.js.map +1 -0
- package/dist/drivers/s3/index.d.ts +79 -5
- package/dist/drivers/s3/index.js +2 -3
- package/dist/index.d.ts +271 -17
- package/dist/index.js +1078 -16
- package/dist/index.js.map +1 -0
- package/dist/middleware/index.d.ts +177 -15
- package/dist/middleware/index.js +553 -8
- package/dist/middleware/index.js.map +1 -0
- package/dist/protocol.types-C5PPBD12.d.ts +80 -0
- package/dist/r2.types-Bw4Ft83t.d.ts +71 -0
- package/dist/retry-DXtO6R9D.js +119 -0
- package/dist/retry-DXtO6R9D.js.map +1 -0
- package/dist/s3-DrE9NrnD.js +557 -0
- package/dist/s3-DrE9NrnD.js.map +1 -0
- package/dist/storage.error-DVCOkJhc.js +49 -0
- package/dist/storage.error-DVCOkJhc.js.map +1 -0
- package/dist/storage.types-BJN7Yp1J.d.ts +288 -0
- package/dist/storagesdk/index.d.ts +73 -69
- package/dist/storagesdk/index.js +117 -130
- package/dist/storagesdk/index.js.map +1 -0
- package/dist/stored-file-2Yl07eRc.js +105 -0
- package/dist/stored-file-2Yl07eRc.js.map +1 -0
- package/dist/testing/index.d.ts +12 -8
- package/dist/testing/index.js +36 -53
- package/dist/testing/index.js.map +1 -0
- package/package.json +62 -48
- package/dist/base64.d.ts +0 -8
- package/dist/base64.js +0 -25
- package/dist/decorators/inject-storage.decorator.d.ts +0 -17
- package/dist/decorators/inject-storage.decorator.js +0 -21
- package/dist/drivers/r2/r2.types.d.ts +0 -67
- package/dist/drivers/r2/r2.types.js +0 -5
- package/dist/drivers/s3/s3-client.d.ts +0 -33
- package/dist/drivers/s3/s3-client.js +0 -154
- package/dist/drivers/s3/s3.driver.d.ts +0 -4
- package/dist/drivers/s3/s3.driver.js +0 -407
- package/dist/drivers/s3/s3.types.d.ts +0 -28
- package/dist/drivers/s3/s3.types.js +0 -1
- package/dist/drivers/s3/xml.d.ts +0 -6
- package/dist/drivers/s3/xml.js +0 -52
- package/dist/http/authorizer.types.d.ts +0 -59
- package/dist/http/authorizer.types.js +0 -1
- package/dist/http/http-helpers.d.ts +0 -22
- package/dist/http/http-helpers.js +0 -80
- package/dist/http/protocol.types.d.ts +0 -76
- package/dist/http/protocol.types.js +0 -1
- package/dist/internal/body.d.ts +0 -18
- package/dist/internal/body.js +0 -90
- package/dist/internal/retry.d.ts +0 -41
- package/dist/internal/retry.js +0 -127
- package/dist/internal/stored-file.d.ts +0 -27
- package/dist/internal/stored-file.js +0 -114
- package/dist/middleware/cache.d.ts +0 -50
- package/dist/middleware/cache.js +0 -101
- package/dist/middleware/compose.d.ts +0 -12
- package/dist/middleware/compose.js +0 -11
- package/dist/middleware/compression.d.ts +0 -16
- package/dist/middleware/compression.js +0 -101
- package/dist/middleware/encryption.d.ts +0 -14
- package/dist/middleware/encryption.js +0 -134
- package/dist/middleware/failover.d.ts +0 -18
- package/dist/middleware/failover.js +0 -52
- package/dist/middleware/retry.d.ts +0 -14
- package/dist/middleware/retry.js +0 -47
- package/dist/middleware/versioning.d.ts +0 -36
- package/dist/middleware/versioning.js +0 -89
- package/dist/middleware/wrap.d.ts +0 -11
- package/dist/middleware/wrap.js +0 -46
- package/dist/object-key.d.ts +0 -17
- package/dist/object-key.js +0 -42
- package/dist/storage.controller.d.ts +0 -21
- package/dist/storage.controller.js +0 -386
- package/dist/storage.error.d.ts +0 -38
- package/dist/storage.error.js +0 -52
- package/dist/storage.facade.d.ts +0 -47
- package/dist/storage.facade.js +0 -443
- package/dist/storage.module.d.ts +0 -46
- package/dist/storage.module.js +0 -113
- package/dist/storage.service.d.ts +0 -42
- package/dist/storage.service.js +0 -86
- package/dist/storage.tokens.d.ts +0 -13
- package/dist/storage.tokens.js +0 -26
- package/dist/storage.types.d.ts +0 -245
- package/dist/storage.types.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["#driver","#prefix","#readonly","#opts","#assertWritable","#assertUploadSupported","#path","#exec","#putMultipart","#assertRange","#relabel","#deleteMany","#strip","#assertDelimiter","#listPrefix"],"sources":["../src/object-key.ts","../src/storage.facade.ts","../src/http/http-helpers.ts","../src/storage.controller.ts","../src/storage.service.ts","../src/storage.tokens.ts","../src/storage.module.ts","../src/decorators/inject-storage.decorator.ts"],"sourcesContent":["import { StorageError } from './storage.error';\n\n// Object-key hygiene shared by the facade (prefix scoping) and the HTTP\n// controller (post-authorize re-sanitization). The rules block the classic\n// traversal / injection footguns without being so strict that legitimate\n// keys (nested \"folders\", dots, spaces) are rejected.\n\n// Control characters: C0 range (0x00-0x1F) plus DEL (0x7F).\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/;\n\n/**\n * True when `key` is a safe object key:\n * - non-empty, not longer than 1024 bytes (S3's limit)\n * - no leading `/`\n * - no `.` / `..` path segments (traversal)\n * - no control characters\n * - no backslashes (Windows-style separators)\n */\nexport function isSafeKey(key: string): boolean {\n if (typeof key !== 'string' || key.length === 0 || key.length > 1024) return false;\n if (key.startsWith('/')) return false;\n if (key.includes('\\\\')) return false;\n if (CONTROL_CHARS.test(key)) return false;\n for (const segment of key.split('/')) {\n if (segment === '.' || segment === '..') return false;\n }\n return true;\n}\n\n/** Return `key` if safe, else throw `StorageError('InvalidKey')`. */\nexport function sanitizeKey(key: string): string {\n if (!isSafeKey(key)) {\n throw new StorageError('InvalidKey', `unsafe object key: ${JSON.stringify(key)}`);\n }\n return key;\n}\n\n/** Normalize a prefix: drop leading/trailing slashes, collapse to '' when empty. */\nexport function normalizePrefix(prefix: string | undefined): string {\n if (!prefix) return '';\n return prefix.replace(/^\\/+/, '').replace(/\\/+$/, '');\n}\n\n/** Join a normalized prefix and a key with a single '/'. */\nexport function joinKey(prefix: string, key: string): string {\n return prefix ? `${prefix}/${key}` : key;\n}\n\n/** Strip a normalized prefix from a stored key (for surfacing to callers). */\nexport function stripPrefix(prefix: string, key: string): string {\n if (!prefix) return key;\n const withSlash = `${prefix}/`;\n return key.startsWith(withSlash) ? key.slice(withSlash.length) : key;\n}\n","import { byteLengthOf, chunkStream, countingStream, isStream, toStream } from './internal/body';\nimport { normalizeRetry, runWithRetry } from './internal/retry';\nimport { joinKey, normalizePrefix, sanitizeKey, stripPrefix } from './object-key';\nimport { StorageError } from './storage.error';\nimport type {\n Body,\n CreateMultipartOptions,\n DeleteManyError,\n DeleteManyOptions,\n DeleteManyResult,\n DownloadOptions,\n ListOptions,\n ListResult,\n MultipartOptions,\n MultipartUpload,\n OperationOptions,\n RetryOptions,\n SignedMultipartCapability,\n SignedUpload,\n SignUploadOptions,\n StorageCapabilities,\n StorageDriver,\n StorageOptions,\n StoredFile,\n UploadedPart,\n UploadOptions,\n UploadResult,\n UrlOptions,\n} from './storage.types';\n\nconst DEFAULT_PART_SIZE = 5 * 1024 * 1024; // 5 MiB (S3 minimum non-final part)\nconst DEFAULT_CONCURRENCY = 4;\n// Known-length bodies larger than this are routed through multipart so we never\n// buffer a whole large object in memory (aws4fetch must hash the payload).\nconst MULTIPART_THRESHOLD = 16 * 1024 * 1024;\n\n/**\n * The consumer-facing storage handle. Wraps a {@link StorageDriver} with\n * capability-gating (throws before any driver call), retry/timeout/abort,\n * prefix scoping, generic `move`/`deleteMany` fallbacks, multipart\n * orchestration, progress synthesis, and observability hooks.\n *\n * Framework-free — `StorageService` builds and caches one of these per bucket.\n */\nexport class Storage {\n readonly #driver: StorageDriver;\n readonly #prefix: string;\n readonly #readonly: boolean;\n readonly #opts: StorageOptions;\n\n constructor(opts: StorageOptions) {\n this.#opts = opts;\n this.#driver = opts.driver;\n this.#prefix = normalizePrefix(opts.prefix);\n this.#readonly = opts.readonly ?? false;\n }\n\n get raw(): unknown {\n return this.#driver.raw;\n }\n\n get driver(): StorageDriver {\n return this.#driver;\n }\n\n get capabilities(): StorageCapabilities {\n const d = this.#driver;\n return {\n rangeRead: !!d.supportsRange,\n uploadProgress: !!d.reportsUploadProgress,\n delimiter: !!d.supportsDelimiter,\n metadata: !!d.supportsMetadata,\n cacheControl: !!d.supportsCacheControl,\n serverSideCopy: !!d.supportsServerSideCopy,\n multipart: typeof d.createMultipartUpload === 'function',\n signedMultipart: d.signedMultipart != null,\n signedUrl: d.signedUrl ?? { supported: false, upload: false },\n };\n }\n\n // ---- upload ------------------------------------------------------------\n\n async upload(key: string, body: Body, opts?: UploadOptions): Promise<UploadResult> {\n this.#assertWritable();\n this.#assertUploadSupported(opts);\n const d = this.#driver;\n const path = this.#path(key);\n const len = byteLengthOf(body);\n const wantsMultipart = opts?.multipart != null && opts.multipart !== false;\n const unknownStream = isStream(body) && len === undefined;\n const bigKnown = len != null && len > MULTIPART_THRESHOLD;\n const canMultipart = typeof d.createMultipartUpload === 'function';\n\n if (wantsMultipart && !canMultipart) {\n throw new StorageError('Unsupported', `${d.name}: multipart not supported`);\n }\n if ((wantsMultipart || unknownStream || bigKnown) && canMultipart) {\n const result = await this.#exec('upload', key, false, opts, () =>\n this.#putMultipart(path, body, opts),\n );\n return { ...result, key };\n }\n\n const streaming = isStream(body);\n let outBody = body;\n if (opts?.onProgress && !d.reportsUploadProgress && streaming) {\n outBody = countingStream(body, (loaded) => opts.onProgress!({ loaded, total: len }));\n }\n const result = await this.#exec('upload', key, !streaming, opts, (signal) =>\n d.upload(path, outBody, { ...opts, signal }),\n );\n if (opts?.onProgress && !d.reportsUploadProgress && !streaming && len != null) {\n opts.onProgress({ loaded: len, total: len });\n }\n return { ...result, key };\n }\n\n async #putMultipart(path: string, body: Body, opts?: UploadOptions): Promise<UploadResult> {\n const mp: MultipartOptions = typeof opts?.multipart === 'object' ? opts.multipart : {};\n const partSize = mp.partSize ?? DEFAULT_PART_SIZE;\n const concurrency = Math.max(1, mp.concurrency ?? DEFAULT_CONCURRENCY);\n const total = byteLengthOf(body);\n const upload = await this.#driver.createMultipartUpload!(path, {\n contentType: opts?.contentType,\n cacheControl: opts?.cacheControl,\n metadata: opts?.metadata,\n signal: opts?.signal,\n });\n\n try {\n const parts: UploadedPart[] = [];\n let uploadedBytes = 0;\n let partNumber = 0;\n const inflight = new Set<Promise<void>>();\n\n for await (const chunk of chunkStream(toStream(body), partSize)) {\n partNumber += 1;\n const n = partNumber;\n const size = chunk.byteLength;\n const task: Promise<void> = (async () => {\n const up = await upload.uploadPart(n, chunk, { signal: opts?.signal });\n parts[n - 1] = { partNumber: n, etag: up.etag, size: up.size ?? size };\n uploadedBytes += size;\n opts?.onProgress?.({ loaded: uploadedBytes, total });\n })();\n const tracked = task.finally(() => inflight.delete(tracked));\n inflight.add(tracked);\n if (inflight.size >= concurrency) await Promise.race(inflight);\n }\n await Promise.all(inflight);\n return await upload.complete(parts, { signal: opts?.signal });\n } catch (e) {\n await upload.abort().catch(() => {});\n throw StorageError.wrap(e);\n }\n }\n\n // ---- read / metadata ---------------------------------------------------\n\n async download(key: string, opts?: DownloadOptions): Promise<StoredFile> {\n if (opts?.range) this.#assertRange();\n const file = await this.#exec('download', key, true, opts, (signal) =>\n this.#driver.download(this.#path(key), { ...opts, signal }),\n );\n return this.#relabel(file, key);\n }\n\n async head(key: string, opts?: OperationOptions): Promise<StoredFile> {\n const file = await this.#exec('head', key, true, opts, (signal) =>\n this.#driver.head(this.#path(key), { ...opts, signal }),\n );\n return this.#relabel(file, key);\n }\n\n exists(key: string, opts?: OperationOptions): Promise<boolean> {\n return this.#exec('exists', key, true, opts, (signal) =>\n this.#driver.exists(this.#path(key), { ...opts, signal }),\n );\n }\n\n // ---- mutations ---------------------------------------------------------\n\n delete(key: string, opts?: OperationOptions): Promise<void>;\n delete(keys: string[], opts?: DeleteManyOptions): Promise<DeleteManyResult>;\n async delete(\n keyOrKeys: string | string[],\n opts?: OperationOptions | DeleteManyOptions,\n ): Promise<void | DeleteManyResult> {\n this.#assertWritable();\n if (Array.isArray(keyOrKeys)) return this.#deleteMany(keyOrKeys, opts as DeleteManyOptions);\n const key = keyOrKeys;\n return this.#exec('delete', key, true, opts, (signal) =>\n this.#driver.delete(this.#path(key), { ...opts, signal }),\n );\n }\n\n async #deleteMany(keys: string[], opts?: DeleteManyOptions): Promise<DeleteManyResult> {\n const d = this.#driver;\n if (d.deleteMany) {\n const res = await this.#exec('deleteMany', undefined, true, opts, (signal) =>\n d.deleteMany!(\n keys.map((k) => this.#path(k)),\n { ...opts, signal },\n ),\n );\n return {\n deleted: res.deleted.map((k) => this.#strip(k)),\n errors: res.errors?.map((e) => ({ key: this.#strip(e.key), error: e.error })),\n };\n }\n // Generic bounded fan-out fallback.\n const concurrency = Math.max(1, opts?.concurrency ?? 8);\n const stopOnError = opts?.stopOnError ?? false;\n const deleted: string[] = [];\n const errors: DeleteManyError[] = [];\n let index = 0;\n let stopped = false;\n const worker = async () => {\n while (index < keys.length && !stopped) {\n const key = keys[index++];\n try {\n await d.delete(this.#path(key!), { signal: opts?.signal });\n deleted.push(key!);\n } catch (e) {\n const error = StorageError.wrap(e);\n errors.push({ key: key!, error });\n if (stopOnError) {\n stopped = true;\n throw error;\n }\n }\n }\n };\n const runners = Array.from({ length: Math.min(concurrency, keys.length) }, worker);\n if (stopOnError) await Promise.all(runners);\n else await Promise.allSettled(runners);\n return { deleted, errors: errors.length ? errors : undefined };\n }\n\n async copy(from: string, to: string, opts?: OperationOptions): Promise<void> {\n this.#assertWritable();\n return this.#exec('copy', to, true, opts, (signal) =>\n this.#driver.copy(this.#path(from), this.#path(to), { ...opts, signal }),\n );\n }\n\n async move(from: string, to: string, opts?: OperationOptions): Promise<void> {\n this.#assertWritable();\n const f = this.#path(from);\n const t = this.#path(to);\n if (f === t) return;\n if (this.#driver.move) {\n await this.#exec('move', to, true, opts, (signal) =>\n this.#driver.move!(f, t, { ...opts, signal }),\n );\n return;\n }\n await this.#exec('move', to, true, opts, async (signal) => {\n await this.#driver.copy(f, t, { ...opts, signal });\n await this.#driver.delete(f, { ...opts, signal });\n });\n }\n\n // ---- list --------------------------------------------------------------\n\n async list(opts?: ListOptions): Promise<ListResult> {\n if (opts?.delimiter) this.#assertDelimiter();\n const scopedPrefix = this.#listPrefix(opts?.prefix);\n const res = await this.#exec('list', undefined, true, opts, (signal) =>\n this.#driver.list({ ...opts, prefix: scopedPrefix, signal }),\n );\n return {\n items: res.items.map((f) => this.#relabel(f, this.#strip(f.key))),\n prefixes: res.prefixes?.map((p) => this.#strip(p)),\n cursor: res.cursor,\n };\n }\n\n async *listAll(opts?: ListOptions): AsyncGenerator<StoredFile> {\n let cursor = opts?.cursor;\n do {\n const page = await this.list({ ...opts, cursor });\n for (const item of page.items) yield item;\n cursor = page.cursor;\n } while (cursor);\n }\n\n // ---- URLs / presign ----------------------------------------------------\n\n async url(key: string, opts?: UrlOptions): Promise<string> {\n if (!this.#driver.signedUrl?.supported) {\n throw new StorageError('Unsupported', `${this.#driver.name}: url() not supported`);\n }\n return this.#exec('url', key, true, opts, (signal) =>\n this.#driver.url(this.#path(key), { ...opts, signal }),\n );\n }\n\n async signedUploadUrl(key: string, opts: SignUploadOptions): Promise<SignedUpload> {\n this.#assertWritable();\n if (!this.#driver.signedUrl?.upload) {\n throw new StorageError('Unsupported', `${this.#driver.name}: signed uploads not supported`);\n }\n return this.#exec('signedUploadUrl', key, true, opts, (signal) =>\n this.#driver.signedUploadUrl(this.#path(key), { ...opts, signal }),\n );\n }\n\n /** Prefix-bound view of the driver's presigned-multipart capability. */\n get signedMultipart(): SignedMultipartCapability | undefined {\n const cap = this.#driver.signedMultipart;\n if (!cap) return undefined;\n const path = (k: string) => this.#path(k);\n return {\n create: (key, o) => cap.create(path(key), o),\n signPart: (key, uploadId, partNumber, o) => cap.signPart(path(key), uploadId, partNumber, o),\n complete: (key, uploadId, parts) => cap.complete(path(key), uploadId, parts),\n abort: (key, uploadId) => cap.abort(path(key), uploadId),\n };\n }\n\n // ---- low-level multipart ----------------------------------------------\n\n async createMultipartUpload(\n key: string,\n opts?: CreateMultipartOptions,\n ): Promise<MultipartUpload> {\n this.#assertWritable();\n if (typeof this.#driver.createMultipartUpload !== 'function') {\n throw new StorageError('Unsupported', `${this.#driver.name}: multipart not supported`);\n }\n return this.#driver.createMultipartUpload(this.#path(key), opts);\n }\n\n resumeMultipartUpload(key: string, uploadId: string): MultipartUpload {\n this.#assertWritable();\n if (typeof this.#driver.resumeMultipartUpload !== 'function') {\n throw new StorageError('Unsupported', `${this.#driver.name}: multipart resume not supported`);\n }\n return this.#driver.resumeMultipartUpload(this.#path(key), uploadId);\n }\n\n // ---- ergonomics --------------------------------------------------------\n\n /** A key-bound handle over the common single-object operations. */\n file(key: string): FileHandle {\n return {\n key,\n upload: (body, o) => this.upload(key, body, o),\n download: (o) => this.download(key, o),\n head: (o) => this.head(key, o),\n exists: (o) => this.exists(key, o),\n delete: (o) => this.delete(key, o),\n url: (o) => this.url(key, o),\n signedUploadUrl: (o) => this.signedUploadUrl(key, o),\n };\n }\n\n /** A read-only clone of this handle (mutations throw `ReadOnly`). */\n readonly(): Storage {\n return new Storage({ ...this.#opts, readonly: true });\n }\n\n // ---- internals ---------------------------------------------------------\n\n #path(key: string): string {\n return joinKey(this.#prefix, sanitizeKey(key));\n }\n\n #strip(storedKey: string): string {\n return stripPrefix(this.#prefix, storedKey);\n }\n\n #listPrefix(prefix: string | undefined): string | undefined {\n if (!this.#prefix) return prefix;\n return prefix ? `${this.#prefix}/${prefix}` : `${this.#prefix}/`;\n }\n\n #relabel(file: StoredFile, logicalKey: string): StoredFile {\n if (file.key === logicalKey) return file;\n const name = logicalKey.slice(logicalKey.lastIndexOf('/') + 1);\n return {\n key: logicalKey,\n name,\n size: file.size,\n type: file.type,\n lastModified: file.lastModified,\n etag: file.etag,\n metadata: file.metadata,\n arrayBuffer: () => file.arrayBuffer(),\n text: () => file.text(),\n blob: () => file.blob(),\n stream: () => file.stream(),\n };\n }\n\n #assertWritable(): void {\n if (this.#readonly) throw new StorageError('ReadOnly', 'storage handle is read-only');\n }\n\n #assertUploadSupported(opts?: UploadOptions): void {\n const d = this.#driver;\n if (opts?.metadata && Object.keys(opts.metadata).length > 0 && !d.supportsMetadata) {\n throw new StorageError('Unsupported', `${d.name}: metadata not supported`);\n }\n if (opts?.cacheControl && !d.supportsCacheControl) {\n throw new StorageError('Unsupported', `${d.name}: cacheControl not supported`);\n }\n }\n\n #assertRange(): void {\n if (!this.#driver.supportsRange) {\n throw new StorageError('Unsupported', `${this.#driver.name}: range reads not supported`);\n }\n }\n\n #assertDelimiter(): void {\n if (!this.#driver.supportsDelimiter) {\n throw new StorageError('Unsupported', `${this.#driver.name}: delimiter not supported`);\n }\n }\n\n async #exec<T>(\n type: string,\n key: string | undefined,\n replayable: boolean,\n opts: OperationOptions | undefined,\n fn: (signal: AbortSignal | undefined) => Promise<T>,\n ): Promise<T> {\n const started = Date.now();\n const retries: RetryOptions | undefined = replayable\n ? (opts?.retries ?? this.#opts.retries)\n : 0;\n const maxRetries = normalizeRetry(retries).max;\n const hooks = this.#opts.hooks;\n try {\n const result = await runWithRetry(\n fn,\n {\n retries,\n timeout: opts?.timeout ?? this.#opts.timeout,\n signal: opts?.signal ?? this.#opts.signal,\n },\n (info) =>\n hooks?.onRetry?.({\n type,\n key,\n attempt: info.attempt,\n maxRetries,\n delayMs: info.delayMs,\n error: info.error,\n }),\n );\n hooks?.onOperation?.({ type, key, status: 'success', durationMs: Date.now() - started });\n return result;\n } catch (e) {\n const error = StorageError.wrap(e);\n hooks?.onError?.({ type, key, error });\n hooks?.onOperation?.({\n type,\n key,\n status: 'error',\n durationMs: Date.now() - started,\n error,\n });\n throw error;\n }\n }\n}\n\nexport interface FileHandle {\n readonly key: string;\n upload(body: Body, opts?: UploadOptions): Promise<UploadResult>;\n download(opts?: DownloadOptions): Promise<StoredFile>;\n head(opts?: OperationOptions): Promise<StoredFile>;\n exists(opts?: OperationOptions): Promise<boolean>;\n delete(opts?: OperationOptions): Promise<void>;\n url(opts?: UrlOptions): Promise<string>;\n signedUploadUrl(opts: SignUploadOptions): Promise<SignedUpload>;\n}\n\nexport function createStorage(opts: StorageOptions): Storage {\n return new Storage(opts);\n}\n","import type { StorageErrorCode } from '../storage.error';\nimport type { ByteRange, StoredFile } from '../storage.types';\nimport type { StorageWireErrorCode } from './protocol.types';\n\n/** Map a core error code to (wire code, HTTP status). */\nexport function mapError(code: StorageErrorCode): { wire: StorageWireErrorCode; status: number } {\n switch (code) {\n case 'NotFound':\n return { wire: 'not_found', status: 404 };\n case 'AccessDenied':\n case 'ReadOnly':\n return { wire: 'forbidden', status: 403 };\n case 'Unsupported':\n return { wire: 'capability_unsupported', status: 400 };\n case 'InvalidKey':\n return { wire: 'invalid_key', status: 400 };\n case 'InvalidRequest':\n case 'Aborted':\n return { wire: 'invalid_request', status: 400 };\n case 'Conflict':\n return { wire: 'conflict', status: 409 };\n case 'RateLimited':\n return { wire: 'rate_limited', status: 429 };\n case 'Timeout':\n return { wire: 'upstream_error', status: 504 };\n default:\n return { wire: 'upstream_error', status: 502 };\n }\n}\n\nexport function serializeStored(file: StoredFile) {\n return {\n key: file.key,\n name: file.name,\n size: file.size,\n type: file.type,\n lastModified: file.lastModified,\n etag: file.etag,\n metadata: file.metadata,\n };\n}\n\nexport function clampExpiry(requested: number | undefined, def: number, max: number): number {\n return Math.min(requested ?? def, max);\n}\n\n/** Parse an HTTP `Range` header (single range) into a {@link ByteRange}. */\nexport function parseRange(header: string | undefined | null): ByteRange | undefined {\n if (!header) return undefined;\n const m = /^bytes=(\\d+)-(\\d*)$/.exec(header.trim());\n if (!m) return undefined;\n const start = Number(m[1]);\n const end = m[2] === '' ? undefined : Number(m[2]);\n return { start, end };\n}\n\n/** Content-Disposition header — defaults to `attachment` (anti stored-XSS). */\nexport function dispositionHeader(disposition: string | undefined, name: string): string {\n const filename = `filename*=UTF-8''${encodeURIComponent(name)}`;\n return disposition === 'inline' ? `inline; ${filename}` : `attachment; ${filename}`;\n}\n","import {\n Controller,\n Get,\n Inject,\n Injectable,\n Post,\n Req,\n type Token,\n type Type,\n} from '@velajs/vela';\nimport type { Context } from 'hono';\nimport { sanitizeKey } from './object-key';\nimport { StorageError } from './storage.error';\nimport type { StorageService } from './storage.service';\nimport type { StorageAction, StorageAuthorizer, StorageAuthResult } from './http/authorizer.types';\nimport {\n clampExpiry,\n dispositionHeader,\n mapError,\n parseRange,\n serializeStored,\n} from './http/http-helpers';\nimport type {\n DeleteRequest,\n ListResponse,\n MultipartAbortRequest,\n MultipartCompleteRequest,\n MultipartCreateRequest,\n SignPartRequest,\n SignUploadRequest,\n} from './http/protocol.types';\n\nexport interface ResolvedHttpOptions {\n driverName: string;\n authorize?: StorageAuthorizer;\n defaultPolicy: 'deny' | 'allow';\n download: 'redirect' | 'proxy';\n defaultExpiresIn: number;\n maxExpiresIn: number;\n maxUploadSize?: number;\n maxListLimit: number;\n deleteConcurrency: number;\n}\n\n/**\n * Build a vela controller exposing presigned/multipart upload + download\n * endpoints for one bucket. Factory-decorated (like better-auth's catch-all)\n * so `basePath` bakes in at decoration time. Consumes the {@link StorageService}\n * facade so gating/retry/prefix apply uniformly on the HTTP path.\n */\nexport function createStorageController(\n basePath: string,\n serviceToken: Token<StorageService>,\n http: ResolvedHttpOptions,\n): Type {\n @Controller(basePath)\n @Injectable()\n class StorageController {\n constructor(@Inject(serviceToken) private readonly svc: StorageService) {}\n\n private get storage() {\n return this.svc.storage;\n }\n\n private async authorize(c: Context, action: StorageAction): Promise<StorageAuthResult> {\n if (!http.authorize) {\n if (http.defaultPolicy === 'allow') return {};\n throw new StorageError('AccessDenied', 'storage: no authorizer configured (default deny)');\n }\n const res = await http.authorize(action, { req: c.req.raw, ctx: c, driver: http.driverName });\n if (res === false) throw new StorageError('AccessDenied', 'not allowed');\n if (res === true) return {};\n return res;\n }\n\n private fail(c: Context, e: unknown): Response {\n const err = e instanceof StorageError ? e : StorageError.wrap(e);\n const { wire, status } = mapError(err.code);\n // Never echo a provider/transport/wrapped message to the client: those are\n // flagged `internal` (driver <Message>/<Code>, StorageError.wrap, fromStatus)\n // and can carry host/bucket/credential detail — including on a 4xx status.\n // Redact internal errors at any status, plus all upstream (5xx) responses;\n // 4xx codes with an author-vouched message echo it.\n const message = err.internal || status >= 500 ? 'storage backend error' : err.message;\n return c.json({ error: { code: wire, message } }, status as never);\n }\n\n @Post('/sign-upload')\n async signUpload(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as SignUploadRequest;\n const ov = await this.authorize(c, {\n type: 'sign-upload',\n key: b.key,\n contentType: b.contentType,\n size: b.size,\n });\n const key = sanitizeKey(ov.key ?? b.key);\n const upload = await this.storage.signedUploadUrl(key, {\n expiresIn: clampExpiry(\n ov.expiresIn ?? b.expiresIn,\n http.defaultExpiresIn,\n http.maxExpiresIn,\n ),\n contentType: b.contentType,\n maxSize: ov.maxSize ?? http.maxUploadSize,\n });\n return c.json({ key, upload });\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Post('/multipart/create')\n async multipartCreate(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as MultipartCreateRequest;\n const ov = await this.authorize(c, {\n type: 'multipart-create',\n key: b.key,\n contentType: b.contentType,\n });\n const key = sanitizeKey(ov.key ?? b.key);\n const sm = this.storage.signedMultipart;\n if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');\n const created = await sm.create(key, {\n contentType: b.contentType,\n metadata: ov.metadata ?? b.metadata,\n partSize: b.partSize,\n });\n return c.json({ key, uploadId: created.uploadId, partSize: created.partSize });\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Post('/multipart/sign-part')\n async multipartSignPart(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as SignPartRequest;\n const ov = await this.authorize(c, {\n type: 'multipart-sign-part',\n key: b.key,\n uploadId: b.uploadId,\n partNumber: b.partNumber,\n });\n const key = sanitizeKey(ov.key ?? b.key);\n const sm = this.storage.signedMultipart;\n if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');\n const part = await sm.signPart(key, b.uploadId, b.partNumber, {\n expiresIn: clampExpiry(ov.expiresIn, http.defaultExpiresIn, http.maxExpiresIn),\n });\n return c.json({\n partNumber: b.partNumber,\n method: 'PUT',\n url: part.url,\n headers: part.headers,\n });\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Post('/multipart/complete')\n async multipartComplete(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as MultipartCompleteRequest;\n const ov = await this.authorize(c, {\n type: 'multipart-complete',\n key: b.key,\n uploadId: b.uploadId,\n });\n const key = sanitizeKey(ov.key ?? b.key);\n const sm = this.storage.signedMultipart;\n if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');\n return c.json(await sm.complete(key, b.uploadId, b.parts));\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Post('/multipart/abort')\n async multipartAbort(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as MultipartAbortRequest;\n const ov = await this.authorize(c, {\n type: 'multipart-abort',\n key: b.key,\n uploadId: b.uploadId,\n });\n const key = sanitizeKey(ov.key ?? b.key);\n const sm = this.storage.signedMultipart;\n if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');\n await sm.abort(key, b.uploadId);\n return c.json({ ok: true });\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Get('/list')\n async list(@Req() c: Context): Promise<Response> {\n try {\n const prefix = c.req.query('prefix');\n const ov = await this.authorize(c, { type: 'list', prefix });\n const limit = c.req.query('limit');\n const res = await this.storage.list({\n prefix: ov.prefix ?? prefix,\n cursor: c.req.query('cursor'),\n delimiter: c.req.query('delimiter'),\n limit: limit ? Math.min(Number(limit), http.maxListLimit) : undefined,\n });\n return c.json({\n items: res.items.map(serializeStored),\n prefixes: res.prefixes,\n cursor: res.cursor,\n } satisfies ListResponse);\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Get('/head')\n async head(@Req() c: Context): Promise<Response> {\n try {\n const key = sanitizeKey(c.req.query('key') ?? '');\n const ov = await this.authorize(c, { type: 'head', key });\n const file = await this.storage.head(sanitizeKey(ov.key ?? key));\n return c.json(serializeStored(file));\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Post('/delete')\n async delete(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as DeleteRequest;\n const keys = b.keys.map((k) => sanitizeKey(k));\n const ov = await this.authorize(c, { type: 'delete', keys });\n const effective = (ov.keys ?? keys).map((k) => sanitizeKey(k));\n return c.json(\n await this.storage.delete(effective, { concurrency: http.deleteConcurrency }),\n );\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Get('/download')\n async download(@Req() c: Context): Promise<Response> {\n try {\n const key = sanitizeKey(c.req.query('key') ?? '');\n const disp = c.req.query('disposition');\n const ov = await this.authorize(c, { type: 'download', key });\n const ekey = sanitizeKey(ov.key ?? key);\n const name = ekey.slice(ekey.lastIndexOf('/') + 1);\n\n if (http.download === 'redirect' && this.storage.capabilities.signedUrl.supported) {\n const url = await this.storage.url(ekey, {\n expiresIn: clampExpiry(ov.expiresIn, http.defaultExpiresIn, http.maxExpiresIn),\n responseContentDisposition: dispositionHeader(disp, name),\n });\n return c.redirect(url, 302);\n }\n\n const range = parseRange(c.req.header('range'));\n const file = await this.storage.download(ekey, range ? { range } : undefined);\n const headers = new Headers({\n 'content-type': file.type,\n 'content-length': String(file.size),\n 'content-disposition': dispositionHeader(disp, file.name),\n });\n if (file.etag) headers.set('etag', file.etag);\n if (range) {\n headers.set('content-range', `bytes ${range.start}-${range.start + file.size - 1}/*`);\n return new Response(file.stream(), { status: 206, headers });\n }\n return new Response(file.stream(), { status: 200, headers });\n } catch (e) {\n return this.fail(c, e);\n }\n }\n\n @Post('/sign-download')\n async signDownload(@Req() c: Context): Promise<Response> {\n try {\n const b = (await c.req.json()) as { key: string; expiresIn?: number };\n const ov = await this.authorize(c, { type: 'download', key: b.key });\n const key = sanitizeKey(ov.key ?? b.key);\n const expiresIn = clampExpiry(\n ov.expiresIn ?? b.expiresIn,\n http.defaultExpiresIn,\n http.maxExpiresIn,\n );\n const url = await this.storage.url(key, { expiresIn });\n return c.json({ url, expiresAt: Date.now() + expiresIn * 1000 });\n } catch (e) {\n return this.fail(c, e);\n }\n }\n }\n\n return StorageController;\n}\n","import { Injectable } from '@velajs/vela';\nimport { createStorage, Storage } from './storage.facade';\nimport type {\n Body,\n DeleteManyOptions,\n DeleteManyResult,\n DownloadOptions,\n ListOptions,\n ListResult,\n OperationOptions,\n SignedUpload,\n SignUploadOptions,\n StorageDriver,\n StorageHooks,\n StoredFile,\n UploadOptions,\n UploadResult,\n UrlOptions,\n} from './storage.types';\n\n/**\n * Build the real driver on first property access and delegate to it. This is\n * the edge-binding-safe seam: the driver factory (which may read Cloudflare\n * bindings / `c.env` secrets) does not run at module load — only on the first\n * storage operation, which happens at request time.\n *\n * Functions are bound to the built driver so class-based drivers keep `this`.\n */\nexport function lazyDriver(build: () => StorageDriver): StorageDriver {\n let built: StorageDriver | undefined;\n const ensure = (): StorageDriver => (built ??= build());\n return new Proxy({} as StorageDriver, {\n get(_target, prop) {\n const driver = ensure() as unknown as Record<string | symbol, unknown>;\n const value = driver[prop];\n return typeof value === 'function'\n ? (value as (...a: unknown[]) => unknown).bind(driver)\n : value;\n },\n has(_target, prop) {\n return prop in (ensure() as unknown as object);\n },\n });\n}\n\nexport interface StorageServiceOptions {\n name: string;\n prefix?: string;\n readonly?: boolean;\n hooks?: StorageHooks;\n}\n\n/**\n * The injectable consumers reach for. Wraps one bucket's {@link Storage}\n * facade (lazy driver construction), plus thin forwarders for the common\n * single-object operations so `service.upload(...)` works without reaching\n * through `.storage`.\n *\n * For multiple buckets, register `StorageModule.forRoot({ name })` per bucket\n * and inject with `@InjectStorage(name)`.\n */\n@Injectable()\nexport class StorageService {\n readonly storage: Storage;\n readonly name: string;\n\n constructor(build: () => StorageDriver, options: StorageServiceOptions) {\n this.name = options.name;\n this.storage = createStorage({\n driver: lazyDriver(build),\n prefix: options.prefix,\n readonly: options.readonly,\n hooks: options.hooks,\n });\n }\n\n upload(key: string, body: Body, opts?: UploadOptions): Promise<UploadResult> {\n return this.storage.upload(key, body, opts);\n }\n download(key: string, opts?: DownloadOptions): Promise<StoredFile> {\n return this.storage.download(key, opts);\n }\n head(key: string, opts?: OperationOptions): Promise<StoredFile> {\n return this.storage.head(key, opts);\n }\n exists(key: string, opts?: OperationOptions): Promise<boolean> {\n return this.storage.exists(key, opts);\n }\n delete(key: string, opts?: OperationOptions): Promise<void> {\n return this.storage.delete(key, opts);\n }\n deleteMany(keys: string[], opts?: DeleteManyOptions): Promise<DeleteManyResult> {\n return this.storage.delete(keys, opts);\n }\n copy(from: string, to: string, opts?: OperationOptions): Promise<void> {\n return this.storage.copy(from, to, opts);\n }\n move(from: string, to: string, opts?: OperationOptions): Promise<void> {\n return this.storage.move(from, to, opts);\n }\n list(opts?: ListOptions): Promise<ListResult> {\n return this.storage.list(opts);\n }\n url(key: string, opts?: UrlOptions): Promise<string> {\n return this.storage.url(key, opts);\n }\n signedUploadUrl(key: string, opts: SignUploadOptions): Promise<SignedUpload> {\n return this.storage.signedUploadUrl(key, opts);\n }\n}\n","import { InjectionToken } from '@velajs/vela';\nimport type { StorageDriver } from './storage.types';\nimport type { StorageService } from './storage.service';\n\n/** Bucket name used when a registration omits `name`. */\nexport const DEFAULT_STORAGE_NAME = 'default';\n\n// Tokens are memoized per bucket name so a module's `provide` and a\n// consumer's `inject` resolve to the *same* token instance.\n\nconst builderTokens = new Map<string, InjectionToken<() => StorageDriver>>();\nconst serviceTokens = new Map<string, InjectionToken<StorageService>>();\n\n/** Internal token holding the lazy driver-construction thunk for `name`. */\nexport function storageDriverBuilder(name: string): InjectionToken<() => StorageDriver> {\n let token = builderTokens.get(name);\n if (!token) {\n token = new InjectionToken<() => StorageDriver>(`vela.storage.Builder:${name}`);\n builderTokens.set(name, token);\n }\n return token;\n}\n\n/**\n * Token that resolves to the {@link StorageService} for a named bucket.\n * The default bucket uses the `StorageService` class token directly (see\n * `@InjectStorage()`); named buckets use this.\n */\nexport function storageToken(name: string): InjectionToken<StorageService> {\n let token = serviceTokens.get(name);\n if (!token) {\n token = new InjectionToken<StorageService>(`vela.storage.Service:${name}`);\n serviceTokens.set(name, token);\n }\n return token;\n}\n","import {\n defineModule,\n lazyProvider,\n stableHash,\n type DynamicModule,\n type InferTokens,\n type Token,\n type Type,\n} from '@velajs/vela';\nimport { createStorageController, type ResolvedHttpOptions } from './storage.controller';\nimport { StorageService, type StorageServiceOptions } from './storage.service';\nimport { DEFAULT_STORAGE_NAME, storageDriverBuilder, storageToken } from './storage.tokens';\nimport type { StorageDriver, StorageHooks } from './storage.types';\nimport type { StorageAuthorizer } from './http/authorizer.types';\n\n/** Options for mounting the HTTP upload/download controller for a bucket. */\nexport interface StorageHttpOptions {\n /** Mount path (relative to vela's globalPrefix). Default `/api/storage`. */\n basePath?: string;\n /** Fine-grained per-action authorizer (deny / allow / allow-with-overrides). */\n authorize?: StorageAuthorizer;\n /** Behavior when no `authorize` is set. Default `'deny'`. */\n defaultPolicy?: 'deny' | 'allow';\n /** `redirect` to a signed URL (default) or `proxy` bytes through the Worker. */\n download?: 'redirect' | 'proxy';\n /** Set `false` to configure options without mounting the controller. Default mounts. */\n mountController?: boolean;\n defaultExpiresIn?: number;\n maxExpiresIn?: number;\n maxUploadSize?: number;\n maxListLimit?: number;\n deleteConcurrency?: number;\n}\n\nexport interface StorageModuleOptions {\n driver: StorageDriver;\n name?: string;\n prefix?: string;\n readonly?: boolean;\n hooks?: StorageHooks;\n http?: StorageHttpOptions;\n}\n\nexport interface StorageModuleAsyncOptions<\n Inject extends readonly Token<unknown>[] = readonly Token<unknown>[],\n> {\n inject?: Inject;\n imports?: DynamicModule['imports'];\n useFactory: (...deps: InferTokens<Inject>) => StorageDriver;\n name?: string;\n prefix?: string;\n readonly?: boolean;\n hooks?: StorageHooks;\n http?: StorageHttpOptions;\n key?: string;\n}\n\n/**\n * The internal, normalized options the module engine works with: the driver is\n * always a `() => StorageDriver` thunk so both `forRoot` (a built driver) and\n * `forRootAsync` (a deferred factory) flow through one options token and one\n * {@link lazyProvider}. The thunk is only *called* on first storage operation\n * (edge-binding safe), never at module load or service construction.\n */\ninterface StorageSetupOptions {\n driver: () => StorageDriver;\n name?: string;\n prefix?: string;\n readonly?: boolean;\n hooks?: StorageHooks;\n http?: StorageHttpOptions;\n}\n\n/**\n * The stable, identifying subset of the HTTP options folded into the instance\n * key — matches what `buildControllers` bakes into the mounted controller so\n * two registrations that differ only in HTTP behavior get distinct keys.\n */\nfunction httpKeyPart(http: StorageHttpOptions | undefined): Record<string, unknown> {\n if (!http || http.mountController === false) return {};\n return {\n basePath: http.basePath ?? '/api/storage',\n download: http.download ?? 'redirect',\n defaultPolicy: http.defaultPolicy ?? 'deny',\n };\n}\n\nfunction buildControllers(\n name: string,\n serviceToken: Token<StorageService>,\n http: StorageHttpOptions | undefined,\n): Type[] {\n if (!http || http.mountController === false) return [];\n const resolved: ResolvedHttpOptions = {\n driverName: name,\n authorize: http.authorize,\n defaultPolicy: http.defaultPolicy ?? 'deny',\n download: http.download ?? 'redirect',\n defaultExpiresIn: http.defaultExpiresIn ?? 900,\n maxExpiresIn: http.maxExpiresIn ?? 3600,\n maxUploadSize: http.maxUploadSize,\n maxListLimit: http.maxListLimit ?? 1000,\n deleteConcurrency: http.deleteConcurrency ?? 8,\n };\n const basePath = http.basePath ?? '/api/storage';\n return [createStorageController(basePath, serviceToken, resolved)];\n}\n\nconst { ConfigurableModuleClass } = defineModule<StorageSetupOptions>({\n name: 'Storage',\n // Value-shaped identity only: never the (stateful) driver thunk. Same\n // name+prefix+readonly+hooks+http dedups (HMR-idempotent); a distinct bucket\n // name coexists.\n key: (o) =>\n stableHash({\n name: o.name ?? DEFAULT_STORAGE_NAME,\n prefix: o.prefix ?? '',\n readonly: !!o.readonly,\n hooks: !!o.hooks,\n ...httpKeyPart(o.http),\n }),\n setup: ({ OPTIONS, options }) => {\n const name = options.name ?? DEFAULT_STORAGE_NAME;\n const builderToken = storageDriverBuilder(name);\n const serviceToken = name === DEFAULT_STORAGE_NAME ? StorageService : storageToken(name);\n const svcOptions: StorageServiceOptions = {\n name,\n prefix: options.prefix,\n readonly: options.readonly,\n hooks: options.hooks,\n };\n return {\n providers: [\n // Deferred, memoized driver construction — the seam that keeps\n // Cloudflare bindings / `c.env` reads out of module load.\n lazyProvider({\n provide: builderToken,\n inject: [OPTIONS],\n useFactory: (o: StorageSetupOptions) => o.driver(),\n }),\n {\n provide: serviceToken,\n useFactory: (build: () => StorageDriver) => new StorageService(build, svcOptions),\n inject: [builderToken],\n },\n ],\n controllers: buildControllers(name, serviceToken, options.http),\n exports: [serviceToken, builderToken],\n };\n },\n});\n\nexport class StorageModule {\n /** Synchronous registration — the driver is provided directly. */\n static forRoot(options: StorageModuleOptions): DynamicModule {\n const { driver, ...rest } = options;\n return {\n ...ConfigurableModuleClass.forRoot({ ...rest, driver: () => driver }),\n module: StorageModule,\n };\n }\n\n /** Deferred / DI-driven registration — `useFactory` runs lazily on first use. */\n static forRootAsync<const Inject extends readonly Token<unknown>[] = readonly Token<unknown>[]>(\n options: StorageModuleAsyncOptions<Inject>,\n ): DynamicModule {\n const { useFactory, inject, imports, key, ...structural } = options;\n return {\n ...ConfigurableModuleClass.forRootAsync<Inject>({\n imports,\n inject,\n key,\n ...structural,\n // Wrap the caller's driver factory in a thunk so resolving the options\n // token (at bootstrap) does NOT build the driver — only the first\n // storage operation does.\n useFactory: (...deps: InferTokens<Inject>) => ({ driver: () => useFactory(...deps) }),\n }),\n module: StorageModule,\n };\n }\n}\n","import { Inject } from '@velajs/vela';\nimport { StorageService } from '../storage.service';\nimport { DEFAULT_STORAGE_NAME, storageToken } from '../storage.tokens';\n\n/**\n * Inject the {@link StorageService} for a named bucket.\n *\n * ```ts\n * class UploadService {\n * constructor(\n * @InjectStorage() private readonly uploads: StorageService, // default bucket\n * @InjectStorage('backups') private readonly backups: StorageService, // named bucket\n * ) {}\n * }\n * ```\n *\n * The default bucket resolves the `StorageService` class token directly (so\n * plain `@Inject(StorageService)` and `Test.overrideProvider(StorageService)`\n * keep working); named buckets resolve their per-name token.\n */\nexport function InjectStorage(name: string = DEFAULT_STORAGE_NAME) {\n return Inject(name === DEFAULT_STORAGE_NAME ? StorageService : storageToken(name));\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,177 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { C as StorageDriver, h as RetryOptions } from "../storage.types-BJN7Yp1J.js";
|
|
2
|
+
//#region src/middleware/wrap.d.ts
|
|
3
|
+
/** A driver middleware: wraps a driver, returns a driver. */
|
|
4
|
+
type Middleware = (inner: StorageDriver) => StorageDriver;
|
|
5
|
+
/**
|
|
6
|
+
* Build a driver that delegates to `inner`, applying `over` overrides and
|
|
7
|
+
* omitting the methods in `omit`. Explicit delegation (not spread) keeps
|
|
8
|
+
* class-based drivers' `this`. Optional methods are forwarded only when the
|
|
9
|
+
* inner driver has them (so `presence == capability` is preserved), unless
|
|
10
|
+
* omitted (e.g. a body-transforming middleware suppresses multipart/presign).
|
|
11
|
+
*/
|
|
12
|
+
declare function passthrough(inner: StorageDriver, over?: Partial<StorageDriver>, omit?: ReadonlyArray<keyof StorageDriver>): StorageDriver;
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/middleware/compose.d.ts
|
|
15
|
+
/**
|
|
16
|
+
* Compose middlewares over a base driver. Listed innermost → outermost:
|
|
17
|
+
* `compose(base, a, b, c)` yields `c(b(a(base)))`, so on any call `c` runs
|
|
18
|
+
* first (outermost) and `base` last. The same wrapper handles read and write,
|
|
19
|
+
* so the reverse order on download comes for free.
|
|
20
|
+
*
|
|
21
|
+
* There is deliberately NO default preset — each middleware is opt-in, so you
|
|
22
|
+
* never accidentally ship, e.g., compress-then-encrypt (a CRIME/BREACH vector).
|
|
23
|
+
*/
|
|
24
|
+
declare function compose(base: StorageDriver, ...middlewares: Middleware[]): StorageDriver;
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/middleware/retry.d.ts
|
|
27
|
+
interface RetryMiddlewareOptions {
|
|
28
|
+
/** Default retry policy for driver operations. Per-call `opts.retries` wins. */
|
|
29
|
+
retries?: RetryOptions;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Retry transient failures at the driver level. Reads and idempotent ops
|
|
33
|
+
* always retry; an upload retries only when its body is replayable (not a
|
|
34
|
+
* one-shot stream). Note: the `Storage` facade also retries per
|
|
35
|
+
* `OperationOptions.retries` — use this middleware when driving a driver
|
|
36
|
+
* directly, or set the facade's retries to 0 to avoid compounding.
|
|
37
|
+
*/
|
|
38
|
+
declare function retry(opts?: RetryMiddlewareOptions): Middleware;
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/middleware/failover.d.ts
|
|
41
|
+
interface FailoverOptions {
|
|
42
|
+
/** Decide whether an error should trigger failover. Default: transient errors. */
|
|
43
|
+
shouldFailover?: (error: unknown) => boolean;
|
|
44
|
+
onFailover?: (info: {
|
|
45
|
+
from: number;
|
|
46
|
+
to: number;
|
|
47
|
+
error: unknown;
|
|
48
|
+
}) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Read-failover across a primary + fallbacks. Reads try each driver in order
|
|
52
|
+
* until one succeeds; writes and presigning go to the primary only (avoids
|
|
53
|
+
* partial/divergent writes). Capabilities are the intersection so the facade
|
|
54
|
+
* never routes a feature to a driver that can't serve it.
|
|
55
|
+
*/
|
|
56
|
+
declare function failover(fallbacks: StorageDriver[], opts?: FailoverOptions): Middleware;
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/middleware/cache.d.ts
|
|
59
|
+
interface CachedMeta {
|
|
60
|
+
key: string;
|
|
61
|
+
name: string;
|
|
62
|
+
size: number;
|
|
63
|
+
type: string;
|
|
64
|
+
lastModified?: number;
|
|
65
|
+
etag?: string;
|
|
66
|
+
metadata?: Record<string, string>;
|
|
67
|
+
}
|
|
68
|
+
interface CacheEntry {
|
|
69
|
+
expiresAt: number;
|
|
70
|
+
kind: 'meta' | 'exists';
|
|
71
|
+
meta?: CachedMeta;
|
|
72
|
+
exists?: boolean;
|
|
73
|
+
}
|
|
74
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
75
|
+
interface CacheStore {
|
|
76
|
+
get(key: string): MaybePromise<CacheEntry | undefined>;
|
|
77
|
+
set(key: string, value: CacheEntry, ttlMs: number): MaybePromise<void>;
|
|
78
|
+
delete(key: string): MaybePromise<void>;
|
|
79
|
+
}
|
|
80
|
+
/** In-memory, per-isolate cache with lazy TTL + insertion-order eviction (no timers). */
|
|
81
|
+
declare class MapCacheStore implements CacheStore {
|
|
82
|
+
#private;
|
|
83
|
+
private readonly maxEntries;
|
|
84
|
+
private readonly now;
|
|
85
|
+
constructor(maxEntries?: number, now?: () => number);
|
|
86
|
+
get(key: string): CacheEntry | undefined;
|
|
87
|
+
set(key: string, value: CacheEntry): void;
|
|
88
|
+
delete(key: string): void;
|
|
89
|
+
}
|
|
90
|
+
interface CacheOptions {
|
|
91
|
+
store?: CacheStore;
|
|
92
|
+
ttlMs?: number;
|
|
93
|
+
/** Which reads to cache. Default: head + exists (body/list are not cached). */
|
|
94
|
+
cache?: {
|
|
95
|
+
head?: boolean;
|
|
96
|
+
exists?: boolean;
|
|
97
|
+
};
|
|
98
|
+
keyPrefix?: string;
|
|
99
|
+
now?: () => number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Read-through cache for `head` / `exists`. Bodies are never cached (a `head`
|
|
103
|
+
* hit still lazily fetches on body access), and `list` is not cached
|
|
104
|
+
* (cross-prefix invalidation is intractable). Writes invalidate the key.
|
|
105
|
+
*/
|
|
106
|
+
declare function cache(opts?: CacheOptions): Middleware;
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/middleware/encryption.d.ts
|
|
109
|
+
interface EncryptionOptions {
|
|
110
|
+
/** A 256-bit AES-GCM key: a `CryptoKey` or 32 raw bytes. */
|
|
111
|
+
key: CryptoKey | Uint8Array;
|
|
112
|
+
/** How to treat objects that aren't valid ciphertext (legacy data). Default `throw`. */
|
|
113
|
+
onInvalid?: 'throw' | 'passthrough';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Transparent client-side encryption via Web Crypto AES-GCM. v1 encrypts the
|
|
117
|
+
* WHOLE object (buffered); the stored object is `IV(12) || ciphertext+tag`.
|
|
118
|
+
* Range reads, presigned URLs, and multipart are disabled (a signed URL would
|
|
119
|
+
* hand out ciphertext / accept plaintext, defeating the invariant).
|
|
120
|
+
*/
|
|
121
|
+
declare function encryption(opts: EncryptionOptions): Middleware;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/middleware/compression.d.ts
|
|
124
|
+
type CompressionFormat = 'gzip' | 'deflate' | 'deflate-raw';
|
|
125
|
+
interface CompressionOptions {
|
|
126
|
+
/** Stream format. Default `gzip`. */
|
|
127
|
+
format?: CompressionFormat;
|
|
128
|
+
/** What to do when `CompressionStream` is unavailable. Default `throw`. */
|
|
129
|
+
onUnavailable?: 'throw' | 'passthrough';
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Transparent gzip/deflate via Web Streams `CompressionStream` — fully
|
|
133
|
+
* streaming, opaque mode (v1). The stored object is compressed and tagged
|
|
134
|
+
* `vela-zip`; reads detect the tag and decompress, so pre-existing (untagged)
|
|
135
|
+
* objects pass through unharmed. Range reads / presigned URLs are disabled
|
|
136
|
+
* (the byte stream is not seekable and a direct URL would serve gzip).
|
|
137
|
+
*/
|
|
138
|
+
declare function compression(opts?: CompressionOptions): Middleware;
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/middleware/versioning.d.ts
|
|
141
|
+
interface VersionInfo {
|
|
142
|
+
versionId: string;
|
|
143
|
+
key: string;
|
|
144
|
+
size: number;
|
|
145
|
+
lastModified?: number;
|
|
146
|
+
}
|
|
147
|
+
/** Extra surface a versioning-wrapped driver exposes (reached via {@link unwrapVersioning}). */
|
|
148
|
+
interface Versioned {
|
|
149
|
+
listVersions(key: string): Promise<VersionInfo[]>;
|
|
150
|
+
restore(key: string, versionId: string): Promise<void>;
|
|
151
|
+
deleteVersion(key: string, versionId: string): Promise<void>;
|
|
152
|
+
}
|
|
153
|
+
declare const VERSIONED: unique symbol;
|
|
154
|
+
interface VersioningOptions {
|
|
155
|
+
/** Prefix under which prior versions are stored. Default `.vela-versions/`. */
|
|
156
|
+
prefix?: string;
|
|
157
|
+
versionId?: () => string;
|
|
158
|
+
/** Keep at most this many versions per key (prunes oldest). */
|
|
159
|
+
maxVersions?: number;
|
|
160
|
+
/** Hide the version prefix from `list()`. Default true. */
|
|
161
|
+
hideFromList?: boolean;
|
|
162
|
+
/** On delete: snapshot first (default) or purge all versions. */
|
|
163
|
+
onDelete?: 'snapshot' | 'purge';
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Keeps prior versions on overwrite via key-suffixing (no external manifest →
|
|
167
|
+
* no read-modify-write race). Snapshots are cheap when the base driver
|
|
168
|
+
* `supportsServerSideCopy`. Direct presigned uploads bypass snapshotting, so
|
|
169
|
+
* `signedUploadUrl` throws. Reach `listVersions`/`restore`/`deleteVersion` via
|
|
170
|
+
* {@link unwrapVersioning}.
|
|
171
|
+
*/
|
|
172
|
+
declare function versioning(opts?: VersioningOptions): Middleware;
|
|
173
|
+
/** Retrieve the {@link Versioned} surface from a versioning-wrapped driver (or `undefined`). */
|
|
174
|
+
declare function unwrapVersioning(driver: StorageDriver): Versioned | undefined;
|
|
175
|
+
//#endregion
|
|
176
|
+
export { type CacheEntry, type CacheOptions, type CacheStore, type CachedMeta, type CompressionFormat, type CompressionOptions, type EncryptionOptions, type FailoverOptions, MapCacheStore, type Middleware, type RetryMiddlewareOptions, VERSIONED, type VersionInfo, type Versioned, type VersioningOptions, cache, compose, compression, encryption, failover, passthrough, retry, unwrapVersioning, versioning };
|
|
177
|
+
//# sourceMappingURL=index.d.ts.map
|