import type { PluginInfo, SerovalNode } from 'seroval' import type { RegisteredConfigType, RegisteredSsr, SSROption, } from '../../router' import type { LooseReturnType } from '../../utils' import type { AnyRoute, ResolveAllSSR } from '../../route' import type { RawStream } from './RawStream' declare const TSR_SERIALIZABLE: unique symbol export type TSR_SERIALIZABLE = typeof TSR_SERIALIZABLE export type TsrSerializable = { [TSR_SERIALIZABLE]: true } export interface DefaultSerializable { number: number string: string boolean: boolean null: null undefined: undefined bigint: bigint Date: Date Uint8Array: Uint8Array RawStream: RawStream TsrSerializable: TsrSerializable void: void } export interface SerializableExtensions extends DefaultSerializable {} export type Serializable = SerializableExtensions[keyof SerializableExtensions] export type UnionizeSerializationAdaptersInput< TAdapters extends ReadonlyArray, > = TAdapters[number]['~types']['input'] /** * Create a strongly-typed serialization adapter for SSR hydration. * Use to register custom types with the router serializer. */ export function createSerializationAdapter< TInput = unknown, TOutput = unknown, const TExtendsAdapters extends | ReadonlyArray | never = never, >( opts: CreateSerializationAdapterOptions, ): SerializationAdapter { if (process.env.NODE_ENV !== 'production') { // Seroval escapes most of these characters before plugin lookup. NUL and // lone surrogates are transport-unstable. Reject every surrogate code unit // to keep adapter keys and this development-only check simple. if ( !opts.key || /[\0"\\<\b\t\f\r\n\u2028\u2029\uD800-\uDFFF]/.test(opts.key) ) { throw new Error( `createSerializationAdapter: key ${JSON.stringify(opts.key)} is ` + 'invalid. Serialization adapter keys must be non-empty and not ' + 'contain NUL, ", \\, <, backspace, tab, form feed, line ' + 'terminators, or UTF-16 surrogate code units.', ) } } return opts as unknown as SerializationAdapter< TInput, TOutput, TExtendsAdapters > } export interface CreateSerializationAdapterOptions< TInput, TOutput, TExtendsAdapters extends ReadonlyArray | never, > { /** * A non-empty Seroval plugin identifier. * * Must not contain NUL, `"`, `\\`, `<`, backspace, tab, form feed, line * terminators, or UTF-16 surrogate code units. Key validation runs only in * development. */ key: string extends?: TExtendsAdapters test: (value: unknown) => value is TInput toSerializable: ( value: TInput, ) => ValidateSerializable< TOutput, Serializable | UnionizeSerializationAdaptersInput > fromSerializable: (value: TOutput) => TInput } export type ValidateSerializable = T extends TSerializable ? T : T extends (...args: Array) => any ? SerializationError<'Function may not be serializable'> : T extends RegisteredReadableStream ? SerializationError<'JSX is not be serializable'> : T extends ReadonlyArray ? ValidateSerializableArray : T extends Promise ? ValidateSerializablePromise : T extends ReadableStream ? ValidateReadableStream : T extends Set ? ValidateSerializableSet : T extends Map ? ValidateSerializableMap : T extends AsyncGenerator ? ValidateSerializableAsyncGenerator : T extends object ? ValidateSerializableMapped : SerializationError<'Type may not be serializable'> export type ValidateSerializableAsyncGenerator = T extends AsyncGenerator ? AsyncGenerator< ValidateSerializable, ValidateSerializable, TNext > : never export type ValidateSerializablePromise = T extends Promise ? Promise> : never export type ValidateReadableStream = T extends ReadableStream ? ReadableStream> : never export type ValidateSerializableSet = T extends Set ? Set> : never export type ValidateSerializableMap = T extends Map ? Map< ValidateSerializable, ValidateSerializable > : never export type ValidateSerializableArray = T extends readonly [ any, ...Array, ] ? ValidateSerializableMapped : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> : never export type ValidateSerializableMapped = { [K in keyof T]: ValidateSerializable } const SERIALIZATION_ERROR = Symbol.for('TSR_SERIALIZATION_ERROR') export interface SerializationError { [SERIALIZATION_ERROR]: TMessage } export interface SerializationAdapter< TInput, TOutput, TExtendsAdapters extends ReadonlyArray, > { '~types': SerializationAdapterTypes key: string extends?: TExtendsAdapters test: (value: unknown) => value is TInput toSerializable: (value: TInput) => TOutput fromSerializable: (value: TOutput) => TInput } export interface SerializationAdapterTypes< TInput, TOutput, TExtendsAdapters extends ReadonlyArray, > { input: TInput | UnionizeSerializationAdaptersInput output: TOutput extends: TExtendsAdapters } export type AnySerializationAdapter = SerializationAdapter export interface AdapterNode extends PluginInfo { v: SerovalNode } export type ValidateSerializableInput = ValidateSerializable< T, RegisteredSerializableInput > export type RegisteredSerializableInput = | (unknown extends RegisteredSerializationAdapters ? never : RegisteredSerializationAdapters extends ReadonlyArray ? RegisteredSerializationAdapters[number]['~types']['input'] : never) | Serializable export type RegisteredSerializationAdapters = RegisteredConfigType< TRegister, 'serializationAdapters' > export type RegisteredSSROption = unknown extends RegisteredConfigType ? SSROption : RegisteredConfigType export type ValidateSerializableLifecycleResult< TRegister, TParentRoute extends AnyRoute, TSSR, TFn, > = false extends RegisteredSsr ? any : ValidateSerializableLifecycleResultSSR< TRegister, TParentRoute, TSSR, TFn > extends infer TInput ? TInput : never export type ValidateSerializableLifecycleResultSSR< TRegister, TParentRoute extends AnyRoute, TSSR, TFn, > = ResolveAllSSR extends false ? any : RegisteredSSROption extends false ? any : ValidateSerializableInput> export type RegisteredReadableStream = unknown extends SerializerExtensions['ReadableStream'] ? never : SerializerExtensions['ReadableStream'] export interface DefaultSerializerExtensions { ReadableStream: unknown } export interface SerializerExtensions extends DefaultSerializerExtensions {}