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.
Files changed (107) hide show
  1. package/.vivth/dist/init.mjs +24 -0
  2. package/README.md +2157 -69
  3. package/README.src.md +35 -0
  4. package/bun.lock +57 -3
  5. package/dev/index.mjs +24 -25
  6. package/index.mjs +51 -29
  7. package/package.json +11 -7
  8. package/src/bundler/CompileMJS.mjs +110 -0
  9. package/src/bundler/EsBundler.mjs +79 -0
  10. package/src/class/Console.mjs +62 -0
  11. package/src/class/Derived.mjs +36 -25
  12. package/src/class/Effect.mjs +106 -0
  13. package/src/class/EnvSignal.mjs +88 -0
  14. package/src/class/EventSignal.mjs +200 -0
  15. package/src/class/ListDerived.mjs +39 -0
  16. package/src/class/ListSignal.mjs +256 -0
  17. package/src/class/Paths.mjs +70 -0
  18. package/src/class/QChannel.mjs +184 -0
  19. package/src/class/SafeExit.mjs +131 -0
  20. package/src/class/Setup.mjs +73 -0
  21. package/src/class/Signal.mjs +152 -54
  22. package/src/class/WorkerMainThread.mjs +328 -0
  23. package/src/class/WorkerResult.mjs +30 -0
  24. package/src/class/WorkerThread.mjs +151 -0
  25. package/src/common/Base64URL.mjs +26 -0
  26. package/src/common/EventNameSpace.mjs +8 -0
  27. package/src/common/eventObjects.mjs +5 -0
  28. package/src/common/lazie.mjs +3 -0
  29. package/src/doc/JSautoDOC.mjs +386 -0
  30. package/src/doc/parsedFile.mjs +537 -0
  31. package/src/function/CreateImmutable.mjs +64 -0
  32. package/src/function/EventCheck.mjs +27 -0
  33. package/src/function/EventObject.mjs +21 -0
  34. package/src/function/IsAsync.mjs +23 -0
  35. package/src/function/LazyFactory.mjs +71 -0
  36. package/src/function/Timeout.mjs +23 -0
  37. package/src/function/Try.mjs +64 -0
  38. package/src/function/TryAsync.mjs +15 -4
  39. package/src/function/TrySync.mjs +9 -4
  40. package/src/function/TsToMjs.mjs +67 -0
  41. package/src/function/WriteFileSafe.mjs +37 -0
  42. package/src/types/{AnyButUndefined.type.mjs → AnyButUndefined.mjs} +1 -0
  43. package/src/types/ExtnameType.mjs +6 -0
  44. package/src/types/IsListSignal.mjs +6 -0
  45. package/src/types/ListArg.mjs +6 -0
  46. package/src/types/MutationType.mjs +8 -0
  47. package/src/types/QCBFIFOReturn.mjs +6 -0
  48. package/src/types/QCBReturn.mjs +6 -0
  49. package/tsconfig.json +3 -3
  50. package/types/dev/index.d.mts +1 -0
  51. package/types/index.d.mts +34 -8
  52. package/types/src/bundler/A.d.mts +1 -0
  53. package/types/src/bundler/CompileMJS.d.mts +8 -0
  54. package/types/src/bundler/EsBundler.d.mts +7 -0
  55. package/types/src/class/Console.d.mts +40 -0
  56. package/types/src/class/Derived.d.mts +21 -9
  57. package/types/src/class/Effect.d.mts +77 -0
  58. package/types/src/class/EnvSignal.d.mts +47 -0
  59. package/types/src/class/EventSignal.d.mts +145 -0
  60. package/types/src/class/ListDerived.d.mts +35 -0
  61. package/types/src/class/ListSignal.d.mts +150 -0
  62. package/types/src/class/Paths.d.mts +50 -0
  63. package/types/src/class/QChannel.d.mts +115 -0
  64. package/types/src/class/SafeExit.d.mts +76 -0
  65. package/types/src/class/Setup.d.mts +76 -0
  66. package/types/src/class/Signal.d.mts +105 -26
  67. package/types/src/class/WorkerMainThread.d.mts +149 -0
  68. package/types/src/class/WorkerResult.d.mts +25 -0
  69. package/types/src/class/WorkerThread.d.mts +70 -0
  70. package/types/src/common/Base64URL.d.mts +1 -0
  71. package/types/src/common/EventNameSpace.d.mts +6 -0
  72. package/types/src/common/eventObjects.d.mts +3 -0
  73. package/types/src/common/lazie.d.mts +1 -0
  74. package/types/src/doc/JSautoDOC.d.mts +76 -0
  75. package/types/src/doc/parsedFile.d.mts +154 -0
  76. package/types/src/function/CreateImmutable.d.mts +3 -0
  77. package/types/src/function/EventCheck.d.mts +2 -0
  78. package/types/src/function/EventObject.d.mts +4 -0
  79. package/types/src/function/IsAsync.d.mts +1 -0
  80. package/types/src/function/LazyFactory.d.mts +4 -0
  81. package/types/src/function/Timeout.d.mts +1 -0
  82. package/types/src/function/Try.d.mts +1 -0
  83. package/types/src/function/TsToMjs.d.mts +4 -0
  84. package/types/src/function/WriteFileSafe.d.mts +2 -0
  85. package/types/src/types/{AnyButUndefined.type.d.mts → AnyButUndefined.d.mts} +3 -0
  86. package/types/src/types/ExtnameType.d.mts +4 -0
  87. package/types/src/types/IsListSignal.d.mts +4 -0
  88. package/types/src/types/ListArg.d.mts +4 -0
  89. package/types/src/types/MutationType.d.mts +5 -0
  90. package/types/src/types/QCBFIFOReturn.d.mts +4 -0
  91. package/types/src/types/QCBReturn.d.mts +7 -0
  92. package/src/class/$.mjs +0 -68
  93. package/src/class/PingFIFO.mjs +0 -78
  94. package/src/class/PingUnique.mjs +0 -84
  95. package/src/class/Q.mjs +0 -98
  96. package/src/class/QFIFO.mjs +0 -66
  97. package/src/class/QUnique.mjs +0 -75
  98. package/src/common.mjs +0 -16
  99. package/src/function/NewQBlock.mjs +0 -39
  100. package/types/src/class/$.d.mts +0 -40
  101. package/types/src/class/PingFIFO.d.mts +0 -57
  102. package/types/src/class/PingUnique.d.mts +0 -48
  103. package/types/src/class/Q.d.mts +0 -63
  104. package/types/src/class/QFIFO.d.mts +0 -47
  105. package/types/src/class/QUnique.d.mts +0 -46
  106. package/types/src/common.d.mts +0 -2
  107. package/types/src/function/NewQBlock.d.mts +0 -1
package/README.md CHANGED
@@ -1,93 +1,2198 @@
1
- ## HOW TO INSTALL
2
- ```shell
3
- npm i vivth
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
- ```shell
6
- bun i vivth
171
+
172
+ #### reference:`Console.info`
173
+
174
+
175
+ ```js
176
+ /**
177
+ * @param {any} data
178
+ * @returns {void}
179
+ */
7
180
  ```
8
181
 
9
- ## vivth
10
- - contains helpers to help you write autosubscriber pattern javascript program, including:
11
- >- collections of signal based functions and classes;
12
- >- collections of queue helper functions and classes;
182
+ #### reference:`Console.warn`
183
+
184
+
185
+ ```js
186
+ /**
187
+ * @param {any} data
188
+ * @returns {void}
189
+ */
190
+ ```
13
191
 
14
- - `vivth` technically can run in any `js runtime`, since it uses non platform specific api;
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
- - a class to `autosubscribe` to an signal changes (`Derived` and `Signal` alike);
32
- for minimal total bundle size use `function` [New$](#new$) instead;
195
+ ```js
196
+ /**
197
+ * @param {any} data
198
+ * @returns {void}
199
+ */
200
+ ```
33
201
 
34
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- <h2 id="pingfifo">PingFIFO</h2>
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
- a class for Queue;
50
- function to auto queue callbacks that will be called `first in first out` style;
51
- this class provides `QFIFO.makeQClass`;
682
+ #### reference:`ListSignal_instance.value:getter`
683
+ - reference to original inputed `value`;
52
684
 
53
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- <h2 id="pingunique">PingUnique</h2>
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
- this class provides `QUnique.makeQClass`;
717
+ #### reference:`ListSignal_instance.arrayMethods.push`
718
+ - appends new elements to the end;
60
719
 
61
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- <h2 id="q">Q</h2>
835
+ *) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
64
836
 
65
- - class that containts static methods to generate Promise based `awaiter` inside async function, to prevent race condition, including but not limited to:
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
- <h2 id="qfifo">QFIFO</h2>
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- <h2 id="qunique">QUnique</h2>
1121
+ *) <sub>[go to list of exported API and typehelpers](#list-of-exported-api-and-typehelpers)</sub>
83
1122
 
84
- - a class for Queue;
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- <h2 id="newqblock">NewQBlock</h2>
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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
- *) <sub>[go to exported list](#exported-api-and-type-list)</sub>
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>