Skip to content

Commit 0bdbb16

Browse files
committed
feat: adds return promise to success and error events and better ts support
1 parent bca6bf1 commit 0bdbb16

File tree

3 files changed

+61
-37
lines changed

3 files changed

+61
-37
lines changed

src/event.ts

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,70 @@
1-
import type { VisitOptions, GlobalEventsMap } from '@inertiajs/core';
1+
import type { GlobalEventsMap } from '@inertiajs/core';
22

3-
export type Events<A extends [...args: any]> = {
3+
export type EventCallback<A extends [...args: any]> = {
44
[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'];
69
} & {
710
cancelToken: (...args: [{ cancel: () => void }, ...A]) => void;
811
};
912

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'];
1316

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+
}> = {};
1621

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] = [];
1924

20-
eventList[eventName]?.push(callback);
25+
events[eventName]?.push(callback);
2126
};
2227

2328
const combine = (combineCb: (cb: typeof on) => void | ((cb: typeof on) => void)[]) => {
2429
if (Array.isArray(combineCb)) combineCb.forEach((cb) => cb(on));
2530
combineCb(on);
2631
};
2732

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;
3136

3237
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) {
3447
const res = event(...params);
3548

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+
}
3754
}
55+
56+
return promiseResolver as ReturnType<EventCallback<E>[T]>;
3857
} else {
39-
for (const event of events) {
58+
for (const event of eventList) {
4059
event(...params);
4160
}
4261
}
4362
};
4463

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-
5464
return {
65+
events,
5566
on,
5667
combine,
57-
execute,
58-
toVisitOptions
68+
execute
5969
};
6070
};

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type { Events, EventsList } from './event';
2-
export { useEventsSystem } from './event';
1+
export type { EventCallback, OnFunction, CombineFunction, ExecuteFunction } from './event';
2+
export { createEventCallbackManager } from './event';
33

44
export { useForm } from './inertia';

src/inertia.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import type { Method, VisitOptions, RequestPayload } from '@inertiajs/core';
44
import { createMessage } from '@formkit/core';
55
import { router } from '@inertiajs/core';
66
import { reactive, toRefs, watchEffect } from 'vue';
7-
import { useEventsSystem } from './event';
7+
import { createEventCallbackManager } from './event';
88

99
export const useForm = <F extends RequestPayload>(initialFields?: F) => {
10-
const event = useEventsSystem<[node: FormKitNode]>();
10+
const eventManager = createEventCallbackManager<[node: FormKitNode]>();
1111

1212
let _recentlySuccessfulTimeoutId: ReturnType<typeof setTimeout> | undefined = undefined;
1313
let _cancelToken: {
@@ -34,7 +34,7 @@ export const useForm = <F extends RequestPayload>(initialFields?: F) => {
3434
wasSuccessful: false
3535
});
3636

37-
event.combine((on) => {
37+
eventManager.combine((on) => {
3838
on('cancelToken', (token) => {
3939
_cancelToken = token;
4040
});
@@ -110,15 +110,29 @@ export const useForm = <F extends RequestPayload>(initialFields?: F) => {
110110
};
111111

112112
const _createVisitHandler = (method: Method) => (url: URL | string, options?: Exclude<VisitOptions, 'method' | 'data'>) => (data: F, node: FormKitNode) => {
113+
const _optionEventCallbacks: {
114+
[key: string]: any
115+
} = {};
116+
117+
const names = Object.keys(eventManager.events) as (keyof typeof eventManager.events)[];
118+
119+
for (const name of names) {
120+
const _callbackName = `on${name.charAt(0).toUpperCase() + name.slice(1)}`;
121+
122+
_optionEventCallbacks[_callbackName] = (arg: any) => {
123+
return eventManager.execute(name, arg, node);
124+
};
125+
}
126+
113127
if (method === 'delete') {
114128
router.delete(url, {
115-
...event.toVisitOptions(node),
129+
..._optionEventCallbacks,
116130
...options,
117131
data
118132
});
119133
} else {
120134
router[method](url, data, {
121-
...event.toVisitOptions(node),
135+
..._optionEventCallbacks,
122136
...options,
123137
});
124138
}
@@ -136,8 +150,8 @@ export const useForm = <F extends RequestPayload>(initialFields?: F) => {
136150

137151
...toRefs(state),
138152

139-
on: event.on,
140-
combine: event.combine,
153+
on: eventManager.on,
154+
combine: eventManager.combine,
141155

142156
plugin,
143157
}

0 commit comments

Comments
 (0)