UNPKG

@aurbi/tiny-composite-builder

Version:

Small framework for taking base objects and adding extensions using a builder pattern, but with full and strict compile-time type support.

48 lines (47 loc) 2.87 kB
import { IBaseHint, IBase } from "./IBase"; import { IExtension } from "./IExtension"; import { ExtConsOfBuilder, Constructor, BuilderWithExt, ConstructedType, DropFirst, ExtensionConstructionArray, ConstructedExtensions } from "./Utility"; /** * A function that provides a consumer the ability to extend the base with extensions. * @typeparam T extends ExtensibleBase: what kind of extensible object are we creating? * @typeparam A: original form of the builder * @typeparam B: new form of the builder */ export type BuilderFunction<T extends IBaseHint, A extends Builder<T>, B extends Builder<T>> = (b: A) => B; export type ConstructorParams<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never; /** * A builder that should produce a base * @typeparam T extends ExtensibleBase: what kind of extensible object are we creating? */ export declare class Builder<TBase extends IBaseHint, TExts extends ExtensionConstructionArray<TBase> = []> { private _base; /** * Create a new ExtensibleBase object with optional extensions, added via a builder function. * @param builder Builder function that describes the desired extensions for the object * @returns New instance of ExtensibleBase object with the requested extensions present */ static Create<TBase extends IBaseHint<TBase>, TBuilder extends Builder<TBase, any>>(base: Constructor<TBase>, builder: BuilderFunction<TBase, Builder<TBase>, TBuilder>, ...args: any): IBase<TBase, ConstructedExtensions<TBase, ExtConsOfBuilder<TBuilder>>>; private constructor(); private _extensions; private _methodNameFilter; /** * Add a compatible extension to be grafted onto the base. * @param extClass Extension class (non-instantiated: use the class name as a value!) * @param args Arguments, if any, to pass along to the extension constructor. Do not include the * Base instance parameter, this is automatically provided to the extension constructor later. * @returns The builder, now aware of this extension */ with<TSelf extends Builder<TBase, TExts>, TNewExt extends Constructor<IExtension<TBase>>>(this: TSelf, extClass: TNewExt, ...args: DropFirst<ConstructorParams<TNewExt>>): BuilderWithExt<TBase, TSelf, ConstructedType<TNewExt>>; /** * Change the default method name filter for creating extension forwarding functions in the base. * * By default, this is `(m) => m.startsWith('$')`, meaning only public functions that start with * a dollar sign ($) have method forwarders constructed on the base instance. * * You can disable method forwarding entirely by just setting this to `() => false`. * @param f method name filter * @returns The builder, with modified filter. */ withMethodNameFilter(f: (m: string) => boolean): this; private make; }