@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
package/src/Collector.res DELETED
@@ -1,222 +0,0 @@
1
- // Module-level collector used by the CLI runner.
2
- //
3
- // When the CLI loads a test file via dynamic import, each `describe`/`test`
4
- // call routes through `Bind` or `JestBind` and pushes an entry into this
5
- // collector. After the import resolves (all registrations complete), the CLI
6
- // drains the entries, executes each body asynchronously, and feeds the results
7
- // into a formatter.
8
- //
9
- // Activation is toggled by the CLI — when inactive, `JestBind` falls back to
10
- // Jest globals, so existing Jest test runs are unaffected.
11
-
12
- type status = Skipped | Runnable | Only
13
-
14
- // Source location shape is shared with `RunnerHook` so this collector can be
15
- // exposed as a `RunnerHook.sink` without a conversion layer.
16
- type location = RunnerHook.location
17
-
18
- type entry = {
19
- id: string,
20
- name: string,
21
- describePath: array<string>,
22
- slice: option<string>,
23
- body: unit => promise<Outcome.outcome>,
24
- status: status,
25
- location: option<location>,
26
- // Per-test deadline in ms (from `~timeout` on `testPromise`). `None` = use the
27
- // runner default. The CLI runner races the body against this; the Jest arm
28
- // passes it to Jest's own timeout instead.
29
- timeout: option<int>,
30
- }
31
-
32
- let active = ref(false)
33
- let describeStack: ref<array<string>> = ref([])
34
- let entries: ref<array<entry>> = ref([])
35
- let hasOnly = ref(false)
36
- let skipNext = ref(false)
37
- let onlyNext = ref(false)
38
- let skipDepth = ref(0)
39
- let currentFile: ref<option<string>> = ref(None)
40
-
41
- let activate = () => {
42
- active := true
43
- describeStack := []
44
- entries := []
45
- hasOnly := false
46
- skipNext := false
47
- onlyNext := false
48
- // Reset the skip nesting depth too: a throwing `xdescribe` body in a prior
49
- // file could otherwise leave it > 0, silently skipping every test in every
50
- // subsequently loaded file.
51
- skipDepth := 0
52
- currentFile := None
53
- }
54
-
55
- let deactivate = () => active := false
56
- let isActive = () => active.contents
57
-
58
- let setCurrentFile = path => currentFile := Some(path)
59
- let getCurrentFile = () => currentFile.contents
60
-
61
- let markSkipNext = () => skipNext := true
62
- let markOnlyNext = () => {
63
- onlyNext := true
64
- hasOnly := true
65
- }
66
-
67
- let pushDescribe = (label: string, body: unit => unit) => {
68
- describeStack := Array.concat(describeStack.contents, [label])
69
- body()
70
- let ds = describeStack.contents
71
- describeStack := ds->Array.slice(~start=0, ~end=ds->Array.length - 1)
72
- }
73
-
74
- let buildId = (describePath, name) => {
75
- let prefix = describePath->Array.join("::")
76
- prefix == "" ? name : prefix ++ "::" ++ name
77
- }
78
-
79
- let push = (
80
- ~slice=?,
81
- ~location=?,
82
- ~timeout=?,
83
- name: string,
84
- body: unit => promise<Outcome.outcome>,
85
- ) => {
86
- let status = if skipDepth.contents > 0 {
87
- Skipped
88
- } else if skipNext.contents {
89
- skipNext := false
90
- Skipped
91
- } else if onlyNext.contents {
92
- onlyNext := false
93
- Only
94
- } else {
95
- Runnable
96
- }
97
- let describePath = describeStack.contents
98
- let id = buildId(describePath, name)
99
- let entry = {
100
- id,
101
- name,
102
- describePath,
103
- slice,
104
- body,
105
- status,
106
- location,
107
- timeout,
108
- }
109
- entries.contents->Array.push(entry)
110
- }
111
-
112
- // A `todo` placeholder: a spec-less slice still ships a discoverable, compiling
113
- // `_GWT.res`. Register it as a Skipped entry with a no-op passing body so the
114
- // CLI runner lists it without executing or failing.
115
- let pushTodo = (name: string) => {
116
- let describePath = describeStack.contents
117
- let id = buildId(describePath, name)
118
- let entry = {
119
- id,
120
- name,
121
- describePath,
122
- slice: None,
123
- body: () => Promise.resolve(Outcome.pass),
124
- status: Skipped,
125
- location: None,
126
- timeout: None,
127
- }
128
- entries.contents->Array.push(entry)
129
- }
130
-
131
- let drain = () => {
132
- let result = entries.contents
133
- entries := []
134
- describeStack := []
135
- result
136
- }
137
-
138
- // Parse a single V8 stack frame line like:
139
- // " at body (/abs/path/File.res.mjs:42:13)"
140
- // " at /abs/path/File.res.mjs:42:13"
141
- // Returns (file, line, column) if the frame belongs to a non-internal user file.
142
- let parseFrame = (frame: string): option<location> => {
143
- let trimmed = frame->String.trim
144
- let body = if String.startsWith(trimmed, "at ") {
145
- String.slice(trimmed, ~start=3, ~end=String.length(trimmed))
146
- } else {
147
- trimmed
148
- }
149
- let withLoc = switch String.lastIndexOf(body, "(") {
150
- | -1 => body
151
- | i =>
152
- let rest = String.slice(body, ~start=i + 1, ~end=String.length(body))
153
- switch String.lastIndexOf(rest, ")") {
154
- | -1 => rest
155
- | j => String.slice(rest, ~start=0, ~end=j)
156
- }
157
- }
158
- let parts = withLoc->String.split(":")
159
- let n = parts->Array.length
160
- if n < 3 {
161
- None
162
- } else {
163
- let col = parts->Array.getUnsafe(n - 1)->Int.fromString
164
- let line = parts->Array.getUnsafe(n - 2)->Int.fromString
165
- let file =
166
- parts->Array.slice(~start=0, ~end=n - 2)->Array.join(":")
167
- let file = if String.startsWith(file, "file://") {
168
- String.slice(file, ~start=7, ~end=String.length(file))
169
- } else {
170
- file
171
- }
172
- // Strip the Loader's `?t=N` cache-busting query so locations point at the
173
- // real file path.
174
- let file = switch String.indexOf(file, "?") {
175
- | -1 => file
176
- | q => String.slice(file, ~start=0, ~end=q)
177
- }
178
- switch (line, col) {
179
- | (Some(l), Some(c)) => Some({file, line: l, column: c})
180
- | _ => None
181
- }
182
- }
183
- }
184
-
185
- // Walk a captured stack and return the first frame that lives in a test
186
- // file outside the reventless-gwt package itself.
187
- let captureLocation = (skip: int): option<location> => {
188
- let stack: option<string> = %raw(`(new Error()).stack`)
189
- switch stack {
190
- | None => None
191
- | Some(s) =>
192
- let lines = s->String.split("\n")
193
- let total = lines->Array.length
194
- // Skip the "Error" header, plus `skip` internal frames.
195
- let rec find = i =>
196
- if i >= total {
197
- None
198
- } else {
199
- let frame = lines->Array.getUnsafe(i)
200
- switch parseFrame(frame) {
201
- | Some(loc)
202
- if !(loc.file->String.includes("reventless-gwt/src/")) &&
203
- !(loc.file->String.includes("node_modules/")) =>
204
- Some(loc)
205
- | _ => find(i + 1)
206
- }
207
- }
208
- find(skip + 1)
209
- }
210
- }
211
-
212
- // Expose this collector as a `RunnerHook.sink` so a driver can route `JestBind`
213
- // registrations here. `captureLocation` is bound directly (no wrapper closure)
214
- // so the stack depth `JestBind` skips when capturing the caller's location is
215
- // unchanged from calling `captureLocation` inline.
216
- let asSink: RunnerHook.sink = {
217
- describe: pushDescribe,
218
- todo: pushTodo,
219
- captureLocation,
220
- test: (~slice=?, ~location=?, ~timeout=?, name, body) =>
221
- push(~slice?, ~location?, ~timeout?, name, body),
222
- }
@@ -1,228 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
4
- import * as Outcome$ReventlessGwt from "./Outcome.res.mjs";
5
-
6
- let active = {
7
- contents: false
8
- };
9
-
10
- let describeStack = {
11
- contents: []
12
- };
13
-
14
- let entries = {
15
- contents: []
16
- };
17
-
18
- let hasOnly = {
19
- contents: false
20
- };
21
-
22
- let skipNext = {
23
- contents: false
24
- };
25
-
26
- let onlyNext = {
27
- contents: false
28
- };
29
-
30
- let skipDepth = {
31
- contents: 0
32
- };
33
-
34
- let currentFile = {
35
- contents: undefined
36
- };
37
-
38
- function activate() {
39
- active.contents = true;
40
- describeStack.contents = [];
41
- entries.contents = [];
42
- hasOnly.contents = false;
43
- skipNext.contents = false;
44
- onlyNext.contents = false;
45
- skipDepth.contents = 0;
46
- currentFile.contents = undefined;
47
- }
48
-
49
- function deactivate() {
50
- active.contents = false;
51
- }
52
-
53
- function isActive() {
54
- return active.contents;
55
- }
56
-
57
- function setCurrentFile(path) {
58
- currentFile.contents = path;
59
- }
60
-
61
- function getCurrentFile() {
62
- return currentFile.contents;
63
- }
64
-
65
- function markSkipNext() {
66
- skipNext.contents = true;
67
- }
68
-
69
- function markOnlyNext() {
70
- onlyNext.contents = true;
71
- hasOnly.contents = true;
72
- }
73
-
74
- function pushDescribe(label, body) {
75
- describeStack.contents = describeStack.contents.concat([label]);
76
- body();
77
- let ds = describeStack.contents;
78
- describeStack.contents = ds.slice(0, ds.length - 1 | 0);
79
- }
80
-
81
- function buildId(describePath, name) {
82
- let prefix = describePath.join("::");
83
- if (prefix === "") {
84
- return name;
85
- } else {
86
- return prefix + "::" + name;
87
- }
88
- }
89
-
90
- function push(slice, location, timeout, name, body) {
91
- let status = skipDepth.contents > 0 ? "Skipped" : (
92
- skipNext.contents ? (skipNext.contents = false, "Skipped") : (
93
- onlyNext.contents ? (onlyNext.contents = false, "Only") : "Runnable"
94
- )
95
- );
96
- let describePath = describeStack.contents;
97
- let id = buildId(describePath, name);
98
- let entry = {
99
- id: id,
100
- name: name,
101
- describePath: describePath,
102
- slice: slice,
103
- body: body,
104
- status: status,
105
- location: location,
106
- timeout: timeout
107
- };
108
- entries.contents.push(entry);
109
- }
110
-
111
- function pushTodo(name) {
112
- let describePath = describeStack.contents;
113
- let id = buildId(describePath, name);
114
- let entry_body = () => Promise.resolve(Outcome$ReventlessGwt.pass);
115
- let entry = {
116
- id: id,
117
- name: name,
118
- describePath: describePath,
119
- slice: undefined,
120
- body: entry_body,
121
- status: "Skipped",
122
- location: undefined,
123
- timeout: undefined
124
- };
125
- entries.contents.push(entry);
126
- }
127
-
128
- function drain() {
129
- let result = entries.contents;
130
- entries.contents = [];
131
- describeStack.contents = [];
132
- return result;
133
- }
134
-
135
- function parseFrame(frame) {
136
- let trimmed = frame.trim();
137
- let body = trimmed.startsWith("at ") ? trimmed.slice(3, trimmed.length) : trimmed;
138
- let i = body.lastIndexOf("(");
139
- let withLoc;
140
- if (i !== -1) {
141
- let rest = body.slice(i + 1 | 0, body.length);
142
- let j = rest.lastIndexOf(")");
143
- withLoc = j !== -1 ? rest.slice(0, j) : rest;
144
- } else {
145
- withLoc = body;
146
- }
147
- let parts = withLoc.split(":");
148
- let n = parts.length;
149
- if (n < 3) {
150
- return;
151
- }
152
- let col = Stdlib_Int.fromString(parts[n - 1 | 0], undefined);
153
- let line = Stdlib_Int.fromString(parts[n - 2 | 0], undefined);
154
- let file = parts.slice(0, n - 2 | 0).join(":");
155
- let file$1 = file.startsWith("file://") ? file.slice(7, file.length) : file;
156
- let q = file$1.indexOf("?");
157
- let file$2 = q !== -1 ? file$1.slice(0, q) : file$1;
158
- if (line !== undefined && col !== undefined) {
159
- return {
160
- file: file$2,
161
- line: line,
162
- column: col
163
- };
164
- }
165
- }
166
-
167
- function captureLocation(skip) {
168
- let stack = ((new Error()).stack);
169
- if (stack === undefined) {
170
- return;
171
- }
172
- let lines = stack.split("\n");
173
- let total = lines.length;
174
- let _i = skip + 1 | 0;
175
- while (true) {
176
- let i = _i;
177
- if (i >= total) {
178
- return;
179
- }
180
- let frame = lines[i];
181
- let loc = parseFrame(frame);
182
- if (loc !== undefined) {
183
- if (!loc.file.includes("reventless-gwt/src/") && !loc.file.includes("node_modules/")) {
184
- return loc;
185
- }
186
- _i = i + 1 | 0;
187
- continue;
188
- }
189
- _i = i + 1 | 0;
190
- continue;
191
- };
192
- }
193
-
194
- let asSink_test = push;
195
-
196
- let asSink = {
197
- describe: pushDescribe,
198
- todo: pushTodo,
199
- captureLocation: captureLocation,
200
- test: asSink_test
201
- };
202
-
203
- export {
204
- active,
205
- describeStack,
206
- entries,
207
- hasOnly,
208
- skipNext,
209
- onlyNext,
210
- skipDepth,
211
- currentFile,
212
- activate,
213
- deactivate,
214
- isActive,
215
- setCurrentFile,
216
- getCurrentFile,
217
- markSkipNext,
218
- markOnlyNext,
219
- pushDescribe,
220
- buildId,
221
- push,
222
- pushTodo,
223
- drain,
224
- parseFrame,
225
- captureLocation,
226
- asSink,
227
- }
228
- /* No side effect */
@@ -1,77 +0,0 @@
1
- // Pure helpers mapping a file path to its Reventless component {kind, name}
2
- // using the folder-name convention (the same vocabulary the plugin generator
3
- // classifies by). Shared by the discovery `item` annotation (FormatterVsCode)
4
- // and the src/ component inventory (ComponentScan). No I/O — path strings only.
5
-
6
- type component = {kind: string, name: string}
7
-
8
- // The folder→kind vocabulary and body-file suffixes are the single source in
9
- // `Reventless.ComponentKind` (shared with the plugin generator). Deriving from it
10
- // means the gwt discovery recognises exactly the folder spellings the generator
11
- // classifies — including the plural / short forms this file used to miss.
12
- module Kind = Reventless.ComponentKind
13
-
14
- // Strip a body-file suffix (longest first) to recover the spec stem, so spec and
15
- // body files in one folder collapse to the same component name.
16
- let stripBody = (stem: string) =>
17
- switch Kind.bodySuffixes->Array.find(suf => String.endsWith(stem, suf)) {
18
- | Some(suf) => String.slice(stem, ~start=0, ~end=String.length(stem) - String.length(suf))
19
- | None => stem
20
- }
21
-
22
- // Strip the GWT test marker (`_GWT` / `GwtTest` / `Gwt`) — the three shapes
23
- // `Discovery.isGwtTestFile` recognises.
24
- let stripGwt = (stem: string) =>
25
- if String.endsWith(stem, "_GWT") {
26
- String.slice(stem, ~start=0, ~end=String.length(stem) - 4)
27
- } else if String.endsWith(stem, "GwtTest") {
28
- String.slice(stem, ~start=0, ~end=String.length(stem) - 7)
29
- } else if String.endsWith(stem, "Gwt") {
30
- String.slice(stem, ~start=0, ~end=String.length(stem) - 3)
31
- } else {
32
- stem
33
- }
34
-
35
- // Last path segment (POSIX paths — the monorepo's tooling normalises to `/`).
36
- let basename = (path: string) =>
37
- switch path->String.split("/")->Array.last {
38
- | Some(s) => s
39
- | None => path
40
- }
41
-
42
- // Parent folder name (the segment before the filename), if any.
43
- let parentFolder = (path: string) => {
44
- let segs = path->String.split("/")
45
- let n = segs->Array.length
46
- n >= 2 ? segs->Array.get(n - 2) : None
47
- }
48
-
49
- // Strip the compiled / source extension from a filename.
50
- let stem = (filename: string) =>
51
- if String.endsWith(filename, ".res.mjs") {
52
- String.slice(filename, ~start=0, ~end=String.length(filename) - 8)
53
- } else if String.endsWith(filename, ".res.js") {
54
- String.slice(filename, ~start=0, ~end=String.length(filename) - 7)
55
- } else if String.endsWith(filename, ".resi") {
56
- String.slice(filename, ~start=0, ~end=String.length(filename) - 5)
57
- } else if String.endsWith(filename, ".res") {
58
- String.slice(filename, ~start=0, ~end=String.length(filename) - 4)
59
- } else {
60
- filename
61
- }
62
-
63
- // {kind, name} for a discovered GWT test file, or None if it isn't inside a
64
- // recognised kind folder. `kind` is the canonical folder name, so a plural
65
- // folder (`Aggregates/`) reports the same kind as its singular form.
66
- let componentOfTestFile = (path: string): option<component> =>
67
- switch parentFolder(path)->Option.flatMap(Kind.folderToKind) {
68
- | Some(kind) => Some({kind: Kind.folderName(kind), name: path->basename->stem->stripGwt->stripBody})
69
- | None => None
70
- }
71
-
72
- // {kind, name} for a src/ component file (spec or body), or None.
73
- let componentOfSrcFile = (path: string): option<component> =>
74
- switch parentFolder(path)->Option.flatMap(Kind.folderToKind) {
75
- | Some(kind) => Some({kind: Kind.folderName(kind), name: path->basename->stem->stripBody})
76
- | None => None
77
- }
@@ -1,91 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
4
- import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
- import * as ComponentKind$Reventless from "@reventlessdev/reventless-spec/src/components/ComponentKind.res.mjs";
6
-
7
- function stripBody(stem) {
8
- let suf = ComponentKind$Reventless.bodySuffixes.find(suf => stem.endsWith(suf));
9
- if (suf !== undefined) {
10
- return stem.slice(0, stem.length - suf.length | 0);
11
- } else {
12
- return stem;
13
- }
14
- }
15
-
16
- function stripGwt(stem) {
17
- if (stem.endsWith("_GWT")) {
18
- return stem.slice(0, stem.length - 4 | 0);
19
- } else if (stem.endsWith("GwtTest")) {
20
- return stem.slice(0, stem.length - 7 | 0);
21
- } else if (stem.endsWith("Gwt")) {
22
- return stem.slice(0, stem.length - 3 | 0);
23
- } else {
24
- return stem;
25
- }
26
- }
27
-
28
- function basename(path) {
29
- let s = Stdlib_Array.last(path.split("/"));
30
- if (s !== undefined) {
31
- return s;
32
- } else {
33
- return path;
34
- }
35
- }
36
-
37
- function parentFolder(path) {
38
- let segs = path.split("/");
39
- let n = segs.length;
40
- if (n >= 2) {
41
- return segs[n - 2 | 0];
42
- }
43
- }
44
-
45
- function stem(filename) {
46
- if (filename.endsWith(".res.mjs")) {
47
- return filename.slice(0, filename.length - 8 | 0);
48
- } else if (filename.endsWith(".res.js")) {
49
- return filename.slice(0, filename.length - 7 | 0);
50
- } else if (filename.endsWith(".resi")) {
51
- return filename.slice(0, filename.length - 5 | 0);
52
- } else if (filename.endsWith(".res")) {
53
- return filename.slice(0, filename.length - 4 | 0);
54
- } else {
55
- return filename;
56
- }
57
- }
58
-
59
- function componentOfTestFile(path) {
60
- let kind = Stdlib_Option.flatMap(parentFolder(path), ComponentKind$Reventless.folderToKind);
61
- if (kind !== undefined) {
62
- return {
63
- kind: ComponentKind$Reventless.folderName(kind),
64
- name: stripBody(stripGwt(stem(basename(path))))
65
- };
66
- }
67
- }
68
-
69
- function componentOfSrcFile(path) {
70
- let kind = Stdlib_Option.flatMap(parentFolder(path), ComponentKind$Reventless.folderToKind);
71
- if (kind !== undefined) {
72
- return {
73
- kind: ComponentKind$Reventless.folderName(kind),
74
- name: stripBody(stem(basename(path)))
75
- };
76
- }
77
- }
78
-
79
- let Kind;
80
-
81
- export {
82
- Kind,
83
- stripBody,
84
- stripGwt,
85
- basename,
86
- parentFolder,
87
- stem,
88
- componentOfTestFile,
89
- componentOfSrcFile,
90
- }
91
- /* No side effect */