UNPKG

@typed/fp

Version:

Data Structures and Resources for fp-ts

247 lines 12.4 kB
/** * @typed/fp/Path is a collection of helpers for constructing paths that follow * the path-to-regexp syntax and type-level combinators for parsing that syntax and * for interpolating values. * @since 0.13.0 */ import { A, N } from 'ts-toolbelt'; /** * Template for parameters * @category Model * @since 0.13.0 */ export declare type Param<A extends string> = `:${A}`; /** * @category Constructor * @since 0.13.0 */ export declare const param: <A extends string>(param: A) => `:${A}`; /** * Template for optional path parts * @category Model * @since 0.13.0 */ export declare type Optional<A extends string> = `${A}?`; /** * @category Constructor * @since 0.13.0 */ export declare const optional: <A extends string>(param: A) => `${A}?`; /** * Construct a custom prefix * @category Model * @since 0.13.0 */ export declare type Prefix<P extends string, A extends string> = `{${P}${A}}`; /** * @category Constructor * @since 0.13.0 */ export declare const prefix: <P extends string, A extends `:${string}` | "(.*)">(prefix: P, param: A) => `{${P}${A}}`; /** * Construct query params * @category Model * @since 0.13.0 */ export declare type QueryParam<K extends string, V extends string> = `` extends V ? K : `${K}=${V}`; /** * Construct query params * @category Constructor * @since 0.13.0 */ export declare const queryParam: <K extends string, V extends string>(key: K, value: V) => QueryParam<K, V>; /** * zero or more path parts will be matched to this param * @category Model * @since 0.13.0 */ export declare type ZeroOrMore<A extends string> = `${Param<A>}*`; /** * @category Constructor * @since 0.13.0 */ export declare const zeroOrMore: <A extends string>(param: A) => `:${A}*`; /** * @category Model * @since 0.13.0 */ export declare type OneOrMore<A extends string> = `${Param<A>}+`; /** * one or more path parts will be matched to this param * @category Constructor * @since 0.13.0 */ export declare const oneOrMore: <A extends string>(param: A) => `:${A}+`; /** * Creates the path-to-regexp syntax for query parameters * @category Model * @since 0.13.0 */ export declare type QueryParams<Q extends readonly QueryParam<any, any>[], R extends string = ``> = Q extends readonly [infer Head, ...infer Tail] ? QueryParams<A.Cast<Tail, readonly QueryParam<any, any>[]>, `` extends R ? `\\?${A.Cast<Head, string>}` : `${R}&${A.Cast<Head, string>}`> : R; /** * @category Constructor * @since 0.13.0 */ export declare const queryParams: <P extends readonly [any, ...any[]]>(...params: P) => QueryParams<P, "">; /** * @category Constructor * @since 0.13.0 */ export declare const unnamed: "(.*)"; /** * @category Model * @since 0.13.0 */ export declare type Unnamed = typeof unnamed; /** * Composes other path parts into a single path * @category Type-level * @since 0.13.0 */ export declare type PathJoin<A extends ReadonlyArray<string>> = A extends readonly [ infer Head, ...infer Tail ] ? `${FormatPart<A.Cast<Head, string>>}${PathJoin<A.Cast<Tail, ReadonlyArray<string>>>}` : ``; /** * @category Combinator * @since 0.13.0 */ export declare const pathJoin: <P extends readonly string[]>(...parts: P) => PathJoin<P>; /** * Formats a piece of a path * @category Combinator * @since 0.13.0 */ export declare const formatPart: (part: string) => string; /** * @category Type-level * @since 0.13.0 */ export declare type FormatPart<P extends string> = `` extends P ? P : RemoveLeadingSlash<P> extends `\\?${infer _}` ? RemoveLeadingSlash<P> : RemoveLeadingSlash<P> extends `{${infer _}` ? RemoveLeadingSlash<P> : P extends QueryParam<infer _, infer _> | QueryParams<infer _, infer _> ? P : `/${RemoveLeadingSlash<P>}`; /** * Remove forward slashes prefixes recursively * @category Type-level * @since 0.13.0 */ export declare type RemoveLeadingSlash<A> = A extends `/${infer R}` ? RemoveLeadingSlash<R> : A; /** * @category Combinator * @since 0.13.0 */ export declare const removeLeadingSlash: <A extends string>(a: A) => RemoveLeadingSlash<A>; /** * @category Type-level * @since 0.13.0 */ export declare type ParamsOf<A extends string> = Compact<PartsToParams<PathToParts<A>>>; /** * @category Type-level * @since 0.13.0 */ export declare type QueryParamsOf<P extends string> = Compact<QueryToParams<PathToQuery<P>>>; /** * @category Type-level * @since 0.13.0 */ export declare type PathToParts<P> = P extends `${infer Head}\\?${infer Tail}` ? readonly [...PathToParts<Head>, `\\?${Tail}`] : P extends `${infer Head}/${infer Tail}` ? readonly [...PathToParts<Head>, ...PathToParts<Tail>] : P extends `${infer Head}{${infer Q}}?${infer Tail}` ? readonly [...PathToParts<Head>, `{${Q}}?`, ...PathToParts<`${Tail}`>] : P extends `${infer Head}{${infer Q}}${infer Tail}` ? readonly [...PathToParts<Head>, `{${Q}}`, ...PathToParts<`${Tail}`>] : `` extends P ? readonly [] : readonly [P]; /** * @category Type-level * @since 0.13.0 */ export declare type PartsToParams<A extends ReadonlyArray<string>, AST = {}> = A extends readonly [ infer Head, ...infer Tail ] ? PartsToParams<A.Cast<Tail, readonly string[]>, AST & PartToParam<A.Cast<Head, string>, AST>> : AST; /** * @category Type-level * @since 0.13.0 */ export declare type PartToParam<A extends string, AST> = A extends `\\${infer R}` ? PartsToParams<QueryParamsToParts<R, []>, AST> : A extends Unnamed ? { readonly [K in FindNextIndex<AST> extends number ? FindNextIndex<AST> : never]: string; } : A extends `${infer _}${Unnamed}}?` ? { readonly [K in FindNextIndex<AST> extends number ? FindNextIndex<AST> : never]?: string; } : A extends `${infer _}${Unnamed}}` ? { readonly [K in FindNextIndex<AST> extends number ? FindNextIndex<AST> : never]: string; } : A extends `${infer _}${Param<infer R>}}?` ? { readonly [K in R]?: string; } : A extends `${infer _}${Param<infer R>}}` ? { readonly [K in R]: string; } : A extends `${infer _}${Param<infer R>}?` ? { readonly [K in R]?: string; } : A extends `${infer _}${Param<infer R>}+` ? { readonly [K in R]: readonly [string, ...string[]]; } : A extends `${infer _}${Param<infer R>}*` ? { readonly [K in R]: readonly string[]; } : A extends `${infer _}${Param<infer R>}` ? { readonly [K in R]: string; } : {}; /** * @category Type-level * @since 0.13.0 */ export declare type QueryParamsToParts<Q extends string, R extends ReadonlyArray<string>> = Q extends `\\?${infer Q}` ? QueryParamsToParts<Q, R> : Q extends `?${infer Q}` ? QueryParamsToParts<Q, R> : Q extends `${infer Head}&${infer Tail}` ? QueryParamsToParts<Tail, QueryParamsToParts<Head, R>> : readonly [...R, QueryParamValue<Q>]; /** * @category Type-level * @since 0.13.0 */ export declare type QueryToParams<Q extends string, AST = {}> = Q extends `${infer Head}&${infer Tail}` ? QueryToParams<Tail, QueryToParams<Head, AST>> : Q extends `?${infer K}` ? QueryToParams<K, AST> : Q extends `${infer K}?` ? AST & Partial<QueryParamAst<K>> : Q extends `${infer K}` ? AST & QueryParamAst<K> : AST; /** * @category Type-level * @since 0.13.0 */ export declare type FindNextIndex<AST, I extends number = 0> = I extends keyof AST ? FindNextIndex<AST, N.Add<I, 1>> : I; /** * @category Type-level * @since 0.13.0 */ export declare type PathToQuery<P extends string> = P extends `${infer _}\\${infer Q}` ? Q : ``; declare type QueryParamValue<K extends string> = K extends `${infer _}=${infer R}` ? R : string; declare type QueryParamAst<K extends string> = Readonly<Record<QueryParamAstKey<K>, QueryParamAstValue<K>>>; declare type QueryParamAstKey<K extends string> = K extends `${infer K}=${infer _}` ? K : K; declare type QueryParamAstValue<K extends string> = K extends `${infer _}=${infer R}` ? R extends Param<infer _> | Unnamed ? string : R : string; declare type Compact<A> = { readonly [K in keyof A]: A[K]; }; /** * @category Type-level * @since 0.13.0 */ export declare type Interpolate<P extends string, Params extends ParamsOf<P>> = P extends `${infer Head}\\?${infer Tail}` ? PathJoin<InterpolateWithQueryParams<SplitQueryParams<Tail>, Params, InpterpolateParts<PathToParts<Head>, Params>>[0]> : PathJoin<InpterpolateParts<PathToParts<P>, Params>[0]>; /** * @category Type-level * @since 0.13.0 */ export declare type InpterpolateParts<Parts extends readonly any[], Params extends {}, R extends readonly any[] = [], AST = {}> = Parts extends readonly [infer H, ...infer T] ? H extends Optional<Prefix<infer Pre, Unnamed>> ? FindNextIndex<AST> extends keyof Params ? InpterpolateParts<T, Params, AppendPrefix<R, Pre, `${A.Cast<Params[FindNextIndex<AST>], string | number>}`>, AST & Record<H, Params[FindNextIndex<AST>]>> : InpterpolateParts<T, Params, R, AST> : H extends Prefix<infer Pre, Unnamed> ? InpterpolateParts<T, Params, AppendPrefix<R, Pre, `${A.Cast<Params[A.Cast<FindNextIndex<AST>, keyof Params>], string | number>}`>, AST & Record<H, Params[A.Cast<FindNextIndex<AST>, keyof Params>]>> : H extends Optional<Prefix<infer Pre, Param<infer P>>> ? P extends keyof Params ? InpterpolateParts<T, Params, AppendPrefix<R, Pre, A.Cast<Params[A.Cast<P, keyof Params>], string>>, AST & Record<H, Params[A.Cast<P, keyof Params>]>> : InpterpolateParts<T, Params, R, AST> : H extends Prefix<infer Pre, Param<infer P>> ? InpterpolateParts<T, Params, AppendPrefix<R, Pre, A.Cast<Params[A.Cast<P, keyof Params>], string>>, AST & Record<H, Params[A.Cast<P, keyof Params>]>> : InterpolatePart<H, Params, AST> extends readonly [infer A, infer B] ? InpterpolatePartsWithNext<T, Params, R, readonly [A, B]> : InpterpolateParts<T, Params, R, AST> : readonly [R, AST]; /** * @category Type-level * @since 0.13.0 */ export declare type AppendPrefix<R extends readonly any[], Pre extends string, P extends string> = R extends readonly [...infer Init, infer L] ? readonly [...Init, `${A.Cast<L, string>}${Pre}${P}`] : R; /** * @category Type-level * @since 0.13.0 */ export declare type InpterpolatePartsWithNext<Parts extends readonly any[], Params extends {}, R extends readonly any[], Next extends readonly [any, any]> = InpterpolateParts<Parts, Params, readonly [...R, Next[0]], Next[1]>; /** * @category Type-level * @since 0.13.0 */ export declare type InterpolatePart<P, Params, AST> = P extends Optional<Param<infer R>> ? R extends keyof Params ? readonly [Params[R], AST & Record<R, Params[R]>] : readonly ['', AST] : P extends Param<infer R> ? R extends keyof Params ? readonly [Params[R], AST & Record<R, Params[R]>] : readonly [P, AST] : P extends Unnamed ? FindNextIndex<AST> extends keyof Params ? InterpolateUnnamedPart<Params, FindNextIndex<AST>, AST> : readonly [P, AST] : P extends Prefix<infer Pre, Param<infer R>> ? R extends keyof Params ? [`${Pre}${A.Cast<Params[R], string>}`, AST & Record<R, Params[R]>] : [] : P extends Optional<Prefix<infer Pre, Param<infer R>>> ? R extends keyof Params ? [`${Pre}${A.Cast<Params[R], string>}`, AST & Partial<Record<R, Params[R]>>] : [] : readonly [P, AST]; /** * @category Type-level * @since 0.13.0 */ export declare type InterpolateUnnamedPart<Params, K extends keyof Params, AST> = readonly [ Params[K], AST & Record<K, Params[K]> ]; declare type InterpolateWithQueryParams<Q extends readonly string[], Params, Previous extends readonly [any, any], First extends boolean = true> = Q extends readonly [infer Head, ...infer Tail] ? InterpolateWithQueryParams<A.Cast<Tail, readonly string[]>, Params, InterpolateQueryParamPart<Head, Params, Previous, First>[0], InterpolateQueryParamPart<Head, Params, Previous, First>[1]> : Previous; /** * @category Type-level * @since 0.13.0 */ export declare type InterpolateQueryParamPart<Part, Params, Previous extends readonly [readonly string[], any], First extends boolean> = Part extends QueryParam<infer K, infer V> ? InterpolateQueryParamPartWithKey<First extends true ? `?${K}` : `&${K}`, Previous[0], InterpolatePart<V, Params, Previous[1]>, First> : readonly [[[...Previous[0], Part], Previous[1]], false]; declare type InterpolateQueryParamPartWithKey<K extends string, Parts extends readonly string[], Previous extends readonly [string, any], First extends boolean> = '' extends Previous[0] ? [[Parts, Previous[1]], First] : [[[...Parts, `${K}=${Previous[0]}`], Previous[1]], false]; declare type SplitQueryParams<P extends string> = P extends `${infer Head}&${infer Tail}` ? readonly [Head, ...SplitQueryParams<Tail>] : readonly [P]; export {}; //# sourceMappingURL=Path.d.ts.map