@typed/fp
Version:
Data Structures and Resources for fp-ts
247 lines • 12.4 kB
TypeScript
/**
* @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