@alwatr/signal 0.6.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,112 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [0.6.0](https://github.com/AliMD/alwatr/compare/v0.5.0...v0.6.0) (2022-03-11)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * alalwatr ([898aa6e](https://github.com/AliMD/alwatr/commit/898aa6ed0888eab9265c83b96a50f1b8c216d143))
12
+ * **packages:** duplicate alwatr keyword ([77d4aa2](https://github.com/AliMD/alwatr/commit/77d4aa2105ad47515c3eee251fd6b8c281d0d1fc))
13
+
14
+
15
+
16
+
17
+
18
+ # [0.5.0](https://github.com/AliMD/alwatr/compare/v0.4.0...v0.5.0) (2022-03-11)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **signal:** disabled getter and optional dispatch options ([28ced3d](https://github.com/AliMD/alwatr/commit/28ced3d0c4cdf44fc2aebfab98db0883fc5363fe))
24
+
25
+
26
+ ### Features
27
+
28
+ * **signal:** new SignalInterface ([221701a](https://github.com/AliMD/alwatr/commit/221701a54ea9edda4a3a935a7b098e235ec52691))
29
+
30
+
31
+
32
+
33
+
34
+ # [0.4.0](https://github.com/AliMD/alwatr/compare/v0.3.0...v0.4.0) (2022-03-11)
35
+
36
+ **Note:** Version bump only for package @alwatr/signal
37
+
38
+
39
+
40
+
41
+
42
+ # [0.3.0](https://github.com/AliMD/alwatr/compare/v0.2.1...v0.3.0) (2022-03-06)
43
+
44
+
45
+ ### Bug Fixes
46
+
47
+ * **signal:** signal provider type ([0151c57](https://github.com/AliMD/alwatr/commit/0151c57d9b6d4f7e83bb9b1847ebe0ae53cd8f89))
48
+
49
+
50
+
51
+
52
+
53
+ ## [0.2.1](https://github.com/AliMD/alwatr/compare/v0.2.0...v0.2.1) (2022-03-05)
54
+
55
+
56
+ ### Bug Fixes
57
+
58
+ * **signal:** signal value type issue ([292a4a7](https://github.com/AliMD/alwatr/commit/292a4a7d12a2fd143761e67cd1ecd2e5e40f2ee9))
59
+
60
+
61
+
62
+
63
+
64
+ # [0.2.0](https://github.com/AliMD/alwatr/compare/v0.1.2...v0.2.0) (2022-03-05)
65
+
66
+
67
+ ### Bug Fixes
68
+
69
+ * **router:** rename setSignalProvider callback detail to requestParam ([6e09f87](https://github.com/AliMD/alwatr/commit/6e09f8772d320625fb4c15ccaa0abcfa2932f992))
70
+ * **signal:** fix dispatchSignal value parameters ([4d34cfb](https://github.com/AliMD/alwatr/commit/4d34cfbb5281d5ce4a4f06ddaaf72218dde80cdd))
71
+
72
+
73
+ ### Features
74
+
75
+ * **signal:** add contributors ([64287cd](https://github.com/AliMD/alwatr/commit/64287cd8cea95665a6ed298177df60dadda7642b))
76
+ * **signal:** improve signal provider by dispatch return content ([80c2b27](https://github.com/AliMD/alwatr/commit/80c2b275bcc0521327400c5902f512c778f5eb3f))
77
+
78
+
79
+
80
+
81
+
82
+ ## [0.1.2](https://github.com/AliMD/alwatr/compare/v0.1.1...v0.1.2) (2022-03-03)
83
+
84
+ **Note:** Version bump only for package @alwatr/signal
85
+
86
+
87
+
88
+
89
+
90
+ ## [0.1.1](https://github.com/AliMD/alwatr/compare/v0.1.0...v0.1.1) (2022-03-03)
91
+
92
+ ### Bug Fixes
93
+
94
+ * **packages:** add publish config to public ([9cb3710](https://github.com/AliMD/alwatr/commit/9cb37106b5a35d24d5195ff54232e5769ccc034e))
95
+
96
+ # 0.1.0 (2022-03-02)
97
+
98
+ ### Bug Fixes
99
+
100
+ * **signal:** AlwatrRequestSignals global type ([228e333](https://github.com/AliMD/alwatr/commit/228e3333326b23df51e7834872daf1349826bf09))
101
+
102
+ ### Features
103
+
104
+ * **signal:** addSignalListener ([e7c5742](https://github.com/AliMD/alwatr/commit/e7c57427ef11e2624eb9a52a166720b1a3c5f66a))
105
+ * **signal:** getSignalObject ([b38954c](https://github.com/AliMD/alwatr/commit/b38954cf4ae1c24eaaa79ecf513995a4678814ee))
106
+ * **signal:** impeliment addSignalProvider, waitForSignal, hasSignalDispatchedBefore, expireSignal ([e0b4d78](https://github.com/AliMD/alwatr/commit/e0b4d7831764d4454591f5105c5512e1657a63e5))
107
+ * **signal:** impeliment dispatchSignal ([cb2dfbe](https://github.com/AliMD/alwatr/commit/cb2dfbe23ea751cba93cb1f6516cd2bfa2ecb18e))
108
+ * **signal:** ListenerObject, SignalObject types ([36d8a33](https://github.com/AliMD/alwatr/commit/36d8a336760bba3808cfd26a28e4d24a31c95f8f))
109
+ * **signal:** make new package for manage signals ([5bf82b3](https://github.com/AliMD/alwatr/commit/5bf82b3f05abc89102634e9b864d81b5b5af527e))
110
+ * **signal:** register to alwatr meta ([9c850e8](https://github.com/AliMD/alwatr/commit/9c850e8df787aa44d289929dc65439e921982dce))
111
+ * **signal:** removeSignalListener ([0088a52](https://github.com/AliMD/alwatr/commit/0088a5269ccce8b50a50e444695c81654fda70ff))
112
+ * **signal:** requestSignal ([111ab5a](https://github.com/AliMD/alwatr/commit/111ab5a1436bc380f5121ef8c130da7010258d90))
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 S. Ali Mihandoost
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # @alwatr/signal
2
+
3
+ Elegant powerful event system for handle global signals and states written in tiny TypeScript module.
4
+
5
+ Every signal has own value and can be used as a advance **state management** like redux and recoil without the complexities and unnecessary facilities of those libraries.
6
+
7
+ ## Example usage
8
+
9
+ ### Add your signal name to global `AlwatrSignals` type helper
10
+
11
+ ```ts
12
+ declare global {
13
+ /**
14
+ * Global signals value type registry.
15
+ */
16
+ interface AlwatrSignals {
17
+ readonly 'content-change': Record<string, number>;
18
+ }
19
+
20
+ /**
21
+ * Global request signal parameters types.
22
+ */
23
+ interface AlwatrRequestSignals {
24
+ readonly 'content-change': number;
25
+ }
26
+ }
27
+ ```
28
+
29
+ ### Dispatch signal with value
30
+
31
+ ```ts
32
+ import {SignalInterface} from 'https://esm.run/@alwatr/signal';
33
+
34
+ const contentChangeSignal1 = new SignalInterface('content-change');
35
+
36
+ contentChangeSignal1.dispatch({a:1, b:2});
37
+
38
+ contentChangeSignal1.dispatch({a:2, b:3});
39
+
40
+ // Multiple dispatch debounced and last value dispatched after an animate frame.
41
+ contentChangeSignal1.dispatch({a:3, b:4});
42
+ ```
43
+
44
+ ### Receive the signal value
45
+
46
+ ```ts
47
+ import {SignalInterface} from 'https://esm.run/@alwatr/signal';
48
+
49
+ const contentChangeSignal2 = new SignalInterface('content-change'); // Same share signal as contentChangeSignal1
50
+
51
+ contentChangeSignal2.addListener((content) => {
52
+ console.log(content); // {a:3, b:4}
53
+ });
54
+ ```
55
+
56
+ ## API
57
+
58
+ ### Prepare
59
+
60
+ #### `new SignalInterface(signal-name)`
61
+
62
+ ```ts
63
+ import {SignalInterface} from 'https://esm.run/@alwatr/signal';
64
+
65
+ const contentChangeSignal = new SignalInterface('content-change');
66
+ ```
67
+
68
+ ### `name`
69
+
70
+ Get signal name.
71
+
72
+ Example:
73
+
74
+ ```ts
75
+ console.log(contentChangeSignal.name); // 'content-change'
76
+ ```
77
+
78
+ ### `value`
79
+
80
+ Get last dispatched signal value or undefined.
81
+
82
+ Example:
83
+
84
+ ```ts
85
+ if (contentChangeSignal.dispatched) {
86
+ const content = contentChangeSignal.value!;
87
+ ...
88
+ }
89
+ ```
90
+
91
+ ### `dispatched`
92
+
93
+ Check signal dispatched before or not!
94
+
95
+ Example
96
+
97
+ ```ts
98
+ if(contentChangeSignal.dispatched) {
99
+ // contentChangeSignal.value exist.
100
+ }
101
+ ```
102
+
103
+ ### `disabled`
104
+
105
+ Disable signal, all dispatch's ignored (just value updated) and no more listeners will be called.
106
+
107
+ Example:
108
+
109
+ ```ts
110
+ contentChangeSignal.disabled = true;
111
+ ```
112
+
113
+ ### `expire()`
114
+
115
+ Expire the signal by clear last dispatched value.
116
+
117
+ dispatched and receivePrevious etc not work until new signal.
118
+
119
+ Example:
120
+
121
+ ```ts
122
+ contentChangeSignal.dispatched; // true
123
+ contentChangeSignal.expire();
124
+ contentChangeSignal.value; // undefined
125
+ contentChangeSignal.dispatched; // false
126
+ ```
127
+
128
+ ### `setProvider(provider)`
129
+
130
+ Define signal provider, which will be called when signal requested (addRequestSignalListener).
131
+
132
+ Example:
133
+
134
+ ```ts
135
+ contentChangeSignal.setProvider(async (requestParam) => {
136
+ const content = await fetchNewContent(requestParam);
137
+ if (content != null) {
138
+ return content; // Dispatch signal 'content-change' with content.
139
+ }
140
+ else {
141
+ // dispatch new signal: 'content-not-found'
142
+ }
143
+ });
144
+ ```
145
+
146
+ ### `request(requestParam)`
147
+
148
+ Dispatch request signal and wait for answer (wait for new signal dispatched).
149
+
150
+ Resolved with signal value when new signal received (getNextSignalValue).
151
+
152
+ Example:
153
+
154
+ ```ts
155
+ // dispatch request signal and wait for answer (wait for NEW signal).
156
+ const newContent = await contentChangeSignal.request({foo: 'bar'});
157
+ ```
158
+
159
+ ### `getNextSignalValue()`
160
+
161
+ Resolved with signal value when new signal received.
162
+
163
+ Example:
164
+
165
+ ```ts
166
+ // Wait for NEW signal received.
167
+ const newContent = await contentChangeSignal.getNextSignalValue();
168
+ ```
169
+
170
+ ### `getSignalValue()`
171
+
172
+ Resolved with signal value when signal is ready.
173
+
174
+ Get signal value from last dispatched signal (if any) or wait for new signal received.
175
+
176
+ Example:
177
+
178
+ ```ts
179
+ // get signal value from last dispatched signal (if any) or wait new signal received.
180
+ const content = await contentChangeSignal.getSignalValue();
181
+ ```
182
+
183
+ ### `dispatch(signalValue)`
184
+
185
+ Dispatch signal to all listeners.
186
+
187
+ Example:
188
+
189
+ ```ts
190
+ contentChangeSignal.dispatch(content);
191
+ ```
192
+
193
+ ### `addListener(listener)`
194
+
195
+ Add new listener to the signal.
196
+
197
+ Example:
198
+
199
+ ```ts
200
+ const listener = contentChangeSignal.addListener((content) => console.log(content));
201
+ ```
202
+
203
+ ### `removeListener(listener)`
204
+
205
+ Remove listener from specific signal.
206
+
207
+ Example:
208
+
209
+ ```ts
210
+ const listenerId = contentChangeSignal.addListener((content) => console.log(content));
211
+ ...
212
+ contentChangeSignal.removeListener(listenerId);
213
+ ```
package/core.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type { DispatchOptions, ListenerCallback, ListenerOptions, SignalObject, SignalProvider, SignalProviderOptions } from './type';
2
+ export declare const logger: import("logger/type").Logger;
3
+ /**
4
+ * Access to signal option, Make new signal with default options if not exist.
5
+ */
6
+ export declare function __getSignalObject<SignalName extends keyof AlwatrSignals>(signalName: SignalName): SignalObject<SignalName>;
7
+ /**
8
+ * Add new listener to specific signal.
9
+ *
10
+ * Example:
11
+ *
12
+ * ```ts
13
+ * const listener = addSignalListener('content-change', (content) => console.log(content));
14
+ * ```
15
+ */
16
+ export declare function _addSignalListener<SignalName extends keyof AlwatrSignals>(signalName: SignalName, signalCallback: ListenerCallback<SignalName>, options?: ListenerOptions): symbol;
17
+ /**
18
+ * Remove listener from specific signal.
19
+ *
20
+ * Example:
21
+ *
22
+ * ```ts
23
+ * const listener = addSignalListener('content-change', ...);
24
+ * removeSignalListener('content-change', listener);
25
+ * ```
26
+ */
27
+ export declare function _removeSignalListener<SignalName extends keyof AlwatrSignals>(signalName: SignalName, listenerId: symbol): void;
28
+ /**
29
+ * Dispatch signal to all listeners.
30
+ *
31
+ * @example
32
+ * dispatchSignal('content-change', content);
33
+ */
34
+ export declare function _dispatchSignal<SignalName extends keyof AlwatrSignals>(signalName: SignalName, value: AlwatrSignals[SignalName], options?: DispatchOptions): void;
35
+ /**
36
+ * Define signal provider, which will be called when signal requested (addRequestSignalListener).
37
+ *
38
+ * Example:
39
+ *
40
+ * ```ts
41
+ * setSignalProvider('content-change', async (requestParam) => {
42
+ * const content = await fetchNewContent(requestParam);
43
+ * if (content != null) {
44
+ * return content; // dispatchSignal('content-change', content);
45
+ * }
46
+ * else {
47
+ * dispatchSignal('content-not-found');
48
+ * }
49
+ * }
50
+ * ```
51
+ */
52
+ export declare function _setSignalProvider<SignalName extends keyof AlwatrRequestSignals>(signalName: SignalName, signalProvider: SignalProvider<SignalName>, options?: SignalProviderOptions): symbol;
53
+ //# sourceMappingURL=core.d.ts.map
package/core.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["src/core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAEhB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,qBAAqB,EAEtB,MAAM,QAAQ,CAAC;AAEhB,eAAO,MAAM,MAAM,8BAAgC,CAAC;AAYpD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,SAAS,MAAM,aAAa,EACpE,UAAU,EAAE,UAAU,GACvB,YAAY,CAAC,UAAU,CAAC,CAU1B;AA0BD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,SAAS,MAAM,aAAa,EACrE,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,gBAAgB,CAAC,UAAU,CAAC,EAC5C,OAAO,CAAC,EAAE,eAAe,GAC1B,MAAM,CA8CR;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,SAAS,MAAM,aAAa,EACxE,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,MAAM,GACnB,IAAI,CAON;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,SAAS,MAAM,aAAa,EAClE,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAChC,OAAO,CAAC,EAAE,eAAe,GAC1B,IAAI,CAqBN;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,SAAS,MAAM,oBAAoB,EAC5E,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,CAAC,UAAU,CAAC,EAC1C,OAAO,CAAC,EAAE,qBAAqB,GAChC,MAAM,CAuBR"}
package/core.js ADDED
@@ -0,0 +1,180 @@
1
+ import { createLogger, alwatrRegisteredList } from '@alwatr/logger';
2
+ export const logger = createLogger('alwatr/signal');
3
+ alwatrRegisteredList.push({
4
+ name: '@alwatr/signal',
5
+ version: '{{ALWATR_VERSION}}',
6
+ });
7
+ /**
8
+ * Signal stack database.
9
+ */
10
+ const _signalStack = {};
11
+ /**
12
+ * Access to signal option, Make new signal with default options if not exist.
13
+ */
14
+ export function __getSignalObject(signalName) {
15
+ if (!_signalStack[signalName]) {
16
+ _signalStack[signalName] = {
17
+ name: signalName,
18
+ disabled: false,
19
+ debounced: false,
20
+ listenerList: [],
21
+ };
22
+ }
23
+ return _signalStack[signalName];
24
+ }
25
+ function __callListeners(signal) {
26
+ logger.logMethodArgs('_callListeners', { signalName: signal.name, signalValue: signal.value });
27
+ if (signal.value === undefined) {
28
+ logger.accident('_callListeners', 'no_signal_value', 'signal must have a value', { signalName: signal.name });
29
+ return;
30
+ }
31
+ for (const listener of signal.listenerList) {
32
+ if (listener.disabled)
33
+ continue;
34
+ try {
35
+ const ret = listener.callback(signal.value);
36
+ if (ret instanceof Promise) {
37
+ ret.catch((err) => logger.error('_callListeners', 'call_listener_failed', err.stack || err, { signalName: signal.name }));
38
+ }
39
+ }
40
+ catch (err) {
41
+ logger.error('_callListeners', 'call_listener_failed', err.stack || err, { signalName: signal.name });
42
+ }
43
+ if (listener.once)
44
+ _removeSignalListener(signal.name, listener.id);
45
+ }
46
+ }
47
+ /**
48
+ * Add new listener to specific signal.
49
+ *
50
+ * Example:
51
+ *
52
+ * ```ts
53
+ * const listener = addSignalListener('content-change', (content) => console.log(content));
54
+ * ```
55
+ */
56
+ export function _addSignalListener(signalName, signalCallback, options) {
57
+ var _a, _b;
58
+ logger.logMethodArgs('addSignalListener', { signalName, options });
59
+ const signal = __getSignalObject(signalName);
60
+ const listener = {
61
+ id: Symbol('Alwatr signal listener for ' + signalName),
62
+ once: (_a = options === null || options === void 0 ? void 0 : options.once) !== null && _a !== void 0 ? _a : false,
63
+ disabled: (_b = options === null || options === void 0 ? void 0 : options.disabled) !== null && _b !== void 0 ? _b : false,
64
+ callback: signalCallback,
65
+ };
66
+ let callbackCalled = false;
67
+ // Run callback for old dispatch signal
68
+ if (signal.value !== undefined) {
69
+ if ((options === null || options === void 0 ? void 0 : options.receivePrevious) === 'Immediate') {
70
+ logger.incident('addSignalListener', 'call_signal_callback', 'run callback with previous signal value!', { signalName, mode: 'Immediate' });
71
+ try {
72
+ signalCallback(signal.value);
73
+ }
74
+ catch (err) {
75
+ logger.error('addSignalListener', 'call_signal_callback_failed', err.stack || err, { signalName });
76
+ }
77
+ callbackCalled = true;
78
+ }
79
+ else if ((options === null || options === void 0 ? void 0 : options.receivePrevious) === true) {
80
+ requestAnimationFrame(() => {
81
+ if (signal.value !== undefined) {
82
+ logger.incident('addSignalListener', 'call_signal_callback', 'run callback with previous signal value!', { signalName, mode: 'Delay' });
83
+ signalCallback(signal.value);
84
+ }
85
+ });
86
+ callbackCalled = true; // must be outside of requestAnimationFrame.
87
+ }
88
+ }
89
+ // if once then must remove listener after fist callback called! then why push it to listenerList?!
90
+ if (!((options === null || options === void 0 ? void 0 : options.once) && callbackCalled)) {
91
+ if (options === null || options === void 0 ? void 0 : options.priority) {
92
+ signal.listenerList.unshift(listener);
93
+ }
94
+ else {
95
+ signal.listenerList.push(listener);
96
+ }
97
+ }
98
+ return listener.id;
99
+ }
100
+ /**
101
+ * Remove listener from specific signal.
102
+ *
103
+ * Example:
104
+ *
105
+ * ```ts
106
+ * const listener = addSignalListener('content-change', ...);
107
+ * removeSignalListener('content-change', listener);
108
+ * ```
109
+ */
110
+ export function _removeSignalListener(signalName, listenerId) {
111
+ logger.logMethodArgs('_removeSignalListener', signalName);
112
+ const signal = __getSignalObject(signalName);
113
+ const listenerIndex = signal.listenerList.findIndex((_listener) => _listener.id === listenerId);
114
+ if (listenerIndex !== -1) {
115
+ signal.listenerList.splice(listenerIndex, 1);
116
+ }
117
+ }
118
+ /**
119
+ * Dispatch signal to all listeners.
120
+ *
121
+ * @example
122
+ * dispatchSignal('content-change', content);
123
+ */
124
+ export function _dispatchSignal(signalName, value, options) {
125
+ logger.logMethodArgs('dispatchSignal', { signalName, value, options });
126
+ const signal = __getSignalObject(signalName);
127
+ // set value before check signal.debounced for act like throttle (call listeners with last dispatch value).
128
+ signal.value = value;
129
+ if (signal.disabled)
130
+ return; // signal is disabled.
131
+ if ((options === null || options === void 0 ? void 0 : options.debounce) && signal.debounced)
132
+ return; // last dispatch in progress.
133
+ if (!(options === null || options === void 0 ? void 0 : options.debounce)) {
134
+ // call listeners immediately.
135
+ __callListeners(signal);
136
+ return;
137
+ }
138
+ // else: call listeners in next frame.
139
+ signal.debounced = true;
140
+ requestAnimationFrame(() => {
141
+ __callListeners(signal);
142
+ signal.debounced = false;
143
+ });
144
+ }
145
+ /**
146
+ * Define signal provider, which will be called when signal requested (addRequestSignalListener).
147
+ *
148
+ * Example:
149
+ *
150
+ * ```ts
151
+ * setSignalProvider('content-change', async (requestParam) => {
152
+ * const content = await fetchNewContent(requestParam);
153
+ * if (content != null) {
154
+ * return content; // dispatchSignal('content-change', content);
155
+ * }
156
+ * else {
157
+ * dispatchSignal('content-not-found');
158
+ * }
159
+ * }
160
+ * ```
161
+ */
162
+ export function _setSignalProvider(signalName, signalProvider, options) {
163
+ var _a;
164
+ logger.logMethodArgs('setSignalProvider', { signalName, options });
165
+ // @TODO: refactor with removeSignalProvider
166
+ const signal = __getSignalObject(`request-${signalName}`);
167
+ if (signal.listenerList.length > 0) {
168
+ logger.accident('setSignalProvider', 'signal_provider_already_set', 'another provider defined and will removed', { signalName });
169
+ signal.listenerList = [];
170
+ }
171
+ const _callback = async (requestParam) => {
172
+ var _a;
173
+ const signalValue = await signalProvider(requestParam);
174
+ if (signalValue !== undefined) { // null can be a valid value.
175
+ _dispatchSignal(signalName, signalValue, { debounce: (_a = options === null || options === void 0 ? void 0 : options.debounce) !== null && _a !== void 0 ? _a : true });
176
+ }
177
+ };
178
+ return _addSignalListener(`request-${signalName}`, _callback, { receivePrevious: (_a = options === null || options === void 0 ? void 0 : options.receivePrevious) !== null && _a !== void 0 ? _a : true });
179
+ }
180
+ //# sourceMappingURL=core.js.map
package/core.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["src/core.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@alwatr/signal",
3
+ "version": "0.6.0",
4
+ "description": "Elegant powerful event system for handle global signals and states written in tiny TypeScript module.",
5
+ "keywords": [
6
+ "signal",
7
+ "typescript",
8
+ "esm",
9
+ "alwatr"
10
+ ],
11
+ "main": "signal.js",
12
+ "type": "module",
13
+ "types": "signal.d.ts",
14
+ "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com> (https://ali.mihandoost.com)",
15
+ "contributors": [
16
+ "MohammadMahdi Zamanian <mm25zamanian@gmail.com>"
17
+ ],
18
+ "license": "MIT",
19
+ "files": [
20
+ "**/*.js",
21
+ "**/*.d.ts",
22
+ "**/*.map",
23
+ "**/*.html",
24
+ "**/*.md"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/AliMD/alwatr",
32
+ "directory": "package/signal"
33
+ },
34
+ "homepage": "https://github.com/AliMD/alwatr/tree/main/package/signal#readme",
35
+ "bugs": {
36
+ "url": "https://github.com/AliMD/alwatr/issues"
37
+ },
38
+ "dependencies": {
39
+ "@alwatr/logger": "^0.6.0",
40
+ "tslib": "^2.3.1"
41
+ },
42
+ "gitHead": "8ed13adce22d7bb0cc24eb17c9f8ecfb6bbe8553"
43
+ }
package/signal.d.ts ADDED
@@ -0,0 +1,168 @@
1
+ import type { ListenerOptions, DispatchOptions, ListenerCallback, SignalProvider, SignalProviderOptions } from './type';
2
+ /**
3
+ * Signal API interface as a remote controller.
4
+ */
5
+ export declare class SignalInterface<SignalName extends keyof AlwatrSignals> {
6
+ private _signal;
7
+ private _logger;
8
+ constructor(signalName: SignalName);
9
+ /**
10
+ * Get signal name.
11
+ *
12
+ * Example:
13
+ *
14
+ * ```ts
15
+ * console.log(contentChangeSignal.name);
16
+ * ```
17
+ */
18
+ get name(): SignalName;
19
+ /**
20
+ * Get last dispatched signal value or undefined.
21
+ *
22
+ * Example:
23
+ *
24
+ * ```ts
25
+ * const contentChangeSignal = new SignalInterface('content-change');
26
+ * if (contentChangeSignal.dispatched) {
27
+ * const content = contentChangeSignal.value!;
28
+ * ...
29
+ * }
30
+ * ```
31
+ */
32
+ get value(): AlwatrSignals[SignalName] | undefined;
33
+ /**
34
+ * Check signal dispatched before or not!
35
+ *
36
+ * Example
37
+ *
38
+ * ```ts
39
+ * const contentChangeSignal = new SignalInterface('content-change');
40
+ * if(contentChangeSignal.dispatched) {
41
+ * // contentChangeSignal.value exist.
42
+ * }
43
+ * ```
44
+ */
45
+ get dispatched(): boolean;
46
+ /**
47
+ * Disable signal, all dispatch's ignored (just value updated) and no more listeners will be called.
48
+ *
49
+ * Example:
50
+ *
51
+ * ```ts
52
+ * contentChangeSignal.disabled = true;
53
+ * ```
54
+ */
55
+ get disabled(): boolean;
56
+ set disabled(disabled: boolean);
57
+ /**
58
+ * Expire the signal by clear last dispatched value.
59
+ *
60
+ * dispatched and receivePrevious etc not work until new signal.
61
+ *
62
+ * Example:
63
+ *
64
+ * ```ts
65
+ * const contentChangeSignal = new SignalInterface('content-change');
66
+ * contentChangeSignal.dispatched; // true
67
+ * contentChangeSignal.expire();
68
+ * contentChangeSignal.value; // undefined
69
+ * contentChangeSignal.dispatched; // false
70
+ * ```
71
+ */
72
+ expire(): void;
73
+ /**
74
+ * Define signal provider, which will be called when signal requested (addRequestSignalListener).
75
+ *
76
+ * Example:
77
+ *
78
+ * ```ts
79
+ * const contentChangeSignal = new SignalInterface('content-change');
80
+ * contentChangeSignal.setProvider(async (requestParam) => {
81
+ * const content = await fetchNewContent(requestParam);
82
+ * if (content != null) {
83
+ * return content; // Dispatch signal 'content-change' with content.
84
+ * }
85
+ * else {
86
+ * // dispatch new signal: 'content-not-found'
87
+ * }
88
+ * });
89
+ * ```
90
+ */
91
+ setProvider(signalProvider: SignalProvider<SignalName>, options?: SignalProviderOptions): symbol;
92
+ /**
93
+ * Dispatch request signal and wait for answer (wait for new signal dispatched).
94
+ *
95
+ * Resolved with signal value when new signal received (getNextSignalValue).
96
+ *
97
+ * Example:
98
+ *
99
+ * ```ts
100
+ * const contentChangeSignal = new SignalInterface('content-change');
101
+ * // dispatch request signal and wait for answer (wait for NEW signal).
102
+ * const newContent = await contentChangeSignal.request({foo: 'bar'});
103
+ * ```
104
+ */
105
+ request(requestParam: AlwatrRequestSignals[SignalName]): Promise<AlwatrSignals[SignalName]>;
106
+ /**
107
+ * Resolved with signal value when new signal received.
108
+ *
109
+ * Example:
110
+ *
111
+ * ```ts
112
+ * const contentChangeSignal = new SignalInterface('content-change');
113
+ * // Wait for NEW signal received.
114
+ * const newContent = await contentChangeSignal.getNextSignalValue();
115
+ * ```
116
+ */
117
+ getNextSignalValue(): Promise<AlwatrSignals[SignalName]>;
118
+ /**
119
+ * Resolved with signal value when signal is ready.
120
+ *
121
+ * Get signal value from last dispatched signal (if any) or wait for new signal received.
122
+ *
123
+ * Example:
124
+ *
125
+ * ```ts
126
+ * const contentChangeSignal = new SignalInterface('content-change');
127
+ * // get signal value from last dispatched signal (if any) or wait new signal received.
128
+ * const content = await contentChangeSignal.getSignalValue();
129
+ * ```
130
+ */
131
+ getSignalValue(): Promise<AlwatrSignals[SignalName]>;
132
+ /**
133
+ * Dispatch signal to all listeners.
134
+ *
135
+ * Example:
136
+ *
137
+ * ```ts
138
+ * const contentChangeSignal = new SignalInterface('content-change');
139
+ * contentChangeSignal.dispatch(content);
140
+ * ```
141
+ */
142
+ dispatch(signalValue: AlwatrSignals[SignalName], options?: DispatchOptions): void;
143
+ /**
144
+ * Add new listener to the signal.
145
+ *
146
+ * Example:
147
+ *
148
+ * ```ts
149
+ * const contentChangeSignal = new SignalInterface('content-change');
150
+ * const listener = contentChangeSignal.addListener((content) => console.log(content));
151
+ * ```
152
+ */
153
+ addListener(listener: ListenerCallback<SignalName>, options?: ListenerOptions): symbol;
154
+ /**
155
+ * Remove listener from specific signal.
156
+ *
157
+ * Example:
158
+ *
159
+ * ```ts
160
+ * const contentChangeSignal = new SignalInterface('content-change');
161
+ * const listenerId = contentChangeSignal.addListener((content) => console.log(content));
162
+ * ...
163
+ * contentChangeSignal.removeListener(listenerId);
164
+ * ```
165
+ */
166
+ removeListener(listenerId: symbol): void;
167
+ }
168
+ //# sourceMappingURL=signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["src/signal.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACtB,MAAM,QAAQ,CAAC;AAEhB;;GAEG;AACH,qBAAa,eAAe,CAAC,UAAU,SAAS,MAAM,aAAa;IACjE,OAAO,CAAC,OAAO,CAAC;IAChB,OAAO,CAAC,OAAO,CAAC;gBAEJ,UAAU,EAAE,UAAU;IAKlC;;;;;;;;OAQG;IACH,IAAI,IAAI,IAAI,UAAU,CAErB;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,KAAK,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG,SAAS,CAEjD;IAED;;;;;;;;;;;OAWG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;;;;OAQG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAE7B;IAED;;;;;;;;;;;;;;OAcG;IACH,MAAM,IAAI,IAAI;IAKd;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,cAAc,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM;IAOhG;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,YAAY,EAAE,oBAAoB,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAS3F;;;;;;;;;;OAUG;IACH,kBAAkB,IAAI,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAWxD;;;;;;;;;;;;OAYG;IACH,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IASpD;;;;;;;;;OASG;IACH,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAKjF;;;;;;;;;OASG;IACH,WAAW,CAAC,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM;IAKtF;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAIzC"}
package/signal.js ADDED
@@ -0,0 +1,221 @@
1
+ import { createLogger } from '@alwatr/logger';
2
+ import { __getSignalObject, _removeSignalListener, _setSignalProvider, _dispatchSignal, _addSignalListener, } from './core';
3
+ /**
4
+ * Signal API interface as a remote controller.
5
+ */
6
+ export class SignalInterface {
7
+ constructor(signalName) {
8
+ this._logger = createLogger('Signal:' + signalName);
9
+ this._signal = __getSignalObject(signalName);
10
+ }
11
+ /**
12
+ * Get signal name.
13
+ *
14
+ * Example:
15
+ *
16
+ * ```ts
17
+ * console.log(contentChangeSignal.name);
18
+ * ```
19
+ */
20
+ get name() {
21
+ return this._signal.name;
22
+ }
23
+ /**
24
+ * Get last dispatched signal value or undefined.
25
+ *
26
+ * Example:
27
+ *
28
+ * ```ts
29
+ * const contentChangeSignal = new SignalInterface('content-change');
30
+ * if (contentChangeSignal.dispatched) {
31
+ * const content = contentChangeSignal.value!;
32
+ * ...
33
+ * }
34
+ * ```
35
+ */
36
+ get value() {
37
+ return this._signal.value;
38
+ }
39
+ /**
40
+ * Check signal dispatched before or not!
41
+ *
42
+ * Example
43
+ *
44
+ * ```ts
45
+ * const contentChangeSignal = new SignalInterface('content-change');
46
+ * if(contentChangeSignal.dispatched) {
47
+ * // contentChangeSignal.value exist.
48
+ * }
49
+ * ```
50
+ */
51
+ get dispatched() {
52
+ return 'value' in this._signal;
53
+ }
54
+ /**
55
+ * Disable signal, all dispatch's ignored (just value updated) and no more listeners will be called.
56
+ *
57
+ * Example:
58
+ *
59
+ * ```ts
60
+ * contentChangeSignal.disabled = true;
61
+ * ```
62
+ */
63
+ get disabled() {
64
+ return this._signal.disabled;
65
+ }
66
+ set disabled(disabled) {
67
+ this._signal.disabled = disabled;
68
+ }
69
+ /**
70
+ * Expire the signal by clear last dispatched value.
71
+ *
72
+ * dispatched and receivePrevious etc not work until new signal.
73
+ *
74
+ * Example:
75
+ *
76
+ * ```ts
77
+ * const contentChangeSignal = new SignalInterface('content-change');
78
+ * contentChangeSignal.dispatched; // true
79
+ * contentChangeSignal.expire();
80
+ * contentChangeSignal.value; // undefined
81
+ * contentChangeSignal.dispatched; // false
82
+ * ```
83
+ */
84
+ expire() {
85
+ this._logger.logMethod('expire');
86
+ delete this._signal.value;
87
+ }
88
+ /**
89
+ * Define signal provider, which will be called when signal requested (addRequestSignalListener).
90
+ *
91
+ * Example:
92
+ *
93
+ * ```ts
94
+ * const contentChangeSignal = new SignalInterface('content-change');
95
+ * contentChangeSignal.setProvider(async (requestParam) => {
96
+ * const content = await fetchNewContent(requestParam);
97
+ * if (content != null) {
98
+ * return content; // Dispatch signal 'content-change' with content.
99
+ * }
100
+ * else {
101
+ * // dispatch new signal: 'content-not-found'
102
+ * }
103
+ * });
104
+ * ```
105
+ */
106
+ setProvider(signalProvider, options) {
107
+ this._logger.logMethodArgs('setProvider', { options });
108
+ return _setSignalProvider(this.name, signalProvider, options);
109
+ }
110
+ // @TODO: removeProvider(signalName): void
111
+ /**
112
+ * Dispatch request signal and wait for answer (wait for new signal dispatched).
113
+ *
114
+ * Resolved with signal value when new signal received (getNextSignalValue).
115
+ *
116
+ * Example:
117
+ *
118
+ * ```ts
119
+ * const contentChangeSignal = new SignalInterface('content-change');
120
+ * // dispatch request signal and wait for answer (wait for NEW signal).
121
+ * const newContent = await contentChangeSignal.request({foo: 'bar'});
122
+ * ```
123
+ */
124
+ request(requestParam) {
125
+ this._logger.logMethodArgs('request', { requestParam });
126
+ _dispatchSignal(`request-${this.name}`, requestParam);
127
+ return this.getNextSignalValue();
128
+ }
129
+ /**
130
+ * Resolved with signal value when new signal received.
131
+ *
132
+ * Example:
133
+ *
134
+ * ```ts
135
+ * const contentChangeSignal = new SignalInterface('content-change');
136
+ * // Wait for NEW signal received.
137
+ * const newContent = await contentChangeSignal.getNextSignalValue();
138
+ * ```
139
+ */
140
+ getNextSignalValue() {
141
+ this._logger.logMethod('getNextSignalValue');
142
+ return new Promise((resolve) => {
143
+ this.addListener(resolve, {
144
+ once: true,
145
+ priority: true,
146
+ receivePrevious: false,
147
+ });
148
+ });
149
+ }
150
+ /**
151
+ * Resolved with signal value when signal is ready.
152
+ *
153
+ * Get signal value from last dispatched signal (if any) or wait for new signal received.
154
+ *
155
+ * Example:
156
+ *
157
+ * ```ts
158
+ * const contentChangeSignal = new SignalInterface('content-change');
159
+ * // get signal value from last dispatched signal (if any) or wait new signal received.
160
+ * const content = await contentChangeSignal.getSignalValue();
161
+ * ```
162
+ */
163
+ getSignalValue() {
164
+ this._logger.logMethod('getSignalValue');
165
+ if (this._signal.value !== undefined) {
166
+ return Promise.resolve(this._signal.value);
167
+ }
168
+ else {
169
+ return this.getNextSignalValue();
170
+ }
171
+ }
172
+ /**
173
+ * Dispatch signal to all listeners.
174
+ *
175
+ * Example:
176
+ *
177
+ * ```ts
178
+ * const contentChangeSignal = new SignalInterface('content-change');
179
+ * contentChangeSignal.dispatch(content);
180
+ * ```
181
+ */
182
+ dispatch(signalValue, options) {
183
+ this._logger.logMethodArgs('dispatch', { signalValue, options });
184
+ _dispatchSignal(this._signal.name, signalValue, options);
185
+ }
186
+ /**
187
+ * Add new listener to the signal.
188
+ *
189
+ * Example:
190
+ *
191
+ * ```ts
192
+ * const contentChangeSignal = new SignalInterface('content-change');
193
+ * const listener = contentChangeSignal.addListener((content) => console.log(content));
194
+ * ```
195
+ */
196
+ addListener(listener, options) {
197
+ this._logger.logMethodArgs('addListener', { listener, options });
198
+ return _addSignalListener(this._signal.name, listener, options);
199
+ }
200
+ /**
201
+ * Remove listener from specific signal.
202
+ *
203
+ * Example:
204
+ *
205
+ * ```ts
206
+ * const contentChangeSignal = new SignalInterface('content-change');
207
+ * const listenerId = contentChangeSignal.addListener((content) => console.log(content));
208
+ * ...
209
+ * contentChangeSignal.removeListener(listenerId);
210
+ * ```
211
+ */
212
+ removeListener(listenerId) {
213
+ this._logger.logMethod('removeListener');
214
+ _removeSignalListener(this._signal.name, listenerId);
215
+ }
216
+ }
217
+ // @TODO: getSignalOptions(signalName);
218
+ // @TODO: getListenerOptions(listenerId);
219
+ // @TODO: setSignalOptions(signalName, {...});
220
+ // @TODO: setListenerOptions(listenerId, {...});
221
+ //# sourceMappingURL=signal.js.map
package/signal.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal.js","sourceRoot":"","sources":["src/signal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,GACnB,MAAM,QAAQ,CAAC;AAUhB;;GAEG;AACH,MAAM,OAAO,eAAe;IAI1B,YAAY,UAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;OAWG;IACH,IAAI,UAAU;QACZ,OAAO,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;IACjC,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC/B,CAAC;IACD,IAAI,QAAQ,CAAC,QAAiB;QAC5B,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACnC,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,MAAM;QACJ,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,cAA0C,EAAE,OAA+B;QACrF,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC;QACrD,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED,0CAA0C;IAE1C;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,YAA8C;QACpD,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,EAAE,EAAC,YAAY,EAAC,CAAC,CAAC;QACtD,eAAe,CACb,WAAW,IAAI,CAAC,IAAI,EAA2B,EAC/C,YAAoD,CACrD,CAAC;QACF,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACnC,CAAC;IAED;;;;;;;;;;OAUG;IACH,kBAAkB;QAChB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;gBACxB,IAAI,EAAE,IAAI;gBACV,QAAQ,EAAE,IAAI;gBACd,eAAe,EAAE,KAAK;aACvB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,cAAc;QACZ,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE;YACpC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SAC5C;aAAM;YACL,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;SAClC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,QAAQ,CAAC,WAAsC,EAAE,OAAyB;QACxE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,EAAE,EAAC,WAAW,EAAE,OAAO,EAAC,CAAC,CAAC;QAC/D,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED;;;;;;;;;OASG;IACH,WAAW,CAAC,QAAsC,EAAE,OAAyB;QAC3E,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,EAAC,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAC;QAC/D,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;IAED;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,UAAkB;QAC/B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACzC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACvD,CAAC;CACF;AAED,uCAAuC;AACvC,yCAAyC;AACzC,8CAA8C;AAC9C,gDAAgD"}
package/type.d.ts ADDED
@@ -0,0 +1,131 @@
1
+ declare global {
2
+ /**
3
+ * Global signals value type registry.
4
+ */
5
+ interface AlwatrSignals {
6
+ readonly 'easter-egg': number;
7
+ }
8
+ /**
9
+ * Global request signal parameters types.
10
+ */
11
+ interface AlwatrRequestSignals {
12
+ readonly 'easter-egg': number;
13
+ }
14
+ }
15
+ /**
16
+ * addSignalListener options type
17
+ */
18
+ export interface ListenerOptions {
19
+ /**
20
+ * If true, the listener will be called only once.
21
+ * @default false
22
+ */
23
+ once?: boolean;
24
+ /**
25
+ * If true, the listener will be called before other.
26
+ * @default false
27
+ */
28
+ priority?: boolean;
29
+ /**
30
+ * If true, the listener will be defined disabled by default.
31
+ *
32
+ * @default false
33
+ */
34
+ disabled?: boolean;
35
+ /**
36
+ * Calling this listener (callback) with preview signal value (if dispatched before).
37
+ * If Immediate, the listener will be called immediately without any debounce for preview signal.
38
+ *
39
+ * @default true
40
+ */
41
+ receivePrevious?: boolean | 'Immediate';
42
+ }
43
+ /**
44
+ * dispatchSignal options type
45
+ */
46
+ export interface DispatchOptions {
47
+ /**
48
+ * If true, the dispatch will be send after animation frame debounce.
49
+ * If false, every signal is matter and count.
50
+ * tips: debounce work like throttle this means listeners call with last dispatch value.
51
+ *
52
+ * @default true
53
+ */
54
+ debounce?: boolean;
55
+ }
56
+ export interface SignalProviderOptions {
57
+ /**
58
+ * Calling signal provider (request signal callback) with preview signal value (if dispatched before).
59
+ * If Immediate, the listener will be called immediately without any debounce for preview signal.
60
+ *
61
+ * @default true
62
+ */
63
+ receivePrevious?: boolean | 'Immediate';
64
+ /**
65
+ * If true, the dispatch will be send after animation frame debounce.
66
+ * If false, every signal is matter and count.
67
+ * tips: debounce work like throttle this means listeners call with last dispatch value.
68
+ *
69
+ * @default true
70
+ */
71
+ debounce?: boolean;
72
+ }
73
+ /**
74
+ * Signal listeners callback function type.
75
+ */
76
+ export declare type ListenerCallback<SignalName extends keyof AlwatrSignals> = (signalValue: AlwatrSignals[SignalName]) => void | Promise<void>;
77
+ /**
78
+ * Signal provider function type used to setSignalProvider.
79
+ */
80
+ export declare type SignalProvider<SignalName extends keyof AlwatrRequestSignals> = (requestParam: AlwatrRequestSignals[SignalName]) => AlwatrSignals[SignalName] | void | Promise<AlwatrSignals[SignalName] | void>;
81
+ /**
82
+ * Signal listeners object in database.
83
+ */
84
+ export interface ListenerObject<SignalName extends keyof AlwatrSignals> {
85
+ /**
86
+ * Listener symbol id (unique).
87
+ */
88
+ id: symbol;
89
+ /**
90
+ * If true, the listener will be called only once and removed automatically after first call
91
+ */
92
+ once: boolean;
93
+ /**
94
+ * If true, the listener will be disabled.
95
+ */
96
+ disabled: boolean;
97
+ callback: ListenerCallback<SignalName>;
98
+ }
99
+ /**
100
+ * Signal object in database.
101
+ */
102
+ export interface SignalObject<SignalName extends keyof AlwatrSignals> {
103
+ /**
104
+ * Signal name for direct access.
105
+ */
106
+ name: SignalName;
107
+ /**
108
+ * Last dispatched value.
109
+ */
110
+ value?: AlwatrSignals[SignalName];
111
+ /**
112
+ * If true, the signal is disabled.
113
+ */
114
+ disabled: boolean;
115
+ /**
116
+ * Dispatches debounced (delayed).
117
+ * Internal use case for debounce dispatch signal.
118
+ */
119
+ debounced: boolean;
120
+ /**
121
+ * Signal listeners list.
122
+ */
123
+ listenerList: Array<ListenerObject<SignalName>>;
124
+ }
125
+ /**
126
+ * Signal stack database.
127
+ */
128
+ export declare type SignalStack = {
129
+ [SignalName in keyof AlwatrSignals]?: SignalObject<SignalName>;
130
+ };
131
+ //# sourceMappingURL=type.d.ts.map
package/type.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["src/type.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,aAAa;QACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;KAC/B;IAED;;OAEG;IACF,UAAU,oBAAoB;QAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;KAC/B;CACF;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACF,eAAe,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAEzC;;;;;;OAMG;IACJ,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,oBAAY,gBAAgB,CAAC,UAAU,SAAS,MAAM,aAAa,IACjE,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnE;;GAEG;AACH,oBAAY,cAAc,CAAC,UAAU,SAAS,MAAM,oBAAoB,IACtE,CAAC,YAAY,EAAE,oBAAoB,CAAC,UAAU,CAAC,KAC7C,aAAa,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,UAAU,SAAS,MAAM,aAAa;IAEpE;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,UAAU,SAAS,MAAM,aAAa;IAElE;;OAEG;IACH,IAAI,EAAE,UAAU,CAAC;IAEjB;;OAEG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAElC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;CACjD;AAED;;GAEG;AACH,oBAAY,WAAW,GAAG;KACvB,UAAU,IAAI,MAAM,aAAa,CAAC,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC;CAC/D,CAAA"}
package/type.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=type.js.map
package/type.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.js","sourceRoot":"","sources":["src/type.ts"],"names":[],"mappings":""}