Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ features:
- title: Type safety
details: Type safe events and payload
- title: Useful API
details: Includes on, off, once, next, emit, and clear
details: Includes on, off, once, next, emit, count, and clear
- title: Support Global Handlers
details: Setup handlers that run on all events
---
Expand Down
21 changes: 21 additions & 0 deletions src/createEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,26 @@ export function createEmitter<TEvents extends EmitterEvents>(options?: EmitterOp
onEvent(event, payload!)
}

type CountOptions = {
global?: boolean
}

function count<E extends TEvent>(): number
function count<E extends TEvent>(event: E, options?: CountOptions): number
function count<E extends TEvent>(event?: E, { global = false }: CountOptions = {}): number {
if(event) {
const eventHandlers = handlers.get(event)?.size ?? 0

if(global) {
return eventHandlers + globalHandlers.size
}

return eventHandlers
}

return globalHandlers.size
}

function clear(): void {
handlers.clear()
globalHandlers.clear()
Expand Down Expand Up @@ -210,6 +230,7 @@ export function createEmitter<TEvents extends EmitterEvents>(options?: EmitterOp
next,
emit,
clear,
count,
setOptions,
}
}
Expand Down
29 changes: 29 additions & 0 deletions tests/events.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,32 @@ describe('emitter.setOptions', () => {
expectTypeOf<Source>().toEqualTypeOf<Expected>()
})
})

describe('emitter.count', () => {
test('has the correct return type', () => {
const emitter = createEmitter<Events>()
const response = emitter.count()

type Source = typeof response
type Expected = number

expectTypeOf<Source>().toEqualTypeOf<Expected>()
})

test('accepts only valid event names', () => {
const emitter = createEmitter<Events>()

emitter.count('ping')
emitter.count('hello')
emitter.count('user')

// @ts-expect-error - Invalid event name
emitter.count('invalid')
})

test('accepts a global option', () => {
const emitter = createEmitter<Events>()

emitter.count('ping', { global: true })
})
})
18 changes: 18 additions & 0 deletions tests/events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,22 @@ test('next without event returns the global event payload', async () => {
kind: 'hello',
payload: 'world',
})
})

describe('emitter.count', () => {
test('returns the correct number of handlers', () => {
const emitter = createEmitter<{ hello: void, goodbye: void }>()

emitter.on('hello', vi.fn())
emitter.on('goodbye', vi.fn())
emitter.on(vi.fn())

expect(emitter.count()).toBe(1)
expect(emitter.count('hello')).toBe(1)
expect(emitter.count('goodbye')).toBe(1)
expect(emitter.count('hello', { global: true })).toBe(2)
expect(emitter.count('goodbye', { global: true })).toBe(2)
expect(emitter.count('hello', { global: false })).toBe(1)
expect(emitter.count('goodbye', { global: false })).toBe(1)
})
})