@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.
- package/CHANGELOG.md +11 -0
- package/package.json +5 -12
- package/rescript.json +0 -1
- package/bin/reventless-dev.mjs +0 -21
- package/src/Bind.res +0 -29
- package/src/Bind.res.mjs +0 -22
- package/src/BuildClassifier.res +0 -147
- package/src/BuildClassifier.res.mjs +0 -136
- package/src/Cancellation.res +0 -37
- package/src/Cancellation.res.mjs +0 -46
- package/src/ChildProcess.res +0 -102
- package/src/ChildProcess.res.mjs +0 -107
- package/src/Cli.res +0 -889
- package/src/Cli.res.mjs +0 -944
- package/src/Collector.res +0 -222
- package/src/Collector.res.mjs +0 -228
- package/src/ComponentMeta.res +0 -77
- package/src/ComponentMeta.res.mjs +0 -91
- package/src/ComponentScan.res +0 -101
- package/src/ComponentScan.res.mjs +0 -92
- package/src/Discovery.res +0 -102
- package/src/Discovery.res.mjs +0 -86
- package/src/DomainDeadCode.res +0 -98
- package/src/DomainDeadCode.res.mjs +0 -72
- package/src/DomainGraph.res +0 -0
- package/src/DomainGraph.res.mjs +0 -0
- package/src/ExnMessage.res +0 -14
- package/src/ExnMessage.res.mjs +0 -17
- package/src/ExnReflect.mjs +0 -24
- package/src/Filter.res +0 -45
- package/src/Filter.res.mjs +0 -47
- package/src/FormatterHuman.res +0 -109
- package/src/FormatterHuman.res.mjs +0 -115
- package/src/FormatterJson.res +0 -264
- package/src/FormatterJson.res.mjs +0 -322
- package/src/FormatterJunit.res +0 -93
- package/src/FormatterJunit.res.mjs +0 -90
- package/src/FormatterTap.res +0 -100
- package/src/FormatterTap.res.mjs +0 -131
- package/src/FormatterVsCode.res +0 -352
- package/src/FormatterVsCode.res.mjs +0 -546
- package/src/Loader.res +0 -24
- package/src/Loader.res.mjs +0 -23
- package/src/PackageScan.res +0 -80
- package/src/PackageScan.res.mjs +0 -81
- package/src/PlatformRunner.res +0 -191
- package/src/PlatformRunner.res.mjs +0 -178
- package/src/PlatformScan.res +0 -141
- package/src/PlatformScan.res.mjs +0 -124
- package/src/ProcessManager.res +0 -135
- package/src/ProcessManager.res.mjs +0 -119
- package/src/RunWorker.res +0 -24
- package/src/RunWorker.res.mjs +0 -16
- package/src/RunnerTypes.res +0 -68
- package/src/RunnerTypes.res.mjs +0 -60
- package/src/ScanIgnore.res +0 -11
- package/src/ScanIgnore.res.mjs +0 -23
- package/src/Watch.res +0 -102
- package/src/Watch.res.mjs +0 -80
- package/src/WatcherProbe.res +0 -56
- package/src/WatcherProbe.res.mjs +0 -59
- package/src/Worker.res +0 -24
- package/src/Worker.res.mjs +0 -9
- package/tests/BuildClassifierTest.res +0 -133
- package/tests/BuildClassifierTest.res.mjs +0 -176
- package/tests/CliRunEntryTest.res +0 -57
- package/tests/CliRunEntryTest.res.mjs +0 -65
- package/tests/CliWatchScopeTest.res +0 -62
- package/tests/CliWatchScopeTest.res.mjs +0 -95
- package/tests/ComponentMetaTest.res +0 -67
- package/tests/ComponentMetaTest.res.mjs +0 -71
- package/tests/DiscoveryTest.res +0 -42
- package/tests/DiscoveryTest.res.mjs +0 -43
- package/tests/DomainDeadCodeTest.res +0 -119
- package/tests/DomainDeadCodeTest.res.mjs +0 -158
- package/tests/DomainGraphTest.res +0 -448
- package/tests/DomainGraphTest.res.mjs +0 -505
- package/tests/ExnMessageTest.res +0 -42
- package/tests/ExnMessageTest.res.mjs +0 -64
- package/tests/FormatterGoldenTest.res +0 -125
- package/tests/FormatterGoldenTest.res.mjs +0 -162
- package/tests/FormatterVsCodeMessageTest.res +0 -41
- package/tests/FormatterVsCodeMessageTest.res.mjs +0 -42
- package/tests/PlatformRunnerTest.res +0 -66
- package/tests/PlatformRunnerTest.res.mjs +0 -85
- package/tests/PlatformScanTest.res +0 -61
- package/tests/PlatformScanTest.res.mjs +0 -56
- package/tests/RunnerUnitTest.res +0 -219
- package/tests/RunnerUnitTest.res.mjs +0 -244
- package/tests/WatchDebounceTest.res +0 -106
- package/tests/WatchDebounceTest.res.mjs +0 -128
package/src/PlatformScan.res.mjs
DELETED
|
@@ -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 */
|
package/src/ProcessManager.res
DELETED
|
@@ -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
|
-
}
|
package/src/RunWorker.res.mjs
DELETED
|
@@ -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 */
|
package/src/RunnerTypes.res
DELETED
|
@@ -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
|
-
}
|
package/src/RunnerTypes.res.mjs
DELETED
|
@@ -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 */
|
package/src/ScanIgnore.res
DELETED
|
@@ -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 ++ "/**")
|
package/src/ScanIgnore.res.mjs
DELETED
|
@@ -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
|
-
}
|