UNPKG

3.23 kBTypeScriptView Raw
1/* eslint-disable @typescript-eslint/ban-types */
2
3type LastArrayElement<T extends readonly unknown[]> = T extends [...any, infer L]
4 ? L
5 : never;
6
7type DropLastArrayElement<T extends readonly unknown[]> = T extends [...(infer U), unknown]
8 ? U
9 : [];
10
11type StringEndsWith<S, X extends string> = S extends `${infer _}${X}` ? true : false;
12
13type Options<Includes extends readonly unknown[], Excludes extends readonly unknown[], MultiArgs extends boolean = false, ErrorFirst extends boolean = true, ExcludeMain extends boolean = false> = {
14 multiArgs?: MultiArgs;
15 include?: Includes;
16 exclude?: Excludes;
17 errorFirst?: ErrorFirst;
18 promiseModule?: PromiseConstructor;
19 excludeMain?: ExcludeMain;
20};
21
22type InternalOptions<Includes extends readonly unknown[], Excludes extends readonly unknown[], MultiArgs extends boolean = false, ErrorFirst extends boolean = true> = {
23 multiArgs: MultiArgs;
24 include: Includes;
25 exclude: Excludes;
26 errorFirst: ErrorFirst;
27};
28
29type Promisify<Args extends readonly unknown[], GenericOptions extends InternalOptions<readonly unknown[], readonly unknown[], boolean, boolean>> = (
30 ...args: DropLastArrayElement<Args>
31) =>
32LastArrayElement<Args> extends (...arguments_: any) => any
33// For single-argument functions when errorFirst: true we just return Promise<unknown> as it will always reject.
34 ? Parameters<LastArrayElement<Args>> extends [infer SingleCallbackArg] ? GenericOptions extends {errorFirst: true} ? Promise<unknown> : Promise<SingleCallbackArg>
35 : Promise<
36 GenericOptions extends {multiArgs: false}
37 ? LastArrayElement<Parameters<LastArrayElement<Args>>>
38 : Parameters<LastArrayElement<Args>>
39 >
40 // Functions without a callback will return a promise that never settles. We model this as Promise<unknown>
41 : Promise<unknown>;
42
43type PromisifyModule<
44 Module extends Record<string, any>,
45 MultiArgs extends boolean,
46 ErrorFirst extends boolean,
47 Includes extends ReadonlyArray<keyof Module>,
48 Excludes extends ReadonlyArray<keyof Module>,
49> = {
50 [K in keyof Module]: Module[K] extends (...arguments_: infer Arguments) => any
51 ? K extends Includes[number]
52 ? Promisify<Arguments, InternalOptions<Includes, Excludes, MultiArgs>>
53 : K extends Excludes[number]
54 ? Module[K]
55 : StringEndsWith<K, 'Sync' | 'Stream'> extends true
56 ? Module[K]
57 : Promisify<Arguments, InternalOptions<Includes, Excludes, MultiArgs, ErrorFirst>>
58 : Module[K];
59};
60
61export default function pify<
62 FirstArgument,
63 Arguments extends readonly unknown[],
64 MultiArgs extends boolean = false,
65 ErrorFirst extends boolean = true,
66>(
67 input: (argument: FirstArgument, ...arguments_: Arguments) => any,
68 options?: Options<[], [], MultiArgs, ErrorFirst>
69): Promisify<[FirstArgument, ...Arguments], InternalOptions<[], [], MultiArgs, ErrorFirst>>;
70export default function pify<
71 Module extends Record<string, any>,
72 Includes extends ReadonlyArray<keyof Module> = [],
73 Excludes extends ReadonlyArray<keyof Module> = [],
74 MultiArgs extends boolean = false,
75 ErrorFirst extends boolean = true,
76>(
77 // eslint-disable-next-line unicorn/prefer-module
78 module: Module,
79 options?: Options<Includes, Excludes, MultiArgs, ErrorFirst, true>
80): PromisifyModule<Module, MultiArgs, ErrorFirst, Includes, Excludes>;