UNPKG

@edgestore/server

Version:

Upload files with ease from React/Next.js

217 lines 7.13 kB
import { type AnyBuilder, type AnyRouter, type InferBucketPathKeys, type InferBucketPathObject, type InferMetadataObject, type Prettify, type Simplify } from '@edgestore/shared'; import { type z, type ZodNever } from 'zod'; import { type Comparison } from '..'; export type GetFileRes<TBucket extends AnyBuilder> = { url: string; size: number; uploadedAt: Date; metadata: InferMetadataObject<TBucket>; path: InferBucketPathObject<TBucket>; }; export type UploadOptions = { /** * e.g. 'my-file-name.jpg' * * By default, a unique file name will be generated for each upload. * If you want to use a custom file name, you can use this option. * If you use the same file name for multiple uploads, the previous file will be overwritten. * But it might take some time for the CDN cache to be cleared. * So maybe you will keep seeing the old file for a while. * * If you want to replace an existing file, immediately leave the `manualFileName` option empty and use the `replaceTargetUrl` option. */ manualFileName?: string; /** * Use this to replace an existing file. * It will automatically delete the existing file when the upload is complete. */ replaceTargetUrl?: string; /** * If true, the file needs to be confirmed by using the `confirmUpload` function. * If the file is not confirmed within 24 hours, it will be deleted. * * This is useful for pages where the file is uploaded as soon as it is selected, * but the user can leave the page without submitting the form. * * This avoids unnecessary zombie files in the bucket. */ temporary?: boolean; }; type TextContent = string; type BlobContent = { blob: Blob; extension: string; }; type UrlContent = { url: string; extension: string; }; export type UploadFileRequest<TBucket extends AnyBuilder> = { /** * Can be a string, a blob or an url. * * If it's a string, it will be converted to a blob with the type `text/plain`. * * @example * // string * content: "some text" * * @example * // blob * content: { * blob: new Blob([text], { type: "text/csv" }), * extension: "csv", * } * * @example * // url * content: { * url: "https://example.com/my-file.csv", * extension: "csv", * } */ content: TextContent | BlobContent | UrlContent; options?: UploadOptions; } & (TBucket['$config']['ctx'] extends Record<string, never> ? {} : { ctx: TBucket['$config']['ctx']; }) & (TBucket['_def']['input'] extends ZodNever ? {} : { input: z.infer<TBucket['_def']['input']>; }); export type UploadFileRes<TBucket extends AnyBuilder> = TBucket['_def']['type'] extends 'IMAGE' ? { url: string; thumbnailUrl: string | null; size: number; metadata: InferMetadataObject<TBucket>; path: InferBucketPathObject<TBucket>; pathOrder: (keyof InferBucketPathObject<TBucket>)[]; } : { url: string; size: number; metadata: InferMetadataObject<TBucket>; path: InferBucketPathObject<TBucket>; pathOrder: (keyof InferBucketPathObject<TBucket>)[]; }; type Filter<TBucket extends AnyBuilder> = { AND?: Filter<TBucket>[]; OR?: Filter<TBucket>[]; uploadedAt?: Comparison<Date>; path?: { [K in InferBucketPathKeys<TBucket>]?: Comparison; }; metadata?: { [K in keyof InferMetadataObject<TBucket>]?: Comparison; }; }; export type ListFilesRequest<TBucket extends AnyBuilder> = { filter?: Filter<TBucket>; pagination?: { currentPage: number; pageSize: number; }; }; export type ListFilesResponse<TBucket extends AnyBuilder> = { data: TBucket['_def']['type'] extends 'IMAGE' ? { url: string; thumbnailUrl: string | null; size: number; uploadedAt: Date; metadata: InferMetadataObject<TBucket>; path: InferBucketPathObject<TBucket>; }[] : { url: string; size: number; uploadedAt: Date; metadata: InferMetadataObject<TBucket>; path: InferBucketPathObject<TBucket>; }[]; pagination: { currentPage: number; totalPages: number; totalCount: number; }; }; type EdgeStoreClient<TRouter extends AnyRouter> = { [K in keyof TRouter['buckets']]: { getFile: (params: { url: string; }) => Promise<GetFileRes<TRouter['buckets'][K]>>; /** * Use this function to upload a file to the bucket directly from your backend. * * @example * ```ts * // simple example * await backendClient.myBucket.upload({ * content: "some text", * }); * ``` * * @example * ```ts * // complete example * await backendClient.myBucket.upload({ * content: { * blob: new Blob([text], { type: "text/csv" }), * extension: "csv", * }, * options: { * temporary: true, * replaceTargetUrl: replaceUrl, * manualFileName: "test.csv", * }, * ctx: { * userId: "123", * userRole: "admin", * }, * input: { * type: "post", * }, * }); * ``` */ upload: (params: UploadFileRequest<TRouter['buckets'][K]>) => Promise<Prettify<UploadFileRes<TRouter['buckets'][K]>>>; /** * Confirm a temporary file upload directly from your backend. */ confirmUpload: (params: { url: string; }) => Promise<{ success: boolean; }>; /** * Programmatically delete a file directly from your backend. */ deleteFile: (params: { url: string; }) => Promise<{ success: boolean; }>; /** * List files in a bucket. * * You can also filter the results by passing a filter object. * The results are paginated. */ listFiles: (params?: ListFilesRequest<TRouter['buckets'][K]>) => Promise<Prettify<ListFilesResponse<TRouter['buckets'][K]>>>; }; }; export declare function initEdgeStoreClient<TRouter extends AnyRouter>(config: { router: TRouter; accessKey?: string; secretKey?: string; /** * The base URL of your application. * * This is only needed for getting protected files in a development environment. * * @example http://localhost:3000/api/edgestore */ baseUrl?: string; }): EdgeStoreClient<TRouter>; export type InferClientResponse<TRouter extends AnyRouter> = { [TBucketName in keyof TRouter['buckets']]: { [TClienFn in keyof EdgeStoreClient<TRouter>[TBucketName]]: Simplify<Awaited<ReturnType<EdgeStoreClient<TRouter>[TBucketName][TClienFn] extends (...args: any) => any ? EdgeStoreClient<TRouter>[TBucketName][TClienFn] : never>>>; }; }; export {}; //# sourceMappingURL=index.d.ts.map