|
1 | | -import type { VisitOptions, GlobalEventsMap } from '@inertiajs/core'; |
| 1 | +import type { GlobalEventsMap } from '@inertiajs/core'; |
2 | 2 |
|
3 | | -export type Events<A extends [...args: any]> = { |
| 3 | +export type EventCallback<A extends [...args: any]> = { |
4 | 4 | [K in keyof Omit<GlobalEventsMap, 'navigate' | 'invalid' | 'exception'>] |
5 | | - : (...args: [...GlobalEventsMap[K]['parameters'], ...A]) => GlobalEventsMap[K]['result']; |
| 5 | + : (...args: [...GlobalEventsMap[K]['parameters'], ...A]) |
| 6 | + => K extends 'success' | 'error' |
| 7 | + ? Promise<GlobalEventsMap[K]['result']> | GlobalEventsMap[K]['result'] |
| 8 | + : GlobalEventsMap[K]['result']; |
6 | 9 | } & { |
7 | 10 | cancelToken: (...args: [{ cancel: () => void }, ...A]) => void; |
8 | 11 | }; |
9 | 12 |
|
10 | | -export type EventsList<A extends [...args: any]> = { |
11 | | - [K in keyof Events<A>]: Events<A>[K][]; |
12 | | -}; |
| 13 | +export type OnFunction<A extends [...args: any]> = ReturnType<typeof createEventCallbackManager<A>>['on']; |
| 14 | +export type CombineFunction<A extends [...args: any]> = ReturnType<typeof createEventCallbackManager<A>>['combine']; |
| 15 | +export type ExecuteFunction<A extends [...args: any]> = ReturnType<typeof createEventCallbackManager<A>>['execute']; |
13 | 16 |
|
14 | | -export const useEventsSystem = <E extends [...args: any]>() => { |
15 | | - const eventList: Partial<EventsList<E>> = {}; |
| 17 | +export const createEventCallbackManager = <E extends [...args: any]>() => { |
| 18 | + const events: Partial<{ |
| 19 | + [K in keyof EventCallback<E>]: EventCallback<E>[K][]; |
| 20 | + }> = {}; |
16 | 21 |
|
17 | | - const on = <T extends keyof Events<E>>(eventName: T, callback: Events<E>[T]) => { |
18 | | - if (typeof eventList[eventName] === 'undefined') eventList[eventName] = []; |
| 22 | + const on = <T extends keyof EventCallback<E>>(eventName: T, callback: EventCallback<E>[T]) => { |
| 23 | + if (typeof events[eventName] === 'undefined') events[eventName] = []; |
19 | 24 |
|
20 | | - eventList[eventName]?.push(callback); |
| 25 | + events[eventName]?.push(callback); |
21 | 26 | }; |
22 | 27 |
|
23 | 28 | const combine = (combineCb: (cb: typeof on) => void | ((cb: typeof on) => void)[]) => { |
24 | 29 | if (Array.isArray(combineCb)) combineCb.forEach((cb) => cb(on)); |
25 | 30 | combineCb(on); |
26 | 31 | }; |
27 | 32 |
|
28 | | - const execute = <T extends keyof Events<E>>(eventName: T, ...params: Parameters<Events<E>[T]>): ReturnType<Events<E>[T]> | undefined => { |
29 | | - const events = eventList[eventName]; |
30 | | - if (!events) return; |
| 33 | + const execute = <T extends keyof EventCallback<E>>(eventName: T, ...params: Parameters<EventCallback<E>[T]>): ReturnType<EventCallback<E>[T]> | undefined => { |
| 34 | + const eventList = events[eventName]; |
| 35 | + if (!eventList) return; |
31 | 36 |
|
32 | 37 | if (eventName === 'before') { |
33 | | - for (const event of events) { |
| 38 | + for (const event of eventList) { |
| 39 | + const res = event(...params); |
| 40 | + |
| 41 | + if (typeof res === 'boolean') return res as ReturnType<EventCallback<E>[T]>; |
| 42 | + } |
| 43 | + } else if (['success', 'error'].includes(eventName)) { |
| 44 | + let promiseResolver = Promise.resolve(); |
| 45 | + |
| 46 | + for (const event of eventList) { |
34 | 47 | const res = event(...params); |
35 | 48 |
|
36 | | - if (typeof res === 'boolean') return res as ReturnType<Events<E>[T]>; |
| 49 | + if (res instanceof Promise) { |
| 50 | + promiseResolver = res; |
| 51 | + } else { |
| 52 | + promiseResolver = Promise.resolve(res as void); |
| 53 | + } |
37 | 54 | } |
| 55 | + |
| 56 | + return promiseResolver as ReturnType<EventCallback<E>[T]>; |
38 | 57 | } else { |
39 | | - for (const event of events) { |
| 58 | + for (const event of eventList) { |
40 | 59 | event(...params); |
41 | 60 | } |
42 | 61 | } |
43 | 62 | }; |
44 | 63 |
|
45 | | - const toVisitOptions = (...params: E): VisitOptions => ((Object.keys(eventList) as (keyof typeof eventList)[]).map((name) => ({ |
46 | | - [`on${(name.charAt(0).toUpperCase() + name.slice(1)) as Capitalize<keyof typeof eventList>}`]: (arg: any) => { |
47 | | - return execute(name, ...[arg, ...params]); |
48 | | - } |
49 | | - })).reduce((p, c) => ({ |
50 | | - ...p, |
51 | | - ...c |
52 | | - }), {})); |
53 | | - |
54 | 64 | return { |
| 65 | + events, |
55 | 66 | on, |
56 | 67 | combine, |
57 | | - execute, |
58 | | - toVisitOptions |
| 68 | + execute |
59 | 69 | }; |
60 | 70 | }; |
0 commit comments