vivth 0.11.2 → 1.0.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/dist/init.mjs +24 -0
- package/README.md +2157 -69
- package/README.src.md +35 -0
- package/bun.lock +57 -3
- package/dev/index.mjs +24 -25
- package/index.mjs +51 -29
- package/package.json +11 -7
- package/src/bundler/CompileMJS.mjs +110 -0
- package/src/bundler/EsBundler.mjs +79 -0
- package/src/class/Console.mjs +62 -0
- package/src/class/Derived.mjs +36 -25
- package/src/class/Effect.mjs +106 -0
- package/src/class/EnvSignal.mjs +88 -0
- package/src/class/EventSignal.mjs +200 -0
- package/src/class/ListDerived.mjs +39 -0
- package/src/class/ListSignal.mjs +256 -0
- package/src/class/Paths.mjs +70 -0
- package/src/class/QChannel.mjs +184 -0
- package/src/class/SafeExit.mjs +131 -0
- package/src/class/Setup.mjs +73 -0
- package/src/class/Signal.mjs +152 -54
- package/src/class/WorkerMainThread.mjs +328 -0
- package/src/class/WorkerResult.mjs +30 -0
- package/src/class/WorkerThread.mjs +151 -0
- package/src/common/Base64URL.mjs +26 -0
- package/src/common/EventNameSpace.mjs +8 -0
- package/src/common/eventObjects.mjs +5 -0
- package/src/common/lazie.mjs +3 -0
- package/src/doc/JSautoDOC.mjs +386 -0
- package/src/doc/parsedFile.mjs +537 -0
- package/src/function/CreateImmutable.mjs +64 -0
- package/src/function/EventCheck.mjs +27 -0
- package/src/function/EventObject.mjs +21 -0
- package/src/function/IsAsync.mjs +23 -0
- package/src/function/LazyFactory.mjs +71 -0
- package/src/function/Timeout.mjs +23 -0
- package/src/function/Try.mjs +64 -0
- package/src/function/TryAsync.mjs +15 -4
- package/src/function/TrySync.mjs +9 -4
- package/src/function/TsToMjs.mjs +67 -0
- package/src/function/WriteFileSafe.mjs +37 -0
- package/src/types/{AnyButUndefined.type.mjs → AnyButUndefined.mjs} +1 -0
- package/src/types/ExtnameType.mjs +6 -0
- package/src/types/IsListSignal.mjs +6 -0
- package/src/types/ListArg.mjs +6 -0
- package/src/types/MutationType.mjs +8 -0
- package/src/types/QCBFIFOReturn.mjs +6 -0
- package/src/types/QCBReturn.mjs +6 -0
- package/tsconfig.json +3 -3
- package/types/dev/index.d.mts +1 -0
- package/types/index.d.mts +34 -8
- package/types/src/bundler/A.d.mts +1 -0
- package/types/src/bundler/CompileMJS.d.mts +8 -0
- package/types/src/bundler/EsBundler.d.mts +7 -0
- package/types/src/class/Console.d.mts +40 -0
- package/types/src/class/Derived.d.mts +21 -9
- package/types/src/class/Effect.d.mts +77 -0
- package/types/src/class/EnvSignal.d.mts +47 -0
- package/types/src/class/EventSignal.d.mts +145 -0
- package/types/src/class/ListDerived.d.mts +35 -0
- package/types/src/class/ListSignal.d.mts +150 -0
- package/types/src/class/Paths.d.mts +50 -0
- package/types/src/class/QChannel.d.mts +115 -0
- package/types/src/class/SafeExit.d.mts +76 -0
- package/types/src/class/Setup.d.mts +76 -0
- package/types/src/class/Signal.d.mts +105 -26
- package/types/src/class/WorkerMainThread.d.mts +149 -0
- package/types/src/class/WorkerResult.d.mts +25 -0
- package/types/src/class/WorkerThread.d.mts +70 -0
- package/types/src/common/Base64URL.d.mts +1 -0
- package/types/src/common/EventNameSpace.d.mts +6 -0
- package/types/src/common/eventObjects.d.mts +3 -0
- package/types/src/common/lazie.d.mts +1 -0
- package/types/src/doc/JSautoDOC.d.mts +76 -0
- package/types/src/doc/parsedFile.d.mts +154 -0
- package/types/src/function/CreateImmutable.d.mts +3 -0
- package/types/src/function/EventCheck.d.mts +2 -0
- package/types/src/function/EventObject.d.mts +4 -0
- package/types/src/function/IsAsync.d.mts +1 -0
- package/types/src/function/LazyFactory.d.mts +4 -0
- package/types/src/function/Timeout.d.mts +1 -0
- package/types/src/function/Try.d.mts +1 -0
- package/types/src/function/TsToMjs.d.mts +4 -0
- package/types/src/function/WriteFileSafe.d.mts +2 -0
- package/types/src/types/{AnyButUndefined.type.d.mts → AnyButUndefined.d.mts} +3 -0
- package/types/src/types/ExtnameType.d.mts +4 -0
- package/types/src/types/IsListSignal.d.mts +4 -0
- package/types/src/types/ListArg.d.mts +4 -0
- package/types/src/types/MutationType.d.mts +5 -0
- package/types/src/types/QCBFIFOReturn.d.mts +4 -0
- package/types/src/types/QCBReturn.d.mts +7 -0
- package/src/class/$.mjs +0 -68
- package/src/class/PingFIFO.mjs +0 -78
- package/src/class/PingUnique.mjs +0 -84
- package/src/class/Q.mjs +0 -98
- package/src/class/QFIFO.mjs +0 -66
- package/src/class/QUnique.mjs +0 -75
- package/src/common.mjs +0 -16
- package/src/function/NewQBlock.mjs +0 -39
- package/types/src/class/$.d.mts +0 -40
- package/types/src/class/PingFIFO.d.mts +0 -57
- package/types/src/class/PingUnique.d.mts +0 -48
- package/types/src/class/Q.d.mts +0 -63
- package/types/src/class/QFIFO.d.mts +0 -47
- package/types/src/class/QUnique.d.mts +0 -46
- package/types/src/common.d.mts +0 -2
- package/types/src/function/NewQBlock.d.mts +0 -1
package/README.md
CHANGED
|
@@ -1,93 +1,2198 @@
|
|
|
1
|
-
## HOW TO INSTALL
|
|
2
|
-
|
|
3
|
-
npm
|
|
1
|
+
## HOW TO INSTALL
|
|
2
|
+
|
|
3
|
+
- example uses `npm`, you can allways use your own favourite package manager;
|
|
4
|
+
|
|
5
|
+
```shell
|
|
6
|
+
npm i vivth
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## vivth
|
|
10
|
+
|
|
11
|
+
- `vivth` are intended to be a collections of usefull `primitives`, and not to be directly used as
|
|
12
|
+
underlying framework;
|
|
13
|
+
- completely `JSruntime` agnostic:
|
|
14
|
+
> - instead of `vivth` trying to guess, all runtime specific API should be provided by dev;
|
|
15
|
+
- contains helpers to help you write data driven javascript program, including:
|
|
16
|
+
> - collections of extremely ⚡ performant `signal` classes;
|
|
17
|
+
> > - `vivth` deliberately take away `auto-subscription`:
|
|
18
|
+
> > > - and introducing more imperative way of subsrciption yet still simple enough, which in
|
|
19
|
+
> > > turn, it completely removes total code blocking on previously needed auto subsrciption
|
|
20
|
+
> > > process on first run;
|
|
21
|
+
> > > - and also make previously unthinkable dynamic subscription on conditionals that runs
|
|
22
|
+
> > > outside first run, now completely possible;
|
|
23
|
+
> - collections of `queue-helper` classes;
|
|
24
|
+
> - fully typed `worker-threads` abstraction;
|
|
25
|
+
> - ` error as value` function helper;
|
|
26
|
+
> - opionated `autoDocumentation`;
|
|
27
|
+
> - opionated `bundler`;
|
|
28
|
+
|
|
29
|
+
## versions:
|
|
30
|
+
|
|
31
|
+
- `1.0.0:b`:
|
|
32
|
+
> - beta release;
|
|
33
|
+
> - checking edge cases;
|
|
34
|
+
> - stable API, the exposed API access are highly unlikely to changes, only the underlying code
|
|
35
|
+
> might changes for improving performance;
|
|
36
|
+
|
|
37
|
+
<h2 id="list-of-exported-api-and-typehelpers">list of exported API and typehelpers</h2>
|
|
38
|
+
|
|
39
|
+
- [CompileMJS](#compilemjs)
|
|
40
|
+
- [EsBundler](#esbundler)
|
|
41
|
+
- [Console](#console)
|
|
42
|
+
- [Derived](#derived)
|
|
43
|
+
- [Effect](#effect)
|
|
44
|
+
- [EnvSignal](#envsignal)
|
|
45
|
+
- [EventSignal](#eventsignal)
|
|
46
|
+
- [ListDerived](#listderived)
|
|
47
|
+
- [ListSignal](#listsignal)
|
|
48
|
+
- [Paths](#paths)
|
|
49
|
+
- [QChannel](#qchannel)
|
|
50
|
+
- [SafeExit](#safeexit)
|
|
51
|
+
- [Setup](#setup)
|
|
52
|
+
- [Signal](#signal)
|
|
53
|
+
- [WorkerMainThread](#workermainthread)
|
|
54
|
+
- [WorkerResult](#workerresult)
|
|
55
|
+
- [WorkerThread](#workerthread)
|
|
56
|
+
- [Base64URL](#base64url)
|
|
57
|
+
- [EventNameSpace](#eventnamespace)
|
|
58
|
+
- [JSautoDOC](#jsautodoc)
|
|
59
|
+
- [CreateImmutable](#createimmutable)
|
|
60
|
+
- [EventCheck](#eventcheck)
|
|
61
|
+
- [EventObject](#eventobject)
|
|
62
|
+
- [IsAsync](#isasync)
|
|
63
|
+
- [LazyFactory](#lazyfactory)
|
|
64
|
+
- [Timeout](#timeout)
|
|
65
|
+
- [Try](#try)
|
|
66
|
+
- [TryAsync](#tryasync)
|
|
67
|
+
- [TrySync](#trysync)
|
|
68
|
+
- [TsToMjs](#tstomjs)
|
|
69
|
+
- [WriteFileSafe](#writefilesafe)
|
|
70
|
+
- [AnyButUndefined](#anybutundefined)
|
|
71
|
+
- [ExtnameType](#extnametype)
|
|
72
|
+
- [IsListSignal](#islistsignal)
|
|
73
|
+
- [ListArg](#listarg)
|
|
74
|
+
- [MutationType](#mutationtype)
|
|
75
|
+
- [QCBFIFOReturn](#qcbfiforeturn)
|
|
76
|
+
- [QCBReturn](#qcbreturn)
|
|
77
|
+
|
|
78
|
+
<h2 id="compilemjs">CompileMJS</h2>
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
#### reference:`CompileMJS`
|
|
82
|
+
- function to bundle to single mjs file, including the workerThread;
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
/**
|
|
86
|
+
* @param {Object} options
|
|
87
|
+
* @param {string} options.entryPoint
|
|
88
|
+
* @param {string} options.outputNoExt
|
|
89
|
+
* - no extention needed, result will always be '.mjs';
|
|
90
|
+
* @param {BufferEncoding} options.encoding
|
|
91
|
+
* @param {boolean} [options.minify]
|
|
92
|
+
* - default false;
|
|
93
|
+
* @param {boolean} [options.asBinary]
|
|
94
|
+
* - default false;
|
|
95
|
+
* @returns {Promise<ReturnType<typeof WriteFileSafe>>}
|
|
96
|
+
*/
|
|
97
|
+
```
|
|
98
|
+
- <i>example</i>:
|
|
99
|
+
```js
|
|
100
|
+
import { Paths, CompileMJS } from 'vivth';
|
|
101
|
+
|
|
102
|
+
new Paths({
|
|
103
|
+
root: process?.env?.INIT_CWD ?? process?.cwd(),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
CompileMJS({
|
|
107
|
+
entryPoint: '/index.mjs',
|
|
108
|
+
encoding: 'utf-8',
|
|
109
|
+
outputNoExt: '/test/compiled',
|
|
110
|
+
minify: false,
|
|
111
|
+
asBinary: true,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
117
|
+
|
|
118
|
+
<h2 id="esbundler">EsBundler</h2>
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
#### reference:`EsBundler`
|
|
122
|
+
- opinionated bundler for extension below using esbuild;
|
|
123
|
+
- bundles all imports into a single output string;
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
/**
|
|
127
|
+
* @param {Object} options
|
|
128
|
+
* @param {string} options.content
|
|
129
|
+
* - the code can also uses composites from the result from multiple readFiles;
|
|
130
|
+
* - the import statements on the content should use absolute path from project root, prefixed with forward slash;
|
|
131
|
+
* @param {string} options.extension
|
|
132
|
+
* @param {boolean} [options.asBinary]
|
|
133
|
+
* @param {Omit<Parameters<build>[0], 'entryPoints'|'bundle'|'write'|'format'|'sourcemap'|'external'|'stdin'>} [esbuildOptions]
|
|
134
|
+
* @returns {Promise<ReturnType<typeof TryAsync<string>>>}
|
|
135
|
+
*/
|
|
136
|
+
```
|
|
137
|
+
- <i>example</i>:
|
|
138
|
+
```js
|
|
139
|
+
import { EsBundler } from 'vivth';
|
|
140
|
+
|
|
141
|
+
const bundledString = EsBundler(,
|
|
142
|
+
{
|
|
143
|
+
content: ``,
|
|
144
|
+
extension: '.mts',
|
|
145
|
+
...options
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
...esbuildOptions,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
154
|
+
|
|
155
|
+
<h2 id="console">Console</h2>
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
#### reference:`Console`
|
|
159
|
+
- class with static methods to print to standard console with added style;
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
#### reference:`Console.log`
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
/**
|
|
167
|
+
* @param {any} data
|
|
168
|
+
* @returns {void}
|
|
169
|
+
*/
|
|
4
170
|
```
|
|
5
|
-
|
|
6
|
-
|
|
171
|
+
|
|
172
|
+
#### reference:`Console.info`
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
/**
|
|
177
|
+
* @param {any} data
|
|
178
|
+
* @returns {void}
|
|
179
|
+
*/
|
|
7
180
|
```
|
|
8
181
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
182
|
+
#### reference:`Console.warn`
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
/**
|
|
187
|
+
* @param {any} data
|
|
188
|
+
* @returns {void}
|
|
189
|
+
*/
|
|
190
|
+
```
|
|
13
191
|
|
|
14
|
-
|
|
15
|
-
- it is written specifically to be used as a primitives for javascript library or runtime, so there are no complex abstraction is, nor will be, added in `vivth` it self;
|
|
192
|
+
#### reference:`Console.error`
|
|
16
193
|
|
|
17
|
-
## exported-api-and-type-list
|
|
18
|
-
- [$](#$)
|
|
19
|
-
- [Derived](#derived)
|
|
20
|
-
- [PingFIFO](#pingfifo)
|
|
21
|
-
- [PingUnique](#pingunique)
|
|
22
|
-
- [Q](#q)
|
|
23
|
-
- [QFIFO](#qfifo)
|
|
24
|
-
- [QUnique](#qunique)
|
|
25
|
-
- [Signal](#signal)
|
|
26
|
-
- [NewQBlock](#newqblock)
|
|
27
|
-
- [TryAsync](#tryasync)
|
|
28
|
-
- [TrySync](#trysync)
|
|
29
|
-
<h2 id="$">$</h2>
|
|
30
194
|
|
|
31
|
-
|
|
32
|
-
|
|
195
|
+
```js
|
|
196
|
+
/**
|
|
197
|
+
* @param {any} data
|
|
198
|
+
* @returns {void}
|
|
199
|
+
*/
|
|
200
|
+
```
|
|
33
201
|
|
|
34
|
-
*) <sub>[go to exported
|
|
202
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
35
203
|
|
|
36
204
|
<h2 id="derived">Derived</h2>
|
|
37
205
|
|
|
38
|
-
- a class for creating signal which its value are derived from other signal (`Derived` and `Signal` alike);
|
|
39
|
-
can be subscribed by using [New$](#new$);
|
|
40
|
-
for minimal total bundle size use `function` [NewDerived](#newderived) instead;
|
|
41
206
|
|
|
42
|
-
|
|
207
|
+
#### reference:`Derived`
|
|
208
|
+
- a class for creating derived version of [Signal](#signal);
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
/**
|
|
212
|
+
* @template V
|
|
213
|
+
* @extends Signal<V>
|
|
214
|
+
*/
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### reference:`new Derived`
|
|
218
|
+
- Derived used [Signal](#signal) and [Effect](#effect) under the hood;
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
/**
|
|
222
|
+
* @param {(effectInstanceOptions:Effect["options"])=>Promise<V>} derivedFunction
|
|
223
|
+
*/
|
|
224
|
+
```
|
|
225
|
+
- <i>example</i>:
|
|
226
|
+
```js
|
|
227
|
+
import { Signal, Derived } from 'vivth';
|
|
228
|
+
|
|
229
|
+
const count = new Signal(0);
|
|
230
|
+
const double = new Derived(async({
|
|
231
|
+
subscribe,
|
|
232
|
+
// : registrar callback for this derived instance, immediately return the signal instance
|
|
233
|
+
}) => {
|
|
234
|
+
return subscribe(count).value + count.value;
|
|
235
|
+
// double listen to count changes, by returning the value, double.value also changes
|
|
236
|
+
// notice the count.value are accessed double, but it's all safe,
|
|
237
|
+
// since the wrapped one is the only one that are recorded as notifier.
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
count.value++;
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### reference:`Derived_instance.value:getter`
|
|
245
|
+
- the most recent value of the instance
|
|
246
|
+
- can be turn into reactive with Effect or Derived instantiation;
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
/**
|
|
250
|
+
* @type {V}
|
|
251
|
+
*/
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### reference:`Derived_instance.value:setter`
|
|
255
|
+
- Derived instance value cannot be manually assigned;
|
|
256
|
+
- it's value should always be determined by it's own `derivedFunction`;
|
|
257
|
+
|
|
258
|
+
```js
|
|
259
|
+
/**
|
|
260
|
+
* @private
|
|
261
|
+
* @type {V}
|
|
262
|
+
*/
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
266
|
+
|
|
267
|
+
<h2 id="effect">Effect</h2>
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
#### reference:`Effect`
|
|
271
|
+
- a class for creating effect;
|
|
272
|
+
- compared to previous class <b>$</b> reactivity model, `Effect`:
|
|
273
|
+
>- doesn't autosubscribe at first run;
|
|
274
|
+
>- it is using passed <b>$</b> named `arg0` options as subscriber;
|
|
275
|
+
>- doesn't block other queues during first run(previously blocks other queues to safely register signal autoscubscriber);
|
|
276
|
+
>- now can dynamically subscribes to signal, even on conditionals, that are not run during first run;
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
#### reference:`new Effect`
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
```js
|
|
283
|
+
/**
|
|
284
|
+
* @param {(arg0:Effect["options"])=>Promise<void>} effect
|
|
285
|
+
*/
|
|
286
|
+
```
|
|
287
|
+
- <i>example</i>:
|
|
288
|
+
```js
|
|
289
|
+
import { Signal, Derived, Effect, Console } from 'vivth';
|
|
290
|
+
|
|
291
|
+
const count = new Signal(0);
|
|
292
|
+
const double = new Derived( async({$}) => $(count).value * 2); // double listen to count changes
|
|
293
|
+
new Effect(async ({
|
|
294
|
+
subscribe, // : registrar callback for this effect instance, immediately return the signal instance
|
|
295
|
+
removeEffect, // : disable this effect instance from reacting to dependency changes;
|
|
296
|
+
}) => {
|
|
297
|
+
Console.log(subscribe(double).value); // effect listen to double changes
|
|
298
|
+
const a = double.value; // no need to wrap double twice with $
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
count.value++;
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### reference:`Effect_instance.options.subscribe`
|
|
306
|
+
- normally it's passed as argument to constructor, however it is also accessible from `options` property;
|
|
307
|
+
|
|
308
|
+
```js
|
|
309
|
+
/**
|
|
310
|
+
* @template {Signal} S
|
|
311
|
+
* @param {S} signal
|
|
312
|
+
* @returns {S}
|
|
313
|
+
*/
|
|
314
|
+
```
|
|
315
|
+
- <i>example</i>:
|
|
316
|
+
```js
|
|
317
|
+
const effect = new Effect(async () => {
|
|
318
|
+
// code
|
|
319
|
+
})
|
|
320
|
+
effect.options.subscribe(signalInstance);
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### reference:`Effect_instance.options.removeEffect`
|
|
325
|
+
- normally it's passed as argument to constructor, however it is also accessible from `options` property;
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
/**
|
|
329
|
+
* @type {()=>void}
|
|
330
|
+
*/
|
|
331
|
+
```
|
|
332
|
+
- <i>example</i>:
|
|
333
|
+
```js
|
|
334
|
+
const effect = new Effect(async () => {
|
|
335
|
+
// code
|
|
336
|
+
})
|
|
337
|
+
effect.options.removeEffect();
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### reference:`Effect_instance.run`
|
|
342
|
+
- normally is to let to be automatically run when dependency signals changes, however it's also accessible as instance method;
|
|
343
|
+
|
|
344
|
+
```js
|
|
345
|
+
/**
|
|
346
|
+
* @returns {void}
|
|
347
|
+
*/
|
|
348
|
+
```
|
|
349
|
+
- <i>example</i>:
|
|
350
|
+
```js
|
|
351
|
+
const effect = new Effect(async ()=>{
|
|
352
|
+
// code
|
|
353
|
+
})
|
|
354
|
+
effect.run();
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
359
|
+
|
|
360
|
+
<h2 id="envsignal">EnvSignal</h2>
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
#### reference:`EnvSignal`
|
|
364
|
+
- non browser API;
|
|
365
|
+
- uses [Signal](#signal) and [Derived](#derived) under the hood;
|
|
366
|
+
|
|
367
|
+
```js
|
|
368
|
+
/**
|
|
369
|
+
* @template V
|
|
370
|
+
*/
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### reference:`new EnvSignal`
|
|
374
|
+
- create `EnvSignal` instance;
|
|
375
|
+
|
|
376
|
+
```js
|
|
377
|
+
/**
|
|
378
|
+
* @param {V} initialValue
|
|
379
|
+
*/
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### reference:`EnvSignal_instance.env`
|
|
383
|
+
- exposed property to listen to;
|
|
384
|
+
|
|
385
|
+
```js
|
|
386
|
+
/**
|
|
387
|
+
* @type {Derived<V>}
|
|
388
|
+
*/
|
|
389
|
+
```
|
|
390
|
+
- <i>example</i>:
|
|
391
|
+
```js
|
|
392
|
+
import { EnvSignal, Effect } from 'vivth';
|
|
393
|
+
|
|
394
|
+
export const myEnv = new EnvSignal(true);
|
|
395
|
+
new Effect(async ({ subscribe }) => {
|
|
396
|
+
const myEnvValue = subscribe(myEnv.env).value;
|
|
397
|
+
// code
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### reference:`EnvSignal_instance.correction`
|
|
403
|
+
- call to correct the value of previously declared value;
|
|
404
|
+
- can only be called once;
|
|
405
|
+
|
|
406
|
+
```js
|
|
407
|
+
/**
|
|
408
|
+
* @param {V} correctedValue
|
|
409
|
+
* @returns {void}
|
|
410
|
+
*/
|
|
411
|
+
```
|
|
412
|
+
- <i>example</i>:
|
|
413
|
+
```js
|
|
414
|
+
import { EnvSignal } from 'vivth';
|
|
415
|
+
|
|
416
|
+
export const myEnv = new EnvSignal(true);
|
|
417
|
+
|
|
418
|
+
// somewhere else on the program
|
|
419
|
+
import { myEnv } from '$src/myEnv'
|
|
420
|
+
|
|
421
|
+
myEnv.correction(false); // this will notify all subscribers;
|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
426
|
+
|
|
427
|
+
<h2 id="eventsignal">EventSignal</h2>
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
#### reference:`EventSignal`
|
|
431
|
+
- Signal implementation for `CustomEvent`, to dispatch and listen;
|
|
432
|
+
|
|
433
|
+
```js
|
|
434
|
+
/**
|
|
435
|
+
* @template {IsListSignal} isList
|
|
436
|
+
* - boolean;
|
|
437
|
+
*/
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
#### reference:`EventSignal.map`
|
|
441
|
+
- `Map` of `EventSignal`, using the `stringName` of the `EventSignal_instance` as `key`;
|
|
442
|
+
|
|
443
|
+
```js
|
|
444
|
+
/**
|
|
445
|
+
* @type {Map<string, EventSignal>}
|
|
446
|
+
*/
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### reference:`EventSignal.get`
|
|
450
|
+
- the constructor it self is set to `private`;
|
|
451
|
+
- it's globally queued:
|
|
452
|
+
>- the `Promise` nature is to prevent race condition on creating the instance;
|
|
453
|
+
|
|
454
|
+
```js
|
|
455
|
+
/**
|
|
456
|
+
* @param {string} stringName
|
|
457
|
+
* @param {IsListSignal} [isList_]
|
|
458
|
+
* @returns {Promise<EventSignal>}
|
|
459
|
+
*/
|
|
460
|
+
```
|
|
461
|
+
- <i>example</i>:
|
|
462
|
+
```js
|
|
463
|
+
import { EventSignal } from 'vivth';
|
|
464
|
+
|
|
465
|
+
const myEventSignal = await EventSignal.get('dataEvent');
|
|
466
|
+
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
#### reference:`EventSignal_instance.dispatch`
|
|
470
|
+
- is [Signal](#signal) or [ListSignal](#listsignal) instance, depending on the `isList` argument;
|
|
471
|
+
- if needed to pass along the messages, it can be used as `dispatcher` and `listener` at the same time;
|
|
472
|
+
- is `lazily` created;
|
|
473
|
+
|
|
474
|
+
```js
|
|
475
|
+
/**
|
|
476
|
+
* @type {Signal|ListSignal}
|
|
477
|
+
*/
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
#### reference:`EventSignal_instance.listen`
|
|
481
|
+
- is [Derived](#derived) or [ListDerived](#listderived) instance, depending on the `isList` argument;
|
|
482
|
+
- can be used as listener when passed down value shouldn't be modified manually;
|
|
483
|
+
- is `lazily` created along with `dispatch`, if `listen` is accessed first, then `dispatch` will also be created automatically;
|
|
484
|
+
|
|
485
|
+
```js
|
|
486
|
+
/**
|
|
487
|
+
* @type {Derived|ListDerived}
|
|
488
|
+
*/
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
#### reference:`EventSignal.remove`
|
|
492
|
+
- methods of this static property is lazily created;
|
|
493
|
+
- remove signal and effect subscription of the named `EventSignal_instance`;
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
#### reference:`EventSignal.remove.subscriber`
|
|
497
|
+
- remove subscriber from the named `EventSignal_instance`;
|
|
498
|
+
|
|
499
|
+
```js
|
|
500
|
+
/**
|
|
501
|
+
* @param {string} name
|
|
502
|
+
* @param {import('./Effect.mjs').Effect} effect
|
|
503
|
+
* @returns {void}
|
|
504
|
+
*/
|
|
505
|
+
```
|
|
506
|
+
- <i>example</i>:
|
|
507
|
+
```js
|
|
508
|
+
import { EventSignal } from 'vivth';
|
|
509
|
+
|
|
510
|
+
EventSignal.remove.subscriber('yourEventSignalName', yourEffectInstance);
|
|
511
|
+
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
#### reference:`EventSignal.remove.allSubscribers`
|
|
515
|
+
- remove all subscribers from the named `EventSignal_instance`;
|
|
516
|
+
|
|
517
|
+
```js
|
|
518
|
+
/**
|
|
519
|
+
* @param {string} name
|
|
520
|
+
* @returns {void}
|
|
521
|
+
*/
|
|
522
|
+
```
|
|
523
|
+
- <i>example</i>:
|
|
524
|
+
```js
|
|
525
|
+
import { EventSignal } from 'vivth';
|
|
526
|
+
|
|
527
|
+
EventSignal.remove.allSubscribers('yourEventSignalName');
|
|
528
|
+
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
#### reference:`EventSignal.remove.refs`
|
|
532
|
+
- remove reference of the `proxySignals` of the named `EventSignal_instance`;
|
|
533
|
+
|
|
534
|
+
```js
|
|
535
|
+
/**
|
|
536
|
+
* @param {string} name
|
|
537
|
+
* @returns {void}
|
|
538
|
+
*/
|
|
539
|
+
```
|
|
540
|
+
- <i>example</i>:
|
|
541
|
+
```js
|
|
542
|
+
import { EventSignal } from 'vivth';
|
|
543
|
+
|
|
544
|
+
EventSignal.remove.refs('yourEventSignalName');
|
|
545
|
+
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
#### reference:`EventSignal_instance.remove.subscriber`
|
|
549
|
+
- remove subscriber from the `EventSignal_instance`;
|
|
550
|
+
|
|
551
|
+
```js
|
|
552
|
+
/**
|
|
553
|
+
* @param {import('./Effect.mjs').Effect} effect
|
|
554
|
+
* @returns {void}
|
|
555
|
+
*/
|
|
556
|
+
```
|
|
557
|
+
- <i>example</i>:
|
|
558
|
+
```js
|
|
559
|
+
eventSignal_instance.remove.subscriber(yourEffectInstance);
|
|
560
|
+
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
#### reference:`EventSignal_instance.remove.allSubscribers`
|
|
564
|
+
- remove allSubscribers from the `EventSignal_instance`;
|
|
565
|
+
|
|
566
|
+
```js
|
|
567
|
+
/**
|
|
568
|
+
* @type {()=>void}
|
|
569
|
+
*/
|
|
570
|
+
```
|
|
571
|
+
- <i>example</i>:
|
|
572
|
+
```js
|
|
573
|
+
eventSignal_instance.remove.allSubscribers();
|
|
574
|
+
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
#### reference:`EventSignal_instance.remove.ref`
|
|
578
|
+
- remove reference of the `proxySignals` of the `EventSignal_instance`;
|
|
579
|
+
|
|
580
|
+
```js
|
|
581
|
+
/**
|
|
582
|
+
* @type {()=>void}
|
|
583
|
+
*/
|
|
584
|
+
```
|
|
585
|
+
- <i>example</i>:
|
|
586
|
+
```js
|
|
587
|
+
eventSignal_instance.remove.ref();
|
|
588
|
+
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
592
|
+
|
|
593
|
+
<h2 id="listderived">ListDerived</h2>
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
#### reference:`ListDerived`
|
|
597
|
+
- class to create `dervivedList` that satisfy `Array<Record<string, string>>`;
|
|
598
|
+
- usefull for `derivedLoops`, e.g. temporary search values;
|
|
599
|
+
- is a `Derived` instance;
|
|
600
|
+
|
|
601
|
+
```js
|
|
602
|
+
/**
|
|
603
|
+
* @template {ListArg} LA
|
|
604
|
+
* @extends {Derived<LA[]>}
|
|
605
|
+
*/
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
#### reference:`new ListDerived`
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
```js
|
|
612
|
+
/**
|
|
613
|
+
* @param {(effectInstanceOptions:Effect["options"])=>Promise<LA[]>} derivedFunction
|
|
614
|
+
*/
|
|
615
|
+
```
|
|
616
|
+
- <i>example</i>:
|
|
617
|
+
```js
|
|
618
|
+
import { ListSignal, ListDerived } from 'vivth';
|
|
619
|
+
|
|
620
|
+
const listExample = new ListSignal([
|
|
621
|
+
{key1: "test1"},
|
|
622
|
+
{key1: "test2"},
|
|
623
|
+
]);
|
|
624
|
+
|
|
625
|
+
export const listDerivedExample = new ListDerived(async({ subscribe }) => {
|
|
626
|
+
// becarefull to not mutate the reference value
|
|
627
|
+
return subscribe(listExample).value.filter((val) => {
|
|
628
|
+
// subscribe(listExample).structuredClone can be used as alternative
|
|
629
|
+
// filter logic
|
|
630
|
+
})
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
636
|
+
|
|
637
|
+
<h2 id="listsignal">ListSignal</h2>
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
#### reference:`ListSignal`
|
|
641
|
+
- class to create list that satisfy `Array<Record<string, string>>`.
|
|
43
642
|
|
|
44
|
-
|
|
643
|
+
```js
|
|
644
|
+
/**
|
|
645
|
+
* @template {import('../types/ListArg.mjs').ListArg} LA
|
|
646
|
+
* @extends {Signal<LA[]>}
|
|
647
|
+
*/
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
#### reference:`ListSignal.isValid`
|
|
651
|
+
- Checks if the input is an array whose first item (if present) is a plain object
|
|
652
|
+
- with string keys and string values. Allows empty arrays.
|
|
653
|
+
|
|
654
|
+
```js
|
|
655
|
+
/**
|
|
656
|
+
* @param {unknown} value - The value to validate.
|
|
657
|
+
* @returns {value is Array<Record<string, string>>} True if the first item is a valid string record or array is empty.
|
|
658
|
+
*/
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
#### reference:`new ListSignal`
|
|
662
|
+
- usefull for `loops`;
|
|
663
|
+
|
|
664
|
+
```js
|
|
665
|
+
/**
|
|
666
|
+
* @param {LA[]} [value]
|
|
667
|
+
*/
|
|
668
|
+
```
|
|
669
|
+
- <i>example</i>:
|
|
670
|
+
```js
|
|
671
|
+
import { ListSignal } from 'vivth';
|
|
672
|
+
|
|
673
|
+
const listExample = new ListSignal([
|
|
674
|
+
{key1: "test1",},
|
|
675
|
+
{key1: "test2",},
|
|
676
|
+
]);
|
|
677
|
+
|
|
678
|
+
```
|
|
45
679
|
|
|
46
|
-
```js
|
|
47
680
|
* @typedef {[callback:()=>(any|Promise<any>),debounce?:(number)]} queueFIFODetails
|
|
48
681
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this class provides `QFIFO.makeQClass`;
|
|
682
|
+
#### reference:`ListSignal_instance.value:getter`
|
|
683
|
+
- reference to original inputed `value`;
|
|
52
684
|
|
|
53
|
-
|
|
685
|
+
```js
|
|
686
|
+
/**
|
|
687
|
+
* @type {LA[]}
|
|
688
|
+
*/
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
#### reference:`ListSignal_instance.value:setter`
|
|
692
|
+
- you cannot mannually set`value` `ListSignal_instance`;
|
|
693
|
+
|
|
694
|
+
```js
|
|
695
|
+
/**
|
|
696
|
+
* @private
|
|
697
|
+
* @type {LA[]}
|
|
698
|
+
*/
|
|
699
|
+
```
|
|
54
700
|
|
|
55
|
-
|
|
701
|
+
#### reference:`ListSignal_instance.arrayMethods`
|
|
702
|
+
- methods collection that mimics `Array` API;
|
|
703
|
+
- calling this methods will notify subscribers for changes, except for some;
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
#### reference:`ListSignal_instance.arrayMethods.structuredClone:getter`
|
|
707
|
+
- reference to structuredClone elements of `value`;
|
|
708
|
+
- calling doesn't notify
|
|
709
|
+
|
|
710
|
+
```js
|
|
711
|
+
/**
|
|
712
|
+
* @type {Array<LA>}
|
|
713
|
+
*/
|
|
714
|
+
```
|
|
56
715
|
|
|
57
|
-
- a class for Queue;
|
|
58
716
|
new PingUnique(uniqueID, async () => {
|
|
59
|
-
|
|
717
|
+
#### reference:`ListSignal_instance.arrayMethods.push`
|
|
718
|
+
- appends new elements to the end;
|
|
60
719
|
|
|
61
|
-
|
|
720
|
+
```js
|
|
721
|
+
/**
|
|
722
|
+
* @param {...LA} listArg
|
|
723
|
+
* @returns {void}
|
|
724
|
+
*/
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
#### reference:`ListSignal_instance.arrayMethods.shift`
|
|
728
|
+
- removes the first element;
|
|
729
|
+
|
|
730
|
+
```js
|
|
731
|
+
/**
|
|
732
|
+
* @type {()=>void}
|
|
733
|
+
*/
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
#### reference:`ListSignal_instance.arrayMethods.unshift`
|
|
737
|
+
- inserts new element at the start;
|
|
738
|
+
|
|
739
|
+
```js
|
|
740
|
+
/**
|
|
741
|
+
* @param {...LA} listArg
|
|
742
|
+
* @returns {void}
|
|
743
|
+
*/
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
#### reference:`ListSignal_instance.arrayMethods.slice`
|
|
747
|
+
- for both start and end, a negative index can be used to indicate an offset from the end of the data. For example, -2 refers to the second to last element of the data;
|
|
748
|
+
|
|
749
|
+
```js
|
|
750
|
+
/**
|
|
751
|
+
* @param {number} [start]
|
|
752
|
+
* - the beginning index of the specified portion of the data. If start is undefined, then the slice begins at index 0.
|
|
753
|
+
* @param {number} [end]
|
|
754
|
+
* - the end index of the specified portion of the data. This is exclusive of the element at the index 'end'. If end is undefined, then the slice extends to the end of the data.
|
|
755
|
+
* @returns {void}
|
|
756
|
+
*/
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
#### reference:`ListSignal_instance.arrayMethods.replace`
|
|
760
|
+
- replace whole `List` data with new array.
|
|
761
|
+
|
|
762
|
+
```js
|
|
763
|
+
/**
|
|
764
|
+
* @param {LA[]} listArgs
|
|
765
|
+
* - new array in place of the deleted array.
|
|
766
|
+
* @returns {void}
|
|
767
|
+
*/
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
#### reference:`ListSignal_instance.arrayMethods.splice`
|
|
771
|
+
- removes elements from an data and, if necessary, inserts new elements in their place;
|
|
772
|
+
|
|
773
|
+
```js
|
|
774
|
+
/**
|
|
775
|
+
* @param {number} start
|
|
776
|
+
* - The zero-based location in the data from which to start removing elements.
|
|
777
|
+
* @param {number} deleteCount
|
|
778
|
+
* -The number of elements to remove.
|
|
779
|
+
* @param {...LA} listArg
|
|
780
|
+
* - new data in place of the deleted data.
|
|
781
|
+
* @returns {void}
|
|
782
|
+
*/
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
#### reference:`ListSignal_instance.arrayMethods.swap`
|
|
786
|
+
- swap `List` data between two indexes;
|
|
787
|
+
|
|
788
|
+
```js
|
|
789
|
+
/**
|
|
790
|
+
* @param {number} indexA
|
|
791
|
+
* @param {number} indexB
|
|
792
|
+
* @returns {void}
|
|
793
|
+
*/
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
#### reference:`ListSignal_instance.arrayMethods.modify`
|
|
797
|
+
- modify `List` element at specific index;
|
|
798
|
+
|
|
799
|
+
```js
|
|
800
|
+
/**
|
|
801
|
+
* @param {number} index
|
|
802
|
+
* @param {Partial<LA>} listArg
|
|
803
|
+
* @returns {void}
|
|
804
|
+
*/
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
#### reference:`ListSignal_instance.arrayMethods.remove`
|
|
808
|
+
- remove `List` element at specific index;
|
|
809
|
+
|
|
810
|
+
```js
|
|
811
|
+
/**
|
|
812
|
+
* @param {number} index
|
|
813
|
+
* @returns {void}
|
|
814
|
+
*/
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
#### reference:`ListSignal_instance.arrayMethods.reverse`
|
|
818
|
+
- reverses the elements in an `List` in place.
|
|
819
|
+
|
|
820
|
+
```js
|
|
821
|
+
/**
|
|
822
|
+
* @returns {void}
|
|
823
|
+
*/
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
#### reference:`ListSignal_instance.arrayMethods.pop`
|
|
827
|
+
- removes the last element;
|
|
828
|
+
|
|
829
|
+
```js
|
|
830
|
+
/**
|
|
831
|
+
* @returns {void}
|
|
832
|
+
*/
|
|
833
|
+
```
|
|
62
834
|
|
|
63
|
-
<
|
|
835
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
64
836
|
|
|
65
|
-
|
|
66
|
-
behaviour:
|
|
67
|
-
this class provides `Q.makeQClass`;
|
|
837
|
+
<h2 id="paths">Paths</h2>
|
|
68
838
|
|
|
69
|
-
*) <sub>[go to exported list](#exported-api-and-type-list)</sub>
|
|
70
839
|
|
|
71
|
-
|
|
840
|
+
#### reference:`Paths`
|
|
841
|
+
- class helpers to define pathReference;
|
|
842
|
+
- is a singleton;
|
|
72
843
|
|
|
73
|
-
```js
|
|
74
844
|
* @typedef {[callback:()=>(any|Promise<any>),debounce?:(number)]} queueFIFODetails
|
|
75
845
|
*/
|
|
76
|
-
a class for Queue;
|
|
77
|
-
for minimal total bundle size use `function` [NewPingFIFO](#newpingfifo) instead;
|
|
78
|
-
this class provides `QFIFO.makeQClass`;
|
|
79
846
|
|
|
80
|
-
|
|
847
|
+
#### reference:`new Paths`
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
```js
|
|
851
|
+
/**
|
|
852
|
+
* @param {Object} options
|
|
853
|
+
* @param {string} options.root
|
|
854
|
+
* - browser: location.origin
|
|
855
|
+
* - node/bun compatible: process?.env?.INIT_CWD ?? process?.cwd();
|
|
856
|
+
* - deno: Deno.env.get("INIT_CWD") ?? Deno.cwd(); need for `deno run --allow-env --allow-read your_script.ts`
|
|
857
|
+
* - other: you need to check your JSRuntime for the rootPath reference;
|
|
858
|
+
*/
|
|
859
|
+
```
|
|
860
|
+
- <i>example</i>:
|
|
861
|
+
```js
|
|
862
|
+
import { Paths } from 'vivth';
|
|
863
|
+
|
|
864
|
+
new Paths({
|
|
865
|
+
root: location.origin,
|
|
866
|
+
})
|
|
867
|
+
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
#### reference:`Paths.root:getter`
|
|
871
|
+
- reference for rootPath
|
|
872
|
+
- `Paths` needed to be instantiated via:
|
|
873
|
+
>- `Paths` constructor;
|
|
874
|
+
>- `Setup.paths` constructor;
|
|
875
|
+
|
|
876
|
+
```js
|
|
877
|
+
/**
|
|
878
|
+
* @type {string}
|
|
879
|
+
*/
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
#### reference:`Paths.normalize`
|
|
883
|
+
- normalize path separator to forward slash `/`;
|
|
884
|
+
|
|
885
|
+
```js
|
|
886
|
+
/**
|
|
887
|
+
* @param {string} path_
|
|
888
|
+
* @returns {string}
|
|
889
|
+
*/
|
|
890
|
+
```
|
|
891
|
+
- <i>example</i>:
|
|
892
|
+
```js
|
|
893
|
+
import { Paths } from 'vivth';
|
|
894
|
+
|
|
895
|
+
Paths.normalize('file:\\D:\\myFile.mjs'); // return 'file://D://myFile.mjs'
|
|
896
|
+
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
900
|
+
|
|
901
|
+
<h2 id="qchannel">QChannel</h2>
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
#### reference:`QChannel`
|
|
905
|
+
- class for `Queue` handling;
|
|
906
|
+
|
|
907
|
+
```js
|
|
908
|
+
/**
|
|
909
|
+
* @template {AnyButUndefinedType} T
|
|
910
|
+
*/
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
#### reference:`QChannel.makeQClass`
|
|
914
|
+
- to modify `MapReference`
|
|
915
|
+
|
|
916
|
+
```js
|
|
917
|
+
/**
|
|
918
|
+
* @param {Map<AnyButUndefinedType, [Promise<any>, {}]>} uniqueMap
|
|
919
|
+
* @returns {typeof QChannel}
|
|
920
|
+
* - usefull for Queue primitive on multiple library but single reference, like the Web by making the `Map` on `window` object;
|
|
921
|
+
*/
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
#### reference:`QChannel.fifo`
|
|
925
|
+
- first in first out handler
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
#### reference:`QChannel.fifo.key`
|
|
929
|
+
- blocks execution for subsequent calls until the current one finishes.
|
|
930
|
+
|
|
931
|
+
```js
|
|
932
|
+
/**
|
|
933
|
+
* @returns {Promise<QCBFIFOReturn>} Resolves when it's safe to proceed, returning a cleanup function
|
|
934
|
+
*/
|
|
935
|
+
```
|
|
936
|
+
- <i>example</i>:
|
|
937
|
+
```js
|
|
938
|
+
const { resume } = await QChannel.fifo.key();
|
|
939
|
+
// blocks all `FIFO` called using this method and QChannel.fifoCallback;
|
|
940
|
+
resume();
|
|
941
|
+
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
#### reference:`QChannel.fifo.callback`
|
|
945
|
+
- blocks execution for subsequent calls until the current one finishes.
|
|
946
|
+
|
|
947
|
+
```js
|
|
948
|
+
/**
|
|
949
|
+
* @template ResultType
|
|
950
|
+
* @param {()=>Promise<ResultType>} asyncCallback
|
|
951
|
+
* @returns {Promise<[ResultType|undefined, Error|undefined]>}
|
|
952
|
+
*/
|
|
953
|
+
```
|
|
954
|
+
- <i>example</i>:
|
|
955
|
+
```js
|
|
956
|
+
const [result, error] = await QChannel.fifo.callback(async () = > {
|
|
957
|
+
// code
|
|
958
|
+
})
|
|
959
|
+
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
#### reference:`QChannel_instance.clear`
|
|
963
|
+
- clear up all queued on the instance;
|
|
964
|
+
- only clear up the reference, the already called will not be stoped;
|
|
965
|
+
|
|
966
|
+
```js
|
|
967
|
+
/**
|
|
968
|
+
* @returns {void}
|
|
969
|
+
*/
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
#### reference:`QChannel_instance.key`
|
|
973
|
+
- each `QChannelInstance` are managing it's own `queue`, and will not `await` for other `QChannelInstance`;
|
|
974
|
+
- caveat:
|
|
975
|
+
>- need to manually call resume();
|
|
976
|
+
>- slightly more performant than `callback`;
|
|
977
|
+
|
|
978
|
+
```js
|
|
979
|
+
/**
|
|
980
|
+
* @param {T} keyID
|
|
981
|
+
* @returns {Promise<QCBReturn>}
|
|
982
|
+
*/
|
|
983
|
+
```
|
|
984
|
+
- <i>example</i>:
|
|
985
|
+
```js
|
|
986
|
+
const q = new QChannel();
|
|
987
|
+
const handler = async () => {
|
|
988
|
+
const { resume, isLastOnQ } = await q.key(keyID);
|
|
989
|
+
// if (!isLastOnQ) { // imperative debounce if needed
|
|
990
|
+
// resume();
|
|
991
|
+
// return;
|
|
992
|
+
// }
|
|
993
|
+
// don't forget to call resume before any returns;
|
|
994
|
+
// blocks only if keyID is the same, until resume is called;
|
|
995
|
+
resume(); // don't forget to call resume before any returns;
|
|
996
|
+
return 'something';
|
|
997
|
+
}
|
|
998
|
+
handler();
|
|
999
|
+
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
#### reference:`QChannel_instance.callback`
|
|
1003
|
+
- `callbackBlock` with error as value:
|
|
1004
|
+
- caveat:
|
|
1005
|
+
>- no need to manually call resume();
|
|
1006
|
+
>- slightly less performant than `callback`;
|
|
1007
|
+
|
|
1008
|
+
```js
|
|
1009
|
+
/**
|
|
1010
|
+
* @template ResultType
|
|
1011
|
+
* @param {T} keyID
|
|
1012
|
+
* @param {(options:Omit<QCBReturn, "resume">)=>Promise<ResultType>} asyncCallback
|
|
1013
|
+
* @returns {Promise<[ResultType|undefined, Error|undefined]>}
|
|
1014
|
+
*/
|
|
1015
|
+
```
|
|
1016
|
+
- <i>example</i>:
|
|
1017
|
+
```js
|
|
1018
|
+
const q = new QChannel();
|
|
1019
|
+
const [result, error] = await q.callback(keyID, async ({ isLastOnQ }) = > {
|
|
1020
|
+
// if (!isLastOnQ) { // imperative debounce if needed
|
|
1021
|
+
// return;
|
|
1022
|
+
// }
|
|
1023
|
+
// code
|
|
1024
|
+
})
|
|
1025
|
+
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1029
|
+
|
|
1030
|
+
<h2 id="safeexit">SafeExit</h2>
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
#### reference:`SafeExit`
|
|
1034
|
+
- class helper for describing how to Safely Response on exit events
|
|
1035
|
+
- singleton;
|
|
1036
|
+
|
|
1037
|
+
```js
|
|
1038
|
+
/**
|
|
1039
|
+
* @template {[string, ...string[]]} ExitEventNames
|
|
1040
|
+
*/
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
#### reference:`SafeExit.instance`
|
|
1044
|
+
- only accessible after instantiation;
|
|
1045
|
+
|
|
1046
|
+
```js
|
|
1047
|
+
/**
|
|
1048
|
+
* @type {SafeExit}
|
|
1049
|
+
*/
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
#### reference:`new SafeExit`
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
```js
|
|
1056
|
+
/**
|
|
1057
|
+
* @param {Object} options
|
|
1058
|
+
* @param {ExitEventNames} options.exitEventNames
|
|
1059
|
+
* @param {(eventName:string)=>void} [options.exitCallbackListeners]
|
|
1060
|
+
* - default value
|
|
1061
|
+
* ```js
|
|
1062
|
+
* (eventName) => {
|
|
1063
|
+
* process.once(eventName, function () {
|
|
1064
|
+
* SafeExit.instance.exiting.correction(true);
|
|
1065
|
+
* Console.log(`safe exit via "${eventName}"`);
|
|
1066
|
+
* });
|
|
1067
|
+
* };
|
|
1068
|
+
* ```
|
|
1069
|
+
* - if your exit callback doesn't uses `process` global object you need to input on the SafeExit instantiation
|
|
1070
|
+
*/
|
|
1071
|
+
```
|
|
1072
|
+
- <i>example</i>:
|
|
1073
|
+
```js
|
|
1074
|
+
import { SafeExit, Console } from 'vivth';
|
|
1075
|
+
|
|
1076
|
+
new SafeExit({
|
|
1077
|
+
// exitEventNames are blank by default, you need to manually name them all;
|
|
1078
|
+
exitEventNames: ['SIGINT', 'SIGTERM', ...otherExitEventNames],
|
|
1079
|
+
// optional deno example
|
|
1080
|
+
exitCallbackListeners = (eventName) => {
|
|
1081
|
+
const sig = Deno.signal(eventName);
|
|
1082
|
+
for await (const _ of sig) {
|
|
1083
|
+
exiting.correction(true);
|
|
1084
|
+
sig.dispose();
|
|
1085
|
+
Console.log(`safe exit via "${eventName}"`);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
```
|
|
1091
|
+
|
|
1092
|
+
#### reference:`SafeExit_instance.exiting`
|
|
1093
|
+
- optional exit event registration, by listening to it inside an `Effect`;
|
|
1094
|
+
- when the value is `true`, meaning program is exitting;
|
|
1095
|
+
|
|
1096
|
+
```js
|
|
1097
|
+
/**
|
|
1098
|
+
* @type {EnvSignal<boolean>}
|
|
1099
|
+
*/
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
#### reference:`SafeExit_instance.addCallback`
|
|
1103
|
+
- optional exit event registration;
|
|
1104
|
+
- the callbacks will be called when exiting;
|
|
1105
|
+
|
|
1106
|
+
```js
|
|
1107
|
+
/**
|
|
1108
|
+
* @param {()=>(Promise<void>)} cb
|
|
1109
|
+
*/
|
|
1110
|
+
```
|
|
1111
|
+
- <i>example</i>:
|
|
1112
|
+
```js
|
|
1113
|
+
import { SafeExit } from 'vivth';
|
|
1114
|
+
|
|
1115
|
+
SafeExit.instance.addCallback(()=>{
|
|
1116
|
+
// code
|
|
1117
|
+
})
|
|
1118
|
+
|
|
1119
|
+
```
|
|
81
1120
|
|
|
82
|
-
<
|
|
1121
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
83
1122
|
|
|
84
|
-
|
|
85
|
-
for minimal total bundle size use `function` [NewPingUnique](#newpingunique) instead;
|
|
86
|
-
this class provides `QUnique.makeQClass`;
|
|
1123
|
+
<h2 id="setup">Setup</h2>
|
|
87
1124
|
|
|
88
|
-
|
|
1125
|
+
|
|
1126
|
+
#### reference:`Setup`
|
|
1127
|
+
- class with collections of methods/constructors for setting up necessary variables for vivth internal functionalities;
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
#### reference:`Setup.safeExit`
|
|
1131
|
+
- proxy `SafeExit_instance` for Setup
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
- <i>example</i>:
|
|
1135
|
+
```js
|
|
1136
|
+
import { Setup, Console } from 'vivth';
|
|
1137
|
+
|
|
1138
|
+
new Setup.safeExit({
|
|
1139
|
+
// exitEventNames are blank by default, you need to manually name them all;
|
|
1140
|
+
exitEventNames: ['SIGINT', 'SIGTERM', ...otherExitEventNames],
|
|
1141
|
+
// optional deno example
|
|
1142
|
+
exitCallbackListeners = (eventName) => {
|
|
1143
|
+
const sig = Deno.signal(eventName);
|
|
1144
|
+
for await (const _ of sig) {
|
|
1145
|
+
SafeExit.instance.exiting.correction(true);
|
|
1146
|
+
sig.dispose();
|
|
1147
|
+
Console.info(`safe exit via "${eventName}"`);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
|
|
1152
|
+
```
|
|
1153
|
+
|
|
1154
|
+
#### reference:`Setup.paths`
|
|
1155
|
+
- proxy `Paths_instance` for Setup;
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
- <i>example</i>:
|
|
1159
|
+
```js
|
|
1160
|
+
import { Setup } from 'vivth';
|
|
1161
|
+
|
|
1162
|
+
new Setup.paths({
|
|
1163
|
+
root: location.origin, // browser example
|
|
1164
|
+
})
|
|
1165
|
+
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
#### reference:`Setup.workerMain`
|
|
1169
|
+
- proxy `WorkerMainThread_instance` for Setup;
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
- <i>example</i>:
|
|
1173
|
+
```js
|
|
1174
|
+
import { Setup } from 'vivth';
|
|
1175
|
+
|
|
1176
|
+
Setup.workerMain({
|
|
1177
|
+
workerClass: async () => await (import('worker_threads')).Worker,
|
|
1178
|
+
basePath: 'public/assets/js/workers',
|
|
1179
|
+
pathValidator: async (workerPath, root, base) => {
|
|
1180
|
+
const res = await fetch(`${root}/${base}/${workerPath}`);
|
|
1181
|
+
// might also check wheter it need base or not
|
|
1182
|
+
return await res.ok;
|
|
1183
|
+
},
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
#### reference:`Setup.workerThread`
|
|
1189
|
+
- correct `parentPort` reference when needed;
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
- <i>example</i>:
|
|
1193
|
+
```js
|
|
1194
|
+
import { Setup } from 'vivth';
|
|
1195
|
+
|
|
1196
|
+
Setup.workerThread({ parentPort: async () => await import('node:worker_threads') });
|
|
1197
|
+
// that is the default value, if your parentPort/equivalent API is not that;
|
|
1198
|
+
// you need to call this method;
|
|
1199
|
+
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
89
1203
|
|
|
90
1204
|
<h2 id="signal">Signal</h2>
|
|
91
1205
|
|
|
92
|
-
- a class for creating signal;
|
|
93
|
-
can be subscribed by using [New$](#new$) or [NewDerived](#newderived);
|
|
94
|
-
for minimal total bundle size use `function` [NewSignal](#newSignal) instead;
|
|
95
1206
|
|
|
96
|
-
|
|
1207
|
+
#### reference:`Signal`
|
|
1208
|
+
- a class for creating effect to signals;
|
|
1209
|
+
|
|
1210
|
+
```js
|
|
1211
|
+
/**
|
|
1212
|
+
* @template Value
|
|
1213
|
+
*/
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
#### reference:`Signal_instance.subscribers`
|
|
1217
|
+
- subsrcibers reference of this instance;
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
#### reference:`Signal_instance.subscribers.setOf`
|
|
1221
|
+
- subscribedEffects
|
|
97
1222
|
|
|
98
|
-
|
|
1223
|
+
```js
|
|
1224
|
+
/**
|
|
1225
|
+
* @type {Set<Effect>}
|
|
1226
|
+
*/
|
|
1227
|
+
```
|
|
1228
|
+
|
|
1229
|
+
#### reference:`Signal_instance.subscribers.notify`
|
|
1230
|
+
- manually notify on non primitive value or value that have depths;
|
|
1231
|
+
|
|
1232
|
+
```js
|
|
1233
|
+
/**
|
|
1234
|
+
* @param {(options:{signalInstance:Signal<Value>})=>Promise<void>} [callback]
|
|
1235
|
+
* @returns {void}
|
|
1236
|
+
*/
|
|
1237
|
+
```
|
|
1238
|
+
- <i>example</i>:
|
|
1239
|
+
```js
|
|
1240
|
+
// for deep signal like array or object you can:
|
|
1241
|
+
|
|
1242
|
+
const arraySignal = new Signal([1,2]);
|
|
1243
|
+
arraySignal.value.push(3);
|
|
1244
|
+
arraySignal.subscribers.notify();
|
|
1245
|
+
|
|
1246
|
+
// OR for more complex mutation:
|
|
1247
|
+
|
|
1248
|
+
const objectSignal = new Signal({a:'test', b:'test'});
|
|
1249
|
+
objectSignal.subscribers.notify(async ({ signalInstance }) => {
|
|
1250
|
+
signalInstance.value['c'] = 'testc';
|
|
1251
|
+
signalInstance.value['d'] = 'testd';
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
#### reference:`Signal_instance.remove`
|
|
1257
|
+
- collection of remove methods
|
|
99
1258
|
|
|
100
|
-
- a function for Queue;
|
|
101
|
-
will wait next execution of the same `arg1`:`objectReferenceID`, without blocking other calls;
|
|
102
1259
|
const objectReferenceID = 'yourUniqueID'; // can be anything, reference to object is preferable;
|
|
103
1260
|
);
|
|
104
1261
|
|
|
105
|
-
|
|
1262
|
+
#### reference:`Signal_instance.remove.subscriber`
|
|
1263
|
+
- remove effect subscriber to react from this instance value changes;
|
|
1264
|
+
|
|
1265
|
+
```js
|
|
1266
|
+
/**
|
|
1267
|
+
* @param {Effect} effectInstance
|
|
1268
|
+
* @returns {void}
|
|
1269
|
+
*/
|
|
1270
|
+
```
|
|
1271
|
+
|
|
1272
|
+
#### reference:`Signal_instance.remove.allSubscribers`
|
|
1273
|
+
- remove all effect subscribers to react from this instance value changes;
|
|
1274
|
+
|
|
1275
|
+
```js
|
|
1276
|
+
/**
|
|
1277
|
+
* @type {()=>void}
|
|
1278
|
+
*/
|
|
1279
|
+
```
|
|
1280
|
+
|
|
1281
|
+
#### reference:`Signal_instance.remove.ref`
|
|
1282
|
+
- remove this instance from `vivth` reactivity engine, and nullify it's own value;
|
|
1283
|
+
|
|
1284
|
+
```js
|
|
1285
|
+
/**
|
|
1286
|
+
* @type {()=>void}
|
|
1287
|
+
*/
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
#### reference:`new Signal`
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
```js
|
|
1294
|
+
/**
|
|
1295
|
+
* @param {Value} value
|
|
1296
|
+
*/
|
|
1297
|
+
```
|
|
1298
|
+
- <i>example</i>:
|
|
1299
|
+
```js
|
|
1300
|
+
import { Signal, Effect } from 'vivth';
|
|
1301
|
+
|
|
1302
|
+
const count = new Signal(0);
|
|
1303
|
+
|
|
1304
|
+
```
|
|
1305
|
+
|
|
1306
|
+
#### reference:`Signal_instance.prev:getter`
|
|
1307
|
+
- value before change;
|
|
1308
|
+
|
|
1309
|
+
```js
|
|
1310
|
+
/**
|
|
1311
|
+
* @type {Value}
|
|
1312
|
+
*/
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
#### reference:`Signal_instance.value:getter`
|
|
1316
|
+
- value after change;
|
|
1317
|
+
|
|
1318
|
+
```js
|
|
1319
|
+
/**
|
|
1320
|
+
* @type {Value}
|
|
1321
|
+
*/
|
|
1322
|
+
```
|
|
1323
|
+
- <i>example</i>:
|
|
1324
|
+
```js
|
|
1325
|
+
import { Signal, Effect, Derived } from 'vivth';
|
|
1326
|
+
|
|
1327
|
+
const count = new Signal(0);
|
|
1328
|
+
count.value; // not reactive
|
|
1329
|
+
|
|
1330
|
+
new Effect(async ({ subscribe }) =>{
|
|
1331
|
+
const countValue = subscribe(count).value; // reactive
|
|
1332
|
+
})
|
|
1333
|
+
const oneMoreThanCount = new Effect(async ({ subscribe }) =>{
|
|
1334
|
+
return subscribe(count).value + 1; // reactive
|
|
1335
|
+
})
|
|
1336
|
+
|
|
1337
|
+
```
|
|
1338
|
+
|
|
1339
|
+
#### reference:`Signal_instance.value:setter`
|
|
1340
|
+
- assign new value then automatically notify all subscribers;
|
|
1341
|
+
|
|
1342
|
+
```js
|
|
1343
|
+
/**
|
|
1344
|
+
* @type {Value}
|
|
1345
|
+
*/
|
|
1346
|
+
```
|
|
1347
|
+
- <i>example</i>:
|
|
1348
|
+
```js
|
|
1349
|
+
import { Signal } from 'vivth';
|
|
1350
|
+
|
|
1351
|
+
const count = new Signal(0);
|
|
1352
|
+
count.value++;
|
|
1353
|
+
// OR
|
|
1354
|
+
count.value = 9;
|
|
1355
|
+
|
|
1356
|
+
```
|
|
1357
|
+
|
|
1358
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1359
|
+
|
|
1360
|
+
<h2 id="workermainthread">WorkerMainThread</h2>
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
#### reference:`WorkerMainThread`
|
|
1364
|
+
- class helper to create `Worker` instance;
|
|
1365
|
+
|
|
1366
|
+
```js
|
|
1367
|
+
/**
|
|
1368
|
+
* @template {WorkerThread} WT
|
|
1369
|
+
*/
|
|
1370
|
+
```
|
|
1371
|
+
|
|
1372
|
+
#### reference:`WorkerMainThread.setup`
|
|
1373
|
+
- need to be called first, before any `WorkerMainThread` instantiation:
|
|
1374
|
+
|
|
1375
|
+
```js
|
|
1376
|
+
/**
|
|
1377
|
+
* @param {Object} param0
|
|
1378
|
+
* @param {typeof WorkerMainThread["workerClass"]} param0.workerClass
|
|
1379
|
+
* @param {typeof WorkerMainThread["pathValidator"]} param0.pathValidator
|
|
1380
|
+
* ```js
|
|
1381
|
+
* async(relativePath) => {
|
|
1382
|
+
* // verify whether relativePath exist, then return the full path
|
|
1383
|
+
* // use fetch | fs, chained with Paths.instance.root + WorkerMainThread.basePath;
|
|
1384
|
+
* }
|
|
1385
|
+
* ```
|
|
1386
|
+
* @param {typeof WorkerMainThread["basePath"]} [param0.basePath]
|
|
1387
|
+
* - additonal realtivePath from rootPath;
|
|
1388
|
+
* - default: '';
|
|
1389
|
+
*/
|
|
1390
|
+
```
|
|
1391
|
+
- <i>example</i>:
|
|
1392
|
+
```js
|
|
1393
|
+
import { WorkerMainThread } from 'vivth';
|
|
1394
|
+
|
|
1395
|
+
WorkerMainThread.setup({
|
|
1396
|
+
workerClass: async () => await (import('worker_threads')).Worker,
|
|
1397
|
+
basePath: 'public/assets/js/workers',
|
|
1398
|
+
pathValidator: async (workerPath, root, base) => {
|
|
1399
|
+
const res = await fetch(`${root}/${base}/${workerPath}`);
|
|
1400
|
+
// might also check wheter it need base or not
|
|
1401
|
+
return await res.ok;
|
|
1402
|
+
},
|
|
1403
|
+
});
|
|
1404
|
+
|
|
1405
|
+
```
|
|
1406
|
+
|
|
1407
|
+
#### reference:`WorkerMainThread.workerClass`
|
|
1408
|
+
- reference for `Worker` class;
|
|
1409
|
+
- edit via `setup`;
|
|
1410
|
+
|
|
1411
|
+
```js
|
|
1412
|
+
/**
|
|
1413
|
+
* @type {()=>Promise<typeof Worker|typeof import('worker_threads').Worker>}
|
|
1414
|
+
*/
|
|
1415
|
+
```
|
|
1416
|
+
|
|
1417
|
+
#### reference:`WorkerMainThread.basePath`
|
|
1418
|
+
- reference for worker file `basePath`;
|
|
1419
|
+
- edit via `setup`;
|
|
1420
|
+
|
|
1421
|
+
```js
|
|
1422
|
+
/**
|
|
1423
|
+
* @type {string}
|
|
1424
|
+
*/
|
|
1425
|
+
```
|
|
1426
|
+
|
|
1427
|
+
#### reference:`WorkerMainThread.pathValidator`
|
|
1428
|
+
- reference for validating path;
|
|
1429
|
+
- edit via `setup`;
|
|
1430
|
+
|
|
1431
|
+
```js
|
|
1432
|
+
/**
|
|
1433
|
+
* @type {(paths:{worker: string, root:string, base: string})=>Promise<string>}
|
|
1434
|
+
*/
|
|
1435
|
+
```
|
|
1436
|
+
|
|
1437
|
+
#### reference:`new WorkerMainThread`
|
|
1438
|
+
- create Worker_instance;
|
|
1439
|
+
|
|
1440
|
+
```js
|
|
1441
|
+
/**
|
|
1442
|
+
* @param {string} handler
|
|
1443
|
+
* - if `isInline` === `false`, `handler` should be:
|
|
1444
|
+
* >- pointing to worker thread file; WHICH
|
|
1445
|
+
* >- the path must be relative to `projectRoot`;
|
|
1446
|
+
* - if `isInline` === `true`, `handler` should be
|
|
1447
|
+
* >- string literal of prebundled worker thread script; OR
|
|
1448
|
+
* >- manually made string literal of worker thread script;
|
|
1449
|
+
* @param {Omit<WorkerOptions|import('worker_threads').WorkerOptions, 'eval'|'type'>} [options]
|
|
1450
|
+
* @param {boolean} [isInline]
|
|
1451
|
+
*/
|
|
1452
|
+
```
|
|
1453
|
+
- <i>example</i>:
|
|
1454
|
+
```js
|
|
1455
|
+
import { WorkerMainThread } from 'vivth';
|
|
1456
|
+
|
|
1457
|
+
export const myDoubleWorker = new WorkerMainThread('./doubleWorkerThread.mjs');
|
|
1458
|
+
|
|
1459
|
+
```
|
|
1460
|
+
|
|
1461
|
+
#### reference:`WorkerMainThread.isBrowser:getter`
|
|
1462
|
+
- check whether js run in browser
|
|
1463
|
+
|
|
1464
|
+
```js
|
|
1465
|
+
/**
|
|
1466
|
+
* @type {boolean}
|
|
1467
|
+
*/
|
|
1468
|
+
```
|
|
1469
|
+
|
|
1470
|
+
#### reference:`WorkerMainThread_instance.terminate`
|
|
1471
|
+
- terminate all signals that are used on this instance;
|
|
1472
|
+
|
|
1473
|
+
```js
|
|
1474
|
+
/**
|
|
1475
|
+
* @type {()=>void}
|
|
1476
|
+
*/
|
|
1477
|
+
```
|
|
1478
|
+
|
|
1479
|
+
#### reference:`WorkerMainThread_instance.receiverSignal`
|
|
1480
|
+
- result signal of the processed message;
|
|
1481
|
+
|
|
1482
|
+
```js
|
|
1483
|
+
/**
|
|
1484
|
+
* @type {Derived<WorkerResult<WT["Post"]>>}
|
|
1485
|
+
*/
|
|
1486
|
+
```
|
|
1487
|
+
- <i>example</i>:
|
|
1488
|
+
```js
|
|
1489
|
+
import { Effect } from 'vivth';
|
|
1490
|
+
import { myDoubleWorker } from './myDoubleWorker.mjs';
|
|
1491
|
+
|
|
1492
|
+
const doubleReceiverSignal = myDoubleWorker.receiverSignal;
|
|
1493
|
+
new Effect(async({ subscribe }) => {
|
|
1494
|
+
const value = subscribe(doubleReceiverSignal).value;
|
|
1495
|
+
// code
|
|
1496
|
+
})
|
|
1497
|
+
|
|
1498
|
+
```
|
|
1499
|
+
|
|
1500
|
+
#### reference:`WorkerMainThread_instance.postMessage`
|
|
1501
|
+
- callback to send message to the worker thread;
|
|
1502
|
+
|
|
1503
|
+
```js
|
|
1504
|
+
/**
|
|
1505
|
+
* @type {(event: WT["Receive"])=>void}
|
|
1506
|
+
*/
|
|
1507
|
+
```
|
|
1508
|
+
- <i>example</i>:
|
|
1509
|
+
```js
|
|
1510
|
+
import { myDoubleWorker } from './myDoubleWorker.mjs';
|
|
1511
|
+
|
|
1512
|
+
myDoubleWorker.postMessage(90);
|
|
1513
|
+
|
|
1514
|
+
```
|
|
1515
|
+
|
|
1516
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1517
|
+
|
|
1518
|
+
<h2 id="workerresult">WorkerResult</h2>
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
#### reference:`WorkerResult`
|
|
1522
|
+
- typeHelper for `Worker` message passing;
|
|
1523
|
+
- uses error as value instead;
|
|
1524
|
+
|
|
1525
|
+
```js
|
|
1526
|
+
/**
|
|
1527
|
+
* @template POST
|
|
1528
|
+
*/
|
|
1529
|
+
```
|
|
1530
|
+
|
|
1531
|
+
#### reference:`WorkerResult_instance.data`
|
|
1532
|
+
- result value;
|
|
1533
|
+
|
|
1534
|
+
```js
|
|
1535
|
+
/**
|
|
1536
|
+
* @type {POST}
|
|
1537
|
+
*/
|
|
1538
|
+
```
|
|
1539
|
+
|
|
1540
|
+
#### reference:`WorkerResult_instance.error`
|
|
1541
|
+
- error value;
|
|
1542
|
+
|
|
1543
|
+
```js
|
|
1544
|
+
/**
|
|
1545
|
+
* @type {Error|string|undefined}
|
|
1546
|
+
*/
|
|
1547
|
+
```
|
|
1548
|
+
|
|
1549
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1550
|
+
|
|
1551
|
+
<h2 id="workerthread">WorkerThread</h2>
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
#### reference:`WorkerThread`
|
|
1555
|
+
- class helper for `WorkerThread` creation;
|
|
1556
|
+
|
|
1557
|
+
```js
|
|
1558
|
+
/**
|
|
1559
|
+
* @template Receive
|
|
1560
|
+
* @template Post
|
|
1561
|
+
*/
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
#### reference:`WorkerThread.setup`
|
|
1565
|
+
- need to be called and exported as new `WorkerThread` class reference;
|
|
1566
|
+
|
|
1567
|
+
```js
|
|
1568
|
+
/**
|
|
1569
|
+
* @template Receive_
|
|
1570
|
+
* @template Post_
|
|
1571
|
+
* @param {{parentPort:()=>Promise<any>}} parentPortRef
|
|
1572
|
+
* - correct parentPort reference;
|
|
1573
|
+
* @returns {typeof WorkerThread<Receive_, Post_>}
|
|
1574
|
+
*/
|
|
1575
|
+
```
|
|
1576
|
+
- <i>example</i>:
|
|
1577
|
+
```js
|
|
1578
|
+
import { WorkerThread } from 'vivth';
|
|
1579
|
+
|
|
1580
|
+
WorkerThread.setup({ parentPort: async () => await import('node:worker_threads') });
|
|
1581
|
+
// that is the default value, if your parentPort/equivalent API is not that;
|
|
1582
|
+
// you need to call this method;
|
|
1583
|
+
|
|
1584
|
+
```
|
|
1585
|
+
|
|
1586
|
+
#### reference:`new WorkerThread`
|
|
1587
|
+
- instantiate via created class from `setup` static method;
|
|
1588
|
+
|
|
1589
|
+
```js
|
|
1590
|
+
/**
|
|
1591
|
+
* @param {WorkerThread["handler"]} handler
|
|
1592
|
+
*/
|
|
1593
|
+
```
|
|
1594
|
+
- <i>example</i>:
|
|
1595
|
+
```js
|
|
1596
|
+
import { MyWorkerThread } from './MyWorkerThread.mjs';
|
|
1597
|
+
|
|
1598
|
+
const doubleWorker = new MyWorkerThread((ev, isLastOnQ) => {
|
|
1599
|
+
// if(!isLastOnQ) {
|
|
1600
|
+
// return null; // can be used for imperative debouncing;
|
|
1601
|
+
// }
|
|
1602
|
+
return ev = ev * 2;
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1605
|
+
```
|
|
1606
|
+
|
|
1607
|
+
#### reference:`WorkerThread_instance.handler`
|
|
1608
|
+
- type helper;
|
|
1609
|
+
|
|
1610
|
+
```js
|
|
1611
|
+
/**
|
|
1612
|
+
* @type {(ev: Receive, isLastOnQ:boolean) => Post}
|
|
1613
|
+
*/
|
|
1614
|
+
```
|
|
1615
|
+
|
|
1616
|
+
#### reference:`WorkerThread_instance.Receive`
|
|
1617
|
+
- helper type, hold no actual value;
|
|
1618
|
+
|
|
1619
|
+
```js
|
|
1620
|
+
/**
|
|
1621
|
+
* @type {Receive}
|
|
1622
|
+
*/
|
|
1623
|
+
```
|
|
1624
|
+
|
|
1625
|
+
#### reference:`WorkerThread_instance.Post`
|
|
1626
|
+
- helper type, hold no actual value;
|
|
1627
|
+
|
|
1628
|
+
```js
|
|
1629
|
+
/**
|
|
1630
|
+
* @type {Post}
|
|
1631
|
+
*/
|
|
1632
|
+
```
|
|
1633
|
+
|
|
1634
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1635
|
+
|
|
1636
|
+
<h2 id="base64url">Base64URL</h2>
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
#### reference:`Base64URL`
|
|
1640
|
+
- create inline base64 url;
|
|
1641
|
+
- usage:
|
|
1642
|
+
>- can be extremely usefull to display file on desktop app webview, without exposing http server;
|
|
1643
|
+
|
|
1644
|
+
```js
|
|
1645
|
+
/**
|
|
1646
|
+
* @param {string} fileString
|
|
1647
|
+
* @param {string} mimeType
|
|
1648
|
+
* @param {(string:string)=>string} btoaFunction
|
|
1649
|
+
* - check your js runtime `btoa`;
|
|
1650
|
+
* @returns {string}
|
|
1651
|
+
*/
|
|
1652
|
+
```
|
|
1653
|
+
- <i>example</i>:
|
|
1654
|
+
```js
|
|
1655
|
+
import { Base64URL } from 'vivth'
|
|
1656
|
+
import { fileString } from './fileString.mjs';
|
|
1657
|
+
|
|
1658
|
+
Base64URL(fileString, 'application/javascript', btoa);
|
|
1659
|
+
|
|
1660
|
+
```
|
|
1661
|
+
|
|
1662
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1663
|
+
|
|
1664
|
+
<h2 id="eventnamespace">EventNameSpace</h2>
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
#### reference:`EventNameSpace`
|
|
1668
|
+
- namespacing for event, string as ID, related API;
|
|
1669
|
+
|
|
1670
|
+
```js
|
|
1671
|
+
/**
|
|
1672
|
+
* @type {'vivthEvent'}
|
|
1673
|
+
*/
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1676
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1677
|
+
|
|
1678
|
+
<h2 id="jsautodoc">JSautoDOC</h2>
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
#### reference:`JSautoDOC`
|
|
1682
|
+
- class for auto documenting mjs package/project, using jsdoc;
|
|
1683
|
+
- this autodocumenter uses [chokidar](https://npmjs.com/package/chokidar) under the hood;
|
|
1684
|
+
- this class also is used to generate this `README.md`;
|
|
1685
|
+
- behaviours:
|
|
1686
|
+
>1) export all named exported 'const'|'function'|'async function'|'class', alphanumeric name, started with Capital letter, same name with fileName on `options.pahts.file`;
|
|
1687
|
+
>2) declare typedef of existing typedef with alphanumeric name, started with Capital letter, same name with fileName, and have no valid export like on point <sup>1</sup> on `options.pahts.file`;
|
|
1688
|
+
>3) create `README.md` based on, `options.paths.dir` and `README.src.md`;
|
|
1689
|
+
>4) extract `"at"description` jsdoc:
|
|
1690
|
+
>>- on static/prop that have depths, all of children should have `"at"static`/`"at"instance` `nameOfImmediateParent`, same block but before `"at"description` comment line;
|
|
1691
|
+
>>- `"at"description` are treated as plain `markdown`;
|
|
1692
|
+
>>- first `"at"${string}` after `"at"description` until `"at"example` will be treated as `javascript` comment block on the `markdown`;
|
|
1693
|
+
>>- `"at"example` are treated as `javascript` block on the `markdown` file, and should be placed last on the same comment block;
|
|
1694
|
+
>>- you can always look at `vivth/src` files to check how the source, and the `README.md` and `index.mjs` is documentation/generation results;
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
#### reference:`new JSautoDOC`
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
```js
|
|
1701
|
+
/**
|
|
1702
|
+
* @param {Object} [options]
|
|
1703
|
+
* @param {Object} [options.paths]
|
|
1704
|
+
* @param {string} [options.paths.file]
|
|
1705
|
+
* - entry point;
|
|
1706
|
+
* @param {string} [options.paths.readMe]
|
|
1707
|
+
* - readme target;
|
|
1708
|
+
* @param {string} [options.paths.dir]
|
|
1709
|
+
* - source directory;
|
|
1710
|
+
* @param {string} [options.copyright]
|
|
1711
|
+
* @param {string} [options.tableOfContentTitle]
|
|
1712
|
+
* @param {import('chokidar').ChokidarOptions} [options.option]
|
|
1713
|
+
* - ChokidarOptions;
|
|
1714
|
+
*/
|
|
1715
|
+
```
|
|
1716
|
+
- <i>example</i>:
|
|
1717
|
+
```js
|
|
1718
|
+
import { Console } from '../src/class/Console.mjs';
|
|
1719
|
+
import { Setup } from '../src/class/Setup.mjs';
|
|
1720
|
+
import { JSautoDOC } from '../src/doc/JSautoDOC.mjs';
|
|
1721
|
+
|
|
1722
|
+
const { paths, safeExit } = Setup;
|
|
1723
|
+
|
|
1724
|
+
new paths({
|
|
1725
|
+
root: process?.env?.INIT_CWD ?? process?.cwd(),
|
|
1726
|
+
});
|
|
1727
|
+
|
|
1728
|
+
new safeExit({
|
|
1729
|
+
exitEventNames: ['SIGINT', 'SIGTERM', 'exit'],
|
|
1730
|
+
exitCallbackListeners: (eventName) => {
|
|
1731
|
+
process.once(eventName, function () {
|
|
1732
|
+
safeExit.instance.exiting.correction(true);
|
|
1733
|
+
Console.log(`safe exit via "${eventName}"`);
|
|
1734
|
+
});
|
|
1735
|
+
},
|
|
1736
|
+
});
|
|
1737
|
+
|
|
1738
|
+
new JSautoDOC({
|
|
1739
|
+
paths: { dir: 'src', file: 'index.mjs', readMe: 'README.md' },
|
|
1740
|
+
copyright: 'this library is made and distributed under MIT license;',
|
|
1741
|
+
tableOfContentTitle: 'list of exported API and typehelpers',
|
|
1742
|
+
});
|
|
1743
|
+
|
|
1744
|
+
```
|
|
1745
|
+
|
|
1746
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1747
|
+
|
|
1748
|
+
<h2 id="createimmutable">CreateImmutable</h2>
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
#### reference:`CreateImmutable`
|
|
1752
|
+
- function for create immutable object;
|
|
1753
|
+
- usefull for binding immutable object to global for shared object:
|
|
1754
|
+
>- e.g. to window object in browser;
|
|
1755
|
+
|
|
1756
|
+
```js
|
|
1757
|
+
/**
|
|
1758
|
+
* @template {Object} P
|
|
1759
|
+
* @template {Object} O
|
|
1760
|
+
* @param {string} keyName
|
|
1761
|
+
* @param {P} parent
|
|
1762
|
+
* @param {(this:P)=>O} object
|
|
1763
|
+
* @param {Object} [options]
|
|
1764
|
+
* @param {boolean} [options.lazy]
|
|
1765
|
+
* @return {O}
|
|
1766
|
+
*/
|
|
1767
|
+
```
|
|
1768
|
+
- <i>example</i>:
|
|
1769
|
+
```js
|
|
1770
|
+
import { CreateImmutable } from 'vivth';
|
|
1771
|
+
|
|
1772
|
+
const mappedObject = new Map();
|
|
1773
|
+
|
|
1774
|
+
CreateImmutable(window, 'mySharedObject', {
|
|
1775
|
+
setMap(name_, value) => {
|
|
1776
|
+
mappedObject.set(name_, value)
|
|
1777
|
+
},
|
|
1778
|
+
getMap(name_) => mappedObject.get(name_),
|
|
1779
|
+
})
|
|
1780
|
+
|
|
1781
|
+
```
|
|
1782
|
+
|
|
1783
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1784
|
+
|
|
1785
|
+
<h2 id="eventcheck">EventCheck</h2>
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
#### reference:`EventCheck`
|
|
1789
|
+
- simple validation function for [EventObject](#eventobject), for multiple context, eg: `mainThread` <-> `workerThread`;
|
|
1790
|
+
|
|
1791
|
+
```js
|
|
1792
|
+
/**
|
|
1793
|
+
* @param {any} object
|
|
1794
|
+
* @param {Record<typeof EventNameSpace, string>} eventObject
|
|
1795
|
+
* @returns {boolean}
|
|
1796
|
+
*/
|
|
1797
|
+
```
|
|
1798
|
+
- <i>example</i>:
|
|
1799
|
+
```js
|
|
1800
|
+
import { EventCheck } from 'vivth';
|
|
1801
|
+
import { incomingMessage } from './some/where.mjs';
|
|
1802
|
+
|
|
1803
|
+
const eventObjectPayload = EventObject('worker:exit');
|
|
1804
|
+
// assuming `incomingMessage`, also created using EventObject('worker:exit');
|
|
1805
|
+
// or manually {[EventNameSpace]:'worker:exit'};
|
|
1806
|
+
// which either will result true;
|
|
1807
|
+
|
|
1808
|
+
```
|
|
1809
|
+
|
|
1810
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1811
|
+
|
|
1812
|
+
<h2 id="eventobject">EventObject</h2>
|
|
1813
|
+
|
|
1814
|
+
|
|
1815
|
+
#### reference:`EventObject`
|
|
1816
|
+
- simple object generation function helper for [EventCheck](#eventcheck), for multiple context, eg: `mainThread` <-> `workerThread`;
|
|
1817
|
+
|
|
1818
|
+
```js
|
|
1819
|
+
/**
|
|
1820
|
+
* @template {string} N
|
|
1821
|
+
* @param {N} name
|
|
1822
|
+
* @returns {{[EventNameSpace]: N}}
|
|
1823
|
+
*/
|
|
1824
|
+
```
|
|
1825
|
+
- <i>example</i>:
|
|
1826
|
+
```js
|
|
1827
|
+
import { EventCheck } from 'vivth';
|
|
1828
|
+
import { incomingMessage } from './some/where.mjs';
|
|
1829
|
+
|
|
1830
|
+
const eventObjectPayload = EventObject('worker:exit');
|
|
1831
|
+
// assuming `incomingMessage`, also created using EventObject('worker:exit');
|
|
1832
|
+
// or manually {[EventNameSpace]:'worker:exit'};
|
|
1833
|
+
// which either will result true;
|
|
1834
|
+
|
|
1835
|
+
```
|
|
1836
|
+
|
|
1837
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1838
|
+
|
|
1839
|
+
<h2 id="isasync">IsAsync</h2>
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
#### reference:`IsAsync`
|
|
1843
|
+
- function helper for checking whether `functionReference` is async;
|
|
1844
|
+
|
|
1845
|
+
```js
|
|
1846
|
+
/**
|
|
1847
|
+
* @param {(...any:any)=>(any|Promise<any>)} functionReference
|
|
1848
|
+
* @returns {boolean}
|
|
1849
|
+
*/
|
|
1850
|
+
```
|
|
1851
|
+
- <i>example</i>:
|
|
1852
|
+
```js
|
|
1853
|
+
import { IsAsync } from 'vivth';
|
|
1854
|
+
|
|
1855
|
+
const a = function (params) {
|
|
1856
|
+
// code
|
|
1857
|
+
}
|
|
1858
|
+
const b = async () => {
|
|
1859
|
+
// code
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
IsAsync(a); // false
|
|
1863
|
+
IsAsync(b); // true
|
|
1864
|
+
|
|
1865
|
+
```
|
|
1866
|
+
|
|
1867
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1868
|
+
|
|
1869
|
+
<h2 id="lazyfactory">LazyFactory</h2>
|
|
1870
|
+
|
|
1871
|
+
|
|
1872
|
+
#### reference:`LazyFactory`
|
|
1873
|
+
- function helper for creating lazyObject:
|
|
1874
|
+
>- usefull for lazily instantiating an object, since instance naturally have props/methods;
|
|
1875
|
+
|
|
1876
|
+
```js
|
|
1877
|
+
/**
|
|
1878
|
+
* @template T
|
|
1879
|
+
* @param {() => T} factory
|
|
1880
|
+
* @returns {T & {[unwrapLazy]: string}}
|
|
1881
|
+
* - the unwrapLazy prop can be accessed to force instatiation/call;
|
|
1882
|
+
* >- `unwrapLazy` prop name can be checked by checking the list of possible prop, from your ide;
|
|
1883
|
+
* >- as of version 1.0.0, value is `vivth:unwrapLazy;`;
|
|
1884
|
+
*/
|
|
1885
|
+
```
|
|
1886
|
+
- <i>example</i>:
|
|
1887
|
+
```js
|
|
1888
|
+
import { LazyFactory } from 'vivth';
|
|
1889
|
+
class MyClass{
|
|
1890
|
+
constructor() {
|
|
1891
|
+
this.myProp = 1; // will only available when accessed;
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
export const myInstance = LazyFactory(() => {
|
|
1896
|
+
// the instance of MyClass will only be available when,
|
|
1897
|
+
// it's prop, or method is accessed/reassign;
|
|
1898
|
+
return new MyClass();
|
|
1899
|
+
});
|
|
1900
|
+
|
|
1901
|
+
// on other file
|
|
1902
|
+
import { myInstance } from './myInstance.mjs';
|
|
1903
|
+
|
|
1904
|
+
const a = myInstance; // not yet initiated;
|
|
1905
|
+
const b = a.myProp // imediately initiated;
|
|
1906
|
+
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1909
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1910
|
+
|
|
1911
|
+
<h2 id="timeout">Timeout</h2>
|
|
1912
|
+
|
|
1913
|
+
|
|
1914
|
+
#### reference:`Timeout`
|
|
1915
|
+
- function helper to temporarily block the code in async context;
|
|
1916
|
+
|
|
1917
|
+
```js
|
|
1918
|
+
/**
|
|
1919
|
+
* @param {number} timeMS
|
|
1920
|
+
* - in miliseconds;
|
|
1921
|
+
* @returns {Promise<void>}
|
|
1922
|
+
*/
|
|
1923
|
+
```
|
|
1924
|
+
- <i>example</i>:
|
|
1925
|
+
```js
|
|
1926
|
+
import { Timeout } from 'vivth';
|
|
1927
|
+
|
|
1928
|
+
const test = async () => {
|
|
1929
|
+
// code0
|
|
1930
|
+
await Timeout(1000);
|
|
1931
|
+
// code1
|
|
1932
|
+
}
|
|
1933
|
+
test();
|
|
1934
|
+
|
|
1935
|
+
```
|
|
1936
|
+
|
|
1937
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
1938
|
+
|
|
1939
|
+
<h2 id="try">Try</h2>
|
|
1940
|
+
|
|
1941
|
+
|
|
1942
|
+
#### reference:`Try`
|
|
1943
|
+
- function for error as value for chained operations;
|
|
1944
|
+
- utility function to brute force which key is able to run;
|
|
1945
|
+
- usefull to flatten indentation for error handlings;
|
|
1946
|
+
- caveat:
|
|
1947
|
+
>- run in sequence, awaiting each key bofore running next key;
|
|
1948
|
+
|
|
1949
|
+
```js
|
|
1950
|
+
/**
|
|
1951
|
+
* @template {string} Key
|
|
1952
|
+
* @template ReturnType_
|
|
1953
|
+
* @template {Record<
|
|
1954
|
+
* Key,
|
|
1955
|
+
* () => Promise<ReturnType_>
|
|
1956
|
+
* >} RecordTryType
|
|
1957
|
+
* @param {RecordTryType} tryRecord
|
|
1958
|
+
* @returns {Promise<
|
|
1959
|
+
* [[keyof RecordTryType, ReturnType_], undefined]
|
|
1960
|
+
* | [[undefined, undefined], Error]
|
|
1961
|
+
* >}
|
|
1962
|
+
*/
|
|
1963
|
+
```
|
|
1964
|
+
- <i>example</i>:
|
|
1965
|
+
```js
|
|
1966
|
+
import { Try } from 'vivth';
|
|
1967
|
+
|
|
1968
|
+
const [[key, result], error] = await Try({
|
|
1969
|
+
someRuntime: async () => {
|
|
1970
|
+
// asuming on this one doesn't naturally throw error,
|
|
1971
|
+
// yet you need to continue to next key,
|
|
1972
|
+
// instead of returning,
|
|
1973
|
+
// you should throw new Error(something);
|
|
1974
|
+
},
|
|
1975
|
+
browser: async () => {
|
|
1976
|
+
return location?.origin;
|
|
1977
|
+
// if no error, stop other key function from running;
|
|
1978
|
+
// key = 'browser'
|
|
1979
|
+
// result = location?.origin;
|
|
1980
|
+
// error = undefined;
|
|
1981
|
+
// if error;
|
|
1982
|
+
// run nodeOrBun;
|
|
1983
|
+
},
|
|
1984
|
+
nodeOrBun: async () => {
|
|
1985
|
+
return process?.env?.INIT_CWD ?? process?.cwd();
|
|
1986
|
+
// if no error;
|
|
1987
|
+
// key = 'nodeOrBun'
|
|
1988
|
+
// result = process?.env?.INIT_CWD ?? process?.cwd();
|
|
1989
|
+
// if error;
|
|
1990
|
+
// key = undefined;
|
|
1991
|
+
// result = undefined;
|
|
1992
|
+
// error = new Error('unable to run any key');
|
|
1993
|
+
},
|
|
1994
|
+
});
|
|
1995
|
+
|
|
1996
|
+
```
|
|
1997
|
+
|
|
1998
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
106
1999
|
|
|
107
2000
|
<h2 id="tryasync">TryAsync</h2>
|
|
108
2001
|
|
|
109
|
-
- error as value for asynchronous operation
|
|
110
2002
|
|
|
111
|
-
|
|
2003
|
+
#### reference:`TryAsync`
|
|
2004
|
+
- function for error as value for asynchronous operation;
|
|
2005
|
+
- usefull to flatten indentation for error handlings;
|
|
2006
|
+
|
|
2007
|
+
```js
|
|
2008
|
+
/**
|
|
2009
|
+
* @template ResultType
|
|
2010
|
+
* @param {()=>Promise<ResultType>} asyncFunction_
|
|
2011
|
+
* @returns {Promise<[ResultType|undefined, Error|undefined]>}
|
|
2012
|
+
*/
|
|
2013
|
+
```
|
|
2014
|
+
- <i>example</i>:
|
|
2015
|
+
```js
|
|
2016
|
+
import { TryAsync } from 'vivth';
|
|
2017
|
+
|
|
2018
|
+
let [res, error] = await TryAsync(async () => {
|
|
2019
|
+
return await fetch('./someAPI/Path');
|
|
2020
|
+
});
|
|
2021
|
+
|
|
2022
|
+
[res, error] = await TryAsync(async () => {
|
|
2023
|
+
if(!res.ok) {
|
|
2024
|
+
throw new Error(404);
|
|
2025
|
+
}
|
|
2026
|
+
return await res.json();
|
|
2027
|
+
})
|
|
2028
|
+
|
|
2029
|
+
```
|
|
2030
|
+
|
|
2031
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
112
2032
|
|
|
113
2033
|
<h2 id="trysync">TrySync</h2>
|
|
114
2034
|
|
|
115
|
-
- error as value for synchronous operation
|
|
116
2035
|
|
|
117
|
-
|
|
2036
|
+
#### reference:`TrySync`
|
|
2037
|
+
- function for error as value for synchronous operation;
|
|
2038
|
+
- usefull to flatten indentation for error handlings;
|
|
2039
|
+
|
|
2040
|
+
```js
|
|
2041
|
+
/**
|
|
2042
|
+
* @template ResultType
|
|
2043
|
+
* @param {()=>ResultType} function_
|
|
2044
|
+
* @returns {[ResultType|undefined, Error|undefined]}
|
|
2045
|
+
*/
|
|
2046
|
+
```
|
|
2047
|
+
- <i>example</i>:
|
|
2048
|
+
```js
|
|
2049
|
+
import { readFileSync } from 'fs';
|
|
2050
|
+
import { TrySync } from './yourModule.js';
|
|
2051
|
+
|
|
2052
|
+
const [data, error] = TrySync(() => {
|
|
2053
|
+
return readFileSync('./some/file.txt', 'utf-8');
|
|
2054
|
+
});
|
|
2055
|
+
|
|
2056
|
+
```
|
|
2057
|
+
|
|
2058
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2059
|
+
|
|
2060
|
+
<h2 id="tstomjs">TsToMjs</h2>
|
|
2061
|
+
|
|
2062
|
+
|
|
2063
|
+
#### reference:`TsToMjs`
|
|
2064
|
+
- turn `.mts`||`.ts` file into `.mjs`, no bundling, just translation;
|
|
2065
|
+
- on certain circumstance where `.mjs` result needed to be typed, you need to manually add `jsdoc`;
|
|
2066
|
+
>- uses `"at"preserve` to register `jsdoc` inline;
|
|
2067
|
+
|
|
2068
|
+
```js
|
|
2069
|
+
/**
|
|
2070
|
+
* @param {string} path_
|
|
2071
|
+
* @param {Object} [options]
|
|
2072
|
+
* @param {string} [options.overrideDir]
|
|
2073
|
+
* - default: write conversion to same directory;
|
|
2074
|
+
* - path are relative to project root;
|
|
2075
|
+
* @param {BufferEncoding} [options.encoding]
|
|
2076
|
+
* - default: `utf-8`;
|
|
2077
|
+
* @returns {Promise<void>}
|
|
2078
|
+
*/
|
|
2079
|
+
```
|
|
2080
|
+
- <i>example</i>:
|
|
2081
|
+
```js
|
|
2082
|
+
import { TsToMjs } from 'vivth';
|
|
2083
|
+
|
|
2084
|
+
TsToMjs('./myFile.mts', { encoding: 'utf-8', overrideDir: './other/dir' });
|
|
2085
|
+
|
|
2086
|
+
```
|
|
2087
|
+
|
|
2088
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2089
|
+
|
|
2090
|
+
<h2 id="writefilesafe">WriteFileSafe</h2>
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
#### reference:`WriteFileSafe`
|
|
2094
|
+
- function to create file by recursively mkdir the dirname of the outFile;
|
|
2095
|
+
- also returing promise of result & error as value;
|
|
2096
|
+
|
|
2097
|
+
```js
|
|
2098
|
+
/**
|
|
2099
|
+
* @param {string} outFile
|
|
2100
|
+
* @param {string} content
|
|
2101
|
+
* @param {import('node:fs').WriteFileOptions} options
|
|
2102
|
+
* @returns {Promise<ReturnType<typeof TryAsync<void>>>}
|
|
2103
|
+
*/
|
|
2104
|
+
```
|
|
2105
|
+
- <i>example</i>:
|
|
2106
|
+
```js
|
|
2107
|
+
import { WriteFileSafe } from 'vivth';
|
|
2108
|
+
|
|
2109
|
+
const [_, writeError] = await TryAsync(async () => {
|
|
2110
|
+
return await WriteFileSafe(
|
|
2111
|
+
'/some/path.mjs',
|
|
2112
|
+
'console.log("hello-world!!");',
|
|
2113
|
+
{ encoding: 'utf-8' }
|
|
2114
|
+
);
|
|
2115
|
+
});
|
|
2116
|
+
|
|
2117
|
+
```
|
|
2118
|
+
|
|
2119
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2120
|
+
|
|
2121
|
+
<h2 id="anybutundefined">AnyButUndefined</h2>
|
|
2122
|
+
|
|
2123
|
+
- jsdoc types:
|
|
2124
|
+
|
|
2125
|
+
```js
|
|
2126
|
+
/**
|
|
2127
|
+
* - type helper for ID or objects;
|
|
2128
|
+
* @typedef {{}|null|number|string|boolean|symbol|bigint|function} AnyButUndefined
|
|
2129
|
+
*/
|
|
2130
|
+
```
|
|
2131
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2132
|
+
|
|
2133
|
+
<h2 id="extnametype">ExtnameType</h2>
|
|
2134
|
+
|
|
2135
|
+
- jsdoc types:
|
|
2136
|
+
|
|
2137
|
+
```js
|
|
2138
|
+
/**
|
|
2139
|
+
* - jsRuntime extention naming convention;
|
|
2140
|
+
* @typedef {`.${string}`} ExtnameType
|
|
2141
|
+
*/
|
|
2142
|
+
```
|
|
2143
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2144
|
+
|
|
2145
|
+
<h2 id="islistsignal">IsListSignal</h2>
|
|
2146
|
+
|
|
2147
|
+
- jsdoc types:
|
|
2148
|
+
|
|
2149
|
+
```js
|
|
2150
|
+
/**
|
|
2151
|
+
* - `EnvSignal.get` argument whether signal need to be a list or not;
|
|
2152
|
+
* @typedef {boolean} IsListSignal
|
|
2153
|
+
*/
|
|
2154
|
+
```
|
|
2155
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2156
|
+
|
|
2157
|
+
<h2 id="listarg">ListArg</h2>
|
|
2158
|
+
|
|
2159
|
+
- jsdoc types:
|
|
2160
|
+
|
|
2161
|
+
```js
|
|
2162
|
+
/**
|
|
2163
|
+
* - ListSignal argument type;
|
|
2164
|
+
* @typedef {Record<string, string>} ListArg
|
|
2165
|
+
*/
|
|
2166
|
+
```
|
|
2167
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2168
|
+
|
|
2169
|
+
<h2 id="mutationtype">MutationType</h2>
|
|
2170
|
+
|
|
2171
|
+
- jsdoc types:
|
|
2172
|
+
|
|
2173
|
+
```js
|
|
2174
|
+
/**
|
|
2175
|
+
* - `ListSignal` mutation type;
|
|
2176
|
+
* @typedef {'push'|'unshift'|'splice'|'swap'|'modify'|'shift'|'remove'} MutationType
|
|
2177
|
+
* - instance method: serves as helper to mutate, and notify for `effects`;
|
|
2178
|
+
* > - `slice` uses `splice` in the background, you don't need to manually reindex when using it;
|
|
2179
|
+
*/
|
|
2180
|
+
```
|
|
2181
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2182
|
+
|
|
2183
|
+
<h2 id="qcbfiforeturn">QCBFIFOReturn</h2>
|
|
2184
|
+
|
|
2185
|
+
- jsdoc types:
|
|
2186
|
+
|
|
2187
|
+
```js
|
|
2188
|
+
/**
|
|
2189
|
+
* - return type of Q callback fifo;
|
|
2190
|
+
* @typedef {Omit<import("./src/types/QCBReturn.mjs").QCBReturn, "isLastOnQ">} QCBFIFOReturn
|
|
2191
|
+
*/
|
|
2192
|
+
```
|
|
2193
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|
|
2194
|
+
|
|
2195
|
+
<h2 id="qcbreturn">QCBReturn</h2>
|
|
2196
|
+
|
|
2197
|
+
- jsdoc types:
|
|
2198
|
+
|
|
2199
|
+
```js
|
|
2200
|
+
/**
|
|
2201
|
+
* - return type of Q callback;
|
|
2202
|
+
* @typedef {{resume:()=>void, isLastOnQ:boolean}} QCBReturn
|
|
2203
|
+
*/
|
|
2204
|
+
```
|
|
2205
|
+
*) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
|