Gathering detailed insights and metrics for fsa-emitter
Gathering detailed insights and metrics for fsa-emitter
Gathering detailed insights and metrics for fsa-emitter
Gathering detailed insights and metrics for fsa-emitter
npm install fsa-emitter
Typescript
Module System
Node Version
NPM Version
66.1
Supply Chain
97.8
Quality
75
Maintenance
100
Vulnerability
99.6
License
TypeScript (90.57%)
JavaScript (8.15%)
Shell (1.28%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
1 Stars
147 Commits
2 Watchers
18 Branches
2 Contributors
Updated on Dec 14, 2022
Latest Version
2.0.0
Package Id
fsa-emitter@2.0.0
Unpacked Size
61.94 kB
Size
13.73 kB
File Count
43
NPM Version
8.5.0
Node Version
16.14.2
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
32
EventEmitter in FSA style.
When dealing with event, I find myself need to remember the name of the event, and the parameters each event has.
The person who defines the events and the person who consumes the events can be two different person.
This implicit knowledge coupling relies on communication and documentation that are prone to error, and are not convenient.
This library addresses this issue by emitting and consuming events using a standard format, and provides IDE type support so they can be consumed easily.
One of the benefits of using events is decoupling. Here is one way to organize your code:
1// app.ts 2import { doWork } from './doWork' 3 4const emitter = new Emitter() 5 6doWork({ emitter }) 7 8// doWork.ts 9import { createEvent, Emitter } from 'fsa-emitter' 10 11export const count = createEvent<number>('count') 12 13export function doWork({ emitter }) { 14 emitter.emit(count(1, undefined)) 15} 16 17// in UI 18import { count } from './doWork' 19 20emitter.on(count, payload => { 21 console.log('payload is typed and is a number: ', payload) 22})
1npm install fsa-emitter
Emitter
uses FluxStandardAction
as the standard event format.
Another key difference between Emitter
and NodeJS EventEmitter
is that Emitter
will capture any error thrown in listener and send it to console.error()
.
This avoid any listener code throws error and break the event emitting logic.
To create event, use one of the helper methods below:
1import { 2 createEvent, 3 createScopedCreateEvent, 4 createEventAction, 5 createScopedCreateEventAction, 6 Emitter 7} from 'fsa-emitter' 8 9const count = createEvent<number>('count') 10 11// create scoped event 12const createMyModuleEvent = createScopedCreateEvent('myModule') 13// `scopedCount` will emit FSA with `type: 'myModule/count'` 14const scopedCount = createMyModuleEvent<number>('count') 15 16const add = createAction< 17 /* input */ { a: number, b: number }, 18 /* payload */ number>('add', ({ a, b }) => emit => emit(a + b)) 19 20// create scoped action 21const createMyModuleAction = createScopedCreateEventAction('myModule') 22// `scopedCountAction` will emit FSA with `type: 'myModule/add'` 23const scopedAdd = createMyModuleAction< 24 /* input */ { a: number, b: number }, 25 /* payload */ number>('add', ({ a, b }) => emit => emit(a + b)) 26 27const emitter = new Emitter() 28 29emitter.emit(count(1, undefined)) 30emitter.emit(scopedCount(2, undefined)) 31add(emitter, { a: 1, b: 2 }, undefined) 32scopedAdd(emitter, { a: 1, b: 2 }, undefined)
Note that due to https://github.com/Microsoft/TypeScript/issues/12400,
you need to supply undefined
at where they expect meta
.
To consume the event, use one of the following methods:
1import { createEvent, Emitter } from 'fsa-emitter'
2
3const count = createEvent<number>('count')
4const emitter = new Emitter()
5
6emitter.addListener(count, value => console.info(value))
7emitter.on(count, value => console.info(value))
8
9// Will only listen to the event once
10emitter.once(count, value => console.info(value))
11
12// line up in queue to listen for the event once
13emitter.queue(count, value => console.info(value))
14
15// listen to all events
16emitter.onAny(fsa => console.info(fsa.type, fsa.payload))
17
18// listen to any event that does not have a listener
19emitter.onMissed(fsa => console.info(fsa.type, fsa.payload))
Command
is a simple command pattern that provides a simple way to manage dependencies.
1import { Command, createEvent, Emitter } from 'fsa-emitter' 2 3const count = createEvent<{ n: number }>('count') 4 5class CountCommand extends Command { 6 run(n: number) { 7 while (n) { 8 this.emitter.emit(count({ n }, undefined)) 9 n-- 10 } 11 } 12} 13 14const emitter = new Emitter() 15const cmd = new CountCommand({ emitter }) 16cmd(10)
1import { Command, createEvent, Emitter } from 'fsa-emitter' 2 3const changeHeight = createEvent<{ height: number }>('changeHeight') 4const landed = createEvent('landed') 5 6class FlyCommand extends Command<{ fuel: number }> { 7 fuel: number 8 height = 0 9 run() { 10 while (this.fuel > 0) { 11 this.height += 100 12 this.fuel-- 13 this.emitter.emit(changeHeight({ height: this.height }, undefined)) 14 } 15 const gliding = setInterval(() => { 16 this.height -= 50 17 this.emitter.emit(changeHeight({ height: this.height }, undefined)) 18 if (this.height <= 0) { 19 this.emitter.emit(landed(undefined, undefined)) 20 clearInterval(gliding) 21 } 22 }, 100) 23 } 24} 25 26// `fuel` is in the constructor context 27const fly = new FlyCommand({ emitter: new Emitter(), fuel: 10 }) 28fly.run()
TestEmitter
can be used as a drop in replacement as Emitter
during test.
The difference between TestEmitter
and Emitter
is that TestEmitter
will not capture errors thrown in listeners.
This make it more suitable to use during testing so that you can detect any error thrown during the test.
Also, it provides some additional methods:
1import { TestEmitter, createEvent } from 'fsa-emitter' 2 3const emitter = new TestEmitter() 4const count = createEvent<number>('count') 5emitter.on(count, () => ({})) 6t.false(emitter.listenerCalled(count)) 7 8emitter.emit(count(1, undefined)) 9t.true(emitter.listenerCalled(count)) 10t.true(emitter.listenerCalled(count.type))
1import { TestEmitter, createEvent } from 'fsa-emitter' 2 3const emitter = new TestEmitter() 4const count = createEvent<number>('count') 5const bound = createEvent<number>('bound') 6 7emitter.on(count, () => ({})) 8emitter.on(bound, () => ({})) 9 10emitter.emit(count(1, undefined)) 11 12t.false(emitter.allListenersCalled()) 13 14emitter.emit(bound(1, undefined)) 15 16t.true(emitter.allListenersCalled())
1import { TestEmitter, createEvent } from 'fsa-emitter' 2 3const emitter = new TestEmitter() 4const count = createEvent<number>('count') 5const bound = createEvent<number>('bound') 6 7emitter.on(count, () => ({})) 8 9emitter.listenedTo([count]) // true 10emitter.listenedTo({ count }) // true 11emitter.listenedTo(['count']) // true 12 13emitter.listenedTo([ bound ]) // false 14emitter.listenedTo({ bound }) // false 15emitter.listenedTo([ 'bound' ]) // false
setupCommandTest()
is a simple helper to create a TestEmitter
for the command to run with.
The same completion support is available as in the Command
constructor.
1import { Command, createEvent, setupCommandTest } from 'fsa-emitter' 2 3const count = createEvent<{ n: number }>('count') 4 5class CountCommand extends Command { 6 ... 7} 8 9const { command, emitter } = setupCommandTest(CountCommand) 10 11class FlyCommand extends Command<{ fuel: number }> { 12 ... 13} 14 15// completion is available for `fuel` 16const { command, emitter } = setupCommandTest(FlyCommand, { fuel: 10 })
1# after fork and clone 2npm install 3 4# begin making changes 5git checkout -b <branch> 6npm run watch 7 8# after making change(s) 9git commit -m "<commit message>" 10git push 11 12# create PR
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
security policy file detected
Details
Reason
SAST tool detected but not run on all commits
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
13 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More