UNPKG

@ibnlanre/builder

Version:

Creates a builder object for defining keys and values.

106 lines (95 loc) 5.12 kB
/** * Represents a store key. * * @param {Field} Field The type of the field. * @param {Prefix} Prefix The type of the prefix. * * @returns {Base<Field, Prefix>} A store key object with get and use functions. */ type Base<Field, Prefix extends readonly string[] = []> = { $get: <Arguments extends unknown[]>(...args: Arguments) => [...Prefix, Field, ...Arguments]; $use: () => [...Prefix, Field]; }; type Dictionary = { readonly [k: number]: unknown; readonly [k: string]: unknown; readonly [k: symbol]: unknown; }; type Primitives = bigint | boolean | null | number | string | undefined; type Serialize<Head extends Primitives> = Head extends Exclude<Primitives, null | undefined> ? `${Head}` : ""; /** * Represents a list of primitives joined by a separator. * * @template List The type of the list. * @template Separator The type of the separator. * * @returns {string} The joined list. */ type Join<List extends ReadonlyArray<Primitives>, Separator extends string = ""> = List extends [infer Head, ...infer Rest] ? JoinHelper<Head, Rest, Separator> : ""; type JoinHelper<Head, Rest extends unknown[], Separator extends string> = Head extends Primitives ? Rest extends [] ? `${Serialize<Head>}` : Rest extends Primitives[] ? `${Serialize<Head>}${Separator}${Join<Rest, Separator>}` : "" : ""; /** * Represents a builder for a store key. * * @params Register The type of the store. * @params Prefix The type of the path. * * @return KeyBuilder<Register, Prefix> A store key builder object. */ type KeyBuilder<Register extends Dictionary, Prefix extends readonly string[] = []> = { [Field in keyof Register]: Register[Field] extends (...args: infer Arguments) => unknown ? { $get: <Variables extends any[]>(...args: Variables) => [...Prefix, Extract<Field, string>, ...Variables]; $use: (...args: Parameters<Register[Field]>) => [...Prefix, Extract<Field, string>, ...Arguments]; } : Register[Field] extends Dictionary ? Base<Field, Prefix> & KeyBuilder<Register[Field], [...Prefix, Extract<Field, string>]> : Base<Field, Prefix>; }; type Values<List extends readonly string[], Separator extends string = ".", Result extends string = ""> = List extends [infer Head extends string, ...infer Tail extends string[]] ? Result extends "" ? Values<Tail, Separator, `${Head}`> : Result | Values<Tail, Separator, `${Result}${Separator}${Head}`> : Result; type Paths<Register extends Dictionary, Prefix extends readonly string[] = [], Separator extends string = "."> = Register extends Dictionary ? { [Key in keyof Register]: Key extends number | string ? Register[Key] extends Dictionary ? PathsHelper<Prefix, `${Key}${Separator}${Paths<Register[Key], [], Separator>}`, Separator> | PathsHelper<Prefix, `${Key}`, Separator> : PathsHelper<Prefix, `${Key}`, Separator> : never; }[keyof Register] : never; type PathsHelper<Prefix extends readonly string[], Key extends string, Separator extends string = "."> = Values<[...Prefix, Key], Separator>; /** * Represents the builder for a store. * * @template Register The type of the store. * @template Prefix The type of the path. * @template Separator The type of the separator. */ type Builder<Register extends Dictionary, Prefix extends readonly string[] = [], Separator extends string = "."> = KeyBuilder<Register, Prefix> & { $get: Get<Register, Prefix, Separator>; $use: Register; }; interface Get<Register extends Dictionary, Prefix extends readonly string[] = [], Separator extends string = "."> { /** * Returns the prefix array. * * @returns {Prefix} The prefix array. */ (): Prefix; /** * Returns the key passed to the method. * If no key is provided, it returns the prefix array. * * @template {Paths<Register, Prefix, Separator>} Path * @template {readonly [Path, ...Array<Primitives>]} Key * * @param {Key} path The key to return. * @returns {Join<Key, Separator>} The key passed to the method. */ <Path extends Paths<Register, Prefix, Separator>, Key extends readonly [Path, ...Array<Primitives>]>(...path: Key): Join<Key, Separator>; } /** * Returns a builder object that represents the nested keys of the provided object. * * @template Register The type of the object. * @template Prefix The type of the prefix array. * * @param {Register} register The object to traverse and retrieve the nested keys. * @param {string[]} [prefix=[]] An optional prefix to prepend to keys array in the builder object. * @param {string} [separator="."] An optional separator to join the keys in the builder object. * * @returns {Builder<Register, Prefix>} A builder object with callable functions representing the nested keys. */ declare function createBuilder<Register extends Dictionary, const Prefix extends string[] = [], const Separator extends string = ".">(register: Register, options?: { prefix?: Prefix; separator?: Separator; }): Builder<Register, Prefix, Separator>; export { type Builder, type Dictionary, type KeyBuilder, type Paths, type Primitives, type Values, createBuilder };