uploadthing
Version:
Learn more: [docs.uploadthing.com](https://docs.uploadthing.com)
431 lines (425 loc) • 15.2 kB
TypeScript
import * as LogLevel from 'effect/LogLevel';
import { FetchEsque, MaybeUrl, Either, SerializedUploadThingError, Time, ErrorMessage, MaybePromise, ExtendObjectIf } from '@uploadthing/shared';
export { EndpointMetadata, ExpandedRouteConfig } from '@uploadthing/shared';
import * as Config from 'effect/Config';
import { AnyFileRoute } from '../internal/types.js';
export { AnyFileRoute, FileRoute } from '../internal/types.js';
import { Blob as Blob$1 } from 'buffer';
import * as effect_Redacted from 'effect/Redacted';
import * as S from 'effect/Schema';
declare const LogFormat: Config.Config<"json" | "logFmt" | "structured" | "pretty">;
type LogFormat = Config.Config.Success<typeof LogFormat>;
interface UTApiOptions {
/**
* Provide a custom fetch function.
* @default globalThis.fetch
*/
fetch?: FetchEsque;
/**
* Provide a custom UploadThing token
* @default process.env.UPLOADTHING_TOKEN
*/
token?: string;
/**
* @default "info"
*/
logLevel?: LogLevel.Literal;
/**
* What format log entries should be in
* @default "pretty" in development, else "json"
* @see https://effect.website/docs/guides/observability/logging#built-in-loggers
*/
logFormat?: Config.Config.Success<typeof LogFormat>;
/**
* Set the default key type for file operations. Allows you to set your preferred filter
* for file keys or custom identifiers without needing to specify it on every call.
* @default "fileKey"
*/
defaultKeyType?: "fileKey" | "customId";
/**
* URL override for the API server
*/
apiUrl?: string;
/**
* URL override for the ingest server
*/
ingestUrl?: string;
}
type UrlWithOverrides = {
url: MaybeUrl;
name?: string;
customId?: string;
};
type BlobEsque = Blob$1 | Blob;
type FileEsque = BlobEsque & {
name: string;
lastModified?: number;
customId?: string | null | undefined;
};
type UploadFileResult = Either<UploadedFileData, SerializedUploadThingError>;
interface KeyTypeOptionsBase {
/**
* Whether the provided key is a fileKey or a custom identifier. fileKey is the
* identifier you get from UploadThing after uploading a file, customId is a
* custom identifier you provided when uploading a file.
* @default fileKey
*/
keyType?: "fileKey" | "customId";
}
interface DeleteFilesOptions extends KeyTypeOptionsBase {
}
interface GetFileUrlsOptions extends KeyTypeOptionsBase {
}
interface ListFilesOptions {
limit?: number;
offset?: number;
}
type KeyRename = {
fileKey: string;
newName: string;
};
type CustomIdRename = {
customId: string;
newName: string;
};
type RenameFileUpdate = KeyRename | CustomIdRename;
interface GetSignedURLOptions extends KeyTypeOptionsBase {
/**
* How long the URL will be valid for.
* - Must be positive and less than 7 days (604800 seconds).
* - You must accept overrides on the UploadThing dashboard for this option to be accepted.
* @default app default on UploadThing dashboard
*/
expiresIn?: Time;
}
interface ACLUpdateOptions extends KeyTypeOptionsBase {
}
declare const UploadThingToken: S.SchemaClass<{
readonly apiKey: effect_Redacted.Redacted<string>;
readonly appId: string;
readonly regions: readonly [string, ...string[]];
readonly ingestHost: string;
}, string, never>;
declare const FileUploadData_base: S.Class<FileUploadData, {
name: typeof S.String;
size: typeof S.Number;
type: typeof S.String;
lastModified: S.optional<typeof S.Number>;
}, S.Struct.Encoded<{
name: typeof S.String;
size: typeof S.Number;
type: typeof S.String;
lastModified: S.optional<typeof S.Number>;
}>, never, {
readonly name: string;
} & {
readonly size: number;
} & {
readonly type: string;
} & {
readonly lastModified?: number | undefined;
}, {}, {}>;
/**
* =============================================================================
* ======================== File Type Hierarchy ===============================
* =============================================================================
*/
/**
* Properties from the web File object, this is what the client sends when initiating an upload
*/
declare class FileUploadData extends FileUploadData_base {
}
declare const FileUploadDataWithCustomId_base: S.Class<FileUploadDataWithCustomId, {
name: typeof S.String;
size: typeof S.Number;
type: typeof S.String;
lastModified: S.optional<typeof S.Number>;
} & {
customId: S.NullOr<typeof S.String>;
}, {
readonly name: string;
readonly size: number;
readonly type: string;
} & {
readonly lastModified?: number | undefined;
} & {
readonly customId: string | null;
} & {}, never, {
readonly name: string;
} & {
readonly size: number;
} & {
readonly type: string;
} & {
readonly lastModified?: number | undefined;
} & {
readonly customId: string | null;
}, FileUploadData, {}>;
/**
* `.middleware()` can add a customId to the incoming file data
*/
declare class FileUploadDataWithCustomId extends FileUploadDataWithCustomId_base {
}
declare const UploadedFileData_base: S.Class<UploadedFileData, {
name: typeof S.String;
size: typeof S.Number;
type: typeof S.String;
lastModified: S.optional<typeof S.Number>;
} & {
customId: S.NullOr<typeof S.String>;
} & {
key: typeof S.String;
url: typeof S.String;
appUrl: typeof S.String;
fileHash: typeof S.String;
}, {
readonly name: string;
readonly size: number;
readonly type: string;
} & {
readonly lastModified?: number | undefined;
} & {
readonly customId: string | null;
} & {} & {
readonly key: string;
readonly url: string;
readonly appUrl: string;
readonly fileHash: string;
} & {}, never, {
readonly name: string;
} & {
readonly size: number;
} & {
readonly type: string;
} & {
readonly lastModified?: number | undefined;
} & {
readonly customId: string | null;
} & {
readonly key: string;
} & {
readonly url: string;
} & {
readonly appUrl: string;
} & {
readonly fileHash: string;
}, FileUploadDataWithCustomId, {}>;
/**
* When files are uploaded, we get back
* - a key
* - a direct URL for the file
* - an app-specific URL for the file (useful for scoping eg. for optimization allowed origins)
* - the hash (md5-hex) of the uploaded file's contents
*/
declare class UploadedFileData extends UploadedFileData_base {
}
/**
* When the client has uploaded a file and polled for data returned by `.onUploadComplete()`
*/
interface ClientUploadedFileData<T> extends UploadedFileData {
/**
* Matches what's returned from the serverside `onUploadComplete` callback
*/
readonly serverData: T;
}
declare const NewPresignedUrl_base: S.Class<NewPresignedUrl, {
url: typeof S.String;
key: typeof S.String;
customId: S.NullOr<typeof S.String>;
name: typeof S.String;
}, S.Struct.Encoded<{
url: typeof S.String;
key: typeof S.String;
customId: S.NullOr<typeof S.String>;
name: typeof S.String;
}>, never, {
readonly name: string;
} & {
readonly customId: string | null;
} & {
readonly key: string;
} & {
readonly url: string;
}, {}, {}>;
/**
* =============================================================================
* ======================== Server Response Schemas ============================
* =============================================================================
*/
declare class NewPresignedUrl extends NewPresignedUrl_base {
}
type FileRouter = Record<string, AnyFileRoute>;
type inferEndpointInput<TFileRoute extends AnyFileRoute> = TFileRoute["$types"]["input"];
type inferEndpointOutput<TFileRoute extends AnyFileRoute> = TFileRoute["$types"]["output"];
type inferErrorShape<TFileRoute extends AnyFileRoute> = TFileRoute["$types"]["errorShape"];
type RouteHandlerConfig = {
logLevel?: LogLevel.Literal;
/**
* What format log entries should be in
* @default "pretty" in development, else "json"
* @see https://effect.website/docs/guides/observability/logging#built-in-loggers
*/
logFormat?: LogFormat;
/**
* The full, absolute URL to where your route handler is hosted. UploadThing
* attempts to automatically detect this value based on the request URL and
* headers. You can override this if the automatic detection fails.
* @example URL { https://www.example.com/api/uploadthing }
*/
callbackUrl?: string;
token?: string;
/**
* Used to determine whether to run dev hook or not
* @default `env.NODE_ENV === "development" || env.NODE_ENV === "dev"`
*/
isDev?: boolean;
/**
* Used to override the fetch implementation
* @default `globalThis.fetch`
*/
fetch?: FetchEsque;
/**
* Set how UploadThing should handle the daemon promise before returning a response to the client.
* You can also provide a synchronous function that will be called before returning a response to
* the client. This can be useful for things like:
* - [`@vercel/functions.waitUntil`](https://vercel.com/docs/functions/functions-api-reference#waituntil)
* - [`next/after`](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental)
* - or equivalent function from your serverless infrastructure provider that allows asynchronous streaming
* If deployed on a stateful server, you most likely want "void" to run the daemon in the background.
* @remarks - `"await"` is not allowed in development environments
* @default isDev === true ? "void" : "await"
*/
handleDaemonPromise?: "void" | "await" | ((promise: Promise<unknown>) => void);
/**
* URL override for the ingest server
*/
ingestUrl?: string;
};
type RouteHandlerOptions<TRouter extends FileRouter> = {
router: TRouter;
config?: RouteHandlerConfig;
};
type UploadFilesOptions<TFileRoute extends AnyFileRoute> = {
/**
* The files to upload
*/
files: File[];
/**
* An AbortSignal to cancel the upload
* Calling `abort()` on the parent AbortController will
* cause this function to throw an `UploadAbortedError`
*/
signal?: AbortSignal | undefined;
/**
* Called when presigned URLs have been retrieved and the file upload is about to begin
*/
onUploadBegin?: ((opts: {
file: string;
}) => void) | undefined;
/**
* Called continuously as the file is uploaded to the storage provider
*/
onUploadProgress?: ((opts: {
/** The file that triggered the progress event */
file: File;
/** Percentage of the file that has been uploaded */
progress: number;
/** Total bytes of the file that has been uploaded */
loaded: number;
/** How many bytes have been uploaded since the last progress event for this file */
delta: number;
/** Total bytes uploaded for all files in this upload */
totalLoaded: number;
/** Percentage of the total loaded bytes for the upload */
totalProgress: number;
}) => void) | undefined;
/**
* This option has been moved to your serverside route config.
* Please opt-in by setting `awaitServerData: false` in your route
* config instead.
* ### Example
* ```ts
* f(
* { image: { maxFileSize: "1MB" } },
* { awaitServerData: false }
* ).middleware(...)
* ```
* @deprecated
* @see https://docs.uploadthing.com/api-reference/server#route-options
*/
skipPolling?: ErrorMessage<"This option has been moved to your serverside route config. Please use `awaitServerData` in your route config instead.">;
/**
* URL to the UploadThing API endpoint
* @example URL { http://localhost:3000/api/uploadthing }
* @example URL { https://www.example.com/api/uploadthing }
* @remarks This option is not required when `uploadFiles` has been generated with `genUploader`
*/
url: URL;
/**
* Set custom headers that'll get sent with requests
* to your server
*/
headers?: HeadersInit | (() => MaybePromise<HeadersInit>) | undefined;
/**
* The uploadthing package that is making this request, used to identify the client in the server logs
* @example "@uploadthing/react"
* @remarks This option is not required when `uploadFiles` has been generated with `genUploader`
*/
package: string;
} & ExtendObjectIf<inferEndpointInput<TFileRoute>, {
input: inferEndpointInput<TFileRoute>;
}>;
type CreateUploadOptions<TFileRoute extends AnyFileRoute> = {
/**
* The files to upload
*/
files: File[];
/**
* Called continuously as the file is uploaded to the storage provider
*/
onUploadProgress?: ((opts: {
/** The file that triggered the progress event */
file: File;
/** Percentage of the file that has been uploaded */
progress: number;
/** Total bytes of the file that has been uploaded */
loaded: number;
/** How many bytes have been uploaded since the last progress event for this file */
delta: number;
/** Total bytes uploaded for all files in this upload */
totalLoaded: number;
/** Percentage of the total loaded bytes for the upload */
totalProgress: number;
}) => void) | undefined;
/**
* Set custom headers that'll get sent with requests
* to your server
*/
headers?: HeadersInit | (() => MaybePromise<HeadersInit>) | undefined;
} & ExtendObjectIf<inferEndpointInput<TFileRoute>, {
input: inferEndpointInput<TFileRoute>;
}>;
type GenerateUploaderOptions = {
/**
* URL to the UploadThing API endpoint
* @example /api/uploadthing
* @example URL { https://www.example.com/api/uploadthing }
*
* If relative, host will be inferred from either the `VERCEL_URL` environment variable or `window.location.origin`
*
* @default (VERCEL_URL ?? window.location.origin) + "/api/uploadthing"
*/
url?: string | URL;
/**
* The uploadthing package that is making this request
* @example "@uploadthing/react"
*
* This is used to identify the client in the server logs
*/
package: string;
};
type EndpointArg<TRouter extends FileRouter, TEndpoint extends keyof TRouter> = TEndpoint | ((_: RouteRegistry<TRouter>) => TEndpoint);
type RouteRegistry<TRouter extends FileRouter> = {
[k in keyof TRouter]: k;
};
export { type ACLUpdateOptions, type ClientUploadedFileData, type CreateUploadOptions, type DeleteFilesOptions, type EndpointArg, type FileEsque, type FileRouter, FileUploadData, FileUploadDataWithCustomId, type GenerateUploaderOptions, type GetFileUrlsOptions, type GetSignedURLOptions, type ListFilesOptions, NewPresignedUrl, type RenameFileUpdate, type RouteHandlerConfig, type RouteHandlerOptions, type RouteRegistry, type UTApiOptions, type UploadFileResult, type UploadFilesOptions, UploadThingToken, UploadedFileData, type UrlWithOverrides, type inferEndpointInput, type inferEndpointOutput, type inferErrorShape };