testeranto 0.94.0 → 0.100.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 (103) hide show
  1. package/bundle.js +4 -7
  2. package/dist/common/src/PM/main.js +160 -42
  3. package/dist/common/src/PM/node.js +20 -5
  4. package/dist/common/src/PM/web.js +19 -4
  5. package/dist/common/src/SubPackages/react/jsx/node.js +1 -6
  6. package/dist/common/src/cli.js +439 -0
  7. package/dist/common/src/cli2.js +144 -0
  8. package/dist/common/src/esbuildConfigs/inputFilesPlugin.js +18 -6
  9. package/dist/common/src/esbuildConfigs/node.js +1 -4
  10. package/dist/common/src/esbuildConfigs/web.js +1 -1
  11. package/dist/common/src/lib/abstractBase.js +14 -91
  12. package/dist/common/src/lib/types.js +1 -0
  13. package/dist/common/tsconfig.common.tsbuildinfo +1 -1
  14. package/dist/module/src/PM/main.js +160 -42
  15. package/dist/module/src/PM/node.js +20 -5
  16. package/dist/module/src/PM/web.js +19 -4
  17. package/dist/module/src/SubPackages/react/jsx/node.js +1 -6
  18. package/dist/module/src/cli.js +411 -0
  19. package/dist/module/src/cli2.js +116 -0
  20. package/dist/module/src/esbuildConfigs/inputFilesPlugin.js +18 -6
  21. package/dist/module/src/esbuildConfigs/node.js +1 -4
  22. package/dist/module/src/esbuildConfigs/web.js +1 -1
  23. package/dist/module/src/lib/abstractBase.js +14 -91
  24. package/dist/module/src/lib/types.js +1 -0
  25. package/dist/module/tsconfig.module.tsbuildinfo +1 -1
  26. package/dist/prebuild/cli.mjs +1491 -0
  27. package/dist/prebuild/{run-tests.mjs → cli2.mjs} +203 -156
  28. package/dist/types/src/Node.d.ts +2 -2
  29. package/dist/types/src/PM/index.d.ts +10 -2
  30. package/dist/types/src/PM/main.d.ts +13 -7
  31. package/dist/types/src/PM/node.d.ts +9 -2
  32. package/dist/types/src/PM/web.d.ts +9 -3
  33. package/dist/types/src/SubPackages/puppeteer.d.ts +1 -1
  34. package/dist/types/src/SubPackages/react/component/node.d.ts +1 -1
  35. package/dist/types/src/SubPackages/react/component/web.d.ts +1 -1
  36. package/dist/types/src/SubPackages/react/jsx/node.d.ts +3 -3
  37. package/dist/types/src/SubPackages/react/jsx/web.d.ts +2 -2
  38. package/dist/types/src/SubPackages/react-dom/component/node.d.ts +2 -2
  39. package/dist/types/src/SubPackages/react-dom/component/web.d.ts +1 -1
  40. package/dist/types/src/SubPackages/react-dom/jsx/node.d.ts +1 -1
  41. package/dist/types/src/SubPackages/react-dom/jsx/web.d.ts +2 -2
  42. package/dist/types/src/SubPackages/react-test-renderer/MemoExoticComponent/node.d.ts +2 -2
  43. package/dist/types/src/SubPackages/react-test-renderer/component/node.d.ts +2 -2
  44. package/dist/types/src/SubPackages/react-test-renderer/component/web.d.ts +2 -2
  45. package/dist/types/src/SubPackages/react-test-renderer/fc/node.d.ts +2 -2
  46. package/dist/types/src/SubPackages/react-test-renderer/fc/web.d.ts +2 -2
  47. package/dist/types/src/SubPackages/react-test-renderer/jsx/node.d.ts +3 -2
  48. package/dist/types/src/SubPackages/react-test-renderer/jsx/web.d.ts +2 -2
  49. package/dist/types/src/SubPackages/react-test-renderer/jsx-promised/node.d.ts +2 -2
  50. package/dist/types/src/SubPackages/react-test-renderer/jsx-promised/web.d.ts +2 -2
  51. package/dist/types/src/Types.d.ts +60 -21
  52. package/dist/types/src/Web.d.ts +2 -2
  53. package/dist/types/src/lib/index.d.ts +1 -1
  54. package/dist/types/src/lib/types.d.ts +2 -30
  55. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  56. package/package.json +11 -8
  57. package/src/PM/index.ts +12 -8
  58. package/src/PM/main.ts +218 -62
  59. package/src/PM/node.ts +42 -7
  60. package/src/PM/web.ts +33 -5
  61. package/src/SubPackages/react/jsx/node.ts +16 -5
  62. package/src/SubPackages/react-test-renderer/jsx/node.ts +16 -1
  63. package/src/Types.ts +362 -114
  64. package/src/cli.ts +535 -0
  65. package/src/cli2.ts +157 -0
  66. package/src/esbuildConfigs/inputFilesPlugin.ts +27 -6
  67. package/src/esbuildConfigs/node.ts +4 -7
  68. package/src/esbuildConfigs/web.ts +4 -3
  69. package/src/lib/abstractBase.ts +58 -115
  70. package/src/lib/types.ts +3 -177
  71. package/dist/common/src/Aider.js +0 -143
  72. package/dist/common/src/Project.js +0 -227
  73. package/dist/common/src/Puppeteer.js +0 -111
  74. package/dist/common/src/build-tests.js +0 -39
  75. package/dist/common/src/esbuildConfigs/features.js +0 -14
  76. package/dist/common/src/esbuildConfigs/report.js +0 -14
  77. package/dist/common/src/esbuildConfigs/tests.js +0 -13
  78. package/dist/common/src/run-tests.js +0 -39
  79. package/dist/module/src/Aider.js +0 -136
  80. package/dist/module/src/Project.js +0 -220
  81. package/dist/module/src/Puppeteer.js +0 -106
  82. package/dist/module/src/build-tests.js +0 -11
  83. package/dist/module/src/esbuildConfigs/features.js +0 -12
  84. package/dist/module/src/esbuildConfigs/report.js +0 -14
  85. package/dist/module/src/esbuildConfigs/tests.js +0 -11
  86. package/dist/module/src/run-tests.js +0 -11
  87. package/dist/prebuild/build-tests.mjs +0 -553
  88. package/dist/types/src/Aider.d.ts +0 -1
  89. package/dist/types/src/Project.d.ts +0 -12
  90. package/dist/types/src/Puppeteer.d.ts +0 -2
  91. package/dist/types/src/esbuildConfigs/features.d.ts +0 -4
  92. package/dist/types/src/esbuildConfigs/report.d.ts +0 -0
  93. package/dist/types/src/esbuildConfigs/tests.d.ts +0 -4
  94. package/src/Aider.ts +0 -168
  95. package/src/Project.ts +0 -292
  96. package/src/Puppeteer.ts +0 -143
  97. package/src/build-tests.ts +0 -12
  98. package/src/esbuildConfigs/features.ts +0 -17
  99. package/src/esbuildConfigs/report.ts +0 -15
  100. package/src/esbuildConfigs/tests.ts +0 -14
  101. package/src/run-tests.ts +0 -12
  102. /package/dist/types/src/{build-tests.d.ts → cli.d.ts} +0 -0
  103. /package/dist/types/src/{run-tests.d.ts → cli2.d.ts} +0 -0
package/src/cli.ts ADDED
@@ -0,0 +1,535 @@
1
+ import { spawn } from "child_process";
2
+ import fs, { watch } from "fs";
3
+ import path from "path";
4
+ import readline from "readline";
5
+ import { glob } from "glob";
6
+ import crypto from "node:crypto";
7
+
8
+ import { debounceWatch } from "@bscotch/debounce-watch";
9
+ import type { DebouncedEventsProcessor } from "@bscotch/debounce-watch";
10
+
11
+ import esbuild from "esbuild";
12
+ import tseslint from "typescript-eslint";
13
+ import { ESLint } from "eslint";
14
+
15
+ import esbuildNodeConfiger from "./esbuildConfigs/node.js";
16
+ import esbuildWebConfiger from "./esbuildConfigs/web.js";
17
+ import webHtmlFrame from "./web.html.js";
18
+ import {
19
+ ITestTypes,
20
+ IBaseConfig,
21
+ IRunTime,
22
+ IBuiltConfig,
23
+ } from "./lib/types.js";
24
+ import { PM_Main } from "./PM/main.js";
25
+
26
+ readline.emitKeypressEvents(process.stdin);
27
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
28
+
29
+ function parseTsErrors(logContent): void {
30
+ fs.writeFileSync("docs/types/log.txt", logContent.join("\n"));
31
+
32
+ try {
33
+ const regex = /(^src(.*?))\(\d*,\d*\): error/gm;
34
+ const brokenFilesToLines: Record<string, Set<number>> = {};
35
+
36
+ for (let i = 0; i < logContent.length - 1; i++) {
37
+ let m;
38
+
39
+ while ((m = regex.exec(logContent[i])) !== null) {
40
+ // This is necessary to avoid infinite loops with zero-width matches
41
+ if (m.index === regex.lastIndex) {
42
+ regex.lastIndex++;
43
+ }
44
+ if (!brokenFilesToLines[m[1]]) {
45
+ brokenFilesToLines[m[1]] = new Set<number>();
46
+ }
47
+ brokenFilesToLines[m[1]].add(i);
48
+ }
49
+ }
50
+
51
+ const final = Object.keys(brokenFilesToLines).reduce((mm, lm, ndx) => {
52
+ mm[lm] = Array.from(brokenFilesToLines[lm]).map((l, ndx3) => {
53
+ const a = Array.from(brokenFilesToLines[lm]);
54
+
55
+ return Object.keys(a).reduce((mm2, lm2, ndx2) => {
56
+ const acc: string[] = [];
57
+
58
+ let j = a[lm2] + 1;
59
+
60
+ let working = true;
61
+ while (j < logContent.length - 1 && working) {
62
+ if (
63
+ !logContent[j].match(regex) &&
64
+ working &&
65
+ !logContent[j].match(/^..\/(.*?)\(\d*,\d*\)/)
66
+ ) {
67
+ acc.push(logContent[j]);
68
+ } else {
69
+ working = false;
70
+ }
71
+
72
+ j++;
73
+ }
74
+
75
+ mm2[lm] = [logContent[l], ...acc];
76
+
77
+ return mm2;
78
+ }, {} as any)[lm];
79
+ });
80
+ return mm;
81
+ }, {});
82
+
83
+ Object.keys(final).forEach((k) => {
84
+ fs.mkdirSync(`./docs/types/${k.split("/").slice(0, -1).join("/")}`, {
85
+ recursive: true,
86
+ });
87
+ fs.writeFileSync(
88
+ `./docs/types/${k}.type_errors.txt`,
89
+ final[k].flat().flat().join("\r\n")
90
+ );
91
+ });
92
+ } catch (error) {
93
+ console.error("Error reading or parsing the log file:", error);
94
+ process.exit(1);
95
+ }
96
+ }
97
+
98
+ function parseLintErrors(logContent): void {
99
+ fs.writeFileSync("docs/eslint/log.txt", logContent.join("\n"));
100
+
101
+ try {
102
+ const regex = new RegExp(`^${process.cwd()}/(.*?)`, "gm");
103
+ const brokenFilesToLines: Record<string, Set<number>> = {};
104
+
105
+ for (let i = 0; i < logContent.length - 1; i++) {
106
+ let m;
107
+
108
+ while ((m = regex.exec(logContent[i])) !== null) {
109
+ // This is necessary to avoid infinite loops with zero-width matches
110
+ if (m.index === regex.lastIndex) {
111
+ regex.lastIndex++;
112
+ }
113
+ if (!brokenFilesToLines[m[1]]) {
114
+ brokenFilesToLines[m[1]] = new Set<number>();
115
+ }
116
+ brokenFilesToLines[m[1]].add(i);
117
+ }
118
+ }
119
+
120
+ const final = Object.keys(brokenFilesToLines).reduce((mm, lm, ndx) => {
121
+ mm[lm] = Array.from(brokenFilesToLines[lm]).map((l, ndx3) => {
122
+ const a = Array.from(brokenFilesToLines[lm]);
123
+
124
+ return Object.keys(a).reduce((mm2, lm2, ndx2) => {
125
+ const acc: string[] = [];
126
+
127
+ let j = a[lm2] + 1;
128
+
129
+ let working = true;
130
+ while (j < logContent.length - 1 && working) {
131
+ if (
132
+ !logContent[j].match(regex) &&
133
+ working
134
+ // &&
135
+ // !logContent[j].match(/^..\/(.*?)\(\d*,\d*\)/)
136
+ ) {
137
+ acc.push(logContent[j]);
138
+ } else {
139
+ working = false;
140
+ }
141
+
142
+ j++;
143
+ }
144
+
145
+ mm2[lm] = [logContent[l], ...acc];
146
+
147
+ return mm2;
148
+ }, {} as any)[lm];
149
+ });
150
+ return mm;
151
+ }, {});
152
+
153
+ Object.keys(final).forEach((k) => {
154
+ fs.mkdirSync(`./docs/eslint/${k.split("/").slice(0, -1).join("/")}`, {
155
+ recursive: true,
156
+ });
157
+ fs.writeFileSync(
158
+ `./docs/eslint/${k}.lint_errors.txt`,
159
+ final[k].flat().flat().join("\r\n")
160
+ );
161
+ });
162
+ } catch (error) {
163
+ console.error("Error reading or parsing the log file:", error);
164
+ process.exit(1);
165
+ }
166
+ }
167
+
168
+ const typecheck = () => {
169
+ const logContent: string[] = [];
170
+ fs.rmSync("docs/types", { force: true, recursive: true });
171
+ fs.mkdirSync("docs/types");
172
+
173
+ const tsc = spawn("tsc", ["-noEmit"]);
174
+
175
+ tsc.stdout.on("data", (data) => {
176
+ const lines = data.toString().split("\n");
177
+ logContent.push(...lines);
178
+ });
179
+
180
+ tsc.stderr.on("data", (data) => {
181
+ console.error(`stderr: ${data}`);
182
+ process.exit(-1);
183
+ });
184
+
185
+ tsc.on("close", (code) => {
186
+ parseTsErrors(logContent);
187
+ });
188
+ };
189
+
190
+ const eslint = () => {
191
+ const logContent: string[] = [];
192
+ fs.rmSync("docs/eslint", { force: true, recursive: true });
193
+ fs.mkdirSync("docs/eslint");
194
+
195
+ const tsc = spawn("eslint", ["./src"]);
196
+
197
+ tsc.stdout.on("data", (data) => {
198
+ const lines = data.toString().split("\n");
199
+ logContent.push(...lines);
200
+ });
201
+
202
+ tsc.stderr.on("data", (data) => {
203
+ console.error(`stderr: ${data}`);
204
+ process.exit(-1);
205
+ });
206
+
207
+ tsc.on("close", (code) => {
208
+ parseLintErrors(logContent);
209
+ });
210
+ };
211
+
212
+ type IRunnables = {
213
+ nodeEntryPoints: Record<string, string>;
214
+ webEntryPoints: Record<string, string>;
215
+ };
216
+
217
+ const getRunnables = (
218
+ tests: ITestTypes[],
219
+ payload = {
220
+ nodeEntryPoints: {},
221
+ webEntryPoints: {},
222
+ }
223
+ ): IRunnables => {
224
+ return tests.reduce((pt, cv, cndx, cry) => {
225
+ if (cv[1] === "node") {
226
+ pt.nodeEntryPoints[cv[0]] = path.resolve(
227
+ `./docs/node/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
228
+ );
229
+ } else if (cv[1] === "web") {
230
+ pt.webEntryPoints[cv[0]] = path.resolve(
231
+ `./docs/web/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
232
+ );
233
+ }
234
+
235
+ if (cv[3].length) {
236
+ getRunnables(cv[3], payload);
237
+ }
238
+
239
+ return pt;
240
+ }, payload as IRunnables);
241
+ };
242
+
243
+ import(process.cwd() + "/" + process.argv[2]).then(async (module) => {
244
+ const rawConfig: IBaseConfig = module.default;
245
+
246
+ const getSecondaryEndpointsPoints = (runtime?: IRunTime): string[] => {
247
+ const meta = (ts: ITestTypes[], st: Set<string>): Set<string> => {
248
+ ts.forEach((t) => {
249
+ if (t[1] === runtime) {
250
+ st.add(t[0]);
251
+ }
252
+ if (Array.isArray(t[3])) {
253
+ meta(t[3], st);
254
+ }
255
+ });
256
+ return st;
257
+ };
258
+ return Array.from(meta(config.tests, new Set()));
259
+ };
260
+
261
+ const config: IBuiltConfig = {
262
+ ...rawConfig,
263
+ buildDir: process.cwd() + "/" + rawConfig.outdir,
264
+ };
265
+
266
+ let nodeDone: boolean = false;
267
+ let webDone: boolean = false;
268
+ let mode = config.devMode ? "DEV" : "PROD";
269
+ let status: "build" | "built" = "build";
270
+ let pm: PM_Main | undefined = new PM_Main(config);
271
+ const fileHashes = {};
272
+ const { nodeEntryPoints, webEntryPoints } = getRunnables(config.tests);
273
+
274
+ const onNodeDone = () => {
275
+ nodeDone = true;
276
+ onDone();
277
+ };
278
+
279
+ const onWebDone = () => {
280
+ webDone = true;
281
+ onDone();
282
+ };
283
+
284
+ // async function fileHash(filePath, algorithm = "md5") {
285
+ // return new Promise((resolve, reject) => {
286
+ // const hash = crypto.createHash(algorithm);
287
+ // const fileStream = fs.createReadStream(filePath);
288
+
289
+ // fileStream.on("data", (data) => {
290
+ // hash.update(data);
291
+ // });
292
+
293
+ // fileStream.on("end", () => {
294
+ // const fileHash = hash.digest("hex");
295
+ // resolve(fileHash);
296
+ // });
297
+
298
+ // fileStream.on("error", (error) => {
299
+ // reject(`Error reading file: ${error.message}`);
300
+ // });
301
+ // });
302
+ // }
303
+
304
+ const onDone = async () => {
305
+ if (nodeDone && webDone) {
306
+ status = "built";
307
+ }
308
+ if (nodeDone && webDone && status === "built") {
309
+ // Object.entries(nodeEntryPoints).forEach(([k, outputFile]) => {
310
+ // console.log("watching", outputFile);
311
+ // try {
312
+ // watch(outputFile, async (filename) => {
313
+ // const hash = await fileHash(outputFile);
314
+ // if (fileHashes[k] !== hash) {
315
+ // fileHashes[k] = hash;
316
+ // console.log(`< ${filename} `);
317
+ // pm.launchNode(k, outputFile);
318
+ // }
319
+ // });
320
+ // } catch (e) {
321
+ // console.error(e);
322
+ // }
323
+ // });
324
+ // Object.entries(webEntryPoints).forEach(([k, outputFile]) => {
325
+ // console.log("watching", outputFile);
326
+ // watch(outputFile, async (filename) => {
327
+ // const hash = await fileHash(outputFile);
328
+ // console.log(`< ${filename} ${hash}`);
329
+ // if (fileHashes[k] !== hash) {
330
+ // fileHashes[k] = hash;
331
+ // pm.launchWeb(k, outputFile);
332
+ // }
333
+ // });
334
+ // });
335
+ }
336
+
337
+ if (nodeDone && webDone && mode === "PROD") {
338
+ console.log("Testeranto-EsBuild is all done. Goodbye!");
339
+ process.exit();
340
+ } else {
341
+ if (mode === "PROD") {
342
+ console.log("waiting for tests to finish");
343
+ console.log(
344
+ JSON.stringify(
345
+ {
346
+ nodeDone: nodeDone,
347
+ webDone: webDone,
348
+ mode: mode,
349
+ },
350
+ null,
351
+ 2
352
+ )
353
+ );
354
+ } else {
355
+ console.log("waiting for tests to change");
356
+ }
357
+ console.log("press 'q' to quit");
358
+
359
+ if (config.devMode) {
360
+ console.log("ready and watching for changes...");
361
+ } else {
362
+ pm.shutDown();
363
+ }
364
+ ////////////////////////////////////////////////////////////////////////////////
365
+ }
366
+ };
367
+
368
+ console.log(
369
+ `Press 'q' to shutdown gracefully. Press 'x' to shutdown forcefully.`
370
+ );
371
+ process.stdin.on("keypress", (str, key) => {
372
+ if (key.name === "q") {
373
+ console.log("Testeranto-EsBuild is shutting down...");
374
+ mode = "PROD";
375
+ onDone();
376
+ }
377
+ });
378
+
379
+ // const eslint = new ESLint();
380
+ // const configEslint = await eslint.calculateConfigForFile(
381
+ // "./src/eslint.config.mjs"
382
+ // );
383
+ // // console.log(`configEslint`, configEslint);
384
+ // fs.watch("src", { recursive: true }, async (eventType, filename) => {
385
+ // if (eventType === "change") {
386
+ // console.log(`File ${filename} has been modified.`);
387
+ // const x = await eslint.lintFiles([`./src/${filename}`]);
388
+ // console.log(x[0].messages);
389
+ // } else if (eventType === "rename") {
390
+ // console.log(`File ${filename} has been created or deleted.`);
391
+ // }
392
+ // });
393
+
394
+ fs.writeFileSync(
395
+ `${config.outdir}/testeranto.json`,
396
+ JSON.stringify(config, null, 2)
397
+ );
398
+
399
+ Promise.resolve(
400
+ Promise.all(
401
+ [...getSecondaryEndpointsPoints("web")].map(async (sourceFilePath) => {
402
+ const sourceFileSplit = sourceFilePath.split("/");
403
+ const sourceDir = sourceFileSplit.slice(0, -1);
404
+ const sourceFileName = sourceFileSplit[sourceFileSplit.length - 1];
405
+ const sourceFileNameMinusJs = sourceFileName
406
+ .split(".")
407
+ .slice(0, -1)
408
+ .join(".");
409
+
410
+ const htmlFilePath = path.normalize(
411
+ `${process.cwd()}/${config.outdir}/web/${sourceDir.join(
412
+ "/"
413
+ )}/${sourceFileNameMinusJs}.html`
414
+ );
415
+ const jsfilePath = `./${sourceFileNameMinusJs}.mjs`;
416
+
417
+ return fs.promises
418
+ .mkdir(path.dirname(htmlFilePath), { recursive: true })
419
+ .then((x) =>
420
+ fs.writeFileSync(
421
+ htmlFilePath,
422
+ webHtmlFrame(jsfilePath, htmlFilePath)
423
+ )
424
+ );
425
+ })
426
+ )
427
+ );
428
+
429
+ glob(`./${config.outdir}/chunk-*.mjs`, {
430
+ ignore: "node_modules/**",
431
+ }).then((chunks) => {
432
+ chunks.forEach((chunk) => {
433
+ fs.unlinkSync(chunk);
434
+ });
435
+ });
436
+
437
+ // const processDebouncedEvents: DebouncedEventsProcessor = (events) => {
438
+ // typecheck();
439
+ // };
440
+
441
+ debounceWatch(
442
+ (events) => {
443
+ typecheck();
444
+ eslint();
445
+ },
446
+ "./src",
447
+ {
448
+ onlyFileExtensions: ["ts", "tsx", "mts"],
449
+ debounceWaitSeconds: 0.2,
450
+ allowOverlappingRuns: false,
451
+ }
452
+ );
453
+
454
+ await pm.startPuppeteer(
455
+ {
456
+ slowMo: 1,
457
+ // timeout: 1,
458
+ waitForInitialPage: false,
459
+ executablePath:
460
+ // process.env.CHROMIUM_PATH || "/opt/homebrew/bin/chromium",
461
+ "/opt/homebrew/bin/chromium",
462
+ headless: true,
463
+ dumpio: true,
464
+ // timeout: 0,
465
+ devtools: true,
466
+
467
+ args: [
468
+ "--auto-open-devtools-for-tabs",
469
+ `--remote-debugging-port=3234`,
470
+
471
+ // "--disable-features=IsolateOrigins,site-per-process",
472
+ "--disable-site-isolation-trials",
473
+ "--allow-insecure-localhost",
474
+ "--allow-file-access-from-files",
475
+ "--allow-running-insecure-content",
476
+
477
+ "--disable-dev-shm-usage",
478
+ "--disable-extensions",
479
+ "--disable-gpu",
480
+ "--disable-setuid-sandbox",
481
+ "--disable-site-isolation-trials",
482
+ "--disable-web-security",
483
+ "--no-first-run",
484
+ "--no-sandbox",
485
+ "--no-startup-window",
486
+ // "--no-zygote",
487
+ "--reduce-security-for-testing",
488
+ "--remote-allow-origins=*",
489
+ "--unsafely-treat-insecure-origin-as-secure=*",
490
+ // "--disable-features=IsolateOrigins",
491
+ // "--remote-allow-origins=ws://localhost:3234",
492
+ // "--single-process",
493
+ // "--unsafely-treat-insecure-origin-as-secure",
494
+ // "--unsafely-treat-insecure-origin-as-secure=ws://192.168.0.101:3234",
495
+
496
+ // "--disk-cache-dir=/dev/null",
497
+ // "--disk-cache-size=1",
498
+ // "--start-maximized",
499
+ ],
500
+ },
501
+ "."
502
+ );
503
+
504
+ await Promise.all([
505
+ esbuild
506
+ .context(esbuildNodeConfiger(config, Object.keys(nodeEntryPoints)))
507
+ .then(async (nodeContext) => {
508
+ if (config.devMode) {
509
+ await nodeContext.watch().then((v) => {
510
+ onNodeDone();
511
+ });
512
+ } else {
513
+ nodeContext.rebuild().then((v) => {
514
+ onNodeDone();
515
+ });
516
+ }
517
+
518
+ return nodeContext;
519
+ }),
520
+ esbuild
521
+ .context(esbuildWebConfiger(config, Object.keys(webEntryPoints)))
522
+ .then(async (webContext) => {
523
+ if (config.devMode) {
524
+ await webContext.watch().then((v) => {
525
+ onWebDone();
526
+ });
527
+ } else {
528
+ webContext.rebuild().then((v) => {
529
+ onWebDone();
530
+ });
531
+ }
532
+ return webContext;
533
+ }),
534
+ ]);
535
+ });
package/src/cli2.ts ADDED
@@ -0,0 +1,157 @@
1
+ import { watch } from "fs";
2
+ import { config } from "process";
3
+ import { PM_Main } from "./PM/main";
4
+ import { IBaseConfig, IBuiltConfig, ITestTypes } from "./lib/types";
5
+ import path from "path";
6
+ import crypto from "node:crypto";
7
+ import fs from "fs";
8
+
9
+ type IRunnables = {
10
+ nodeEntryPoints: Record<string, string>;
11
+ webEntryPoints: Record<string, string>;
12
+ };
13
+
14
+ const fileHashes = {};
15
+
16
+ async function fileHash(filePath, algorithm = "md5") {
17
+ return new Promise((resolve, reject) => {
18
+ const hash = crypto.createHash(algorithm);
19
+ const fileStream = fs.createReadStream(filePath);
20
+
21
+ fileStream.on("data", (data) => {
22
+ hash.update(data);
23
+ });
24
+
25
+ fileStream.on("end", () => {
26
+ const fileHash = hash.digest("hex");
27
+ resolve(fileHash);
28
+ });
29
+
30
+ fileStream.on("error", (error) => {
31
+ reject(`Error reading file: ${error.message}`);
32
+ });
33
+ });
34
+ }
35
+
36
+ const getRunnables = (
37
+ tests: ITestTypes[],
38
+ payload = {
39
+ nodeEntryPoints: {},
40
+ webEntryPoints: {},
41
+ }
42
+ ): IRunnables => {
43
+ return tests.reduce((pt, cv, cndx, cry) => {
44
+ if (cv[1] === "node") {
45
+ pt.nodeEntryPoints[cv[0]] = path.resolve(
46
+ `./docs/node/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
47
+ );
48
+ } else if (cv[1] === "web") {
49
+ pt.webEntryPoints[cv[0]] = path.resolve(
50
+ `./docs/web/${cv[0].split(".").slice(0, -1).concat("mjs").join(".")}`
51
+ );
52
+ }
53
+
54
+ if (cv[3].length) {
55
+ getRunnables(cv[3], payload);
56
+ }
57
+
58
+ return pt;
59
+ }, payload as IRunnables);
60
+ };
61
+
62
+ import(process.cwd() + "/" + process.argv[2]).then(async (module) => {
63
+ const rawConfig: IBaseConfig = module.default;
64
+
65
+ const config: IBuiltConfig = {
66
+ ...rawConfig,
67
+ buildDir: process.cwd() + "/" + rawConfig.outdir,
68
+ };
69
+
70
+ let pm: PM_Main | undefined = new PM_Main(config);
71
+
72
+ await pm.startPuppeteer(
73
+ {
74
+ slowMo: 1,
75
+ // timeout: 1,
76
+ waitForInitialPage: false,
77
+ executablePath:
78
+ // process.env.CHROMIUM_PATH || "/opt/homebrew/bin/chromium",
79
+ "/opt/homebrew/bin/chromium",
80
+ headless: true,
81
+ dumpio: true,
82
+ // timeout: 0,
83
+ devtools: true,
84
+
85
+ args: [
86
+ "--auto-open-devtools-for-tabs",
87
+ `--remote-debugging-port=3234`,
88
+
89
+ // "--disable-features=IsolateOrigins,site-per-process",
90
+ "--disable-site-isolation-trials",
91
+ "--allow-insecure-localhost",
92
+ "--allow-file-access-from-files",
93
+ "--allow-running-insecure-content",
94
+
95
+ "--disable-dev-shm-usage",
96
+ "--disable-extensions",
97
+ "--disable-gpu",
98
+ "--disable-setuid-sandbox",
99
+ "--disable-site-isolation-trials",
100
+ "--disable-web-security",
101
+ "--no-first-run",
102
+ "--no-sandbox",
103
+ "--no-startup-window",
104
+ // "--no-zygote",
105
+ "--reduce-security-for-testing",
106
+ "--remote-allow-origins=*",
107
+ "--unsafely-treat-insecure-origin-as-secure=*",
108
+ // "--disable-features=IsolateOrigins",
109
+ // "--remote-allow-origins=ws://localhost:3234",
110
+ // "--single-process",
111
+ // "--unsafely-treat-insecure-origin-as-secure",
112
+ // "--unsafely-treat-insecure-origin-as-secure=ws://192.168.0.101:3234",
113
+
114
+ // "--disk-cache-dir=/dev/null",
115
+ // "--disk-cache-size=1",
116
+ // "--start-maximized",
117
+ ],
118
+ },
119
+ "."
120
+ );
121
+
122
+ const { nodeEntryPoints, webEntryPoints } = getRunnables(config.tests);
123
+
124
+ Object.entries(nodeEntryPoints).forEach(
125
+ ([k, outputFile]: [string, string]) => {
126
+ console.log("watching and running", outputFile);
127
+ pm.launchNode(k, outputFile);
128
+ try {
129
+ watch(outputFile, async (e, filename) => {
130
+ const hash = await fileHash(outputFile);
131
+ if (fileHashes[k] !== hash) {
132
+ fileHashes[k] = hash;
133
+ console.log(`< ${e} ${filename} ${hash}`);
134
+ pm.launchNode(k, outputFile);
135
+ }
136
+ });
137
+ } catch (e) {
138
+ console.error(e);
139
+ }
140
+ }
141
+ );
142
+
143
+ Object.entries(webEntryPoints).forEach(
144
+ ([k, outputFile]: [string, string]) => {
145
+ console.log("watching and running", outputFile);
146
+ pm.launchWeb(k, outputFile);
147
+ watch(outputFile, async (e, filename) => {
148
+ const hash = await fileHash(outputFile);
149
+ console.log(`< ${e} ${filename} ${hash}`);
150
+ if (fileHashes[k] !== hash) {
151
+ fileHashes[k] = hash;
152
+ pm.launchWeb(k, outputFile);
153
+ }
154
+ });
155
+ }
156
+ );
157
+ });