-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(signal): make new package for manage signals
- Loading branch information
Showing
5 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# @vatr/signal | ||
|
||
Manage and control all signals in your project. | ||
|
||
## Example usage | ||
|
||
```js | ||
import { ... } from 'https://esm.run/@vatr/signal'; | ||
... | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "@vatr/signal", | ||
"version": "0.0.0", | ||
"description": "Manage and control all signals in your project.", | ||
"main": "signal.js", | ||
"type": "module", | ||
"types": "signal.d.ts", | ||
"author": "S. Ali Mihandoost <[email protected]>", | ||
"license": "MIT", | ||
"files": [ | ||
"**/*.js", | ||
"**/*.d.ts", | ||
"**/*.map", | ||
"**/*.html", | ||
"**/*.md" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/AliMD/vatr", | ||
"directory": "package/signal" | ||
}, | ||
"dependencies": { | ||
"tslib": "^2.3.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import {createLogger} from '@vatr/logger'; | ||
import type {ListenerOptions, DispatchOptions, ListenerCallback, RequestSignalOptions} from './type'; | ||
|
||
const log = createLogger('vatr/signal'); | ||
|
||
/** | ||
* Add new listener to specific signal. | ||
* | ||
* @example | ||
* const listener = addSignalListener('route-change', money => console.log(money)); | ||
*/ | ||
export function addSignalListener<SignalName extends keyof VatrSignals>( | ||
signalName: SignalName, | ||
signalCallback: ListenerCallback<VatrSignals[SignalName]>, | ||
options?: Partial<ListenerOptions>, | ||
): symbol { | ||
log('addSignalListener: %o', {signalName, options}); | ||
|
||
// return _addSignalListener(signalName, signalCallback as ListenerCallback, { | ||
// once: false, | ||
// capture: false, | ||
// disabled: false, | ||
// ...options, | ||
// }); | ||
} | ||
|
||
/** | ||
* Remove listener from specific signal. | ||
* | ||
* @example | ||
* const listener = addSignalListener('content-change', ...); | ||
* removeSignalListener('content-change', listener); | ||
*/ | ||
export function removeSignalListener<SignalName extends keyof VatrSignals>( | ||
signalName: SignalName, | ||
listenerId: symbol, | ||
): void { | ||
log('removeSignalListener: %s', signalName); | ||
} | ||
|
||
/** | ||
* Dispatch signal to all listeners. | ||
* | ||
* @example | ||
* dispatchSignal('content-change', content); | ||
*/ | ||
export function dispatchSignal<SignalName extends keyof VatrSignals>( | ||
signalName: SignalName, | ||
value: VatrSignals[SignalName], | ||
options?: Partial<DispatchOptions>, | ||
): void { | ||
log('dispatchSignal: %s => %o', signalName, value); | ||
} | ||
|
||
/** | ||
* Resolved with signal value when signal is ready base on requested options. | ||
* By default, dispatch request signal and wait for answer (wait new signal dispatched). | ||
* | ||
* @example | ||
* // dispatch request signal and wait for answer (wait for NEW signal). | ||
* const newContent = await requestSignal('content-change', {foo: 'bar'}); | ||
*/ | ||
export async function requestSignal<SignalName extends keyof VatrRequestSignals>( | ||
signalName: SignalName, | ||
requestParam: VatrRequestSignals[SignalName], | ||
): Promise<VatrSignals[SignalName]> { | ||
log('requestSignal: %s', signalName); | ||
|
||
return Promise.resolve(undefined); | ||
} | ||
|
||
/** | ||
* Define signal provider, which will be called when signal requested. | ||
* | ||
* @example | ||
* defineSignalProvider('content-change', async (requestParam) => { | ||
* const content = await fetchNewContent(requestParam); | ||
* if (content != null) { | ||
* return content; // dispatchSignal('content-change', content); | ||
* } | ||
* else { | ||
* dispatchSignal('content-not-found'); | ||
* } | ||
* } | ||
*/ | ||
export function defineSignalProvider<SignalName extends keyof VatrSignals>( | ||
signalName: SignalName, | ||
signalCallback: ListenerCallback<VatrSignals[SignalName]>, | ||
): symbol { | ||
log('addSignalListener: %o', {signalName, options}); | ||
|
||
// return _addSignalListener(signalName, signalCallback as ListenerCallback, { | ||
// once: false, | ||
// capture: false, | ||
// disabled: false, | ||
// ...options, | ||
// }); | ||
} | ||
|
||
|
||
/** | ||
* Resolved with signal value when signal is ready base on requested options. | ||
* By default, wait new signal received. | ||
* | ||
* @param receivePrevious If true, get signal value from last dispatched signal (if any) or wait new signal received. | ||
* | ||
* @example | ||
* // Wait for NEW signal received. | ||
* const newContent = await waitForSignal('content-change'); | ||
* // get signal value from last dispatched signal (if any) or wait new signal received. | ||
* const route = await waitForSignal('route-change', {receivePrevious: true}); | ||
*/ | ||
export async function waitForSignal<SignalName extends keyof VatrSignals>( | ||
signalName: SignalName, | ||
receivePrevious?: boolean, | ||
): Promise<VatrSignals[SignalName]> { | ||
log('requestSignal: %s', signalName); | ||
|
||
return Promise.resolve(undefined); | ||
} | ||
|
||
/** | ||
* Check signal dispatched before or not! | ||
* | ||
* @example | ||
* if(hasSignalDispatchedBefore('easter-egg')) { ... } | ||
*/ | ||
export function hasSignalDispatchedBefore<SignalName extends keyof VatrSignals>(signalName: SignalName): boolean { | ||
const dispatched = true; | ||
log('hasSignalDispatchedBefore: %s => %s', signalName, dispatched); | ||
return dispatched; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
declare global | ||
{ | ||
/** | ||
* Global signal registry. | ||
*/ | ||
interface VatrSignals | ||
{ | ||
readonly 'easter-egg': void; | ||
} | ||
|
||
interface VatrRequestSignals | ||
{ | ||
readonly 'easter-egg': number; | ||
} | ||
} | ||
|
||
export interface ListenerOptions | ||
{ | ||
/** | ||
* If true, the listener will be called only once. | ||
* @default false | ||
*/ | ||
once: boolean; | ||
|
||
/** | ||
* If true, the listener will be called before other. | ||
* @default false | ||
* @deprecated @TODO Please implement this feature. | ||
*/ | ||
priority: boolean; | ||
|
||
/** | ||
* If true, the listener will be defined disabled by default. | ||
* | ||
* @default false | ||
*/ | ||
disabled: boolean; | ||
|
||
/** | ||
* If true, the listener will be called in animation frame debounce. | ||
* If false, every signal is matter and count. | ||
* | ||
* @default true or dispatch signal config. | ||
* @deprecated @TODO Please implement this feature. | ||
*/ | ||
debounce: boolean; | ||
|
||
/** | ||
* Calling this listener (callback) with preview signal value (if dispatched before). | ||
* If Immediate, the listener will be called immediately without any debounce for preview signal. | ||
* | ||
* @default true | ||
*/ | ||
receivePrevious: boolean | 'Immediate'; | ||
} | ||
|
||
export interface DispatchOptions | ||
{ | ||
/** | ||
* If true, the dispatch will be send after animation frame debounce. | ||
* If false, every signal is matter and count. | ||
* | ||
* @default true | ||
*/ | ||
debounce: boolean; | ||
} | ||
|
||
export type ListenerCallback<T = unknown> = (detail: T) => void | Promise<void>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"composite": true, | ||
"tsBuildInfoFile": ".tsbuildinfo", | ||
"rootDir": "src", | ||
"outDir": ".", | ||
}, | ||
// files, include and exclude from the inheriting config are always overwritten. | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [], | ||
"references": [ | ||
{ "path": "../logger" }, | ||
] | ||
} |