Skip to content

Commit

Permalink
fix: improving typings and apis for creating events and filtering eve…
Browse files Browse the repository at this point in the history
…nt in epics
  • Loading branch information
carere committed Sep 27, 2022
1 parent 8f362a2 commit 26c9ce2
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"*.{ts,tsx,json}": ["prettier --write"],
"*.{ts,tsx}": ["pnpm run lint --"],
"*.{ts,tsx}": ["eslint --cache --fix"],
"package.json": "sort-package-json"
}
9 changes: 0 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,5 @@
},
"volta": {
"node": "18.9.0"
},
"wallaby": {
"autoDetect": true,
"files": [
"src/**/*.ts"
],
"test": [
"test/unit/*.spec.ts"
]
}
}
18 changes: 10 additions & 8 deletions src/createEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import type { Event, EventCreator, PrepareCallback } from './types'
* if an event is produced by the return event creator
*
* @param name The event type to use for created events.
* @param prepareEvent (optional) a method that takes an object and returns { payload, meta? }.
* @param options (optional) a method that takes an object and returns { payload, meta? }.
* If this is given, the resulting event creator will pass its arguments to this method to calculate payload.
* @template P The type of the `payload` attribute of the created events
* @template V The type of the argument used to `prepare` the payload
*
* @returns An event creator
*/
export const createEvent = <P, M = unknown, V = unknown>(
export const createEvent = <P, M = undefined, V = undefined>(
name: string,
prepareEvent?: PrepareCallback<P, M, V>,
): EventCreator<P, M, V> => {
const creator = (value?: P | V) => {
if (prepareEvent) {
const prepared = prepareEvent(value as V)
options: Partial<{
prepare: PrepareCallback<P, M, V>
}> = {},
) => {
const creator: EventCreator<P, M, V> = (value?) => {
if (options.prepare) {
const prepared = options.prepare(value as V)

if (!('meta' in prepared) && !('payload' in prepared))
throw Error(`
Expand All @@ -44,7 +46,7 @@ export const createEvent = <P, M = unknown, V = unknown>(
}

creator.type = name
creator.match = (event: Event) => event.type === name
creator.match = (event: Event<P>) => event.type === name

return creator
}
9 changes: 5 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import type { Observable, Subscription } from 'rxjs'
* performed. The `type` field needs to be a `string`
*
* If you need some data to represent what happen, you are free to populate
* the payload property of an event.
* the payload / meta property of an event.
*
* @template P the type of the event's `payload` property.
* @template M the type of the event's `meta` property.
*/
export type Event<P = unknown, M = unknown> = { type: string; payload?: P; meta?: M }

Expand Down Expand Up @@ -86,8 +87,8 @@ export type Store<S> = {
* @param value The argument used to prepare the event
*
* @template P The type of the `payload` field of the created events
* @template V The type of the argument used to `prepare` the payload
* @template M The type of the `meta` field of the created events
* @template V The type of the argument passed to the prepare callbacks
*/
export type PrepareCallback<P, M, V> = (value: V) => Partial<Omit<Event<P, M>, 'type'>>

Expand All @@ -97,8 +98,8 @@ export type PrepareCallback<P, M, V> = (value: V) => Partial<Omit<Event<P, M>, '
* @template P the `payload` type
* @template V the type of the parameter passed to the prepared callback
*/
export type EventCreator<P = unknown, M = unknown, V = unknown> = {
(value?: P | V): Event<P, M>
export type EventCreator<P, M = undefined, V = undefined> = {
(value?: V extends undefined ? P : V): Event<P, M>
type: string
match: (event: Event<P, M>) => boolean
}
Expand Down
22 changes: 13 additions & 9 deletions test/unit/createEvents.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'
import { createEvent } from '../../src/createEvent'

describe('Creating an event', () => {
it('should contain a property type with then name of the type', () => {
it('should contain a property type with the name of the type', () => {
const creator = createEvent('someDomain')

expect(creator.type).toEqual('someDomain')
Expand Down Expand Up @@ -36,23 +36,27 @@ describe('Creating an event', () => {
})
})

describe('with prepared callback', () => {
describe('with options', () => {
it('should throw and error if callback does not generate proper object', () => {
expect(createEvent('error', () => ({}))).toThrowError()
expect(createEvent('error', { prepare: () => ({}) })).toThrowError()
})

it('should be able to construct an event with prepared payload', () => {
const creator = createEvent('someDomain', (value: string) => ({
payload: { depth: Number.parseInt(value) },
}))
const creator = createEvent('someDomain', {
prepare: (value: string) => ({
payload: { depth: Number.parseInt(value) },
}),
})

expect(creator('42')).toEqual({ type: 'someDomain', payload: { depth: 42 } })
})

it('should be able to construct an event with prepared meta', () => {
const creator = createEvent('event-meta', (value: number) => ({
meta: value,
}))
const creator = createEvent('event-meta', {
prepare: (value: number) => ({
meta: value,
}),
})

expect(creator(42)).toEqual({ type: 'event-meta', meta: 42 })
})
Expand Down

0 comments on commit 26c9ce2

Please sign in to comment.