UNPKG

builder-pattern

Version:

Create a builder pattern for Typescript using ES6 proxy.

1 lines 5.31 kB
{"version":3,"sources":["../src/Builder.ts","../src/StrictBuilder.ts"],"sourcesContent":["export type IBuilder<T> = {\r\n [k in keyof T]-?: ((arg: T[k]) => IBuilder<T>) & (() => T[k]);\r\n}\r\n& {\r\n build(): T;\r\n};\r\n\r\ntype Clazz<T> = new(...args: unknown[]) => T;\r\n\r\n/**\r\n * Create a Builder for a class. Returned objects will be of the class type.\r\n *\r\n * e.g. let obj: MyClass = Builder(MyClass).setA(5).setB(\"str\").build();\r\n *\r\n * @param type the name of the class to instantiate.\r\n * @param template optional class partial which the builder will derive initial params from.\r\n * @param override optional class partial which the builder will override params from when calling build().\r\n */\r\nexport function Builder<T>(type: Clazz<T>, template?: Partial<T> | null, override?: Partial<T> | null): IBuilder<T>;\r\n\r\n/**\r\n * Create a Builder for an interface. Returned objects will be untyped.\r\n *\r\n * e.g. let obj: Interface = Builder<Interface>().setA(5).setB(\"str\").build();\r\n *\r\n * @param template optional partial object which the builder will derive initial params from.\r\n * @param override optional partial object which the builder will override params from when calling build().\r\n */\r\nexport function Builder<T>(template?: Partial<T> | null, override?: Partial<T> | null): IBuilder<T>;\r\n\r\nexport function Builder<T>(typeOrTemplate?: Clazz<T> | Partial<T> | null,\r\n templateOrOverride?: Partial<T> | null,\r\n override?: Partial<T> | null): IBuilder<T> {\r\n let type: Clazz<T> | undefined;\r\n let template: Partial<T> | null | undefined;\r\n let overrideValues: Partial<T> | null | undefined;\r\n\r\n if (typeOrTemplate instanceof Function) {\r\n type = typeOrTemplate;\r\n template = templateOrOverride;\r\n overrideValues = override;\r\n } else {\r\n template = typeOrTemplate;\r\n overrideValues = templateOrOverride;\r\n }\r\n\r\n const built: Record<string, unknown> = template ? Object.assign({}, template) : {};\r\n\r\n const builder = new Proxy(\r\n {},\r\n {\r\n get(target, prop) {\r\n if ('build' === prop) {\r\n if (overrideValues) {\r\n Object.assign(built, overrideValues);\r\n }\r\n\r\n if (type) {\r\n // A class name (identified by the constructor) was passed. Instantiate it with props.\r\n const obj: T = new type();\r\n return () => Object.assign(obj as T & Record<string, unknown>, {...built});\r\n } else {\r\n // No type information - just return the object.\r\n return () => built;\r\n }\r\n }\r\n\r\n return (...args: unknown[]): unknown => {\r\n // If no arguments passed return current value.\r\n if (0 === args.length) {\r\n return built[prop.toString()];\r\n }\r\n \r\n built[prop.toString()] = args[0];\r\n return builder;\r\n };\r\n }\r\n }\r\n );\r\n\r\n return builder as IBuilder<T>;\r\n}\r\n","export type IStrictBuilder<T, B = Record<string, unknown>> = {\r\n [k in keyof T]-?: ((arg: T[k]) => IStrictBuilder<T, B & Record<k, T[k]>>) & (() => T[k]);\r\n}\r\n& {\r\n build: B extends T ? () => T : never\r\n};\r\n\r\n/**\r\n * Create a StrictBuilder for an interface. Returned objects will be untyped.\r\n *\r\n * e.g. let obj: Interface = StrictBuilder<Interface>().setA(5).setB(\"str\").build();\r\n *\r\n */\r\nexport function StrictBuilder<T>(): IStrictBuilder<T> {\r\n\r\n const built: Record<string, unknown> = {};\r\n\r\n const strictbuilder = new Proxy(\r\n {},\r\n {\r\n get(target, prop) {\r\n if ('build' === prop) {\r\n return () => built;\r\n }\r\n\r\n return (...args: unknown[]): unknown => {\r\n // If no arguments passed return current value.\r\n if (0 === args.length) {\r\n return built[prop.toString()];\r\n }\r\n \r\n built[prop.toString()] = args[0];\r\n return strictbuilder as IStrictBuilder<T>;\r\n };\r\n }\r\n }\r\n );\r\n\r\n return strictbuilder as IStrictBuilder<T>;\r\n}\r\n"],"mappings":";AA8BO,SAAS,QAAW,gBACA,oBACA,UAA2C;AACpE,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,0BAA0B,UAAU;AACtC,WAAO;AACP,eAAW;AACX,qBAAiB;AAAA,EACnB,OAAO;AACL,eAAW;AACX,qBAAiB;AAAA,EACnB;AAEA,QAAM,QAAiC,WAAW,OAAO,OAAO,CAAC,GAAG,QAAQ,IAAI,CAAC;AAEjF,QAAM,UAAU,IAAI;AAAA,IAClB,CAAC;AAAA,IACD;AAAA,MACE,IAAI,QAAQ,MAAM;AAChB,YAAI,YAAY,MAAM;AACpB,cAAI,gBAAgB;AAClB,mBAAO,OAAO,OAAO,cAAc;AAAA,UACrC;AAEA,cAAI,MAAM;AAER,kBAAM,MAAS,IAAI,KAAK;AACxB,mBAAO,MAAM,OAAO,OAAO,KAAoC,EAAC,GAAG,MAAK,CAAC;AAAA,UAC3E,OAAO;AAEL,mBAAO,MAAM;AAAA,UACf;AAAA,QACF;AAEA,eAAO,IAAI,SAA6B;AAEtC,cAAI,MAAM,KAAK,QAAQ;AACrB,mBAAO,MAAM,KAAK,SAAS;AAAA,UAC7B;AAEA,gBAAM,KAAK,SAAS,KAAK,KAAK;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACpEO,SAAS,gBAAsC;AAEpD,QAAM,QAAiC,CAAC;AAExC,QAAM,gBAAgB,IAAI;AAAA,IACxB,CAAC;AAAA,IACD;AAAA,MACE,IAAI,QAAQ,MAAM;AAChB,YAAI,YAAY,MAAM;AACpB,iBAAO,MAAM;AAAA,QACf;AAEA,eAAO,IAAI,SAA6B;AAEtC,cAAI,MAAM,KAAK,QAAQ;AACrB,mBAAO,MAAM,KAAK,SAAS;AAAA,UAC7B;AAEA,gBAAM,KAAK,SAAS,KAAK,KAAK;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}