uploadthing
Version:
Learn more: [docs.uploadthing.com](https://docs.uploadthing.com)
301 lines (296 loc) • 10.2 kB
TypeScript
import * as S from 'effect/Schema';
import { Schema } from 'effect/Schema';
import { Json, ErrorMessage, JsonObject, Simplify, FileRouterInputConfig, RouteOptions, UploadThingError, MaybePromise } from '@uploadthing/shared';
import * as Standard from '@standard-schema/spec';
type ParseFn<TType> = (input: unknown) => Promise<TType>;
type ParserZodEsque<TInput extends Json, TParsedInput> = {
_input: TInput;
_output: TParsedInput;
parseAsync: ParseFn<TParsedInput>;
};
type JsonParser<In extends Json, Out = In> = ParserZodEsque<In, Out> | Standard.v1.StandardSchema<In, Out> | S.Schema<Out, In>;
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 {
}
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 {
}
declare const UploadActionPayload_base: S.Class<UploadActionPayload, {
files: S.Array$<typeof FileUploadData>;
input: S.Schema<Json>;
}, S.Struct.Encoded<{
files: S.Array$<typeof FileUploadData>;
input: S.Schema<Json>;
}>, never, {
readonly files: readonly FileUploadData[];
} & {
readonly input: Json;
}, {}, {}>;
/**
* =============================================================================
* ======================== Client Action Payloads ============================
* =============================================================================
*/
declare class UploadActionPayload extends UploadActionPayload_base {
}
/**
* Marker used to append a `customId` to the incoming file data in `.middleware()`
* @example
* ```ts
* .middleware((opts) => {
* return {
* [UTFiles]: opts.files.map((file) => ({
* ...file,
* customId: generateId(),
* }))
* };
* })
* ```
*/
declare const UTFiles: unique symbol;
declare const unsetMarker: "unsetMarker" & {
__brand: "unsetMarker";
};
type UnsetMarker = typeof unsetMarker;
type ValidMiddlewareObject = {
[UTFiles]?: Partial<FileUploadDataWithCustomId>[];
[key: string]: unknown;
};
/**
* Different frameworks have different request and response types
*/
type AdapterFnArgs<TRequest, TResponse, TEvent> = {
req: TRequest;
res: TResponse;
event: TEvent;
};
interface AnyParams {
_routeOptions: any;
_input: {
in: any;
out: any;
};
_metadata: any;
_adapterFnArgs: AdapterFnArgs<any, any, any>;
_errorShape: any;
_errorFn: any;
_output: any;
}
type MiddlewareFn<TInput extends Json | UnsetMarker, TOutput extends ValidMiddlewareObject, TArgs extends AdapterFnArgs<any, any, any>> = (opts: TArgs & {
files: Schema.Type<typeof UploadActionPayload>["files"];
input: TInput extends UnsetMarker ? undefined : TInput;
}) => MaybePromise<TOutput>;
type UploadCompleteFn<TMetadata, TOutput extends JsonObject | void, TArgs extends AdapterFnArgs<any, any, any>> = (opts: TArgs & {
metadata: TMetadata;
file: UploadedFileData;
}) => MaybePromise<TOutput>;
type UploadErrorFn<TArgs extends AdapterFnArgs<any, any, any>> = (input: TArgs & {
error: UploadThingError;
fileKey: string;
}) => MaybePromise<void>;
interface UploadBuilder<TParams extends AnyParams> {
input: <TIn extends Json, TOut>(parser: TParams["_input"]["in"] extends UnsetMarker ? JsonParser<TIn, TOut> : ErrorMessage<"input is already set">) => UploadBuilder<{
_routeOptions: TParams["_routeOptions"];
_input: {
in: TIn;
out: TOut;
};
_metadata: TParams["_metadata"];
_adapterFnArgs: TParams["_adapterFnArgs"];
_errorShape: TParams["_errorShape"];
_errorFn: TParams["_errorFn"];
_output: UnsetMarker;
}>;
middleware: <TOutput extends ValidMiddlewareObject>(fn: TParams["_metadata"] extends UnsetMarker ? MiddlewareFn<TParams["_input"]["out"], TOutput, TParams["_adapterFnArgs"]> : ErrorMessage<"middleware is already set">) => UploadBuilder<{
_routeOptions: TParams["_routeOptions"];
_input: TParams["_input"];
_metadata: TOutput;
_adapterFnArgs: TParams["_adapterFnArgs"];
_errorShape: TParams["_errorShape"];
_errorFn: TParams["_errorFn"];
_output: UnsetMarker;
}>;
onUploadError: (fn: TParams["_errorFn"] extends UnsetMarker ? UploadErrorFn<TParams["_adapterFnArgs"]> : ErrorMessage<"onUploadError is already set">) => UploadBuilder<{
_routeOptions: TParams["_routeOptions"];
_input: TParams["_input"];
_metadata: TParams["_metadata"];
_adapterFnArgs: TParams["_adapterFnArgs"];
_errorShape: TParams["_errorShape"];
_errorFn: UploadErrorFn<TParams["_adapterFnArgs"]>;
_output: UnsetMarker;
}>;
onUploadComplete: <TOutput extends JsonObject | void>(fn: UploadCompleteFn<Simplify<TParams["_metadata"] extends UnsetMarker ? undefined : Omit<TParams["_metadata"], typeof UTFiles>>, TOutput, TParams["_adapterFnArgs"]>) => FileRoute<{
input: TParams["_input"]["in"] extends UnsetMarker ? undefined : TParams["_input"]["in"];
output: TParams["_routeOptions"]["awaitServerData"] extends false ? null : TOutput extends void | undefined ? null : TOutput;
errorShape: TParams["_errorShape"];
}>;
}
type AnyBuiltUploaderTypes = {
input: any;
output: any;
errorShape: any;
};
interface FileRoute<TTypes extends AnyBuiltUploaderTypes> {
$types: TTypes;
routerConfig: FileRouterInputConfig;
routeOptions: RouteOptions;
inputParser: JsonParser<any>;
middleware: MiddlewareFn<any, ValidMiddlewareObject, any>;
onUploadError: UploadErrorFn<any>;
errorFormatter: (err: UploadThingError) => any;
onUploadComplete: UploadCompleteFn<any, any, any>;
}
type AnyFileRoute = FileRoute<AnyBuiltUploaderTypes>;
/**
* Map actionType to the required payload for that action
* @todo Look into using @effect/rpc :thinking:
*/
type UTEvents = {
upload: {
in: UploadActionPayload;
out: ReadonlyArray<NewPresignedUrl>;
};
};
/**
* Result from the PUT request to the UploadThing Ingest server
*/
type UploadPutResult<TServerOutput = unknown> = {
url: string;
appUrl: string;
fileHash: string;
serverData: TServerOutput;
};
export { type AdapterFnArgs, type AnyBuiltUploaderTypes, type AnyFileRoute, type AnyParams, type FileRoute, type UTEvents, UTFiles, type UnsetMarker, type UploadBuilder, type UploadPutResult, type ValidMiddlewareObject };