@reventlessdev/reventless-gwt 1.0.0-alpha.115 → 1.0.0-alpha.116

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 (91) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/package.json +5 -12
  3. package/rescript.json +0 -1
  4. package/bin/reventless-dev.mjs +0 -21
  5. package/src/Bind.res +0 -29
  6. package/src/Bind.res.mjs +0 -22
  7. package/src/BuildClassifier.res +0 -147
  8. package/src/BuildClassifier.res.mjs +0 -136
  9. package/src/Cancellation.res +0 -37
  10. package/src/Cancellation.res.mjs +0 -46
  11. package/src/ChildProcess.res +0 -102
  12. package/src/ChildProcess.res.mjs +0 -107
  13. package/src/Cli.res +0 -889
  14. package/src/Cli.res.mjs +0 -944
  15. package/src/Collector.res +0 -222
  16. package/src/Collector.res.mjs +0 -228
  17. package/src/ComponentMeta.res +0 -77
  18. package/src/ComponentMeta.res.mjs +0 -91
  19. package/src/ComponentScan.res +0 -101
  20. package/src/ComponentScan.res.mjs +0 -92
  21. package/src/Discovery.res +0 -102
  22. package/src/Discovery.res.mjs +0 -86
  23. package/src/DomainDeadCode.res +0 -98
  24. package/src/DomainDeadCode.res.mjs +0 -72
  25. package/src/DomainGraph.res +0 -0
  26. package/src/DomainGraph.res.mjs +0 -0
  27. package/src/ExnMessage.res +0 -14
  28. package/src/ExnMessage.res.mjs +0 -17
  29. package/src/ExnReflect.mjs +0 -24
  30. package/src/Filter.res +0 -45
  31. package/src/Filter.res.mjs +0 -47
  32. package/src/FormatterHuman.res +0 -109
  33. package/src/FormatterHuman.res.mjs +0 -115
  34. package/src/FormatterJson.res +0 -264
  35. package/src/FormatterJson.res.mjs +0 -322
  36. package/src/FormatterJunit.res +0 -93
  37. package/src/FormatterJunit.res.mjs +0 -90
  38. package/src/FormatterTap.res +0 -100
  39. package/src/FormatterTap.res.mjs +0 -131
  40. package/src/FormatterVsCode.res +0 -352
  41. package/src/FormatterVsCode.res.mjs +0 -546
  42. package/src/Loader.res +0 -24
  43. package/src/Loader.res.mjs +0 -23
  44. package/src/PackageScan.res +0 -80
  45. package/src/PackageScan.res.mjs +0 -81
  46. package/src/PlatformRunner.res +0 -191
  47. package/src/PlatformRunner.res.mjs +0 -178
  48. package/src/PlatformScan.res +0 -141
  49. package/src/PlatformScan.res.mjs +0 -124
  50. package/src/ProcessManager.res +0 -135
  51. package/src/ProcessManager.res.mjs +0 -119
  52. package/src/RunWorker.res +0 -24
  53. package/src/RunWorker.res.mjs +0 -16
  54. package/src/RunnerTypes.res +0 -68
  55. package/src/RunnerTypes.res.mjs +0 -60
  56. package/src/ScanIgnore.res +0 -11
  57. package/src/ScanIgnore.res.mjs +0 -23
  58. package/src/Watch.res +0 -102
  59. package/src/Watch.res.mjs +0 -80
  60. package/src/WatcherProbe.res +0 -56
  61. package/src/WatcherProbe.res.mjs +0 -59
  62. package/src/Worker.res +0 -24
  63. package/src/Worker.res.mjs +0 -9
  64. package/tests/BuildClassifierTest.res +0 -133
  65. package/tests/BuildClassifierTest.res.mjs +0 -176
  66. package/tests/CliRunEntryTest.res +0 -57
  67. package/tests/CliRunEntryTest.res.mjs +0 -65
  68. package/tests/CliWatchScopeTest.res +0 -62
  69. package/tests/CliWatchScopeTest.res.mjs +0 -95
  70. package/tests/ComponentMetaTest.res +0 -67
  71. package/tests/ComponentMetaTest.res.mjs +0 -71
  72. package/tests/DiscoveryTest.res +0 -42
  73. package/tests/DiscoveryTest.res.mjs +0 -43
  74. package/tests/DomainDeadCodeTest.res +0 -119
  75. package/tests/DomainDeadCodeTest.res.mjs +0 -158
  76. package/tests/DomainGraphTest.res +0 -448
  77. package/tests/DomainGraphTest.res.mjs +0 -505
  78. package/tests/ExnMessageTest.res +0 -42
  79. package/tests/ExnMessageTest.res.mjs +0 -64
  80. package/tests/FormatterGoldenTest.res +0 -125
  81. package/tests/FormatterGoldenTest.res.mjs +0 -162
  82. package/tests/FormatterVsCodeMessageTest.res +0 -41
  83. package/tests/FormatterVsCodeMessageTest.res.mjs +0 -42
  84. package/tests/PlatformRunnerTest.res +0 -66
  85. package/tests/PlatformRunnerTest.res.mjs +0 -85
  86. package/tests/PlatformScanTest.res +0 -61
  87. package/tests/PlatformScanTest.res.mjs +0 -56
  88. package/tests/RunnerUnitTest.res +0 -219
  89. package/tests/RunnerUnitTest.res.mjs +0 -244
  90. package/tests/WatchDebounceTest.res +0 -106
  91. package/tests/WatchDebounceTest.res.mjs +0 -128
@@ -1,124 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Nodefs from "node:fs";
4
- import * as Nodepath from "node:path";
5
- import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
6
- import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
- import * as Promises from "node:fs/promises";
8
- import * as ScanIgnore$ReventlessGwt from "./ScanIgnore.res.mjs";
9
-
10
- let localPlatformDep = "@reventlessdev/reventless-local";
11
-
12
- function matchPlatform(pkgJsonText, mainExists) {
13
- if (!mainExists) {
14
- return;
15
- }
16
- let json;
17
- try {
18
- json = JSON.parse(pkgJsonText);
19
- } catch (exn) {
20
- return;
21
- }
22
- let obj = Stdlib_JSON.Decode.object(json);
23
- if (obj === undefined) {
24
- return;
25
- }
26
- let match = obj["name"];
27
- let name = typeof match === "string" ? match : "";
28
- let depsHave = key => {
29
- let deps = Stdlib_Option.flatMap(obj[key], Stdlib_JSON.Decode.object);
30
- if (deps !== undefined) {
31
- return Stdlib_Option.isSome(deps[localPlatformDep]);
32
- } else {
33
- return false;
34
- }
35
- };
36
- let dependsOnLocal = depsHave("dependencies") || depsHave("devDependencies") || depsHave("optionalDependencies");
37
- if (!dependsOnLocal) {
38
- return;
39
- }
40
- let scripts = Stdlib_Option.flatMap(obj["scripts"], Stdlib_JSON.Decode.object);
41
- let serveScript = scripts !== undefined ? (
42
- Stdlib_Option.isSome(scripts["serve:memory"]) ? "serve:memory" : (
43
- Stdlib_Option.isSome(scripts["serve"]) ? "serve" : undefined
44
- )
45
- ) : undefined;
46
- return [
47
- name,
48
- serveScript
49
- ];
50
- }
51
-
52
- function inspectDir(dir) {
53
- let pkgJson = Nodepath.join(dir, "package.json");
54
- let mainPath = Nodepath.join(Nodepath.join(dir, "src"), "Main.res.mjs");
55
- if (!Nodefs.existsSync(pkgJson)) {
56
- return;
57
- }
58
- let text;
59
- try {
60
- text = Nodefs.readFileSync(pkgJson, "utf8");
61
- } catch (exn) {
62
- text = "";
63
- }
64
- let match = matchPlatform(text, Nodefs.existsSync(mainPath));
65
- if (match !== undefined) {
66
- return {
67
- name: match[0],
68
- dir: dir,
69
- mainPath: mainPath,
70
- serveScript: match[1]
71
- };
72
- }
73
- }
74
-
75
- async function walk(dir, acc) {
76
- let pkg = inspectDir(dir);
77
- if (pkg !== undefined) {
78
- acc.push(pkg);
79
- } else {
80
- let entries;
81
- try {
82
- entries = await Promises.readdir(dir, {
83
- withFileTypes: true
84
- });
85
- } catch (exn) {
86
- entries = [];
87
- }
88
- for (let i = 0, i_finish = entries.length; i < i_finish; ++i) {
89
- let entry = entries[i];
90
- if (entry.isDirectory() && !ScanIgnore$ReventlessGwt.shouldIgnore(entry.name)) {
91
- await walk(Nodepath.join(dir, entry.name), acc);
92
- }
93
- }
94
- }
95
- return acc;
96
- }
97
-
98
- async function scan(roots) {
99
- let seen = {};
100
- let out = [];
101
- for (let i = 0, i_finish = roots.length; i < i_finish; ++i) {
102
- let found = await walk(roots[i], []);
103
- found.forEach(pkg => {
104
- let match = seen[pkg.dir];
105
- if (match !== undefined) {
106
- return;
107
- } else {
108
- seen[pkg.dir] = true;
109
- out.push(pkg);
110
- return;
111
- }
112
- });
113
- }
114
- return out;
115
- }
116
-
117
- export {
118
- localPlatformDep,
119
- matchPlatform,
120
- inspectDir,
121
- walk,
122
- scan,
123
- }
124
- /* node:fs Not a pure module */
@@ -1,135 +0,0 @@
1
- // Owns the `rescript build -w` watchers a watch session spawns — one per
2
- // package that owns tests (PackageScan), at most one per directory,
3
- // reference-counted by `dir`. Registered with Cancellation so SIGINT/SIGTERM
4
- // tears down every spawned watcher; never orphans a compiler.
5
-
6
- type managed = {
7
- dir: string,
8
- proc: ChildProcess.t,
9
- }
10
-
11
- let running: Dict.t<managed> = Dict.make()
12
-
13
- // Per-dir count of unexpected watcher exits, so a build-watcher that crashes on
14
- // startup (bad config, missing binary) is respawned a bounded number of times
15
- // rather than either freezing the build status forever or spinning in a tight
16
- // respawn loop.
17
- let restarts: Dict.t<int> = Dict.make()
18
- let maxRestarts = 3
19
-
20
- let isManaging = (dir: string): bool =>
21
- switch running->Dict.get(dir) {
22
- | Some(_) => true
23
- | None => false
24
- }
25
-
26
- // Spawn `pnpm run start` (the package's `rescript build -w`) in `pkg.dir`,
27
- // unless one is already managed there. `onStdout` receives each output line so
28
- // the caller can classify compiler markers (Phase 5).
29
- let rec spawnWatcher = (pkg: PackageScan.pkg, ~onStdout: (string, string) => unit): unit =>
30
- switch running->Dict.get(pkg.dir) {
31
- | Some(_) => ()
32
- | None => {
33
- let proc = ChildProcess.spawn("pnpm", ["run", "start"], ~cwd=pkg.dir)
34
- ChildProcess.onStdoutLine(proc, line => onStdout(pkg.dir, line))
35
- // stderr carries compiler/pnpm crash output; without this a watcher that
36
- // dies on stderr was invisible until the caller's 120s watchdog.
37
- ChildProcess.onStderrLine(proc, line => onStdout(pkg.dir, line))
38
- // A spawn failure ("error") never reaches "close"; surface it as output.
39
- ChildProcess.onError(proc, msg => onStdout(pkg.dir, msg))
40
- // Detect an unexpected exit. We compare the stored proc identity: an
41
- // intentional `stop` deletes the entry synchronously before "close" fires,
42
- // so if we still own this exact proc, the watcher crashed — respawn it up
43
- // to `maxRestarts` times so build status doesn't freeze.
44
- ChildProcess.onClose(proc, _code =>
45
- switch running->Dict.get(pkg.dir) {
46
- | Some(m) if m.proc === proc =>
47
- running->Dict.delete(pkg.dir)
48
- let n = restarts->Dict.get(pkg.dir)->Option.getOr(0)
49
- if n < maxRestarts {
50
- restarts->Dict.set(pkg.dir, n + 1)
51
- spawnWatcher(pkg, ~onStdout)
52
- }
53
- | _ => ()
54
- }
55
- )
56
- running->Dict.set(pkg.dir, {dir: pkg.dir, proc})
57
- }
58
- }
59
-
60
- // Stop just the watcher managed for `dir` (if any), tearing down its process
61
- // group. Returns true when one was running — i.e. the caller *owned* this
62
- // package's build (vs. an adopted external watcher, which we can't stop).
63
- let stop = (dir: string): bool =>
64
- switch running->Dict.get(dir) {
65
- | Some(m) => {
66
- ChildProcess.killTree(m.proc, "SIGTERM")
67
- running->Dict.delete(dir)
68
- true
69
- }
70
- | None => false
71
- }
72
-
73
- // Force a full re-emit of `pkg` after a structural change — a module relocation
74
- // that incremental compilation can't detect, since it keys invalidation on
75
- // source + dependency-interface hashes, never on a dependency's filesystem
76
- // location (see plan Phase 12). Drives a deterministic one-shot `rescript clean`
77
- // → `rescript build` to completion (the `clean` is what forces every dependent
78
- // `.res.mjs` to be re-emitted against the new layout; the `build` is essential
79
- // even on the adopted path — an external watcher won't rebuild after a clean
80
- // without a fresh source change, so a bare clean would strand the package with
81
- // no outputs). If we *owned* the package's watcher we stop it first (no lock
82
- // contention) and respawn it afterward to resume incremental watching; on the
83
- // adopted path the developer's own watcher keeps running untouched. `onStdout`
84
- // streams the clean/build output (compiler markers) to the caller; `onDone`
85
- // fires once the build completes, gating the test re-run.
86
- let cleanRebuild = (
87
- pkg: PackageScan.pkg,
88
- ~onStdout: (string, string) => unit,
89
- ~onDone: bool => unit,
90
- ): unit => {
91
- let wasManaged = stop(pkg.dir)
92
- // `next` receives the step's exit code so the chain can tell a failed clean or
93
- // build (non-zero / crash) from success — the previous shape discarded exit
94
- // codes and always reported the rebuild as OK, masking compile failures.
95
- let step = (cmd: string, args: array<string>, next: option<int> => unit): unit => {
96
- let proc = ChildProcess.spawn(cmd, args, ~cwd=pkg.dir)
97
- // "error" (spawn failure) and "close" can both fire; ensure the chain
98
- // advances exactly once.
99
- let settled = ref(false)
100
- let settle = (code: option<int>) =>
101
- if !settled.contents {
102
- settled := true
103
- next(code)
104
- }
105
- ChildProcess.onStdoutLine(proc, line => onStdout(pkg.dir, line))
106
- ChildProcess.onStderrLine(proc, line => onStdout(pkg.dir, line))
107
- ChildProcess.onError(proc, msg => {
108
- onStdout(pkg.dir, msg)
109
- settle(None)
110
- })
111
- ChildProcess.onClose(proc, code => settle(code))
112
- }
113
- step("pnpm", ["exec", "rescript", "clean"], _cleanCode =>
114
- step("pnpm", ["exec", "rescript", "build"], buildCode => {
115
- if wasManaged {
116
- spawnWatcher(pkg, ~onStdout)
117
- }
118
- onDone(buildCode == Some(0))
119
- })
120
- )
121
- }
122
-
123
- // SIGTERM, not SIGINT: a POSIX shell sets background children to ignore SIGINT,
124
- // so SIGINT can leak a watcher; SIGTERM tears down the whole group reliably
125
- // (verified across foreground and background process-tree shapes).
126
- let killAll = (): unit => {
127
- running
128
- ->Dict.valuesToArray
129
- ->Array.forEach(m => ChildProcess.killTree(m.proc, "SIGTERM"))
130
- running
131
- ->Dict.keysToArray
132
- ->Array.forEach(k => running->Dict.delete(k))
133
- }
134
-
135
- let managedCount = (): int => running->Dict.keysToArray->Array.length
@@ -1,119 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
4
- import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
- import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
6
- import * as ChildProcess$ReventlessGwt from "./ChildProcess.res.mjs";
7
-
8
- let running = {};
9
-
10
- let restarts = {};
11
-
12
- function isManaging(dir) {
13
- return running[dir] !== undefined;
14
- }
15
-
16
- function spawnWatcher(pkg, onStdout) {
17
- let match = running[pkg.dir];
18
- if (match !== undefined) {
19
- return;
20
- }
21
- let proc = ChildProcess$ReventlessGwt.spawn("pnpm", [
22
- "run",
23
- "start"
24
- ], pkg.dir, undefined);
25
- ChildProcess$ReventlessGwt.onStdoutLine(proc, line => onStdout(pkg.dir, line));
26
- ChildProcess$ReventlessGwt.onStderrLine(proc, line => onStdout(pkg.dir, line));
27
- ChildProcess$ReventlessGwt.onError(proc, msg => onStdout(pkg.dir, msg));
28
- ChildProcess$ReventlessGwt.onClose(proc, _code => {
29
- let m = running[pkg.dir];
30
- if (m === undefined) {
31
- return;
32
- }
33
- if (m.proc !== proc) {
34
- return;
35
- }
36
- Stdlib_Dict.$$delete(running, pkg.dir);
37
- let n = Stdlib_Option.getOr(restarts[pkg.dir], 0);
38
- if (n < 3) {
39
- restarts[pkg.dir] = n + 1 | 0;
40
- return spawnWatcher(pkg, onStdout);
41
- }
42
- });
43
- running[pkg.dir] = {
44
- dir: pkg.dir,
45
- proc: proc
46
- };
47
- }
48
-
49
- function stop(dir) {
50
- let m = running[dir];
51
- if (m !== undefined) {
52
- ChildProcess$ReventlessGwt.killTree(m.proc, "SIGTERM");
53
- Stdlib_Dict.$$delete(running, dir);
54
- return true;
55
- } else {
56
- return false;
57
- }
58
- }
59
-
60
- function cleanRebuild(pkg, onStdout, onDone) {
61
- let wasManaged = stop(pkg.dir);
62
- let step = (cmd, args, next) => {
63
- let proc = ChildProcess$ReventlessGwt.spawn(cmd, args, pkg.dir, undefined);
64
- let settled = {
65
- contents: false
66
- };
67
- let settle = code => {
68
- if (!settled.contents) {
69
- settled.contents = true;
70
- return next(code);
71
- }
72
- };
73
- ChildProcess$ReventlessGwt.onStdoutLine(proc, line => onStdout(pkg.dir, line));
74
- ChildProcess$ReventlessGwt.onStderrLine(proc, line => onStdout(pkg.dir, line));
75
- ChildProcess$ReventlessGwt.onError(proc, msg => {
76
- onStdout(pkg.dir, msg);
77
- settle(undefined);
78
- });
79
- ChildProcess$ReventlessGwt.onClose(proc, settle);
80
- };
81
- step("pnpm", [
82
- "exec",
83
- "rescript",
84
- "clean"
85
- ], _cleanCode => step("pnpm", [
86
- "exec",
87
- "rescript",
88
- "build"
89
- ], buildCode => {
90
- if (wasManaged) {
91
- spawnWatcher(pkg, onStdout);
92
- }
93
- onDone(Primitive_object.equal(buildCode, 0));
94
- }));
95
- }
96
-
97
- function killAll() {
98
- Object.values(running).forEach(m => ChildProcess$ReventlessGwt.killTree(m.proc, "SIGTERM"));
99
- Object.keys(running).forEach(k => Stdlib_Dict.$$delete(running, k));
100
- }
101
-
102
- function managedCount() {
103
- return Object.keys(running).length;
104
- }
105
-
106
- let maxRestarts = 3;
107
-
108
- export {
109
- running,
110
- restarts,
111
- maxRestarts,
112
- isManaging,
113
- spawnWatcher,
114
- stop,
115
- cleanRebuild,
116
- killAll,
117
- managedCount,
118
- }
119
- /* ChildProcess-ReventlessGwt Not a pure module */
package/src/RunWorker.res DELETED
@@ -1,24 +0,0 @@
1
- // Worker entry for a single gwt watch re-run pass.
2
- //
3
- // Spawned by `Cli.runWatch` with the run `options` passed as `workerData`. Runs
4
- // exactly one `runOnce` in this fresh worker (fresh ESM registry → recompiled
5
- // implementation modules are re-imported, not served stale), emits its NDJSON to
6
- // stdout (piped to the parent), then exits so the imported graph is reclaimed.
7
- // The parent never reuses a worker — one per re-run.
8
-
9
- @val @module("node:worker_threads") external workerData: Cli.options = "workerData"
10
- @val external processExit: int => unit = "process.exit"
11
-
12
- let () = {
13
- let _ =
14
- Cli.runOnce(workerData)
15
- ->Promise.then(code => {
16
- processExit(code)
17
- Promise.resolve()
18
- })
19
- ->Promise.catch(e => {
20
- Console.error2("gwt run worker failed:", e)
21
- processExit(1)
22
- Promise.resolve()
23
- })
24
- }
@@ -1,16 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
4
- import * as Cli$ReventlessGwt from "./Cli.res.mjs";
5
- import * as Nodeworker_threads from "node:worker_threads";
6
-
7
- Stdlib_Promise.$$catch(Cli$ReventlessGwt.runOnce(Nodeworker_threads.workerData).then(code => {
8
- process.exit(code);
9
- return Promise.resolve();
10
- }), e => {
11
- console.error("gwt run worker failed:", e);
12
- process.exit(1);
13
- return Promise.resolve();
14
- });
15
-
16
- /* Not a pure module */
@@ -1,68 +0,0 @@
1
- // Shared data types between the runner loop and formatters.
2
-
3
- type testStatus = Pass | Fail | Skip
4
-
5
- type testResult = {
6
- id: string,
7
- name: string,
8
- describePath: array<string>,
9
- status: testStatus,
10
- durationMs: float,
11
- location: option<Collector.location>,
12
- slice: option<string>,
13
- mismatch: option<Outcome.mismatch>,
14
- skipReason: option<string>,
15
- }
16
-
17
- type fileResult = {
18
- path: string,
19
- tests: array<testResult>,
20
- }
21
-
22
- type summary = {
23
- total: int,
24
- passed: int,
25
- failed: int,
26
- skipped: int,
27
- files: int,
28
- durationMs: float,
29
- startedAt: string,
30
- }
31
-
32
- type runResult = {
33
- summary: summary,
34
- files: array<fileResult>,
35
- }
36
-
37
- let statusString = (s: testStatus) =>
38
- switch s {
39
- | Pass => "pass"
40
- | Fail => "fail"
41
- | Skip => "skip"
42
- }
43
-
44
- let summaryOf = (files: array<fileResult>, durationMs: float, startedAt: string): summary => {
45
- let total = ref(0)
46
- let passed = ref(0)
47
- let failed = ref(0)
48
- let skipped = ref(0)
49
- files->Array.forEach(f =>
50
- f.tests->Array.forEach(t => {
51
- total := total.contents + 1
52
- switch t.status {
53
- | Pass => passed := passed.contents + 1
54
- | Fail => failed := failed.contents + 1
55
- | Skip => skipped := skipped.contents + 1
56
- }
57
- })
58
- )
59
- {
60
- total: total.contents,
61
- passed: passed.contents,
62
- failed: failed.contents,
63
- skipped: skipped.contents,
64
- files: files->Array.length,
65
- durationMs,
66
- startedAt,
67
- }
68
- }
@@ -1,60 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
-
4
- function statusString(s) {
5
- switch (s) {
6
- case "Pass" :
7
- return "pass";
8
- case "Fail" :
9
- return "fail";
10
- case "Skip" :
11
- return "skip";
12
- }
13
- }
14
-
15
- function summaryOf(files, durationMs, startedAt) {
16
- let total = {
17
- contents: 0
18
- };
19
- let passed = {
20
- contents: 0
21
- };
22
- let failed = {
23
- contents: 0
24
- };
25
- let skipped = {
26
- contents: 0
27
- };
28
- files.forEach(f => {
29
- f.tests.forEach(t => {
30
- total.contents = total.contents + 1 | 0;
31
- let match = t.status;
32
- switch (match) {
33
- case "Pass" :
34
- passed.contents = passed.contents + 1 | 0;
35
- return;
36
- case "Fail" :
37
- failed.contents = failed.contents + 1 | 0;
38
- return;
39
- case "Skip" :
40
- skipped.contents = skipped.contents + 1 | 0;
41
- return;
42
- }
43
- });
44
- });
45
- return {
46
- total: total.contents,
47
- passed: passed.contents,
48
- failed: failed.contents,
49
- skipped: skipped.contents,
50
- files: files.length,
51
- durationMs: durationMs,
52
- startedAt: startedAt
53
- };
54
- }
55
-
56
- export {
57
- statusString,
58
- summaryOf,
59
- }
60
- /* No side effect */
@@ -1,11 +0,0 @@
1
- // Single source for the directory names pruned from every monorepo scan — test
2
- // discovery, component scan, platform scan — and the equivalent chokidar globs
3
- // for the watch. Previously duplicated verbatim across the three walkers and,
4
- // divergently, as inline globs in `Watch`; that drift once let `dist/` writes
5
- // drive a re-run loop.
6
- let names = ["node_modules", ".git", "dist", "lib", ".history"]
7
-
8
- let shouldIgnore = (name: string): bool => names->Array.includes(name)
9
-
10
- // chokidar-style globs derived from the same list (the watch's ignore set).
11
- let globs = names->Array.map(n => "**/" ++ n ++ "/**")
@@ -1,23 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
-
4
- let names = [
5
- "node_modules",
6
- ".git",
7
- "dist",
8
- "lib",
9
- ".history"
10
- ];
11
-
12
- function shouldIgnore(name) {
13
- return names.includes(name);
14
- }
15
-
16
- let globs = names.map(n => "**/" + n + "/**");
17
-
18
- export {
19
- names,
20
- shouldIgnore,
21
- globs,
22
- }
23
- /* globs Not a pure module */
package/src/Watch.res DELETED
@@ -1,102 +0,0 @@
1
- // Wraps `chokidar` for the `reventless-gwt watch` and `reventless-gwt run
2
- // --watch` modes. Emits one callback per file change event (creates, edits,
3
- // deletes) after a small debounce window so rapid editor saves don't trigger
4
- // overlapping runs.
5
-
6
- type watcher
7
- type opts = {
8
- ignoreInitial: bool,
9
- ignored: array<string>,
10
- }
11
-
12
- // The kind of filesystem change, threaded through so the consumer can tell a
13
- // *structural* change (a source file appearing/disappearing — the move/delete
14
- // half of a relocation) from a plain edit. Phase 12 keys its clean-rebuild on
15
- // an `Unlink` of a `.res` source.
16
- type event = Add | Change | Unlink
17
-
18
- @module("chokidar") external watch: (array<string>, opts) => watcher = "watch"
19
- @send external on: (watcher, string, string => unit) => watcher = "on"
20
- @send external close: watcher => promise<unit> = "close"
21
-
22
- @val external setTimeout: (unit => unit, int) => float = "setTimeout"
23
- @val external clearTimeout: float => unit = "clearTimeout"
24
-
25
- // True when an event is the *structural* signal Phase 12 acts on: a source
26
- // `.res` file leaving a directory (the move/delete half of a relocation).
27
- // Generated `.res.mjs` outputs end in `.mjs`, so they never match — which is
28
- // also what keeps a `rescript clean` (it deletes those outputs) from
29
- // re-triggering the clean-rebuild it just ran.
30
- let isStructuralSource = (event: event, path: string): bool =>
31
- event == Unlink && String.endsWith(path, ".res")
32
-
33
- // Coalesce a burst of chokidar events into a single debounce window, then emit.
34
- // A window may span *multiple* packages — a branch switch or a multi-package
35
- // refactor emits `.res` unlinks under several package roots at once. The old
36
- // shape kept only one "best" path, so it clean-rebuilt just one package and
37
- // left the others with stale `.res.mjs`. Instead accumulate the *set* of
38
- // distinct structural source paths and emit one `Unlink` callback per path
39
- // (the consumer maps each to its owning package). If the window held no
40
- // structural signal, emit a single representative event so the consumer does a
41
- // plain re-run.
42
- let debounce = (wait: int, fn: (event, string) => unit) => {
43
- let pending: ref<option<float>> = ref(None)
44
- let structural: ref<array<string>> = ref([])
45
- let sawOther = ref(false)
46
- let otherEvent = ref(Change)
47
- let otherPath = ref("")
48
- (event, path) => {
49
- if isStructuralSource(event, path) {
50
- if !(structural.contents->Array.includes(path)) {
51
- structural := Array.concat(structural.contents, [path])
52
- }
53
- } else {
54
- sawOther := true
55
- otherEvent := event
56
- otherPath := path
57
- }
58
- switch pending.contents {
59
- | Some(t) => clearTimeout(t)
60
- | None => ()
61
- }
62
- pending :=
63
- Some(
64
- setTimeout(() => {
65
- pending := None
66
- let paths = structural.contents
67
- let other = sawOther.contents
68
- let oe = otherEvent.contents
69
- let op = otherPath.contents
70
- structural := []
71
- sawOther := false
72
- otherEvent := Change
73
- otherPath := ""
74
- if paths->Array.length > 0 {
75
- // One rebuild per distinct owning package; a plain edit alongside
76
- // is covered by each structural rebuild's own re-run.
77
- paths->Array.forEach(p => fn(Unlink, p))
78
- } else if other {
79
- fn(oe, op)
80
- }
81
- }, wait),
82
- )
83
- }
84
- }
85
-
86
- let start = (roots: array<string>, onChange: (event, string) => unit): watcher => {
87
- let w = watch(
88
- roots,
89
- {
90
- ignoreInitial: true,
91
- // Shared with the scanners via `ScanIgnore` — writes under `dist/` or
92
- // `.history/` are build/editor output, not source, and a `dist/` write
93
- // could otherwise drive a re-run loop.
94
- ignored: ScanIgnore.globs,
95
- },
96
- )
97
- let debounced = debounce(120, onChange)
98
- w
99
- ->on("add", p => debounced(Add, p))
100
- ->on("change", p => debounced(Change, p))
101
- ->on("unlink", p => debounced(Unlink, p))
102
- }