186 lines
4.4 KiB
TypeScript
186 lines
4.4 KiB
TypeScript
type HookMethod<Options, Result> = (
|
|
options: Options
|
|
) => Result | Promise<Result>
|
|
|
|
type BeforeHook<Options> = (options: Options) => void | Promise<void>
|
|
type ErrorHook<Options, Error> = (
|
|
error: Error,
|
|
options: Options
|
|
) => void | Promise<void>
|
|
type AfterHook<Options, Result> = (
|
|
result: Result,
|
|
options: Options
|
|
) => void | Promise<void>
|
|
type WrapHook<Options, Result> = (
|
|
hookMethod: HookMethod<Options, Result>,
|
|
options: Options
|
|
) => Result | Promise<Result>
|
|
|
|
type AnyHook<Options, Result, Error> =
|
|
| BeforeHook<Options>
|
|
| ErrorHook<Options, Error>
|
|
| AfterHook<Options, Result>
|
|
| WrapHook<Options, Result>
|
|
|
|
type TypeStoreKeyLong = 'Options' | 'Result' | 'Error'
|
|
type TypeStoreKeyShort = 'O' | 'R' | 'E'
|
|
type TypeStore =
|
|
| ({ [key in TypeStoreKeyLong]?: any } &
|
|
{ [key in TypeStoreKeyShort]?: never })
|
|
| ({ [key in TypeStoreKeyLong]?: never } &
|
|
{ [key in TypeStoreKeyShort]?: any })
|
|
type GetType<
|
|
Store extends TypeStore,
|
|
LongKey extends TypeStoreKeyLong,
|
|
ShortKey extends TypeStoreKeyShort
|
|
> = LongKey extends keyof Store
|
|
? Store[LongKey]
|
|
: ShortKey extends keyof Store
|
|
? Store[ShortKey]
|
|
: any
|
|
|
|
export interface HookCollection<
|
|
HooksType extends Record<string, TypeStore> = Record<
|
|
string,
|
|
{ Options: any; Result: any; Error: any }
|
|
>,
|
|
HookName extends keyof HooksType = keyof HooksType
|
|
> {
|
|
/**
|
|
* Invoke before and after hooks
|
|
*/
|
|
<Name extends HookName>(
|
|
name: Name | Name[],
|
|
hookMethod: HookMethod<
|
|
GetType<HooksType[Name], 'Options', 'O'>,
|
|
GetType<HooksType[Name], 'Result', 'R'>
|
|
>,
|
|
options?: GetType<HooksType[Name], 'Options', 'O'>
|
|
): Promise<GetType<HooksType[Name], 'Result', 'R'>>
|
|
/**
|
|
* Add `before` hook for given `name`
|
|
*/
|
|
before<Name extends HookName>(
|
|
name: Name,
|
|
beforeHook: BeforeHook<GetType<HooksType[Name], 'Options', 'O'>>
|
|
): void
|
|
/**
|
|
* Add `error` hook for given `name`
|
|
*/
|
|
error<Name extends HookName>(
|
|
name: Name,
|
|
errorHook: ErrorHook<
|
|
GetType<HooksType[Name], 'Options', 'O'>,
|
|
GetType<HooksType[Name], 'Error', 'E'>
|
|
>
|
|
): void
|
|
/**
|
|
* Add `after` hook for given `name`
|
|
*/
|
|
after<Name extends HookName>(
|
|
name: Name,
|
|
afterHook: AfterHook<
|
|
GetType<HooksType[Name], 'Options', 'O'>,
|
|
GetType<HooksType[Name], 'Result', 'R'>
|
|
>
|
|
): void
|
|
/**
|
|
* Add `wrap` hook for given `name`
|
|
*/
|
|
wrap<Name extends HookName>(
|
|
name: Name,
|
|
wrapHook: WrapHook<
|
|
GetType<HooksType[Name], 'Options', 'O'>,
|
|
GetType<HooksType[Name], 'Result', 'R'>
|
|
>
|
|
): void
|
|
/**
|
|
* Remove added hook for given `name`
|
|
*/
|
|
remove<Name extends HookName>(
|
|
name: Name,
|
|
hook: AnyHook<
|
|
GetType<HooksType[Name], 'Options', 'O'>,
|
|
GetType<HooksType[Name], 'Result', 'R'>,
|
|
GetType<HooksType[Name], 'Error', 'E'>
|
|
>
|
|
): void
|
|
/**
|
|
* Public API
|
|
*/
|
|
api: Pick<
|
|
HookCollection<HooksType>,
|
|
'before' | 'error' | 'after' | 'wrap' | 'remove'
|
|
>
|
|
}
|
|
|
|
export interface HookSingular<Options, Result, Error> {
|
|
/**
|
|
* Invoke before and after hooks
|
|
*/
|
|
(hookMethod: HookMethod<Options, Result>, options?: Options): Promise<Result>
|
|
/**
|
|
* Add `before` hook
|
|
*/
|
|
before(beforeHook: BeforeHook<Options>): void
|
|
/**
|
|
* Add `error` hook
|
|
*/
|
|
error(errorHook: ErrorHook<Options, Error>): void
|
|
/**
|
|
* Add `after` hook
|
|
*/
|
|
after(afterHook: AfterHook<Options, Result>): void
|
|
/**
|
|
* Add `wrap` hook
|
|
*/
|
|
wrap(wrapHook: WrapHook<Options, Result>): void
|
|
/**
|
|
* Remove added hook
|
|
*/
|
|
remove(hook: AnyHook<Options, Result, Error>): void
|
|
/**
|
|
* Public API
|
|
*/
|
|
api: Pick<
|
|
HookSingular<Options, Result, Error>,
|
|
'before' | 'error' | 'after' | 'wrap' | 'remove'
|
|
>
|
|
}
|
|
|
|
type Collection = new <
|
|
HooksType extends Record<string, TypeStore> = Record<
|
|
string,
|
|
{ Options: any; Result: any; Error: any }
|
|
>
|
|
>() => HookCollection<HooksType>
|
|
type Singular = new <
|
|
Options = any,
|
|
Result = any,
|
|
Error = any
|
|
>() => HookSingular<Options, Result, Error>
|
|
|
|
interface Hook {
|
|
new <
|
|
HooksType extends Record<string, TypeStore> = Record<
|
|
string,
|
|
{ Options: any; Result: any; Error: any }
|
|
>
|
|
>(): HookCollection<HooksType>
|
|
|
|
/**
|
|
* Creates a collection of hooks
|
|
*/
|
|
Collection: Collection
|
|
|
|
/**
|
|
* Creates a nameless hook that supports strict typings
|
|
*/
|
|
Singular: Singular
|
|
}
|
|
|
|
export const Hook: Hook
|
|
export const Collection: Collection
|
|
export const Singular: Singular
|
|
|
|
export default Hook
|