vivth 1.1.1 → 1.2.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/.vivth-temp/README.src.md +35 -0
- package/README.md +1243 -441
- package/README.src.md +5 -2
- package/bun.lock +228 -0
- package/index.mjs +22 -9
- package/package.json +6 -3
- package/src/bundler/CompileJS.mjs +258 -0
- package/src/bundler/CreateESPlugin.mjs +24 -0
- package/src/bundler/EsBundler.mjs +27 -13
- package/src/bundler/FSInline.mjs +57 -0
- package/src/bundler/FSInlineAnalyzer.mjs +197 -0
- package/src/bundler/FSInlineBundled.mjs +34 -0
- package/src/bundler/adds/ToBundledJSPlugin.mjs +77 -0
- package/src/bundler/adds/externals.mjs +8 -0
- package/src/bundler/adds/pluginVivthBundle.mjs +5 -0
- package/src/class/Console.mjs +48 -27
- package/src/class/Derived.mjs +55 -7
- package/src/class/Effect.mjs +100 -39
- package/src/class/EnvSignal.mjs +5 -5
- package/src/class/EventSignal.mjs +55 -5
- package/src/class/FileSafe.mjs +124 -0
- package/src/class/ListDerived.mjs +6 -3
- package/src/class/ListSignal.mjs +11 -11
- package/src/class/LitExp.mjs +405 -0
- package/src/class/Paths.mjs +39 -4
- package/src/class/QChannel.mjs +79 -28
- package/src/class/SafeExit.mjs +31 -11
- package/src/class/Setup.mjs +12 -7
- package/src/class/Signal.mjs +26 -24
- package/src/class/WorkerMainThread.mjs +108 -135
- package/src/class/WorkerMainThreadBundled.mjs +216 -0
- package/src/class/WorkerThread.mjs +40 -31
- package/src/common/Base64URL.mjs +10 -5
- package/src/common/Base64URLFromFile.mjs +24 -0
- package/src/common/keys.mjs +3 -0
- package/src/doc/JSautoDOC.mjs +32 -56
- package/src/doc/parsedFile.mjs +37 -36
- package/src/function/CreateImmutable.mjs +9 -9
- package/src/function/EventCheck.mjs +2 -2
- package/src/function/EventObject.mjs +5 -5
- package/src/function/GetRuntime.mjs +38 -0
- package/src/function/IsAsync.mjs +2 -2
- package/src/function/LazyFactory.mjs +13 -13
- package/src/function/Timeout.mjs +2 -2
- package/src/function/Try.mjs +17 -12
- package/src/function/TryAsync.mjs +5 -5
- package/src/function/TrySync.mjs +5 -5
- package/src/function/TsToMjs.mjs +5 -4
- package/src/types/LitExpKeyType.mjs +5 -0
- package/src/types/QCBReturn.mjs +1 -1
- package/src/types/Runtime.mjs +7 -0
- package/types/dev/fsInline.d.mts +1 -0
- package/types/dev/test.d.mts +1 -0
- package/types/dev/testWorker.d.mts +7 -0
- package/types/dev/testbundle.d.mts +1 -0
- package/types/dev/workerThreadClass.d.mts +13 -0
- package/types/index.d.mts +18 -9
- package/types/src/bundler/CompileJS.d.mts +78 -0
- package/types/src/bundler/CreateESPlugin.d.mts +17 -0
- package/types/src/bundler/EsBundler.d.mts +33 -4
- package/types/src/bundler/FSInline.d.mts +43 -0
- package/types/src/bundler/FSInlineAnalyzer.d.mts +36 -0
- package/types/src/bundler/FSInlineBundled.d.mts +22 -0
- package/types/src/bundler/adds/ToBundledJSPlugin.d.mts +16 -0
- package/types/src/bundler/adds/externals.d.mts +1 -0
- package/types/src/bundler/adds/pluginVivthBundle.d.mts +1 -0
- package/types/src/class/Console.d.mts +36 -5
- package/types/src/class/Derived.d.mts +132 -5
- package/types/src/class/Effect.d.mts +106 -7
- package/types/src/class/EnvSignal.d.mts +8 -8
- package/types/src/class/EventSignal.d.mts +151 -7
- package/types/src/class/FileSafe.d.mts +90 -0
- package/types/src/class/ListDerived.d.mts +8 -5
- package/types/src/class/ListSignal.d.mts +123 -18
- package/types/src/class/LitExp.d.mts +361 -0
- package/types/src/class/Paths.d.mts +30 -4
- package/types/src/class/QChannel.d.mts +69 -22
- package/types/src/class/SafeExit.d.mts +24 -9
- package/types/src/class/Setup.d.mts +13 -10
- package/types/src/class/Signal.d.mts +73 -17
- package/types/src/class/WorkerMainThread.d.mts +47 -39
- package/types/src/class/WorkerMainThreadBundled.d.mts +85 -0
- package/types/src/class/WorkerThread.d.mts +34 -26
- package/types/src/common/Base64URL.d.mts +22 -1
- package/types/src/common/Base64URLFromFile.d.mts +16 -0
- package/types/src/common/keys.d.mts +1 -0
- package/types/src/doc/JSautoDOC.d.mts +3 -19
- package/types/src/doc/parsedFile.d.mts +72 -13
- package/types/src/function/CreateImmutable.d.mts +27 -2
- package/types/src/function/EventCheck.d.mts +15 -0
- package/types/src/function/EventObject.d.mts +17 -2
- package/types/src/function/GetRuntime.d.mts +2 -0
- package/types/src/function/IsAsync.d.mts +18 -0
- package/types/src/function/LazyFactory.d.mts +35 -2
- package/types/src/function/Timeout.d.mts +16 -0
- package/types/src/function/Try.d.mts +52 -1
- package/types/src/function/TryAsync.d.mts +22 -1
- package/types/src/function/TrySync.d.mts +16 -1
- package/types/src/function/TsToMjs.d.mts +19 -0
- package/types/src/types/LitExpKeyType.d.mts +1 -0
- package/types/src/types/QCBReturn.d.mts +1 -1
- package/types/src/types/Runtime.d.mts +1 -0
- package/dev/index.mjs +0 -28
- package/src/bundler/CompileMJS.mjs +0 -110
- package/src/function/WriteFileSafe.mjs +0 -37
- package/types/src/bundler/A.d.mts +0 -1
- package/types/src/bundler/CompileMJS.d.mts +0 -8
- package/types/src/function/WriteFileSafe.d.mts +0 -2
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { basename, extname } from 'node:path';
|
|
4
|
+
import { readFile, exists } from 'node:fs/promises';
|
|
5
|
+
import { CreateESPlugin } from '../CreateESPlugin.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* - generate `esbuild.Plugin` for changing dev time file into runtime file;
|
|
10
|
+
* - on using esbuild with this plugin, it will replace any module that have similiar file name but ended with Bundled(before extname);
|
|
11
|
+
* >- works on `.mts`|`.ts`|`.mjs`|`.cjs`|`.js`;
|
|
12
|
+
* >- `anyFileName.mjs` -> seek for and use `anyFileNameBundled.mjs`, if not found use `anyFileName.mjs`;
|
|
13
|
+
* @param {string} includedInPath
|
|
14
|
+
* - is generalized, you can freely uses forward or backward slash;
|
|
15
|
+
* @returns {ReturnType<CreateESPlugin>}
|
|
16
|
+
* @example
|
|
17
|
+
* import { ToBundledJSPlugin } from 'vivth';
|
|
18
|
+
*
|
|
19
|
+
* export const myBundledPlugin = ToBundledJSPlugin('/myProjectName/src/');
|
|
20
|
+
*/
|
|
21
|
+
export function ToBundledJSPlugin(includedInPath) {
|
|
22
|
+
const filter = new RegExp(includedInPath.replace(/[\\/]/g, '[\\\\/]'), '');
|
|
23
|
+
return CreateESPlugin(`ToBundledJSPlugin:${includedInPath}`, (build) => {
|
|
24
|
+
build.onLoad({ filter }, async (args) => {
|
|
25
|
+
const filePath = args.path;
|
|
26
|
+
const fileExt = extname(filePath);
|
|
27
|
+
/**
|
|
28
|
+
* @type {'js'|'ts'}
|
|
29
|
+
*/
|
|
30
|
+
let loader;
|
|
31
|
+
switch (fileExt) {
|
|
32
|
+
case '.mts':
|
|
33
|
+
case '.ts':
|
|
34
|
+
loader = 'ts';
|
|
35
|
+
break;
|
|
36
|
+
case '.mjs':
|
|
37
|
+
case '.cjs':
|
|
38
|
+
case '.js':
|
|
39
|
+
default:
|
|
40
|
+
loader = 'js';
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
const originalContent = (await readFile(filePath)).toString('utf-8');
|
|
44
|
+
if (!loader) {
|
|
45
|
+
return {
|
|
46
|
+
contents: originalContent,
|
|
47
|
+
loader,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (filePath.endsWith(`Bundled${fileExt}`)) {
|
|
51
|
+
return {
|
|
52
|
+
contents: originalContent,
|
|
53
|
+
loader,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const originalBaseName = basename(filePath);
|
|
57
|
+
const originalFileName = originalBaseName.replace(fileExt, '');
|
|
58
|
+
const realRef = `${originalFileName}Bundled`;
|
|
59
|
+
const runtimeFile = filePath.replace(
|
|
60
|
+
new RegExp(`${originalBaseName}\$`.replace('.', '\\.'), ''),
|
|
61
|
+
`${realRef}${fileExt}`
|
|
62
|
+
);
|
|
63
|
+
const isExist = await exists(runtimeFile);
|
|
64
|
+
if (!isExist) {
|
|
65
|
+
return {
|
|
66
|
+
contents: originalContent,
|
|
67
|
+
loader,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const contents = (await readFile(runtimeFile)).toString('utf-8');
|
|
71
|
+
return {
|
|
72
|
+
contents,
|
|
73
|
+
loader,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
package/src/class/Console.mjs
CHANGED
|
@@ -2,61 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @description
|
|
5
|
-
* - class with static methods to print to standard console with
|
|
5
|
+
* - class with static methods to print to standard console with bare minimum ANSI styles;
|
|
6
6
|
*/
|
|
7
7
|
export class Console {
|
|
8
|
+
static #ansi = {
|
|
9
|
+
reset: '\x1b[0m',
|
|
10
|
+
bold: '\x1b[1m',
|
|
11
|
+
colors: {
|
|
12
|
+
log: '\x1b[32m', // green
|
|
13
|
+
info: '\x1b[34m', // blue
|
|
14
|
+
warn: '\x1b[33m', // yellow
|
|
15
|
+
error: '\x1b[31m', // red
|
|
16
|
+
},
|
|
17
|
+
};
|
|
8
18
|
/**
|
|
9
19
|
* @param {string} prefix
|
|
10
20
|
* @param {'log'|'info'|'error'|'warn'} mode
|
|
11
|
-
* - Console method to use
|
|
12
21
|
* @param {any} data
|
|
13
|
-
* @param {string} color
|
|
14
|
-
* @param {string} bgcolor
|
|
15
22
|
* @returns {void}
|
|
16
23
|
*/
|
|
17
|
-
static #call = (prefix, mode, data
|
|
18
|
-
/** @type {unknown} */
|
|
24
|
+
static #call = (prefix, mode, data) => {
|
|
19
25
|
const fn = console[mode];
|
|
20
|
-
if (typeof fn !== 'function')
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
data
|
|
28
|
-
);
|
|
26
|
+
if (typeof fn !== 'function') return;
|
|
27
|
+
|
|
28
|
+
const color = Console.#ansi.colors[mode] || '';
|
|
29
|
+
const styledPrefix = `${color}${Console.#ansi.bold}${prefix} ${mode.toUpperCase()}:${
|
|
30
|
+
Console.#ansi.reset
|
|
31
|
+
}`;
|
|
32
|
+
fn(styledPrefix, data);
|
|
29
33
|
};
|
|
34
|
+
|
|
30
35
|
/**
|
|
31
36
|
* @description
|
|
32
37
|
* @param {any} data
|
|
33
38
|
* @returns {void}
|
|
39
|
+
* @example
|
|
40
|
+
* import { Console } from 'vivth';
|
|
41
|
+
*
|
|
42
|
+
* Console.log({
|
|
43
|
+
* hello: 'world!!',
|
|
44
|
+
* });
|
|
34
45
|
*/
|
|
35
|
-
static log = (data) =>
|
|
36
|
-
Console.#call('🟢', 'log', data, 'white', '#2e7d32');
|
|
37
|
-
};
|
|
46
|
+
static log = (data) => Console.#call('🟢', 'log', data);
|
|
38
47
|
/**
|
|
39
48
|
* @description
|
|
40
49
|
* @param {any} data
|
|
41
50
|
* @returns {void}
|
|
51
|
+
* @example
|
|
52
|
+
* import { Console } from 'vivth';
|
|
53
|
+
*
|
|
54
|
+
* Console.info({
|
|
55
|
+
* hello: 'world!!',
|
|
56
|
+
* });
|
|
42
57
|
*/
|
|
43
|
-
static info = (data) =>
|
|
44
|
-
Console.#call('🔵', 'info', data, 'white', '#1565c0');
|
|
45
|
-
};
|
|
58
|
+
static info = (data) => Console.#call('🔵', 'info', data);
|
|
46
59
|
/**
|
|
47
60
|
* @description
|
|
48
61
|
* @param {any} data
|
|
49
62
|
* @returns {void}
|
|
63
|
+
* @example
|
|
64
|
+
* import { Console } from 'vivth';
|
|
65
|
+
*
|
|
66
|
+
* Console.warn({
|
|
67
|
+
* hello: 'world!!',
|
|
68
|
+
* });
|
|
50
69
|
*/
|
|
51
|
-
static warn = (data) =>
|
|
52
|
-
Console.#call('🟠', 'warn', data, 'black', '#ffb300');
|
|
53
|
-
};
|
|
70
|
+
static warn = (data) => Console.#call('🟠', 'warn', data);
|
|
54
71
|
/**
|
|
55
72
|
* @description
|
|
56
73
|
* @param {any} data
|
|
57
74
|
* @returns {void}
|
|
75
|
+
* @example
|
|
76
|
+
* import { Console } from 'vivth';
|
|
77
|
+
*
|
|
78
|
+
* Console.error({
|
|
79
|
+
* hello: 'world!!',
|
|
80
|
+
* });
|
|
58
81
|
*/
|
|
59
|
-
static error = (data) =>
|
|
60
|
-
Console.#call('🔴', 'error', data, 'white', '#c62828');
|
|
61
|
-
};
|
|
82
|
+
static error = (data) => Console.#call('🔴', 'error', data);
|
|
62
83
|
}
|
package/src/class/Derived.mjs
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import { Signal } from './Signal.mjs';
|
|
4
|
-
import { Effect } from './Effect.mjs';
|
|
5
4
|
import { Console } from './Console.mjs';
|
|
5
|
+
import { Effect } from './Effect.mjs';
|
|
6
|
+
import { LazyFactory } from '../function/LazyFactory.mjs';
|
|
7
|
+
import { unwrapLazy } from '../common/lazie.mjs';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @description
|
|
9
11
|
* - a class for creating derived version of [Signal](#signal);
|
|
10
|
-
* @template
|
|
11
|
-
* @extends Signal<
|
|
12
|
+
* @template VALUE
|
|
13
|
+
* @extends Signal<VALUE>
|
|
12
14
|
*/
|
|
13
15
|
export class Derived extends Signal {
|
|
14
16
|
/**
|
|
15
17
|
* @description
|
|
16
18
|
* - Derived used [Signal](#signal) and [Effect](#effect) under the hood;
|
|
17
|
-
* @param {(effectInstanceOptions:Effect["options"]
|
|
19
|
+
* @param {(effectInstanceOptions:Omit<Effect["options"] &
|
|
20
|
+
* Derived["options"], unwrapLazy>) =>
|
|
21
|
+
* Promise<VALUE>} derivedFunction
|
|
18
22
|
* @example
|
|
19
23
|
* import { Signal, Derived } from 'vivth';
|
|
20
24
|
*
|
|
@@ -33,15 +37,59 @@ export class Derived extends Signal {
|
|
|
33
37
|
*/
|
|
34
38
|
constructor(derivedFunction) {
|
|
35
39
|
super(undefined);
|
|
40
|
+
const derived_instanceOptions = this.options;
|
|
36
41
|
new Effect(async (options) => {
|
|
37
|
-
|
|
42
|
+
const currentValue = await derivedFunction({
|
|
43
|
+
...options,
|
|
44
|
+
...derived_instanceOptions[unwrapLazy](),
|
|
45
|
+
});
|
|
46
|
+
if (currentValue === derived_instanceOptions.dontUpdate) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
super.value = currentValue;
|
|
38
50
|
});
|
|
39
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* @description
|
|
54
|
+
* - additional helper to be accessed on effect;
|
|
55
|
+
*/
|
|
56
|
+
options = LazyFactory(() => {
|
|
57
|
+
return {
|
|
58
|
+
/**
|
|
59
|
+
* @instance options
|
|
60
|
+
* @description
|
|
61
|
+
* - return this value tandem with `isLastCalled`, to not to update the value of this instance, even when returning early;
|
|
62
|
+
* @type {Object}
|
|
63
|
+
* @example
|
|
64
|
+
* import { Signal, Derived } from 'vivth';
|
|
65
|
+
*
|
|
66
|
+
* const count = new Signal(0);
|
|
67
|
+
* const double = new Derived(async({
|
|
68
|
+
* subscribe,
|
|
69
|
+
* dontUpdate,
|
|
70
|
+
* isLastCalled,
|
|
71
|
+
* }) => {
|
|
72
|
+
* const currentValue = subscribe(count).value;
|
|
73
|
+
* if (!(await isLastCalled(10))) {
|
|
74
|
+
* return dontUpdate;
|
|
75
|
+
* }
|
|
76
|
+
* const res = await fetch(`some/path/${curentValue.toString()}`);
|
|
77
|
+
* if (!(await isLastCalled())) {
|
|
78
|
+
* return dontUpdate; // this will prevent race condition, even if the earlier fetch return late;
|
|
79
|
+
* }
|
|
80
|
+
* return res;
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* count.value++;
|
|
84
|
+
*/
|
|
85
|
+
dontUpdate: {},
|
|
86
|
+
};
|
|
87
|
+
});
|
|
40
88
|
/**
|
|
41
89
|
* @description
|
|
42
90
|
* - the most recent value of the instance
|
|
43
91
|
* - can be turn into reactive with Effect or Derived instantiation;
|
|
44
|
-
* @
|
|
92
|
+
* @returns {VALUE}
|
|
45
93
|
*/
|
|
46
94
|
get value() {
|
|
47
95
|
return super.value;
|
|
@@ -51,7 +99,7 @@ export class Derived extends Signal {
|
|
|
51
99
|
* - Derived instance value cannot be manually assigned;
|
|
52
100
|
* - it's value should always be determined by it's own `derivedFunction`;
|
|
53
101
|
* @private
|
|
54
|
-
* @type {
|
|
102
|
+
* @type {VALUE}
|
|
55
103
|
*/
|
|
56
104
|
set value(newValue) {
|
|
57
105
|
Console.warn({
|
package/src/class/Effect.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { unwrapLazy } from '../common/lazie.mjs';
|
|
4
4
|
import { LazyFactory } from '../function/LazyFactory.mjs';
|
|
5
|
+
import { Timeout } from '../function/Timeout.mjs';
|
|
5
6
|
import { TryAsync } from '../function/TryAsync.mjs';
|
|
6
7
|
import { Console } from './Console.mjs';
|
|
7
8
|
import { Signal } from './Signal.mjs';
|
|
@@ -21,9 +22,96 @@ export const setOfEffects = new Set();
|
|
|
21
22
|
* >- now can dynamically subscribes to signal, even on conditionals, that are not run during first run;
|
|
22
23
|
*/
|
|
23
24
|
export class Effect {
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {import('../common/lazie.mjs').unwrapLazy} unwrapLazy
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* @description
|
|
30
|
+
* - collections of lazy methods to handle effect calls of this instance;
|
|
31
|
+
*/
|
|
32
|
+
options = LazyFactory(() => {
|
|
33
|
+
const this_ = this;
|
|
34
|
+
return {
|
|
35
|
+
/**
|
|
36
|
+
* @instance options
|
|
37
|
+
* @description
|
|
38
|
+
* @returns {(timeoutMS?:number)=>Promise<boolean>}
|
|
39
|
+
* - timeoutMS only necessary if the operation doesn't naturally await;
|
|
40
|
+
* - if it's operation such as `fetch`, you can just leave it blank;
|
|
41
|
+
* @example
|
|
42
|
+
*
|
|
43
|
+
* import { Effect } from 'vivth';
|
|
44
|
+
*
|
|
45
|
+
* const effect = new Effect(async ({ isLastCalled }) => {
|
|
46
|
+
* if (!(await isLastCalled(100))) {
|
|
47
|
+
* return;
|
|
48
|
+
* }
|
|
49
|
+
* // OR
|
|
50
|
+
* const res = await fetch('some/path');
|
|
51
|
+
* if (!(await isLastCalled(
|
|
52
|
+
* // no need to add timeoutMS argument, as fetch are naturally add delay;
|
|
53
|
+
* ))) {
|
|
54
|
+
* return;
|
|
55
|
+
* }
|
|
56
|
+
* })
|
|
57
|
+
*/
|
|
58
|
+
get isLastCalled() {
|
|
59
|
+
const current = {};
|
|
60
|
+
this_.#current = current;
|
|
61
|
+
return async (timeoutMS = 0) => {
|
|
62
|
+
if (timeoutMS) {
|
|
63
|
+
await Timeout(timeoutMS);
|
|
64
|
+
}
|
|
65
|
+
return current === this_.#current;
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* @instance options
|
|
70
|
+
* @description
|
|
71
|
+
* - normally it's passed as argument to constructor, however it is also accessible from `options` property;
|
|
72
|
+
* @template {Signal} SIGNAL
|
|
73
|
+
* @param {SIGNAL} signal
|
|
74
|
+
* @returns {SIGNAL}
|
|
75
|
+
* @example
|
|
76
|
+
* import { Effect } from 'vivth';
|
|
77
|
+
*
|
|
78
|
+
* const effect = new Effect(async () => {
|
|
79
|
+
* // code
|
|
80
|
+
* })
|
|
81
|
+
* effect.options.subscribe(signalInstance);
|
|
82
|
+
*/
|
|
83
|
+
subscribe: (signal) => {
|
|
84
|
+
if (!(signal instanceof Signal)) {
|
|
85
|
+
// @ts-expect-error
|
|
86
|
+
signal = signal[unwrapLazy]();
|
|
87
|
+
}
|
|
88
|
+
signal.subscribers.setOf.add(this_);
|
|
89
|
+
return signal;
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* @instance options
|
|
93
|
+
* @description
|
|
94
|
+
* - normally it's passed as argument to constructor, however it is also accessible from `options` property;
|
|
95
|
+
* @type {()=>void}
|
|
96
|
+
* @example
|
|
97
|
+
* import { Effect } from 'vivth';
|
|
98
|
+
*
|
|
99
|
+
* const effect = new Effect(async () => {
|
|
100
|
+
* // code
|
|
101
|
+
* })
|
|
102
|
+
* effect.options.removeEffect();
|
|
103
|
+
*/
|
|
104
|
+
removeEffect: () => {
|
|
105
|
+
setOfEffects.delete(this);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
});
|
|
24
109
|
/**
|
|
25
110
|
* @description
|
|
26
|
-
* @param {(arg0:
|
|
111
|
+
* @param {( arg0:
|
|
112
|
+
* Omit<Effect["options"], typeof unwrapLazy>
|
|
113
|
+
* ) =>
|
|
114
|
+
* Promise<void>} effect
|
|
27
115
|
* @example
|
|
28
116
|
* import { Signal, Derived, Effect, Console } from 'vivth';
|
|
29
117
|
*
|
|
@@ -32,6 +120,7 @@ export class Effect {
|
|
|
32
120
|
* new Effect(async ({
|
|
33
121
|
* subscribe, // : registrar callback for this effect instance, immediately return the signal instance
|
|
34
122
|
* removeEffect, // : disable this effect instance from reacting to dependency changes;
|
|
123
|
+
* isLastCalled, // : check whether this callback run is this instant last called effect;
|
|
35
124
|
* }) => {
|
|
36
125
|
* Console.log(subscribe(double).value); // effect listen to double changes
|
|
37
126
|
* const a = double.value; // no need to wrap double twice with $
|
|
@@ -44,44 +133,12 @@ export class Effect {
|
|
|
44
133
|
setOfEffects.add(this);
|
|
45
134
|
this.run();
|
|
46
135
|
}
|
|
47
|
-
options = LazyFactory(() => ({
|
|
48
|
-
/**
|
|
49
|
-
* @instance options
|
|
50
|
-
* @description
|
|
51
|
-
* - normally it's passed as argument to constructor, however it is also accessible from `options` property;
|
|
52
|
-
* @template {Signal} S
|
|
53
|
-
* @param {S} signal
|
|
54
|
-
* @returns {S}
|
|
55
|
-
* @example
|
|
56
|
-
* const effect = new Effect(async () => {
|
|
57
|
-
* // code
|
|
58
|
-
* })
|
|
59
|
-
* effect.options.subscribe(signalInstance);
|
|
60
|
-
*/
|
|
61
|
-
subscribe: (signal) => {
|
|
62
|
-
if (!(signal instanceof Signal)) {
|
|
63
|
-
signal = signal[unwrapLazy];
|
|
64
|
-
}
|
|
65
|
-
signal.subscribers.setOf.add(this);
|
|
66
|
-
return signal;
|
|
67
|
-
},
|
|
68
|
-
/**
|
|
69
|
-
* @instance options
|
|
70
|
-
* @description
|
|
71
|
-
* - normally it's passed as argument to constructor, however it is also accessible from `options` property;
|
|
72
|
-
* @type {()=>void}
|
|
73
|
-
* @example
|
|
74
|
-
* const effect = new Effect(async () => {
|
|
75
|
-
* // code
|
|
76
|
-
* })
|
|
77
|
-
* effect.options.removeEffect();
|
|
78
|
-
*/
|
|
79
|
-
removeEffect: () => {
|
|
80
|
-
setOfEffects.delete(this);
|
|
81
|
-
},
|
|
82
|
-
}));
|
|
83
136
|
/**
|
|
84
|
-
* @
|
|
137
|
+
* @type {Object}
|
|
138
|
+
*/
|
|
139
|
+
#current;
|
|
140
|
+
/**
|
|
141
|
+
* @param {Omit<Effect["options"], typeof unwrapLazy>} effectInstance
|
|
85
142
|
* @returns {Promise<void>}
|
|
86
143
|
*/
|
|
87
144
|
#effect;
|
|
@@ -90,13 +147,17 @@ export class Effect {
|
|
|
90
147
|
* - normally is to let to be automatically run when dependency signals changes, however it's also accessible as instance method;
|
|
91
148
|
* @returns {void}
|
|
92
149
|
* @example
|
|
150
|
+
* import { Effect } from 'vivth';
|
|
151
|
+
*
|
|
93
152
|
* const effect = new Effect(async ()=>{
|
|
94
153
|
* // code
|
|
95
154
|
* })
|
|
96
155
|
* effect.run();
|
|
97
156
|
*/
|
|
98
157
|
run = () => {
|
|
99
|
-
TryAsync(async () =>
|
|
158
|
+
TryAsync(async () => {
|
|
159
|
+
await this.#effect(this.options[unwrapLazy]());
|
|
160
|
+
}).then(([, error]) => {
|
|
100
161
|
if (!error) {
|
|
101
162
|
return;
|
|
102
163
|
}
|
package/src/class/EnvSignal.mjs
CHANGED
|
@@ -9,13 +9,13 @@ import { Signal } from './Signal.mjs';
|
|
|
9
9
|
* @description
|
|
10
10
|
* - non browser API;
|
|
11
11
|
* - uses [Signal](#signal) and [Derived](#derived) under the hood;
|
|
12
|
-
* @template
|
|
12
|
+
* @template VALUE
|
|
13
13
|
*/
|
|
14
14
|
export class EnvSignal {
|
|
15
15
|
/**
|
|
16
16
|
* @description
|
|
17
17
|
* - create `EnvSignal` instance;
|
|
18
|
-
* @param {
|
|
18
|
+
* @param {VALUE} initialValue
|
|
19
19
|
*/
|
|
20
20
|
constructor(initialValue) {
|
|
21
21
|
this.#proxyConst = LazyFactory(() => new Signal(initialValue));
|
|
@@ -34,13 +34,13 @@ export class EnvSignal {
|
|
|
34
34
|
}
|
|
35
35
|
#isModified = false;
|
|
36
36
|
/**
|
|
37
|
-
* @type {Signal<
|
|
37
|
+
* @type {Signal<VALUE>}
|
|
38
38
|
*/
|
|
39
39
|
#proxyConst;
|
|
40
40
|
/**
|
|
41
41
|
* @description
|
|
42
42
|
* - exposed property to listen to;
|
|
43
|
-
* @type {Derived<
|
|
43
|
+
* @type {Derived<VALUE>}
|
|
44
44
|
* @example
|
|
45
45
|
* import { EnvSignal, Effect } from 'vivth';
|
|
46
46
|
*
|
|
@@ -55,7 +55,7 @@ export class EnvSignal {
|
|
|
55
55
|
* @description
|
|
56
56
|
* - call to correct the value of previously declared value;
|
|
57
57
|
* - can only be called once;
|
|
58
|
-
* @param {
|
|
58
|
+
* @param {VALUE} correctedValue
|
|
59
59
|
* @returns {void}
|
|
60
60
|
* @example
|
|
61
61
|
* import { EnvSignal } from 'vivth';
|
|
@@ -10,7 +10,8 @@ import { Signal } from './Signal.mjs';
|
|
|
10
10
|
/**
|
|
11
11
|
* @description
|
|
12
12
|
* - Signal implementation for `CustomEvent`, to dispatch and listen;
|
|
13
|
-
*
|
|
13
|
+
* - it's based on string as key, so it can be listened/dispatched even without direct instance reference;
|
|
14
|
+
* @template {IsListSignal} ISLIST
|
|
14
15
|
* - boolean;
|
|
15
16
|
*/
|
|
16
17
|
export class EventSignal {
|
|
@@ -26,7 +27,7 @@ export class EventSignal {
|
|
|
26
27
|
/**
|
|
27
28
|
* @type {QChannel<string>}
|
|
28
29
|
*/
|
|
29
|
-
static #qChannelEventSignal = new QChannel();
|
|
30
|
+
static #qChannelEventSignal = new QChannel('EventSignal');
|
|
30
31
|
/**
|
|
31
32
|
* @description
|
|
32
33
|
* - the constructor it self is set to `private`;
|
|
@@ -53,7 +54,7 @@ export class EventSignal {
|
|
|
53
54
|
/**
|
|
54
55
|
* @private
|
|
55
56
|
* @param {string} name
|
|
56
|
-
* @param {
|
|
57
|
+
* @param {ISLIST} [isList]
|
|
57
58
|
*/
|
|
58
59
|
// @ts-expect-error
|
|
59
60
|
constructor(name, isList = false) {
|
|
@@ -74,6 +75,17 @@ export class EventSignal {
|
|
|
74
75
|
* - if needed to pass along the messages, it can be used as `dispatcher` and `listener` at the same time;
|
|
75
76
|
* - is `lazily` created;
|
|
76
77
|
* @type {Signal|ListSignal}
|
|
78
|
+
* @example
|
|
79
|
+
* import { EventSignal, Effect, Console } from 'vivth';
|
|
80
|
+
*
|
|
81
|
+
* const myEventSignal = await EventSignal.get('dataEvent', false);
|
|
82
|
+
*
|
|
83
|
+
* new Effect(({ subscribe })=>{
|
|
84
|
+
* const listenValue = subscribe(myEventSignal.dispatch).value;
|
|
85
|
+
* // dispatch can be used as two way communication;
|
|
86
|
+
* Console.log({ listenValue });
|
|
87
|
+
* })
|
|
88
|
+
* myEventSignal.dispatch.value = 'hey';
|
|
77
89
|
*/
|
|
78
90
|
dispatch = LazyFactory(() => {
|
|
79
91
|
if (this.#isList) {
|
|
@@ -87,6 +99,17 @@ export class EventSignal {
|
|
|
87
99
|
* - can be used as listener when passed down value shouldn't be modified manually;
|
|
88
100
|
* - is `lazily` created along with `dispatch`, if `listen` is accessed first, then `dispatch` will also be created automatically;
|
|
89
101
|
* @type {Derived|ListDerived}
|
|
102
|
+
* @example
|
|
103
|
+
* import { EventSignal, Effect, Console } from 'vivth';
|
|
104
|
+
*
|
|
105
|
+
* const myEventSignal = await EventSignal.get('dataEvent', false);
|
|
106
|
+
*
|
|
107
|
+
* new Effect(({ subscribe })=>{
|
|
108
|
+
* const listenValue = subscribe(myEventSignal.listen).value;
|
|
109
|
+
* // listen can be used only as listener for one way communication;
|
|
110
|
+
* Console.log({ listenValue });
|
|
111
|
+
* })
|
|
112
|
+
* myEventSignal.dispatch.value = 'hey';
|
|
90
113
|
*/
|
|
91
114
|
listen = LazyFactory(() => {
|
|
92
115
|
const dispatch = this.dispatch;
|
|
@@ -116,7 +139,7 @@ export class EventSignal {
|
|
|
116
139
|
* @example
|
|
117
140
|
* import { EventSignal } from 'vivth';
|
|
118
141
|
*
|
|
119
|
-
* EventSignal.remove.subscriber('yourEventSignalName',
|
|
142
|
+
* EventSignal.remove.subscriber('yourEventSignalName', myEffectInstance);
|
|
120
143
|
*/
|
|
121
144
|
subscriber: (name, effect) => {
|
|
122
145
|
effect.options.removeEffect();
|
|
@@ -165,7 +188,16 @@ export class EventSignal {
|
|
|
165
188
|
* @param {import('./Effect.mjs').Effect} effect
|
|
166
189
|
* @returns {void}
|
|
167
190
|
* @example
|
|
168
|
-
*
|
|
191
|
+
* import { EventSignal, Effect, Console } from 'vivth';
|
|
192
|
+
*
|
|
193
|
+
* const myEventSignal = await EventSignal.get('dataEvent', false);
|
|
194
|
+
*
|
|
195
|
+
* const myEffectInstance = new Effect(({ subscribe })=>{
|
|
196
|
+
* const listenValue = subscribe(myEventSignal.dispatch).value;
|
|
197
|
+
* Console.log({ listenValue });
|
|
198
|
+
* })
|
|
199
|
+
* myEventSignal.dispatch.value = 'hey';
|
|
200
|
+
* eventSignal_instance.remove.subscriber(myEffectInstance);
|
|
169
201
|
*/
|
|
170
202
|
subscriber: (effect) => {
|
|
171
203
|
effect.options.removeEffect();
|
|
@@ -178,6 +210,15 @@ export class EventSignal {
|
|
|
178
210
|
* - remove allSubscribers from the `EventSignal_instance`;
|
|
179
211
|
* @type {()=>void}
|
|
180
212
|
* @example
|
|
213
|
+
* import { EventSignal, Effect, Console } from 'vivth';
|
|
214
|
+
*
|
|
215
|
+
* const myEventSignal = await EventSignal.get('dataEvent', false);
|
|
216
|
+
*
|
|
217
|
+
* const myEffectInstance = new Effect(({ subscribe })=>{
|
|
218
|
+
* const listenValue = subscribe(myEventSignal.dispatch).value;
|
|
219
|
+
* Console.log({ listenValue });
|
|
220
|
+
* })
|
|
221
|
+
* myEventSignal.dispatch.value = 'hey';
|
|
181
222
|
* eventSignal_instance.remove.allSubscribers();
|
|
182
223
|
*/
|
|
183
224
|
allSubscribers: () => {
|
|
@@ -190,6 +231,15 @@ export class EventSignal {
|
|
|
190
231
|
* - remove reference of the `proxySignals` of the `EventSignal_instance`;
|
|
191
232
|
* @type {()=>void}
|
|
192
233
|
* @example
|
|
234
|
+
* import { EventSignal, Effect, Console } from 'vivth';
|
|
235
|
+
*
|
|
236
|
+
* const myEventSignal = await EventSignal.get('dataEvent', false);
|
|
237
|
+
*
|
|
238
|
+
* const myEffectInstance = new Effect(({ subscribe })=>{
|
|
239
|
+
* const listenValue = subscribe(myEventSignal.dispatch).value;
|
|
240
|
+
* Console.log({ listenValue });
|
|
241
|
+
* });
|
|
242
|
+
*
|
|
193
243
|
* eventSignal_instance.remove.ref();
|
|
194
244
|
*/
|
|
195
245
|
ref: () => {
|