= `{${P}${A}}` /** * @category Constructor * @since 0.13.0 */ export const prefix =
| Unnamed>(prefix: P, param: A) => `{${prefix}${param}}` as Prefix
/**
* Construct query params
* @category Model
* @since 0.13.0
*/
export type QueryParam , ...QueryParam => `\\?${params.join('&')}` as QueryParams
/**
* @category Constructor
* @since 0.13.0
*/
export const unnamed = `(.*)` as const
/**
* @category Model
* @since 0.13.0
*/
export type Unnamed = typeof unnamed
/**
* Composes other path parts into a single path
* @category Type-level
* @since 0.13.0
*/
export type PathJoin> = A extends readonly [
infer Head,
...infer Tail
]
? `${FormatPart >(...parts: P): PathJoin => {
if (parts.length === 0) {
return `` as PathJoin
}
const [head, ...tail] = parts
return `${formatPart(head)}${pathJoin(...tail)}` as PathJoin
}
/**
* Formats a piece of a path
* @category Combinator
* @since 0.13.0
*/
export const formatPart = (part: string) => {
part = removeLeadingSlash(part)
if (part.startsWith('{')) {
return part
}
if (part.startsWith('\\?')) {
return part
}
return part === '' ? '' : `/${part}`
}
/**
* @category Type-level
* @since 0.13.0
*/
export type FormatPart = `` extends P
? P
: RemoveLeadingSlash extends `\\?${infer _}`
? RemoveLeadingSlash
: RemoveLeadingSlash extends `{${infer _}`
? RemoveLeadingSlash
: P extends QueryParam }`
/**
* Remove forward slashes prefixes recursively
* @category Type-level
* @since 0.13.0
*/
export type RemoveLeadingSlash = A extends `/${infer R}` ? RemoveLeadingSlash = Compact = P extends `${infer Head}\\?${infer Tail}`
? readonly [...PathToParts
: Q extends `?${infer Q}`
? QueryParamsToParts
: Q extends `${infer Head}&${infer Tail}`
? QueryParamsToParts
]
/**
* @category Type-level
* @since 0.13.0
*/
export type QueryToParams
= Q extends `${infer Head}&${infer Tail}`
? QueryToParams