@reventlessdev/reventless-gwt 1.0.0-alpha.74

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 (172) hide show
  1. package/CHANGELOG.md +698 -0
  2. package/LICENSE +202 -0
  3. package/bin/reventless-dev.mjs +21 -0
  4. package/package.json +54 -0
  5. package/rescript.json +36 -0
  6. package/src/.gwtignore +10 -0
  7. package/src/Automation_GWT.res +207 -0
  8. package/src/Automation_GWT.res.mjs +160 -0
  9. package/src/Behavior_GWT.res +603 -0
  10. package/src/Behavior_GWT.res.mjs +426 -0
  11. package/src/Bind.res +29 -0
  12. package/src/Bind.res.mjs +22 -0
  13. package/src/BuildClassifier.res +137 -0
  14. package/src/BuildClassifier.res.mjs +136 -0
  15. package/src/Cancellation.res +31 -0
  16. package/src/Cancellation.res.mjs +45 -0
  17. package/src/ChildProcess.res +84 -0
  18. package/src/ChildProcess.res.mjs +92 -0
  19. package/src/Cli.res +671 -0
  20. package/src/Cli.res.mjs +754 -0
  21. package/src/Collector.res +201 -0
  22. package/src/Collector.res.mjs +215 -0
  23. package/src/ComponentMeta.res +104 -0
  24. package/src/ComponentMeta.res.mjs +120 -0
  25. package/src/ComponentScan.res +103 -0
  26. package/src/ComponentScan.res.mjs +105 -0
  27. package/src/Delegate_GWT.res +303 -0
  28. package/src/Delegate_GWT.res.mjs +372 -0
  29. package/src/Diff.res +91 -0
  30. package/src/Diff.res.mjs +98 -0
  31. package/src/Discovery.res +105 -0
  32. package/src/Discovery.res.mjs +103 -0
  33. package/src/DomainDeadCode.res +93 -0
  34. package/src/DomainDeadCode.res.mjs +69 -0
  35. package/src/DomainGraph.res +0 -0
  36. package/src/DomainGraph.res.mjs +0 -0
  37. package/src/EventMapping_GWT.res +29 -0
  38. package/src/EventMapping_GWT.res.mjs +44 -0
  39. package/src/Filter.res +36 -0
  40. package/src/Filter.res.mjs +40 -0
  41. package/src/Flow_GWT.res +664 -0
  42. package/src/Flow_GWT.res.mjs +604 -0
  43. package/src/FormatterHuman.res +138 -0
  44. package/src/FormatterHuman.res.mjs +122 -0
  45. package/src/FormatterJson.res +257 -0
  46. package/src/FormatterJson.res.mjs +320 -0
  47. package/src/FormatterJunit.res +93 -0
  48. package/src/FormatterJunit.res.mjs +90 -0
  49. package/src/FormatterTap.res +139 -0
  50. package/src/FormatterTap.res.mjs +149 -0
  51. package/src/FormatterVsCode.res +362 -0
  52. package/src/FormatterVsCode.res.mjs +564 -0
  53. package/src/Hint.res +119 -0
  54. package/src/Hint.res.mjs +124 -0
  55. package/src/InboundTranslation_GWT.res +83 -0
  56. package/src/InboundTranslation_GWT.res.mjs +94 -0
  57. package/src/JestBind.res +70 -0
  58. package/src/JestBind.res.mjs +63 -0
  59. package/src/Loader.res +24 -0
  60. package/src/Loader.res.mjs +23 -0
  61. package/src/LocalHost.res +135 -0
  62. package/src/LocalHost.res.mjs +127 -0
  63. package/src/Mapping_GWT.res +474 -0
  64. package/src/Mapping_GWT.res.mjs +322 -0
  65. package/src/MultiSourceProjection_GWT.res +316 -0
  66. package/src/MultiSourceProjection_GWT.res.mjs +354 -0
  67. package/src/OutboundTranslation_GWT.res +238 -0
  68. package/src/OutboundTranslation_GWT.res.mjs +186 -0
  69. package/src/Outcome.res +161 -0
  70. package/src/Outcome.res.mjs +140 -0
  71. package/src/PackageScan.res +80 -0
  72. package/src/PackageScan.res.mjs +81 -0
  73. package/src/PlatformRunner.res +160 -0
  74. package/src/PlatformRunner.res.mjs +155 -0
  75. package/src/PlatformScan.res +138 -0
  76. package/src/PlatformScan.res.mjs +131 -0
  77. package/src/ProcessManager.res +91 -0
  78. package/src/ProcessManager.res.mjs +80 -0
  79. package/src/Projection_GWT.res +312 -0
  80. package/src/Projection_GWT.res.mjs +332 -0
  81. package/src/Query_GWT.res +379 -0
  82. package/src/Query_GWT.res.mjs +367 -0
  83. package/src/RenderRescript.res +125 -0
  84. package/src/RenderRescript.res.mjs +141 -0
  85. package/src/RunnerTypes.res +68 -0
  86. package/src/RunnerTypes.res.mjs +60 -0
  87. package/src/SideEffect_GWT.res +157 -0
  88. package/src/SideEffect_GWT.res.mjs +113 -0
  89. package/src/StateChange/ExternalAddCategorySlice.res +25 -0
  90. package/src/StateChange/ExternalAddCategorySlice.res.mjs +34 -0
  91. package/src/StateChange/ExternalAddCategorySlice_Behavior.res +19 -0
  92. package/src/StateChange/ExternalAddCategorySlice_Behavior.res.mjs +46 -0
  93. package/src/StateChange/WithFixtures.res +22 -0
  94. package/src/StateChange/WithFixtures.res.mjs +31 -0
  95. package/src/StateChange/WithFixtures_Behavior.res +17 -0
  96. package/src/StateChange/WithFixtures_Behavior.res.mjs +37 -0
  97. package/src/StateChange/WithManualOpen.res +23 -0
  98. package/src/StateChange/WithManualOpen.res.mjs +31 -0
  99. package/src/StateChange/WithManualOpen_Behavior.res +17 -0
  100. package/src/StateChange/WithManualOpen_Behavior.res.mjs +37 -0
  101. package/src/StubRuntime.res +53 -0
  102. package/src/StubRuntime.res.mjs +54 -0
  103. package/src/TestFixtures.res +16 -0
  104. package/src/TestFixtures.res.mjs +34 -0
  105. package/src/Watch.res +92 -0
  106. package/src/Watch.res.mjs +83 -0
  107. package/src/WatcherProbe.res +48 -0
  108. package/src/WatcherProbe.res.mjs +46 -0
  109. package/tests/AutomationGwtTest.res +71 -0
  110. package/tests/AutomationGwtTest.res.mjs +189 -0
  111. package/tests/BuildClassifierTest.res +94 -0
  112. package/tests/BuildClassifierTest.res.mjs +132 -0
  113. package/tests/ComponentMetaTest.res +52 -0
  114. package/tests/ComponentMetaTest.res.mjs +57 -0
  115. package/tests/DelegateGwtTest.res +487 -0
  116. package/tests/DelegateGwtTest.res.mjs +891 -0
  117. package/tests/DiscoveryTest.res +42 -0
  118. package/tests/DiscoveryTest.res.mjs +43 -0
  119. package/tests/DomainDeadCodeTest.res +116 -0
  120. package/tests/DomainDeadCodeTest.res.mjs +155 -0
  121. package/tests/DomainGraphTest.res +365 -0
  122. package/tests/DomainGraphTest.res.mjs +413 -0
  123. package/tests/FlowAggregateGwtTest.res +169 -0
  124. package/tests/FlowAggregateGwtTest.res.mjs +269 -0
  125. package/tests/FlowCrossPluginGwtTest.res +340 -0
  126. package/tests/FlowCrossPluginGwtTest.res.mjs +798 -0
  127. package/tests/FlowGwtTest.res +222 -0
  128. package/tests/FlowGwtTest.res.mjs +432 -0
  129. package/tests/FormatterVsCodeMessageTest.res +41 -0
  130. package/tests/FormatterVsCodeMessageTest.res.mjs +42 -0
  131. package/tests/InboundTranslationGwtTest.res +34 -0
  132. package/tests/InboundTranslationGwtTest.res.mjs +98 -0
  133. package/tests/LocalHostIntegration.res +70 -0
  134. package/tests/LocalHostIntegration.res.mjs +64 -0
  135. package/tests/LocalHostTest.res +71 -0
  136. package/tests/LocalHostTest.res.mjs +63 -0
  137. package/tests/MappingGwtTest.res +348 -0
  138. package/tests/MappingGwtTest.res.mjs +592 -0
  139. package/tests/OutboundTranslationGwtTest.res +59 -0
  140. package/tests/OutboundTranslationGwtTest.res.mjs +138 -0
  141. package/tests/PlatformRunnerTest.res +66 -0
  142. package/tests/PlatformRunnerTest.res.mjs +85 -0
  143. package/tests/PlatformScanTest.res +61 -0
  144. package/tests/PlatformScanTest.res.mjs +56 -0
  145. package/tests/QueryGwtTest.res +161 -0
  146. package/tests/QueryGwtTest.res.mjs +314 -0
  147. package/tests/QueryResolverGwtTest.res +71 -0
  148. package/tests/QueryResolverGwtTest.res.mjs +136 -0
  149. package/tests/RunnerUnitTest.res +219 -0
  150. package/tests/RunnerUnitTest.res.mjs +244 -0
  151. package/tests/SideEffect/FakeOrderNotification.res +23 -0
  152. package/tests/SideEffect/FakeOrderNotification.res.mjs +36 -0
  153. package/tests/SideEffect/FakeOrderNotificationGwtTest.res +35 -0
  154. package/tests/SideEffect/FakeOrderNotificationGwtTest.res.mjs +73 -0
  155. package/tests/SideEffect/MockEmail.res +18 -0
  156. package/tests/SideEffect/MockEmail.res.mjs +47 -0
  157. package/tests/StateChange/ExternalAddCategorySlice_GWT.res +27 -0
  158. package/tests/StateChange/ExternalAddCategorySlice_GWT.res.mjs +70 -0
  159. package/tests/StateChange/WithFixtures_Fixtures.res +9 -0
  160. package/tests/StateChange/WithFixtures_Fixtures.res.mjs +20 -0
  161. package/tests/StateChange/WithFixtures_GWT.res +23 -0
  162. package/tests/StateChange/WithFixtures_GWT.res.mjs +56 -0
  163. package/tests/StateChange/WithManualOpen_Fixtures.res +7 -0
  164. package/tests/StateChange/WithManualOpen_Fixtures.res.mjs +20 -0
  165. package/tests/StateChange/WithManualOpen_GWT.res +17 -0
  166. package/tests/StateChange/WithManualOpen_GWT.res.mjs +56 -0
  167. package/tests/StateChangeSliceGwtTest.res +160 -0
  168. package/tests/StateChangeSliceGwtTest.res.mjs +280 -0
  169. package/tests/StateViewSliceGwtTest.res +64 -0
  170. package/tests/StateViewSliceGwtTest.res.mjs +161 -0
  171. package/tests/WatchDebounceTest.res +78 -0
  172. package/tests/WatchDebounceTest.res.mjs +97 -0
@@ -0,0 +1,186 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
5
+ import * as Outcome$ReventlessGwt from "./Outcome.res.mjs";
6
+ import * as JestBind$ReventlessGwt from "./JestBind.res.mjs";
7
+ import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
8
+
9
+ function Make(Spec) {
10
+ S.enableJson();
11
+ let test = (name, timeout, body) => JestBind$ReventlessGwt.testPromise(Spec.name, name, timeout, body);
12
+ let testSync = (name, body) => JestBind$ReventlessGwt.test(Spec.name, name, body);
13
+ let encItems = arr => arr.map(param => [
14
+ param[0],
15
+ Message$ReventlessCore.encode(param[1], Spec.outboundItemSchema)
16
+ ]);
17
+ let givenEvent = e => e;
18
+ let whenCollect = e => Spec.collect(e);
19
+ let thenTodos = (actual, expected) => {
20
+ if (Primitive_object.equal(actual, expected)) {
21
+ return Outcome$ReventlessGwt.pass;
22
+ } else {
23
+ return Outcome$ReventlessGwt.fail({
24
+ TAG: "TodoMismatch",
25
+ expected: encItems(expected),
26
+ actual: encItems(actual)
27
+ });
28
+ }
29
+ };
30
+ let givenTodo = (id, item) => [
31
+ id,
32
+ item
33
+ ];
34
+ let whenTranslateMocked = async (param, mock) => {
35
+ let item = param[1];
36
+ let id = param[0];
37
+ let result = await mock(id, item);
38
+ return {
39
+ id: id,
40
+ item: item,
41
+ result: result,
42
+ retries: 0
43
+ };
44
+ };
45
+ let whenTranslateRetrying = async (param, maxRetries, mock) => {
46
+ let item = param[1];
47
+ let id = param[0];
48
+ let result = {
49
+ contents: await mock(id, item)
50
+ };
51
+ let retries = 0;
52
+ let failed = () => {
53
+ let match = result.contents;
54
+ return match.TAG !== "Ok";
55
+ };
56
+ while (failed() && retries < maxRetries) {
57
+ retries = retries + 1 | 0;
58
+ result.contents = await mock(id, item);
59
+ };
60
+ return {
61
+ id: id,
62
+ item: item,
63
+ result: result.contents,
64
+ retries: retries
65
+ };
66
+ };
67
+ let commandPairJson = (id, cmd) => {
68
+ let d = {};
69
+ d["id"] = id;
70
+ d["command"] = Message$ReventlessCore.encode(cmd, Spec.inboundCommandSchema);
71
+ return d;
72
+ };
73
+ let thenCommand = async (pending, expectedId, expectedCmd) => {
74
+ let match = await pending;
75
+ let result = match.result;
76
+ if (result.TAG !== "Ok") {
77
+ return Outcome$ReventlessGwt.fail({
78
+ TAG: "TranslateError",
79
+ expected: "(command)",
80
+ actual: result._0
81
+ });
82
+ }
83
+ let match$1 = result._0;
84
+ if (match$1 === undefined) {
85
+ return Outcome$ReventlessGwt.fail({
86
+ TAG: "EventsMismatch",
87
+ expected: [commandPairJson(expectedId, expectedCmd)],
88
+ actual: []
89
+ });
90
+ }
91
+ let cmd = match$1[1];
92
+ let id = match$1[0];
93
+ if (id === expectedId && Primitive_object.equal(cmd, expectedCmd)) {
94
+ return Outcome$ReventlessGwt.pass;
95
+ } else {
96
+ return Outcome$ReventlessGwt.fail({
97
+ TAG: "EventsMismatch",
98
+ expected: [commandPairJson(expectedId, expectedCmd)],
99
+ actual: [commandPairJson(id, cmd)]
100
+ });
101
+ }
102
+ };
103
+ let thenNoCommand = async pending => {
104
+ let match = await pending;
105
+ let result = match.result;
106
+ if (result.TAG !== "Ok") {
107
+ return Outcome$ReventlessGwt.fail({
108
+ TAG: "TranslateError",
109
+ expected: "(no command)",
110
+ actual: result._0
111
+ });
112
+ }
113
+ let match$1 = result._0;
114
+ if (match$1 !== undefined) {
115
+ return Outcome$ReventlessGwt.fail({
116
+ TAG: "NoEventExpected",
117
+ actual: [commandPairJson(match$1[0], match$1[1])]
118
+ });
119
+ } else {
120
+ return Outcome$ReventlessGwt.pass;
121
+ }
122
+ };
123
+ let thenRetryRecorded = async (pending, expectedRetries) => {
124
+ let match = await pending;
125
+ let retries = match.retries;
126
+ if (retries === expectedRetries) {
127
+ return Outcome$ReventlessGwt.pass;
128
+ } else {
129
+ return Outcome$ReventlessGwt.fail({
130
+ TAG: "StateMismatch",
131
+ key: "retries",
132
+ expected: expectedRetries,
133
+ actual: retries
134
+ });
135
+ }
136
+ };
137
+ let statusToString = s => {
138
+ if (s === "Pending") {
139
+ return "#Pending";
140
+ } else {
141
+ return "#Completed";
142
+ }
143
+ };
144
+ let thenTodoStatus = async (pending, expectedId, expectedStatus) => {
145
+ let match = await pending;
146
+ let id = match.id;
147
+ let actualStatus;
148
+ actualStatus = match.result.TAG === "Ok" ? "Completed" : "Pending";
149
+ if (id === expectedId && actualStatus === expectedStatus) {
150
+ return Outcome$ReventlessGwt.pass;
151
+ }
152
+ let encOne = (rid, rstatus) => {
153
+ let d = {};
154
+ d["id"] = rid;
155
+ d["status"] = statusToString(rstatus);
156
+ return d;
157
+ };
158
+ return Outcome$ReventlessGwt.fail({
159
+ TAG: "StateMismatch",
160
+ key: id,
161
+ expected: encOne(expectedId, expectedStatus),
162
+ actual: encOne(id, actualStatus)
163
+ });
164
+ };
165
+ return {
166
+ Spec: Spec,
167
+ describe: JestBind$ReventlessGwt.describe,
168
+ test: test,
169
+ testSync: testSync,
170
+ givenEvent: givenEvent,
171
+ whenCollect: whenCollect,
172
+ thenTodos: thenTodos,
173
+ givenTodo: givenTodo,
174
+ whenTranslateMocked: whenTranslateMocked,
175
+ whenTranslateRetrying: whenTranslateRetrying,
176
+ thenCommand: thenCommand,
177
+ thenNoCommand: thenNoCommand,
178
+ thenRetryRecorded: thenRetryRecorded,
179
+ thenTodoStatus: thenTodoStatus
180
+ };
181
+ }
182
+
183
+ export {
184
+ Make,
185
+ }
186
+ /* S Not a pure module */
@@ -0,0 +1,161 @@
1
+ // The `Outcome` algebra — Stage 2 of the reventless-gwt plan.
2
+ //
3
+ // Every `then*` combinator in every GWT DSL returns `Outcome.outcome`
4
+ // (`result<unit, mismatch>`). The runner, the human formatter, the AI loop,
5
+ // and the IDE all consume the same `Outcome` value, just rendered differently.
6
+ //
7
+ // See `docs/analysis/given-when-then-specifications.md` §3.2 for the canonical
8
+ // shape and §3.3 for the JSON rendering. Stage 7 adds sury-aware rendering and
9
+ // structural `fieldDiff`. Stage 4 added `AppendConditionMismatch`.
10
+
11
+ type mismatch =
12
+ | EventsMismatch({expected: array<JSON.t>, actual: array<JSON.t>})
13
+ | ErrorMismatch({
14
+ expected: JSON.t,
15
+ actual: option<JSON.t>,
16
+ actualEvents: array<JSON.t>,
17
+ })
18
+ | StateMismatch({key: string, expected: option<JSON.t>, actual: option<JSON.t>})
19
+ | NoEventExpected({actual: array<JSON.t>})
20
+ | TodoMismatch({expected: array<(string, JSON.t)>, actual: array<(string, JSON.t)>})
21
+ | AppendConditionMismatch({expected: JSON.t, actual: JSON.t})
22
+ | TranslateError({expected: string, actual: option<string>})
23
+ | QueryRowsMismatch({expected: array<JSON.t>, actual: array<JSON.t>})
24
+ // The set of published actions (events/commands) emitted by an ExtensionPoint
25
+ // mapping or an Extension delegate diverged from the expectation. Supports
26
+ // one-to-many fan-out (one inbound message → N published actions). Used by
27
+ // `Delegate_GWT` and the cross-plugin `Flow_GWT` boundary steps.
28
+ | PublishedActionsMismatch({expected: array<JSON.t>, actual: array<JSON.t>})
29
+ | Throw({error: string, stack: string})
30
+
31
+ type outcome = result<unit, mismatch>
32
+
33
+ let pass: outcome = Ok()
34
+ let fail = (m): outcome => Error(m)
35
+
36
+ let kindName = (m: mismatch) =>
37
+ switch m {
38
+ | EventsMismatch(_) => "EventsMismatch"
39
+ | ErrorMismatch(_) => "ErrorMismatch"
40
+ | StateMismatch(_) => "StateMismatch"
41
+ | NoEventExpected(_) => "NoEventExpected"
42
+ | TodoMismatch(_) => "TodoMismatch"
43
+ | AppendConditionMismatch(_) => "AppendConditionMismatch"
44
+ | TranslateError(_) => "TranslateError"
45
+ | QueryRowsMismatch(_) => "QueryRowsMismatch"
46
+ | PublishedActionsMismatch(_) => "PublishedActionsMismatch"
47
+ | Throw(_) => "Throw"
48
+ }
49
+
50
+ let stringifyJson = (j: JSON.t) => JSON.stringify(j, ~space=2)
51
+ let stringifyOptJson = (j: option<JSON.t>) =>
52
+ switch j {
53
+ | Some(v) => stringifyJson(v)
54
+ | None => "(none)"
55
+ }
56
+ let stringifyJsonArray = (arr: array<JSON.t>) =>
57
+ "[" ++ arr->Array.map(stringifyJson)->Array.join(", ") ++ "]"
58
+
59
+ let format = (m: mismatch) =>
60
+ switch m {
61
+ | EventsMismatch({expected, actual}) =>
62
+ `EventsMismatch:\n expected: ${stringifyJsonArray(expected)}\n actual: ${stringifyJsonArray(
63
+ actual,
64
+ )}`
65
+ | ErrorMismatch({expected, actual, actualEvents}) =>
66
+ `ErrorMismatch:\n expected error: ${stringifyJson(expected)}\n actual error: ${stringifyOptJson(
67
+ actual,
68
+ )}\n actual events: ${stringifyJsonArray(actualEvents)}`
69
+ | StateMismatch({key, expected, actual}) =>
70
+ `StateMismatch (key: ${key}):\n expected: ${stringifyOptJson(
71
+ expected,
72
+ )}\n actual: ${stringifyOptJson(actual)}`
73
+ | NoEventExpected({actual}) =>
74
+ `NoEventExpected: expected no events, got:\n ${stringifyJsonArray(actual)}`
75
+ | TodoMismatch({expected, actual}) => {
76
+ let fmt = arr =>
77
+ arr
78
+ ->Array.map(((id, j)) => `(${id}, ${stringifyJson(j)})`)
79
+ ->Array.join(", ")
80
+ `TodoMismatch:\n expected: [${fmt(expected)}]\n actual: [${fmt(actual)}]`
81
+ }
82
+ | AppendConditionMismatch({expected, actual}) =>
83
+ `AppendConditionMismatch:\n expected: ${stringifyJson(expected)}\n actual: ${stringifyJson(
84
+ actual,
85
+ )}`
86
+ | TranslateError({expected, actual}) =>
87
+ `TranslateError:\n expected: ${expected}\n actual: ${actual->Option.getOr("(none)")}`
88
+ | QueryRowsMismatch({expected, actual}) =>
89
+ `QueryRowsMismatch:\n expected: ${stringifyJsonArray(expected)}\n actual: ${stringifyJsonArray(
90
+ actual,
91
+ )}`
92
+ | PublishedActionsMismatch({expected, actual}) =>
93
+ `PublishedActionsMismatch:\n expected: ${stringifyJsonArray(expected)}\n actual: ${stringifyJsonArray(
94
+ actual,
95
+ )}`
96
+ | Throw({error, stack}) => `Throw: ${error}\n${stack}`
97
+ }
98
+
99
+ // Structured JSON payload per §3.3 of the analysis.
100
+ // Closed schema — consumers switch on the `kind` discriminator.
101
+ // Stage 7 enriches with `rendered` strings and `fieldDiff`.
102
+ let toJson = (m: mismatch): JSON.t => {
103
+ let obj = Dict.make()
104
+ obj->Dict.set("kind", JSON.Encode.string(kindName(m)))
105
+ let jsonArr = arr => JSON.Encode.array(arr)
106
+ let optJson = o => o->Option.getOr(JSON.Encode.null)
107
+ switch m {
108
+ | EventsMismatch({expected, actual}) => {
109
+ obj->Dict.set("expected", jsonArr(expected))
110
+ obj->Dict.set("actual", jsonArr(actual))
111
+ }
112
+ | ErrorMismatch({expected, actual, actualEvents}) => {
113
+ obj->Dict.set("expected", expected)
114
+ obj->Dict.set("actual", optJson(actual))
115
+ obj->Dict.set("actualEvents", jsonArr(actualEvents))
116
+ }
117
+ | StateMismatch({key, expected, actual}) => {
118
+ obj->Dict.set("key", JSON.Encode.string(key))
119
+ obj->Dict.set("expected", optJson(expected))
120
+ obj->Dict.set("actual", optJson(actual))
121
+ }
122
+ | NoEventExpected({actual}) => obj->Dict.set("actual", jsonArr(actual))
123
+ | TodoMismatch({expected, actual}) => {
124
+ let pairArr = pairs =>
125
+ pairs
126
+ ->Array.map(((id, v)) => {
127
+ let d = Dict.make()
128
+ d->Dict.set("id", JSON.Encode.string(id))
129
+ d->Dict.set("value", v)
130
+ JSON.Encode.object(d)
131
+ })
132
+ ->jsonArr
133
+ obj->Dict.set("expected", pairArr(expected))
134
+ obj->Dict.set("actual", pairArr(actual))
135
+ }
136
+ | AppendConditionMismatch({expected, actual}) => {
137
+ obj->Dict.set("expected", expected)
138
+ obj->Dict.set("actual", actual)
139
+ }
140
+ | TranslateError({expected, actual}) => {
141
+ obj->Dict.set("expected", JSON.Encode.string(expected))
142
+ obj->Dict.set(
143
+ "actual",
144
+ actual->Option.mapOr(JSON.Encode.null, JSON.Encode.string),
145
+ )
146
+ }
147
+ | QueryRowsMismatch({expected, actual}) => {
148
+ obj->Dict.set("expected", jsonArr(expected))
149
+ obj->Dict.set("actual", jsonArr(actual))
150
+ }
151
+ | PublishedActionsMismatch({expected, actual}) => {
152
+ obj->Dict.set("expected", jsonArr(expected))
153
+ obj->Dict.set("actual", jsonArr(actual))
154
+ }
155
+ | Throw({error, stack}) => {
156
+ obj->Dict.set("error", JSON.Encode.string(error))
157
+ obj->Dict.set("stack", JSON.Encode.string(stack))
158
+ }
159
+ }
160
+ JSON.Encode.object(obj)
161
+ }
@@ -0,0 +1,140 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+
5
+ function fail(m) {
6
+ return {
7
+ TAG: "Error",
8
+ _0: m
9
+ };
10
+ }
11
+
12
+ function kindName(m) {
13
+ switch (m.TAG) {
14
+ case "EventsMismatch" :
15
+ return "EventsMismatch";
16
+ case "ErrorMismatch" :
17
+ return "ErrorMismatch";
18
+ case "StateMismatch" :
19
+ return "StateMismatch";
20
+ case "NoEventExpected" :
21
+ return "NoEventExpected";
22
+ case "TodoMismatch" :
23
+ return "TodoMismatch";
24
+ case "AppendConditionMismatch" :
25
+ return "AppendConditionMismatch";
26
+ case "TranslateError" :
27
+ return "TranslateError";
28
+ case "QueryRowsMismatch" :
29
+ return "QueryRowsMismatch";
30
+ case "PublishedActionsMismatch" :
31
+ return "PublishedActionsMismatch";
32
+ case "Throw" :
33
+ return "Throw";
34
+ }
35
+ }
36
+
37
+ function stringifyJson(j) {
38
+ return JSON.stringify(j, undefined, 2);
39
+ }
40
+
41
+ function stringifyOptJson(j) {
42
+ if (j !== undefined) {
43
+ return JSON.stringify(j, undefined, 2);
44
+ } else {
45
+ return "(none)";
46
+ }
47
+ }
48
+
49
+ function stringifyJsonArray(arr) {
50
+ return "[" + arr.map(stringifyJson).join(", ") + "]";
51
+ }
52
+
53
+ function format(m) {
54
+ switch (m.TAG) {
55
+ case "EventsMismatch" :
56
+ return `EventsMismatch:\n expected: ` + stringifyJsonArray(m.expected) + `\n actual: ` + stringifyJsonArray(m.actual);
57
+ case "ErrorMismatch" :
58
+ return `ErrorMismatch:\n expected error: ` + JSON.stringify(m.expected, undefined, 2) + `\n actual error: ` + stringifyOptJson(m.actual) + `\n actual events: ` + stringifyJsonArray(m.actualEvents);
59
+ case "StateMismatch" :
60
+ return `StateMismatch (key: ` + m.key + `):\n expected: ` + stringifyOptJson(m.expected) + `\n actual: ` + stringifyOptJson(m.actual);
61
+ case "NoEventExpected" :
62
+ return `NoEventExpected: expected no events, got:\n ` + stringifyJsonArray(m.actual);
63
+ case "TodoMismatch" :
64
+ let fmt = arr => arr.map(param => `(` + param[0] + `, ` + JSON.stringify(param[1], undefined, 2) + `)`).join(", ");
65
+ return `TodoMismatch:\n expected: [` + fmt(m.expected) + `]\n actual: [` + fmt(m.actual) + `]`;
66
+ case "AppendConditionMismatch" :
67
+ return `AppendConditionMismatch:\n expected: ` + JSON.stringify(m.expected, undefined, 2) + `\n actual: ` + JSON.stringify(m.actual, undefined, 2);
68
+ case "TranslateError" :
69
+ return `TranslateError:\n expected: ` + m.expected + `\n actual: ` + Stdlib_Option.getOr(m.actual, "(none)");
70
+ case "QueryRowsMismatch" :
71
+ return `QueryRowsMismatch:\n expected: ` + stringifyJsonArray(m.expected) + `\n actual: ` + stringifyJsonArray(m.actual);
72
+ case "PublishedActionsMismatch" :
73
+ return `PublishedActionsMismatch:\n expected: ` + stringifyJsonArray(m.expected) + `\n actual: ` + stringifyJsonArray(m.actual);
74
+ case "Throw" :
75
+ return `Throw: ` + m.error + `\n` + m.stack;
76
+ }
77
+ }
78
+
79
+ function toJson(m) {
80
+ let obj = {};
81
+ obj["kind"] = kindName(m);
82
+ switch (m.TAG) {
83
+ case "ErrorMismatch" :
84
+ obj["expected"] = m.expected;
85
+ obj["actual"] = Stdlib_Option.getOr(m.actual, null);
86
+ obj["actualEvents"] = m.actualEvents;
87
+ break;
88
+ case "StateMismatch" :
89
+ obj["key"] = m.key;
90
+ obj["expected"] = Stdlib_Option.getOr(m.expected, null);
91
+ obj["actual"] = Stdlib_Option.getOr(m.actual, null);
92
+ break;
93
+ case "NoEventExpected" :
94
+ obj["actual"] = m.actual;
95
+ break;
96
+ case "TodoMismatch" :
97
+ let pairArr = pairs => pairs.map(param => {
98
+ let d = {};
99
+ d["id"] = param[0];
100
+ d["value"] = param[1];
101
+ return d;
102
+ });
103
+ obj["expected"] = pairArr(m.expected);
104
+ obj["actual"] = pairArr(m.actual);
105
+ break;
106
+ case "TranslateError" :
107
+ obj["expected"] = m.expected;
108
+ obj["actual"] = Stdlib_Option.mapOr(m.actual, null, prim => prim);
109
+ break;
110
+ case "EventsMismatch" :
111
+ case "AppendConditionMismatch" :
112
+ case "QueryRowsMismatch" :
113
+ case "PublishedActionsMismatch" :
114
+ obj["expected"] = m.expected;
115
+ obj["actual"] = m.actual;
116
+ break;
117
+ case "Throw" :
118
+ obj["error"] = m.error;
119
+ obj["stack"] = m.stack;
120
+ break;
121
+ }
122
+ return obj;
123
+ }
124
+
125
+ let pass = {
126
+ TAG: "Ok",
127
+ _0: undefined
128
+ };
129
+
130
+ export {
131
+ pass,
132
+ fail,
133
+ kindName,
134
+ stringifyJson,
135
+ stringifyOptJson,
136
+ stringifyJsonArray,
137
+ format,
138
+ toJson,
139
+ }
140
+ /* No side effect */
@@ -0,0 +1,80 @@
1
+ // Derives the set of workspace packages that own GWT test files, so a watch
2
+ // session knows which packages to keep compiling (`pnpm run start` →
3
+ // `rescript build -w`). Given the absolute test-file paths from `Discovery`,
4
+ // each is mapped to its nearest ancestor `package.json` that declares a
5
+ // `start` script; results are deduplicated by directory.
6
+ //
7
+ // This is the input both the `packages` NDJSON event (FormatterVsCode) and the
8
+ // watch-mode build manager (ProcessManager) consume — computed fresh per run so
9
+ // it never drifts when a plugin is added or removed.
10
+
11
+ type pkg = {
12
+ // Package name from package.json (may be "" if absent).
13
+ name: string,
14
+ // Absolute directory containing the owning package.json.
15
+ dir: string,
16
+ // The `start` script's command (the ReScript watch command), informational.
17
+ build: string,
18
+ }
19
+
20
+ @module("node:fs") external _existsSync: string => bool = "existsSync"
21
+ @module("node:fs") external _readFileSync: (string, string) => string = "readFileSync"
22
+ @module("node:path") external dirname: string => string = "dirname"
23
+ @module("node:path") external join: (string, string) => string = "join"
24
+
25
+ // Reads name + `start` command from a package.json, if it declares one.
26
+ let readPackage = (pkgJsonPath: string): option<(string, string)> =>
27
+ try {
28
+ let json = JSON.parseOrThrow(_readFileSync(pkgJsonPath, "utf8"))
29
+ switch json {
30
+ | Object(obj) =>
31
+ let name = switch obj->Dict.get("name") {
32
+ | Some(String(n)) => n
33
+ | _ => ""
34
+ }
35
+ switch obj->Dict.get("scripts") {
36
+ | Some(Object(scripts)) =>
37
+ switch scripts->Dict.get("start") {
38
+ | Some(String(cmd)) => Some((name, cmd))
39
+ | _ => None
40
+ }
41
+ | _ => None
42
+ }
43
+ | _ => None
44
+ }
45
+ } catch {
46
+ | _ => None
47
+ }
48
+
49
+ // Walks up from `dir` to the nearest package.json declaring a `start` script.
50
+ let rec findOwning = (dir: string): option<pkg> => {
51
+ let pkgJson = join(dir, "package.json")
52
+ let here = _existsSync(pkgJson) ? readPackage(pkgJson) : None
53
+ switch here {
54
+ | Some((name, build)) => Some({name, dir, build})
55
+ | None => {
56
+ let parent = dirname(dir)
57
+ parent == dir ? None : findOwning(parent)
58
+ }
59
+ }
60
+ }
61
+
62
+ // Maps test files → deduplicated owning packages (declaration order preserved).
63
+ let scan = (testFiles: array<string>): array<pkg> => {
64
+ let seen = Dict.make()
65
+ let out = []
66
+ testFiles->Array.forEach(file =>
67
+ switch findOwning(dirname(file)) {
68
+ | Some(pkg) =>
69
+ switch seen->Dict.get(pkg.dir) {
70
+ | Some(_) => ()
71
+ | None => {
72
+ seen->Dict.set(pkg.dir, true)
73
+ out->Array.push(pkg)
74
+ }
75
+ }
76
+ | None => ()
77
+ }
78
+ )
79
+ out
80
+ }
@@ -0,0 +1,81 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Nodefs from "node:fs";
4
+ import * as Nodepath from "node:path";
5
+
6
+ function readPackage(pkgJsonPath) {
7
+ try {
8
+ let json = JSON.parse(Nodefs.readFileSync(pkgJsonPath, "utf8"));
9
+ if (typeof json !== "object" || json === null || Array.isArray(json)) {
10
+ return;
11
+ }
12
+ let match = json["name"];
13
+ let name = typeof match === "string" ? match : "";
14
+ let match$1 = json["scripts"];
15
+ if (match$1 === undefined) {
16
+ return;
17
+ }
18
+ if (typeof match$1 !== "object" || match$1 === null || Array.isArray(match$1)) {
19
+ return;
20
+ }
21
+ let match$2 = match$1["start"];
22
+ if (typeof match$2 === "string") {
23
+ return [
24
+ name,
25
+ match$2
26
+ ];
27
+ } else {
28
+ return;
29
+ }
30
+ } catch (exn) {
31
+ return;
32
+ }
33
+ }
34
+
35
+ function findOwning(_dir) {
36
+ while (true) {
37
+ let dir = _dir;
38
+ let pkgJson = Nodepath.join(dir, "package.json");
39
+ let here = Nodefs.existsSync(pkgJson) ? readPackage(pkgJson) : undefined;
40
+ if (here !== undefined) {
41
+ return {
42
+ name: here[0],
43
+ dir: dir,
44
+ build: here[1]
45
+ };
46
+ }
47
+ let parent = Nodepath.dirname(dir);
48
+ if (parent === dir) {
49
+ return;
50
+ }
51
+ _dir = parent;
52
+ continue;
53
+ };
54
+ }
55
+
56
+ function scan(testFiles) {
57
+ let seen = {};
58
+ let out = [];
59
+ testFiles.forEach(file => {
60
+ let pkg = findOwning(Nodepath.dirname(file));
61
+ if (pkg === undefined) {
62
+ return;
63
+ }
64
+ let match = seen[pkg.dir];
65
+ if (match !== undefined) {
66
+ return;
67
+ } else {
68
+ seen[pkg.dir] = true;
69
+ out.push(pkg);
70
+ return;
71
+ }
72
+ });
73
+ return out;
74
+ }
75
+
76
+ export {
77
+ readPackage,
78
+ findOwning,
79
+ scan,
80
+ }
81
+ /* node:fs Not a pure module */