@lark-apaas/file-service 0.1.1 → 0.1.2-alpha.1

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/dist/index.cjs CHANGED
@@ -90,7 +90,7 @@ var FILE_SIZE_LIMIT = 50 * 1024 * 1024;
90
90
 
91
91
  // src/utils/helpers.ts
92
92
  var isValidDownloadUrl = /* @__PURE__ */ __name((url) => {
93
- return /^\/spark\/app\/app_[\w]+\/runtime\/api\/v1\/storage/.test(url);
93
+ return /^(\/spark)?\/app\/app_[\w]+\/runtime\/api\/v1\/storage\/object\//.test(url);
94
94
  }, "isValidDownloadUrl");
95
95
  var maybeRetrieveFilePathFromDownloadUrl = /* @__PURE__ */ __name((path) => {
96
96
  if (!isValidDownloadUrl(path)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/lru-cache.ts","../src/core/http-error.ts","../src/const.ts","../src/utils/helpers.ts","../src/core/http-client.ts","../src/core/StreamDownloadBuilder.ts","../src/core/FileDownloadBuilder.ts","../src/core/file-service.ts","../src/types.ts"],"names":["LRUCache","capacity","cache","Error","Map","get","key","has","undefined","value","delete","set","put","size","firstKey","keys","next","clear","HttpError","status","body","message","name","THIRTY_DAYS_IN_SECONDS","FILE_SIZE_LIMIT","isValidDownloadUrl","url","test","maybeRetrieveFilePathFromDownloadUrl","path","objectPath","objectIndex","indexOf","afterObject","slice","length","bucketEndIndex","result","decodeURIComponent","parseFilePath","filePath","replace","toValidExpiresIn","expiresIn","isPlainObject","proto","Object","getPrototypeOf","prototype","getFileSize","fileBody","Buffer","byteLength","isBuffer","ArrayBuffer","isView","Blob","sanitizeFileName","fileName","illegalChars","encodeURIComponent","isNodeReadableStream","obj","hasPipe","pipe","hasNodeStreamFeatures","readable","isNotWebStream","getReader","isWebReadableStream","ReadableStream","CustomHttpClient","fetchClient","request","config","headers","JSON","stringify","some","toLowerCase","res","ok","statusText","clone","text","data","json","error_msg","status_code","method","post","StreamDownloadBuilder","downloadFn","then","onfulfilled","onrejected","execute","content","metadata","FileDownloadBuilder","asStream","contentLength","Number","blob","FileServiceCore","httpClient","upload","params","appId","bucketId","options","contentType","upsert","contentDisposition","cacheControl","optFileName","fileSize","preUploadBody","preUploadRes","uploadURL","uploadID","tosHeaders","isNodeStream","isWebStream","isStream","bodyToUpload","stream","Readable","toWeb","tosRes","fetch","duplex","eTag","callbackRes","downloadInner","fileMeta","getFileMetadata","signedURL","createSignedUrl","fileRes","download","list","prefix","searchOptions","attachments","hasMore","remove","filePaths","map","error","getDefaultBucket","cachedBucket","fetchBucket","defaultBucketId","app_runtime_extra","bucket","default_bucket_id","UserStatus"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 一个简单的 LRU (最近最少使用) 缓存实现。\n * 利用 JavaScript Map 维护插入顺序的特性。\n */\nexport class LRUCache<K, V> {\n private capacity: number;\n private cache: Map<K, V>;\n\n constructor(capacity: number) {\n if (capacity <= 0) {\n throw new Error('Capacity must be greater than 0');\n }\n this.capacity = capacity;\n this.cache = new Map<K, V>();\n }\n\n /**\n * 获取缓存值,如果存在则将其移动到最近使用的位置。\n */\n get(key: K): V | undefined {\n if (!this.cache.has(key)) {\n return undefined;\n }\n\n // 将访问的键移到末尾(表示最近使用)\n const value = this.cache.get(key)!;\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n /**\n * 存入缓存值。如果超过容量,则删除最久未使用的项。\n */\n put(key: K, value: V): void {\n if (this.cache.has(key)) {\n // 如果已存在,先删除,后面重新 set 会移到末尾\n this.cache.delete(key);\n } else if (this.cache.size >= this.capacity) {\n // 达到容量上限,删除第一个(最久未使用)\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * 检查是否包含某个键。不影响使用顺序。\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * 删除指定键。\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * 清空缓存。\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * 获取当前缓存大小。\n */\n get size(): number {\n return this.cache.size;\n }\n}\n","export class HttpError extends Error {\n status: number | string;\n body?: string;\n\n constructor(message: string, status: string | number, body?: string) {\n super(message);\n this.name = \"HttpError\";\n this.status = status;\n this.body = body;\n }\n}","export const THIRTY_DAYS_IN_SECONDS = 2592000;\nexport const FILE_SIZE_LIMIT = 50 * 1024 * 1024; // 50 MB","import { THIRTY_DAYS_IN_SECONDS } from '../const';\nimport { type FileBody } from \"../types\";\n\nconst isValidDownloadUrl = (url: string) => {\n return /^\\/spark\\/app\\/app_[\\w]+\\/runtime\\/api\\/v1\\/storage/.test(url);\n}\n\nconst maybeRetrieveFilePathFromDownloadUrl = (path: string) => {\n if (!isValidDownloadUrl(path)) {\n return path;\n }\n\n const objectPath = '/object/';\n const objectIndex = path.indexOf(objectPath);\n if (objectIndex === -1) {\n return '';\n }\n\n const afterObject = path.slice(objectIndex + objectPath.length);\n const bucketEndIndex = afterObject.indexOf('/');\n\n if (bucketEndIndex !== -1) {\n const result = afterObject.slice(bucketEndIndex + 1);\n return decodeURIComponent(result);\n }\n\n return '';\n}\n\nexport const parseFilePath = (filePath: string) => {\n const path = maybeRetrieveFilePathFromDownloadUrl(filePath);\n return path.replace(/^\\/+/, '');\n}\n\nexport const toValidExpiresIn = (expiresIn: number) => {\n if (expiresIn < 1) {\n return 1;\n }\n if (expiresIn > THIRTY_DAYS_IN_SECONDS) {\n return THIRTY_DAYS_IN_SECONDS;\n }\n return expiresIn;\n};\n\nexport const isPlainObject = (value: any): boolean => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nexport const getFileSize = (fileBody: FileBody): number | undefined => {\n if (typeof fileBody === 'string') {\n return Buffer.byteLength(fileBody);\n }\n if (Buffer.isBuffer(fileBody)) {\n return fileBody.length;\n }\n if (fileBody instanceof ArrayBuffer) {\n return fileBody.byteLength;\n }\n if (ArrayBuffer.isView(fileBody)) {\n return fileBody.byteLength;\n }\n if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {\n return fileBody.size;\n }\n return undefined;\n}\n\nexport const sanitizeFileName = (fileName: string) => {\n const illegalChars = /[:\"\\\\/*?<>|,;]/g;\n return encodeURIComponent(fileName.replace(illegalChars, '')) || 'download_file';\n};\n\n/**\n * 检测是否为 Node.js Readable Stream\n * 通过检查 Node.js Stream 特有的属性和方法来判断\n */\nexport const isNodeReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const obj = value as Record<string, unknown>;\n // Node.js Readable Stream 特征:\n // 1. 必须有 pipe 方法\n // 2. 必须有 _readableState 内部属性(Node.js Readable 特有)或 readable 属性\n // 3. 不能有 getReader 方法(排除 Web ReadableStream)\n const hasPipe = typeof obj.pipe === 'function';\n const hasNodeStreamFeatures = '_readableState' in obj || (typeof obj.readable === 'boolean');\n const isNotWebStream = typeof obj.getReader !== 'function';\n return hasPipe && hasNodeStreamFeatures && isNotWebStream;\n};\n\n/**\n * 检测是否为 Web ReadableStream\n * 通过检查 Web Streams API 特有的属性和方法来判断\n */\nexport const isWebReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n // 优先使用 instanceof 检查(如果 ReadableStream 在全局可用)\n if (typeof ReadableStream !== 'undefined' && value instanceof ReadableStream) {\n return true;\n }\n const obj = value as Record<string, unknown>;\n // Web ReadableStream 特征:\n // 1. 必须有 getReader 方法\n // 2. 必须有 locked 属性(Web ReadableStream 特有)\n return typeof obj.getReader === 'function' && 'locked' in obj;\n};","import type { FetchClient, CustomError, RequestConfig } from '../types';\nimport { HttpError } from './http-error';\nimport { isPlainObject } from '../utils/helpers';\n\nexport class CustomHttpClient {\n constructor(private readonly fetchClient: FetchClient) {}\n\n\n async request<T>(config: RequestConfig): Promise<T> {\n const headers: Record<string, string> = { ...config?.headers } as Record<string, string>;\n const body = config.body;\n if (isPlainObject(body)) {\n config.body = JSON.stringify(body);\n if (!Object.keys(headers).some((key) => key.toLowerCase() === 'content-type')) {\n headers['Content-Type'] = 'application/json';\n }\n }\n\n const res = await this.fetchClient.request({ ...config, headers });\n\n if (!res.ok) {\n throw new HttpError(res.statusText, res.status, await res.clone().text());\n }\n\n const data = await res.json(); \n \n if ((data as CustomError)?.error_msg && (data as CustomError)?.status_code) {\n throw new HttpError((data as CustomError).error_msg, (data as CustomError).status_code);\n }\n return data as T;\n }\n\n async get<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, method: 'GET', url }) as Promise<T>;\n }\n\n async post<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'POST', body: data }) as Promise<T>;\n }\n\n async put<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'PUT', body: data }) as Promise<T>;\n }\n\n async delete<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'DELETE' }) as Promise<T>;\n }\n}","import type { DownloadInnerResponse, DownloadResult } from \"../types\";\n\nexport class StreamDownloadBuilder implements PromiseLike<DownloadResult<ReadableStream>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n then<TResult1 = DownloadResult<ReadableStream>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<ReadableStream>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<ReadableStream>> {\n const result = await this.downloadFn();\n const { content, metadata } = result;\n\n if (!content.body) {\n throw new Error('Response body is null, cannot create stream');\n }\n\n return {\n content: content.body,\n metadata,\n }\n }\n}","import type { DownloadResult, DownloadInnerResponse } from \"../types\";\nimport { StreamDownloadBuilder } from \"./StreamDownloadBuilder\";\nimport { FILE_SIZE_LIMIT } from \"../const\";\n\nexport class FileDownloadBuilder implements PromiseLike<DownloadResult<Blob>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n asStream(): StreamDownloadBuilder {\n return new StreamDownloadBuilder(this.downloadFn);\n }\n\n then<TResult1 = DownloadResult<Blob>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<Blob>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<Blob>> {\n const result = await this.downloadFn();\n const { contentLength } = result.metadata?.metadata || {};\n if (contentLength && Number(contentLength) > FILE_SIZE_LIMIT) {\n throw new Error('Can\\'t download file blob larger than 50MB, use asStream() instead.');\n }\n const { content, metadata } = result;\n\n return {\n content: await content.blob(),\n metadata,\n }\n }\n}","import { LRUCache } from '../utils/lru-cache';\nimport type { FetchClient, SearchOptions, GetPublishedV2Response, FileBody, UploadOptions, PreUploadResponse, CallbackResponse, DownloadInnerResponse, FileMeta, ApiResponse, ListResponse, RemoveResponse, GetMetaResponse } from '../types';\nimport { CustomHttpClient } from './http-client';\nimport { HttpError } from \"./http-error\";\n\nimport { parseFilePath, toValidExpiresIn, getFileSize, sanitizeFileName, isNodeReadableStream, isWebReadableStream } from \"../utils/helpers\";\nimport { FileDownloadBuilder } from './FileDownloadBuilder';\n\nexport class FileServiceCore {\n private readonly cache = new LRUCache<string, string>(1000);\n private readonly httpClient: CustomHttpClient;\n\n constructor(\n private readonly fetchClient: FetchClient,\n ) {\n this.httpClient = new CustomHttpClient(this.fetchClient);\n }\n\n async upload(params: { appId: string; bucketId: string; fileBody: FileBody; options?: UploadOptions }) {\n const { appId, bucketId, fileBody, options } = params;\n const { contentType, upsert, contentDisposition, cacheControl, filePath, fileName: optFileName } = options ?? {};\n\n const fileSize = getFileSize(fileBody);\n const fileName = optFileName ?? (fileBody as File).name ?? \"\";\n\n const preUploadBody = {\n filePath,\n fileName,\n fileSize,\n contentType,\n upsert,\n };\n\n const preUploadRes = await this.httpClient.post<PreUploadResponse>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/preUpload`, preUploadBody);\n const { uploadURL, uploadID } = preUploadRes?.data ?? {};\n\n if (!uploadURL || !uploadID) {\n throw new Error('preUpload failed, uploadURL or uploadID is empty');\n }\n\n const tosHeaders: Record<string, string> = {};\n\n if (contentDisposition) {\n tosHeaders['content-disposition'] = contentDisposition;\n } else if (fileName) {\n tosHeaders['content-disposition'] = `attachment; filename=\"${sanitizeFileName(\n fileName\n )}\"`;\n }\n if (cacheControl || cacheControl === 0) {\n tosHeaders['cache-control'] = `max-age=${cacheControl}`;\n }\n if (contentType) {\n tosHeaders['content-type'] = contentType;\n }\n\n // 检测 Stream 类型\n const isNodeStream = isNodeReadableStream(fileBody);\n const isWebStream = isWebReadableStream(fileBody);\n const isStream = isNodeStream || isWebStream;\n\n // 转换 Node.js Stream 为 Web ReadableStream\n let bodyToUpload = fileBody;\n if (isNodeStream) {\n const stream = await import('stream');\n // Readable.toWeb 将 Node.js Stream 转换为 Web ReadableStream\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bodyToUpload = stream.Readable.toWeb(fileBody as any) as ReadableStream<Uint8Array>;\n }\n\n const tosRes = await fetch(uploadURL, {\n method: 'PUT',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n body: bodyToUpload as any,\n headers: tosHeaders,\n duplex: isStream ? 'half' : undefined,\n } as RequestInit);\n if (!tosRes.ok) {\n throw new HttpError(`upload failed, status: ${tosRes.status}, statusText: ${tosRes.statusText}`, tosRes.status);\n }\n const eTag = tosRes?.headers?.get('Etag') ?? '';\n\n const callbackRes = await this.httpClient.post<ApiResponse<CallbackResponse>>(`/api/v1/storage/inner/app/${appId}/object/callback`, { eTag, uploadID });\n\n return callbackRes?.data?.metadata;\n }\n\n // 对 nestjs 封装层透出的方法\n async downloadInner(params: { appId: string, bucketId: string; filePath: string; }): Promise<DownloadInnerResponse> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n const fileMeta = await this.getFileMetadata({ appId, bucketId, filePath: path });\n const signedURL = await this.createSignedUrl({ appId, bucketId, filePath: path, expiresIn: 60 });\n\n const fileRes = await fetch(signedURL);\n if (!fileRes.ok) {\n throw new HttpError(`download failed, status: ${fileRes.status}, statusText: ${fileRes.statusText}`, fileRes.status);\n }\n \n return {\n content: fileRes,\n metadata: fileMeta,\n };\n }\n\n // 封装层,可以通过download() 或者 download().asStream() 直接调用\n download(params: { appId: string, bucketId: string; filePath: string; }): FileDownloadBuilder {\n const downloadFn = () => this.downloadInner(params);\n return new FileDownloadBuilder(downloadFn);\n }\n\n async createSignedUrl(params: { appId: string; bucketId: string; filePath: string; expiresIn: number }): Promise<string> {\n const { appId, bucketId, filePath, expiresIn } = params;\n const path = parseFilePath(filePath);\n\n const res = await this.httpClient.post<ApiResponse<{ signedURL: string }>>(`/api/v1/storage/inner/app/${appId}/object/sign/${bucketId}/${encodeURIComponent(path)}`, {\n expiresIn: toValidExpiresIn(expiresIn),\n });\n\n return res?.data?.signedURL ?? '';\n }\n\n async list(params: { appId: string; bucketId: string; prefix: string; searchOptions?: SearchOptions}): Promise<ListResponse> {\n const { appId, bucketId, prefix, searchOptions } = params;\n\n const res = await this.httpClient.post<ApiResponse<ListResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/list`, {\n ...searchOptions,\n prefix,\n });\n\n return res?.data ?? { attachments: [], hasMore: false };\n }\n\n async remove(params: { appId: string; bucketId: string; filePaths: string[] }): Promise<FileMeta[]> {\n const { appId, bucketId, filePaths } = params;\n\n const res = await this.httpClient.delete<ApiResponse<RemoveResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/delete`, {\n body: {\n filePaths: filePaths.map((filePath) => parseFilePath(filePath)),\n } as any,\n });\n\n return res?.data?.attachments ?? [];\n }\n\n async getFileMetadata(params: { appId: string; bucketId: string; filePath: string }): Promise<FileMeta | null> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n try {\n const res = await this.httpClient.get<ApiResponse<GetMetaResponse>>(`/api/v1/storage/inner/app/${appId}/object/${bucketId}/head/${encodeURIComponent(path)}`);\n return res?.data?.metadata ?? null;\n } catch (error) {\n // 如果没有找到,返回null\n if (error instanceof HttpError && error.status === \"k_img_ec_000034\") {\n return null;\n }\n throw error;\n }\n }\n\n \n async getDefaultBucket(appId: string){\n const cachedBucket = this.cache.get(appId);\n if (cachedBucket) {\n return cachedBucket;\n }\n\n return this.fetchBucket(appId);\n }\n\n private async fetchBucket(appId: string): Promise<string> {\n const res = await this.httpClient.get<GetPublishedV2Response>(`/b/${appId}/get_published_v2`);\n const defaultBucketId = res?.data?.app_runtime_extra?.bucket?.default_bucket_id;\n \n if (defaultBucketId) {\n this.cache.put(appId, defaultBucketId);\n return defaultBucketId;\n } else {\n throw new HttpError(`No bucket found from remote for appId ${appId}`, 404);\n }\n }\n}","export type FileBody =\n | ArrayBuffer\n | Blob\n | Buffer\n | File\n | NodeJS.ArrayBufferView\n | NodeJS.ReadableStream\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface ApiResponse<T> {\n data: T\n}\n\nexport enum UserStatus {\n active = 1,\n inactive,\n}\n\nexport interface User {\n avatar: string;\n status: UserStatus;\n userID: number;\n email: string;\n name: string;\n userType: string;\n}\n\nexport interface FileMeta {\n id: string;\n name: string;\n filePath: string;\n metadata: {\n contentLength: string;\n mimeType: string;\n } & Record<string, string>;\n downloadURL: string;\n createdAt: string;\n createdBy: User;\n updatedAt: string;\n updatedBy: User;\n bucketID: string;\n}\n\nexport interface UploadOptions {\n filePath?: string;\n fileName?: string;\n cacheControl?: string | number;\n contentType?: string;\n upsert?: boolean;\n contentDisposition?: string;\n}\n\nexport interface SortBy {\n column?: string;\n order?: string;\n}\n\nexport interface SearchOptions {\n /**\n * The number of files you want to be returned.\n * @default 100\n */\n maxKeys?: number;\n\n /**\n * The starting file token.\n */\n continuationToken?: string;\n\n /**\n * The column to sort by. Can be any column inside a FileObject.\n */\n sortBy?: SortBy;\n}\n\nexport interface FetchClient {\n request(config: RequestInit): Promise<Response>;\n}\n\nexport interface RequestConfig extends RequestInit {\n url?: string;\n params?: Record<string, unknown>;\n timeout?: number;\n baseURL?: string;\n}\n\nexport interface CustomError {\n error_msg: string;\n status_code: string;\n lang_id: string;\n}\n\nexport interface DownloadResult<T> {\n content: T;\n metadata: FileMeta | null;\n}\n\nexport interface PreUploadResponse {\n data?: {\n uploadURL: string;\n uploadID: string;\n }\n}\n\nexport interface CallbackResponse {\n metadata: FileMeta\n}\n\nexport interface GetPublishedV2Response {\n data?: {\n app_info: {\n app_avatar: string;\n app_description: string;\n app_name: string;\n };\n app_runtime_extra: {\n bucket: {\n default_bucket_id: string;\n };\n url: string;\n };\n };\n}\n\nexport interface DownloadInnerResponse {\n content: Response;\n metadata: FileMeta | null;\n}\n\nexport interface ListResponse {\n attachments: FileMeta[],\n hasMore: boolean,\n}\n\nexport interface RemoveResponse {\n attachments: FileMeta[],\n}\n\nexport interface GetMetaResponse {\n metadata: FileMeta,\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/lru-cache.ts","../src/core/http-error.ts","../src/const.ts","../src/utils/helpers.ts","../src/core/http-client.ts","../src/core/StreamDownloadBuilder.ts","../src/core/FileDownloadBuilder.ts","../src/core/file-service.ts","../src/types.ts"],"names":["LRUCache","capacity","cache","Error","Map","get","key","has","undefined","value","delete","set","put","size","firstKey","keys","next","clear","HttpError","status","body","message","name","THIRTY_DAYS_IN_SECONDS","FILE_SIZE_LIMIT","isValidDownloadUrl","url","test","maybeRetrieveFilePathFromDownloadUrl","path","objectPath","objectIndex","indexOf","afterObject","slice","length","bucketEndIndex","result","decodeURIComponent","parseFilePath","filePath","replace","toValidExpiresIn","expiresIn","isPlainObject","proto","Object","getPrototypeOf","prototype","getFileSize","fileBody","Buffer","byteLength","isBuffer","ArrayBuffer","isView","Blob","sanitizeFileName","fileName","illegalChars","encodeURIComponent","isNodeReadableStream","obj","hasPipe","pipe","hasNodeStreamFeatures","readable","isNotWebStream","getReader","isWebReadableStream","ReadableStream","CustomHttpClient","fetchClient","request","config","headers","JSON","stringify","some","toLowerCase","res","ok","statusText","clone","text","data","json","error_msg","status_code","method","post","StreamDownloadBuilder","downloadFn","then","onfulfilled","onrejected","execute","content","metadata","FileDownloadBuilder","asStream","contentLength","Number","blob","FileServiceCore","httpClient","upload","params","appId","bucketId","options","contentType","upsert","contentDisposition","cacheControl","optFileName","fileSize","preUploadBody","preUploadRes","uploadURL","uploadID","tosHeaders","isNodeStream","isWebStream","isStream","bodyToUpload","stream","Readable","toWeb","tosRes","fetch","duplex","eTag","callbackRes","downloadInner","fileMeta","getFileMetadata","signedURL","createSignedUrl","fileRes","download","list","prefix","searchOptions","attachments","hasMore","remove","filePaths","map","error","getDefaultBucket","cachedBucket","fetchBucket","defaultBucketId","app_runtime_extra","bucket","default_bucket_id","UserStatus"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 一个简单的 LRU (最近最少使用) 缓存实现。\n * 利用 JavaScript Map 维护插入顺序的特性。\n */\nexport class LRUCache<K, V> {\n private capacity: number;\n private cache: Map<K, V>;\n\n constructor(capacity: number) {\n if (capacity <= 0) {\n throw new Error('Capacity must be greater than 0');\n }\n this.capacity = capacity;\n this.cache = new Map<K, V>();\n }\n\n /**\n * 获取缓存值,如果存在则将其移动到最近使用的位置。\n */\n get(key: K): V | undefined {\n if (!this.cache.has(key)) {\n return undefined;\n }\n\n // 将访问的键移到末尾(表示最近使用)\n const value = this.cache.get(key)!;\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n /**\n * 存入缓存值。如果超过容量,则删除最久未使用的项。\n */\n put(key: K, value: V): void {\n if (this.cache.has(key)) {\n // 如果已存在,先删除,后面重新 set 会移到末尾\n this.cache.delete(key);\n } else if (this.cache.size >= this.capacity) {\n // 达到容量上限,删除第一个(最久未使用)\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * 检查是否包含某个键。不影响使用顺序。\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * 删除指定键。\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * 清空缓存。\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * 获取当前缓存大小。\n */\n get size(): number {\n return this.cache.size;\n }\n}\n","export class HttpError extends Error {\n status: number | string;\n body?: string;\n\n constructor(message: string, status: string | number, body?: string) {\n super(message);\n this.name = \"HttpError\";\n this.status = status;\n this.body = body;\n }\n}","export const THIRTY_DAYS_IN_SECONDS = 2592000;\nexport const FILE_SIZE_LIMIT = 50 * 1024 * 1024; // 50 MB","import { THIRTY_DAYS_IN_SECONDS } from '../const';\nimport { type FileBody } from \"../types\";\n\nconst isValidDownloadUrl = (url: string) => {\n return /^(\\/spark)?\\/app\\/app_[\\w]+\\/runtime\\/api\\/v1\\/storage\\/object\\//.test(url);\n}\n\nconst maybeRetrieveFilePathFromDownloadUrl = (path: string) => {\n if (!isValidDownloadUrl(path)) {\n return path;\n }\n\n const objectPath = '/object/';\n const objectIndex = path.indexOf(objectPath);\n if (objectIndex === -1) {\n return '';\n }\n\n const afterObject = path.slice(objectIndex + objectPath.length);\n const bucketEndIndex = afterObject.indexOf('/');\n\n if (bucketEndIndex !== -1) {\n const result = afterObject.slice(bucketEndIndex + 1);\n return decodeURIComponent(result);\n }\n\n return '';\n}\n\nexport const parseFilePath = (filePath: string) => {\n const path = maybeRetrieveFilePathFromDownloadUrl(filePath);\n return path.replace(/^\\/+/, '');\n}\n\nexport const toValidExpiresIn = (expiresIn: number) => {\n if (expiresIn < 1) {\n return 1;\n }\n if (expiresIn > THIRTY_DAYS_IN_SECONDS) {\n return THIRTY_DAYS_IN_SECONDS;\n }\n return expiresIn;\n};\n\nexport const isPlainObject = (value: any): boolean => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nexport const getFileSize = (fileBody: FileBody): number | undefined => {\n if (typeof fileBody === 'string') {\n return Buffer.byteLength(fileBody);\n }\n if (Buffer.isBuffer(fileBody)) {\n return fileBody.length;\n }\n if (fileBody instanceof ArrayBuffer) {\n return fileBody.byteLength;\n }\n if (ArrayBuffer.isView(fileBody)) {\n return fileBody.byteLength;\n }\n if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {\n return fileBody.size;\n }\n return undefined;\n}\n\nexport const sanitizeFileName = (fileName: string) => {\n const illegalChars = /[:\"\\\\/*?<>|,;]/g;\n return encodeURIComponent(fileName.replace(illegalChars, '')) || 'download_file';\n};\n\n/**\n * 检测是否为 Node.js Readable Stream\n * 通过检查 Node.js Stream 特有的属性和方法来判断\n */\nexport const isNodeReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const obj = value as Record<string, unknown>;\n // Node.js Readable Stream 特征:\n // 1. 必须有 pipe 方法\n // 2. 必须有 _readableState 内部属性(Node.js Readable 特有)或 readable 属性\n // 3. 不能有 getReader 方法(排除 Web ReadableStream)\n const hasPipe = typeof obj.pipe === 'function';\n const hasNodeStreamFeatures = '_readableState' in obj || (typeof obj.readable === 'boolean');\n const isNotWebStream = typeof obj.getReader !== 'function';\n return hasPipe && hasNodeStreamFeatures && isNotWebStream;\n};\n\n/**\n * 检测是否为 Web ReadableStream\n * 通过检查 Web Streams API 特有的属性和方法来判断\n */\nexport const isWebReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n // 优先使用 instanceof 检查(如果 ReadableStream 在全局可用)\n if (typeof ReadableStream !== 'undefined' && value instanceof ReadableStream) {\n return true;\n }\n const obj = value as Record<string, unknown>;\n // Web ReadableStream 特征:\n // 1. 必须有 getReader 方法\n // 2. 必须有 locked 属性(Web ReadableStream 特有)\n return typeof obj.getReader === 'function' && 'locked' in obj;\n};","import type { FetchClient, CustomError, RequestConfig } from '../types';\nimport { HttpError } from './http-error';\nimport { isPlainObject } from '../utils/helpers';\n\nexport class CustomHttpClient {\n constructor(private readonly fetchClient: FetchClient) {}\n\n\n async request<T>(config: RequestConfig): Promise<T> {\n const headers: Record<string, string> = { ...config?.headers } as Record<string, string>;\n const body = config.body;\n if (isPlainObject(body)) {\n config.body = JSON.stringify(body);\n if (!Object.keys(headers).some((key) => key.toLowerCase() === 'content-type')) {\n headers['Content-Type'] = 'application/json';\n }\n }\n\n const res = await this.fetchClient.request({ ...config, headers });\n\n if (!res.ok) {\n throw new HttpError(res.statusText, res.status, await res.clone().text());\n }\n\n const data = await res.json(); \n \n if ((data as CustomError)?.error_msg && (data as CustomError)?.status_code) {\n throw new HttpError((data as CustomError).error_msg, (data as CustomError).status_code);\n }\n return data as T;\n }\n\n async get<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, method: 'GET', url }) as Promise<T>;\n }\n\n async post<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'POST', body: data }) as Promise<T>;\n }\n\n async put<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'PUT', body: data }) as Promise<T>;\n }\n\n async delete<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'DELETE' }) as Promise<T>;\n }\n}","import type { DownloadInnerResponse, DownloadResult } from \"../types\";\n\nexport class StreamDownloadBuilder implements PromiseLike<DownloadResult<ReadableStream>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n then<TResult1 = DownloadResult<ReadableStream>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<ReadableStream>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<ReadableStream>> {\n const result = await this.downloadFn();\n const { content, metadata } = result;\n\n if (!content.body) {\n throw new Error('Response body is null, cannot create stream');\n }\n\n return {\n content: content.body,\n metadata,\n }\n }\n}","import type { DownloadResult, DownloadInnerResponse } from \"../types\";\nimport { StreamDownloadBuilder } from \"./StreamDownloadBuilder\";\nimport { FILE_SIZE_LIMIT } from \"../const\";\n\nexport class FileDownloadBuilder implements PromiseLike<DownloadResult<Blob>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n asStream(): StreamDownloadBuilder {\n return new StreamDownloadBuilder(this.downloadFn);\n }\n\n then<TResult1 = DownloadResult<Blob>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<Blob>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<Blob>> {\n const result = await this.downloadFn();\n const { contentLength } = result.metadata?.metadata || {};\n if (contentLength && Number(contentLength) > FILE_SIZE_LIMIT) {\n throw new Error('Can\\'t download file blob larger than 50MB, use asStream() instead.');\n }\n const { content, metadata } = result;\n\n return {\n content: await content.blob(),\n metadata,\n }\n }\n}","import { LRUCache } from '../utils/lru-cache';\nimport type { FetchClient, SearchOptions, GetPublishedV2Response, FileBody, UploadOptions, PreUploadResponse, CallbackResponse, DownloadInnerResponse, FileMeta, ApiResponse, ListResponse, RemoveResponse, GetMetaResponse } from '../types';\nimport { CustomHttpClient } from './http-client';\nimport { HttpError } from \"./http-error\";\n\nimport { parseFilePath, toValidExpiresIn, getFileSize, sanitizeFileName, isNodeReadableStream, isWebReadableStream } from \"../utils/helpers\";\nimport { FileDownloadBuilder } from './FileDownloadBuilder';\n\nexport class FileServiceCore {\n private readonly cache = new LRUCache<string, string>(1000);\n private readonly httpClient: CustomHttpClient;\n\n constructor(\n private readonly fetchClient: FetchClient,\n ) {\n this.httpClient = new CustomHttpClient(this.fetchClient);\n }\n\n async upload(params: { appId: string; bucketId: string; fileBody: FileBody; options?: UploadOptions }) {\n const { appId, bucketId, fileBody, options } = params;\n const { contentType, upsert, contentDisposition, cacheControl, filePath, fileName: optFileName } = options ?? {};\n\n const fileSize = getFileSize(fileBody);\n const fileName = optFileName ?? (fileBody as File).name ?? \"\";\n\n const preUploadBody = {\n filePath,\n fileName,\n fileSize,\n contentType,\n upsert,\n };\n\n const preUploadRes = await this.httpClient.post<PreUploadResponse>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/preUpload`, preUploadBody);\n const { uploadURL, uploadID } = preUploadRes?.data ?? {};\n\n if (!uploadURL || !uploadID) {\n throw new Error('preUpload failed, uploadURL or uploadID is empty');\n }\n\n const tosHeaders: Record<string, string> = {};\n\n if (contentDisposition) {\n tosHeaders['content-disposition'] = contentDisposition;\n } else if (fileName) {\n tosHeaders['content-disposition'] = `attachment; filename=\"${sanitizeFileName(\n fileName\n )}\"`;\n }\n if (cacheControl || cacheControl === 0) {\n tosHeaders['cache-control'] = `max-age=${cacheControl}`;\n }\n if (contentType) {\n tosHeaders['content-type'] = contentType;\n }\n\n // 检测 Stream 类型\n const isNodeStream = isNodeReadableStream(fileBody);\n const isWebStream = isWebReadableStream(fileBody);\n const isStream = isNodeStream || isWebStream;\n\n // 转换 Node.js Stream 为 Web ReadableStream\n let bodyToUpload = fileBody;\n if (isNodeStream) {\n const stream = await import('stream');\n // Readable.toWeb 将 Node.js Stream 转换为 Web ReadableStream\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bodyToUpload = stream.Readable.toWeb(fileBody as any) as unknown as ReadableStream<Uint8Array>;\n }\n\n const tosRes = await fetch(uploadURL, {\n method: 'PUT',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n body: bodyToUpload as any,\n headers: tosHeaders,\n duplex: isStream ? 'half' : undefined,\n } as RequestInit);\n if (!tosRes.ok) {\n throw new HttpError(`upload failed, status: ${tosRes.status}, statusText: ${tosRes.statusText}`, tosRes.status);\n }\n const eTag = tosRes?.headers?.get('Etag') ?? '';\n\n const callbackRes = await this.httpClient.post<ApiResponse<CallbackResponse>>(`/api/v1/storage/inner/app/${appId}/object/callback`, { eTag, uploadID });\n\n return callbackRes?.data?.metadata;\n }\n\n // 对 nestjs 封装层透出的方法\n async downloadInner(params: { appId: string, bucketId: string; filePath: string; }): Promise<DownloadInnerResponse> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n const fileMeta = await this.getFileMetadata({ appId, bucketId, filePath: path });\n const signedURL = await this.createSignedUrl({ appId, bucketId, filePath: path, expiresIn: 60 });\n\n const fileRes = await fetch(signedURL);\n if (!fileRes.ok) {\n throw new HttpError(`download failed, status: ${fileRes.status}, statusText: ${fileRes.statusText}`, fileRes.status);\n }\n \n return {\n content: fileRes,\n metadata: fileMeta,\n };\n }\n\n // 封装层,可以通过download() 或者 download().asStream() 直接调用\n download(params: { appId: string, bucketId: string; filePath: string; }): FileDownloadBuilder {\n const downloadFn = () => this.downloadInner(params);\n return new FileDownloadBuilder(downloadFn);\n }\n\n async createSignedUrl(params: { appId: string; bucketId: string; filePath: string; expiresIn: number }): Promise<string> {\n const { appId, bucketId, filePath, expiresIn } = params;\n const path = parseFilePath(filePath);\n\n const res = await this.httpClient.post<ApiResponse<{ signedURL: string }>>(`/api/v1/storage/inner/app/${appId}/object/sign/${bucketId}/${encodeURIComponent(path)}`, {\n expiresIn: toValidExpiresIn(expiresIn),\n });\n\n return res?.data?.signedURL ?? '';\n }\n\n async list(params: { appId: string; bucketId: string; prefix: string; searchOptions?: SearchOptions}): Promise<ListResponse> {\n const { appId, bucketId, prefix, searchOptions } = params;\n\n const res = await this.httpClient.post<ApiResponse<ListResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/list`, {\n ...searchOptions,\n prefix,\n });\n\n return res?.data ?? { attachments: [], hasMore: false };\n }\n\n async remove(params: { appId: string; bucketId: string; filePaths: string[] }): Promise<FileMeta[]> {\n const { appId, bucketId, filePaths } = params;\n\n const res = await this.httpClient.delete<ApiResponse<RemoveResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/delete`, {\n body: {\n filePaths: filePaths.map((filePath) => parseFilePath(filePath)),\n } as any,\n });\n\n return res?.data?.attachments ?? [];\n }\n\n async getFileMetadata(params: { appId: string; bucketId: string; filePath: string }): Promise<FileMeta | null> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n try {\n const res = await this.httpClient.get<ApiResponse<GetMetaResponse>>(`/api/v1/storage/inner/app/${appId}/object/${bucketId}/head/${encodeURIComponent(path)}`);\n return res?.data?.metadata ?? null;\n } catch (error) {\n // 如果没有找到,返回null\n if (error instanceof HttpError && error.status === \"k_img_ec_000034\") {\n return null;\n }\n throw error;\n }\n }\n\n \n async getDefaultBucket(appId: string){\n const cachedBucket = this.cache.get(appId);\n if (cachedBucket) {\n return cachedBucket;\n }\n\n return this.fetchBucket(appId);\n }\n\n private async fetchBucket(appId: string): Promise<string> {\n const res = await this.httpClient.get<GetPublishedV2Response>(`/b/${appId}/get_published_v2`);\n const defaultBucketId = res?.data?.app_runtime_extra?.bucket?.default_bucket_id;\n \n if (defaultBucketId) {\n this.cache.put(appId, defaultBucketId);\n return defaultBucketId;\n } else {\n throw new HttpError(`No bucket found from remote for appId ${appId}`, 404);\n }\n }\n}\n","export type FileBody =\n | ArrayBuffer\n | Blob\n | Buffer\n | File\n | NodeJS.ArrayBufferView\n | NodeJS.ReadableStream\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface ApiResponse<T> {\n data: T\n}\n\nexport enum UserStatus {\n active = 1,\n inactive,\n}\n\nexport interface User {\n avatar: string;\n status: UserStatus;\n userID: number;\n email: string;\n name: string;\n userType: string;\n}\n\nexport interface FileMeta {\n id: string;\n name: string;\n filePath: string;\n metadata: {\n contentLength: string;\n mimeType: string;\n } & Record<string, string>;\n downloadURL: string;\n createdAt: string;\n createdBy: User;\n updatedAt: string;\n updatedBy: User;\n bucketID: string;\n}\n\nexport interface UploadOptions {\n filePath?: string;\n fileName?: string;\n cacheControl?: string | number;\n contentType?: string;\n upsert?: boolean;\n contentDisposition?: string;\n}\n\nexport interface SortBy {\n column?: string;\n order?: string;\n}\n\nexport interface SearchOptions {\n /**\n * The number of files you want to be returned.\n * @default 100\n */\n maxKeys?: number;\n\n /**\n * The starting file token.\n */\n continuationToken?: string;\n\n /**\n * The column to sort by. Can be any column inside a FileObject.\n */\n sortBy?: SortBy;\n}\n\nexport interface FetchClient {\n request(config: RequestInit): Promise<Response>;\n}\n\nexport interface RequestConfig extends RequestInit {\n url?: string;\n params?: Record<string, unknown>;\n timeout?: number;\n baseURL?: string;\n}\n\nexport interface CustomError {\n error_msg: string;\n status_code: string;\n lang_id: string;\n}\n\nexport interface DownloadResult<T> {\n content: T;\n metadata: FileMeta | null;\n}\n\nexport interface PreUploadResponse {\n data?: {\n uploadURL: string;\n uploadID: string;\n }\n}\n\nexport interface CallbackResponse {\n metadata: FileMeta\n}\n\nexport interface GetPublishedV2Response {\n data?: {\n app_info: {\n app_avatar: string;\n app_description: string;\n app_name: string;\n };\n app_runtime_extra: {\n bucket: {\n default_bucket_id: string;\n };\n url: string;\n };\n };\n}\n\nexport interface DownloadInnerResponse {\n content: Response;\n metadata: FileMeta | null;\n}\n\nexport interface ListResponse {\n attachments: FileMeta[],\n hasMore: boolean,\n}\n\nexport interface RemoveResponse {\n attachments: FileMeta[],\n}\n\nexport interface GetMetaResponse {\n metadata: FileMeta,\n}\n"]}
package/dist/index.js CHANGED
@@ -88,7 +88,7 @@ var FILE_SIZE_LIMIT = 50 * 1024 * 1024;
88
88
 
89
89
  // src/utils/helpers.ts
90
90
  var isValidDownloadUrl = /* @__PURE__ */ __name((url) => {
91
- return /^\/spark\/app\/app_[\w]+\/runtime\/api\/v1\/storage/.test(url);
91
+ return /^(\/spark)?\/app\/app_[\w]+\/runtime\/api\/v1\/storage\/object\//.test(url);
92
92
  }, "isValidDownloadUrl");
93
93
  var maybeRetrieveFilePathFromDownloadUrl = /* @__PURE__ */ __name((path) => {
94
94
  if (!isValidDownloadUrl(path)) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/lru-cache.ts","../src/core/http-error.ts","../src/const.ts","../src/utils/helpers.ts","../src/core/http-client.ts","../src/core/StreamDownloadBuilder.ts","../src/core/FileDownloadBuilder.ts","../src/core/file-service.ts","../src/types.ts"],"names":["LRUCache","capacity","cache","Error","Map","get","key","has","undefined","value","delete","set","put","size","firstKey","keys","next","clear","HttpError","status","body","message","name","THIRTY_DAYS_IN_SECONDS","FILE_SIZE_LIMIT","isValidDownloadUrl","url","test","maybeRetrieveFilePathFromDownloadUrl","path","objectPath","objectIndex","indexOf","afterObject","slice","length","bucketEndIndex","result","decodeURIComponent","parseFilePath","filePath","replace","toValidExpiresIn","expiresIn","isPlainObject","proto","Object","getPrototypeOf","prototype","getFileSize","fileBody","Buffer","byteLength","isBuffer","ArrayBuffer","isView","Blob","sanitizeFileName","fileName","illegalChars","encodeURIComponent","isNodeReadableStream","obj","hasPipe","pipe","hasNodeStreamFeatures","readable","isNotWebStream","getReader","isWebReadableStream","ReadableStream","CustomHttpClient","fetchClient","request","config","headers","JSON","stringify","some","toLowerCase","res","ok","statusText","clone","text","data","json","error_msg","status_code","method","post","StreamDownloadBuilder","downloadFn","then","onfulfilled","onrejected","execute","content","metadata","FileDownloadBuilder","asStream","contentLength","Number","blob","FileServiceCore","httpClient","upload","params","appId","bucketId","options","contentType","upsert","contentDisposition","cacheControl","optFileName","fileSize","preUploadBody","preUploadRes","uploadURL","uploadID","tosHeaders","isNodeStream","isWebStream","isStream","bodyToUpload","stream","Readable","toWeb","tosRes","fetch","duplex","eTag","callbackRes","downloadInner","fileMeta","getFileMetadata","signedURL","createSignedUrl","fileRes","download","list","prefix","searchOptions","attachments","hasMore","remove","filePaths","map","error","getDefaultBucket","cachedBucket","fetchBucket","defaultBucketId","app_runtime_extra","bucket","default_bucket_id","UserStatus"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 一个简单的 LRU (最近最少使用) 缓存实现。\n * 利用 JavaScript Map 维护插入顺序的特性。\n */\nexport class LRUCache<K, V> {\n private capacity: number;\n private cache: Map<K, V>;\n\n constructor(capacity: number) {\n if (capacity <= 0) {\n throw new Error('Capacity must be greater than 0');\n }\n this.capacity = capacity;\n this.cache = new Map<K, V>();\n }\n\n /**\n * 获取缓存值,如果存在则将其移动到最近使用的位置。\n */\n get(key: K): V | undefined {\n if (!this.cache.has(key)) {\n return undefined;\n }\n\n // 将访问的键移到末尾(表示最近使用)\n const value = this.cache.get(key)!;\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n /**\n * 存入缓存值。如果超过容量,则删除最久未使用的项。\n */\n put(key: K, value: V): void {\n if (this.cache.has(key)) {\n // 如果已存在,先删除,后面重新 set 会移到末尾\n this.cache.delete(key);\n } else if (this.cache.size >= this.capacity) {\n // 达到容量上限,删除第一个(最久未使用)\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * 检查是否包含某个键。不影响使用顺序。\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * 删除指定键。\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * 清空缓存。\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * 获取当前缓存大小。\n */\n get size(): number {\n return this.cache.size;\n }\n}\n","export class HttpError extends Error {\n status: number | string;\n body?: string;\n\n constructor(message: string, status: string | number, body?: string) {\n super(message);\n this.name = \"HttpError\";\n this.status = status;\n this.body = body;\n }\n}","export const THIRTY_DAYS_IN_SECONDS = 2592000;\nexport const FILE_SIZE_LIMIT = 50 * 1024 * 1024; // 50 MB","import { THIRTY_DAYS_IN_SECONDS } from '../const';\nimport { type FileBody } from \"../types\";\n\nconst isValidDownloadUrl = (url: string) => {\n return /^\\/spark\\/app\\/app_[\\w]+\\/runtime\\/api\\/v1\\/storage/.test(url);\n}\n\nconst maybeRetrieveFilePathFromDownloadUrl = (path: string) => {\n if (!isValidDownloadUrl(path)) {\n return path;\n }\n\n const objectPath = '/object/';\n const objectIndex = path.indexOf(objectPath);\n if (objectIndex === -1) {\n return '';\n }\n\n const afterObject = path.slice(objectIndex + objectPath.length);\n const bucketEndIndex = afterObject.indexOf('/');\n\n if (bucketEndIndex !== -1) {\n const result = afterObject.slice(bucketEndIndex + 1);\n return decodeURIComponent(result);\n }\n\n return '';\n}\n\nexport const parseFilePath = (filePath: string) => {\n const path = maybeRetrieveFilePathFromDownloadUrl(filePath);\n return path.replace(/^\\/+/, '');\n}\n\nexport const toValidExpiresIn = (expiresIn: number) => {\n if (expiresIn < 1) {\n return 1;\n }\n if (expiresIn > THIRTY_DAYS_IN_SECONDS) {\n return THIRTY_DAYS_IN_SECONDS;\n }\n return expiresIn;\n};\n\nexport const isPlainObject = (value: any): boolean => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nexport const getFileSize = (fileBody: FileBody): number | undefined => {\n if (typeof fileBody === 'string') {\n return Buffer.byteLength(fileBody);\n }\n if (Buffer.isBuffer(fileBody)) {\n return fileBody.length;\n }\n if (fileBody instanceof ArrayBuffer) {\n return fileBody.byteLength;\n }\n if (ArrayBuffer.isView(fileBody)) {\n return fileBody.byteLength;\n }\n if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {\n return fileBody.size;\n }\n return undefined;\n}\n\nexport const sanitizeFileName = (fileName: string) => {\n const illegalChars = /[:\"\\\\/*?<>|,;]/g;\n return encodeURIComponent(fileName.replace(illegalChars, '')) || 'download_file';\n};\n\n/**\n * 检测是否为 Node.js Readable Stream\n * 通过检查 Node.js Stream 特有的属性和方法来判断\n */\nexport const isNodeReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const obj = value as Record<string, unknown>;\n // Node.js Readable Stream 特征:\n // 1. 必须有 pipe 方法\n // 2. 必须有 _readableState 内部属性(Node.js Readable 特有)或 readable 属性\n // 3. 不能有 getReader 方法(排除 Web ReadableStream)\n const hasPipe = typeof obj.pipe === 'function';\n const hasNodeStreamFeatures = '_readableState' in obj || (typeof obj.readable === 'boolean');\n const isNotWebStream = typeof obj.getReader !== 'function';\n return hasPipe && hasNodeStreamFeatures && isNotWebStream;\n};\n\n/**\n * 检测是否为 Web ReadableStream\n * 通过检查 Web Streams API 特有的属性和方法来判断\n */\nexport const isWebReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n // 优先使用 instanceof 检查(如果 ReadableStream 在全局可用)\n if (typeof ReadableStream !== 'undefined' && value instanceof ReadableStream) {\n return true;\n }\n const obj = value as Record<string, unknown>;\n // Web ReadableStream 特征:\n // 1. 必须有 getReader 方法\n // 2. 必须有 locked 属性(Web ReadableStream 特有)\n return typeof obj.getReader === 'function' && 'locked' in obj;\n};","import type { FetchClient, CustomError, RequestConfig } from '../types';\nimport { HttpError } from './http-error';\nimport { isPlainObject } from '../utils/helpers';\n\nexport class CustomHttpClient {\n constructor(private readonly fetchClient: FetchClient) {}\n\n\n async request<T>(config: RequestConfig): Promise<T> {\n const headers: Record<string, string> = { ...config?.headers } as Record<string, string>;\n const body = config.body;\n if (isPlainObject(body)) {\n config.body = JSON.stringify(body);\n if (!Object.keys(headers).some((key) => key.toLowerCase() === 'content-type')) {\n headers['Content-Type'] = 'application/json';\n }\n }\n\n const res = await this.fetchClient.request({ ...config, headers });\n\n if (!res.ok) {\n throw new HttpError(res.statusText, res.status, await res.clone().text());\n }\n\n const data = await res.json(); \n \n if ((data as CustomError)?.error_msg && (data as CustomError)?.status_code) {\n throw new HttpError((data as CustomError).error_msg, (data as CustomError).status_code);\n }\n return data as T;\n }\n\n async get<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, method: 'GET', url }) as Promise<T>;\n }\n\n async post<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'POST', body: data }) as Promise<T>;\n }\n\n async put<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'PUT', body: data }) as Promise<T>;\n }\n\n async delete<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'DELETE' }) as Promise<T>;\n }\n}","import type { DownloadInnerResponse, DownloadResult } from \"../types\";\n\nexport class StreamDownloadBuilder implements PromiseLike<DownloadResult<ReadableStream>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n then<TResult1 = DownloadResult<ReadableStream>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<ReadableStream>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<ReadableStream>> {\n const result = await this.downloadFn();\n const { content, metadata } = result;\n\n if (!content.body) {\n throw new Error('Response body is null, cannot create stream');\n }\n\n return {\n content: content.body,\n metadata,\n }\n }\n}","import type { DownloadResult, DownloadInnerResponse } from \"../types\";\nimport { StreamDownloadBuilder } from \"./StreamDownloadBuilder\";\nimport { FILE_SIZE_LIMIT } from \"../const\";\n\nexport class FileDownloadBuilder implements PromiseLike<DownloadResult<Blob>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n asStream(): StreamDownloadBuilder {\n return new StreamDownloadBuilder(this.downloadFn);\n }\n\n then<TResult1 = DownloadResult<Blob>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<Blob>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<Blob>> {\n const result = await this.downloadFn();\n const { contentLength } = result.metadata?.metadata || {};\n if (contentLength && Number(contentLength) > FILE_SIZE_LIMIT) {\n throw new Error('Can\\'t download file blob larger than 50MB, use asStream() instead.');\n }\n const { content, metadata } = result;\n\n return {\n content: await content.blob(),\n metadata,\n }\n }\n}","import { LRUCache } from '../utils/lru-cache';\nimport type { FetchClient, SearchOptions, GetPublishedV2Response, FileBody, UploadOptions, PreUploadResponse, CallbackResponse, DownloadInnerResponse, FileMeta, ApiResponse, ListResponse, RemoveResponse, GetMetaResponse } from '../types';\nimport { CustomHttpClient } from './http-client';\nimport { HttpError } from \"./http-error\";\n\nimport { parseFilePath, toValidExpiresIn, getFileSize, sanitizeFileName, isNodeReadableStream, isWebReadableStream } from \"../utils/helpers\";\nimport { FileDownloadBuilder } from './FileDownloadBuilder';\n\nexport class FileServiceCore {\n private readonly cache = new LRUCache<string, string>(1000);\n private readonly httpClient: CustomHttpClient;\n\n constructor(\n private readonly fetchClient: FetchClient,\n ) {\n this.httpClient = new CustomHttpClient(this.fetchClient);\n }\n\n async upload(params: { appId: string; bucketId: string; fileBody: FileBody; options?: UploadOptions }) {\n const { appId, bucketId, fileBody, options } = params;\n const { contentType, upsert, contentDisposition, cacheControl, filePath, fileName: optFileName } = options ?? {};\n\n const fileSize = getFileSize(fileBody);\n const fileName = optFileName ?? (fileBody as File).name ?? \"\";\n\n const preUploadBody = {\n filePath,\n fileName,\n fileSize,\n contentType,\n upsert,\n };\n\n const preUploadRes = await this.httpClient.post<PreUploadResponse>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/preUpload`, preUploadBody);\n const { uploadURL, uploadID } = preUploadRes?.data ?? {};\n\n if (!uploadURL || !uploadID) {\n throw new Error('preUpload failed, uploadURL or uploadID is empty');\n }\n\n const tosHeaders: Record<string, string> = {};\n\n if (contentDisposition) {\n tosHeaders['content-disposition'] = contentDisposition;\n } else if (fileName) {\n tosHeaders['content-disposition'] = `attachment; filename=\"${sanitizeFileName(\n fileName\n )}\"`;\n }\n if (cacheControl || cacheControl === 0) {\n tosHeaders['cache-control'] = `max-age=${cacheControl}`;\n }\n if (contentType) {\n tosHeaders['content-type'] = contentType;\n }\n\n // 检测 Stream 类型\n const isNodeStream = isNodeReadableStream(fileBody);\n const isWebStream = isWebReadableStream(fileBody);\n const isStream = isNodeStream || isWebStream;\n\n // 转换 Node.js Stream 为 Web ReadableStream\n let bodyToUpload = fileBody;\n if (isNodeStream) {\n const stream = await import('stream');\n // Readable.toWeb 将 Node.js Stream 转换为 Web ReadableStream\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bodyToUpload = stream.Readable.toWeb(fileBody as any) as ReadableStream<Uint8Array>;\n }\n\n const tosRes = await fetch(uploadURL, {\n method: 'PUT',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n body: bodyToUpload as any,\n headers: tosHeaders,\n duplex: isStream ? 'half' : undefined,\n } as RequestInit);\n if (!tosRes.ok) {\n throw new HttpError(`upload failed, status: ${tosRes.status}, statusText: ${tosRes.statusText}`, tosRes.status);\n }\n const eTag = tosRes?.headers?.get('Etag') ?? '';\n\n const callbackRes = await this.httpClient.post<ApiResponse<CallbackResponse>>(`/api/v1/storage/inner/app/${appId}/object/callback`, { eTag, uploadID });\n\n return callbackRes?.data?.metadata;\n }\n\n // 对 nestjs 封装层透出的方法\n async downloadInner(params: { appId: string, bucketId: string; filePath: string; }): Promise<DownloadInnerResponse> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n const fileMeta = await this.getFileMetadata({ appId, bucketId, filePath: path });\n const signedURL = await this.createSignedUrl({ appId, bucketId, filePath: path, expiresIn: 60 });\n\n const fileRes = await fetch(signedURL);\n if (!fileRes.ok) {\n throw new HttpError(`download failed, status: ${fileRes.status}, statusText: ${fileRes.statusText}`, fileRes.status);\n }\n \n return {\n content: fileRes,\n metadata: fileMeta,\n };\n }\n\n // 封装层,可以通过download() 或者 download().asStream() 直接调用\n download(params: { appId: string, bucketId: string; filePath: string; }): FileDownloadBuilder {\n const downloadFn = () => this.downloadInner(params);\n return new FileDownloadBuilder(downloadFn);\n }\n\n async createSignedUrl(params: { appId: string; bucketId: string; filePath: string; expiresIn: number }): Promise<string> {\n const { appId, bucketId, filePath, expiresIn } = params;\n const path = parseFilePath(filePath);\n\n const res = await this.httpClient.post<ApiResponse<{ signedURL: string }>>(`/api/v1/storage/inner/app/${appId}/object/sign/${bucketId}/${encodeURIComponent(path)}`, {\n expiresIn: toValidExpiresIn(expiresIn),\n });\n\n return res?.data?.signedURL ?? '';\n }\n\n async list(params: { appId: string; bucketId: string; prefix: string; searchOptions?: SearchOptions}): Promise<ListResponse> {\n const { appId, bucketId, prefix, searchOptions } = params;\n\n const res = await this.httpClient.post<ApiResponse<ListResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/list`, {\n ...searchOptions,\n prefix,\n });\n\n return res?.data ?? { attachments: [], hasMore: false };\n }\n\n async remove(params: { appId: string; bucketId: string; filePaths: string[] }): Promise<FileMeta[]> {\n const { appId, bucketId, filePaths } = params;\n\n const res = await this.httpClient.delete<ApiResponse<RemoveResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/delete`, {\n body: {\n filePaths: filePaths.map((filePath) => parseFilePath(filePath)),\n } as any,\n });\n\n return res?.data?.attachments ?? [];\n }\n\n async getFileMetadata(params: { appId: string; bucketId: string; filePath: string }): Promise<FileMeta | null> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n try {\n const res = await this.httpClient.get<ApiResponse<GetMetaResponse>>(`/api/v1/storage/inner/app/${appId}/object/${bucketId}/head/${encodeURIComponent(path)}`);\n return res?.data?.metadata ?? null;\n } catch (error) {\n // 如果没有找到,返回null\n if (error instanceof HttpError && error.status === \"k_img_ec_000034\") {\n return null;\n }\n throw error;\n }\n }\n\n \n async getDefaultBucket(appId: string){\n const cachedBucket = this.cache.get(appId);\n if (cachedBucket) {\n return cachedBucket;\n }\n\n return this.fetchBucket(appId);\n }\n\n private async fetchBucket(appId: string): Promise<string> {\n const res = await this.httpClient.get<GetPublishedV2Response>(`/b/${appId}/get_published_v2`);\n const defaultBucketId = res?.data?.app_runtime_extra?.bucket?.default_bucket_id;\n \n if (defaultBucketId) {\n this.cache.put(appId, defaultBucketId);\n return defaultBucketId;\n } else {\n throw new HttpError(`No bucket found from remote for appId ${appId}`, 404);\n }\n }\n}","export type FileBody =\n | ArrayBuffer\n | Blob\n | Buffer\n | File\n | NodeJS.ArrayBufferView\n | NodeJS.ReadableStream\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface ApiResponse<T> {\n data: T\n}\n\nexport enum UserStatus {\n active = 1,\n inactive,\n}\n\nexport interface User {\n avatar: string;\n status: UserStatus;\n userID: number;\n email: string;\n name: string;\n userType: string;\n}\n\nexport interface FileMeta {\n id: string;\n name: string;\n filePath: string;\n metadata: {\n contentLength: string;\n mimeType: string;\n } & Record<string, string>;\n downloadURL: string;\n createdAt: string;\n createdBy: User;\n updatedAt: string;\n updatedBy: User;\n bucketID: string;\n}\n\nexport interface UploadOptions {\n filePath?: string;\n fileName?: string;\n cacheControl?: string | number;\n contentType?: string;\n upsert?: boolean;\n contentDisposition?: string;\n}\n\nexport interface SortBy {\n column?: string;\n order?: string;\n}\n\nexport interface SearchOptions {\n /**\n * The number of files you want to be returned.\n * @default 100\n */\n maxKeys?: number;\n\n /**\n * The starting file token.\n */\n continuationToken?: string;\n\n /**\n * The column to sort by. Can be any column inside a FileObject.\n */\n sortBy?: SortBy;\n}\n\nexport interface FetchClient {\n request(config: RequestInit): Promise<Response>;\n}\n\nexport interface RequestConfig extends RequestInit {\n url?: string;\n params?: Record<string, unknown>;\n timeout?: number;\n baseURL?: string;\n}\n\nexport interface CustomError {\n error_msg: string;\n status_code: string;\n lang_id: string;\n}\n\nexport interface DownloadResult<T> {\n content: T;\n metadata: FileMeta | null;\n}\n\nexport interface PreUploadResponse {\n data?: {\n uploadURL: string;\n uploadID: string;\n }\n}\n\nexport interface CallbackResponse {\n metadata: FileMeta\n}\n\nexport interface GetPublishedV2Response {\n data?: {\n app_info: {\n app_avatar: string;\n app_description: string;\n app_name: string;\n };\n app_runtime_extra: {\n bucket: {\n default_bucket_id: string;\n };\n url: string;\n };\n };\n}\n\nexport interface DownloadInnerResponse {\n content: Response;\n metadata: FileMeta | null;\n}\n\nexport interface ListResponse {\n attachments: FileMeta[],\n hasMore: boolean,\n}\n\nexport interface RemoveResponse {\n attachments: FileMeta[],\n}\n\nexport interface GetMetaResponse {\n metadata: FileMeta,\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/lru-cache.ts","../src/core/http-error.ts","../src/const.ts","../src/utils/helpers.ts","../src/core/http-client.ts","../src/core/StreamDownloadBuilder.ts","../src/core/FileDownloadBuilder.ts","../src/core/file-service.ts","../src/types.ts"],"names":["LRUCache","capacity","cache","Error","Map","get","key","has","undefined","value","delete","set","put","size","firstKey","keys","next","clear","HttpError","status","body","message","name","THIRTY_DAYS_IN_SECONDS","FILE_SIZE_LIMIT","isValidDownloadUrl","url","test","maybeRetrieveFilePathFromDownloadUrl","path","objectPath","objectIndex","indexOf","afterObject","slice","length","bucketEndIndex","result","decodeURIComponent","parseFilePath","filePath","replace","toValidExpiresIn","expiresIn","isPlainObject","proto","Object","getPrototypeOf","prototype","getFileSize","fileBody","Buffer","byteLength","isBuffer","ArrayBuffer","isView","Blob","sanitizeFileName","fileName","illegalChars","encodeURIComponent","isNodeReadableStream","obj","hasPipe","pipe","hasNodeStreamFeatures","readable","isNotWebStream","getReader","isWebReadableStream","ReadableStream","CustomHttpClient","fetchClient","request","config","headers","JSON","stringify","some","toLowerCase","res","ok","statusText","clone","text","data","json","error_msg","status_code","method","post","StreamDownloadBuilder","downloadFn","then","onfulfilled","onrejected","execute","content","metadata","FileDownloadBuilder","asStream","contentLength","Number","blob","FileServiceCore","httpClient","upload","params","appId","bucketId","options","contentType","upsert","contentDisposition","cacheControl","optFileName","fileSize","preUploadBody","preUploadRes","uploadURL","uploadID","tosHeaders","isNodeStream","isWebStream","isStream","bodyToUpload","stream","Readable","toWeb","tosRes","fetch","duplex","eTag","callbackRes","downloadInner","fileMeta","getFileMetadata","signedURL","createSignedUrl","fileRes","download","list","prefix","searchOptions","attachments","hasMore","remove","filePaths","map","error","getDefaultBucket","cachedBucket","fetchBucket","defaultBucketId","app_runtime_extra","bucket","default_bucket_id","UserStatus"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 一个简单的 LRU (最近最少使用) 缓存实现。\n * 利用 JavaScript Map 维护插入顺序的特性。\n */\nexport class LRUCache<K, V> {\n private capacity: number;\n private cache: Map<K, V>;\n\n constructor(capacity: number) {\n if (capacity <= 0) {\n throw new Error('Capacity must be greater than 0');\n }\n this.capacity = capacity;\n this.cache = new Map<K, V>();\n }\n\n /**\n * 获取缓存值,如果存在则将其移动到最近使用的位置。\n */\n get(key: K): V | undefined {\n if (!this.cache.has(key)) {\n return undefined;\n }\n\n // 将访问的键移到末尾(表示最近使用)\n const value = this.cache.get(key)!;\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n /**\n * 存入缓存值。如果超过容量,则删除最久未使用的项。\n */\n put(key: K, value: V): void {\n if (this.cache.has(key)) {\n // 如果已存在,先删除,后面重新 set 会移到末尾\n this.cache.delete(key);\n } else if (this.cache.size >= this.capacity) {\n // 达到容量上限,删除第一个(最久未使用)\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * 检查是否包含某个键。不影响使用顺序。\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * 删除指定键。\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * 清空缓存。\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * 获取当前缓存大小。\n */\n get size(): number {\n return this.cache.size;\n }\n}\n","export class HttpError extends Error {\n status: number | string;\n body?: string;\n\n constructor(message: string, status: string | number, body?: string) {\n super(message);\n this.name = \"HttpError\";\n this.status = status;\n this.body = body;\n }\n}","export const THIRTY_DAYS_IN_SECONDS = 2592000;\nexport const FILE_SIZE_LIMIT = 50 * 1024 * 1024; // 50 MB","import { THIRTY_DAYS_IN_SECONDS } from '../const';\nimport { type FileBody } from \"../types\";\n\nconst isValidDownloadUrl = (url: string) => {\n return /^(\\/spark)?\\/app\\/app_[\\w]+\\/runtime\\/api\\/v1\\/storage\\/object\\//.test(url);\n}\n\nconst maybeRetrieveFilePathFromDownloadUrl = (path: string) => {\n if (!isValidDownloadUrl(path)) {\n return path;\n }\n\n const objectPath = '/object/';\n const objectIndex = path.indexOf(objectPath);\n if (objectIndex === -1) {\n return '';\n }\n\n const afterObject = path.slice(objectIndex + objectPath.length);\n const bucketEndIndex = afterObject.indexOf('/');\n\n if (bucketEndIndex !== -1) {\n const result = afterObject.slice(bucketEndIndex + 1);\n return decodeURIComponent(result);\n }\n\n return '';\n}\n\nexport const parseFilePath = (filePath: string) => {\n const path = maybeRetrieveFilePathFromDownloadUrl(filePath);\n return path.replace(/^\\/+/, '');\n}\n\nexport const toValidExpiresIn = (expiresIn: number) => {\n if (expiresIn < 1) {\n return 1;\n }\n if (expiresIn > THIRTY_DAYS_IN_SECONDS) {\n return THIRTY_DAYS_IN_SECONDS;\n }\n return expiresIn;\n};\n\nexport const isPlainObject = (value: any): boolean => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nexport const getFileSize = (fileBody: FileBody): number | undefined => {\n if (typeof fileBody === 'string') {\n return Buffer.byteLength(fileBody);\n }\n if (Buffer.isBuffer(fileBody)) {\n return fileBody.length;\n }\n if (fileBody instanceof ArrayBuffer) {\n return fileBody.byteLength;\n }\n if (ArrayBuffer.isView(fileBody)) {\n return fileBody.byteLength;\n }\n if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {\n return fileBody.size;\n }\n return undefined;\n}\n\nexport const sanitizeFileName = (fileName: string) => {\n const illegalChars = /[:\"\\\\/*?<>|,;]/g;\n return encodeURIComponent(fileName.replace(illegalChars, '')) || 'download_file';\n};\n\n/**\n * 检测是否为 Node.js Readable Stream\n * 通过检查 Node.js Stream 特有的属性和方法来判断\n */\nexport const isNodeReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const obj = value as Record<string, unknown>;\n // Node.js Readable Stream 特征:\n // 1. 必须有 pipe 方法\n // 2. 必须有 _readableState 内部属性(Node.js Readable 特有)或 readable 属性\n // 3. 不能有 getReader 方法(排除 Web ReadableStream)\n const hasPipe = typeof obj.pipe === 'function';\n const hasNodeStreamFeatures = '_readableState' in obj || (typeof obj.readable === 'boolean');\n const isNotWebStream = typeof obj.getReader !== 'function';\n return hasPipe && hasNodeStreamFeatures && isNotWebStream;\n};\n\n/**\n * 检测是否为 Web ReadableStream\n * 通过检查 Web Streams API 特有的属性和方法来判断\n */\nexport const isWebReadableStream = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n // 优先使用 instanceof 检查(如果 ReadableStream 在全局可用)\n if (typeof ReadableStream !== 'undefined' && value instanceof ReadableStream) {\n return true;\n }\n const obj = value as Record<string, unknown>;\n // Web ReadableStream 特征:\n // 1. 必须有 getReader 方法\n // 2. 必须有 locked 属性(Web ReadableStream 特有)\n return typeof obj.getReader === 'function' && 'locked' in obj;\n};","import type { FetchClient, CustomError, RequestConfig } from '../types';\nimport { HttpError } from './http-error';\nimport { isPlainObject } from '../utils/helpers';\n\nexport class CustomHttpClient {\n constructor(private readonly fetchClient: FetchClient) {}\n\n\n async request<T>(config: RequestConfig): Promise<T> {\n const headers: Record<string, string> = { ...config?.headers } as Record<string, string>;\n const body = config.body;\n if (isPlainObject(body)) {\n config.body = JSON.stringify(body);\n if (!Object.keys(headers).some((key) => key.toLowerCase() === 'content-type')) {\n headers['Content-Type'] = 'application/json';\n }\n }\n\n const res = await this.fetchClient.request({ ...config, headers });\n\n if (!res.ok) {\n throw new HttpError(res.statusText, res.status, await res.clone().text());\n }\n\n const data = await res.json(); \n \n if ((data as CustomError)?.error_msg && (data as CustomError)?.status_code) {\n throw new HttpError((data as CustomError).error_msg, (data as CustomError).status_code);\n }\n return data as T;\n }\n\n async get<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, method: 'GET', url }) as Promise<T>;\n }\n\n async post<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'POST', body: data }) as Promise<T>;\n }\n\n async put<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'PUT', body: data }) as Promise<T>;\n }\n\n async delete<T>(url: string, config?: RequestConfig): Promise<T> {\n return this.request({ ...config, url, method: 'DELETE' }) as Promise<T>;\n }\n}","import type { DownloadInnerResponse, DownloadResult } from \"../types\";\n\nexport class StreamDownloadBuilder implements PromiseLike<DownloadResult<ReadableStream>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n then<TResult1 = DownloadResult<ReadableStream>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<ReadableStream>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<ReadableStream>> {\n const result = await this.downloadFn();\n const { content, metadata } = result;\n\n if (!content.body) {\n throw new Error('Response body is null, cannot create stream');\n }\n\n return {\n content: content.body,\n metadata,\n }\n }\n}","import type { DownloadResult, DownloadInnerResponse } from \"../types\";\nimport { StreamDownloadBuilder } from \"./StreamDownloadBuilder\";\nimport { FILE_SIZE_LIMIT } from \"../const\";\n\nexport class FileDownloadBuilder implements PromiseLike<DownloadResult<Blob>> {\n constructor(private readonly downloadFn: () => Promise<DownloadInnerResponse>) {}\n\n asStream(): StreamDownloadBuilder {\n return new StreamDownloadBuilder(this.downloadFn);\n }\n\n then<TResult1 = DownloadResult<Blob>, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult<Blob>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n\n private async execute(): Promise<DownloadResult<Blob>> {\n const result = await this.downloadFn();\n const { contentLength } = result.metadata?.metadata || {};\n if (contentLength && Number(contentLength) > FILE_SIZE_LIMIT) {\n throw new Error('Can\\'t download file blob larger than 50MB, use asStream() instead.');\n }\n const { content, metadata } = result;\n\n return {\n content: await content.blob(),\n metadata,\n }\n }\n}","import { LRUCache } from '../utils/lru-cache';\nimport type { FetchClient, SearchOptions, GetPublishedV2Response, FileBody, UploadOptions, PreUploadResponse, CallbackResponse, DownloadInnerResponse, FileMeta, ApiResponse, ListResponse, RemoveResponse, GetMetaResponse } from '../types';\nimport { CustomHttpClient } from './http-client';\nimport { HttpError } from \"./http-error\";\n\nimport { parseFilePath, toValidExpiresIn, getFileSize, sanitizeFileName, isNodeReadableStream, isWebReadableStream } from \"../utils/helpers\";\nimport { FileDownloadBuilder } from './FileDownloadBuilder';\n\nexport class FileServiceCore {\n private readonly cache = new LRUCache<string, string>(1000);\n private readonly httpClient: CustomHttpClient;\n\n constructor(\n private readonly fetchClient: FetchClient,\n ) {\n this.httpClient = new CustomHttpClient(this.fetchClient);\n }\n\n async upload(params: { appId: string; bucketId: string; fileBody: FileBody; options?: UploadOptions }) {\n const { appId, bucketId, fileBody, options } = params;\n const { contentType, upsert, contentDisposition, cacheControl, filePath, fileName: optFileName } = options ?? {};\n\n const fileSize = getFileSize(fileBody);\n const fileName = optFileName ?? (fileBody as File).name ?? \"\";\n\n const preUploadBody = {\n filePath,\n fileName,\n fileSize,\n contentType,\n upsert,\n };\n\n const preUploadRes = await this.httpClient.post<PreUploadResponse>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/preUpload`, preUploadBody);\n const { uploadURL, uploadID } = preUploadRes?.data ?? {};\n\n if (!uploadURL || !uploadID) {\n throw new Error('preUpload failed, uploadURL or uploadID is empty');\n }\n\n const tosHeaders: Record<string, string> = {};\n\n if (contentDisposition) {\n tosHeaders['content-disposition'] = contentDisposition;\n } else if (fileName) {\n tosHeaders['content-disposition'] = `attachment; filename=\"${sanitizeFileName(\n fileName\n )}\"`;\n }\n if (cacheControl || cacheControl === 0) {\n tosHeaders['cache-control'] = `max-age=${cacheControl}`;\n }\n if (contentType) {\n tosHeaders['content-type'] = contentType;\n }\n\n // 检测 Stream 类型\n const isNodeStream = isNodeReadableStream(fileBody);\n const isWebStream = isWebReadableStream(fileBody);\n const isStream = isNodeStream || isWebStream;\n\n // 转换 Node.js Stream 为 Web ReadableStream\n let bodyToUpload = fileBody;\n if (isNodeStream) {\n const stream = await import('stream');\n // Readable.toWeb 将 Node.js Stream 转换为 Web ReadableStream\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bodyToUpload = stream.Readable.toWeb(fileBody as any) as unknown as ReadableStream<Uint8Array>;\n }\n\n const tosRes = await fetch(uploadURL, {\n method: 'PUT',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n body: bodyToUpload as any,\n headers: tosHeaders,\n duplex: isStream ? 'half' : undefined,\n } as RequestInit);\n if (!tosRes.ok) {\n throw new HttpError(`upload failed, status: ${tosRes.status}, statusText: ${tosRes.statusText}`, tosRes.status);\n }\n const eTag = tosRes?.headers?.get('Etag') ?? '';\n\n const callbackRes = await this.httpClient.post<ApiResponse<CallbackResponse>>(`/api/v1/storage/inner/app/${appId}/object/callback`, { eTag, uploadID });\n\n return callbackRes?.data?.metadata;\n }\n\n // 对 nestjs 封装层透出的方法\n async downloadInner(params: { appId: string, bucketId: string; filePath: string; }): Promise<DownloadInnerResponse> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n const fileMeta = await this.getFileMetadata({ appId, bucketId, filePath: path });\n const signedURL = await this.createSignedUrl({ appId, bucketId, filePath: path, expiresIn: 60 });\n\n const fileRes = await fetch(signedURL);\n if (!fileRes.ok) {\n throw new HttpError(`download failed, status: ${fileRes.status}, statusText: ${fileRes.statusText}`, fileRes.status);\n }\n \n return {\n content: fileRes,\n metadata: fileMeta,\n };\n }\n\n // 封装层,可以通过download() 或者 download().asStream() 直接调用\n download(params: { appId: string, bucketId: string; filePath: string; }): FileDownloadBuilder {\n const downloadFn = () => this.downloadInner(params);\n return new FileDownloadBuilder(downloadFn);\n }\n\n async createSignedUrl(params: { appId: string; bucketId: string; filePath: string; expiresIn: number }): Promise<string> {\n const { appId, bucketId, filePath, expiresIn } = params;\n const path = parseFilePath(filePath);\n\n const res = await this.httpClient.post<ApiResponse<{ signedURL: string }>>(`/api/v1/storage/inner/app/${appId}/object/sign/${bucketId}/${encodeURIComponent(path)}`, {\n expiresIn: toValidExpiresIn(expiresIn),\n });\n\n return res?.data?.signedURL ?? '';\n }\n\n async list(params: { appId: string; bucketId: string; prefix: string; searchOptions?: SearchOptions}): Promise<ListResponse> {\n const { appId, bucketId, prefix, searchOptions } = params;\n\n const res = await this.httpClient.post<ApiResponse<ListResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/list`, {\n ...searchOptions,\n prefix,\n });\n\n return res?.data ?? { attachments: [], hasMore: false };\n }\n\n async remove(params: { appId: string; bucketId: string; filePaths: string[] }): Promise<FileMeta[]> {\n const { appId, bucketId, filePaths } = params;\n\n const res = await this.httpClient.delete<ApiResponse<RemoveResponse>>(`/api/v1/storage/inner/app/${appId}/bucket/${bucketId}/delete`, {\n body: {\n filePaths: filePaths.map((filePath) => parseFilePath(filePath)),\n } as any,\n });\n\n return res?.data?.attachments ?? [];\n }\n\n async getFileMetadata(params: { appId: string; bucketId: string; filePath: string }): Promise<FileMeta | null> {\n const { appId, bucketId, filePath } = params;\n const path = parseFilePath(filePath);\n\n try {\n const res = await this.httpClient.get<ApiResponse<GetMetaResponse>>(`/api/v1/storage/inner/app/${appId}/object/${bucketId}/head/${encodeURIComponent(path)}`);\n return res?.data?.metadata ?? null;\n } catch (error) {\n // 如果没有找到,返回null\n if (error instanceof HttpError && error.status === \"k_img_ec_000034\") {\n return null;\n }\n throw error;\n }\n }\n\n \n async getDefaultBucket(appId: string){\n const cachedBucket = this.cache.get(appId);\n if (cachedBucket) {\n return cachedBucket;\n }\n\n return this.fetchBucket(appId);\n }\n\n private async fetchBucket(appId: string): Promise<string> {\n const res = await this.httpClient.get<GetPublishedV2Response>(`/b/${appId}/get_published_v2`);\n const defaultBucketId = res?.data?.app_runtime_extra?.bucket?.default_bucket_id;\n \n if (defaultBucketId) {\n this.cache.put(appId, defaultBucketId);\n return defaultBucketId;\n } else {\n throw new HttpError(`No bucket found from remote for appId ${appId}`, 404);\n }\n }\n}\n","export type FileBody =\n | ArrayBuffer\n | Blob\n | Buffer\n | File\n | NodeJS.ArrayBufferView\n | NodeJS.ReadableStream\n | ReadableStream<Uint8Array>\n | string;\n\nexport interface ApiResponse<T> {\n data: T\n}\n\nexport enum UserStatus {\n active = 1,\n inactive,\n}\n\nexport interface User {\n avatar: string;\n status: UserStatus;\n userID: number;\n email: string;\n name: string;\n userType: string;\n}\n\nexport interface FileMeta {\n id: string;\n name: string;\n filePath: string;\n metadata: {\n contentLength: string;\n mimeType: string;\n } & Record<string, string>;\n downloadURL: string;\n createdAt: string;\n createdBy: User;\n updatedAt: string;\n updatedBy: User;\n bucketID: string;\n}\n\nexport interface UploadOptions {\n filePath?: string;\n fileName?: string;\n cacheControl?: string | number;\n contentType?: string;\n upsert?: boolean;\n contentDisposition?: string;\n}\n\nexport interface SortBy {\n column?: string;\n order?: string;\n}\n\nexport interface SearchOptions {\n /**\n * The number of files you want to be returned.\n * @default 100\n */\n maxKeys?: number;\n\n /**\n * The starting file token.\n */\n continuationToken?: string;\n\n /**\n * The column to sort by. Can be any column inside a FileObject.\n */\n sortBy?: SortBy;\n}\n\nexport interface FetchClient {\n request(config: RequestInit): Promise<Response>;\n}\n\nexport interface RequestConfig extends RequestInit {\n url?: string;\n params?: Record<string, unknown>;\n timeout?: number;\n baseURL?: string;\n}\n\nexport interface CustomError {\n error_msg: string;\n status_code: string;\n lang_id: string;\n}\n\nexport interface DownloadResult<T> {\n content: T;\n metadata: FileMeta | null;\n}\n\nexport interface PreUploadResponse {\n data?: {\n uploadURL: string;\n uploadID: string;\n }\n}\n\nexport interface CallbackResponse {\n metadata: FileMeta\n}\n\nexport interface GetPublishedV2Response {\n data?: {\n app_info: {\n app_avatar: string;\n app_description: string;\n app_name: string;\n };\n app_runtime_extra: {\n bucket: {\n default_bucket_id: string;\n };\n url: string;\n };\n };\n}\n\nexport interface DownloadInnerResponse {\n content: Response;\n metadata: FileMeta | null;\n}\n\nexport interface ListResponse {\n attachments: FileMeta[],\n hasMore: boolean,\n}\n\nexport interface RemoveResponse {\n attachments: FileMeta[],\n}\n\nexport interface GetMetaResponse {\n metadata: FileMeta,\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/file-service",
3
- "version": "0.1.1",
3
+ "version": "0.1.2-alpha.1",
4
4
  "description": "File Service Core Package",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",