s3kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +398 -0
- package/dist/adapters/express.cjs +305 -0
- package/dist/adapters/express.cjs.map +1 -0
- package/dist/adapters/express.d.cts +10 -0
- package/dist/adapters/express.d.ts +10 -0
- package/dist/adapters/express.js +278 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/fetch.cjs +298 -0
- package/dist/adapters/fetch.cjs.map +1 -0
- package/dist/adapters/fetch.d.cts +9 -0
- package/dist/adapters/fetch.d.ts +9 -0
- package/dist/adapters/fetch.js +271 -0
- package/dist/adapters/fetch.js.map +1 -0
- package/dist/adapters/next.cjs +796 -0
- package/dist/adapters/next.cjs.map +1 -0
- package/dist/adapters/next.d.cts +28 -0
- package/dist/adapters/next.d.ts +28 -0
- package/dist/adapters/next.js +775 -0
- package/dist/adapters/next.js.map +1 -0
- package/dist/client/index.cjs +153 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +59 -0
- package/dist/client/index.d.ts +59 -0
- package/dist/client/index.js +126 -0
- package/dist/client/index.js.map +1 -0
- package/dist/core/index.cjs +452 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +11 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.js +430 -0
- package/dist/core/index.js.map +1 -0
- package/dist/http/index.cjs +270 -0
- package/dist/http/index.cjs.map +1 -0
- package/dist/http/index.d.cts +49 -0
- package/dist/http/index.d.ts +49 -0
- package/dist/http/index.js +243 -0
- package/dist/http/index.js.map +1 -0
- package/dist/index.cjs +808 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +784 -0
- package/dist/index.js.map +1 -0
- package/dist/manager-BbmXpgXN.d.ts +29 -0
- package/dist/manager-gIjo-t8h.d.cts +29 -0
- package/dist/react/index.cjs +4320 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.css +155 -0
- package/dist/react/index.css.map +1 -0
- package/dist/react/index.d.cts +79 -0
- package/dist/react/index.d.ts +79 -0
- package/dist/react/index.js +4315 -0
- package/dist/react/index.js.map +1 -0
- package/dist/types-g2IYvH3O.d.cts +123 -0
- package/dist/types-g2IYvH3O.d.ts +123 -0
- package/package.json +100 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/manager.ts","../src/core/errors.ts","../src/http/handler.ts","../src/client/client.ts"],"sourcesContent":["import {\n CopyObjectCommand,\n DeleteObjectCommand,\n DeleteObjectsCommand,\n ListObjectsV2Command,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3'\nimport { GetObjectCommand } from '@aws-sdk/client-s3'\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner'\n\nimport type {\n S3CopyOptions,\n S3CreateFolderOptions,\n S3DeleteFilesOptions,\n S3DeleteFolderOptions,\n S3FileEntry,\n S3FileManagerAuthContext,\n S3FileManagerAuthorizationMode,\n S3FileManagerHooks,\n S3FileManagerOptions,\n S3FolderEntry,\n S3GetPreviewUrlOptions,\n S3GetPreviewUrlResult,\n S3ListOptions,\n S3ListResult,\n S3MoveOptions,\n S3PrepareUploadsOptions,\n S3PreparedUpload,\n S3SearchOptions,\n S3SearchResult,\n} from './types'\nimport { S3FileManagerAuthorizationError } from './errors'\n\nconst DEFAULT_DELIMITER = '/'\n\nfunction trimSlashes(input: string): string {\n return input.replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n\nfunction normalizePath(input: string): string {\n const raw = input.replace(/\\\\/g, '/')\n const noLeading = raw.replace(/^\\/+/, '')\n const segments = noLeading.split('/').filter((s) => s.length > 0)\n for (const seg of segments) {\n if (seg === '..') {\n throw new Error('Invalid path')\n }\n }\n return segments.join('/')\n}\n\nfunction ensureTrailingDelimiter(prefix: string, delimiter: string): string {\n if (prefix === '') return ''\n return prefix.endsWith(delimiter) ? prefix : `${prefix}${delimiter}`\n}\n\nfunction encodeS3CopySource(bucket: string, key: string): string {\n return encodeURIComponent(`${bucket}/${key}`).replace(/%2F/g, '/')\n}\n\nfunction isNoSuchKeyError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false\n if ('name' in err && err.name === 'NoSuchKey') return true\n if ('message' in err && typeof err.message === 'string') {\n return err.message.includes('The specified key does not exist')\n }\n return false\n}\n\nasync function* listAllKeys(\n s3: S3Client,\n bucket: string,\n prefix: string,\n): AsyncGenerator<string, void, void> {\n let cursor: string | undefined\n while (true) {\n const out = await s3.send(\n new ListObjectsV2Command({\n Bucket: bucket,\n Prefix: prefix,\n ContinuationToken: cursor,\n }),\n )\n\n for (const obj of out.Contents ?? []) {\n if (obj.Key) yield obj.Key\n }\n\n if (!out.IsTruncated) break\n cursor = out.NextContinuationToken\n }\n}\n\nasync function deleteKeysInBatches(s3: S3Client, bucket: string, keys: string[]): Promise<void> {\n const batchSize = 1000\n for (let i = 0; i < keys.length; i += batchSize) {\n const batch = keys.slice(i, i + batchSize)\n await s3.send(\n new DeleteObjectsCommand({\n Bucket: bucket,\n Delete: {\n Objects: batch.map((Key) => ({ Key })),\n Quiet: true,\n },\n }),\n )\n }\n}\n\nexport class S3FileManager<FileExtra = unknown, FolderExtra = unknown> {\n private readonly s3: S3Client\n private readonly bucket: string\n private readonly rootPrefix: string\n private readonly delimiter: string\n private readonly hooks: S3FileManagerHooks<FileExtra, FolderExtra> | undefined\n private readonly authorizationMode: S3FileManagerAuthorizationMode\n\n constructor(s3: S3Client, options: S3FileManagerOptions<FileExtra, FolderExtra>) {\n this.s3 = s3\n this.bucket = options.bucket\n this.delimiter = options.delimiter ?? DEFAULT_DELIMITER\n this.rootPrefix = ensureTrailingDelimiter(trimSlashes(options.rootPrefix ?? ''), this.delimiter)\n this.hooks = options.hooks\n this.authorizationMode = options.authorizationMode ?? 'deny-by-default'\n }\n\n private async authorize(\n args: Parameters<NonNullable<S3FileManagerHooks['authorize']>>[0],\n ): Promise<void> {\n const hasAuthHooks = Boolean(this.hooks?.authorize || this.hooks?.allowAction)\n\n if (this.hooks?.authorize) {\n const result = await this.hooks.authorize(args)\n if (result === false) {\n throw new S3FileManagerAuthorizationError('Unauthorized', 401, 'unauthorized')\n }\n }\n\n if (this.hooks?.allowAction) {\n const allowed = await this.hooks.allowAction(args)\n if (allowed === false) {\n throw new S3FileManagerAuthorizationError('Forbidden', 403, 'forbidden')\n }\n }\n\n if (!hasAuthHooks && this.authorizationMode === 'deny-by-default') {\n throw new S3FileManagerAuthorizationError('Unauthorized', 401, 'unauthorized')\n }\n }\n\n private pathToKey(path: string): string {\n const p = normalizePath(path)\n return `${this.rootPrefix}${p}`\n }\n\n private pathToFolderPrefix(path: string): string {\n const key = this.pathToKey(path)\n return ensureTrailingDelimiter(key, this.delimiter)\n }\n\n private keyToPath(key: string): string {\n if (!key.startsWith(this.rootPrefix)) {\n throw new Error('Key is outside of rootPrefix')\n }\n return key.slice(this.rootPrefix.length)\n }\n\n private makeFolderEntry(path: string): S3FolderEntry<FolderExtra> {\n const p = normalizePath(path)\n const name = p === '' ? '' : (p.split('/').at(-1) ?? '')\n return {\n type: 'folder',\n path: p === '' ? '' : ensureTrailingDelimiter(p, this.delimiter),\n name,\n }\n }\n\n private makeFileEntryFromKey(\n key: string,\n obj: {\n Size?: number\n LastModified?: Date\n ETag?: string\n },\n ): S3FileEntry<FileExtra> {\n const path = this.keyToPath(key)\n const name = path.split('/').at(-1) ?? ''\n return {\n type: 'file',\n path,\n name,\n ...(obj.Size !== undefined ? { size: obj.Size } : {}),\n ...(obj.LastModified ? { lastModified: obj.LastModified.toISOString() } : {}),\n ...(obj.ETag !== undefined ? { etag: obj.ETag } : {}),\n }\n }\n\n async list(\n options: S3ListOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<S3ListResult<FileExtra, FolderExtra>> {\n const path = normalizePath(options.path)\n await this.authorize({ action: 'list', path, ctx })\n\n const prefix = path === '' ? this.rootPrefix : this.pathToFolderPrefix(path)\n\n const out = await this.s3.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: prefix,\n Delimiter: this.delimiter,\n ContinuationToken: options.cursor,\n MaxKeys: options.limit,\n }),\n )\n\n const folders: Array<S3FolderEntry<FolderExtra>> = (\n (out.CommonPrefixes ?? []) as Array<{ Prefix?: string }>\n )\n .map((cp: { Prefix?: string }) => cp.Prefix)\n .filter((p: string | undefined): p is string => typeof p === 'string')\n .map((p: string) => {\n const rel = this.keyToPath(p)\n const folderPath = ensureTrailingDelimiter(trimSlashes(rel), this.delimiter)\n return this.makeFolderEntry(folderPath)\n })\n\n const files: Array<S3FileEntry<FileExtra>> = (\n (out.Contents ?? []) as Array<{\n Key?: string\n Size?: number\n LastModified?: Date\n ETag?: string\n }>\n )\n .filter((obj: { Key?: string }) => typeof obj.Key === 'string')\n .filter((obj: { Key?: string }) => obj.Key !== prefix)\n .map((obj) => this.makeFileEntryFromKey(obj.Key as string, obj))\n\n for (const folder of folders) {\n await this.hooks?.decorateFolder?.(folder, {\n path: folder.path,\n prefix: this.pathToFolderPrefix(folder.path),\n })\n }\n\n for (const file of files) {\n await this.hooks?.decorateFile?.(file, {\n path: file.path,\n key: this.pathToKey(file.path),\n })\n }\n\n const entries = [...folders, ...files].sort((a, b) => {\n if (a.type !== b.type) return a.type === 'folder' ? -1 : 1\n return a.name.localeCompare(b.name)\n })\n\n return {\n path,\n entries,\n ...(out.IsTruncated && out.NextContinuationToken\n ? { nextCursor: out.NextContinuationToken }\n : {}),\n }\n }\n\n async createFolder(\n options: S3CreateFolderOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<void> {\n const path = ensureTrailingDelimiter(normalizePath(options.path), this.delimiter)\n await this.authorize({ action: 'folder.create', path, ctx })\n\n const key = this.pathToFolderPrefix(path)\n await this.s3.send(\n new PutObjectCommand({\n Bucket: this.bucket,\n Key: key,\n Body: '',\n }),\n )\n }\n\n async deleteFolder(\n options: S3DeleteFolderOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<void> {\n const path = ensureTrailingDelimiter(normalizePath(options.path), this.delimiter)\n await this.authorize({ action: 'folder.delete', path, ctx })\n\n const prefix = this.pathToFolderPrefix(path)\n\n if (!options.recursive) {\n const out = await this.s3.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: prefix,\n MaxKeys: 2,\n }),\n )\n\n const keys = ((out.Contents ?? []) as Array<{ Key?: string }>)\n .map((o: { Key?: string }) => o.Key)\n .filter((k: string | undefined): k is string => typeof k === 'string' && k !== prefix)\n\n if (keys.length > 0) {\n throw new Error('Folder is not empty')\n }\n\n await this.s3.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: prefix }))\n return\n }\n\n const keys: string[] = []\n for await (const key of listAllKeys(this.s3, this.bucket, prefix)) {\n keys.push(key)\n }\n\n if (keys.length === 0) return\n await deleteKeysInBatches(this.s3, this.bucket, keys)\n }\n\n async deleteFiles(\n options: S3DeleteFilesOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<void> {\n const paths = options.paths.map((p) => normalizePath(p))\n for (const path of paths) {\n await this.authorize({ action: 'file.delete', path, ctx })\n }\n\n const keys = paths.map((p) => this.pathToKey(p))\n await deleteKeysInBatches(this.s3, this.bucket, keys)\n }\n\n async copy(options: S3CopyOptions, ctx: S3FileManagerAuthContext = {}): Promise<void> {\n const isFolder = options.fromPath.endsWith(this.delimiter)\n const fromPath = normalizePath(options.fromPath)\n const toPath = normalizePath(options.toPath)\n if (fromPath === toPath) return\n\n if (isFolder) {\n const fromPathWithSlash = ensureTrailingDelimiter(fromPath, this.delimiter)\n const toPathWithSlash = ensureTrailingDelimiter(toPath, this.delimiter)\n\n await this.authorize({\n action: 'folder.copy',\n fromPath: fromPathWithSlash,\n toPath: toPathWithSlash,\n ctx,\n })\n\n const fromPrefix = this.pathToFolderPrefix(fromPathWithSlash)\n const toPrefix = this.pathToFolderPrefix(toPathWithSlash)\n\n // Try copying the folder object itself\n try {\n await this.s3.send(\n new CopyObjectCommand({\n Bucket: this.bucket,\n Key: toPrefix,\n CopySource: encodeS3CopySource(this.bucket, fromPrefix),\n }),\n )\n } catch {\n // Ignore errors if the source folder object doesn't exist\n }\n\n // Copy all children\n for await (const sourceKey of listAllKeys(this.s3, this.bucket, fromPrefix)) {\n if (sourceKey === fromPrefix) continue\n\n const relKey = sourceKey.slice(fromPrefix.length)\n const destKey = toPrefix + relKey\n\n try {\n await this.s3.send(\n new CopyObjectCommand({\n Bucket: this.bucket,\n Key: destKey,\n CopySource: encodeS3CopySource(this.bucket, sourceKey),\n }),\n )\n } catch (err) {\n if (isNoSuchKeyError(err)) continue\n throw err\n }\n }\n return\n }\n\n await this.authorize({ action: 'file.copy', fromPath, toPath, ctx })\n\n const fromKey = this.pathToKey(fromPath)\n const toKey = this.pathToKey(toPath)\n\n await this.s3.send(\n new CopyObjectCommand({\n Bucket: this.bucket,\n Key: toKey,\n CopySource: encodeS3CopySource(this.bucket, fromKey),\n }),\n )\n }\n\n async move(options: S3MoveOptions, ctx: S3FileManagerAuthContext = {}): Promise<void> {\n const isFolder = options.fromPath.endsWith(this.delimiter)\n const fromPath = normalizePath(options.fromPath)\n const toPath = normalizePath(options.toPath)\n if (fromPath === toPath) return\n\n if (isFolder) {\n const fromPathWithSlash = ensureTrailingDelimiter(fromPath, this.delimiter)\n const toPathWithSlash = ensureTrailingDelimiter(toPath, this.delimiter)\n\n await this.authorize({\n action: 'folder.move',\n fromPath: fromPathWithSlash,\n toPath: toPathWithSlash,\n ctx,\n })\n\n // Delegate to copy (handles recursion)\n await this.copy(options, ctx)\n\n // Delete original folder recursively\n await this.deleteFolder({ path: fromPathWithSlash, recursive: true }, ctx)\n return\n }\n\n await this.authorize({ action: 'file.move', fromPath, toPath, ctx })\n\n await this.copy(options, ctx)\n await this.deleteFiles({ paths: [fromPath] }, ctx)\n }\n\n async prepareUploads(\n options: S3PrepareUploadsOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<S3PreparedUpload[]> {\n const expiresIn = options.expiresInSeconds ?? 60 * 5\n\n const result: S3PreparedUpload[] = []\n\n for (const item of options.items) {\n const path = normalizePath(item.path)\n await this.authorize({ action: 'upload.prepare', path, ctx })\n\n const key = this.pathToKey(path)\n\n const cmd = new PutObjectCommand({\n Bucket: this.bucket,\n Key: key,\n ContentType: item.contentType,\n CacheControl: item.cacheControl,\n ContentDisposition: item.contentDisposition,\n Metadata: item.metadata,\n })\n\n const url = await getSignedUrl(this.s3, cmd, { expiresIn })\n const headers: Record<string, string> = {}\n if (item.contentType) headers['Content-Type'] = item.contentType\n if (item.cacheControl) headers['Cache-Control'] = item.cacheControl\n if (item.contentDisposition) headers['Content-Disposition'] = item.contentDisposition\n if (item.metadata) {\n for (const [k, v] of Object.entries(item.metadata)) {\n headers[`x-amz-meta-${k}`] = v\n }\n }\n\n result.push({\n path,\n url,\n method: 'PUT',\n headers,\n })\n }\n\n return result\n }\n\n async search(\n options: S3SearchOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<S3SearchResult<FileExtra, FolderExtra>> {\n const query = options.query.toLowerCase().trim()\n if (!query) {\n return { query: options.query, entries: [] }\n }\n\n await this.authorize({ action: 'search', ctx })\n\n const searchPrefix = options.path\n ? this.pathToFolderPrefix(normalizePath(options.path))\n : this.rootPrefix\n\n const entries: Array<S3FileEntry<FileExtra>> = []\n\n // Search through objects (cursor is the underlying S3 continuation token).\n // Results are returned in the natural S3 listing order (lexicographic by key),\n // which keeps pagination stable.\n const limit = options.limit ?? 500\n const recursive = options.recursive !== false\n let cursor: string | undefined = options.cursor\n let nextCursor: string | undefined\n\n while (entries.length < limit) {\n const out = await this.s3.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: searchPrefix,\n ContinuationToken: cursor,\n MaxKeys: 1000, // Fetch more to filter\n }),\n )\n\n nextCursor =\n out.IsTruncated && out.NextContinuationToken ? out.NextContinuationToken : undefined\n\n // Process files\n for (const obj of out.Contents ?? []) {\n if (!obj.Key || obj.Key === searchPrefix) continue\n\n const path = this.keyToPath(obj.Key)\n const name = path.split('/').at(-1) ?? ''\n\n if (!recursive && options.path) {\n const base = ensureTrailingDelimiter(normalizePath(options.path), this.delimiter)\n const rel = path.startsWith(base) ? path.slice(base.length) : path\n if (rel.includes(this.delimiter)) continue\n }\n\n if (!recursive && !options.path) {\n if (path.includes(this.delimiter)) continue\n }\n\n // Check if file name matches search query\n if (name.toLowerCase().includes(query)) {\n const fileEntry = this.makeFileEntryFromKey(obj.Key, {\n ...(obj.Size !== undefined ? { Size: obj.Size } : {}),\n ...(obj.LastModified !== undefined ? { LastModified: obj.LastModified } : {}),\n ...(obj.ETag !== undefined ? { ETag: obj.ETag } : {}),\n })\n await this.hooks?.decorateFile?.(fileEntry, {\n path: fileEntry.path,\n key: this.pathToKey(fileEntry.path),\n })\n entries.push(fileEntry)\n }\n\n if (entries.length >= limit) break\n }\n\n if (!out.IsTruncated || !out.NextContinuationToken) break\n cursor = out.NextContinuationToken\n }\n\n return {\n query: options.query,\n entries,\n ...(nextCursor ? { nextCursor } : {}),\n }\n }\n\n async getPreviewUrl(\n options: S3GetPreviewUrlOptions,\n ctx: S3FileManagerAuthContext = {},\n ): Promise<S3GetPreviewUrlResult> {\n const path = normalizePath(options.path)\n await this.authorize({ action: 'preview.get', path, ctx })\n\n const expiresIn = options.expiresInSeconds ?? 60 * 5\n const key = this.pathToKey(path)\n\n const cmd = new GetObjectCommand({\n Bucket: this.bucket,\n Key: key,\n ResponseContentDisposition: options.inline ? 'inline' : 'attachment',\n })\n\n const url = await getSignedUrl(this.s3, cmd, { expiresIn })\n\n const expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString()\n return { path, url, expiresAt }\n }\n}\n","export class S3FileManagerAuthorizationError extends Error {\n readonly status: number\n readonly code: string\n\n constructor(message: string, status: number, code: string) {\n super(message)\n this.status = status\n this.code = code\n }\n}\n","import type { S3FileManager } from '../core/manager'\nimport { S3FileManagerAuthorizationError } from '../core/errors'\nimport type { S3FileManagerAuthContext } from '../core/types'\nimport type { HttpRequest, HttpResponse, S3FileManagerApiOptions } from './types'\n\nclass S3FileManagerHttpError extends Error {\n readonly status: number\n readonly code: string\n\n constructor(status: number, code: string, message: string) {\n super(message)\n this.status = status\n this.code = code\n }\n}\n\nfunction normalizeBasePath(basePath?: string): string {\n if (!basePath) return ''\n if (basePath === '/') return ''\n return basePath.startsWith('/')\n ? basePath.replace(/\\/+$/, '')\n : `/${basePath.replace(/\\/+$/, '')}`\n}\n\nfunction jsonError(status: number, code: string, message: string): HttpResponse {\n return {\n status,\n headers: { 'content-type': 'application/json' },\n body: {\n error: {\n code,\n message,\n },\n },\n }\n}\n\nfunction ensureObject(body: unknown): Record<string, unknown> {\n if (body && typeof body === 'object' && !Array.isArray(body))\n return body as Record<string, unknown>\n throw new S3FileManagerHttpError(400, 'invalid_body', 'Expected JSON object body')\n}\n\nfunction optionalString(value: unknown, key: string): string | undefined {\n if (value === undefined) return undefined\n if (typeof value === 'string') return value\n throw new S3FileManagerHttpError(400, 'invalid_body', `Expected '${key}' to be a string`)\n}\n\nfunction requiredString(value: unknown, key: string): string {\n if (typeof value === 'string') return value\n throw new S3FileManagerHttpError(400, 'invalid_body', `Expected '${key}' to be a string`)\n}\n\nfunction optionalNumber(value: unknown, key: string): number | undefined {\n if (value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value\n throw new S3FileManagerHttpError(400, 'invalid_body', `Expected '${key}' to be a finite number`)\n}\n\nfunction optionalBoolean(value: unknown, key: string): boolean | undefined {\n if (value === undefined) return undefined\n if (typeof value === 'boolean') return value\n throw new S3FileManagerHttpError(400, 'invalid_body', `Expected '${key}' to be a boolean`)\n}\n\nfunction requiredStringArray(value: unknown, key: string): string[] {\n if (!Array.isArray(value)) {\n throw new S3FileManagerHttpError(\n 400,\n 'invalid_body',\n `Expected '${key}' to be an array of strings`,\n )\n }\n for (const item of value) {\n if (typeof item !== 'string') {\n throw new S3FileManagerHttpError(\n 400,\n 'invalid_body',\n `Expected '${key}' to be an array of strings`,\n )\n }\n }\n return value\n}\n\nfunction optionalStringRecord(value: unknown, key: string): Record<string, string> | undefined {\n if (value === undefined) return undefined\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new S3FileManagerHttpError(\n 400,\n 'invalid_body',\n `Expected '${key}' to be an object of strings`,\n )\n }\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(value)) {\n if (typeof v !== 'string') {\n throw new S3FileManagerHttpError(400, 'invalid_body', `Expected '${key}.${k}' to be a string`)\n }\n out[k] = v\n }\n return out\n}\n\nfunction parseListOptions(body: unknown) {\n const obj = ensureObject(body)\n return {\n path: requiredString(obj.path, 'path'),\n cursor: optionalString(obj.cursor, 'cursor'),\n limit: optionalNumber(obj.limit, 'limit'),\n }\n}\n\nfunction parseSearchOptions(body: unknown) {\n const obj = ensureObject(body)\n return {\n query: requiredString(obj.query, 'query'),\n path: optionalString(obj.path, 'path'),\n recursive: optionalBoolean(obj.recursive, 'recursive'),\n limit: optionalNumber(obj.limit, 'limit'),\n cursor: optionalString(obj.cursor, 'cursor'),\n }\n}\n\nfunction parseCreateFolderOptions(body: unknown) {\n const obj = ensureObject(body)\n return { path: requiredString(obj.path, 'path') }\n}\n\nfunction parseDeleteFolderOptions(body: unknown) {\n const obj = ensureObject(body)\n return {\n path: requiredString(obj.path, 'path'),\n recursive: optionalBoolean(obj.recursive, 'recursive'),\n }\n}\n\nfunction parseDeleteFilesOptions(body: unknown) {\n const obj = ensureObject(body)\n return { paths: requiredStringArray(obj.paths, 'paths') }\n}\n\nfunction parseCopyMoveOptions(body: unknown) {\n const obj = ensureObject(body)\n return {\n fromPath: requiredString(obj.fromPath, 'fromPath'),\n toPath: requiredString(obj.toPath, 'toPath'),\n }\n}\n\nfunction parsePrepareUploadsOptions(body: unknown) {\n const obj = ensureObject(body)\n const itemsValue = obj.items\n if (!Array.isArray(itemsValue)) {\n throw new S3FileManagerHttpError(400, 'invalid_body', \"Expected 'items' to be an array\")\n }\n\n const items = itemsValue.map((raw, idx) => {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n throw new S3FileManagerHttpError(\n 400,\n 'invalid_body',\n `Expected 'items[${idx}]' to be an object`,\n )\n }\n const item = raw as Record<string, unknown>\n return {\n path: requiredString(item.path, `items[${idx}].path`),\n contentType: optionalString(item.contentType, `items[${idx}].contentType`),\n cacheControl: optionalString(item.cacheControl, `items[${idx}].cacheControl`),\n contentDisposition: optionalString(\n item.contentDisposition,\n `items[${idx}].contentDisposition`,\n ),\n metadata: optionalStringRecord(item.metadata, `items[${idx}].metadata`),\n }\n })\n\n return {\n items,\n expiresInSeconds: optionalNumber(obj.expiresInSeconds, 'expiresInSeconds'),\n }\n}\n\nfunction parsePreviewOptions(body: unknown) {\n const obj = ensureObject(body)\n return {\n path: requiredString(obj.path, 'path'),\n expiresInSeconds: optionalNumber(obj.expiresInSeconds, 'expiresInSeconds'),\n inline: optionalBoolean(obj.inline, 'inline'),\n }\n}\n\nexport interface CreateS3FileManagerHttpHandlerOptions<FileExtra, FolderExtra> {\n manager?: S3FileManager<FileExtra, FolderExtra>\n getManager?: (\n req: HttpRequest,\n ctx: S3FileManagerAuthContext,\n ) => S3FileManager<FileExtra, FolderExtra> | Promise<S3FileManager<FileExtra, FolderExtra>>\n getContext?: (req: HttpRequest) => Promise<S3FileManagerAuthContext> | S3FileManagerAuthContext\n api?: S3FileManagerApiOptions\n}\n\nexport function createS3FileManagerHttpHandler<FileExtra = unknown, FolderExtra = unknown>(\n options: CreateS3FileManagerHttpHandlerOptions<FileExtra, FolderExtra>,\n): (req: HttpRequest) => Promise<HttpResponse> {\n const basePath = normalizeBasePath(options.api?.basePath)\n\n if (!options.manager && !options.getManager) {\n throw new Error('createS3FileManagerHttpHandler requires either manager or getManager')\n }\n\n return async (req: HttpRequest): Promise<HttpResponse> => {\n try {\n const ctx = (await options.getContext?.(req)) ?? {}\n const manager = options.getManager ? await options.getManager(req, ctx) : options.manager!\n const method = req.method.toUpperCase()\n const path = req.path.startsWith(basePath) ? req.path.slice(basePath.length) || '/' : req.path\n\n if (method === 'POST' && path === '/list') {\n const out = await manager.list(parseListOptions(req.body) as any, ctx)\n return { status: 200, headers: { 'content-type': 'application/json' }, body: out as any }\n }\n\n if (method === 'POST' && path === '/search') {\n const out = await manager.search(parseSearchOptions(req.body) as any, ctx)\n return { status: 200, headers: { 'content-type': 'application/json' }, body: out as any }\n }\n\n if (method === 'POST' && path === '/folder/create') {\n await manager.createFolder(parseCreateFolderOptions(req.body) as any, ctx)\n return { status: 204 }\n }\n\n if (method === 'POST' && path === '/folder/delete') {\n await manager.deleteFolder(parseDeleteFolderOptions(req.body) as any, ctx)\n return { status: 204 }\n }\n\n if (method === 'POST' && path === '/files/delete') {\n await manager.deleteFiles(parseDeleteFilesOptions(req.body) as any, ctx)\n return { status: 204 }\n }\n\n if (method === 'POST' && path === '/files/copy') {\n await manager.copy(parseCopyMoveOptions(req.body) as any, ctx)\n return { status: 204 }\n }\n\n if (method === 'POST' && path === '/files/move') {\n await manager.move(parseCopyMoveOptions(req.body) as any, ctx)\n return { status: 204 }\n }\n\n if (method === 'POST' && path === '/upload/prepare') {\n const out = await manager.prepareUploads(parsePrepareUploadsOptions(req.body) as any, ctx)\n return { status: 200, headers: { 'content-type': 'application/json' }, body: out as any }\n }\n\n if (method === 'POST' && path === '/preview') {\n const out = await manager.getPreviewUrl(parsePreviewOptions(req.body) as any, ctx)\n return { status: 200, headers: { 'content-type': 'application/json' }, body: out as any }\n }\n\n return jsonError(404, 'not_found', 'Route not found')\n } catch (err) {\n if (err instanceof S3FileManagerHttpError) {\n return jsonError(err.status, err.code, err.message)\n }\n if (err instanceof S3FileManagerAuthorizationError) {\n return jsonError(err.status, err.code, err.message)\n }\n\n console.error('[S3FileManager Error]', err)\n const message = err instanceof Error ? err.message : 'Unknown error'\n return jsonError(500, 'internal_error', message)\n }\n }\n}\n","import type {\n S3CopyOptions,\n S3CreateFolderOptions,\n S3DeleteFilesOptions,\n S3DeleteFolderOptions,\n S3GetPreviewUrlOptions,\n S3ListOptions,\n S3MoveOptions,\n S3PrepareUploadsOptions,\n S3PreparedUpload,\n S3SearchOptions,\n} from '../core/types'\n\nimport type {\n S3FileManagerClientHooks,\n S3FileManagerClientOptions,\n S3FileManagerClientListResult,\n S3FileManagerClientSearchResult,\n S3FileManagerClientPreviewResult,\n} from './types'\n\nfunction normalizeBasePath(basePath?: string): string {\n if (!basePath) return ''\n if (basePath === '/') return ''\n return basePath.startsWith('/')\n ? basePath.replace(/\\/+$/, '')\n : `/${basePath.replace(/\\/+$/, '')}`\n}\n\nfunction normalizeApiRootFromParts(baseUrl: string, basePath?: string): string {\n const b = baseUrl.replace(/\\/+$/, '')\n const p = normalizeBasePath(basePath)\n return p ? `${b}${p}` : b\n}\n\nasync function fetchJson<T>(f: typeof fetch, url: string, body: unknown): Promise<T> {\n const res = await f(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(text || `Request failed: ${res.status}`)\n }\n\n if (res.status === 204) return undefined as T\n return (await res.json()) as T\n}\n\nfunction uploadWithXhr(\n upload: S3PreparedUpload,\n file: File,\n hooks?: S3FileManagerClientHooks,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest()\n xhr.open(upload.method, upload.url)\n\n for (const [k, v] of Object.entries(upload.headers ?? {})) {\n xhr.setRequestHeader(k, v)\n }\n\n xhr.upload.onprogress = (evt) => {\n hooks?.onUploadProgress?.({\n path: upload.path,\n loaded: evt.loaded,\n total: evt.total,\n })\n }\n\n xhr.onload = async () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n await hooks?.onUploadComplete?.({ path: upload.path })\n resolve()\n return\n }\n\n const responseText = xhr.responseText ? ` - ${xhr.responseText.slice(0, 200)}` : ''\n const error = new Error(`Upload failed: ${xhr.status}${responseText}`)\n await hooks?.onUploadError?.({ path: upload.path, error })\n reject(error)\n }\n\n xhr.onerror = async () => {\n const error = new Error('Upload failed: network error')\n await hooks?.onUploadError?.({ path: upload.path, error })\n reject(error)\n }\n\n xhr.send(file)\n })\n}\n\nexport class S3FileManagerClient {\n private readonly apiRoot: string\n private readonly f: typeof fetch\n\n constructor(options: S3FileManagerClientOptions) {\n this.apiRoot =\n 'apiUrl' in options\n ? options.apiUrl.replace(/\\/+$/, '')\n : normalizeApiRootFromParts(options.baseUrl, options.basePath)\n this.f = options.fetch ?? fetch\n }\n\n private endpoint(path: string): string {\n const p = path.startsWith('/') ? path : `/${path}`\n return `${this.apiRoot}${p}`\n }\n\n list(options: S3ListOptions): Promise<S3FileManagerClientListResult> {\n return fetchJson(this.f, this.endpoint('/list'), options)\n }\n\n search(options: S3SearchOptions): Promise<S3FileManagerClientSearchResult> {\n return fetchJson(this.f, this.endpoint('/search'), options)\n }\n\n createFolder(options: S3CreateFolderOptions): Promise<void> {\n return fetchJson(this.f, this.endpoint('/folder/create'), options)\n }\n\n deleteFolder(options: S3DeleteFolderOptions): Promise<void> {\n return fetchJson(this.f, this.endpoint('/folder/delete'), options)\n }\n\n deleteFiles(options: S3DeleteFilesOptions): Promise<void> {\n return fetchJson(this.f, this.endpoint('/files/delete'), options)\n }\n\n copy(options: S3CopyOptions): Promise<void> {\n return fetchJson(this.f, this.endpoint('/files/copy'), options)\n }\n\n move(options: S3MoveOptions): Promise<void> {\n return fetchJson(this.f, this.endpoint('/files/move'), options)\n }\n\n prepareUploads(options: S3PrepareUploadsOptions): Promise<S3PreparedUpload[]> {\n return fetchJson(this.f, this.endpoint('/upload/prepare'), options)\n }\n\n getPreviewUrl(options: S3GetPreviewUrlOptions): Promise<S3FileManagerClientPreviewResult> {\n return fetchJson(this.f, this.endpoint('/preview'), options)\n }\n\n async uploadFiles(args: {\n files: Array<{ file: File; path: string; contentType?: string }>\n expiresInSeconds?: number\n hooks?: S3FileManagerClientHooks\n parallel?: number\n }): Promise<void> {\n const prepare: S3PrepareUploadsOptions = {\n items: args.files.map((f) => ({\n path: f.path,\n contentType: f.contentType ?? f.file.type,\n })),\n ...(args.expiresInSeconds !== undefined ? { expiresInSeconds: args.expiresInSeconds } : {}),\n }\n\n const uploads = await this.prepareUploads(prepare)\n\n const byPath = new Map(uploads.map((u) => [u.path, u] as const))\n\n const tasks = args.files.map(({ file, path }) => {\n const upload = byPath.get(path)\n if (!upload) throw new Error(`Missing presigned upload for: ${path}`)\n return () => uploadWithXhr(upload, file, args.hooks)\n })\n\n const parallel = Math.max(1, args.parallel ?? 4)\n let i = 0\n\n const runWorker = async () => {\n while (true) {\n const idx = i++\n if (idx >= tasks.length) return\n await tasks[idx]!()\n }\n }\n\n await Promise.all(Array.from({ length: Math.min(parallel, tasks.length) }, runWorker))\n }\n}\n"],"mappings":"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","names":["keys","normalizeBasePath"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { A as S3FileManagerOptions, j as S3ListOptions, b as S3FileManagerAuthContext, k as S3ListResult, n as S3CreateFolderOptions, o as S3DeleteFolderOptions, p as S3DeleteFilesOptions, q as S3CopyOptions, r as S3MoveOptions, u as S3PrepareUploadsOptions, t as S3PreparedUpload, l as S3SearchOptions, m as S3SearchResult, v as S3GetPreviewUrlOptions, w as S3GetPreviewUrlResult } from './types-g2IYvH3O.js';
|
|
3
|
+
|
|
4
|
+
declare class S3FileManager<FileExtra = unknown, FolderExtra = unknown> {
|
|
5
|
+
private readonly s3;
|
|
6
|
+
private readonly bucket;
|
|
7
|
+
private readonly rootPrefix;
|
|
8
|
+
private readonly delimiter;
|
|
9
|
+
private readonly hooks;
|
|
10
|
+
private readonly authorizationMode;
|
|
11
|
+
constructor(s3: S3Client, options: S3FileManagerOptions<FileExtra, FolderExtra>);
|
|
12
|
+
private authorize;
|
|
13
|
+
private pathToKey;
|
|
14
|
+
private pathToFolderPrefix;
|
|
15
|
+
private keyToPath;
|
|
16
|
+
private makeFolderEntry;
|
|
17
|
+
private makeFileEntryFromKey;
|
|
18
|
+
list(options: S3ListOptions, ctx?: S3FileManagerAuthContext): Promise<S3ListResult<FileExtra, FolderExtra>>;
|
|
19
|
+
createFolder(options: S3CreateFolderOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
20
|
+
deleteFolder(options: S3DeleteFolderOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
21
|
+
deleteFiles(options: S3DeleteFilesOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
22
|
+
copy(options: S3CopyOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
23
|
+
move(options: S3MoveOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
24
|
+
prepareUploads(options: S3PrepareUploadsOptions, ctx?: S3FileManagerAuthContext): Promise<S3PreparedUpload[]>;
|
|
25
|
+
search(options: S3SearchOptions, ctx?: S3FileManagerAuthContext): Promise<S3SearchResult<FileExtra, FolderExtra>>;
|
|
26
|
+
getPreviewUrl(options: S3GetPreviewUrlOptions, ctx?: S3FileManagerAuthContext): Promise<S3GetPreviewUrlResult>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { S3FileManager as S };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { A as S3FileManagerOptions, j as S3ListOptions, b as S3FileManagerAuthContext, k as S3ListResult, n as S3CreateFolderOptions, o as S3DeleteFolderOptions, p as S3DeleteFilesOptions, q as S3CopyOptions, r as S3MoveOptions, u as S3PrepareUploadsOptions, t as S3PreparedUpload, l as S3SearchOptions, m as S3SearchResult, v as S3GetPreviewUrlOptions, w as S3GetPreviewUrlResult } from './types-g2IYvH3O.cjs';
|
|
3
|
+
|
|
4
|
+
declare class S3FileManager<FileExtra = unknown, FolderExtra = unknown> {
|
|
5
|
+
private readonly s3;
|
|
6
|
+
private readonly bucket;
|
|
7
|
+
private readonly rootPrefix;
|
|
8
|
+
private readonly delimiter;
|
|
9
|
+
private readonly hooks;
|
|
10
|
+
private readonly authorizationMode;
|
|
11
|
+
constructor(s3: S3Client, options: S3FileManagerOptions<FileExtra, FolderExtra>);
|
|
12
|
+
private authorize;
|
|
13
|
+
private pathToKey;
|
|
14
|
+
private pathToFolderPrefix;
|
|
15
|
+
private keyToPath;
|
|
16
|
+
private makeFolderEntry;
|
|
17
|
+
private makeFileEntryFromKey;
|
|
18
|
+
list(options: S3ListOptions, ctx?: S3FileManagerAuthContext): Promise<S3ListResult<FileExtra, FolderExtra>>;
|
|
19
|
+
createFolder(options: S3CreateFolderOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
20
|
+
deleteFolder(options: S3DeleteFolderOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
21
|
+
deleteFiles(options: S3DeleteFilesOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
22
|
+
copy(options: S3CopyOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
23
|
+
move(options: S3MoveOptions, ctx?: S3FileManagerAuthContext): Promise<void>;
|
|
24
|
+
prepareUploads(options: S3PrepareUploadsOptions, ctx?: S3FileManagerAuthContext): Promise<S3PreparedUpload[]>;
|
|
25
|
+
search(options: S3SearchOptions, ctx?: S3FileManagerAuthContext): Promise<S3SearchResult<FileExtra, FolderExtra>>;
|
|
26
|
+
getPreviewUrl(options: S3GetPreviewUrlOptions, ctx?: S3FileManagerAuthContext): Promise<S3GetPreviewUrlResult>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { S3FileManager as S };
|