export type UrlUpdateType = "replaceIn" | "pushIn" | "replace" | "push"; type Require = Pick, Keys> & Omit export type API = { getSearch: () => string, replaceState: (params: string, state?: unknown) => void, pushState: (params: string, state?: unknown) => void, registerListener: (listener: (state?: unknown) => void) => void, } export type RenderingType = "server" | "client"; export type Serializer = { encode: (value: T) => string, decode: (value: string) => T, } export type SerializerOptions = Partial> export type Value = T | (() => T) export type ValueOptions = { defaultValue?: Value } export type UrlOptions = { updateType?: UrlUpdateType, } export type Dispatch = (value: A) => void; export type Setter = S | ((prevState: S) => S); export type PrefixOptions = { prefix?: string, } export type FinalOptions = UrlOptions & Validator & ValueOptions & PrefixOptions export type Options = SerializerOptions & FinalOptions export type OptionsWithDefault = Require, "defaultValue"> export type RequiredOptions = Require, "encode" | "decode"> type Param = { useSet: (options?: FinalOptions) => Dispatch>, use: (options?: FinalOptions) => [T, Dispatch>], } type TransformedParam = { useSet: (options?: FinalOptions) => SetRes, use: (options?: FinalOptions) => [T, SetRes], } export type Validator = { validate?: (value: T) => boolean, onError?: (serializedValue: string | undefined, value?: T) => T | undefined, } export type SetTransformerParams = { setter: Dispatch>, } type TransformInfo = { set: SetRes } export type SetterTransformMethod = (params: SetTransformerParams) => SetRes type Builder | undefined = undefined> = { withDefault: (value: NonNullable) => Builder, TInfo> validate: (validator: Validator) => Builder withSerializer: (coder: Serializer) => Builder withCustomSetter: (transformer: SetterTransformMethod) => Builder> } type ListBuilder | undefined = undefined> = Omit, "withSerializer"> type ListItemBuilder = Omit, "transform"> export type ListOptions = { separator?: string, item: ListItemBuilder } & UrlOptions type ParamBuilder = (options?: UrlOptions) => Builder export type OptionsBuilder = { string: ParamBuilder, number: ParamBuilder, boolean: ParamBuilder, datetime: ParamBuilder, date: ParamBuilder, object: (options?: UrlOptions) => Builder, enum: (options?: UrlOptions) => Builder, list: (options?: ListOptions) => ListBuilder[] | null>, } export type AllTypedOptions = Builder | ListBuilder type KebabToCamel = S extends `${infer P1}-${infer P2}${infer P3}` ? `${P1}${Uppercase}${KebabToCamel}` : S; export type Schema = Record type InferShape = Info extends undefined ? Param : Info extends TransformInfo ? TransformedParam : never export type InferValue = T extends Builder ? InferShape : T extends ListBuilder ? InferShape : never; type InferBuildValue = T extends Builder ? R : never; type KeysToCamelCase = { [K in keyof T as KebabToCamel]: T[K] } export type BuildArg> = Partial }>> export type Params> = KeysToCamelCase<{ [K in keyof T]: InferValue }> & { batch(fn: () => void): void, build(arg: BuildArg): void, withOptions(globalOptions: UrlOptions): Params, };