vivth 1.2.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +608 -586
- package/README.src.md +5 -1
- package/bun.lock +6 -0
- package/index.mjs +10 -6
- package/package.json +3 -1
- package/src/bundler/CompileJS.mjs +11 -8
- package/src/bundler/EsBundler.mjs +4 -2
- package/src/bundler/FSInline.mjs +3 -0
- package/src/bundler/FSInlineAnalyzer.mjs +31 -7
- package/src/bundler/FSInlineBundled.mjs +5 -1
- package/src/bundler/adds/ToBundledJSPlugin.mjs +3 -4
- package/src/class/Console.mjs +12 -4
- package/src/class/Derived.mjs +5 -1
- package/src/class/Effect.mjs +6 -6
- package/src/class/EnvSignal.mjs +1 -8
- package/src/class/EventSignal.mjs +8 -7
- package/src/class/FileSafe.mjs +1 -1
- package/src/class/ListSignal.mjs +18 -10
- package/src/class/LitExp.mjs +241 -204
- package/src/class/Paths.mjs +10 -8
- package/src/class/QChannel.mjs +14 -7
- package/src/class/SafeExit.mjs +16 -7
- package/src/class/Signal.mjs +8 -7
- package/src/class/WorkerMainThread.mjs +45 -24
- package/src/class/WorkerMainThreadBundled.mjs +42 -24
- package/src/class/WorkerThread.mjs +21 -7
- package/src/common/Base64URL.mjs +2 -2
- package/src/common/Base64URLFromFile.mjs +1 -1
- package/src/doc/JSautoDOC.mjs +99 -62
- package/src/doc/correctBeforeParse.mjs +139 -0
- package/src/doc/parsedFile.mjs +127 -76
- package/src/function/CreateImmutable.mjs +12 -7
- package/src/function/GetRuntime.mjs +8 -3
- package/src/function/LazyFactory.mjs +10 -4
- package/src/function/Try.mjs +4 -1
- package/src/function/TryAsync.mjs +2 -1
- package/src/function/TrySync.mjs +3 -1
- package/src/function/TsToMjs.mjs +7 -4
- package/src/types/AnyButUndefined.mjs +1 -0
- package/src/types/LitExpResultType.mjs +7 -0
- package/src/types/Runtime.mjs +1 -1
- package/tsconfig.json +27 -5
- package/types/dev/workerThreadClass.d.mts +1 -1
- package/types/index.d.mts +7 -6
- package/types/src/bundler/CompileJS.d.mts +14 -9
- package/types/src/bundler/EsBundler.d.mts +1 -1
- package/types/src/class/Derived.d.mts +4 -64
- package/types/src/class/Effect.d.mts +8 -8
- package/types/src/class/EnvSignal.d.mts +0 -1
- package/types/src/class/EventSignal.d.mts +5 -5
- package/types/src/class/FileSafe.d.mts +2 -2
- package/types/src/class/ListSignal.d.mts +1 -1
- package/types/src/class/LitExp.d.mts +49 -53
- package/types/src/class/Paths.d.mts +4 -4
- package/types/src/class/QChannel.d.mts +1 -1
- package/types/src/class/SafeExit.d.mts +3 -3
- package/types/src/class/Signal.d.mts +3 -3
- package/types/src/class/WorkerMainThread.d.mts +13 -8
- package/types/src/class/WorkerMainThreadBundled.d.mts +13 -8
- package/types/src/class/WorkerThread.d.mts +4 -4
- package/types/src/common/Base64URL.d.mts +2 -2
- package/types/src/common/Base64URLFromFile.d.mts +2 -2
- package/types/src/doc/JSautoDOC.d.mts +33 -12
- package/types/src/doc/correctBeforeParse.d.mts +2 -0
- package/types/src/doc/parsedFile.d.mts +7 -10
- package/types/src/function/CreateImmutable.d.mts +2 -2
- package/types/src/function/Try.d.mts +2 -2
- package/types/src/function/TryAsync.d.mts +2 -2
- package/types/src/function/TrySync.d.mts +3 -2
- package/types/src/function/TsToMjs.d.mts +2 -2
- package/types/src/types/LitExpResultType.d.mts +7 -0
package/src/class/LitExp.mjs
CHANGED
|
@@ -18,6 +18,22 @@ export class LitExp {
|
|
|
18
18
|
/**
|
|
19
19
|
* @typedef {import("../types/LitExpKeyType.mjs").LitExpKeyType} LitExpKeyType
|
|
20
20
|
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @description
|
|
24
|
+
* - to escape special chars from string literal;
|
|
25
|
+
* - returned value can be used to create instance of RegExp;
|
|
26
|
+
* @param {string} string
|
|
27
|
+
* @returns {string}
|
|
28
|
+
* @example
|
|
29
|
+
* import { LitExp } from 'vivt';
|
|
30
|
+
*
|
|
31
|
+
* const escapedLiteral = LitExp.escape(`something[][;alerk325]`);
|
|
32
|
+
* new RegExp(escapedLiteral, 'g');
|
|
33
|
+
*/
|
|
34
|
+
static escape = (string) => {
|
|
35
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
36
|
+
};
|
|
21
37
|
/**
|
|
22
38
|
* @description
|
|
23
39
|
* - constructor helper;
|
|
@@ -57,7 +73,7 @@ export class LitExp {
|
|
|
57
73
|
* // recommended to end the template literal with any string but `key`;
|
|
58
74
|
* })()
|
|
59
75
|
*/
|
|
60
|
-
static prepare
|
|
76
|
+
static prepare(keysAndDefaultValuePair) {
|
|
61
77
|
return TrySync(() => {
|
|
62
78
|
for (const key in keysAndDefaultValuePair) {
|
|
63
79
|
const regex = keysAndDefaultValuePair[key];
|
|
@@ -69,7 +85,7 @@ export class LitExp {
|
|
|
69
85
|
return (templateStringArray, ...values) =>
|
|
70
86
|
new LitExp(keysAndDefaultValuePair, templateStringArray, ...values);
|
|
71
87
|
});
|
|
72
|
-
}
|
|
88
|
+
}
|
|
73
89
|
/**
|
|
74
90
|
* @private
|
|
75
91
|
* @param {KEYS} keys
|
|
@@ -101,22 +117,31 @@ export class LitExp {
|
|
|
101
117
|
* @param {TemplateStringsArray} strings
|
|
102
118
|
* @returns {ReturnType<typeof TrySync<string[]>>}
|
|
103
119
|
*/
|
|
104
|
-
static #processTemplate
|
|
120
|
+
static #processTemplate(instance_rules, intance_values, valueHandler, strings) {
|
|
105
121
|
return TrySync(() => {
|
|
122
|
+
/**
|
|
123
|
+
* @type {string[]}
|
|
124
|
+
*/
|
|
106
125
|
const result = [];
|
|
107
126
|
const values = intance_values;
|
|
108
127
|
const stringsLength = strings.length;
|
|
109
128
|
for (let i = 0; i < stringsLength; i++) {
|
|
110
129
|
const string = strings[i];
|
|
130
|
+
if (string === undefined) {
|
|
131
|
+
throw new Error('string undefined');
|
|
132
|
+
}
|
|
111
133
|
if (i + 1 == stringsLength && string === '') {
|
|
112
|
-
result.push('(?:\\s
|
|
134
|
+
result.push('(?:\\s+?|$)');
|
|
113
135
|
} else {
|
|
114
|
-
result.push(string);
|
|
136
|
+
result.push(LitExp.escape(string));
|
|
115
137
|
}
|
|
116
138
|
if (i < values.length) {
|
|
117
139
|
const value = values[i];
|
|
140
|
+
if (value === undefined || instance_rules[value] === undefined) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
118
143
|
const [valueHandled, errorValue] = valueHandler(value, instance_rules[value]);
|
|
119
|
-
if (errorValue ||
|
|
144
|
+
if (errorValue || valueHandled === '') {
|
|
120
145
|
throw errorValue;
|
|
121
146
|
}
|
|
122
147
|
result.push(valueHandled);
|
|
@@ -124,7 +149,7 @@ export class LitExp {
|
|
|
124
149
|
}
|
|
125
150
|
return result;
|
|
126
151
|
});
|
|
127
|
-
}
|
|
152
|
+
}
|
|
128
153
|
/**
|
|
129
154
|
* @param {Parameters<LitExp<KEYS>["evaluate"]["execGroups"]>[1] &
|
|
130
155
|
* { absoluteLeadAndFollowing: boolean }} options
|
|
@@ -133,7 +158,7 @@ export class LitExp {
|
|
|
133
158
|
#regExp = ({ flags, whiteSpaceSensitive, absoluteLeadAndFollowing }) => {
|
|
134
159
|
return TrySync(() => {
|
|
135
160
|
let regExpStringCache;
|
|
136
|
-
if (
|
|
161
|
+
if (this.#regExpStringCache === undefined) {
|
|
137
162
|
const [regExpStringCache, error] = LitExp.#processTemplate(
|
|
138
163
|
this.#keyRules,
|
|
139
164
|
this.#values,
|
|
@@ -145,10 +170,10 @@ export class LitExp {
|
|
|
145
170
|
}
|
|
146
171
|
this.#regExpStringCache = regExpStringCache.join('');
|
|
147
172
|
}
|
|
148
|
-
if (
|
|
149
|
-
regExpStringCache = this.#regExpStringCache.replace(/\s+/g, `\\s+`);
|
|
150
|
-
} else {
|
|
173
|
+
if (whiteSpaceSensitive) {
|
|
151
174
|
regExpStringCache = this.#regExpStringCache;
|
|
175
|
+
} else {
|
|
176
|
+
regExpStringCache = this.#regExpStringCache.replace(/\s+/g, `\\s+`);
|
|
152
177
|
}
|
|
153
178
|
return new RegExp(
|
|
154
179
|
absoluteLeadAndFollowing ? `\^${regExpStringCache}\$` : regExpStringCache,
|
|
@@ -163,75 +188,83 @@ export class LitExp {
|
|
|
163
188
|
#regexToMatchAll = ({ flags, whiteSpaceSensitive }) => {
|
|
164
189
|
return TrySync(() => {
|
|
165
190
|
let regExpToMatchStringCache;
|
|
166
|
-
if (
|
|
191
|
+
if (this.#regExpToMatchStringCache === undefined) {
|
|
167
192
|
const [regExpToMatchStringCache, error] = LitExp.#processTemplate(
|
|
168
193
|
this.#keyRules,
|
|
169
194
|
this.#values,
|
|
170
195
|
LitExp.#namedChapture,
|
|
171
196
|
this.#templateStringArray
|
|
172
197
|
);
|
|
173
|
-
if (error) {
|
|
198
|
+
if (error || regExpToMatchStringCache === undefined) {
|
|
174
199
|
throw error;
|
|
175
200
|
}
|
|
176
201
|
this.#regExpToMatchStringCache = regExpToMatchStringCache.join('');
|
|
177
202
|
}
|
|
178
|
-
if (
|
|
179
|
-
regExpToMatchStringCache = this.#regExpToMatchStringCache.replace(/\s+/g, `\\s+`);
|
|
180
|
-
} else {
|
|
203
|
+
if (whiteSpaceSensitive) {
|
|
181
204
|
regExpToMatchStringCache = this.#regExpToMatchStringCache;
|
|
205
|
+
} else {
|
|
206
|
+
regExpToMatchStringCache = this.#regExpToMatchStringCache.replace(/\s+/g, `\\s+`);
|
|
182
207
|
}
|
|
183
208
|
return new RegExp(`\(${regExpToMatchStringCache}\)`, flags);
|
|
184
209
|
});
|
|
185
210
|
};
|
|
186
|
-
|
|
211
|
+
/**
|
|
212
|
+
* @typedef {ReturnType<LitExp<KEYS>["evaluate"]["execGroups"]>} ExecGroups
|
|
213
|
+
* @typedef {ExecGroups extends [infer First, ...any] ? First : undefined} FirstGroup
|
|
214
|
+
* @typedef {FirstGroup extends { result: any } ? Partial<FirstGroup["result"]> : undefined} Overrides
|
|
215
|
+
*/
|
|
187
216
|
/**
|
|
188
217
|
* @description
|
|
189
218
|
* - instance methods for generating things;
|
|
190
219
|
*/
|
|
191
|
-
make = LazyFactory(() =>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
220
|
+
make = LazyFactory(() => {
|
|
221
|
+
const this_ = this;
|
|
222
|
+
return {
|
|
223
|
+
/**
|
|
224
|
+
* @instance make
|
|
225
|
+
* @description
|
|
226
|
+
* - to make string based on the template literal;
|
|
227
|
+
* @param {Partial<{ [K in keyof KEYS]?: string }>} overrides
|
|
228
|
+
* @returns {string|undefined}
|
|
229
|
+
* @example
|
|
230
|
+
* import { LitExp } from 'vivth';
|
|
231
|
+
*
|
|
232
|
+
* const [literal, errorPreparing] = LitExp.prepare({
|
|
233
|
+
* myKey: false,
|
|
234
|
+
* ...keyCaptureLogicPair
|
|
235
|
+
* })
|
|
236
|
+
*
|
|
237
|
+
* // asuming no error
|
|
238
|
+
* litExp_instance = `templateLiteral:${'myKey'};`;
|
|
239
|
+
* const [result, error] = litExp_instance.make.string({
|
|
240
|
+
* myKey: 'actualvalue',
|
|
241
|
+
* });
|
|
242
|
+
*
|
|
243
|
+
* console.log(result); // "templateLiteral:actualvalue;"
|
|
244
|
+
*/
|
|
245
|
+
string: (overrides) => {
|
|
246
|
+
return TrySync(() => {
|
|
247
|
+
const [res, error] = LitExp.#processTemplate(
|
|
248
|
+
this_.#keyRules,
|
|
249
|
+
this_.#values,
|
|
250
|
+
// @ts-expect-error
|
|
251
|
+
(key) => {
|
|
252
|
+
return TrySync(() => {
|
|
253
|
+
return overrides[key];
|
|
254
|
+
});
|
|
255
|
+
},
|
|
256
|
+
this_.#templateStringArray
|
|
257
|
+
);
|
|
258
|
+
if (error) {
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
return res.join('');
|
|
262
|
+
})[0];
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
});
|
|
233
266
|
/**
|
|
234
|
-
* @type {string}
|
|
267
|
+
* @type {string|undefined}
|
|
235
268
|
*/
|
|
236
269
|
#regExpStringCache;
|
|
237
270
|
/**
|
|
@@ -240,152 +273,81 @@ export class LitExp {
|
|
|
240
273
|
* @param {keyof KEYS} value
|
|
241
274
|
* @returns {ReturnType<typeof TrySync<string>>}
|
|
242
275
|
*/
|
|
243
|
-
static #namedChapture
|
|
276
|
+
static #namedChapture(value, regex) {
|
|
244
277
|
return TrySync(() => {
|
|
245
|
-
const capture =
|
|
278
|
+
const capture = regex === false ? `[\\s\\S]*?` : regex.source;
|
|
246
279
|
return `(?<${value.toString()}>${capture})`;
|
|
247
280
|
});
|
|
248
|
-
}
|
|
281
|
+
}
|
|
249
282
|
/**
|
|
250
|
-
* @type {string}
|
|
283
|
+
* @type {string|undefined}
|
|
251
284
|
*/
|
|
252
285
|
#regExpToMatchStringCache;
|
|
253
286
|
/**
|
|
254
287
|
* @description
|
|
255
288
|
* - methods collections to evaluate string with `Literal Expression`;
|
|
256
289
|
*/
|
|
257
|
-
evaluate = LazyFactory(() =>
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
})
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
return { result, regexp };
|
|
322
|
-
});
|
|
323
|
-
},
|
|
324
|
-
/**
|
|
325
|
-
* @instance evaluate
|
|
326
|
-
* @description
|
|
327
|
-
* - to match all and grouped based on `key`;
|
|
328
|
-
* @param {Parameters<LitExp<KEYS>["evaluate"]["execGroups"]>[0]} string
|
|
329
|
-
* @param {Omit<Parameters<LitExp<KEYS>["evaluate"]["execGroups"]>[1], 'absoluteLeadAndFollowing'>} options
|
|
330
|
-
* @returns {ReturnType<typeof TrySync<{result:{whole:string[], named:Array<Record<keyof KEYS, string>>},
|
|
331
|
-
* regexp: RegExp}>>
|
|
332
|
-
* }
|
|
333
|
-
* @example
|
|
334
|
-
* import { LitExp, Console } from 'vivth';
|
|
335
|
-
*
|
|
336
|
-
* const [literal, errorPreparing] = LitExp.prepare({
|
|
337
|
-
* myKey: false,
|
|
338
|
-
* ...keyCaptureLogicPair
|
|
339
|
-
* })
|
|
340
|
-
*
|
|
341
|
-
* // asuming no error;
|
|
342
|
-
* litExp_instance = literal`templateLiteral:${'myKey'};`
|
|
343
|
-
*
|
|
344
|
-
* const [resultOfMatchedAllAndGrouped, error] = litExp_instance.evaluate.matchedAllAndGrouped(
|
|
345
|
-
* `templateLiteral:Something;
|
|
346
|
-
* templateLiteral:SomethingElse;`,
|
|
347
|
-
* { ...options }
|
|
348
|
-
* )
|
|
349
|
-
* (()=>{
|
|
350
|
-
* if (error) {
|
|
351
|
-
* Console.error(error);
|
|
352
|
-
* return;
|
|
353
|
-
* }
|
|
354
|
-
* const {
|
|
355
|
-
* result: {
|
|
356
|
-
* whole: [whole0, whole1],
|
|
357
|
-
* named: [
|
|
358
|
-
* { myKey: myKeyExec0, },
|
|
359
|
-
* { myKey: myKeyExec1, },
|
|
360
|
-
* ],
|
|
361
|
-
* },
|
|
362
|
-
* regexp
|
|
363
|
-
* } = resultOfMatchedAllAndGrouped;
|
|
364
|
-
*
|
|
365
|
-
* console.log(whole0); // "templateLiteral:Something;"
|
|
366
|
-
* console.log(whole1); // "templateLiteral:SomethingElse;"
|
|
367
|
-
* console.log(myKeyExec0); // "Something"
|
|
368
|
-
* console.log(myKeyExec1); // "SomethingElse"
|
|
369
|
-
* })()
|
|
370
|
-
*/
|
|
371
|
-
matchedAllAndGrouped: (string, options) => {
|
|
372
|
-
return TrySync(() => {
|
|
373
|
-
const [regexp, error] = this.#regexToMatchAll(options);
|
|
374
|
-
if (error || !regexp) {
|
|
375
|
-
throw error;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* @type {Array<Record<keyof KEYS, string>>}
|
|
379
|
-
*/
|
|
380
|
-
const named = [];
|
|
381
|
-
const whole = [];
|
|
382
|
-
/**
|
|
383
|
-
* @type {{whole:string[], named:Array<Record<keyof KEYS, string>>}}
|
|
384
|
-
*/
|
|
385
|
-
const result = { named, whole };
|
|
386
|
-
const matchedAll = string.matchAll(regexp);
|
|
387
|
-
for (const match of matchedAll) {
|
|
388
|
-
if (!match.groups) {
|
|
290
|
+
evaluate = LazyFactory(() => {
|
|
291
|
+
const this_ = this;
|
|
292
|
+
return {
|
|
293
|
+
/**
|
|
294
|
+
* @instance evaluate
|
|
295
|
+
* @description
|
|
296
|
+
* - to exec and grouped based on `key`;
|
|
297
|
+
* @param {string} string
|
|
298
|
+
* @param {Object} options
|
|
299
|
+
* @param {ConstructorParameters<typeof RegExp>[1]} options.flags
|
|
300
|
+
* @param {boolean} options.whiteSpaceSensitive
|
|
301
|
+
* - true: leave any whitespace as is to be used as regex detection;
|
|
302
|
+
* - false: convert all whitespace to `\s+`;
|
|
303
|
+
* @param {boolean} options.absoluteLeadAndFollowing
|
|
304
|
+
* - false: standard capture;
|
|
305
|
+
* - true: add `^` and `$` to capture definition:
|
|
306
|
+
* >- meaning string will have to match starting and end of line from capture definition;
|
|
307
|
+
* @returns {ReturnType<typeof TrySync<{
|
|
308
|
+
* result:{ whole:string, named: Record<keyof KEYS, string>},
|
|
309
|
+
* regexp:RegExp}>>
|
|
310
|
+
* }
|
|
311
|
+
* @example
|
|
312
|
+
* import { LitExp } from 'vivth';
|
|
313
|
+
*
|
|
314
|
+
* const [literal, errorPreparing] = LitExp.prepare({
|
|
315
|
+
* myKey: false,
|
|
316
|
+
* ...keyCaptureLogicPair
|
|
317
|
+
* })
|
|
318
|
+
*
|
|
319
|
+
* // asuming no eror
|
|
320
|
+
* const litExp_instance = literal`templateLiteral:${'myKey'};`
|
|
321
|
+
*
|
|
322
|
+
* const [{
|
|
323
|
+
* result:{ // asuming there's no error
|
|
324
|
+
* named: { myKey },
|
|
325
|
+
* whole,
|
|
326
|
+
* },
|
|
327
|
+
* regex, // for reference
|
|
328
|
+
* }, error] = litExp_instance.evaluate.execGroups(
|
|
329
|
+
* `templateLiteral:Something;`,
|
|
330
|
+
* { ...options }
|
|
331
|
+
* )
|
|
332
|
+
*
|
|
333
|
+
* console.log(whole); // "templateLiteral:Something;"
|
|
334
|
+
* console.log(myKey); // "Something"
|
|
335
|
+
*/
|
|
336
|
+
execGroups(string, options) {
|
|
337
|
+
// @ts-expect-error
|
|
338
|
+
return TrySync(() => {
|
|
339
|
+
const [regexp, error] = this_.#regExp(options);
|
|
340
|
+
if (error) {
|
|
341
|
+
throw error;
|
|
342
|
+
}
|
|
343
|
+
const execResult = regexp.exec(string);
|
|
344
|
+
if (execResult === null) {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
const whole = execResult[1];
|
|
348
|
+
const named = execResult?.groups;
|
|
349
|
+
const result = { named, whole };
|
|
350
|
+
if (named === undefined) {
|
|
389
351
|
throw new Error(
|
|
390
352
|
JSON.stringify({
|
|
391
353
|
regexpSource: regexp.source,
|
|
@@ -394,12 +356,87 @@ export class LitExp {
|
|
|
394
356
|
})
|
|
395
357
|
);
|
|
396
358
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
359
|
+
return { result, regexp };
|
|
360
|
+
});
|
|
361
|
+
},
|
|
362
|
+
/**
|
|
363
|
+
* @instance evaluate
|
|
364
|
+
* @description
|
|
365
|
+
* - to match all and grouped based on `key`;
|
|
366
|
+
* @param {Parameters<LitExp<KEYS>["evaluate"]["execGroups"]>[0]} string
|
|
367
|
+
* @param {Omit<Parameters<LitExp<KEYS>["evaluate"]["execGroups"]>[1], 'absoluteLeadAndFollowing'>} options
|
|
368
|
+
* @returns {ReturnType<typeof TrySync<import('../types/LitExpResultType.mjs').LitExpResultType<KEYS>>>
|
|
369
|
+
* }
|
|
370
|
+
* @example
|
|
371
|
+
* import { LitExp, Console } from 'vivth';
|
|
372
|
+
*
|
|
373
|
+
* const [literal, errorPreparing] = LitExp.prepare({
|
|
374
|
+
* myKey: false,
|
|
375
|
+
* ...keyCaptureLogicPair
|
|
376
|
+
* })
|
|
377
|
+
*
|
|
378
|
+
* // asuming no error;
|
|
379
|
+
* litExp_instance = literal`templateLiteral:${'myKey'};`
|
|
380
|
+
*
|
|
381
|
+
* const [resultOfMatchedAllAndGrouped, error] = litExp_instance.evaluate.matchedAllAndGrouped(
|
|
382
|
+
* `templateLiteral:Something;
|
|
383
|
+
* templateLiteral:SomethingElse;`,
|
|
384
|
+
* { ...options }
|
|
385
|
+
* )
|
|
386
|
+
* (()=>{
|
|
387
|
+
* if (error) {
|
|
388
|
+
* Console.error(error);
|
|
389
|
+
* return;
|
|
390
|
+
* }
|
|
391
|
+
* const {
|
|
392
|
+
* result: { whole, named },
|
|
393
|
+
* regexp
|
|
394
|
+
* } = resultOfMatchedAllAndGrouped;
|
|
395
|
+
*
|
|
396
|
+
* named.foreach(({myKey})=>{
|
|
397
|
+
* // code
|
|
398
|
+
* })
|
|
399
|
+
* whole.foreach((capturedString)=>{
|
|
400
|
+
* // code
|
|
401
|
+
* })
|
|
402
|
+
* })()
|
|
403
|
+
*/
|
|
404
|
+
matchedAllAndGrouped: (string, options) => {
|
|
405
|
+
return TrySync(() => {
|
|
406
|
+
const [regexp, error] = this.#regexToMatchAll(options);
|
|
407
|
+
if (error) {
|
|
408
|
+
throw error;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* @type {Array<Record<keyof KEYS, string>>}
|
|
412
|
+
*/
|
|
413
|
+
const named = [];
|
|
414
|
+
/**
|
|
415
|
+
* @type {Array<string>}
|
|
416
|
+
*/
|
|
417
|
+
const whole = [];
|
|
418
|
+
/**
|
|
419
|
+
* @type {{whole:string[], named:Array<Record<keyof KEYS, string>>}}
|
|
420
|
+
*/
|
|
421
|
+
const result = { named, whole };
|
|
422
|
+
const matchedAll = string.matchAll(regexp);
|
|
423
|
+
for (const match of matchedAll) {
|
|
424
|
+
if (match.groups === undefined) {
|
|
425
|
+
throw new Error(
|
|
426
|
+
JSON.stringify({
|
|
427
|
+
regexpSource: regexp.source,
|
|
428
|
+
message: 'no match is found',
|
|
429
|
+
sugestion: 'make sure all `keys` values will capture any scenario',
|
|
430
|
+
})
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
whole.push(match[1] ?? '');
|
|
434
|
+
// @ts-expect-error
|
|
435
|
+
named.push(match.groups);
|
|
436
|
+
}
|
|
437
|
+
return { result, regexp };
|
|
438
|
+
});
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
});
|
|
405
442
|
}
|
package/src/class/Paths.mjs
CHANGED
|
@@ -12,9 +12,9 @@ import { Console } from './Console.mjs';
|
|
|
12
12
|
*/
|
|
13
13
|
export class Paths {
|
|
14
14
|
/**
|
|
15
|
-
* @type {Paths}
|
|
15
|
+
* @type {Paths|undefined}
|
|
16
16
|
*/
|
|
17
|
-
static #instance
|
|
17
|
+
static #instance;
|
|
18
18
|
/**
|
|
19
19
|
* @description
|
|
20
20
|
* @param {Object} options
|
|
@@ -51,19 +51,19 @@ export class Paths {
|
|
|
51
51
|
this.#root = root;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* @type {string}
|
|
54
|
+
* @type {string|undefined}
|
|
55
55
|
*/
|
|
56
|
-
#root
|
|
56
|
+
#root;
|
|
57
57
|
/**
|
|
58
58
|
* @description
|
|
59
59
|
* - reference for rootPath
|
|
60
60
|
* - `Paths` needed to be instantiated via:
|
|
61
61
|
* >- `Paths` constructor;
|
|
62
62
|
* >- `Setup.paths` constructor;
|
|
63
|
-
* @type {string}
|
|
63
|
+
* @type {string|undefined}
|
|
64
64
|
*/
|
|
65
65
|
static get root() {
|
|
66
|
-
if (
|
|
66
|
+
if (Paths.#instance === undefined) {
|
|
67
67
|
Console.error({
|
|
68
68
|
error: 'Paths.instance.#root is undefined',
|
|
69
69
|
solutions: 'instantiate `Paths` or instantiate `Setup`',
|
|
@@ -82,7 +82,9 @@ export class Paths {
|
|
|
82
82
|
*
|
|
83
83
|
* Paths.normalize('file:\\D:\\myFile.mjs'); // "file://D://myFile.mjs"
|
|
84
84
|
*/
|
|
85
|
-
static normalize = (path_) =>
|
|
85
|
+
static normalize = (path_) => {
|
|
86
|
+
return path_.replace(/\\/g, '/');
|
|
87
|
+
};
|
|
86
88
|
/**
|
|
87
89
|
* @description
|
|
88
90
|
* - normalize path separator to forward slash `/`;
|
|
@@ -96,7 +98,7 @@ export class Paths {
|
|
|
96
98
|
*/
|
|
97
99
|
static normalizesForRoot = (path_) => {
|
|
98
100
|
let normalized = Paths.normalize(path_);
|
|
99
|
-
if (
|
|
101
|
+
if (normalized.startsWith('/') === false) {
|
|
100
102
|
normalized = `/${normalized}`;
|
|
101
103
|
}
|
|
102
104
|
// @ts-expect-error
|
package/src/class/QChannel.mjs
CHANGED
|
@@ -48,17 +48,18 @@ export class QChannel {
|
|
|
48
48
|
* - ensures that each id has only one task running at a time.
|
|
49
49
|
* - calls with the same id will wait for the previous call to finish.
|
|
50
50
|
* @param {AnyButUndefined} id
|
|
51
|
-
* @param {QChannel} instance
|
|
51
|
+
* @param {QChannel<any>} instance
|
|
52
52
|
* @returns {Promise<QCBReturn>} Resolves when it's safe to proceed for the given id, returning a cleanup function
|
|
53
53
|
*/
|
|
54
54
|
static #uniqueCB = async (id, instance) => {
|
|
55
55
|
const existing = QChannel.#uniquePromiser.get(id);
|
|
56
|
+
// @ts-expect-error
|
|
56
57
|
let resolveFn;
|
|
57
58
|
const nextPromise = new Promise((resolve) => {
|
|
58
59
|
resolveFn = resolve;
|
|
59
60
|
});
|
|
60
61
|
const context = {};
|
|
61
|
-
if (
|
|
62
|
+
if (existing === undefined) {
|
|
62
63
|
QChannel.#uniquePromiser.set(id, [nextPromise, context]);
|
|
63
64
|
await Promise.resolve();
|
|
64
65
|
} else {
|
|
@@ -67,15 +68,17 @@ export class QChannel {
|
|
|
67
68
|
QChannel.#uniquePromiser.set(id, [nextPromise, context]);
|
|
68
69
|
}
|
|
69
70
|
const resume = () => {
|
|
71
|
+
// @ts-expect-error
|
|
70
72
|
resolveFn();
|
|
71
73
|
QChannel.#uniquePromiser.delete(id);
|
|
72
74
|
};
|
|
73
75
|
return {
|
|
74
76
|
resume,
|
|
75
77
|
isLastOnQ: () => {
|
|
76
|
-
if (
|
|
78
|
+
if (QChannel.#uniquePromiser.has(id) === false) {
|
|
77
79
|
return false;
|
|
78
80
|
}
|
|
81
|
+
// @ts-expect-error
|
|
79
82
|
const [, lastContext] = QChannel.#uniquePromiser.get(id);
|
|
80
83
|
return instance.#shouldRun && lastContext === context;
|
|
81
84
|
},
|
|
@@ -140,13 +143,13 @@ export class QChannel {
|
|
|
140
143
|
/**
|
|
141
144
|
* @type {boolean}
|
|
142
145
|
*/
|
|
143
|
-
#shouldRun_;
|
|
146
|
+
#shouldRun_ = true;
|
|
144
147
|
/**
|
|
145
148
|
* @returns {boolean}
|
|
146
149
|
*/
|
|
147
150
|
get #shouldRun() {
|
|
148
151
|
const shoulRun = this.#shouldRun_;
|
|
149
|
-
if (
|
|
152
|
+
if (shoulRun === false) {
|
|
150
153
|
Console.warn({ qChannel_name: this.name, message: 'is closed' });
|
|
151
154
|
}
|
|
152
155
|
return shoulRun;
|
|
@@ -197,11 +200,15 @@ export class QChannel {
|
|
|
197
200
|
key = async (keyID) => {
|
|
198
201
|
const { resume } = await QChannel.#uniqueCB(this, this);
|
|
199
202
|
const mapped = this.#mapped;
|
|
200
|
-
if (
|
|
203
|
+
if (mapped.has(keyID) === false) {
|
|
201
204
|
mapped.set(keyID, {});
|
|
202
205
|
}
|
|
203
206
|
resume();
|
|
204
|
-
return await QChannel.#uniqueCB(
|
|
207
|
+
return await QChannel.#uniqueCB(
|
|
208
|
+
// @ts-expect-error
|
|
209
|
+
mapped.get(keyID),
|
|
210
|
+
this
|
|
211
|
+
);
|
|
205
212
|
};
|
|
206
213
|
/**
|
|
207
214
|
* @description
|