easy-signal 1.0.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -11
- package/index.d.ts +31 -5
- package/index.js +48 -7
- package/index.ts +64 -12
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Easy Signal
|
|
2
2
|
|
|
3
|
-
A simple interface for creating a defined event or action that can be triggered
|
|
3
|
+
A simple interface for creating a defined event or action that can be triggered and listened to by any number of
|
|
4
|
+
subscribers. Producing a single function that can be used to subscribe to the events, subscribe to errors, and dispatch
|
|
5
|
+
events and errors.
|
|
6
|
+
|
|
7
|
+
Full type safety with TypeScript providing good autocomplete.
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
@@ -10,9 +14,13 @@ npm install easy-signal
|
|
|
10
14
|
|
|
11
15
|
## Usage
|
|
12
16
|
|
|
13
|
-
A signal is a
|
|
17
|
+
A signal is a function that represents a single event. The function can be used to subscribe to be notified of the
|
|
18
|
+
events as well as to trigger them.
|
|
14
19
|
|
|
15
|
-
Signals offer similar functionality as the browser's `eventDispatcher` API, but rather than a general API for any event,
|
|
20
|
+
Signals offer similar functionality as the browser's `eventDispatcher` API, but rather than a general API for any event,
|
|
21
|
+
each event would use its own signal. This allows each signal to have a specific function signature as opposed to the
|
|
22
|
+
browser's generic `event` object. This is a great system in TypeScript being able to see the exact data each event
|
|
23
|
+
produces.
|
|
16
24
|
|
|
17
25
|
### Basic Usage
|
|
18
26
|
|
|
@@ -21,9 +29,13 @@ Signals offer similar functionality as the browser's `eventDispatcher` API, but
|
|
|
21
29
|
import { signal } from 'easy-signal';
|
|
22
30
|
|
|
23
31
|
// Create the signal and export it for use. Optionally provide the subscriber signature
|
|
24
|
-
export const onSecond = signal<
|
|
32
|
+
export const onSecond = signal<number>();
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
// Passing a non-function value will dispatch the event
|
|
35
|
+
setInterval(() => {
|
|
36
|
+
const currentSecond = Math.floor(Date.now() / 1000);
|
|
37
|
+
onSecond(currentSecond);
|
|
38
|
+
});
|
|
27
39
|
```
|
|
28
40
|
|
|
29
41
|
```ts
|
|
@@ -35,15 +47,47 @@ const unsubscribe = onSecond(seconds => {
|
|
|
35
47
|
});
|
|
36
48
|
```
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
Errors may also be listened to from the signal by passing `ForErrors` as the second parameter when adding the listener
|
|
51
|
+
and errors may be dispatched by passing an Error object to the signal method.
|
|
40
52
|
|
|
41
53
|
```ts
|
|
42
|
-
import { signal } from 'easy-signal';
|
|
54
|
+
import { signal, ForErrors } from 'easy-signal';
|
|
43
55
|
|
|
44
56
|
const dataStream = signal();
|
|
45
|
-
dataStream.error = signal();
|
|
46
57
|
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
dataStream(data => console.log('data is:' data));
|
|
59
|
+
dataStream(error => console.log('Error is:' error), ForErrors);
|
|
60
|
+
|
|
61
|
+
stream.on('data', obj => dataStream(obj));
|
|
62
|
+
stream.on('error', err => dataStream(err));
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
To get a subscriber-only method for external use, pass in the `GetOnSignal` constant.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { signal, GetOnSignal } from 'easy-signal';
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
function getMyAPI() {
|
|
72
|
+
const doSomething = signal();
|
|
73
|
+
|
|
74
|
+
// doSomething() will trigger subscribers that were added in onSomething(...). This protects the signal from being
|
|
75
|
+
// triggered/dispatched outside of `getMyAPI`. Sometimes you may want more control to prevent just anyone from
|
|
76
|
+
// triggering the event.
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
onSomething: doSomething(GetOnSignal),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
To clear the listeners from the signal, pass in the `ClearSignal` constant.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { signal, ClearSignal } from 'easy-signal';
|
|
89
|
+
|
|
90
|
+
const onSomething = signal();
|
|
91
|
+
|
|
92
|
+
onSomething(ClearSignal); // clears signal
|
|
49
93
|
```
|
package/index.d.ts
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
declare type Args<T> = T extends (...args: infer A) => any ? A : never;
|
|
2
2
|
export declare type Subscriber = (...args: any[]) => any;
|
|
3
|
-
export declare type
|
|
4
|
-
export declare type
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export declare type ErrorSubscriber = (error: Error) => any;
|
|
4
|
+
export declare type Unsubscriber = () => void;
|
|
5
|
+
export declare type OnSignal<T extends Subscriber = Subscriber> = {
|
|
6
|
+
(subscriber: T): Unsubscriber;
|
|
7
|
+
(errorListener: ErrorSubscriber, what: typeof ForErrors): Unsubscriber;
|
|
8
8
|
};
|
|
9
|
+
export declare type Signal<T extends Subscriber = Subscriber> = OnSignal<T> & {
|
|
10
|
+
(...args: Args<T>): void;
|
|
11
|
+
(data: Error): void;
|
|
12
|
+
(data: typeof ClearSignal): void;
|
|
13
|
+
(data: typeof GetOnSignal): OnSignal<T>;
|
|
14
|
+
};
|
|
15
|
+
export declare const ClearSignal: unique symbol;
|
|
16
|
+
export declare const GetOnSignal: unique symbol;
|
|
17
|
+
export declare const ForErrors: unique symbol;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a signal, a function that can be used to subscribe to events. The signal can be called with a subscriber
|
|
20
|
+
* function, which will be called when the signal is dispatched. The signal can also be called with data, which will
|
|
21
|
+
* dispatch to all subscribers. An optional second argument can be passed to subscribe to errors instead. When the
|
|
22
|
+
* signal is called with an instance of Error, it will dispatch to all error listeners.
|
|
23
|
+
* The signal can also be called with `ClearSignal`, which will clear all subscribers.
|
|
24
|
+
* @example
|
|
25
|
+
* const onLoad = signal();
|
|
26
|
+
*
|
|
27
|
+
* // Subscribe to data
|
|
28
|
+
* onLoad((data) => console.log('loaded', data));
|
|
29
|
+
* onLoad((error) => console.error('error', error), true);
|
|
30
|
+
*
|
|
31
|
+
* // Dispatch data
|
|
32
|
+
* onLoad('data'); // logs 'loaded data'
|
|
33
|
+
* onLoad(new Error('error')); // logs 'error Error: error'
|
|
34
|
+
*/
|
|
9
35
|
export declare function signal<T extends Subscriber = Subscriber>(): Signal<T>;
|
|
10
36
|
export {};
|
package/index.js
CHANGED
|
@@ -1,10 +1,51 @@
|
|
|
1
|
+
export const ClearSignal = Symbol();
|
|
2
|
+
export const GetOnSignal = Symbol();
|
|
3
|
+
export const ForErrors = Symbol();
|
|
4
|
+
/**
|
|
5
|
+
* Creates a signal, a function that can be used to subscribe to events. The signal can be called with a subscriber
|
|
6
|
+
* function, which will be called when the signal is dispatched. The signal can also be called with data, which will
|
|
7
|
+
* dispatch to all subscribers. An optional second argument can be passed to subscribe to errors instead. When the
|
|
8
|
+
* signal is called with an instance of Error, it will dispatch to all error listeners.
|
|
9
|
+
* The signal can also be called with `ClearSignal`, which will clear all subscribers.
|
|
10
|
+
* @example
|
|
11
|
+
* const onLoad = signal();
|
|
12
|
+
*
|
|
13
|
+
* // Subscribe to data
|
|
14
|
+
* onLoad((data) => console.log('loaded', data));
|
|
15
|
+
* onLoad((error) => console.error('error', error), true);
|
|
16
|
+
*
|
|
17
|
+
* // Dispatch data
|
|
18
|
+
* onLoad('data'); // logs 'loaded data'
|
|
19
|
+
* onLoad(new Error('error')); // logs 'error Error: error'
|
|
20
|
+
*/
|
|
1
21
|
export function signal() {
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
22
|
+
const subscribers = new Set();
|
|
23
|
+
const errorListeners = new Set();
|
|
24
|
+
function onSignal(subscriber, what) {
|
|
25
|
+
const listeners = what === ForErrors ? errorListeners : subscribers;
|
|
26
|
+
listeners.add(subscriber);
|
|
27
|
+
return () => {
|
|
28
|
+
listeners.delete(subscriber);
|
|
29
|
+
};
|
|
6
30
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
31
|
+
function signal(...args) {
|
|
32
|
+
const arg = args[0];
|
|
33
|
+
if (typeof arg === 'function') {
|
|
34
|
+
return onSignal(arg);
|
|
35
|
+
}
|
|
36
|
+
else if (arg === ClearSignal) {
|
|
37
|
+
subscribers.clear();
|
|
38
|
+
errorListeners.clear();
|
|
39
|
+
}
|
|
40
|
+
else if (arg === GetOnSignal) {
|
|
41
|
+
return onSignal;
|
|
42
|
+
}
|
|
43
|
+
else if (arg instanceof Error) {
|
|
44
|
+
errorListeners.forEach(listener => listener(arg));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
subscribers.forEach(listener => listener(...args));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return signal;
|
|
10
51
|
}
|
package/index.ts
CHANGED
|
@@ -1,23 +1,75 @@
|
|
|
1
1
|
type Args<T> = T extends (...args: infer A) => any ? A : never;
|
|
2
2
|
export type Subscriber = (...args: any[]) => any;
|
|
3
|
-
export type
|
|
3
|
+
export type ErrorSubscriber = (error: Error) => any;
|
|
4
|
+
export type Unsubscriber = () => void;
|
|
4
5
|
|
|
5
|
-
export type
|
|
6
|
-
(
|
|
7
|
-
|
|
8
|
-
error?: Signal<(err: Error) => any>;
|
|
6
|
+
export type OnSignal<T extends Subscriber = Subscriber> = {
|
|
7
|
+
(subscriber: T): Unsubscriber;
|
|
8
|
+
(errorListener: ErrorSubscriber, what: typeof ForErrors): Unsubscriber;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export type Signal<T extends Subscriber = Subscriber> = OnSignal<T> & {
|
|
12
|
+
(...args: Args<T>): void;
|
|
13
|
+
(data: Error): void;
|
|
14
|
+
(data: typeof ClearSignal): void;
|
|
15
|
+
(data: typeof GetOnSignal): OnSignal<T>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const ClearSignal = Symbol();
|
|
19
|
+
export const GetOnSignal = Symbol();
|
|
20
|
+
export const ForErrors = Symbol();
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a signal, a function that can be used to subscribe to events. The signal can be called with a subscriber
|
|
25
|
+
* function, which will be called when the signal is dispatched. The signal can also be called with data, which will
|
|
26
|
+
* dispatch to all subscribers. An optional second argument can be passed to subscribe to errors instead. When the
|
|
27
|
+
* signal is called with an instance of Error, it will dispatch to all error listeners.
|
|
28
|
+
* The signal can also be called with `ClearSignal`, which will clear all subscribers.
|
|
29
|
+
* @example
|
|
30
|
+
* const onLoad = signal();
|
|
31
|
+
*
|
|
32
|
+
* // Subscribe to data
|
|
33
|
+
* onLoad((data) => console.log('loaded', data));
|
|
34
|
+
* onLoad((error) => console.error('error', error), true);
|
|
35
|
+
*
|
|
36
|
+
* // Dispatch data
|
|
37
|
+
* onLoad('data'); // logs 'loaded data'
|
|
38
|
+
* onLoad(new Error('error')); // logs 'error Error: error'
|
|
39
|
+
*/
|
|
11
40
|
export function signal<T extends Subscriber = Subscriber>(): Signal<T> {
|
|
12
|
-
const
|
|
41
|
+
const subscribers = new Set<Subscriber>();
|
|
42
|
+
const errorListeners = new Set<Subscriber>();
|
|
13
43
|
|
|
14
|
-
function
|
|
15
|
-
listeners
|
|
16
|
-
|
|
44
|
+
function onSignal(subscriber: T | ErrorSubscriber, what?: typeof ForErrors): Unsubscriber {
|
|
45
|
+
const listeners = what === ForErrors ? errorListeners : subscribers;
|
|
46
|
+
listeners.add(subscriber);
|
|
47
|
+
return () => {
|
|
48
|
+
listeners.delete(subscriber);
|
|
49
|
+
};
|
|
17
50
|
}
|
|
18
51
|
|
|
19
|
-
|
|
20
|
-
|
|
52
|
+
function signal(...args: Args<T>): void;
|
|
53
|
+
function signal(error: Error): void;
|
|
54
|
+
function signal(data: typeof ClearSignal): void;
|
|
55
|
+
function signal(data: typeof GetOnSignal): OnSignal<T>;
|
|
56
|
+
function signal(subscriber: T): Unsubscriber;
|
|
57
|
+
function signal(errorListener: Subscriber, what: typeof ForErrors): Unsubscriber;
|
|
58
|
+
function signal(...args: any[]): Unsubscriber | OnSignal<T> | void {
|
|
59
|
+
const arg = args[0];
|
|
60
|
+
if (typeof arg === 'function') {
|
|
61
|
+
return onSignal(arg);
|
|
62
|
+
} else if (arg === ClearSignal) {
|
|
63
|
+
subscribers.clear();
|
|
64
|
+
errorListeners.clear();
|
|
65
|
+
} else if (arg === GetOnSignal) {
|
|
66
|
+
return onSignal as OnSignal<T>;
|
|
67
|
+
} else if (arg instanceof Error) {
|
|
68
|
+
errorListeners.forEach(listener => listener(arg));
|
|
69
|
+
} else {
|
|
70
|
+
subscribers.forEach(listener => listener(...args));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
21
73
|
|
|
22
|
-
return
|
|
74
|
+
return signal;
|
|
23
75
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "easy-signal",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A tiny (
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "A tiny (25 LOC), simple utility for alerting subscribers when an event happens, allowing for error handling and clearing.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsc",
|