vivth 0.11.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vivth/dist/init.mjs +24 -0
- package/README.md +2157 -69
- package/README.src.md +35 -0
- package/bun.lock +57 -3
- package/dev/index.mjs +24 -25
- package/index.mjs +51 -29
- package/package.json +11 -7
- package/src/bundler/CompileMJS.mjs +110 -0
- package/src/bundler/EsBundler.mjs +79 -0
- package/src/class/Console.mjs +62 -0
- package/src/class/Derived.mjs +37 -21
- package/src/class/Effect.mjs +106 -0
- package/src/class/EnvSignal.mjs +88 -0
- package/src/class/EventSignal.mjs +200 -0
- package/src/class/ListDerived.mjs +39 -0
- package/src/class/ListSignal.mjs +256 -0
- package/src/class/Paths.mjs +70 -0
- package/src/class/QChannel.mjs +184 -0
- package/src/class/SafeExit.mjs +131 -0
- package/src/class/Setup.mjs +73 -0
- package/src/class/Signal.mjs +152 -54
- package/src/class/WorkerMainThread.mjs +328 -0
- package/src/class/WorkerResult.mjs +30 -0
- package/src/class/WorkerThread.mjs +151 -0
- package/src/common/Base64URL.mjs +26 -0
- package/src/common/EventNameSpace.mjs +8 -0
- package/src/common/eventObjects.mjs +5 -0
- package/src/common/lazie.mjs +3 -0
- package/src/doc/JSautoDOC.mjs +386 -0
- package/src/doc/parsedFile.mjs +537 -0
- package/src/function/CreateImmutable.mjs +64 -0
- package/src/function/EventCheck.mjs +27 -0
- package/src/function/EventObject.mjs +21 -0
- package/src/function/IsAsync.mjs +23 -0
- package/src/function/LazyFactory.mjs +71 -0
- package/src/function/Timeout.mjs +23 -0
- package/src/function/Try.mjs +64 -0
- package/src/function/TryAsync.mjs +15 -4
- package/src/function/TrySync.mjs +9 -4
- package/src/function/TsToMjs.mjs +67 -0
- package/src/function/WriteFileSafe.mjs +37 -0
- package/src/types/{AnyButUndefined.type.mjs → AnyButUndefined.mjs} +1 -0
- package/src/types/ExtnameType.mjs +6 -0
- package/src/types/IsListSignal.mjs +6 -0
- package/src/types/ListArg.mjs +6 -0
- package/src/types/MutationType.mjs +8 -0
- package/src/types/QCBFIFOReturn.mjs +6 -0
- package/src/types/QCBReturn.mjs +6 -0
- package/tsconfig.json +3 -3
- package/types/dev/index.d.mts +1 -0
- package/types/index.d.mts +34 -8
- package/types/src/bundler/A.d.mts +1 -0
- package/types/src/bundler/CompileMJS.d.mts +8 -0
- package/types/src/bundler/EsBundler.d.mts +7 -0
- package/types/src/class/Console.d.mts +40 -0
- package/types/src/class/Derived.d.mts +21 -7
- package/types/src/class/Effect.d.mts +77 -0
- package/types/src/class/EnvSignal.d.mts +47 -0
- package/types/src/class/EventSignal.d.mts +145 -0
- package/types/src/class/ListDerived.d.mts +35 -0
- package/types/src/class/ListSignal.d.mts +150 -0
- package/types/src/class/Paths.d.mts +50 -0
- package/types/src/class/QChannel.d.mts +115 -0
- package/types/src/class/SafeExit.d.mts +76 -0
- package/types/src/class/Setup.d.mts +76 -0
- package/types/src/class/Signal.d.mts +105 -26
- package/types/src/class/WorkerMainThread.d.mts +149 -0
- package/types/src/class/WorkerResult.d.mts +25 -0
- package/types/src/class/WorkerThread.d.mts +70 -0
- package/types/src/common/Base64URL.d.mts +1 -0
- package/types/src/common/EventNameSpace.d.mts +6 -0
- package/types/src/common/eventObjects.d.mts +3 -0
- package/types/src/common/lazie.d.mts +1 -0
- package/types/src/doc/JSautoDOC.d.mts +76 -0
- package/types/src/doc/parsedFile.d.mts +154 -0
- package/types/src/function/CreateImmutable.d.mts +3 -0
- package/types/src/function/EventCheck.d.mts +2 -0
- package/types/src/function/EventObject.d.mts +4 -0
- package/types/src/function/IsAsync.d.mts +1 -0
- package/types/src/function/LazyFactory.d.mts +4 -0
- package/types/src/function/Timeout.d.mts +1 -0
- package/types/src/function/Try.d.mts +1 -0
- package/types/src/function/TsToMjs.d.mts +4 -0
- package/types/src/function/WriteFileSafe.d.mts +2 -0
- package/types/src/types/{AnyButUndefined.type.d.mts → AnyButUndefined.d.mts} +3 -0
- package/types/src/types/ExtnameType.d.mts +4 -0
- package/types/src/types/IsListSignal.d.mts +4 -0
- package/types/src/types/ListArg.d.mts +4 -0
- package/types/src/types/MutationType.d.mts +5 -0
- package/types/src/types/QCBFIFOReturn.d.mts +4 -0
- package/types/src/types/QCBReturn.d.mts +7 -0
- package/src/class/$.mjs +0 -68
- package/src/class/PingFIFO.mjs +0 -78
- package/src/class/PingUnique.mjs +0 -84
- package/src/class/Q.mjs +0 -98
- package/src/class/QFIFO.mjs +0 -66
- package/src/class/QUnique.mjs +0 -75
- package/src/common.mjs +0 -16
- package/src/function/NewQBlock.mjs +0 -39
- package/types/src/class/$.d.mts +0 -38
- package/types/src/class/PingFIFO.d.mts +0 -57
- package/types/src/class/PingUnique.d.mts +0 -48
- package/types/src/class/Q.d.mts +0 -63
- package/types/src/class/QFIFO.d.mts +0 -47
- package/types/src/class/QUnique.d.mts +0 -46
- package/types/src/common.d.mts +0 -2
- package/types/src/function/NewQBlock.d.mts +0 -1
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { extname, join } from 'node:path';
|
|
4
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
5
|
+
|
|
6
|
+
import chokidar from 'chokidar';
|
|
7
|
+
import { EventSignal } from '../class/EventSignal.mjs';
|
|
8
|
+
import { QChannel } from '../class/QChannel.mjs';
|
|
9
|
+
import { parsedFile } from './parsedFile.mjs';
|
|
10
|
+
import { SafeExit } from '../class/SafeExit.mjs';
|
|
11
|
+
import { Effect } from '../class/Effect.mjs';
|
|
12
|
+
import { Paths } from '../class/Paths.mjs';
|
|
13
|
+
import { Signal } from '../class/Signal.mjs';
|
|
14
|
+
import { LazyFactory } from '../function/LazyFactory.mjs';
|
|
15
|
+
import { TryAsync } from '../function/TryAsync.mjs';
|
|
16
|
+
import { Timeout } from '../function/Timeout.mjs';
|
|
17
|
+
import { Console } from '../class/Console.mjs';
|
|
18
|
+
import { TsToMjs } from '../function/TsToMjs.mjs';
|
|
19
|
+
import { WriteFileSafe } from '../function/WriteFileSafe.mjs';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {import('fs').Stats} Stats
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @type {BufferEncoding}
|
|
26
|
+
*/
|
|
27
|
+
const encoding = 'utf-8';
|
|
28
|
+
const readmesrcname = 'README.src.md';
|
|
29
|
+
/**
|
|
30
|
+
* @type {Set<import('../types/ExtnameType.mjs').ExtnameType>}
|
|
31
|
+
*/
|
|
32
|
+
const acceptableExt = new Set(['.mjs', '.mts', '.ts']);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @description
|
|
36
|
+
* - class for auto documenting mjs package/project, using jsdoc;
|
|
37
|
+
* - this autodocumenter uses [chokidar](https://npmjs.com/package/chokidar) under the hood;
|
|
38
|
+
* - this class also is used to generate this `README.md`;
|
|
39
|
+
* - behaviours:
|
|
40
|
+
* >1) export all named exported 'const'|'function'|'async function'|'class', alphanumeric name, started with Capital letter, same name with fileName on `options.pahts.file`;
|
|
41
|
+
* >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`;
|
|
42
|
+
* >3) create `README.md` based on, `options.paths.dir` and `README.src.md`;
|
|
43
|
+
* >4) extract `"at"description` jsdoc:
|
|
44
|
+
* >>- on static/prop that have depths, all of children should have `"at"static`/`"at"instance` `nameOfImmediateParent`, same block but before `"at"description` comment line;
|
|
45
|
+
* >>- `"at"description` are treated as plain `markdown`;
|
|
46
|
+
* >>- first `"at"${string}` after `"at"description` until `"at"example` will be treated as `javascript` comment block on the `markdown`;
|
|
47
|
+
* >>- `"at"example` are treated as `javascript` block on the `markdown` file, and should be placed last on the same comment block;
|
|
48
|
+
* >>- you can always look at `vivth/src` files to check how the source, and the `README.md` and `index.mjs` is documentation/generation results;
|
|
49
|
+
*/
|
|
50
|
+
export class JSautoDOC {
|
|
51
|
+
/**
|
|
52
|
+
* @type {JSautoDOC}
|
|
53
|
+
*/
|
|
54
|
+
static #instance = undefined;
|
|
55
|
+
/**
|
|
56
|
+
* @description
|
|
57
|
+
* @param {Object} [options]
|
|
58
|
+
* @param {Object} [options.paths]
|
|
59
|
+
* @param {string} [options.paths.file]
|
|
60
|
+
* - entry point;
|
|
61
|
+
* @param {string} [options.paths.readMe]
|
|
62
|
+
* - readme target;
|
|
63
|
+
* @param {string} [options.paths.dir]
|
|
64
|
+
* - source directory;
|
|
65
|
+
* @param {string} [options.copyright]
|
|
66
|
+
* @param {string} [options.tableOfContentTitle]
|
|
67
|
+
* @param {import('chokidar').ChokidarOptions} [options.option]
|
|
68
|
+
* - ChokidarOptions;
|
|
69
|
+
* @example
|
|
70
|
+
* import { Console } from '../src/class/Console.mjs';
|
|
71
|
+
* import { Setup } from '../src/class/Setup.mjs';
|
|
72
|
+
* import { JSautoDOC } from '../src/doc/JSautoDOC.mjs';
|
|
73
|
+
*
|
|
74
|
+
* const { paths, safeExit } = Setup;
|
|
75
|
+
*
|
|
76
|
+
* new paths({
|
|
77
|
+
* root: process?.env?.INIT_CWD ?? process?.cwd(),
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* new safeExit({
|
|
81
|
+
* exitEventNames: ['SIGINT', 'SIGTERM', 'exit'],
|
|
82
|
+
* exitCallbackListeners: (eventName) => {
|
|
83
|
+
* process.once(eventName, function () {
|
|
84
|
+
* safeExit.instance.exiting.correction(true);
|
|
85
|
+
* Console.log(`safe exit via "${eventName}"`);
|
|
86
|
+
* });
|
|
87
|
+
* },
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* new JSautoDOC({
|
|
91
|
+
* paths: { dir: 'src', file: 'index.mjs', readMe: 'README.md' },
|
|
92
|
+
* copyright: 'this library is made and distributed under MIT license;',
|
|
93
|
+
* tableOfContentTitle: 'list of exported API and typehelpers',
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
97
|
+
constructor({
|
|
98
|
+
paths = { dir: './src', file: './index.mjs', readMe: './README.md' },
|
|
99
|
+
tableOfContentTitle = 'exported-api-and-type-list',
|
|
100
|
+
copyright = '',
|
|
101
|
+
option = {},
|
|
102
|
+
} = {}) {
|
|
103
|
+
if (JSautoDOC.#instance instanceof JSautoDOC) {
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
JSautoDOC.#instance = this;
|
|
107
|
+
this.#tableOfContentTitle = tableOfContentTitle;
|
|
108
|
+
this.#paths = paths;
|
|
109
|
+
this.#copyright = copyright;
|
|
110
|
+
const rootPath = Paths.root;
|
|
111
|
+
const watchpath = join(rootPath, this.#paths.dir);
|
|
112
|
+
const watcher = chokidar.watch(watchpath, option);
|
|
113
|
+
const watcherReadme = chokidar.watch(join(rootPath, readmesrcname), option);
|
|
114
|
+
/**
|
|
115
|
+
* @type {(eventName: 'add'|'change'|'unlink', path: string, stats?: import('fs').Stats) => void}
|
|
116
|
+
*/
|
|
117
|
+
const listener = (eventName, path, stats) => {
|
|
118
|
+
const ext = extname(path);
|
|
119
|
+
if (
|
|
120
|
+
!acceptableExt.has(
|
|
121
|
+
// @ts-expect-error
|
|
122
|
+
ext
|
|
123
|
+
)
|
|
124
|
+
) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (ext !== '.mjs') {
|
|
128
|
+
TsToMjs(path, {
|
|
129
|
+
encoding,
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
switch (eventName) {
|
|
134
|
+
case 'add':
|
|
135
|
+
case 'change':
|
|
136
|
+
this.#addHandler(eventName, path, stats);
|
|
137
|
+
break;
|
|
138
|
+
case 'unlink':
|
|
139
|
+
this.#removeHandler(eventName, path, stats);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
watcher.on('all', listener);
|
|
144
|
+
watcherReadme.on('all', this.#readMeListener);
|
|
145
|
+
SafeExit.instance.addCallback(async () => {
|
|
146
|
+
watcher.close();
|
|
147
|
+
watcherReadme.close();
|
|
148
|
+
watcher.removeAllListeners();
|
|
149
|
+
watcherReadme.removeAllListeners();
|
|
150
|
+
watcher.removeListener('all', listener);
|
|
151
|
+
watcherReadme.removeAllListeners(this.#readMeListener);
|
|
152
|
+
watcherReadme.removeListener('all', this.#readMeListener);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* @type {string}
|
|
157
|
+
*/
|
|
158
|
+
#copyright = undefined;
|
|
159
|
+
/**
|
|
160
|
+
* @type {{
|
|
161
|
+
* file?: string;
|
|
162
|
+
* readMe?: string;
|
|
163
|
+
* dir?: string;
|
|
164
|
+
* }}
|
|
165
|
+
*/
|
|
166
|
+
#paths;
|
|
167
|
+
/**
|
|
168
|
+
* @type {string}
|
|
169
|
+
*/
|
|
170
|
+
#tableOfContentTitle;
|
|
171
|
+
/**
|
|
172
|
+
* @param {string} _eventName
|
|
173
|
+
* @param {string} path_
|
|
174
|
+
* @param {Stats} stats
|
|
175
|
+
* @returns {Promise<void>}
|
|
176
|
+
*/
|
|
177
|
+
#readMeListener = async (_eventName, path_, stats) => {
|
|
178
|
+
if (!stats.isFile()) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const content = await readFile(path_, { encoding });
|
|
182
|
+
this.#readMESRCContent.value = content;
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* @type {Signal<Set<string>>}
|
|
186
|
+
*/
|
|
187
|
+
#filePaths = LazyFactory(() => new Signal(new Set()));
|
|
188
|
+
/**
|
|
189
|
+
* @type {Signal<string>}
|
|
190
|
+
*/
|
|
191
|
+
#readMESRCContent = LazyFactory(() => new Signal(undefined));
|
|
192
|
+
/**
|
|
193
|
+
* @type {QChannel<JSautoDOC>}
|
|
194
|
+
*/
|
|
195
|
+
#modQ = new QChannel();
|
|
196
|
+
#generatedREADME_md = new Effect(async ({ subscribe }) => {
|
|
197
|
+
this.#modQ.callback(this, async ({ isLastOnQ }) => {
|
|
198
|
+
if (!isLastOnQ) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
await Timeout(1000);
|
|
202
|
+
const contentSRC = subscribe(this.#readMESRCContent).value;
|
|
203
|
+
const filepaths = subscribe(this.#filePaths).value;
|
|
204
|
+
if (!contentSRC || !filepaths) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const { readme, mjsFile } = await this.#generateFromSRC(contentSRC, filepaths);
|
|
208
|
+
const readmePath = join(Paths.root, this.#paths.readMe);
|
|
209
|
+
const mjsFilePath = join(Paths.root, this.#paths.file);
|
|
210
|
+
const [[, errorWriteReadme], [, errorWriteMjsFile]] = await Promise.all([
|
|
211
|
+
WriteFileSafe(readmePath, readme, { encoding }),
|
|
212
|
+
WriteFileSafe(join(Paths.root, this.#paths.file), mjsFile, { encoding }),
|
|
213
|
+
]);
|
|
214
|
+
if (!errorWriteMjsFile) {
|
|
215
|
+
Console.info({ message: `successfully generate: '${mjsFilePath}'` });
|
|
216
|
+
} else {
|
|
217
|
+
Console.error({ message: `unable to generate: '${mjsFilePath}';`, errorWriteMjsFile });
|
|
218
|
+
}
|
|
219
|
+
if (!errorWriteReadme) {
|
|
220
|
+
Console.info({ message: `successfully generate: '${readmePath}'` });
|
|
221
|
+
} else {
|
|
222
|
+
Console.error({ message: `unable to generate: '${readmePath}';`, errorWriteReadme });
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
/**
|
|
227
|
+
* @param {string} string
|
|
228
|
+
* @returns {string}
|
|
229
|
+
*/
|
|
230
|
+
#generateJSDOCFromstring = (string) => {
|
|
231
|
+
return `\n/**\n * automatically generated by \`vivth.MJSautoDOC\`\n * @copyright\n${string.replace(
|
|
232
|
+
/^/gm,
|
|
233
|
+
' * '
|
|
234
|
+
)}\n */\n`;
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* @typedef { Object } generatedFromSRC
|
|
238
|
+
* @property { string } readme
|
|
239
|
+
* @property { string } mjsFile
|
|
240
|
+
*/
|
|
241
|
+
/**
|
|
242
|
+
* @param {string} contentSRC
|
|
243
|
+
* @param {Set<string>} filepaths
|
|
244
|
+
* @returns {Promise<generatedFromSRC>}
|
|
245
|
+
*/
|
|
246
|
+
#generateFromSRC = async (contentSRC, filepaths) => {
|
|
247
|
+
const tableID = this.#tableOfContentTitle.replace(/\s+/g, '-').toLowerCase();
|
|
248
|
+
const tableOfContent = [];
|
|
249
|
+
const apiDocuments = [];
|
|
250
|
+
const mjsMain = ['// @ts-check', this.#generateJSDOCFromstring(this.#copyright)];
|
|
251
|
+
const mjsTypes = [];
|
|
252
|
+
for await (const path_ of filepaths) {
|
|
253
|
+
const {
|
|
254
|
+
documented,
|
|
255
|
+
hasValidExportObject,
|
|
256
|
+
path: { relative: relativePath },
|
|
257
|
+
baseName: { noExt },
|
|
258
|
+
} = (await this.#parsedFilesRef.get(path_)).value;
|
|
259
|
+
if (hasValidExportObject) {
|
|
260
|
+
mjsMain.push(
|
|
261
|
+
`export { ${noExt} } from '${
|
|
262
|
+
relativePath.startsWith('.') ? relativePath : `./${relativePath}`
|
|
263
|
+
}';`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
const currentDescription = [];
|
|
267
|
+
const { readme, typedef } = documented;
|
|
268
|
+
const [typedefString, error] = await TryAsync(async () => {
|
|
269
|
+
if (hasValidExportObject) {
|
|
270
|
+
throw new Error('');
|
|
271
|
+
}
|
|
272
|
+
const result = await typedef();
|
|
273
|
+
return result;
|
|
274
|
+
});
|
|
275
|
+
if (!error && typedefString) {
|
|
276
|
+
mjsTypes.push(typedefString.module);
|
|
277
|
+
const nameVarID = noExt.toLowerCase();
|
|
278
|
+
tableOfContent.push(`[${noExt}](#${nameVarID})`);
|
|
279
|
+
apiDocuments.push(
|
|
280
|
+
`<h2 id="${nameVarID}">${noExt}</h2>\n\n- jsdoc types:\n\n\`\`\`js\n${
|
|
281
|
+
typedefString.readme
|
|
282
|
+
}\n\`\`\`\n*) <sub>[go to ${this.#tableOfContentTitle}](#${tableID})</sub>`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
readme.forEach((ref) => {
|
|
286
|
+
const {
|
|
287
|
+
// fullDescription,
|
|
288
|
+
// instanceOrStatic,
|
|
289
|
+
// namedVar,
|
|
290
|
+
// typeOfVar,
|
|
291
|
+
parsedFullDescription,
|
|
292
|
+
reference,
|
|
293
|
+
} = ref;
|
|
294
|
+
const { description, jsPreview } = parsedFullDescription;
|
|
295
|
+
currentDescription.push(`\n#### reference:${reference}\n${description}\n${jsPreview}`);
|
|
296
|
+
});
|
|
297
|
+
if (hasValidExportObject) {
|
|
298
|
+
const nameVarID = noExt.toLowerCase();
|
|
299
|
+
tableOfContent.push(`[${noExt}](#${noExt.toLowerCase()})`);
|
|
300
|
+
apiDocuments.push(
|
|
301
|
+
`<h2 id="${nameVarID}">${noExt}</h2>\n\n-current-description-to-replace-\n\n*) <sub>[go to ${
|
|
302
|
+
this.#tableOfContentTitle
|
|
303
|
+
}](#${tableID})</sub>`.replace(
|
|
304
|
+
'-current-description-to-replace-',
|
|
305
|
+
currentDescription.join('\n')
|
|
306
|
+
)
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const tableOfContentString = `<h2 id="${this.#tableOfContentTitle
|
|
311
|
+
.replace(/\s+/g, '-')
|
|
312
|
+
.toLowerCase()}">${
|
|
313
|
+
this.#tableOfContentTitle
|
|
314
|
+
}</h2>\n\n - -table-of-content-to-replace-\n\n-api-document-to-replace-`
|
|
315
|
+
.replace('-table-of-content-to-replace-', tableOfContent.join('\n - '))
|
|
316
|
+
.replace('-api-document-to-replace-', apiDocuments.join('\n\n'));
|
|
317
|
+
return {
|
|
318
|
+
mjsFile: [...mjsMain, ...mjsTypes].join('\n'),
|
|
319
|
+
readme: `${contentSRC}\n${tableOfContentString}`,
|
|
320
|
+
};
|
|
321
|
+
};
|
|
322
|
+
#parsedFilesRef = LazyFactory(() => {
|
|
323
|
+
const prefix = 'parsedFiles:';
|
|
324
|
+
return {
|
|
325
|
+
/**
|
|
326
|
+
* @param {string} path__
|
|
327
|
+
* @returns {Promise<Signal<parsedFile>>}
|
|
328
|
+
*/
|
|
329
|
+
get: async (path__) => {
|
|
330
|
+
const dispatch = (await EventSignal.get(`${prefix}${path__}`, false)).dispatch;
|
|
331
|
+
// @ts-expect-error
|
|
332
|
+
return dispatch;
|
|
333
|
+
},
|
|
334
|
+
/**
|
|
335
|
+
* @param {string} path__
|
|
336
|
+
* @returns {Promise<void>}
|
|
337
|
+
*/
|
|
338
|
+
unRef: async (path__) => {
|
|
339
|
+
const parsedFile = await this.#parsedFilesRef.get(`${prefix}${path__}`);
|
|
340
|
+
parsedFile.remove.ref();
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
/**
|
|
345
|
+
* @type {(eventName: 'add'|'change', path: string, stats?: import('fs').Stats) => void}
|
|
346
|
+
*/
|
|
347
|
+
#addHandler = (eventName, path__, _stats) => {
|
|
348
|
+
TryAsync(async () => {
|
|
349
|
+
const dispatch = await this.#parsedFilesRef.get(path__);
|
|
350
|
+
if (!(await stat(path__)).isFile()) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
dispatch.value = new parsedFile(path__, encoding);
|
|
354
|
+
dispatch.subscribers.notify();
|
|
355
|
+
this.#filePaths.subscribers.notify(async ({ signalInstance }) => {
|
|
356
|
+
Console.info({ [eventName]: path__ });
|
|
357
|
+
signalInstance.value.add(path__);
|
|
358
|
+
});
|
|
359
|
+
}).then(([_, error]) => {
|
|
360
|
+
if (!error) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
Console.error(error);
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* @type {(eventName: 'unlink', path: string, stats?: import('fs').Stats) => void}
|
|
368
|
+
*/
|
|
369
|
+
#removeHandler = (eventName, path__, _stats) => {
|
|
370
|
+
TryAsync(async () => {
|
|
371
|
+
if (!(await stat(path__)).isFile()) {
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
return false;
|
|
375
|
+
}).then(([res, error]) => {
|
|
376
|
+
if (res && !error) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
this.#filePaths.subscribers.notify(async ({ signalInstance }) => {
|
|
380
|
+
Console.warn({ [eventName]: path__ });
|
|
381
|
+
signalInstance.value.delete(path__);
|
|
382
|
+
this.#parsedFilesRef.unRef(path__);
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
}
|