@reventlessdev/reventless-gwt 1.0.0-alpha.100
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 +916 -0
- package/LICENSE +202 -0
- package/bin/reventless-dev.mjs +21 -0
- package/package.json +54 -0
- package/rescript.json +36 -0
- package/src/.gwtignore +10 -0
- package/src/Automation_GWT.res +207 -0
- package/src/Automation_GWT.res.mjs +160 -0
- package/src/Behavior_GWT.res +569 -0
- package/src/Behavior_GWT.res.mjs +523 -0
- package/src/Bind.res +29 -0
- package/src/Bind.res.mjs +22 -0
- package/src/BuildClassifier.res +147 -0
- package/src/BuildClassifier.res.mjs +136 -0
- package/src/Cancellation.res +37 -0
- package/src/Cancellation.res.mjs +46 -0
- package/src/ChildProcess.res +102 -0
- package/src/ChildProcess.res.mjs +107 -0
- package/src/Cli.res +905 -0
- package/src/Cli.res.mjs +952 -0
- package/src/Collector.res +212 -0
- package/src/Collector.res.mjs +218 -0
- package/src/ComponentMeta.res +77 -0
- package/src/ComponentMeta.res.mjs +91 -0
- package/src/ComponentScan.res +103 -0
- package/src/ComponentScan.res.mjs +105 -0
- package/src/Delegate_GWT.res +303 -0
- package/src/Delegate_GWT.res.mjs +372 -0
- package/src/Diff.res +91 -0
- package/src/Diff.res.mjs +98 -0
- package/src/Discovery.res +105 -0
- package/src/Discovery.res.mjs +99 -0
- package/src/DomainDeadCode.res +98 -0
- package/src/DomainDeadCode.res.mjs +72 -0
- package/src/DomainGraph.res +0 -0
- package/src/DomainGraph.res.mjs +0 -0
- package/src/EventMapping_GWT.res +29 -0
- package/src/EventMapping_GWT.res.mjs +44 -0
- package/src/Filter.res +45 -0
- package/src/Filter.res.mjs +47 -0
- package/src/Flow_GWT.res +664 -0
- package/src/Flow_GWT.res.mjs +604 -0
- package/src/FormatterHuman.res +109 -0
- package/src/FormatterHuman.res.mjs +115 -0
- package/src/FormatterJson.res +264 -0
- package/src/FormatterJson.res.mjs +322 -0
- package/src/FormatterJunit.res +93 -0
- package/src/FormatterJunit.res.mjs +90 -0
- package/src/FormatterTap.res +100 -0
- package/src/FormatterTap.res.mjs +131 -0
- package/src/FormatterVsCode.res +352 -0
- package/src/FormatterVsCode.res.mjs +546 -0
- package/src/Hint.res +119 -0
- package/src/Hint.res.mjs +124 -0
- package/src/InboundTranslation_GWT.res +83 -0
- package/src/InboundTranslation_GWT.res.mjs +94 -0
- package/src/JestBind.res +70 -0
- package/src/JestBind.res.mjs +63 -0
- package/src/Loader.res +24 -0
- package/src/Loader.res.mjs +23 -0
- package/src/LocalHost.res +119 -0
- package/src/LocalHost.res.mjs +99 -0
- package/src/Mapping_GWT.res +474 -0
- package/src/Mapping_GWT.res.mjs +322 -0
- package/src/MismatchRender.res +72 -0
- package/src/MismatchRender.res.mjs +127 -0
- package/src/MultiSourceProjection_GWT.res +316 -0
- package/src/MultiSourceProjection_GWT.res.mjs +354 -0
- package/src/OutboundTranslation_GWT.res +238 -0
- package/src/OutboundTranslation_GWT.res.mjs +186 -0
- package/src/Outcome.res +97 -0
- package/src/Outcome.res.mjs +93 -0
- package/src/PackageScan.res +80 -0
- package/src/PackageScan.res.mjs +81 -0
- package/src/PlatformRunner.res +181 -0
- package/src/PlatformRunner.res.mjs +176 -0
- package/src/PlatformScan.res +142 -0
- package/src/PlatformScan.res.mjs +132 -0
- package/src/ProcessManager.res +135 -0
- package/src/ProcessManager.res.mjs +119 -0
- package/src/Projection_GWT.res +312 -0
- package/src/Projection_GWT.res.mjs +332 -0
- package/src/Query_GWT.res +379 -0
- package/src/Query_GWT.res.mjs +367 -0
- package/src/RenderRescript.res +125 -0
- package/src/RenderRescript.res.mjs +141 -0
- package/src/RunWorker.res +24 -0
- package/src/RunWorker.res.mjs +16 -0
- package/src/RunnerTypes.res +68 -0
- package/src/RunnerTypes.res.mjs +60 -0
- package/src/SideEffect_GWT.res +157 -0
- package/src/SideEffect_GWT.res.mjs +113 -0
- package/src/StateChange/ExternalAddCategorySlice.res +25 -0
- package/src/StateChange/ExternalAddCategorySlice.res.mjs +34 -0
- package/src/StateChange/ExternalAddCategorySlice_Behavior.res +19 -0
- package/src/StateChange/ExternalAddCategorySlice_Behavior.res.mjs +46 -0
- package/src/StateChange/WithFixtures.res +22 -0
- package/src/StateChange/WithFixtures.res.mjs +31 -0
- package/src/StateChange/WithFixtures_Behavior.res +17 -0
- package/src/StateChange/WithFixtures_Behavior.res.mjs +37 -0
- package/src/StateChange/WithManualOpen.res +23 -0
- package/src/StateChange/WithManualOpen.res.mjs +31 -0
- package/src/StateChange/WithManualOpen_Behavior.res +17 -0
- package/src/StateChange/WithManualOpen_Behavior.res.mjs +37 -0
- package/src/StubRuntime.res +54 -0
- package/src/StubRuntime.res.mjs +55 -0
- package/src/TestFixtures.res +16 -0
- package/src/TestFixtures.res.mjs +34 -0
- package/src/Watch.res +108 -0
- package/src/Watch.res.mjs +85 -0
- package/src/WatcherProbe.res +56 -0
- package/src/WatcherProbe.res.mjs +59 -0
- package/src/Worker.res +24 -0
- package/src/Worker.res.mjs +9 -0
- package/tests/AutomationGwtTest.res +71 -0
- package/tests/AutomationGwtTest.res.mjs +189 -0
- package/tests/BuildClassifierTest.res +133 -0
- package/tests/BuildClassifierTest.res.mjs +176 -0
- package/tests/CliRunEntryTest.res +57 -0
- package/tests/CliRunEntryTest.res.mjs +65 -0
- package/tests/CliWatchScopeTest.res +62 -0
- package/tests/CliWatchScopeTest.res.mjs +95 -0
- package/tests/ComponentMetaTest.res +67 -0
- package/tests/ComponentMetaTest.res.mjs +71 -0
- package/tests/DelegateGwtTest.res +487 -0
- package/tests/DelegateGwtTest.res.mjs +891 -0
- package/tests/DiscoveryTest.res +42 -0
- package/tests/DiscoveryTest.res.mjs +43 -0
- package/tests/DomainDeadCodeTest.res +119 -0
- package/tests/DomainDeadCodeTest.res.mjs +158 -0
- package/tests/DomainGraphTest.res +448 -0
- package/tests/DomainGraphTest.res.mjs +505 -0
- package/tests/FlowAggregateGwtTest.res +171 -0
- package/tests/FlowAggregateGwtTest.res.mjs +273 -0
- package/tests/FlowCrossPluginGwtTest.res +340 -0
- package/tests/FlowCrossPluginGwtTest.res.mjs +798 -0
- package/tests/FlowGwtTest.res +222 -0
- package/tests/FlowGwtTest.res.mjs +433 -0
- package/tests/FormatterGoldenTest.res +125 -0
- package/tests/FormatterGoldenTest.res.mjs +162 -0
- package/tests/FormatterVsCodeMessageTest.res +41 -0
- package/tests/FormatterVsCodeMessageTest.res.mjs +42 -0
- package/tests/InboundTranslationGwtTest.res +34 -0
- package/tests/InboundTranslationGwtTest.res.mjs +99 -0
- package/tests/LocalHostIntegration.res +70 -0
- package/tests/LocalHostIntegration.res.mjs +64 -0
- package/tests/LocalHostTest.res +71 -0
- package/tests/LocalHostTest.res.mjs +63 -0
- package/tests/MappingGwtTest.res +350 -0
- package/tests/MappingGwtTest.res.mjs +596 -0
- package/tests/OutboundTranslationGwtTest.res +59 -0
- package/tests/OutboundTranslationGwtTest.res.mjs +139 -0
- package/tests/PlatformRunnerTest.res +66 -0
- package/tests/PlatformRunnerTest.res.mjs +85 -0
- package/tests/PlatformScanTest.res +61 -0
- package/tests/PlatformScanTest.res.mjs +56 -0
- package/tests/QueryGwtTest.res +161 -0
- package/tests/QueryGwtTest.res.mjs +314 -0
- package/tests/QueryResolverGwtTest.res +71 -0
- package/tests/QueryResolverGwtTest.res.mjs +136 -0
- package/tests/RunnerUnitTest.res +219 -0
- package/tests/RunnerUnitTest.res.mjs +244 -0
- package/tests/SideEffect/FakeOrderNotification.res +23 -0
- package/tests/SideEffect/FakeOrderNotification.res.mjs +36 -0
- package/tests/SideEffect/FakeOrderNotificationGwtTest.res +35 -0
- package/tests/SideEffect/FakeOrderNotificationGwtTest.res.mjs +73 -0
- package/tests/SideEffect/MockEmail.res +18 -0
- package/tests/SideEffect/MockEmail.res.mjs +47 -0
- package/tests/StateChange/ExternalAddCategorySlice_GWT.res +27 -0
- package/tests/StateChange/ExternalAddCategorySlice_GWT.res.mjs +70 -0
- package/tests/StateChange/WithFixtures_Fixtures.res +9 -0
- package/tests/StateChange/WithFixtures_Fixtures.res.mjs +20 -0
- package/tests/StateChange/WithFixtures_GWT.res +23 -0
- package/tests/StateChange/WithFixtures_GWT.res.mjs +56 -0
- package/tests/StateChange/WithManualOpen_Fixtures.res +7 -0
- package/tests/StateChange/WithManualOpen_Fixtures.res.mjs +20 -0
- package/tests/StateChange/WithManualOpen_GWT.res +17 -0
- package/tests/StateChange/WithManualOpen_GWT.res.mjs +56 -0
- package/tests/StateChangeSliceGwtTest.res +160 -0
- package/tests/StateChangeSliceGwtTest.res.mjs +280 -0
- package/tests/StateViewSliceGwtTest.res +64 -0
- package/tests/StateViewSliceGwtTest.res.mjs +161 -0
- package/tests/WatchDebounceTest.res +106 -0
- package/tests/WatchDebounceTest.res.mjs +128 -0
package/src/Cli.res.mjs
ADDED
|
@@ -0,0 +1,952 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodepath from "node:path";
|
|
4
|
+
import * as Nodecrypto from "node:crypto";
|
|
5
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
6
|
+
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
7
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
8
|
+
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
9
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
10
|
+
import * as Watch$ReventlessGwt from "./Watch.res.mjs";
|
|
11
|
+
import * as Nodeworker_threads from "node:worker_threads";
|
|
12
|
+
import * as Loader$ReventlessGwt from "./Loader.res.mjs";
|
|
13
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
14
|
+
import * as Worker$ReventlessGwt from "./Worker.res.mjs";
|
|
15
|
+
import * as Outcome$ReventlessGwt from "./Outcome.res.mjs";
|
|
16
|
+
import * as Collector$ReventlessGwt from "./Collector.res.mjs";
|
|
17
|
+
import * as Discovery$ReventlessGwt from "./Discovery.res.mjs";
|
|
18
|
+
import * as LocalHost$ReventlessGwt from "./LocalHost.res.mjs";
|
|
19
|
+
import * as DomainGraph$ReventlessGwt from "./DomainGraph.res.mjs";
|
|
20
|
+
import * as PackageScan$ReventlessGwt from "./PackageScan.res.mjs";
|
|
21
|
+
import * as RunnerTypes$ReventlessGwt from "./RunnerTypes.res.mjs";
|
|
22
|
+
import * as Cancellation$ReventlessGwt from "./Cancellation.res.mjs";
|
|
23
|
+
import * as FormatterTap$ReventlessGwt from "./FormatterTap.res.mjs";
|
|
24
|
+
import * as PlatformScan$ReventlessGwt from "./PlatformScan.res.mjs";
|
|
25
|
+
import * as WatcherProbe$ReventlessGwt from "./WatcherProbe.res.mjs";
|
|
26
|
+
import * as ComponentScan$ReventlessGwt from "./ComponentScan.res.mjs";
|
|
27
|
+
import * as FormatterJson$ReventlessGwt from "./FormatterJson.res.mjs";
|
|
28
|
+
import * as DomainDeadCode$ReventlessGwt from "./DomainDeadCode.res.mjs";
|
|
29
|
+
import * as FormatterHuman$ReventlessGwt from "./FormatterHuman.res.mjs";
|
|
30
|
+
import * as FormatterJunit$ReventlessGwt from "./FormatterJunit.res.mjs";
|
|
31
|
+
import * as PlatformRunner$ReventlessGwt from "./PlatformRunner.res.mjs";
|
|
32
|
+
import * as ProcessManager$ReventlessGwt from "./ProcessManager.res.mjs";
|
|
33
|
+
import * as BuildClassifier$ReventlessGwt from "./BuildClassifier.res.mjs";
|
|
34
|
+
import * as FormatterVsCode$ReventlessGwt from "./FormatterVsCode.res.mjs";
|
|
35
|
+
import * as Platform_ComponentDefinitionsApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_ComponentDefinitionsApi.res.mjs";
|
|
36
|
+
|
|
37
|
+
let toolVersion = "0.1.0";
|
|
38
|
+
|
|
39
|
+
function sha256(s) {
|
|
40
|
+
return Nodecrypto.createHash("sha256").update(s).digest("hex");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let lastDomainHash = {
|
|
44
|
+
contents: undefined
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
let dateNowIso = (() => new Date().toISOString());
|
|
48
|
+
|
|
49
|
+
function parseFormat(s) {
|
|
50
|
+
switch (s) {
|
|
51
|
+
case "human" :
|
|
52
|
+
return {
|
|
53
|
+
TAG: "Ok",
|
|
54
|
+
_0: "Human"
|
|
55
|
+
};
|
|
56
|
+
case "json" :
|
|
57
|
+
return {
|
|
58
|
+
TAG: "Ok",
|
|
59
|
+
_0: "Json"
|
|
60
|
+
};
|
|
61
|
+
case "junit" :
|
|
62
|
+
return {
|
|
63
|
+
TAG: "Ok",
|
|
64
|
+
_0: "Junit"
|
|
65
|
+
};
|
|
66
|
+
case "tap" :
|
|
67
|
+
return {
|
|
68
|
+
TAG: "Ok",
|
|
69
|
+
_0: "Tap"
|
|
70
|
+
};
|
|
71
|
+
case "vscode" :
|
|
72
|
+
return {
|
|
73
|
+
TAG: "Ok",
|
|
74
|
+
_0: "VsCode"
|
|
75
|
+
};
|
|
76
|
+
default:
|
|
77
|
+
return {
|
|
78
|
+
TAG: "Error",
|
|
79
|
+
_0: "Unknown --format value: " + s
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function defaultRoots() {
|
|
85
|
+
return ["."];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function help() {
|
|
89
|
+
return `reventless-dev — Reventless dev CLI: GWT runner, domain graph, components, platform runner
|
|
90
|
+
|
|
91
|
+
USAGE:
|
|
92
|
+
reventless-dev run [--format=<fmt>] [--filter=<id>] [--stream] [--watch] [path...]
|
|
93
|
+
reventless-dev discover [--format=vscode] [path...]
|
|
94
|
+
reventless-dev watch [--format=<fmt>] [--filter=<id>] [path...]
|
|
95
|
+
reventless-dev platform [--format=vscode] [--backend=<b>] [--ui-ports] [path...]
|
|
96
|
+
reventless-dev platform --list [path...]
|
|
97
|
+
|
|
98
|
+
FORMATS:
|
|
99
|
+
human ANSI-coloured terminal output (default)
|
|
100
|
+
json Structured JSON envelope (--stream for NDJSON)
|
|
101
|
+
tap TAP 14 with YAML diagnostics
|
|
102
|
+
junit JUnit XML (single batch)
|
|
103
|
+
vscode NDJSON event stream for the VS Code Testing API
|
|
104
|
+
|
|
105
|
+
FLAGS:
|
|
106
|
+
--filter <id> Restrict execution to tests whose id contains <id>.
|
|
107
|
+
Repeatable.
|
|
108
|
+
--stream NDJSON streaming (json/vscode)
|
|
109
|
+
--watch Re-run on file change
|
|
110
|
+
--schema-version <v> Pin a JSON schema version for stable AI prompts
|
|
111
|
+
--backend <b> platform: storage backend for the spawned local platform
|
|
112
|
+
("memory" default, or "sqlite:<path>[?reset]")
|
|
113
|
+
--ui-ports platform: pin the platform to the fixed default ports
|
|
114
|
+
(4000/4001/3001/3002) instead of ephemeral ones, so the
|
|
115
|
+
host-shell UI's Vite proxy can reach it
|
|
116
|
+
--list platform: list launchable platform packages as NDJSON
|
|
117
|
+
({name, dir} per line) and exit
|
|
118
|
+
--help Show this help and exit
|
|
119
|
+
|
|
120
|
+
Exit code is 1 if any test failed, 0 otherwise.
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function parseArgv(argv) {
|
|
125
|
+
let slice = argv.slice(2, argv.length);
|
|
126
|
+
let subcommand = "Run";
|
|
127
|
+
let format = "Human";
|
|
128
|
+
let stream = false;
|
|
129
|
+
let watch = false;
|
|
130
|
+
let filters = [];
|
|
131
|
+
let schemaVersion;
|
|
132
|
+
let roots = [];
|
|
133
|
+
let backend = "memory";
|
|
134
|
+
let uiPorts = false;
|
|
135
|
+
let listPlatforms = false;
|
|
136
|
+
let error;
|
|
137
|
+
let showHelp = false;
|
|
138
|
+
let i = 0;
|
|
139
|
+
let len = slice.length;
|
|
140
|
+
if (len > 0) {
|
|
141
|
+
let first = slice[0];
|
|
142
|
+
switch (first) {
|
|
143
|
+
case "--help" :
|
|
144
|
+
case "-h" :
|
|
145
|
+
showHelp = true;
|
|
146
|
+
break;
|
|
147
|
+
case "discover" :
|
|
148
|
+
subcommand = "Discover";
|
|
149
|
+
format = "VsCode";
|
|
150
|
+
i = 1;
|
|
151
|
+
break;
|
|
152
|
+
case "platform" :
|
|
153
|
+
subcommand = "Platform";
|
|
154
|
+
i = 1;
|
|
155
|
+
break;
|
|
156
|
+
case "run" :
|
|
157
|
+
subcommand = "Run";
|
|
158
|
+
i = 1;
|
|
159
|
+
break;
|
|
160
|
+
case "watch" :
|
|
161
|
+
subcommand = "Watch";
|
|
162
|
+
watch = true;
|
|
163
|
+
i = 1;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
while (i < len && error === undefined && !showHelp) {
|
|
168
|
+
let arg = slice[i];
|
|
169
|
+
if (arg === "--help" || arg === "-h") {
|
|
170
|
+
showHelp = true;
|
|
171
|
+
} else if (arg.startsWith("--format=")) {
|
|
172
|
+
let v = arg.slice(9, arg.length);
|
|
173
|
+
let f = parseFormat(v);
|
|
174
|
+
if (f.TAG === "Ok") {
|
|
175
|
+
format = f._0;
|
|
176
|
+
} else {
|
|
177
|
+
error = f._0;
|
|
178
|
+
}
|
|
179
|
+
} else if (arg === "--format" && (i + 1 | 0) < len) {
|
|
180
|
+
let v$1 = slice[i + 1 | 0];
|
|
181
|
+
let f$1 = parseFormat(v$1);
|
|
182
|
+
if (f$1.TAG === "Ok") {
|
|
183
|
+
format = f$1._0;
|
|
184
|
+
} else {
|
|
185
|
+
error = f$1._0;
|
|
186
|
+
}
|
|
187
|
+
i = i + 1 | 0;
|
|
188
|
+
} else if (arg.startsWith("--filter=")) {
|
|
189
|
+
let v$2 = arg.slice(9, arg.length);
|
|
190
|
+
filters = filters.concat([v$2]);
|
|
191
|
+
} else if (arg === "--filter" && (i + 1 | 0) < len) {
|
|
192
|
+
let v$3 = slice[i + 1 | 0];
|
|
193
|
+
filters = filters.concat([v$3]);
|
|
194
|
+
i = i + 1 | 0;
|
|
195
|
+
} else if (arg === "--stream") {
|
|
196
|
+
stream = true;
|
|
197
|
+
} else if (arg === "--watch") {
|
|
198
|
+
watch = true;
|
|
199
|
+
} else if (arg.startsWith("--schema-version=")) {
|
|
200
|
+
let v$4 = arg.slice(17, arg.length);
|
|
201
|
+
schemaVersion = v$4;
|
|
202
|
+
} else if (arg.startsWith("--backend=")) {
|
|
203
|
+
backend = arg.slice(10, arg.length);
|
|
204
|
+
} else if (arg === "--backend" && (i + 1 | 0) < len) {
|
|
205
|
+
backend = slice[i + 1 | 0];
|
|
206
|
+
i = i + 1 | 0;
|
|
207
|
+
} else if (arg === "--ui-ports") {
|
|
208
|
+
uiPorts = true;
|
|
209
|
+
} else if (arg === "--list") {
|
|
210
|
+
listPlatforms = true;
|
|
211
|
+
} else if (arg.startsWith("--")) {
|
|
212
|
+
error = "Unknown flag: " + arg;
|
|
213
|
+
} else {
|
|
214
|
+
roots = roots.concat([arg]);
|
|
215
|
+
}
|
|
216
|
+
i = i + 1 | 0;
|
|
217
|
+
};
|
|
218
|
+
if (showHelp) {
|
|
219
|
+
return {
|
|
220
|
+
TAG: "Error",
|
|
221
|
+
_0: `reventless-dev — Reventless dev CLI: GWT runner, domain graph, components, platform runner
|
|
222
|
+
|
|
223
|
+
USAGE:
|
|
224
|
+
reventless-dev run [--format=<fmt>] [--filter=<id>] [--stream] [--watch] [path...]
|
|
225
|
+
reventless-dev discover [--format=vscode] [path...]
|
|
226
|
+
reventless-dev watch [--format=<fmt>] [--filter=<id>] [path...]
|
|
227
|
+
reventless-dev platform [--format=vscode] [--backend=<b>] [--ui-ports] [path...]
|
|
228
|
+
reventless-dev platform --list [path...]
|
|
229
|
+
|
|
230
|
+
FORMATS:
|
|
231
|
+
human ANSI-coloured terminal output (default)
|
|
232
|
+
json Structured JSON envelope (--stream for NDJSON)
|
|
233
|
+
tap TAP 14 with YAML diagnostics
|
|
234
|
+
junit JUnit XML (single batch)
|
|
235
|
+
vscode NDJSON event stream for the VS Code Testing API
|
|
236
|
+
|
|
237
|
+
FLAGS:
|
|
238
|
+
--filter <id> Restrict execution to tests whose id contains <id>.
|
|
239
|
+
Repeatable.
|
|
240
|
+
--stream NDJSON streaming (json/vscode)
|
|
241
|
+
--watch Re-run on file change
|
|
242
|
+
--schema-version <v> Pin a JSON schema version for stable AI prompts
|
|
243
|
+
--backend <b> platform: storage backend for the spawned local platform
|
|
244
|
+
("memory" default, or "sqlite:<path>[?reset]")
|
|
245
|
+
--ui-ports platform: pin the platform to the fixed default ports
|
|
246
|
+
(4000/4001/3001/3002) instead of ephemeral ones, so the
|
|
247
|
+
host-shell UI's Vite proxy can reach it
|
|
248
|
+
--list platform: list launchable platform packages as NDJSON
|
|
249
|
+
({name, dir} per line) and exit
|
|
250
|
+
--help Show this help and exit
|
|
251
|
+
|
|
252
|
+
Exit code is 1 if any test failed, 0 otherwise.
|
|
253
|
+
`
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
let e = error;
|
|
257
|
+
if (e !== undefined) {
|
|
258
|
+
return {
|
|
259
|
+
TAG: "Error",
|
|
260
|
+
_0: e + "\n\n" + `reventless-dev — Reventless dev CLI: GWT runner, domain graph, components, platform runner
|
|
261
|
+
|
|
262
|
+
USAGE:
|
|
263
|
+
reventless-dev run [--format=<fmt>] [--filter=<id>] [--stream] [--watch] [path...]
|
|
264
|
+
reventless-dev discover [--format=vscode] [path...]
|
|
265
|
+
reventless-dev watch [--format=<fmt>] [--filter=<id>] [path...]
|
|
266
|
+
reventless-dev platform [--format=vscode] [--backend=<b>] [--ui-ports] [path...]
|
|
267
|
+
reventless-dev platform --list [path...]
|
|
268
|
+
|
|
269
|
+
FORMATS:
|
|
270
|
+
human ANSI-coloured terminal output (default)
|
|
271
|
+
json Structured JSON envelope (--stream for NDJSON)
|
|
272
|
+
tap TAP 14 with YAML diagnostics
|
|
273
|
+
junit JUnit XML (single batch)
|
|
274
|
+
vscode NDJSON event stream for the VS Code Testing API
|
|
275
|
+
|
|
276
|
+
FLAGS:
|
|
277
|
+
--filter <id> Restrict execution to tests whose id contains <id>.
|
|
278
|
+
Repeatable.
|
|
279
|
+
--stream NDJSON streaming (json/vscode)
|
|
280
|
+
--watch Re-run on file change
|
|
281
|
+
--schema-version <v> Pin a JSON schema version for stable AI prompts
|
|
282
|
+
--backend <b> platform: storage backend for the spawned local platform
|
|
283
|
+
("memory" default, or "sqlite:<path>[?reset]")
|
|
284
|
+
--ui-ports platform: pin the platform to the fixed default ports
|
|
285
|
+
(4000/4001/3001/3002) instead of ephemeral ones, so the
|
|
286
|
+
host-shell UI's Vite proxy can reach it
|
|
287
|
+
--list platform: list launchable platform packages as NDJSON
|
|
288
|
+
({name, dir} per line) and exit
|
|
289
|
+
--help Show this help and exit
|
|
290
|
+
|
|
291
|
+
Exit code is 1 if any test failed, 0 otherwise.
|
|
292
|
+
`
|
|
293
|
+
};
|
|
294
|
+
} else {
|
|
295
|
+
return {
|
|
296
|
+
TAG: "Ok",
|
|
297
|
+
_0: {
|
|
298
|
+
subcommand: subcommand,
|
|
299
|
+
format: format,
|
|
300
|
+
stream: stream,
|
|
301
|
+
watch: watch,
|
|
302
|
+
filters: filters,
|
|
303
|
+
schemaVersion: schemaVersion,
|
|
304
|
+
roots: roots.length === 0 ? ["."] : roots,
|
|
305
|
+
backend: backend,
|
|
306
|
+
uiPorts: uiPorts,
|
|
307
|
+
listPlatforms: listPlatforms,
|
|
308
|
+
toolVersion: toolVersion,
|
|
309
|
+
paths: undefined
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function passesFilter(id, filters) {
|
|
316
|
+
if (filters.length === 0) {
|
|
317
|
+
return true;
|
|
318
|
+
} else {
|
|
319
|
+
return filters.some(f => id.includes(f));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let exnMessage = (function(e) {
|
|
324
|
+
if (e == null) return "unknown error"
|
|
325
|
+
if (typeof e === "string") return e
|
|
326
|
+
if (typeof e.message === "string" && e.message.length) return e.message
|
|
327
|
+
if (typeof e.RE_EXN_ID === "string") {
|
|
328
|
+
var id = e.RE_EXN_ID
|
|
329
|
+
var tag = id.lastIndexOf(".") >= 0 ? id.slice(id.lastIndexOf(".") + 1) : id
|
|
330
|
+
return (typeof e._1 === "string" && e._1.length) ? e._1 : tag
|
|
331
|
+
}
|
|
332
|
+
return "unknown error"
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
function raceWithTimeout(body, ms) {
|
|
336
|
+
let handleRef = {
|
|
337
|
+
contents: undefined
|
|
338
|
+
};
|
|
339
|
+
let timeout = new Promise((resolve, _reject) => {
|
|
340
|
+
handleRef.contents = Primitive_option.some(setTimeout(() => resolve(Outcome$ReventlessGwt.fail({
|
|
341
|
+
TAG: "Throw",
|
|
342
|
+
error: `timed out after ` + ms.toString() + `ms`,
|
|
343
|
+
stack: ""
|
|
344
|
+
})), ms));
|
|
345
|
+
});
|
|
346
|
+
return Promise.race([
|
|
347
|
+
body(),
|
|
348
|
+
timeout
|
|
349
|
+
]).then(o => {
|
|
350
|
+
let h = handleRef.contents;
|
|
351
|
+
if (h !== undefined) {
|
|
352
|
+
clearTimeout(Primitive_option.valFromOption(h));
|
|
353
|
+
}
|
|
354
|
+
return Promise.resolve(o);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
async function runEntry(entry) {
|
|
359
|
+
let start = performance.now();
|
|
360
|
+
let status = "Pass";
|
|
361
|
+
let mismatch;
|
|
362
|
+
let match = entry.status;
|
|
363
|
+
let exit = 0;
|
|
364
|
+
switch (match) {
|
|
365
|
+
case "Skipped" :
|
|
366
|
+
status = "Skip";
|
|
367
|
+
break;
|
|
368
|
+
case "Runnable" :
|
|
369
|
+
case "Only" :
|
|
370
|
+
exit = 1;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
if (exit === 1) {
|
|
374
|
+
try {
|
|
375
|
+
let deadline = Stdlib_Option.getOr(entry.timeout, 5000);
|
|
376
|
+
let outcome = await raceWithTimeout(entry.body, deadline);
|
|
377
|
+
if (outcome.TAG === "Ok") {
|
|
378
|
+
status = "Pass";
|
|
379
|
+
} else {
|
|
380
|
+
status = "Fail";
|
|
381
|
+
mismatch = outcome._0;
|
|
382
|
+
}
|
|
383
|
+
} catch (raw_exn) {
|
|
384
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
385
|
+
status = "Fail";
|
|
386
|
+
let err = exnMessage(exn);
|
|
387
|
+
let stack = ((e => (e && e.stack) || ""))(exn);
|
|
388
|
+
mismatch = {
|
|
389
|
+
TAG: "Throw",
|
|
390
|
+
error: err,
|
|
391
|
+
stack: stack
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
let durationMs = performance.now() - start;
|
|
396
|
+
return {
|
|
397
|
+
id: entry.id,
|
|
398
|
+
name: entry.name,
|
|
399
|
+
describePath: entry.describePath,
|
|
400
|
+
status: status,
|
|
401
|
+
durationMs: durationMs,
|
|
402
|
+
location: entry.location,
|
|
403
|
+
slice: entry.slice,
|
|
404
|
+
mismatch: mismatch,
|
|
405
|
+
skipReason: entry.status === "Skipped" ? "skipped at source" : undefined
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async function loadAndCollect(path) {
|
|
410
|
+
Collector$ReventlessGwt.activate();
|
|
411
|
+
Collector$ReventlessGwt.setCurrentFile(path);
|
|
412
|
+
try {
|
|
413
|
+
await Loader$ReventlessGwt.loadFile(path);
|
|
414
|
+
} catch (raw_exn) {
|
|
415
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
416
|
+
let msg = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(exn), Stdlib_JsExn.message), "import failed");
|
|
417
|
+
Collector$ReventlessGwt.push(undefined, undefined, undefined, `<file-load-error>`, () => Promise.resolve(Outcome$ReventlessGwt.fail({
|
|
418
|
+
TAG: "Throw",
|
|
419
|
+
error: "Failed to load " + path + ": " + msg,
|
|
420
|
+
stack: ""
|
|
421
|
+
})));
|
|
422
|
+
}
|
|
423
|
+
let entries = Collector$ReventlessGwt.drain();
|
|
424
|
+
Collector$ReventlessGwt.deactivate();
|
|
425
|
+
return entries;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
async function runFiles(opts, paths, onFileFinished, onTestStart, onTestFinished) {
|
|
429
|
+
let startedAt = dateNowIso();
|
|
430
|
+
let startTime = performance.now();
|
|
431
|
+
let files = [];
|
|
432
|
+
for (let i = 0, i_finish = paths.length; i < i_finish; ++i) {
|
|
433
|
+
let path = paths[i];
|
|
434
|
+
if (!Cancellation$ReventlessGwt.isCancelled()) {
|
|
435
|
+
let entries = await loadAndCollect(path);
|
|
436
|
+
let onlyActive = Collector$ReventlessGwt.hasOnly.contents;
|
|
437
|
+
let selected = entries.filter(e => {
|
|
438
|
+
let keepByOnly = onlyActive ? e.status === "Only" : true;
|
|
439
|
+
let qualifiedId = path + "::" + e.id;
|
|
440
|
+
let keepByFilter = passesFilter(e.id, opts.filters) || passesFilter(qualifiedId, opts.filters);
|
|
441
|
+
if (keepByOnly) {
|
|
442
|
+
return keepByFilter;
|
|
443
|
+
} else {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
let tests = [];
|
|
448
|
+
for (let j = 0, j_finish = selected.length; j < j_finish; ++j) {
|
|
449
|
+
if (Cancellation$ReventlessGwt.isCancelled()) {
|
|
450
|
+
let e = selected[j];
|
|
451
|
+
let r_id = e.id;
|
|
452
|
+
let r_name = e.name;
|
|
453
|
+
let r_describePath = e.describePath;
|
|
454
|
+
let r_location = e.location;
|
|
455
|
+
let r_slice = e.slice;
|
|
456
|
+
let r_skipReason = "cancelled";
|
|
457
|
+
let r = {
|
|
458
|
+
id: r_id,
|
|
459
|
+
name: r_name,
|
|
460
|
+
describePath: r_describePath,
|
|
461
|
+
status: "Skip",
|
|
462
|
+
durationMs: 0.0,
|
|
463
|
+
location: r_location,
|
|
464
|
+
slice: r_slice,
|
|
465
|
+
mismatch: undefined,
|
|
466
|
+
skipReason: r_skipReason
|
|
467
|
+
};
|
|
468
|
+
tests.push(r);
|
|
469
|
+
if (onTestFinished !== undefined) {
|
|
470
|
+
onTestFinished(path, r);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
let entry = selected[j];
|
|
474
|
+
if (onTestStart !== undefined) {
|
|
475
|
+
onTestStart(path, entry);
|
|
476
|
+
}
|
|
477
|
+
let r$1 = await runEntry(entry);
|
|
478
|
+
tests.push(r$1);
|
|
479
|
+
if (onTestFinished !== undefined) {
|
|
480
|
+
onTestFinished(path, r$1);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
let fr = {
|
|
485
|
+
path: path,
|
|
486
|
+
tests: tests
|
|
487
|
+
};
|
|
488
|
+
files.push(fr);
|
|
489
|
+
if (onFileFinished !== undefined) {
|
|
490
|
+
onFileFinished(fr);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
let durationMs = performance.now() - startTime;
|
|
495
|
+
let summary = RunnerTypes$ReventlessGwt.summaryOf(files, durationMs, startedAt);
|
|
496
|
+
return {
|
|
497
|
+
summary: summary,
|
|
498
|
+
files: files
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function emitResult(opts, r) {
|
|
503
|
+
let match = opts.format;
|
|
504
|
+
switch (match) {
|
|
505
|
+
case "Human" :
|
|
506
|
+
return FormatterHuman$ReventlessGwt.emit(r);
|
|
507
|
+
case "Json" :
|
|
508
|
+
if (opts.stream) {
|
|
509
|
+
return FormatterJson$ReventlessGwt.streamRunEnd(r);
|
|
510
|
+
} else {
|
|
511
|
+
return FormatterJson$ReventlessGwt.emit(r, opts.toolVersion, opts.schemaVersion);
|
|
512
|
+
}
|
|
513
|
+
case "Tap" :
|
|
514
|
+
return FormatterTap$ReventlessGwt.emit(r);
|
|
515
|
+
case "Junit" :
|
|
516
|
+
return FormatterJunit$ReventlessGwt.emit(r);
|
|
517
|
+
case "VsCode" :
|
|
518
|
+
return FormatterVsCode$ReventlessGwt.runEnd(r.summary);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function mergeScope(a, b) {
|
|
523
|
+
if (typeof a !== "object") {
|
|
524
|
+
return "RunAll";
|
|
525
|
+
}
|
|
526
|
+
if (typeof b !== "object") {
|
|
527
|
+
return "RunAll";
|
|
528
|
+
}
|
|
529
|
+
let seen = {};
|
|
530
|
+
let union = [];
|
|
531
|
+
a._0.concat(b._0).forEach(d => {
|
|
532
|
+
let match = seen[d];
|
|
533
|
+
if (match !== undefined) {
|
|
534
|
+
return;
|
|
535
|
+
} else {
|
|
536
|
+
seen[d] = true;
|
|
537
|
+
union.push(d);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
return {
|
|
542
|
+
TAG: "RunPackages",
|
|
543
|
+
_0: union
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function pathUnderDir(path, dir) {
|
|
548
|
+
return path.startsWith(dir.endsWith("/") ? dir : dir + "/");
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function scopeSubset(scope, allPaths) {
|
|
552
|
+
if (typeof scope !== "object") {
|
|
553
|
+
return allPaths;
|
|
554
|
+
}
|
|
555
|
+
let dirs = scope._0;
|
|
556
|
+
return allPaths.filter(p => dirs.some(d => pathUnderDir(p, d)));
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
async function runOnce(opts) {
|
|
560
|
+
let p = opts.paths;
|
|
561
|
+
let paths = p !== undefined ? p : await Discovery$ReventlessGwt.discover(opts.roots);
|
|
562
|
+
if (opts.format === "Json" && opts.stream) {
|
|
563
|
+
FormatterJson$ReventlessGwt.streamRunStart(opts.toolVersion, dateNowIso(), opts.schemaVersion);
|
|
564
|
+
}
|
|
565
|
+
let match = opts.format;
|
|
566
|
+
let match$1 = opts.stream;
|
|
567
|
+
let onFileFinished;
|
|
568
|
+
onFileFinished = match === "Json" && match$1 ? f => {
|
|
569
|
+
f.tests.forEach(FormatterJson$ReventlessGwt.streamTest);
|
|
570
|
+
FormatterJson$ReventlessGwt.streamFileFinished(f);
|
|
571
|
+
} : undefined;
|
|
572
|
+
let onTestStart = opts.format === "VsCode" ? (path, e) => FormatterVsCode$ReventlessGwt.testStart(path + "::" + e.id) : undefined;
|
|
573
|
+
let onTestFinished = opts.format === "VsCode" ? (path, t) => {
|
|
574
|
+
let id = path + "::" + t.id;
|
|
575
|
+
let match = t.status;
|
|
576
|
+
switch (match) {
|
|
577
|
+
case "Pass" :
|
|
578
|
+
return FormatterVsCode$ReventlessGwt.testPass(id, t.durationMs);
|
|
579
|
+
case "Fail" :
|
|
580
|
+
return FormatterVsCode$ReventlessGwt.testFail(t, id);
|
|
581
|
+
case "Skip" :
|
|
582
|
+
return FormatterVsCode$ReventlessGwt.testSkip(id, Stdlib_Option.getOr(t.skipReason, "skipped"));
|
|
583
|
+
}
|
|
584
|
+
} : undefined;
|
|
585
|
+
if (opts.format === "Json" && opts.stream) {
|
|
586
|
+
paths.forEach(FormatterJson$ReventlessGwt.streamFileStart);
|
|
587
|
+
} else if (opts.format === "VsCode") {
|
|
588
|
+
FormatterVsCode$ReventlessGwt.runStart(0, opts.filters);
|
|
589
|
+
}
|
|
590
|
+
let result = await runFiles(opts, paths, onFileFinished, onTestStart, onTestFinished);
|
|
591
|
+
emitResult(opts, result);
|
|
592
|
+
if (result.summary.failed > 0) {
|
|
593
|
+
return 1;
|
|
594
|
+
} else {
|
|
595
|
+
return 0;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
async function emitDomainAnalysis(pkgs) {
|
|
600
|
+
let plugins = LocalHost$ReventlessGwt.discover(pkgs.map(p => p.dir));
|
|
601
|
+
if (plugins.length === 0) {
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
let platformModulePath = LocalHost$ReventlessGwt.resolveLocalPlatform(plugins[0].packageDir);
|
|
605
|
+
if (platformModulePath === undefined) {
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
try {
|
|
609
|
+
let loaded = await LocalHost$ReventlessGwt.loadGraph(platformModulePath, plugins);
|
|
610
|
+
let definitions = loaded.structures.map(param => Platform_ComponentDefinitionsApi$ReventlessCore.encodePluginStructureEntry(param[0], param[1]));
|
|
611
|
+
let fingerprint = sha256(JSON.stringify(definitions));
|
|
612
|
+
if (Primitive_object.notequal(lastDomainHash.contents, fingerprint)) {
|
|
613
|
+
lastDomainHash.contents = fingerprint;
|
|
614
|
+
FormatterVsCode$ReventlessGwt.deadCode(DomainDeadCode$ReventlessGwt.analyze(loaded.structures));
|
|
615
|
+
FormatterVsCode$ReventlessGwt.graph(DomainGraph$ReventlessGwt.build(loaded.structures));
|
|
616
|
+
return FormatterVsCode$ReventlessGwt.definitions(definitions);
|
|
617
|
+
} else {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
} catch (exn) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
async function emitDiscovery(paths) {
|
|
626
|
+
FormatterVsCode$ReventlessGwt.discoverStart();
|
|
627
|
+
let fileTests = [];
|
|
628
|
+
for (let i = 0, i_finish = paths.length; i < i_finish; ++i) {
|
|
629
|
+
let path = paths[i];
|
|
630
|
+
let entries = await loadAndCollect(path);
|
|
631
|
+
let tests = entries.map(e => ({
|
|
632
|
+
id: e.id,
|
|
633
|
+
name: e.name,
|
|
634
|
+
describePath: e.describePath,
|
|
635
|
+
status: "Skip",
|
|
636
|
+
durationMs: 0.0,
|
|
637
|
+
location: e.location,
|
|
638
|
+
slice: e.slice,
|
|
639
|
+
mismatch: undefined,
|
|
640
|
+
skipReason: undefined
|
|
641
|
+
}));
|
|
642
|
+
fileTests.push([
|
|
643
|
+
path,
|
|
644
|
+
tests
|
|
645
|
+
]);
|
|
646
|
+
}
|
|
647
|
+
FormatterVsCode$ReventlessGwt.emitDiscoveryItems(fileTests);
|
|
648
|
+
let total = Stdlib_Array.reduce(fileTests, 0, (a, param) => a + param[1].length | 0);
|
|
649
|
+
let pkgs = PackageScan$ReventlessGwt.scan(paths);
|
|
650
|
+
FormatterVsCode$ReventlessGwt.packages(pkgs);
|
|
651
|
+
let comps = await ComponentScan$ReventlessGwt.scan(pkgs.map(p => p.dir));
|
|
652
|
+
FormatterVsCode$ReventlessGwt.components(comps);
|
|
653
|
+
FormatterVsCode$ReventlessGwt.discoverEnd(total);
|
|
654
|
+
return await emitDomainAnalysis(pkgs);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
async function runDiscover(opts) {
|
|
658
|
+
let paths = await Discovery$ReventlessGwt.discover(opts.roots);
|
|
659
|
+
await emitDiscovery(paths);
|
|
660
|
+
return 0;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
function startBuildWatchers(paths) {
|
|
664
|
+
Cancellation$ReventlessGwt.onCancel(ProcessManager$ReventlessGwt.killAll);
|
|
665
|
+
PackageScan$ReventlessGwt.scan(paths).forEach(pkg => {
|
|
666
|
+
if (WatcherProbe$ReventlessGwt.hasLiveWatcher(pkg.dir)) {
|
|
667
|
+
return FormatterVsCode$ReventlessGwt.buildExternal(pkg.dir);
|
|
668
|
+
}
|
|
669
|
+
let feed = BuildClassifier$ReventlessGwt.make(undefined, {
|
|
670
|
+
onStart: () => FormatterVsCode$ReventlessGwt.buildStart(pkg.dir),
|
|
671
|
+
onOk: ms => FormatterVsCode$ReventlessGwt.buildOk(pkg.dir, ms),
|
|
672
|
+
onFail: msg => FormatterVsCode$ReventlessGwt.buildFail(pkg.dir, msg)
|
|
673
|
+
});
|
|
674
|
+
ProcessManager$ReventlessGwt.spawnWatcher(pkg, (_dir, line) => feed(line));
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
async function runWatch(opts) {
|
|
679
|
+
let roots = opts.roots;
|
|
680
|
+
let discoveredPaths = {
|
|
681
|
+
contents: []
|
|
682
|
+
};
|
|
683
|
+
if (opts.format === "VsCode") {
|
|
684
|
+
let paths = await Discovery$ReventlessGwt.discover(roots);
|
|
685
|
+
discoveredPaths.contents = paths;
|
|
686
|
+
await emitDiscovery(paths);
|
|
687
|
+
startBuildWatchers(paths);
|
|
688
|
+
}
|
|
689
|
+
let currentWorker = {
|
|
690
|
+
contents: undefined
|
|
691
|
+
};
|
|
692
|
+
Cancellation$ReventlessGwt.onCancel(() => {
|
|
693
|
+
let w = currentWorker.contents;
|
|
694
|
+
if (w !== undefined) {
|
|
695
|
+
Primitive_option.valFromOption(w).terminate();
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
let runInWorker = paths => new Promise((resolve, _reject) => {
|
|
700
|
+
let w = new Nodeworker_threads.Worker(Worker$ReventlessGwt.runWorkerUrl, {
|
|
701
|
+
workerData: {
|
|
702
|
+
subcommand: opts.subcommand,
|
|
703
|
+
format: opts.format,
|
|
704
|
+
stream: opts.stream,
|
|
705
|
+
watch: opts.watch,
|
|
706
|
+
filters: opts.filters,
|
|
707
|
+
schemaVersion: opts.schemaVersion,
|
|
708
|
+
roots: opts.roots,
|
|
709
|
+
backend: opts.backend,
|
|
710
|
+
uiPorts: opts.uiPorts,
|
|
711
|
+
listPlatforms: opts.listPlatforms,
|
|
712
|
+
toolVersion: opts.toolVersion,
|
|
713
|
+
paths: paths
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
currentWorker.contents = Primitive_option.some(w);
|
|
717
|
+
let settled = {
|
|
718
|
+
contents: false
|
|
719
|
+
};
|
|
720
|
+
let settle = () => {
|
|
721
|
+
if (!settled.contents) {
|
|
722
|
+
settled.contents = true;
|
|
723
|
+
currentWorker.contents = undefined;
|
|
724
|
+
return resolve();
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
w.on("exit", _code => settle());
|
|
728
|
+
w.on("error", e => {
|
|
729
|
+
console.error("gwt run worker error:", e);
|
|
730
|
+
settle();
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
let pathsForScope = scope => {
|
|
734
|
+
if (opts.format === "VsCode") {
|
|
735
|
+
return scopeSubset(scope, discoveredPaths.contents);
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
let runInProgress = {
|
|
739
|
+
contents: false
|
|
740
|
+
};
|
|
741
|
+
let pendingScope = {
|
|
742
|
+
contents: undefined
|
|
743
|
+
};
|
|
744
|
+
let requestRun = async scope => {
|
|
745
|
+
if (runInProgress.contents) {
|
|
746
|
+
let s = pendingScope.contents;
|
|
747
|
+
pendingScope.contents = s !== undefined ? mergeScope(s, scope) : scope;
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
runInProgress.contents = true;
|
|
751
|
+
await runInWorker(pathsForScope(scope));
|
|
752
|
+
let drain = async () => {
|
|
753
|
+
let next = pendingScope.contents;
|
|
754
|
+
if (next !== undefined) {
|
|
755
|
+
pendingScope.contents = undefined;
|
|
756
|
+
await runInWorker(pathsForScope(next));
|
|
757
|
+
return await drain();
|
|
758
|
+
} else {
|
|
759
|
+
runInProgress.contents = false;
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
return await drain();
|
|
764
|
+
};
|
|
765
|
+
await requestRun("RunAll");
|
|
766
|
+
let rediscoverAndRun = async () => {
|
|
767
|
+
if (opts.format === "VsCode") {
|
|
768
|
+
discoveredPaths.contents = await Discovery$ReventlessGwt.discover(roots);
|
|
769
|
+
}
|
|
770
|
+
await requestRun("RunAll");
|
|
771
|
+
};
|
|
772
|
+
let rebuilding = {};
|
|
773
|
+
let refreshDiscovery = async () => {
|
|
774
|
+
let paths = await Discovery$ReventlessGwt.discover(roots);
|
|
775
|
+
discoveredPaths.contents = paths;
|
|
776
|
+
await emitDiscovery(paths);
|
|
777
|
+
startBuildWatchers(paths);
|
|
778
|
+
await requestRun("RunAll");
|
|
779
|
+
};
|
|
780
|
+
let affectedScope = path => {
|
|
781
|
+
if (opts.format !== "VsCode") {
|
|
782
|
+
return "RunAll";
|
|
783
|
+
}
|
|
784
|
+
let abs = Nodepath.resolve(path);
|
|
785
|
+
let pkg = PackageScan$ReventlessGwt.findOwning(Nodepath.dirname(abs));
|
|
786
|
+
if (pkg !== undefined && discoveredPaths.contents.some(p => pathUnderDir(p, pkg.dir))) {
|
|
787
|
+
return {
|
|
788
|
+
TAG: "RunPackages",
|
|
789
|
+
_0: [pkg.dir]
|
|
790
|
+
};
|
|
791
|
+
} else {
|
|
792
|
+
return "RunAll";
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
Watch$ReventlessGwt.start(roots, (event, path) => {
|
|
796
|
+
if (opts.format === "VsCode" && Watch$ReventlessGwt.isStructuralSource(event, path)) {
|
|
797
|
+
let pkg = PackageScan$ReventlessGwt.findOwning(path);
|
|
798
|
+
if (pkg !== undefined) {
|
|
799
|
+
if (Stdlib_Option.getOr(rebuilding[pkg.dir], false)) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
rebuilding[pkg.dir] = true;
|
|
803
|
+
let t0 = Date.now();
|
|
804
|
+
FormatterVsCode$ReventlessGwt.buildStart(pkg.dir);
|
|
805
|
+
let sawError = {
|
|
806
|
+
contents: false
|
|
807
|
+
};
|
|
808
|
+
let feed = BuildClassifier$ReventlessGwt.make(undefined, {
|
|
809
|
+
onStart: () => {},
|
|
810
|
+
onOk: _ms => {},
|
|
811
|
+
onFail: msg => {
|
|
812
|
+
sawError.contents = true;
|
|
813
|
+
FormatterVsCode$ReventlessGwt.buildFail(pkg.dir, msg);
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
return ProcessManager$ReventlessGwt.cleanRebuild(pkg, (_dir, line) => feed(line), ok => {
|
|
817
|
+
rebuilding[pkg.dir] = false;
|
|
818
|
+
if (ok) {
|
|
819
|
+
FormatterVsCode$ReventlessGwt.buildOk(pkg.dir, Date.now() - t0);
|
|
820
|
+
} else if (!sawError.contents) {
|
|
821
|
+
FormatterVsCode$ReventlessGwt.buildFail(pkg.dir, "clean rebuild failed");
|
|
822
|
+
}
|
|
823
|
+
rediscoverAndRun();
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
requestRun("RunAll");
|
|
827
|
+
return;
|
|
828
|
+
} else {
|
|
829
|
+
if (opts.format === "VsCode" && event === "Add" && path.endsWith(".res")) {
|
|
830
|
+
refreshDiscovery();
|
|
831
|
+
} else {
|
|
832
|
+
requestRun(affectedScope(path));
|
|
833
|
+
}
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
await new Promise((resolve, _reject) => Cancellation$ReventlessGwt.onCancel(() => resolve()));
|
|
838
|
+
return 0;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
async function runPlatform(opts) {
|
|
842
|
+
let callbacks = opts.format === "VsCode" ? ({
|
|
843
|
+
onStart: FormatterVsCode$ReventlessGwt.platformStart,
|
|
844
|
+
onReady: FormatterVsCode$ReventlessGwt.platformReady,
|
|
845
|
+
onDomainEvent: FormatterVsCode$ReventlessGwt.domainEvent,
|
|
846
|
+
onLog: FormatterVsCode$ReventlessGwt.platformLog,
|
|
847
|
+
onStop: FormatterVsCode$ReventlessGwt.platformStop
|
|
848
|
+
}) : ({
|
|
849
|
+
onStart: ($$package, param, domainPort, param$1) => {
|
|
850
|
+
console.log(`▶ platform ` + $$package + ` starting (domain http://localhost:` + domainPort.toString() + `)`);
|
|
851
|
+
},
|
|
852
|
+
onReady: domainEndpoint => {
|
|
853
|
+
console.log(`✓ platform ready — ` + domainEndpoint);
|
|
854
|
+
},
|
|
855
|
+
onDomainEvent: json => {
|
|
856
|
+
console.log("· event " + JSON.stringify(json));
|
|
857
|
+
},
|
|
858
|
+
onLog: line => {
|
|
859
|
+
console.log(line);
|
|
860
|
+
},
|
|
861
|
+
onStop: code => {
|
|
862
|
+
console.log(`■ platform stopped (code ` + Stdlib_Option.mapOr(code, "?", c => c.toString()) + `)`);
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
return await PlatformRunner$ReventlessGwt.run(opts.roots, opts.backend, opts.uiPorts, callbacks);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
async function listPlatforms(opts) {
|
|
869
|
+
let pkgs = await PlatformScan$ReventlessGwt.scan(opts.roots);
|
|
870
|
+
pkgs.forEach(pkg => {
|
|
871
|
+
let obj = Object.fromEntries([
|
|
872
|
+
[
|
|
873
|
+
"name",
|
|
874
|
+
pkg.name
|
|
875
|
+
],
|
|
876
|
+
[
|
|
877
|
+
"dir",
|
|
878
|
+
pkg.dir
|
|
879
|
+
]
|
|
880
|
+
]);
|
|
881
|
+
console.log(JSON.stringify(obj));
|
|
882
|
+
});
|
|
883
|
+
return 0;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
async function main() {
|
|
887
|
+
Cancellation$ReventlessGwt.install();
|
|
888
|
+
let args = process.argv;
|
|
889
|
+
let msg = parseArgv(args);
|
|
890
|
+
if (msg.TAG === "Ok") {
|
|
891
|
+
let opts = msg._0;
|
|
892
|
+
if (opts.format === "VsCode") {
|
|
893
|
+
FormatterVsCode$ReventlessGwt.hello();
|
|
894
|
+
}
|
|
895
|
+
let match = opts.subcommand;
|
|
896
|
+
switch (match) {
|
|
897
|
+
case "Run" :
|
|
898
|
+
return await runOnce(opts);
|
|
899
|
+
case "Discover" :
|
|
900
|
+
return await runDiscover(opts);
|
|
901
|
+
case "Watch" :
|
|
902
|
+
return await runWatch(opts);
|
|
903
|
+
case "Platform" :
|
|
904
|
+
if (opts.listPlatforms) {
|
|
905
|
+
return await listPlatforms(opts);
|
|
906
|
+
} else {
|
|
907
|
+
return await runPlatform(opts);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
} else {
|
|
911
|
+
console.error(msg._0);
|
|
912
|
+
if (args.some(a => a === "--help" ? true : a === "-h")) {
|
|
913
|
+
return 0;
|
|
914
|
+
} else {
|
|
915
|
+
return 2;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
let defaultTimeoutMs = 5000;
|
|
921
|
+
|
|
922
|
+
export {
|
|
923
|
+
toolVersion,
|
|
924
|
+
sha256,
|
|
925
|
+
lastDomainHash,
|
|
926
|
+
dateNowIso,
|
|
927
|
+
parseFormat,
|
|
928
|
+
defaultRoots,
|
|
929
|
+
help,
|
|
930
|
+
parseArgv,
|
|
931
|
+
passesFilter,
|
|
932
|
+
exnMessage,
|
|
933
|
+
defaultTimeoutMs,
|
|
934
|
+
raceWithTimeout,
|
|
935
|
+
runEntry,
|
|
936
|
+
loadAndCollect,
|
|
937
|
+
runFiles,
|
|
938
|
+
emitResult,
|
|
939
|
+
mergeScope,
|
|
940
|
+
pathUnderDir,
|
|
941
|
+
scopeSubset,
|
|
942
|
+
runOnce,
|
|
943
|
+
emitDomainAnalysis,
|
|
944
|
+
emitDiscovery,
|
|
945
|
+
runDiscover,
|
|
946
|
+
startBuildWatchers,
|
|
947
|
+
runWatch,
|
|
948
|
+
runPlatform,
|
|
949
|
+
listPlatforms,
|
|
950
|
+
main,
|
|
951
|
+
}
|
|
952
|
+
/* node:path Not a pure module */
|