Skip to content

Commit d506bc7

Browse files
committed
Add combineEvents(events) shorthand
1 parent 87fe222 commit d506bc7

File tree

4 files changed

+396
-81
lines changed

4 files changed

+396
-81
lines changed

src/combine-events/combine-events.test.ts

+219
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,152 @@ test('source: shape', () => {
150150
`);
151151
});
152152

153+
test('source: shape (shorthand)', () => {
154+
const fn = jest.fn();
155+
156+
const event1 = createEvent<string | void>();
157+
const event2 = createEvent<string | void>();
158+
const event3 = createEvent<string | void>();
159+
const event4 = createEvent<string | void>();
160+
const event5 = createEvent<string | void>();
161+
162+
type Target = Event<{
163+
event1: string | void;
164+
event2: string | void;
165+
event3: string | void;
166+
event4: string | void;
167+
event5: string | void;
168+
}>;
169+
170+
const event: Target = combineEvents({
171+
event1,
172+
event2,
173+
event3,
174+
event4,
175+
event5,
176+
});
177+
178+
event.watch(fn);
179+
180+
event1();
181+
event1();
182+
event2('-');
183+
event3('c');
184+
event2('b');
185+
event2();
186+
event4();
187+
event4('d');
188+
event5('e');
189+
190+
expect(argumentHistory(fn)).toMatchInlineSnapshot(`
191+
[
192+
{
193+
"event1": undefined,
194+
"event2": undefined,
195+
"event3": "c",
196+
"event4": "d",
197+
"event5": "e",
198+
},
199+
]
200+
`);
201+
202+
event1('a');
203+
event2('-');
204+
event3();
205+
event2('b');
206+
event3();
207+
208+
expect(argumentHistory(fn)).toMatchInlineSnapshot(`
209+
[
210+
{
211+
"event1": undefined,
212+
"event2": undefined,
213+
"event3": "c",
214+
"event4": "d",
215+
"event5": "e",
216+
},
217+
]
218+
`);
219+
event4('-');
220+
event4();
221+
event5('e');
222+
223+
expect(argumentHistory(fn)).toMatchInlineSnapshot(`
224+
[
225+
{
226+
"event1": undefined,
227+
"event2": undefined,
228+
"event3": "c",
229+
"event4": "d",
230+
"event5": "e",
231+
},
232+
{
233+
"event1": "a",
234+
"event2": "b",
235+
"event3": undefined,
236+
"event4": undefined,
237+
"event5": "e",
238+
},
239+
]
240+
`);
241+
242+
event1('1');
243+
event2('-');
244+
event3('-');
245+
event2('2');
246+
event3('3');
247+
event4('-');
248+
event4('4');
249+
250+
expect(argumentHistory(fn)).toMatchInlineSnapshot(`
251+
[
252+
{
253+
"event1": undefined,
254+
"event2": undefined,
255+
"event3": "c",
256+
"event4": "d",
257+
"event5": "e",
258+
},
259+
{
260+
"event1": "a",
261+
"event2": "b",
262+
"event3": undefined,
263+
"event4": undefined,
264+
"event5": "e",
265+
},
266+
]
267+
`);
268+
269+
event5('5');
270+
event5('-');
271+
272+
expect(argumentHistory(fn)).toMatchInlineSnapshot(`
273+
[
274+
{
275+
"event1": undefined,
276+
"event2": undefined,
277+
"event3": "c",
278+
"event4": "d",
279+
"event5": "e",
280+
},
281+
{
282+
"event1": "a",
283+
"event2": "b",
284+
"event3": undefined,
285+
"event4": undefined,
286+
"event5": "e",
287+
},
288+
{
289+
"event1": "1",
290+
"event2": "2",
291+
"event3": "3",
292+
"event4": "4",
293+
"event5": "5",
294+
},
295+
]
296+
`);
297+
});
298+
153299
test('source: array', () => {
154300
const fn = jest.fn();
155301

@@ -225,6 +371,79 @@ test('source: array', () => {
225371
`);
226372
});
227373

374+
test('source: array (shorthand)', () => {
375+
const fn = jest.fn();
376+
377+
const event1 = createEvent<string | void>();
378+
const event2 = createEvent<string | void>();
379+
const event3 = createEvent<string | void>();
380+
const event4 = createEvent<string | void>();
381+
const event5 = createEvent<string | void>();
382+
383+
type Target = Event<
384+
[string | void, string | void, string | void, string | void, string | void]
385+
>;
386+
387+
const event: Target = combineEvents([event1, event2, event3, event4, event5]);
388+
389+
event.watch(fn);
390+
391+
event1();
392+
event1();
393+
event2('-');
394+
event3('c');
395+
event2('b');
396+
event2();
397+
event4();
398+
event4('d');
399+
event5('e');
400+
401+
event1('a');
402+
event2('-');
403+
event3();
404+
event2('b');
405+
event3();
406+
event4('-');
407+
event4();
408+
event5('e');
409+
410+
event1('1');
411+
event2('-');
412+
event3('-');
413+
event2('2');
414+
event3('3');
415+
event4('-');
416+
event4('4');
417+
event5('5');
418+
event5('-');
419+
420+
expect(argumentHistory(fn)).toMatchInlineSnapshot(`
421+
[
422+
[
423+
undefined,
424+
undefined,
425+
"c",
426+
"d",
427+
"e",
428+
],
429+
[
430+
"a",
431+
"b",
432+
undefined,
433+
undefined,
434+
"e",
435+
],
436+
[
437+
"1",
438+
"2",
439+
"3",
440+
"4",
441+
"5",
442+
],
443+
]
444+
`);
445+
});
446+
228447
test('example from readme', () => {
229448
const fn = jest.fn();
230449

src/combine-events/index.ts

+23-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
Event,
66
EventAsReturnType,
77
is,
8-
merge,
98
sample,
109
Store,
1110
Unit,
@@ -44,15 +43,21 @@ export function combineEvents<
4443
T extends UnitTargetable<P extends Tuple ? P : Partial<P>>,
4544
>(config: { events: Events<P>; target: T; reset?: Unit<any> }): ReturnTarget<P, T>;
4645

47-
export function combineEvents<P>({
48-
events,
49-
reset,
50-
target = createEvent(),
51-
}: {
52-
events: Events<any>;
53-
reset?: Unit<any>;
54-
target?: UnitTargetable<any> | Unit<any>;
55-
}) {
46+
export function combineEvents<P extends Shape>(
47+
events: Events<P>,
48+
): EventAsReturnType<P>;
49+
50+
export function combineEvents<P>(
51+
args:
52+
| {
53+
events: Events<any>;
54+
reset?: Unit<any>;
55+
target?: UnitTargetable<any> | Unit<any>;
56+
}
57+
| Events<any>,
58+
) {
59+
const argsShape = isEventsShape(args) ? { events: args } : args;
60+
const { events, reset, target = createEvent() } = argsShape;
5661
if (!(is.unit(target) && is.targetable(target)))
5762
throwError('target should be a targetable unit');
5863
if (reset && !is.unit(reset)) throwError('reset should be a unit');
@@ -64,11 +69,11 @@ export function combineEvents<P>({
6469
const $counter = createStore(keys.length, { serialize: 'ignore' });
6570
const $results = createStore(defaultShape, { serialize: 'ignore' });
6671

67-
$counter.reset(sample({ source: target }));
72+
sample({ source: target, target: $counter.reinit });
6873
$results.reset(target);
6974

7075
if (reset) {
71-
$counter.reset(sample({ source: reset }));
76+
sample({ source: reset, target: $counter.reinit });
7277
$results.reset(reset);
7378
}
7479

@@ -104,6 +109,12 @@ export function combineEvents<P>({
104109
return target;
105110
}
106111

112+
function isEventsShape<P>(args: any): args is Events<any> {
113+
return Object.keys(args).some(
114+
(key) => !['events', 'reset', 'target'].includes(key) && is.unit(args[key]),
115+
);
116+
}
117+
107118
function throwError(message: string) {
108119
throw new Error(message);
109120
}

0 commit comments

Comments
 (0)