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,537 @@
1
+ // @ts-check
2
+
3
+ import { readFile, stat } from 'node:fs/promises';
4
+ import { Stats } from 'node:fs';
5
+ import { normalize, basename, join, relative, extname, dirname } from 'node:path';
6
+
7
+ import { Paths } from '../class/Paths.mjs';
8
+ import { LazyFactory } from '../function/LazyFactory.mjs';
9
+ import { TrySync } from '../function/TrySync.mjs';
10
+ import { Console } from '../class/Console.mjs';
11
+ import { TryAsync } from '../function/TryAsync.mjs';
12
+
13
+ export class parsedFile {
14
+ /**
15
+ * @typedef {{
16
+ * instanceOrStatic:{parent:string, type:string},
17
+ * fullDescription:string,
18
+ * parsedFullDescription:{description:string, jsPreview:string},
19
+ * isExport:boolean,
20
+ * typeOfVar:string,
21
+ * namedVar:string,
22
+ * reference:string,
23
+ * }} refType
24
+ */
25
+ /**
26
+ * @param {string} path__
27
+ * @param {BufferEncoding} [encoding]
28
+ */
29
+ constructor(path__, encoding = 'utf-8') {
30
+ const root = Paths.root.replace(/\\/g, '/');
31
+ if (Paths.normalize(path__).startsWith(root)) {
32
+ this.#fullPath = path__;
33
+ } else {
34
+ this.#fullPath = join(root, path__);
35
+ }
36
+ this.#relativePath = Paths.normalize(relative(root, this.#fullPath));
37
+ this.#encoding = encoding;
38
+ this.content.parsed().then(({ details, error, exportName }) => {
39
+ if (error) {
40
+ return;
41
+ }
42
+ for (let i = 0; i < details.length; i++) {
43
+ const [
44
+ _,
45
+ __,
46
+ instanceOrStaticDef,
47
+ fullDescription,
48
+ isExport,
49
+ typeOfVar,
50
+ getterOrSetter,
51
+ namedVar,
52
+ ] = details[i];
53
+ const interpreted = this.#interpreteArrayDesc(
54
+ exportName,
55
+ instanceOrStaticDef,
56
+ fullDescription,
57
+ isExport,
58
+ typeOfVar,
59
+ getterOrSetter,
60
+ namedVar
61
+ );
62
+ this.documented.readme.add(interpreted);
63
+ }
64
+ });
65
+ }
66
+ documented = LazyFactory(() => {
67
+ return {
68
+ typedef: async () => {
69
+ const relativePath = this.path.relative;
70
+ if (!relativePath) {
71
+ return;
72
+ }
73
+ const typedef = this.#parseTypedef(
74
+ this.baseName.noExt.split('.')[0],
75
+ relativePath,
76
+ await this.content.string()
77
+ );
78
+ return typedef;
79
+ },
80
+ /**
81
+ * @type {Set<refType>}
82
+ */
83
+ readme: new Set(),
84
+ };
85
+ });
86
+ /**
87
+ * @param {string} exportName
88
+ * @returns {boolean}
89
+ */
90
+ static #isExportNameValid = (exportName) => {
91
+ const firstLetter = exportName.split('')[0];
92
+ return firstLetter.toUpperCase() === firstLetter;
93
+ };
94
+ /**
95
+ * @type {undefined|{module:string, readme:string}}
96
+ */
97
+ parsedType = undefined;
98
+ /**
99
+ * @param {string} exportName
100
+ * @param {string} relativePath
101
+ * @param {string} content
102
+ * @returns {parsedFile["parsedType"]}
103
+ */
104
+ #parseTypedef = (exportName, relativePath, content) => {
105
+ if (!parsedFile.#isExportNameValid(exportName)) {
106
+ return undefined;
107
+ }
108
+ if (!this.parsedType) {
109
+ const baseNameNoExt = this.baseName.noExt;
110
+ const relativeDir = this.dirName.relative;
111
+ const contents = content.matchAll(/(\/\*\*[\s\S]*?\*\/)/gm).toArray();
112
+ const readme = contents
113
+ .map(([_, val]) => {
114
+ if (!/import\(['"][\s\S]*['"]\)/g.test(val)) {
115
+ return val;
116
+ }
117
+ const [__, importDec] = /import\(['"]([\s\S]*)['"]\)/g.exec(val);
118
+ const correctedPath = Paths.normalize(normalize(join(relativeDir, importDec)));
119
+ const rep = val.replace(
120
+ importDec,
121
+ correctedPath.startsWith('.') ? correctedPath : `./${correctedPath}`
122
+ );
123
+ return rep;
124
+ })
125
+ .join('\n');
126
+ const [[res]] = contents.filter(([_, captured]) => {
127
+ if (
128
+ !new RegExp(`(?:@typedef|@callback)[\\s\\S]*?${baseNameNoExt}\\s?[\\s\\S]*?`, '').test(
129
+ captured
130
+ )
131
+ ) {
132
+ return false;
133
+ }
134
+ return true;
135
+ });
136
+ if (!res.length) {
137
+ return undefined;
138
+ }
139
+ const templates = res
140
+ .matchAll(/@template\s?{([\s\S]*?)}\s?(\w)*/gm)
141
+ .map(([_, type, name]) => {
142
+ return { name, comment: ` * @template {${type}} ${name}` };
143
+ })
144
+ .toArray();
145
+ this.parsedType = {
146
+ module: `/**-templates-
147
+ * @typedef {import('./${relativePath}').${exportName}${
148
+ templates.length
149
+ ? `<${templates
150
+ .map(({ name }) => {
151
+ return name;
152
+ })
153
+ .join(',')}>`
154
+ : ''
155
+ }} ${exportName}
156
+ */`
157
+ .replace(/\\/g, '/')
158
+ .replace(
159
+ '-templates-',
160
+ templates.length
161
+ ? '\n' +
162
+ templates
163
+ .map(({ comment }) => {
164
+ return comment;
165
+ })
166
+ .join('\n')
167
+ : ''
168
+ ),
169
+ readme,
170
+ };
171
+ }
172
+ return this.parsedType;
173
+ };
174
+ /**
175
+ * @param {string} exportName
176
+ * @param {string} instanceOrStaticDef
177
+ * @param {string} fullDescription
178
+ * @param {string} isExport_
179
+ * @param {string} typeOfVar
180
+ * @param {string} getterOrSetter
181
+ * @param {string} namedVar
182
+ * @returns {refType}
183
+ */
184
+ #interpreteArrayDesc = (
185
+ exportName,
186
+ instanceOrStaticDef,
187
+ fullDescription,
188
+ isExport_,
189
+ typeOfVar,
190
+ getterOrSetter,
191
+ namedVar
192
+ ) => {
193
+ const type = instanceOrStaticDef.includes('@instance')
194
+ ? 'instance'
195
+ : instanceOrStaticDef.includes('@static')
196
+ ? 'static'
197
+ : instanceOrStaticDef.includes('@helper')
198
+ ? 'helper'
199
+ : '';
200
+ const parentSrc = instanceOrStaticDef
201
+ .matchAll(/(?:@instance|@static|@helper)\s+(\w+)/gm)
202
+ .toArray();
203
+ let parent = '';
204
+ if (parentSrc) {
205
+ TrySync(() => {
206
+ parent = parentSrc[0][1];
207
+ });
208
+ }
209
+ const isExport = isExport_ === 'export';
210
+ let reference = isExport ? exportName : '';
211
+ if (parent) {
212
+ reference = `${parent}.${namedVar}`;
213
+ }
214
+ switch (type) {
215
+ case 'instance':
216
+ reference = `${exportName}_instance.${reference}`;
217
+ break;
218
+ case 'static':
219
+ reference = `${exportName}.${reference}`;
220
+ break;
221
+ case 'helper':
222
+ reference = `isolated helper only: ${reference}`;
223
+ break;
224
+ default:
225
+ reference = isExport
226
+ ? `${exportName}`
227
+ : typeOfVar === 'static'
228
+ ? `${exportName}.${namedVar}`
229
+ : typeOfVar === ''
230
+ ? `${exportName}_instance.${namedVar}`
231
+ : '';
232
+ break;
233
+ }
234
+ if (getterOrSetter !== '') {
235
+ reference = `${reference}:${getterOrSetter}ter`;
236
+ }
237
+ fullDescription = fullDescription.trim();
238
+ if (namedVar.startsWith('#')) {
239
+ reference = '';
240
+ }
241
+ if (namedVar === 'constructor') {
242
+ reference = `new ${exportName}`;
243
+ }
244
+ return {
245
+ reference: `\`${reference}\``,
246
+ instanceOrStatic: {
247
+ parent,
248
+ type,
249
+ },
250
+ fullDescription,
251
+ parsedFullDescription: this.#parseFullDesc(fullDescription),
252
+ isExport,
253
+ typeOfVar,
254
+ namedVar,
255
+ };
256
+ };
257
+ /**
258
+ * @param {string} fullDescription
259
+ * @returns {{description:string, jsPreview:string}}
260
+ */
261
+ #parseFullDesc = (fullDescription) => {
262
+ const fullDescTrue = fullDescription.split('@');
263
+ const description = fullDescTrue[0]
264
+ .replace('*', '')
265
+ .replace(/(?<!\\)\*\s/g, '\n')
266
+ .trim();
267
+ fullDescTrue.shift();
268
+ let example;
269
+ let jsPreview = `\n\`\`\`js
270
+ /**
271
+ * @${fullDescTrue.join('@').replace(/(?<!\\)\*/g, '\n *')}
272
+ */\n\`\`\``;
273
+ const [example_] = jsPreview.matchAll(/@example([\s\S]*)\*\//gm).toArray();
274
+ TrySync(() => {
275
+ example = example_[1].replace(/(?<!\\)\*/g, '').replace(/^\s{2,2}/gm, ' ');
276
+ jsPreview = jsPreview.replace(example_[0], '\n */');
277
+ });
278
+ return {
279
+ description,
280
+ jsPreview: fullDescTrue.length
281
+ ? `${jsPreview
282
+ .replace(/\/\*\*[\s\*]*\*\//g, '')
283
+ .replace(/\`\`\`js[\s]*\`\`\`/gm, '')
284
+ .replace(/\*[\*\s]*\*\//g, '*/')}${
285
+ example ? `\n - <i>example</i>:\n\`\`\`js${example}\n\`\`\``.replace(/\\\*/g, '*') : ''
286
+ }`
287
+ : '',
288
+ };
289
+ };
290
+ /**
291
+ * @type {{exportName:undefined, details:undefined, error:{fullpath:string, message:string}}
292
+ * | {exportName:string|undefined, details:ReturnType<typeof parsedFile["getDescription"]>, error:undefined}
293
+ * }
294
+ */
295
+ #parsed;
296
+ /**
297
+ * @returns {Promise<{exportName:undefined, details:undefined, error:{fullpath:string, message:string}}
298
+ * | {exportName:string|undefined, details:ReturnType<typeof parsedFile["getDescription"]>, error:undefined}
299
+ * >}
300
+ */
301
+ #parse = async () => {
302
+ const fullpath = this.#fullPath;
303
+ const content = await this.content.string();
304
+ if (content === undefined) {
305
+ const error = { fullpath, message: 'invalid file content' };
306
+ Console.error(error);
307
+ return { exportName: undefined, details: undefined, error };
308
+ }
309
+ const supposedName = this.baseName.noExt.split('.')[0];
310
+ if (!this.#getTopExport(supposedName, content)) {
311
+ return {
312
+ details: undefined,
313
+ exportName: undefined,
314
+ error: { fullpath, message: 'no valid exported declaration' },
315
+ };
316
+ }
317
+ this.hasValidExportObject = true;
318
+ return {
319
+ details: parsedFile.getDescription(content),
320
+ exportName: supposedName,
321
+ error: undefined,
322
+ };
323
+ };
324
+ hasValidExportObject = false;
325
+ /**
326
+ * @param {string} name
327
+ * @param {string} content
328
+ * @returns {boolean}
329
+ */
330
+ #getTopExport = (name, content) => {
331
+ if (!parsedFile.#isExportNameValid(name)) {
332
+ return false;
333
+ }
334
+ const regex = new RegExp(
335
+ `export\\s*(?:(?:async\\s*|)function|const|class|\\{)\\s*${name}`,
336
+ 'g'
337
+ );
338
+ return regex.test(content);
339
+ };
340
+ /**
341
+ * @param {string} content
342
+ * @returns { RegExpExecArray[] }
343
+ */
344
+ static getDescription = (content) => {
345
+ const regexp =
346
+ /(\/\*\*([\s\S]*?)(?:@description)([\s\S]*?)\*\/\s?(export|\s?)\s?(static|class|const|function|async\s+function|\s?)\s?(?:async|)\s?(get|set|)\s+?(\w+))/gm;
347
+ const modified = content.replace(/\r\n+/g, ' ');
348
+ const matches = modified.matchAll(regexp).toArray();
349
+ return matches;
350
+ };
351
+ /**
352
+ * @type {string}
353
+ */
354
+ #fullPath;
355
+ /**
356
+ * @type {string}
357
+ */
358
+ #relativePath;
359
+ /**
360
+ * @returns {Promise<boolean>}
361
+ */
362
+ isFile = async () => {
363
+ return (await this.stats()).isFile();
364
+ };
365
+ /**
366
+ * @returns {Promise<boolean>}
367
+ */
368
+ isDirectory = async () => {
369
+ return (await this.stats()).isDirectory();
370
+ };
371
+
372
+ baseName = LazyFactory(() => {
373
+ const this_ = this;
374
+ return {
375
+ /**
376
+ * @type {string}
377
+ */
378
+ get withExt() {
379
+ return basename(this_.#fullPath);
380
+ },
381
+ /**
382
+ * @type {string}
383
+ */
384
+ get noExt() {
385
+ return basename(this_.#fullPath, extname(this_.#fullPath));
386
+ },
387
+ };
388
+ });
389
+ path = LazyFactory(() => {
390
+ const this_ = this;
391
+ return {
392
+ /**
393
+ * @type {string}
394
+ */
395
+ get relative() {
396
+ return this_.#relativePath;
397
+ },
398
+ /**
399
+ * @type {string}
400
+ */
401
+ get full() {
402
+ return this_.#fullPath;
403
+ },
404
+ };
405
+ });
406
+ get dirName() {
407
+ const this_ = this;
408
+ return {
409
+ /**
410
+ * @type {string}
411
+ */
412
+ get relative() {
413
+ return dirname(this_.#relativePath);
414
+ },
415
+ /**
416
+ * @type {string}
417
+ */
418
+ get full() {
419
+ return dirname(this_.#fullPath);
420
+ },
421
+ };
422
+ }
423
+ get ext() {
424
+ const this_ = this;
425
+ return {
426
+ /**
427
+ * @type {string|undefined}
428
+ */
429
+ get withDot() {
430
+ if (this_.isDirectory && !this_.isFile) {
431
+ return undefined;
432
+ }
433
+ return extname(this_.#fullPath);
434
+ },
435
+ /**
436
+ * @type {string|undefined}
437
+ */
438
+ get noDot() {
439
+ if (this_.isDirectory && !this_.isFile) {
440
+ return undefined;
441
+ }
442
+ return extname(this_.#fullPath).replace(/^\./, '');
443
+ },
444
+ };
445
+ }
446
+ /**
447
+ * @type {BufferEncoding}
448
+ */
449
+ #encoding;
450
+ /**
451
+ * @type {Stats}
452
+ */
453
+ #stats;
454
+ /**
455
+ * @private
456
+ * @returns {Promise<Stats>}
457
+ */
458
+ stats = async () => {
459
+ if (!this.#stats) {
460
+ this.#stats = await stat(this.#fullPath);
461
+ }
462
+ return this.#stats;
463
+ };
464
+ get timeStamp() {
465
+ const this_ = this;
466
+ return {
467
+ /**
468
+ * @returns {Promise<number>}
469
+ */
470
+ lastModified: async () => {
471
+ return (await this_.stats()).mtimeMs;
472
+ },
473
+ /**
474
+ * @returns {Promise<number>}
475
+ */
476
+ createdAt: async () => {
477
+ return (await this_.stats()).birthtimeMs;
478
+ },
479
+ };
480
+ }
481
+ /**
482
+ * @type {string}
483
+ */
484
+ #rawContent;
485
+ content = LazyFactory(() => {
486
+ const this_ = this;
487
+ return {
488
+ /**
489
+ * @return {Promise<string|undefined>}
490
+ */
491
+ string: async () => {
492
+ if (this_.isDirectory && !this_.isFile) {
493
+ return undefined;
494
+ }
495
+ const [raw, error] = await TryAsync(async () => {
496
+ return await readFile(this_.#fullPath, this_.#encoding);
497
+ });
498
+ if (!error) {
499
+ this_.#rawContent = raw;
500
+ return this_.#rawContent.toString();
501
+ }
502
+ Console.error({
503
+ error,
504
+ fullPath: this_.#fullPath,
505
+ message2: 'failed to read fullPath',
506
+ });
507
+ return undefined;
508
+ },
509
+ parsed: async () => {
510
+ if (!this_.#parsed) {
511
+ this_.#parsed = await this_.#parse();
512
+ }
513
+ return this_.#parsed;
514
+ },
515
+ };
516
+ });
517
+ /**
518
+ * @type {[Promise<any>, undefined]|[undefined, Error]}
519
+ */
520
+ get importAsModuleJS() {
521
+ const realTimePath = `${this.#fullPath}?${Date.now()}`;
522
+ let [importedModule, error] = TrySync(async () => {
523
+ return import(`file://${realTimePath}`);
524
+ });
525
+ if (!error) {
526
+ return [importedModule, undefined];
527
+ }
528
+ [importedModule, error] = TrySync(() => {
529
+ return import(realTimePath);
530
+ });
531
+ if (!error) {
532
+ return [importedModule, undefined];
533
+ }
534
+ Console.error({ error, timeStamp: Date.now() });
535
+ return [undefined, error];
536
+ }
537
+ }
@@ -0,0 +1,64 @@
1
+ // @ts-check
2
+
3
+ import { Console } from '../class/Console.mjs';
4
+ import { LazyFactory } from './LazyFactory.mjs';
5
+ import { TrySync } from './TrySync.mjs';
6
+
7
+ /**
8
+ * @description
9
+ * - function for create immutable object;
10
+ * - usefull for binding immutable object to global for shared object:
11
+ * >- e.g. to window object in browser;
12
+ * @template {Object} P
13
+ * @template {Object} O
14
+ * @param {string} keyName
15
+ * @param {P} parent
16
+ * @param {(this:P)=>O} object
17
+ * @param {Object} [options]
18
+ * @param {boolean} [options.lazy]
19
+ * @return {O}
20
+ * @example
21
+ * import { CreateImmutable } from 'vivth';
22
+ *
23
+ * const mappedObject = new Map();
24
+ *
25
+ * CreateImmutable(window, 'mySharedObject', {
26
+ * setMap(name_, value) => {
27
+ * mappedObject.set(name_, value)
28
+ * },
29
+ * getMap(name_) => mappedObject.get(name_),
30
+ * })
31
+ */
32
+ export const CreateImmutable = (parent, keyName, object, { lazy = true } = {}) => {
33
+ if (!parent || typeof parent !== 'object') {
34
+ Console.error({
35
+ object,
36
+ parent,
37
+ keyName,
38
+ message: 'Invalid parent object provided to `CreateImmutable`;',
39
+ });
40
+ return;
41
+ }
42
+ let [_, error] = TrySync(() => {
43
+ Object.defineProperty(parent, keyName, {
44
+ value: lazy ? LazyFactory(() => object.call(parent)) : object.call(parent),
45
+ writable: false,
46
+ configurable: false,
47
+ enumerable: false,
48
+ });
49
+ });
50
+ if (error) {
51
+ [_, error] = TrySync(() => {
52
+ parent[keyName] = lazy ? LazyFactory(() => object.call(parent)) : object.call(parent);
53
+ });
54
+ }
55
+ if (error) {
56
+ Console.info({
57
+ parent,
58
+ message: `"${keyName}" already defined on the "parent"`,
59
+ realValue: parent[keyName],
60
+ });
61
+ return;
62
+ }
63
+ return parent[keyName];
64
+ };
@@ -0,0 +1,27 @@
1
+ // @ts-check
2
+
3
+ import { EventNameSpace } from '../common/EventNameSpace.mjs';
4
+
5
+ /**
6
+ * @description
7
+ * - simple validation function for [EventObject](#eventobject), for multiple context, eg: `mainThread` <-> `workerThread`;
8
+ * @param {any} object
9
+ * @param {Record<typeof EventNameSpace, string>} eventObject
10
+ * @returns {boolean}
11
+ * @example
12
+ * import { EventCheck } from 'vivth';
13
+ * import { incomingMessage } from './some/where.mjs';
14
+ *
15
+ * const eventObjectPayload = EventObject('worker:exit');
16
+ * // assuming `incomingMessage`, also created using EventObject('worker:exit');
17
+ * // or manually {[EventNameSpace]:'worker:exit'};
18
+ * // which either will result true;
19
+ */
20
+ export const EventCheck = (object, eventObject) => {
21
+ return (
22
+ object &&
23
+ typeof object === 'object' &&
24
+ EventNameSpace in object &&
25
+ object[EventNameSpace] === eventObject[EventNameSpace]
26
+ );
27
+ };
@@ -0,0 +1,21 @@
1
+ // @ts-check
2
+ import { EventNameSpace } from '../common/EventNameSpace.mjs';
3
+
4
+ /**
5
+ * @description
6
+ * - simple object generation function helper for [EventCheck](#eventcheck), for multiple context, eg: `mainThread` <-> `workerThread`;
7
+ * @template {string} N
8
+ * @param {N} name
9
+ * @returns {{[EventNameSpace]: N}}
10
+ * @example
11
+ * import { EventCheck } from 'vivth';
12
+ * import { incomingMessage } from './some/where.mjs';
13
+ *
14
+ * const eventObjectPayload = EventObject('worker:exit');
15
+ * // assuming `incomingMessage`, also created using EventObject('worker:exit');
16
+ * // or manually {[EventNameSpace]:'worker:exit'};
17
+ * // which either will result true;
18
+ */
19
+ export const EventObject = (name) => {
20
+ return { [EventNameSpace]: name };
21
+ };
@@ -0,0 +1,23 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @description
5
+ * - function helper for checking whether `functionReference` is async;
6
+ * @param {(...any:any)=>(any|Promise<any>)} functionReference
7
+ * @returns {boolean}
8
+ * @example
9
+ * import { IsAsync } from 'vivth';
10
+ *
11
+ * const a = function (params) {
12
+ * // code
13
+ * }
14
+ * const b = async () => {
15
+ * // code
16
+ * }
17
+ *
18
+ * IsAsync(a); // false
19
+ * IsAsync(b); // true
20
+ */
21
+ export const IsAsync = (functionReference) => {
22
+ return functionReference.constructor.name === 'AsyncFunction';
23
+ };