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
@@ -0,0 +1,106 @@
1
+ // @ts-check
2
+
3
+ import { unwrapLazy } from '../common/lazie.mjs';
4
+ import { LazyFactory } from '../function/LazyFactory.mjs';
5
+ import { TryAsync } from '../function/TryAsync.mjs';
6
+ import { Console } from './Console.mjs';
7
+ import { Signal } from './Signal.mjs';
8
+
9
+ /**
10
+ * @type {Set<Effect>}
11
+ */
12
+ export const setOfEffects = new Set();
13
+
14
+ /**
15
+ * @description
16
+ * - a class for creating effect;
17
+ * - compared to previous class <b>$</b> reactivity model, `Effect`:
18
+ * >- doesn't autosubscribe at first run;
19
+ * >- it is using passed <b>$</b> named `arg0` options as subscriber;
20
+ * >- doesn't block other queues during first run(previously blocks other queues to safely register signal autoscubscriber);
21
+ * >- now can dynamically subscribes to signal, even on conditionals, that are not run during first run;
22
+ */
23
+ export class Effect {
24
+ /**
25
+ * @description
26
+ * @param {(arg0:Effect["options"])=>Promise<void>} effect
27
+ * @example
28
+ * import { Signal, Derived, Effect, Console } from 'vivth';
29
+ *
30
+ * const count = new Signal(0);
31
+ * const double = new Derived( async({$}) => $(count).value \* 2); // double listen to count changes
32
+ * new Effect(async ({
33
+ * subscribe, // : registrar callback for this effect instance, immediately return the signal instance
34
+ * removeEffect, // : disable this effect instance from reacting to dependency changes;
35
+ * }) => {
36
+ * Console.log(subscribe(double).value); // effect listen to double changes
37
+ * const a = double.value; // no need to wrap double twice with $
38
+ * })
39
+ *
40
+ * count.value++;
41
+ */
42
+ constructor(effect) {
43
+ this.#effect = effect;
44
+ setOfEffects.add(this);
45
+ this.run();
46
+ }
47
+ options = LazyFactory(() => ({
48
+ /**
49
+ * @instance options
50
+ * @description
51
+ * - normally it's passed as argument to constructor, however it is also accessible from `options` property;
52
+ * @template {Signal} S
53
+ * @param {S} signal
54
+ * @returns {S}
55
+ * @example
56
+ * const effect = new Effect(async () => {
57
+ * // code
58
+ * })
59
+ * effect.options.subscribe(signalInstance);
60
+ */
61
+ subscribe: (signal) => {
62
+ if (!(signal instanceof Signal)) {
63
+ signal = signal[unwrapLazy];
64
+ }
65
+ signal.subscribers.setOf.add(this);
66
+ return signal;
67
+ },
68
+ /**
69
+ * @instance options
70
+ * @description
71
+ * - normally it's passed as argument to constructor, however it is also accessible from `options` property;
72
+ * @type {()=>void}
73
+ * @example
74
+ * const effect = new Effect(async () => {
75
+ * // code
76
+ * })
77
+ * effect.options.removeEffect();
78
+ */
79
+ removeEffect: () => {
80
+ setOfEffects.delete(this);
81
+ },
82
+ }));
83
+ /**
84
+ * @param {Effect["options"]} effectInstance
85
+ * @returns {Promise<void>}
86
+ */
87
+ #effect;
88
+ /**
89
+ * @description
90
+ * - normally is to let to be automatically run when dependency signals changes, however it's also accessible as instance method;
91
+ * @returns {void}
92
+ * @example
93
+ * const effect = new Effect(async ()=>{
94
+ * // code
95
+ * })
96
+ * effect.run();
97
+ */
98
+ run = () => {
99
+ TryAsync(async () => await this.#effect(this.options)).then(([_, error]) => {
100
+ if (!error) {
101
+ return;
102
+ }
103
+ Console.error(error);
104
+ });
105
+ };
106
+ }
@@ -0,0 +1,88 @@
1
+ // @ts-check
2
+
3
+ import { LazyFactory } from '../function/LazyFactory.mjs';
4
+ import { Console } from './Console.mjs';
5
+ import { Derived } from './Derived.mjs';
6
+ import { Signal } from './Signal.mjs';
7
+
8
+ /**
9
+ * @description
10
+ * - non browser API;
11
+ * - uses [Signal](#signal) and [Derived](#derived) under the hood;
12
+ * @template V
13
+ */
14
+ export class EnvSignal {
15
+ /**
16
+ * @description
17
+ * - create `EnvSignal` instance;
18
+ * @param {V} initialValue
19
+ */
20
+ constructor(initialValue) {
21
+ this.#proxyConst = LazyFactory(() => new Signal(initialValue));
22
+ let isRun = false;
23
+ this.env = LazyFactory(
24
+ () =>
25
+ new Derived(async ({ subscribe }) => {
26
+ const derived = subscribe(this.#proxyConst).value;
27
+ if (!isRun) {
28
+ isRun = true;
29
+ return initialValue;
30
+ }
31
+ return derived;
32
+ })
33
+ );
34
+ }
35
+ #isModified = false;
36
+ /**
37
+ * @type {Signal<V>}
38
+ */
39
+ #proxyConst;
40
+ /**
41
+ * @description
42
+ * - exposed property to listen to;
43
+ * @type {Derived<V>}
44
+ * @example
45
+ * import { EnvSignal, Effect } from 'vivth';
46
+ *
47
+ * export const myEnv = new EnvSignal(true);
48
+ * new Effect(async ({ subscribe }) => {
49
+ * const myEnvValue = subscribe(myEnv.env).value;
50
+ * // code
51
+ * })
52
+ */
53
+ env;
54
+ /**
55
+ * @description
56
+ * - call to correct the value of previously declared value;
57
+ * - can only be called once;
58
+ * @param {V} correctedValue
59
+ * @returns {void}
60
+ * @example
61
+ * import { EnvSignal } from 'vivth';
62
+ *
63
+ * export const myEnv = new EnvSignal(true);
64
+ *
65
+ * // somewhere else on the program
66
+ * import { myEnv } from '$src/myEnv'
67
+ *
68
+ * myEnv.correction(false); // this will notify all subscribers;
69
+ */
70
+ correction = (correctedValue) => {
71
+ if (this.#proxyConst.value === null) {
72
+ return;
73
+ }
74
+ Console;
75
+ if (this.#isModified) {
76
+ Console.warn({
77
+ correctedValue,
78
+ value: this.#proxyConst.value,
79
+ instance: this,
80
+ message: '"correct" of this instance can only be called once',
81
+ });
82
+ return;
83
+ }
84
+ this.#isModified = true;
85
+ this.#proxyConst.value = correctedValue;
86
+ this.#proxyConst.remove.ref();
87
+ };
88
+ }
@@ -0,0 +1,200 @@
1
+ // @ts-check
2
+
3
+ import { LazyFactory } from '../function/LazyFactory.mjs';
4
+ import { Derived } from './Derived.mjs';
5
+ import { ListDerived } from './ListDerived.mjs';
6
+ import { ListSignal } from './ListSignal.mjs';
7
+ import { QChannel } from './QChannel.mjs';
8
+ import { Signal } from './Signal.mjs';
9
+
10
+ /**
11
+ * @description
12
+ * - Signal implementation for `CustomEvent`, to dispatch and listen;
13
+ * @template {IsListSignal} isList
14
+ * - boolean;
15
+ */
16
+ export class EventSignal {
17
+ /**
18
+ * @typedef {import('../types/IsListSignal.mjs').IsListSignal} IsListSignal
19
+ */
20
+ /**
21
+ * @description
22
+ * - `Map` of `EventSignal`, using the `stringName` of the `EventSignal_instance` as `key`;
23
+ * @type {Map<string, EventSignal>}
24
+ */
25
+ static map = new Map();
26
+ /**
27
+ * @type {QChannel<string>}
28
+ */
29
+ static #qChannelEventSignal = new QChannel();
30
+ /**
31
+ * @description
32
+ * - the constructor it self is set to `private`;
33
+ * - it's globally queued:
34
+ * >- the `Promise` nature is to prevent race condition on creating the instance;
35
+ * @param {string} stringName
36
+ * @param {IsListSignal} [isList_]
37
+ * @returns {Promise<EventSignal>}
38
+ * @example
39
+ * import { EventSignal } from 'vivth';
40
+ *
41
+ * const myEventSignal = await EventSignal.get('dataEvent');
42
+ */
43
+ static async get(stringName, isList_ = false) {
44
+ const { resume } = await EventSignal.#qChannelEventSignal.key(stringName);
45
+ const mapped = EventSignal.map;
46
+ if (!mapped.has(stringName)) {
47
+ let instance = new EventSignal(stringName, isList_);
48
+ mapped.set(stringName, instance);
49
+ }
50
+ resume();
51
+ return mapped.get(stringName);
52
+ }
53
+ /**
54
+ * @private
55
+ * @param {string} name
56
+ * @param {isList} [isList]
57
+ */
58
+ // @ts-expect-error
59
+ constructor(name, isList = false) {
60
+ this.name = name;
61
+ this.#isList = isList;
62
+ }
63
+ /**
64
+ * @type {IsListSignal}
65
+ */
66
+ #isList;
67
+ /**
68
+ * @type {string}
69
+ */
70
+ name;
71
+ /**
72
+ * @description
73
+ * - is [Signal](#signal) or [ListSignal](#listsignal) instance, depending on the `isList` argument;
74
+ * - if needed to pass along the messages, it can be used as `dispatcher` and `listener` at the same time;
75
+ * - is `lazily` created;
76
+ * @type {Signal|ListSignal}
77
+ */
78
+ dispatch = LazyFactory(() => {
79
+ if (this.#isList) {
80
+ return new ListSignal([]);
81
+ }
82
+ return new Signal(undefined);
83
+ });
84
+ /**
85
+ * @description
86
+ * - is [Derived](#derived) or [ListDerived](#listderived) instance, depending on the `isList` argument;
87
+ * - can be used as listener when passed down value shouldn't be modified manually;
88
+ * - is `lazily` created along with `dispatch`, if `listen` is accessed first, then `dispatch` will also be created automatically;
89
+ * @type {Derived|ListDerived}
90
+ */
91
+ listen = LazyFactory(() => {
92
+ const dispatch = this.dispatch;
93
+ const _ = dispatch.value;
94
+ if (this.#isList) {
95
+ return new ListDerived(async ({ subscribe }) => {
96
+ return subscribe(dispatch).value;
97
+ });
98
+ }
99
+ return new Derived(async ({ subscribe }) => {
100
+ return subscribe(dispatch).value;
101
+ });
102
+ });
103
+ /**
104
+ * @description
105
+ * - methods of this static property is lazily created;
106
+ * - remove signal and effect subscription of the named `EventSignal_instance`;
107
+ */
108
+ static remove = LazyFactory(() => ({
109
+ /**
110
+ * @static remove
111
+ * @description
112
+ * - remove subscriber from the named `EventSignal_instance`;
113
+ * @param {string} name
114
+ * @param {import('./Effect.mjs').Effect} effect
115
+ * @returns {void}
116
+ * @example
117
+ * import { EventSignal } from 'vivth';
118
+ *
119
+ * EventSignal.remove.subscriber('yourEventSignalName', yourEffectInstance);
120
+ */
121
+ subscriber: (name, effect) => {
122
+ effect.options.removeEffect();
123
+ EventSignal.get(name).then(({ remove }) => {
124
+ remove.subscriber(effect);
125
+ });
126
+ },
127
+ /**
128
+ * @static remove
129
+ * @description
130
+ * - remove all subscribers from the named `EventSignal_instance`;
131
+ * @param {string} name
132
+ * @returns {void}
133
+ * @example
134
+ * import { EventSignal } from 'vivth';
135
+ *
136
+ * EventSignal.remove.allSubscribers('yourEventSignalName');
137
+ */
138
+ allSubscribers: (name) => {
139
+ EventSignal.get(name).then(({ remove }) => {
140
+ remove.allSubscribers();
141
+ });
142
+ },
143
+ /**
144
+ * @static remove
145
+ * @description
146
+ * - remove reference of the `proxySignals` of the named `EventSignal_instance`;
147
+ * @param {string} name
148
+ * @returns {void}
149
+ * @example
150
+ * import { EventSignal } from 'vivth';
151
+ *
152
+ * EventSignal.remove.refs('yourEventSignalName');
153
+ */
154
+ refs: (name) => {
155
+ EventSignal.get(name).then(({ remove }) => {
156
+ remove.ref();
157
+ });
158
+ },
159
+ }));
160
+ remove = LazyFactory(() => ({
161
+ /**
162
+ * @instance remove
163
+ * @description
164
+ * - remove subscriber from the `EventSignal_instance`;
165
+ * @param {import('./Effect.mjs').Effect} effect
166
+ * @returns {void}
167
+ * @example
168
+ * eventSignal_instance.remove.subscriber(yourEffectInstance);
169
+ */
170
+ subscriber: (effect) => {
171
+ effect.options.removeEffect();
172
+ this.dispatch.remove.subscriber(effect);
173
+ this.listen.remove.subscriber(effect);
174
+ },
175
+ /**
176
+ * @instance remove
177
+ * @description
178
+ * - remove allSubscribers from the `EventSignal_instance`;
179
+ * @type {()=>void}
180
+ * @example
181
+ * eventSignal_instance.remove.allSubscribers();
182
+ */
183
+ allSubscribers: () => {
184
+ this.dispatch.remove.allSubscribers();
185
+ this.listen.remove.allSubscribers();
186
+ },
187
+ /**
188
+ * @instance remove
189
+ * @description
190
+ * - remove reference of the `proxySignals` of the `EventSignal_instance`;
191
+ * @type {()=>void}
192
+ * @example
193
+ * eventSignal_instance.remove.ref();
194
+ */
195
+ ref: () => {
196
+ this.dispatch.remove.ref();
197
+ this.listen.remove.ref();
198
+ },
199
+ }));
200
+ }
@@ -0,0 +1,39 @@
1
+ // @ts-check
2
+
3
+ import { Derived } from './Derived.mjs';
4
+ import { Effect } from './Effect.mjs';
5
+ /**
6
+ * @description
7
+ * - class to create `dervivedList` that satisfy `Array<Record<string, string>>`;
8
+ * - usefull for `derivedLoops`, e.g. temporary search values;
9
+ * - is a `Derived` instance;
10
+ * @template {ListArg} LA
11
+ * @extends {Derived<LA[]>}
12
+ */
13
+ export class ListDerived extends Derived {
14
+ /**
15
+ * @typedef {import('../types/ListArg.mjs').ListArg} ListArg
16
+ */
17
+ /**
18
+ * @description
19
+ * @param {(effectInstanceOptions:Effect["options"])=>Promise<LA[]>} derivedFunction
20
+ * @example
21
+ * import { ListSignal, ListDerived } from 'vivth';
22
+ *
23
+ * const listExample = new ListSignal([
24
+ * {key1: "test1"},
25
+ * {key1: "test2"},
26
+ * ]);
27
+ *
28
+ * export const listDerivedExample = new ListDerived(async({ subscribe }) => {
29
+ * // becarefull to not mutate the reference value
30
+ * return subscribe(listExample).value.filter((val) => {
31
+ * // subscribe(listExample).structuredClone can be used as alternative
32
+ * // filter logic
33
+ * })
34
+ * });
35
+ */
36
+ constructor(derivedFunction) {
37
+ super(derivedFunction);
38
+ }
39
+ }
@@ -0,0 +1,256 @@
1
+ // @ts-check
2
+
3
+ import { LazyFactory } from '../function/LazyFactory.mjs';
4
+ import { Console } from './Console.mjs';
5
+ import { Signal } from './Signal.mjs';
6
+
7
+ /**
8
+ * @typedef {import('../types/ListArg.mjs').ListArg} ListArg
9
+ * @typedef {import('../types/MutationType.mjs').MutationType} MutationType
10
+ */
11
+ /**
12
+ * @description
13
+ * - class to create list that satisfy `Array<Record<string, string>>`.
14
+ * @template {import('../types/ListArg.mjs').ListArg} LA
15
+ * @extends {Signal<LA[]>}
16
+ */
17
+ export class ListSignal extends Signal {
18
+ /**
19
+ * @description
20
+ * - Checks if the input is an array whose first item (if present) is a plain object
21
+ * - with string keys and string values. Allows empty arrays.
22
+ * @param {unknown} value - The value to validate.
23
+ * @returns {value is Array<Record<string, string>>} True if the first item is a valid string record or array is empty.
24
+ */
25
+ static isValid = (value) => {
26
+ if (!Array.isArray(value)) return false;
27
+ const first = value[0];
28
+ if (first === undefined) {
29
+ // allow empty array
30
+ return true;
31
+ }
32
+ return (
33
+ first &&
34
+ typeof first === 'object' &&
35
+ !Array.isArray(first) &&
36
+ Object.entries(first).every(
37
+ ([key, val]) => typeof key === 'string' && typeof val === 'string'
38
+ )
39
+ );
40
+ };
41
+ /**
42
+ * @description
43
+ * - usefull for `loops`;
44
+ * @param {LA[]} [value]
45
+ * @example
46
+ * import { ListSignal } from 'vivth';
47
+ *
48
+ * const listExample = new ListSignal([
49
+ * {key1: "test1",},
50
+ * {key1: "test2",},
51
+ * ]);
52
+ */
53
+ constructor(value = []) {
54
+ super(value);
55
+ }
56
+ /**
57
+ * @description
58
+ * - reference to original inputed `value`;
59
+ * @type {LA[]}
60
+ */
61
+ get value() {
62
+ return super.value;
63
+ }
64
+ /**
65
+ * @description
66
+ * - you cannot mannually set`value` `ListSignal_instance`;
67
+ * @private
68
+ * @type {LA[]}
69
+ */
70
+ set value(_) {
71
+ Console.error('`List.value` `setter` are not available outside the class or instance');
72
+ }
73
+ /**
74
+ * @description
75
+ * - methods collection that mimics `Array` API;
76
+ * - calling this methods will notify subscribers for changes, except for some;
77
+ */
78
+ arrayMethods = LazyFactory(() => {
79
+ return {
80
+ /**
81
+ * @instance arrayMethods
82
+ * @description
83
+ * - reference to structuredClone elements of `value`;
84
+ * - calling doesn't notify
85
+ * @type {Array<LA>}
86
+ */
87
+ get structuredClone() {
88
+ return structuredClone(super.value);
89
+ },
90
+ /**
91
+ * @instance arrayMethods
92
+ * @description
93
+ * - appends new elements to the end;
94
+ * @param {...LA} listArg
95
+ * @returns {void}
96
+ */
97
+ push: (...listArg) => {
98
+ super.value.push(...listArg);
99
+ this.subscribers.notify();
100
+ },
101
+ /**
102
+ * @instance arrayMethods
103
+ * @description
104
+ * - removes the first element;
105
+ * @type {()=>void}
106
+ */
107
+ shift: () => {
108
+ super.value.shift();
109
+ this.subscribers.notify();
110
+ },
111
+ /**
112
+ * @instance arrayMethods
113
+ * @description
114
+ * - inserts new element at the start;
115
+ * @param {...LA} listArg
116
+ * @returns {void}
117
+ */
118
+ unshift: (...listArg) => {
119
+ super.value.unshift(...listArg);
120
+ this.subscribers.notify();
121
+ },
122
+ /**
123
+ * @instance arrayMethods
124
+ * @description
125
+ * - 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;
126
+ * @param {number} [start]
127
+ * - the beginning index of the specified portion of the data. If start is undefined, then the slice begins at index 0.
128
+ * @param {number} [end]
129
+ * - 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.
130
+ * @returns {void}
131
+ */
132
+ slice: (start = 0, end = 0) => {
133
+ const deleteCount = end - start + 1;
134
+ this.arrayMethods.splice(start, deleteCount);
135
+ },
136
+ /**
137
+ * @instance arrayMethods
138
+ * @description
139
+ * - replace whole `List` data with new array.
140
+ * @param {LA[]} listArgs
141
+ * - new array in place of the deleted array.
142
+ * @returns {void}
143
+ */
144
+ replace: (listArgs) => {
145
+ this.arrayMethods.splice(0, super.value.length, ...listArgs);
146
+ },
147
+ /**
148
+ * @instance arrayMethods
149
+ * @description
150
+ * - removes elements from an data and, if necessary, inserts new elements in their place;
151
+ * @param {number} start
152
+ * - The zero-based location in the data from which to start removing elements.
153
+ * @param {number} deleteCount
154
+ * -The number of elements to remove.
155
+ * @param {...LA} listArg
156
+ * - new data in place of the deleted data.
157
+ * @returns {void}
158
+ */
159
+ splice: (start, deleteCount, ...listArg) => {
160
+ const end = start + deleteCount - 1;
161
+ if (!this.#checkLength('splice', end)) {
162
+ return;
163
+ }
164
+ super.value.splice(start, deleteCount, ...listArg);
165
+ this.subscribers.notify();
166
+ },
167
+ /**
168
+ * @instance arrayMethods
169
+ * @description
170
+ * - swap `List` data between two indexes;
171
+ * @param {number} indexA
172
+ * @param {number} indexB
173
+ * @returns {void}
174
+ */
175
+ swap: (indexA, indexB) => {
176
+ if (!this.#checkLength('swap', indexA) || !this.#checkLength('swap', indexB)) {
177
+ return;
178
+ }
179
+ [super.value[indexA], super.value[indexB]] = [super.value[indexB], super.value[indexA]];
180
+ this.subscribers.notify();
181
+ },
182
+ /**
183
+ * @instance arrayMethods
184
+ * @description
185
+ * - modify `List` element at specific index;
186
+ * @param {number} index
187
+ * @param {Partial<LA>} listArg
188
+ * @returns {void}
189
+ */
190
+ modify: (index, listArg) => {
191
+ if (!this.#checkLength('modify', index)) {
192
+ return;
193
+ }
194
+ for (const key in listArg) {
195
+ const listArgKey = listArg[key];
196
+ if (!listArgKey) {
197
+ continue;
198
+ }
199
+ super.value[index][key] = listArgKey;
200
+ }
201
+ this.subscribers.notify();
202
+ },
203
+ /**
204
+ * @instance arrayMethods
205
+ * @description
206
+ * - remove `List` element at specific index;
207
+ * @param {number} index
208
+ * @returns {void}
209
+ */
210
+ remove: (index) => {
211
+ if (!this.#checkLength('remove', index)) {
212
+ return;
213
+ }
214
+ this.arrayMethods.splice(index, 1);
215
+ },
216
+ /**
217
+ * @instance arrayMethods
218
+ * @description
219
+ * - reverses the elements in an `List` in place.
220
+ * @returns {void}
221
+ */
222
+ reverse: () => {
223
+ super.value.reverse();
224
+ this.subscribers.notify();
225
+ },
226
+ /**
227
+ * @instance arrayMethods
228
+ * @description
229
+ * - removes the last element;
230
+ * @returns {void}
231
+ */
232
+ pop: () => {
233
+ super.value.pop();
234
+ this.subscribers.notify();
235
+ },
236
+ };
237
+ });
238
+ /**
239
+ * @param {MutationType} mode
240
+ * @param {number} end
241
+ * @returns {boolean}
242
+ */
243
+ #checkLength = (mode, end) => {
244
+ const dataLength = super.value.length;
245
+ if (end >= dataLength) {
246
+ Console.error({
247
+ mode,
248
+ end,
249
+ dataLength,
250
+ message: 'list modifier, end is out of dataLength',
251
+ });
252
+ return false;
253
+ }
254
+ return true;
255
+ };
256
+ }