{"mappings":";;;;;AAmBO,SAAS,4CAA+B;IAC9C,IAAI,QAAqC,CAAC;IAwB1C,eAAe,KACd,IAAS,EACT,QACC,KAAI,WACJ,QAAO,EAIP,GAAG,CAAC,CAAC,EACN,SAAE,QAAQ,KAAK,GAAE,GAAG,CAAC,CAAC,EACqB;QAC3C,IAAI,SAAS;QACb,MAAM,kBAAkB,KAAK,CAAC,KAAK;QACnC,IAAI,CAAC,iBAAiB,OAAO;QAE7B,IAAI,CAAC,SAAS,MAAM,SAAS,gCAAU;QACvC,IAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,MAAM,EAAE,IAAK;YAChD,MAAM,OAAO,eAAe,CAAC,EAAE;YAC/B,MAAM,MAAM,MAAM,KAAK,QAAQ;YAC/B,IAAI,KAAK,SAAS;QACnB;QAEA,OAAO;IACR;IAEA;;;;;EAKC,GACD,SAAS,KAGP,IAAS,EAAE,EAAM,EAAE,SAAE,MAAK,EAAuB,GAAG,CAAC,CAAC,EAAE;QACzD;;GAEC,GACD,OAAO,CAAC,UACP,eAAgB,GAAG,IAAoB,EAA2B;gBACjE,MAAM,iBAAiB;oBACtB,mEAAmE;oBACnE,MAAM;6BACN;gBACD;gBACA,MAAM,SAAS,MAAM,KAAK,MAAM,gBAAgB;2BAAE;gBAAM;gBACxD,OAAO,MAAM;YACd;IACF;IAEA,SAAS,SAAS,IAAO,EAAE,IAAU,EAAE;QACtC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,EAAE;QAClC,KAAK,CAAC,KAAK,EAAE,KAAK;QAElB,OAAO,IAAM,WAAW,MAAM;IAC/B;IAEA,SAAS,WAAW,IAAO,EAAE,IAAW,EAAE;QACzC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QAClB,IAAI,MACH,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,IAAM,MAAM;aAE/C,KAAK,CAAC,KAAK,GAAG;IAEhB;IAEA;;;;EAIC,GACD,SAAS,aAAa,KAAiB,EAAE;QACxC,OAAO,OAAO,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,UAAU,KAAK,GAAK;YACnD,SAAS,UAAU;QACpB;QAEA,OAAO,IAAM;YACZ,OAAO,OAAO,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,UAAU,KAAK,GAAK;gBACnD,WAAW,UAAU;YACtB;QACD;IACD;IAEA,OAAO;cACN;cACA;kBACA;oBACA;sBACA;IACD;AACD;AAEA;;;CAGC,GACD,SAAS,gCAAa,MAAS,EAAK;IACnC,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU,OAAO;IAClD,OAAO,KAAK,KAAK,CAAC,KAAK,SAAS,CAAC;AAClC","sources":["src/index.ts"],"sourcesContent":["export type Hook<Arguments = void, Context = void> = (\n\targs: Arguments,\n\tcxt: Context\n) => void | Arguments | Promise<void | Arguments>;\n\ntype Hooks = {\n\t[key: string]: Hook<any, any>;\n};\n\ntype ExtractArguments<H extends Hook<any, any>> = H extends Hook<infer Arg, any>\n\t? Arg\n\t: never;\ntype ExtractContext<H extends Hook<any, any>> = H extends Hook<any, infer Cxt>\n\t? Cxt\n\t: never;\n\n/**\n * create hooks instance\n */\nexport function createHooks<T extends Hooks>() {\n\tlet hooks: { [K in keyof T]?: T[K][] } = {};\n\n\ttype K = keyof T;\n\n\t/**\n\t * calls hook\n\t *\n\t * this function will clone passed arguments by default.\n\t * as this might be an intensive task, this can be disabled by setting \"asRef\" to true\n\t */\n\tasync function call(name: K): Promise<void>;\n\tasync function call<Key extends K>(\n\t\tname: Key,\n\t\tpassedArgs: ExtractContext<T[Key]> extends void\n\t\t\t? {\n\t\t\t\t\targs: ExtractArguments<T[Key]>;\n\t\t\t  }\n\t\t\t: {\n\t\t\t\t\targs: ExtractArguments<T[Key]>;\n\t\t\t\t\tcontext: ExtractContext<T[Key]>;\n\t\t\t  },\n\t\tconfig?: { asRef?: boolean }\n\t): Promise<ExtractArguments<T[Key]>>;\n\n\tasync function call<Key extends K>(\n\t\tname: Key,\n\t\t{\n\t\t\targs = undefined,\n\t\t\tcontext = undefined,\n\t\t}: {\n\t\t\targs?: ExtractArguments<T[Key]>;\n\t\t\tcontext?: ExtractContext<T[Key]>;\n\t\t} = {},\n\t\t{ asRef = false } = {}\n\t): Promise<void | ExtractArguments<T[Key]>> {\n\t\tlet result = args;\n\t\tconst registeredHooks = hooks[name];\n\t\tif (!registeredHooks) return result;\n\n\t\tif (!asRef && args) result = deepClone(args);\n\t\tfor (let i = 0; i < registeredHooks.length; i++) {\n\t\t\tconst hook = registeredHooks[i];\n\t\t\tconst res = await hook(result, context);\n\t\t\tif (res) result = res;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * wraps a function with hooks\n\t *\n\t * it returns a function that allows you to pass a context and creates a new function that wraps the original function\n\t *\n\t */\n\tfunction wrap<\n\t\tKey extends K,\n\t\tFn extends (...args: ExtractArguments<T[Key]>) => any\n\t>(name: Key, fn: Fn, { asRef }: { asRef?: boolean } = {}) {\n\t\t/**\n\t\t * create a wrapped function with the given context\n\t\t */\n\t\treturn (context: ExtractContext<T[Key]>) =>\n\t\t\tasync function (...args: Parameters<Fn>): Promise<ReturnType<Fn>> {\n\t\t\t\tconst callParameters = {\n\t\t\t\t\t// we can be sure that the passed arguments are of the correct type\n\t\t\t\t\targs: args as ExtractArguments<T[Key]>,\n\t\t\t\t\tcontext,\n\t\t\t\t};\n\t\t\t\tconst result = await call(name, callParameters, { asRef });\n\t\t\t\treturn fn(...result);\n\t\t\t};\n\t}\n\n\tfunction register(name: K, hook: T[K]) {\n\t\tif (!hooks[name]) hooks[name] = [];\n\t\thooks[name]?.push(hook);\n\n\t\treturn () => unregister(name, hook);\n\t}\n\n\tfunction unregister(name: K, hook?: T[K]) {\n\t\tif (!hooks[name]) return;\n\t\tif (hook) {\n\t\t\thooks[name] = hooks[name]?.filter((h) => h !== hook);\n\t\t} else {\n\t\t\thooks[name] = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * convenience function to register multiple hooks at once\n\t *\n\t * @param hooks an object with hooks where the key is the hook name and the value is the hook\n\t */\n\tfunction registerMany(hooks: Partial<T>) {\n\t\tObject.entries(hooks).forEach(([hookName, hook]) => {\n\t\t\tregister(hookName, hook);\n\t\t});\n\n\t\treturn () => {\n\t\t\tObject.entries(hooks).forEach(([hookName, hook]) => {\n\t\t\t\tunregister(hookName, hook);\n\t\t\t});\n\t\t};\n\t}\n\n\treturn {\n\t\tcall,\n\t\twrap,\n\t\tregister,\n\t\tunregister,\n\t\tregisterMany,\n\t};\n}\n\n/**\n * deeply clones arrays and objects\n * @returns\n */\nfunction deepClone<T>(source: T): T {\n\tif (!source || typeof source !== 'object') return source;\n\treturn JSON.parse(JSON.stringify(source));\n}\n"],"names":[],"version":3,"file":"index.cjs.map"}