vivth 1.1.2 → 1.2.1
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 +1215 -433
- package/README.src.md +5 -2
- package/bun.lock +228 -0
- package/index.mjs +17 -4
- package/package.json +6 -3
- package/src/bundler/CompileJS.mjs +258 -0
- package/src/bundler/CreateESPlugin.mjs +24 -0
- package/src/bundler/EsBundler.mjs +27 -13
- package/src/bundler/FSInline.mjs +57 -0
- package/src/bundler/FSInlineAnalyzer.mjs +197 -0
- package/src/bundler/FSInlineBundled.mjs +34 -0
- package/src/bundler/adds/ToBundledJSPlugin.mjs +77 -0
- package/src/bundler/adds/externals.mjs +8 -0
- package/src/bundler/adds/pluginVivthBundle.mjs +5 -0
- package/src/class/Console.mjs +48 -27
- package/src/class/Derived.mjs +55 -7
- package/src/class/Effect.mjs +100 -39
- package/src/class/EnvSignal.mjs +5 -5
- package/src/class/EventSignal.mjs +55 -5
- package/src/class/FileSafe.mjs +124 -0
- package/src/class/ListDerived.mjs +6 -3
- package/src/class/ListSignal.mjs +11 -11
- package/src/class/LitExp.mjs +405 -0
- package/src/class/Paths.mjs +27 -1
- package/src/class/QChannel.mjs +79 -28
- package/src/class/SafeExit.mjs +31 -11
- package/src/class/Setup.mjs +5 -2
- package/src/class/Signal.mjs +26 -24
- package/src/class/WorkerMainThread.mjs +100 -133
- package/src/class/WorkerMainThreadBundled.mjs +216 -0
- package/src/class/WorkerThread.mjs +38 -32
- package/src/common/Base64URL.mjs +10 -5
- package/src/common/Base64URLFromFile.mjs +24 -0
- package/src/common/keys.mjs +3 -0
- package/src/doc/JSautoDOC.mjs +32 -56
- package/src/doc/parsedFile.mjs +37 -36
- package/src/function/CreateImmutable.mjs +9 -9
- package/src/function/EventCheck.mjs +2 -2
- package/src/function/EventObject.mjs +5 -5
- package/src/function/GetRuntime.mjs +38 -0
- package/src/function/IsAsync.mjs +2 -2
- package/src/function/LazyFactory.mjs +13 -13
- package/src/function/Timeout.mjs +2 -2
- package/src/function/Try.mjs +17 -12
- package/src/function/TryAsync.mjs +5 -5
- package/src/function/TrySync.mjs +5 -5
- package/src/function/TsToMjs.mjs +5 -4
- package/src/types/LitExpKeyType.mjs +5 -0
- package/src/types/QCBReturn.mjs +1 -1
- package/src/types/Runtime.mjs +7 -0
- package/types/dev/fsInline.d.mts +1 -0
- package/types/dev/test.d.mts +1 -0
- package/types/dev/testWorker.d.mts +7 -0
- package/types/dev/testbundle.d.mts +1 -0
- package/types/dev/workerThreadClass.d.mts +13 -0
- package/types/index.d.mts +13 -4
- package/types/src/bundler/CompileJS.d.mts +78 -0
- package/types/src/bundler/CreateESPlugin.d.mts +17 -0
- package/types/src/bundler/EsBundler.d.mts +33 -4
- package/types/src/bundler/FSInline.d.mts +43 -0
- package/types/src/bundler/FSInlineAnalyzer.d.mts +36 -0
- package/types/src/bundler/FSInlineBundled.d.mts +22 -0
- package/types/src/bundler/adds/ToBundledJSPlugin.d.mts +16 -0
- package/types/src/bundler/adds/externals.d.mts +1 -0
- package/types/src/bundler/adds/pluginVivthBundle.d.mts +1 -0
- package/types/src/class/Console.d.mts +36 -5
- package/types/src/class/Derived.d.mts +132 -5
- package/types/src/class/Effect.d.mts +106 -7
- package/types/src/class/EnvSignal.d.mts +8 -8
- package/types/src/class/EventSignal.d.mts +151 -7
- package/types/src/class/FileSafe.d.mts +90 -0
- package/types/src/class/ListDerived.d.mts +8 -5
- package/types/src/class/ListSignal.d.mts +123 -18
- package/types/src/class/LitExp.d.mts +361 -0
- package/types/src/class/Paths.d.mts +18 -1
- package/types/src/class/QChannel.d.mts +69 -22
- package/types/src/class/SafeExit.d.mts +24 -9
- package/types/src/class/Setup.d.mts +6 -5
- package/types/src/class/Signal.d.mts +73 -17
- package/types/src/class/WorkerMainThread.d.mts +39 -37
- package/types/src/class/WorkerMainThreadBundled.d.mts +85 -0
- package/types/src/class/WorkerThread.d.mts +32 -27
- package/types/src/common/Base64URL.d.mts +22 -1
- package/types/src/common/Base64URLFromFile.d.mts +16 -0
- package/types/src/common/keys.d.mts +1 -0
- package/types/src/doc/JSautoDOC.d.mts +3 -19
- package/types/src/doc/parsedFile.d.mts +72 -13
- package/types/src/function/CreateImmutable.d.mts +27 -2
- package/types/src/function/EventCheck.d.mts +15 -0
- package/types/src/function/EventObject.d.mts +17 -2
- package/types/src/function/GetRuntime.d.mts +2 -0
- package/types/src/function/IsAsync.d.mts +18 -0
- package/types/src/function/LazyFactory.d.mts +35 -2
- package/types/src/function/Timeout.d.mts +16 -0
- package/types/src/function/Try.d.mts +52 -1
- package/types/src/function/TryAsync.d.mts +22 -1
- package/types/src/function/TrySync.d.mts +16 -1
- package/types/src/function/TsToMjs.d.mts +19 -0
- package/types/src/types/LitExpKeyType.d.mts +1 -0
- package/types/src/types/QCBReturn.d.mts +1 -1
- package/types/src/types/Runtime.d.mts +1 -0
- package/dev/index.mjs +0 -28
- package/src/bundler/CompileMJS.mjs +0 -110
- package/src/function/WriteFileSafe.mjs +0 -37
- package/types/src/bundler/A.d.mts +0 -1
- package/types/src/bundler/CompileMJS.d.mts +0 -8
- package/types/src/function/WriteFileSafe.d.mts +0 -2
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { writeFile, mkdir, copyFile, rename, rm } from 'node:fs/promises';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { TryAsync } from '../function/TryAsync.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* - collection of static methods of file access with added safety to mkdir before proceeding;
|
|
10
|
+
*/
|
|
11
|
+
export class FileSafe {
|
|
12
|
+
/**
|
|
13
|
+
* @description
|
|
14
|
+
* - method to create file safely by recursively mkdir the dirname of the outFile;
|
|
15
|
+
* - also returning promise of result & error as value;
|
|
16
|
+
* @param {Parameters<writeFile>[0]} outFile
|
|
17
|
+
* @param {Parameters<writeFile>[1]} content
|
|
18
|
+
* @param {Parameters<writeFile>[2]} [options]
|
|
19
|
+
* @returns {ReturnType<typeof TryAsync<void>>}
|
|
20
|
+
* @example
|
|
21
|
+
* import { join } from 'node:path';
|
|
22
|
+
* import { FileSafe, Paths } from 'vivth';
|
|
23
|
+
*
|
|
24
|
+
* const [, errorWrite] = await FileSafe.write(
|
|
25
|
+
* join(Paths.root, '/some/path.mjs'),
|
|
26
|
+
* `console.log("hello-world!!");`,
|
|
27
|
+
* { encoding: 'utf-8' }
|
|
28
|
+
* );
|
|
29
|
+
*/
|
|
30
|
+
static write = async (outFile, content, options) => {
|
|
31
|
+
return await TryAsync(async () => {
|
|
32
|
+
const [, errorMkDir] = await FileSafe.mkdir(dirname(outFile.toString()));
|
|
33
|
+
if (errorMkDir) {
|
|
34
|
+
throw new Error(`error mkdir, "${dirname(outFile.toString())}"`);
|
|
35
|
+
}
|
|
36
|
+
return writeFile(outFile, content, options);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* @description
|
|
41
|
+
* - method to copy file/dir safely by recursively mkdir the dirname of the dest;
|
|
42
|
+
* - also returning promise of result & error as value;
|
|
43
|
+
* @param {Parameters<typeof copyFile>[0]} sourceFile
|
|
44
|
+
* @param {Parameters<typeof copyFile>[1]} destinationFile
|
|
45
|
+
* @param {Parameters<typeof copyFile>[2]} mode
|
|
46
|
+
* @returns {ReturnType<typeof TryAsync<void>>}
|
|
47
|
+
* @example
|
|
48
|
+
* import { join } from 'node:path';
|
|
49
|
+
* import { FileSafe, Paths } from 'vivth';
|
|
50
|
+
*
|
|
51
|
+
* const [, errorWrite] = await FileSafe.copy(
|
|
52
|
+
* join(Paths.root, '/some/path.mjs'),
|
|
53
|
+
* join(Paths.root, '/other/path.copy.mjs'),
|
|
54
|
+
* { encoding: 'utf-8' }
|
|
55
|
+
* );
|
|
56
|
+
*/
|
|
57
|
+
static copy = async (sourceFile, destinationFile, mode) => {
|
|
58
|
+
return await TryAsync(async () => {
|
|
59
|
+
const dest_ = destinationFile.toString();
|
|
60
|
+
const [, errorMkDir] = await FileSafe.mkdir(dirname(dest_));
|
|
61
|
+
if (errorMkDir) {
|
|
62
|
+
throw new Error(`error mkdir, "${dirname(dest_)}"`);
|
|
63
|
+
}
|
|
64
|
+
return await copyFile(sourceFile, destinationFile, mode);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* @description
|
|
69
|
+
* - method to rename file/dir safely by recursively mkdir the dirname of the dest;
|
|
70
|
+
* - also returning promise of result & error as value;
|
|
71
|
+
* @param {Parameters<typeof rename>[0]} oldPath
|
|
72
|
+
* @param {Parameters<typeof rename>[0]} newPath
|
|
73
|
+
* @returns {ReturnType<typeof TryAsync<void>>}
|
|
74
|
+
* @example
|
|
75
|
+
* import { join } from 'node:path';
|
|
76
|
+
* import { FileSafe, Paths } from 'vivth';
|
|
77
|
+
*
|
|
78
|
+
* const [, errorRename] = await FileSafe.rename(
|
|
79
|
+
* join(Paths.root, 'some/path'),
|
|
80
|
+
* join(Paths.root, 'other/path'),
|
|
81
|
+
* );
|
|
82
|
+
*/
|
|
83
|
+
static rename = async (oldPath, newPath) => {
|
|
84
|
+
return await TryAsync(async () => {
|
|
85
|
+
const dest_ = newPath.toString();
|
|
86
|
+
const [, errorMkDir] = await FileSafe.mkdir(dirname(dest_));
|
|
87
|
+
if (errorMkDir) {
|
|
88
|
+
throw new Error(`error mkdir, "${dirname(dest_)}"`);
|
|
89
|
+
}
|
|
90
|
+
return await rename(oldPath, newPath);
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* @description
|
|
95
|
+
* - function to remove dir and file;
|
|
96
|
+
* - also returning promise of result & error as value;
|
|
97
|
+
* @param {Parameters<rm>[0]} path
|
|
98
|
+
* @param {Parameters<rm>[1]} [rmOptions]
|
|
99
|
+
* @returns {ReturnType<typeof TryAsync<void>>}
|
|
100
|
+
*/
|
|
101
|
+
static rm = async (path, rmOptions) => {
|
|
102
|
+
return await TryAsync(async () => {
|
|
103
|
+
return await rm(path, rmOptions);
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* @description
|
|
108
|
+
* - create directory recursively;
|
|
109
|
+
* - also returning promise of result & error as value;
|
|
110
|
+
* @param {Parameters<mkdir>[0]} outDir
|
|
111
|
+
* - absolute path
|
|
112
|
+
* @returns {ReturnType<typeof TryAsync<string>>}
|
|
113
|
+
* @example
|
|
114
|
+
* import { join } from 'node:path';
|
|
115
|
+
* import { FileSafe, Paths } from 'vivth';
|
|
116
|
+
*
|
|
117
|
+
* const [str, errorMkDir] = await FileSafe.mkdir(join(Paths.root, '/some/path/example'));
|
|
118
|
+
*/
|
|
119
|
+
static mkdir = async (outDir) => {
|
|
120
|
+
return await TryAsync(async () => {
|
|
121
|
+
return await mkdir(outDir, { recursive: true });
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -7,16 +7,19 @@ import { Effect } from './Effect.mjs';
|
|
|
7
7
|
* - class to create `dervivedList` that satisfy `Array<Record<string, string>>`;
|
|
8
8
|
* - usefull for `derivedLoops`, e.g. temporary search values;
|
|
9
9
|
* - is a `Derived` instance;
|
|
10
|
-
* @template {ListArg}
|
|
11
|
-
* @extends {Derived<
|
|
10
|
+
* @template {ListArg} LISTARG
|
|
11
|
+
* @extends {Derived<LISTARG[]>}
|
|
12
12
|
*/
|
|
13
13
|
export class ListDerived extends Derived {
|
|
14
14
|
/**
|
|
15
15
|
* @typedef {import('../types/ListArg.mjs').ListArg} ListArg
|
|
16
|
+
* @typedef {import('../common/lazie.mjs').unwrapLazy} unwrapLazy
|
|
16
17
|
*/
|
|
17
18
|
/**
|
|
18
19
|
* @description
|
|
19
|
-
* @param {(effectInstanceOptions:Effect["options"]
|
|
20
|
+
* @param {(effectInstanceOptions:Omit<Effect["options"],
|
|
21
|
+
* unwrapLazy>)=>
|
|
22
|
+
* Promise<LISTARG[]>} derivedFunction
|
|
20
23
|
* @example
|
|
21
24
|
* import { ListSignal, ListDerived } from 'vivth';
|
|
22
25
|
*
|
package/src/class/ListSignal.mjs
CHANGED
|
@@ -11,8 +11,8 @@ import { Signal } from './Signal.mjs';
|
|
|
11
11
|
/**
|
|
12
12
|
* @description
|
|
13
13
|
* - class to create list that satisfy `Array<Record<string, string>>`.
|
|
14
|
-
* @template {import('../types/ListArg.mjs').ListArg}
|
|
15
|
-
* @extends {Signal<
|
|
14
|
+
* @template {import('../types/ListArg.mjs').ListArg} LISTARG
|
|
15
|
+
* @extends {Signal<LISTARG[]>}
|
|
16
16
|
*/
|
|
17
17
|
export class ListSignal extends Signal {
|
|
18
18
|
/**
|
|
@@ -41,7 +41,7 @@ export class ListSignal extends Signal {
|
|
|
41
41
|
/**
|
|
42
42
|
* @description
|
|
43
43
|
* - usefull for `loops`;
|
|
44
|
-
* @param {
|
|
44
|
+
* @param {LISTARG[]} [value]
|
|
45
45
|
* @example
|
|
46
46
|
* import { ListSignal } from 'vivth';
|
|
47
47
|
*
|
|
@@ -56,7 +56,7 @@ export class ListSignal extends Signal {
|
|
|
56
56
|
/**
|
|
57
57
|
* @description
|
|
58
58
|
* - reference to original inputed `value`;
|
|
59
|
-
* @
|
|
59
|
+
* @returns {LISTARG[]}
|
|
60
60
|
*/
|
|
61
61
|
get value() {
|
|
62
62
|
return super.value;
|
|
@@ -65,7 +65,7 @@ export class ListSignal extends Signal {
|
|
|
65
65
|
* @description
|
|
66
66
|
* - you cannot mannually set`value` `ListSignal_instance`;
|
|
67
67
|
* @private
|
|
68
|
-
* @type {
|
|
68
|
+
* @type {LISTARG[]}
|
|
69
69
|
*/
|
|
70
70
|
set value(_) {
|
|
71
71
|
Console.error('`List.value` `setter` are not available outside the class or instance');
|
|
@@ -82,7 +82,7 @@ export class ListSignal extends Signal {
|
|
|
82
82
|
* @description
|
|
83
83
|
* - reference to structuredClone elements of `value`;
|
|
84
84
|
* - calling doesn't notify
|
|
85
|
-
* @
|
|
85
|
+
* @returns {Array<LISTARG>}
|
|
86
86
|
*/
|
|
87
87
|
get structuredClone() {
|
|
88
88
|
return structuredClone(super.value);
|
|
@@ -91,7 +91,7 @@ export class ListSignal extends Signal {
|
|
|
91
91
|
* @instance arrayMethods
|
|
92
92
|
* @description
|
|
93
93
|
* - appends new elements to the end;
|
|
94
|
-
* @param {...
|
|
94
|
+
* @param {...LISTARG} listArg
|
|
95
95
|
* @returns {void}
|
|
96
96
|
*/
|
|
97
97
|
push: (...listArg) => {
|
|
@@ -112,7 +112,7 @@ export class ListSignal extends Signal {
|
|
|
112
112
|
* @instance arrayMethods
|
|
113
113
|
* @description
|
|
114
114
|
* - inserts new element at the start;
|
|
115
|
-
* @param {...
|
|
115
|
+
* @param {...LISTARG} listArg
|
|
116
116
|
* @returns {void}
|
|
117
117
|
*/
|
|
118
118
|
unshift: (...listArg) => {
|
|
@@ -137,7 +137,7 @@ export class ListSignal extends Signal {
|
|
|
137
137
|
* @instance arrayMethods
|
|
138
138
|
* @description
|
|
139
139
|
* - replace whole `List` data with new array.
|
|
140
|
-
* @param {
|
|
140
|
+
* @param {LISTARG[]} listArgs
|
|
141
141
|
* - new array in place of the deleted array.
|
|
142
142
|
* @returns {void}
|
|
143
143
|
*/
|
|
@@ -152,7 +152,7 @@ export class ListSignal extends Signal {
|
|
|
152
152
|
* - The zero-based location in the data from which to start removing elements.
|
|
153
153
|
* @param {number} deleteCount
|
|
154
154
|
* -The number of elements to remove.
|
|
155
|
-
* @param {...
|
|
155
|
+
* @param {...LISTARG} listArg
|
|
156
156
|
* - new data in place of the deleted data.
|
|
157
157
|
* @returns {void}
|
|
158
158
|
*/
|
|
@@ -184,7 +184,7 @@ export class ListSignal extends Signal {
|
|
|
184
184
|
* @description
|
|
185
185
|
* - modify `List` element at specific index;
|
|
186
186
|
* @param {number} index
|
|
187
|
-
* @param {Partial<
|
|
187
|
+
* @param {Partial<LISTARG>} listArg
|
|
188
188
|
* @returns {void}
|
|
189
189
|
*/
|
|
190
190
|
modify: (index, listArg) => {
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { LazyFactory } from '../function/LazyFactory.mjs';
|
|
4
|
+
import { TrySync } from '../function/TrySync.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @description
|
|
8
|
+
* - class helper to created opionated regex helper;
|
|
9
|
+
* - named capture uses `es6+` feature, you might need to add polyfill to target extremely old browser;
|
|
10
|
+
* - class name refer to `Literal Expression`;
|
|
11
|
+
* - please be patient when using this class;
|
|
12
|
+
* >- destructuring is meant for extensive typehelper;
|
|
13
|
+
* >- and destructuring can lead to unhandled error here and there;
|
|
14
|
+
* >- therefore error as value is introduced to help to prevent error on runtime;
|
|
15
|
+
* @template {LitExpKeyType} KEYS
|
|
16
|
+
*/
|
|
17
|
+
export class LitExp {
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {import("../types/LitExpKeyType.mjs").LitExpKeyType} LitExpKeyType
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @description
|
|
23
|
+
* - constructor helper;
|
|
24
|
+
* - under the hood it is an abstraction of `RegExp`, with more template literal touch;
|
|
25
|
+
* >- you can apply inline `RegExp` features on the string template literal(as constructor RegExp arg0);
|
|
26
|
+
* >>- by doing so you are opting in to make:
|
|
27
|
+
* >>>- your regex detection more robust; but
|
|
28
|
+
* >>>- `litExp_instance.make.string` to be `unusable`;
|
|
29
|
+
* >>- also mind the needs of escape for special characters;
|
|
30
|
+
* @template {LitExpKeyType} KEYS
|
|
31
|
+
* @param {KEYS} keysAndDefaultValuePair
|
|
32
|
+
* - keys and whether to override regex detection;
|
|
33
|
+
* >- example:
|
|
34
|
+
* ```js
|
|
35
|
+
* myKey: /myCustomCapture/ // all flags will be stripped;
|
|
36
|
+
* ```
|
|
37
|
+
* - default value === `false` is "[\\s\\S]*?", as in whiteSpace and nonWhiteSpace 0 to more occurence;
|
|
38
|
+
* @returns {ReturnType<typeof TrySync<(templateStringArray:TemplateStringsArray,
|
|
39
|
+
* ...values:(keyof KEYS)[]
|
|
40
|
+
* )=>LitExp<KEYS>>>}
|
|
41
|
+
* - placement of `key` will determine the named capture group will be placed in the template literal;
|
|
42
|
+
* - it is recomended to not end template literal with any of the `key`s as the regex detection might failed to detects the boundary of the end of matched string of that capture group;
|
|
43
|
+
* @example
|
|
44
|
+
* import { LitExp } from 'vivth';
|
|
45
|
+
*
|
|
46
|
+
* (()=>{
|
|
47
|
+
* const [liteal, errorPrep] = LitExp.prepare({
|
|
48
|
+
* myKey: /myCustomCapture/, // is placed on (?<myKey>myCustomCapture)
|
|
49
|
+
* // use false to place "[\\s\\S]\*?" instead;
|
|
50
|
+
* ...keyCaptureLogicPair
|
|
51
|
+
* })
|
|
52
|
+
* if (errorPrep) {
|
|
53
|
+
* console.error(error);
|
|
54
|
+
* return;
|
|
55
|
+
* }
|
|
56
|
+
* const litExp_instance = liteal`templateLiteral:${'myKey'};`
|
|
57
|
+
* // recommended to end the template literal with any string but `key`;
|
|
58
|
+
* })()
|
|
59
|
+
*/
|
|
60
|
+
static prepare = (keysAndDefaultValuePair) => {
|
|
61
|
+
return TrySync(() => {
|
|
62
|
+
for (const key in keysAndDefaultValuePair) {
|
|
63
|
+
const regex = keysAndDefaultValuePair[key];
|
|
64
|
+
const capture = !regex ? `[\\s\\S]*?` : regex.source;
|
|
65
|
+
if (capture.match(/\(\<\w+\>[\s\S]*?\)/g)) {
|
|
66
|
+
throw Error('trying to add named capture');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return (templateStringArray, ...values) =>
|
|
70
|
+
new LitExp(keysAndDefaultValuePair, templateStringArray, ...values);
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* @private
|
|
75
|
+
* @param {KEYS} keys
|
|
76
|
+
* @param {TemplateStringsArray} templateStringArray
|
|
77
|
+
* @param {...(keyof KEYS)} values
|
|
78
|
+
*/
|
|
79
|
+
constructor(keys, templateStringArray, ...values) {
|
|
80
|
+
this.#templateStringArray = templateStringArray;
|
|
81
|
+
this.#keyRules = keys;
|
|
82
|
+
this.#values = values;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* @type {KEYS}
|
|
86
|
+
*/
|
|
87
|
+
#keyRules;
|
|
88
|
+
/**
|
|
89
|
+
* @type {TemplateStringsArray}
|
|
90
|
+
*/
|
|
91
|
+
#templateStringArray;
|
|
92
|
+
/**
|
|
93
|
+
* @type {(keyof KEYS)[]}
|
|
94
|
+
*/
|
|
95
|
+
#values;
|
|
96
|
+
/**
|
|
97
|
+
* @template {LitExpKeyType} KEYS
|
|
98
|
+
* @param {KEYS} instance_rules
|
|
99
|
+
* @param {(keyof KEYS)[]} intance_values
|
|
100
|
+
* @param {(value:keyof KEYS, regex:RegExp|false)=>ReturnType<typeof TrySync<string>>} valueHandler
|
|
101
|
+
* @param {TemplateStringsArray} strings
|
|
102
|
+
* @returns {ReturnType<typeof TrySync<string[]>>}
|
|
103
|
+
*/
|
|
104
|
+
static #processTemplate = (instance_rules, intance_values, valueHandler, strings) => {
|
|
105
|
+
return TrySync(() => {
|
|
106
|
+
const result = [];
|
|
107
|
+
const values = intance_values;
|
|
108
|
+
const stringsLength = strings.length;
|
|
109
|
+
for (let i = 0; i < stringsLength; i++) {
|
|
110
|
+
const string = strings[i];
|
|
111
|
+
if (i + 1 == stringsLength && string === '') {
|
|
112
|
+
result.push('(?:\\s*?|$)');
|
|
113
|
+
} else {
|
|
114
|
+
result.push(string);
|
|
115
|
+
}
|
|
116
|
+
if (i < values.length) {
|
|
117
|
+
const value = values[i];
|
|
118
|
+
const [valueHandled, errorValue] = valueHandler(value, instance_rules[value]);
|
|
119
|
+
if (errorValue || !valueHandled) {
|
|
120
|
+
throw errorValue;
|
|
121
|
+
}
|
|
122
|
+
result.push(valueHandled);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* @param {Parameters<LitExp<KEYS>["evaluate"]["execGroups"]>[1] &
|
|
130
|
+
* { absoluteLeadAndFollowing: boolean }} options
|
|
131
|
+
* @returns {ReturnType<typeof TrySync<RegExp>>}
|
|
132
|
+
*/
|
|
133
|
+
#regExp = ({ flags, whiteSpaceSensitive, absoluteLeadAndFollowing }) => {
|
|
134
|
+
return TrySync(() => {
|
|
135
|
+
let regExpStringCache;
|
|
136
|
+
if (!this.#regExpStringCache) {
|
|
137
|
+
const [regExpStringCache, error] = LitExp.#processTemplate(
|
|
138
|
+
this.#keyRules,
|
|
139
|
+
this.#values,
|
|
140
|
+
LitExp.#namedChapture,
|
|
141
|
+
this.#templateStringArray
|
|
142
|
+
);
|
|
143
|
+
if (error) {
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
this.#regExpStringCache = regExpStringCache.join('');
|
|
147
|
+
}
|
|
148
|
+
if (!whiteSpaceSensitive) {
|
|
149
|
+
regExpStringCache = this.#regExpStringCache.replace(/\s+/g, `\\s+`);
|
|
150
|
+
} else {
|
|
151
|
+
regExpStringCache = this.#regExpStringCache;
|
|
152
|
+
}
|
|
153
|
+
return new RegExp(
|
|
154
|
+
absoluteLeadAndFollowing ? `\^${regExpStringCache}\$` : regExpStringCache,
|
|
155
|
+
flags
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* @param {Parameters<LitExp<KEYS>["evaluate"]["matchedAllAndGrouped"]>[1]} options
|
|
161
|
+
* @returns {ReturnType<typeof TrySync<RegExp>>}
|
|
162
|
+
*/
|
|
163
|
+
#regexToMatchAll = ({ flags, whiteSpaceSensitive }) => {
|
|
164
|
+
return TrySync(() => {
|
|
165
|
+
let regExpToMatchStringCache;
|
|
166
|
+
if (!this.#regExpToMatchStringCache) {
|
|
167
|
+
const [regExpToMatchStringCache, error] = LitExp.#processTemplate(
|
|
168
|
+
this.#keyRules,
|
|
169
|
+
this.#values,
|
|
170
|
+
LitExp.#namedChapture,
|
|
171
|
+
this.#templateStringArray
|
|
172
|
+
);
|
|
173
|
+
if (error) {
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
this.#regExpToMatchStringCache = regExpToMatchStringCache.join('');
|
|
177
|
+
}
|
|
178
|
+
if (!whiteSpaceSensitive) {
|
|
179
|
+
regExpToMatchStringCache = this.#regExpToMatchStringCache.replace(/\s+/g, `\\s+`);
|
|
180
|
+
} else {
|
|
181
|
+
regExpToMatchStringCache = this.#regExpToMatchStringCache;
|
|
182
|
+
}
|
|
183
|
+
return new RegExp(`\(${regExpToMatchStringCache}\)`, flags);
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @description
|
|
189
|
+
* - instance methods for generating things;
|
|
190
|
+
*/
|
|
191
|
+
make = LazyFactory(() => ({
|
|
192
|
+
/**
|
|
193
|
+
* @instance make
|
|
194
|
+
* @description
|
|
195
|
+
* - to make string based on the template literal;
|
|
196
|
+
* @param {Partial<ReturnType<LitExp<KEYS>["evaluate"]["execGroups"]>>[0]["result"]} overrides
|
|
197
|
+
* @returns {string}
|
|
198
|
+
* @example
|
|
199
|
+
* import { LitExp } from 'vivth';
|
|
200
|
+
*
|
|
201
|
+
* const [literal, errorPreparing] = LitExp.prepare({
|
|
202
|
+
* myKey: false,
|
|
203
|
+
* ...keyCaptureLogicPair
|
|
204
|
+
* })
|
|
205
|
+
*
|
|
206
|
+
* // asuming no error
|
|
207
|
+
* litExp_instance = `templateLiteral:${'myKey'};`;
|
|
208
|
+
* const [result, error] = litExp_instance.make.string({
|
|
209
|
+
* myKey: 'actualvalue',
|
|
210
|
+
* });
|
|
211
|
+
*
|
|
212
|
+
* console.log(result); // "templateLiteral:actualvalue;"
|
|
213
|
+
*/
|
|
214
|
+
string: (overrides) => {
|
|
215
|
+
return TrySync(() => {
|
|
216
|
+
const [res, error] = LitExp.#processTemplate(
|
|
217
|
+
this.#keyRules,
|
|
218
|
+
this.#values,
|
|
219
|
+
(key) => {
|
|
220
|
+
return TrySync(() => {
|
|
221
|
+
return overrides[key.toString()] ?? '';
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
this.#templateStringArray
|
|
225
|
+
);
|
|
226
|
+
if (error || !res) {
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
return res.join('');
|
|
230
|
+
})[0];
|
|
231
|
+
},
|
|
232
|
+
}));
|
|
233
|
+
/**
|
|
234
|
+
* @type {string}
|
|
235
|
+
*/
|
|
236
|
+
#regExpStringCache;
|
|
237
|
+
/**
|
|
238
|
+
* @template {LitExpKeyType} KEYS
|
|
239
|
+
* @param {RegExp|false} regex
|
|
240
|
+
* @param {keyof KEYS} value
|
|
241
|
+
* @returns {ReturnType<typeof TrySync<string>>}
|
|
242
|
+
*/
|
|
243
|
+
static #namedChapture = (value, regex) => {
|
|
244
|
+
return TrySync(() => {
|
|
245
|
+
const capture = !regex ? `[\\s\\S]*?` : regex.source;
|
|
246
|
+
return `(?<${value.toString()}>${capture})`;
|
|
247
|
+
});
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* @type {string}
|
|
251
|
+
*/
|
|
252
|
+
#regExpToMatchStringCache;
|
|
253
|
+
/**
|
|
254
|
+
* @description
|
|
255
|
+
* - methods collections to evaluate string with `Literal Expression`;
|
|
256
|
+
*/
|
|
257
|
+
evaluate = LazyFactory(() => ({
|
|
258
|
+
/**
|
|
259
|
+
* @instance evaluate
|
|
260
|
+
* @description
|
|
261
|
+
* - to exec and grouped based on `key`;
|
|
262
|
+
* @param {string} string
|
|
263
|
+
* @param {Object} options
|
|
264
|
+
* @param {ConstructorParameters<typeof RegExp>[1]} options.flags
|
|
265
|
+
* @param {boolean} options.whiteSpaceSensitive
|
|
266
|
+
* - true: leave any whitespace as is to be used as regex detection;
|
|
267
|
+
* - false: convert all whitespace to `\s+`;
|
|
268
|
+
* @param {boolean} options.absoluteLeadAndFollowing
|
|
269
|
+
* - false: standard capture;
|
|
270
|
+
* - true: add `^` and `$` to capture definition:
|
|
271
|
+
* >- meaning string will have to match starting and end of line from capture definition;
|
|
272
|
+
* @returns {ReturnType<typeof TrySync<{
|
|
273
|
+
* result:{ whole:string, named: Record<keyof KEYS, string>},
|
|
274
|
+
* regexp:RegExp}>>
|
|
275
|
+
* }
|
|
276
|
+
* @example
|
|
277
|
+
* import { LitExp } from 'vivth';
|
|
278
|
+
*
|
|
279
|
+
* const [literal, errorPreparing] = LitExp.prepare({
|
|
280
|
+
* myKey: false,
|
|
281
|
+
* ...keyCaptureLogicPair
|
|
282
|
+
* })
|
|
283
|
+
*
|
|
284
|
+
* // asuming no eror
|
|
285
|
+
* const litExp_instance = literal`templateLiteral:${'myKey'};`
|
|
286
|
+
*
|
|
287
|
+
* const [{
|
|
288
|
+
* result:{ // asuming there's no error
|
|
289
|
+
* named: { myKey },
|
|
290
|
+
* whole,
|
|
291
|
+
* },
|
|
292
|
+
* regex, // for reference
|
|
293
|
+
* }, error] = litExp_instance.evaluate.execGroups(
|
|
294
|
+
* `templateLiteral:Something;`,
|
|
295
|
+
* { ...options }
|
|
296
|
+
* )
|
|
297
|
+
*
|
|
298
|
+
* console.log(whole); // "templateLiteral:Something;"
|
|
299
|
+
* console.log(myKey); // "Something"
|
|
300
|
+
*/
|
|
301
|
+
execGroups: (string, options) => {
|
|
302
|
+
// @ts-expect-error
|
|
303
|
+
return TrySync(() => {
|
|
304
|
+
const [regexp, error] = this.#regExp(options);
|
|
305
|
+
if (error || !regexp) {
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
const execResult = regexp.exec(string);
|
|
309
|
+
const whole = execResult[1];
|
|
310
|
+
const named = execResult?.groups;
|
|
311
|
+
const result = { named, whole };
|
|
312
|
+
if (!named) {
|
|
313
|
+
throw new Error(
|
|
314
|
+
JSON.stringify({
|
|
315
|
+
regexpSource: regexp.source,
|
|
316
|
+
message: 'no match is found',
|
|
317
|
+
sugestion: 'make sure all `keys` values will capture any scenario',
|
|
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) {
|
|
389
|
+
throw new Error(
|
|
390
|
+
JSON.stringify({
|
|
391
|
+
regexpSource: regexp.source,
|
|
392
|
+
message: 'no match is found',
|
|
393
|
+
sugestion: 'make sure all `keys` values will capture any scenario',
|
|
394
|
+
})
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
whole.push(match[1]);
|
|
398
|
+
// @ts-expect-error
|
|
399
|
+
named.push(match.groups);
|
|
400
|
+
}
|
|
401
|
+
return { result, regexp };
|
|
402
|
+
});
|
|
403
|
+
},
|
|
404
|
+
}));
|
|
405
|
+
}
|
package/src/class/Paths.mjs
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import { relative } from 'node:path';
|
|
4
|
+
|
|
3
5
|
import { Console } from './Console.mjs';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* @description
|
|
7
9
|
* - class helpers to define pathReference;
|
|
8
10
|
* - is a singleton;
|
|
11
|
+
* - most of functionality need to access `Paths.root`, if you get warning, you can instantiate `Paths` before running anything;
|
|
9
12
|
*/
|
|
10
13
|
export class Paths {
|
|
11
14
|
/**
|
|
@@ -28,6 +31,10 @@ export class Paths {
|
|
|
28
31
|
* ```js
|
|
29
32
|
* Deno.env.get("INIT_CWD") ?? Deno.cwd()
|
|
30
33
|
* ```
|
|
34
|
+
* - pkg:
|
|
35
|
+
* ```js
|
|
36
|
+
* __dirname
|
|
37
|
+
* ```
|
|
31
38
|
* - other: you need to check your JSRuntime for the rootPath reference;
|
|
32
39
|
* @example
|
|
33
40
|
* import { Paths } from 'vivth';
|
|
@@ -73,7 +80,26 @@ export class Paths {
|
|
|
73
80
|
* @example
|
|
74
81
|
* import { Paths } from 'vivth';
|
|
75
82
|
*
|
|
76
|
-
* Paths.normalize('file:\\D:\\myFile.mjs'); //
|
|
83
|
+
* Paths.normalize('file:\\D:\\myFile.mjs'); // "file://D://myFile.mjs"
|
|
77
84
|
*/
|
|
78
85
|
static normalize = (path_) => path_.replace(/\\/g, '/');
|
|
86
|
+
/**
|
|
87
|
+
* @description
|
|
88
|
+
* - normalize path separator to forward slash `/`;
|
|
89
|
+
* - then starts with forward slash `/`;
|
|
90
|
+
* @param {string} path_
|
|
91
|
+
* @returns {`/${string}`}
|
|
92
|
+
* @example
|
|
93
|
+
* import { Paths } from 'vivth';
|
|
94
|
+
*
|
|
95
|
+
* Paths.normalizesForRoot('path\\myFile.mjs'); // "/path/myFile.mjs"
|
|
96
|
+
*/
|
|
97
|
+
static normalizesForRoot = (path_) => {
|
|
98
|
+
let normalized = Paths.normalize(path_);
|
|
99
|
+
if (!normalized.startsWith('/')) {
|
|
100
|
+
normalized = `/${normalized}`;
|
|
101
|
+
}
|
|
102
|
+
// @ts-expect-error
|
|
103
|
+
return normalized;
|
|
104
|
+
};
|
|
79
105
|
}
|