@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,367 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
5
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
6
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
8
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
+ import * as Outcome$ReventlessGwt from "./Outcome.res.mjs";
10
+ import * as JestBind$ReventlessGwt from "./JestBind.res.mjs";
11
+
12
+ function FromReadModel(Spec) {
13
+ return {
14
+ name: Spec.name,
15
+ stateSchema: Spec.stateSchema,
16
+ config: Spec.config,
17
+ subIdConfig: Spec.subIdConfig
18
+ };
19
+ }
20
+
21
+ function FromStateViewSlice(Spec) {
22
+ return {
23
+ name: Spec.name,
24
+ stateSchema: Spec.stateSchema,
25
+ config: Spec.config,
26
+ subIdConfig: Spec.subIdConfig
27
+ };
28
+ }
29
+
30
+ function Make(Spec) {
31
+ S.enableJson();
32
+ let test = (name, body) => JestBind$ReventlessGwt.test(Spec.name, name, body);
33
+ let encState = s => S.reverseConvertToJsonOrThrow(s, Spec.stateSchema);
34
+ let givenStore = pairs => pairs.map(param => ({
35
+ id: param[0],
36
+ subId: undefined,
37
+ state: param[1]
38
+ }));
39
+ let givenCompositeStore = triples => triples.map(param => ({
40
+ id: param[0],
41
+ subId: param[1],
42
+ state: param[2]
43
+ }));
44
+ let whenQueryById = (s, id) => Stdlib_Array.findMap(s, r => {
45
+ if (r.id === id) {
46
+ return Primitive_option.some(r.state);
47
+ }
48
+ });
49
+ let whenQueryByCompositeId = (s, param) => {
50
+ let subId = param.subId;
51
+ let id = param.id;
52
+ if (Spec.subIdConfig !== undefined) {
53
+ return {
54
+ TAG: "Ok",
55
+ _0: Stdlib_Array.findMap(s, r => {
56
+ if (r.id === id && Primitive_object.equal(r.subId, subId)) {
57
+ return Primitive_option.some(r.state);
58
+ }
59
+ })
60
+ };
61
+ } else {
62
+ return {
63
+ TAG: "Error",
64
+ _0: {
65
+ TAG: "QueryRowsMismatch",
66
+ expected: [`composite-id lookup requires subIdConfig = Some({subIdField, getSubId}) in ` + Spec.name + `.config`],
67
+ actual: []
68
+ }
69
+ };
70
+ }
71
+ };
72
+ let indexCovers = (indexName, field) => Spec.config.indexes.some(idx => {
73
+ if (idx.index !== indexName) {
74
+ return false;
75
+ }
76
+ if (Primitive_object.equal(idx.idField, field)) {
77
+ return true;
78
+ }
79
+ let fields = idx.pkFields;
80
+ if (fields !== undefined) {
81
+ return fields.includes(field);
82
+ } else {
83
+ return false;
84
+ }
85
+ });
86
+ let whenQuery = (s, args) => {
87
+ let name = args.index;
88
+ let indexError = name !== undefined && !indexCovers(name, args.by) ? ({
89
+ TAG: "QueryRowsMismatch",
90
+ expected: [`index "` + name + `" covering field "` + args.by + `" is missing from ` + Spec.name + `.config.indexes`],
91
+ actual: []
92
+ }) : undefined;
93
+ if (indexError !== undefined) {
94
+ return {
95
+ TAG: "Error",
96
+ _0: indexError
97
+ };
98
+ }
99
+ let field = args.by;
100
+ let expected = args.value;
101
+ let matches = s.filter(r => {
102
+ let json = S.reverseConvertToJsonOrThrow(r.state, Spec.stateSchema);
103
+ let v = Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(json), d => d[field]);
104
+ if (v === undefined) {
105
+ return false;
106
+ }
107
+ let actualStr;
108
+ switch (typeof v) {
109
+ case "boolean" :
110
+ actualStr = v ? "true" : "false";
111
+ break;
112
+ case "string" :
113
+ actualStr = v;
114
+ break;
115
+ case "number" :
116
+ actualStr = v.toString();
117
+ break;
118
+ default:
119
+ actualStr = JSON.stringify(v);
120
+ }
121
+ return actualStr === expected;
122
+ });
123
+ let p = args.filter;
124
+ let afterFilter = p !== undefined ? matches.filter(r => p(r.state)) : matches;
125
+ let n = args.limit;
126
+ let afterLimit = n !== undefined ? afterFilter.slice(0, n) : afterFilter;
127
+ return {
128
+ TAG: "Ok",
129
+ _0: afterLimit.map(r => r.state)
130
+ };
131
+ };
132
+ let thenRow = (actual, expected) => {
133
+ if (Primitive_object.equal(actual, expected)) {
134
+ return Outcome$ReventlessGwt.pass;
135
+ }
136
+ let actualJson = Stdlib_Option.mapOr(actual, [], s => [S.reverseConvertToJsonOrThrow(s, Spec.stateSchema)]);
137
+ let expectedJson = Stdlib_Option.mapOr(expected, [], s => [S.reverseConvertToJsonOrThrow(s, Spec.stateSchema)]);
138
+ return Outcome$ReventlessGwt.fail({
139
+ TAG: "QueryRowsMismatch",
140
+ expected: expectedJson,
141
+ actual: actualJson
142
+ });
143
+ };
144
+ let thenRows = (result, expected) => {
145
+ if (result.TAG !== "Ok") {
146
+ return Outcome$ReventlessGwt.fail(result._0);
147
+ }
148
+ let actual = result._0;
149
+ if (Primitive_object.equal(actual, expected)) {
150
+ return Outcome$ReventlessGwt.pass;
151
+ } else {
152
+ return Outcome$ReventlessGwt.fail({
153
+ TAG: "QueryRowsMismatch",
154
+ expected: expected.map(encState),
155
+ actual: actual.map(encState)
156
+ });
157
+ }
158
+ };
159
+ let thenRowCount = (result, expected) => {
160
+ if (result.TAG !== "Ok") {
161
+ return Outcome$ReventlessGwt.fail(result._0);
162
+ }
163
+ let actual = result._0;
164
+ if (actual.length === expected) {
165
+ return Outcome$ReventlessGwt.pass;
166
+ } else {
167
+ return Outcome$ReventlessGwt.fail({
168
+ TAG: "QueryRowsMismatch",
169
+ expected: [`row count = ` + expected.toString()],
170
+ actual: [`row count = ` + actual.length.toString()]
171
+ });
172
+ }
173
+ };
174
+ let thenRowFromComposite = (result, expected) => {
175
+ if (result.TAG === "Ok") {
176
+ return thenRow(result._0, expected);
177
+ } else {
178
+ return Outcome$ReventlessGwt.fail(result._0);
179
+ }
180
+ };
181
+ return {
182
+ Spec: Spec,
183
+ describe: JestBind$ReventlessGwt.describe,
184
+ test: test,
185
+ givenStore: givenStore,
186
+ givenCompositeStore: givenCompositeStore,
187
+ whenQueryById: whenQueryById,
188
+ whenQueryByCompositeId: whenQueryByCompositeId,
189
+ whenQuery: whenQuery,
190
+ thenRow: thenRow,
191
+ thenRows: thenRows,
192
+ thenRowCount: thenRowCount,
193
+ thenRowFromComposite: thenRowFromComposite
194
+ };
195
+ }
196
+
197
+ function MakeResolver(Primary) {
198
+ return Target => {
199
+ S.enableJson();
200
+ let sliceName = Primary.name + `→` + Target.name;
201
+ let test = (name, body) => JestBind$ReventlessGwt.test(sliceName, name, body);
202
+ let givenStores = (primary, target) => ({
203
+ primary: primary,
204
+ target: target
205
+ });
206
+ let encTarget = s => S.reverseConvertToJsonOrThrow(s, Target.stateSchema);
207
+ let encTargets = arr => arr.map(encTarget);
208
+ let resolverFor = field => Primary.config.idResolvers.find(r => r.source.idField === field);
209
+ let resolverManyFor = field => Primary.config.idsResolvers.find(r => r.source.idsField === field);
210
+ let missing = msg => ({
211
+ TAG: "QueryRowsMismatch",
212
+ expected: [msg],
213
+ actual: []
214
+ });
215
+ let readField = (state, field) => Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(S.reverseConvertToJsonOrThrow(state, Primary.stateSchema)), d => d[field]);
216
+ let jsonToStr = v => {
217
+ switch (typeof v) {
218
+ case "string" :
219
+ return v;
220
+ case "number" :
221
+ return v.toString();
222
+ default:
223
+ return JSON.stringify(v);
224
+ }
225
+ };
226
+ let lookupTarget = (target, fkId) => Stdlib_Array.findMap(target, param => {
227
+ if (Primitive_object.equal(param[0], fkId)) {
228
+ return Primitive_option.some(param[1]);
229
+ }
230
+ });
231
+ let whenResolve = (scenario, field, primaryId) => {
232
+ let match = resolverFor(field);
233
+ if (match === undefined) {
234
+ return {
235
+ TAG: "Error",
236
+ _0: {
237
+ TAG: "QueryRowsMismatch",
238
+ expected: [`@resolves on field "` + field + `" is missing from ` + Primary.name + `.config.idResolvers`],
239
+ actual: []
240
+ }
241
+ };
242
+ }
243
+ let pstate = Stdlib_Array.findMap(scenario.primary, param => {
244
+ if (param[0] === primaryId) {
245
+ return Primitive_option.some(param[1]);
246
+ }
247
+ });
248
+ if (pstate === undefined) {
249
+ return {
250
+ TAG: "Ok",
251
+ _0: undefined
252
+ };
253
+ }
254
+ let fk = readField(Primitive_option.valFromOption(pstate), field);
255
+ if (fk !== undefined) {
256
+ return {
257
+ TAG: "Ok",
258
+ _0: lookupTarget(scenario.target, jsonToStr(fk))
259
+ };
260
+ } else {
261
+ return {
262
+ TAG: "Ok",
263
+ _0: undefined
264
+ };
265
+ }
266
+ };
267
+ let whenResolveMany = (scenario, field, primaryId) => {
268
+ let match = resolverManyFor(field);
269
+ if (match === undefined) {
270
+ return {
271
+ TAG: "Error",
272
+ _0: {
273
+ TAG: "QueryRowsMismatch",
274
+ expected: [`@resolvesMany on field "` + field + `" is missing from ` + Primary.name + `.config.idsResolvers`],
275
+ actual: []
276
+ }
277
+ };
278
+ }
279
+ let pstate = Stdlib_Array.findMap(scenario.primary, param => {
280
+ if (param[0] === primaryId) {
281
+ return Primitive_option.some(param[1]);
282
+ }
283
+ });
284
+ if (pstate === undefined) {
285
+ return {
286
+ TAG: "Ok",
287
+ _0: []
288
+ };
289
+ }
290
+ let match$1 = readField(Primitive_option.valFromOption(pstate), field);
291
+ if (match$1 !== undefined) {
292
+ if (Array.isArray(match$1)) {
293
+ return {
294
+ TAG: "Ok",
295
+ _0: Stdlib_Array.filterMap(match$1.map(jsonToStr), fkId => lookupTarget(scenario.target, fkId))
296
+ };
297
+ } else {
298
+ return {
299
+ TAG: "Ok",
300
+ _0: []
301
+ };
302
+ }
303
+ } else {
304
+ return {
305
+ TAG: "Ok",
306
+ _0: []
307
+ };
308
+ }
309
+ };
310
+ let thenResolved = (result, expected) => {
311
+ if (result.TAG !== "Ok") {
312
+ return Outcome$ReventlessGwt.fail(result._0);
313
+ }
314
+ let actual = result._0;
315
+ if (Primitive_object.equal(actual, expected)) {
316
+ return Outcome$ReventlessGwt.pass;
317
+ } else {
318
+ return Outcome$ReventlessGwt.fail({
319
+ TAG: "QueryRowsMismatch",
320
+ expected: Stdlib_Option.mapOr(expected, [], s => [S.reverseConvertToJsonOrThrow(s, Target.stateSchema)]),
321
+ actual: Stdlib_Option.mapOr(actual, [], s => [S.reverseConvertToJsonOrThrow(s, Target.stateSchema)])
322
+ });
323
+ }
324
+ };
325
+ let thenResolvedMany = (result, expected) => {
326
+ if (result.TAG !== "Ok") {
327
+ return Outcome$ReventlessGwt.fail(result._0);
328
+ }
329
+ let actual = result._0;
330
+ if (Primitive_object.equal(actual, expected)) {
331
+ return Outcome$ReventlessGwt.pass;
332
+ } else {
333
+ return Outcome$ReventlessGwt.fail({
334
+ TAG: "QueryRowsMismatch",
335
+ expected: expected.map(encTarget),
336
+ actual: actual.map(encTarget)
337
+ });
338
+ }
339
+ };
340
+ return {
341
+ describe: JestBind$ReventlessGwt.describe,
342
+ sliceName: sliceName,
343
+ test: test,
344
+ givenStores: givenStores,
345
+ encTarget: encTarget,
346
+ encTargets: encTargets,
347
+ resolverFor: resolverFor,
348
+ resolverManyFor: resolverManyFor,
349
+ missing: missing,
350
+ readField: readField,
351
+ jsonToStr: jsonToStr,
352
+ lookupTarget: lookupTarget,
353
+ whenResolve: whenResolve,
354
+ whenResolveMany: whenResolveMany,
355
+ thenResolved: thenResolved,
356
+ thenResolvedMany: thenResolvedMany
357
+ };
358
+ };
359
+ }
360
+
361
+ export {
362
+ FromReadModel,
363
+ FromStateViewSlice,
364
+ Make,
365
+ MakeResolver,
366
+ }
367
+ /* S Not a pure module */
@@ -0,0 +1,125 @@
1
+ // Renders a JSON value (produced by sury `Message.encode`) into ReScript
2
+ // source syntax — e.g. the JSON `{"TAG":"CategoryAdded","_0":{"name":"X"}}`
3
+ // becomes the string `CategoryAdded({name: "X"})`.
4
+ //
5
+ // A fully schema-driven renderer would walk `S.t<'a>` and recover every
6
+ // constructor name / record field type. Here we lean on sury's default JS
7
+ // representation instead:
8
+ //
9
+ // - Payload-less variants encode to a bare string ("VariantName").
10
+ // - Single-argument variants encode to `{TAG: "Name", _0: x}`.
11
+ // - Multi-argument variants encode to `{TAG: "Name", _0: x, _1: y, ...}`.
12
+ // - Inline-record variants (`Name({a, b})`) are FLATTENED by ReScript: the
13
+ // record fields sit beside TAG as `{TAG: "Name", a: ..., b: ...}`, NOT under
14
+ // `_0`. These render back as `Name({a: ..., b: ...})`.
15
+ // - Plain records encode to `{field: value, ...}`.
16
+ // - Arrays/tuples encode to JSON arrays.
17
+ //
18
+ // That's enough to produce readable failure diagnostics for every GWT DSL
19
+ // shipped so far. A later pass can replace this with a sury-schema walker
20
+ // for the last 10% of cases (abstract or sealed types, custom schemas).
21
+
22
+ let escapeString = (s: string) => {
23
+ let escaped =
24
+ s
25
+ ->String.replaceAll("\\", "\\\\")
26
+ ->String.replaceAll("\"", "\\\"")
27
+ ->String.replaceAll("\n", "\\n")
28
+ ->String.replaceAll("\r", "\\r")
29
+ ->String.replaceAll("\t", "\\t")
30
+ "\"" ++ escaped ++ "\""
31
+ }
32
+
33
+ let indent = (level: int) => String.repeat(" ", level)
34
+
35
+ let rec render = (~level=0, j: JSON.t): string =>
36
+ switch j {
37
+ | Null => "None"
38
+ | Boolean(true) => "true"
39
+ | Boolean(false) => "false"
40
+ | String(s) => escapeString(s)
41
+ | Number(n) => Float.toString(n)
42
+ | Array(arr) => renderArray(~level, arr)
43
+ | Object(dict) => renderObject(~level, dict)
44
+ }
45
+
46
+ and renderArray = (~level, arr: array<JSON.t>) =>
47
+ switch arr {
48
+ | [] => "[]"
49
+ | _ =>
50
+ let inner = arr->Array.map(render(~level=level + 1, _))->Array.join(", ")
51
+ "[" ++ inner ++ "]"
52
+ }
53
+
54
+ and renderRecord = (~level, keys: array<string>, dict: Dict.t<JSON.t>) => {
55
+ let fields =
56
+ keys
57
+ ->Array.map(k => {
58
+ let v = dict->Dict.getUnsafe(k)
59
+ k ++ ": " ++ render(~level=level + 1, v)
60
+ })
61
+ ->Array.join(", ")
62
+ "{" ++ fields ++ "}"
63
+ }
64
+
65
+ and renderObject = (~level, dict: Dict.t<JSON.t>) => {
66
+ let keys = dict->Dict.keysToArray
67
+ switch dict->Dict.get("TAG") {
68
+ | Some(tagJson) =>
69
+ let tagName = switch tagJson {
70
+ | String(s) => s
71
+ | _ => "?"
72
+ }
73
+ // Positional args are `_0`, `_1`, …; an inline-record variant instead
74
+ // flattens its record fields beside TAG (no `_`-prefixed keys).
75
+ let positional = keys->Array.filter(k => k != "TAG" && String.startsWith(k, "_"))
76
+ let inlineFields = keys->Array.filter(k => k != "TAG" && !String.startsWith(k, "_"))
77
+ switch positional {
78
+ | [] =>
79
+ switch inlineFields {
80
+ | [] => tagName
81
+ | _ => tagName ++ "(" ++ renderRecord(~level, inlineFields, dict) ++ ")"
82
+ }
83
+ | ["_0"] =>
84
+ switch dict->Dict.get("_0") {
85
+ | Some(p) => tagName ++ "(" ++ render(~level=level + 1, p) ++ ")"
86
+ | None => tagName
87
+ }
88
+ | _ =>
89
+ let ordered = positional->Array.toSorted((a, b) => {
90
+ let parseTail = k =>
91
+ String.slice(k, ~start=1, ~end=String.length(k))
92
+ ->Int.fromString
93
+ ->Option.getOr(0)
94
+ Int.compare(parseTail(a), parseTail(b))
95
+ })
96
+ let parts =
97
+ ordered
98
+ ->Array.map(k => render(~level=level + 1, dict->Dict.getUnsafe(k)))
99
+ ->Array.join(", ")
100
+ tagName ++ "(" ++ parts ++ ")"
101
+ }
102
+ | None =>
103
+ switch keys {
104
+ | [] => "{}"
105
+ | _ => renderRecord(~level, keys, dict)
106
+ }
107
+ }
108
+ }
109
+
110
+ let renderMany = (arr: array<JSON.t>): string =>
111
+ switch arr {
112
+ | [] => "[]"
113
+ | [one] => "[" ++ render(one) ++ "]"
114
+ | _ =>
115
+ let inner =
116
+ arr->Array.map(v => indent(1) ++ render(~level=1, v))->Array.join(",\n")
117
+ "[\n" ++ inner ++ ",\n]"
118
+ }
119
+
120
+ // Render an optional JSON as either a ReScript value or the sentinel "None".
121
+ let renderOption = (o: option<JSON.t>): string =>
122
+ switch o {
123
+ | Some(j) => render(j)
124
+ | None => "None"
125
+ }
@@ -0,0 +1,141 @@
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 Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
5
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
+
7
+ function escapeString(s) {
8
+ let escaped = s.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll("\t", "\\t");
9
+ return "\"" + escaped + "\"";
10
+ }
11
+
12
+ function indent(level) {
13
+ return " ".repeat(level);
14
+ }
15
+
16
+ function render(levelOpt, j) {
17
+ let level = levelOpt !== undefined ? levelOpt : 0;
18
+ if (j === null) {
19
+ return "None";
20
+ }
21
+ if (Array.isArray(j)) {
22
+ return renderArray(level, j);
23
+ }
24
+ switch (typeof j) {
25
+ case "boolean" :
26
+ if (j) {
27
+ return "true";
28
+ } else {
29
+ return "false";
30
+ }
31
+ case "string" :
32
+ return escapeString(j);
33
+ case "number" :
34
+ return j.toString();
35
+ case "object" :
36
+ return renderObject(level, j);
37
+ }
38
+ }
39
+
40
+ function renderArray(level, arr) {
41
+ if (arr.length === 0) {
42
+ return "[]";
43
+ }
44
+ let inner = arr.map(__x => render(level + 1 | 0, __x)).join(", ");
45
+ return "[" + inner + "]";
46
+ }
47
+
48
+ function renderRecord(level, keys, dict) {
49
+ let fields = keys.map(k => {
50
+ let v = dict[k];
51
+ return k + ": " + render(level + 1 | 0, v);
52
+ }).join(", ");
53
+ return "{" + fields + "}";
54
+ }
55
+
56
+ function renderObject(level, dict) {
57
+ let keys = Object.keys(dict);
58
+ let tagJson = dict["TAG"];
59
+ if (tagJson === undefined) {
60
+ if (keys.length !== 0) {
61
+ return renderRecord(level, keys, dict);
62
+ } else {
63
+ return "{}";
64
+ }
65
+ }
66
+ let tagName;
67
+ tagName = typeof tagJson === "string" ? tagJson : "?";
68
+ let positional = keys.filter(k => {
69
+ if (k !== "TAG") {
70
+ return k.startsWith("_");
71
+ } else {
72
+ return false;
73
+ }
74
+ });
75
+ let inlineFields = keys.filter(k => {
76
+ if (k !== "TAG") {
77
+ return !k.startsWith("_");
78
+ } else {
79
+ return false;
80
+ }
81
+ });
82
+ let len = positional.length;
83
+ if (len !== 1) {
84
+ if (len === 0) {
85
+ if (inlineFields.length !== 0) {
86
+ return tagName + "(" + renderRecord(level, inlineFields, dict) + ")";
87
+ } else {
88
+ return tagName;
89
+ }
90
+ }
91
+ } else {
92
+ let match = positional[0];
93
+ if (match === "_0") {
94
+ let p = dict["_0"];
95
+ if (p !== undefined) {
96
+ return tagName + "(" + render(level + 1 | 0, p) + ")";
97
+ } else {
98
+ return tagName;
99
+ }
100
+ }
101
+ }
102
+ let ordered = positional.toSorted((a, b) => {
103
+ let parseTail = k => Stdlib_Option.getOr(Stdlib_Int.fromString(k.slice(1, k.length), undefined), 0);
104
+ return Primitive_int.compare(parseTail(a), parseTail(b));
105
+ });
106
+ let parts = ordered.map(k => render(level + 1 | 0, dict[k])).join(", ");
107
+ return tagName + "(" + parts + ")";
108
+ }
109
+
110
+ function renderMany(arr) {
111
+ let len = arr.length;
112
+ if (len !== 1) {
113
+ if (len === 0) {
114
+ return "[]";
115
+ }
116
+ let inner = arr.map(v => " ".repeat(1) + render(1, v)).join(",\n");
117
+ return "[\n" + inner + ",\n]";
118
+ }
119
+ let one = arr[0];
120
+ return "[" + render(undefined, one) + "]";
121
+ }
122
+
123
+ function renderOption(o) {
124
+ if (o !== undefined) {
125
+ return render(undefined, o);
126
+ } else {
127
+ return "None";
128
+ }
129
+ }
130
+
131
+ export {
132
+ escapeString,
133
+ indent,
134
+ render,
135
+ renderArray,
136
+ renderRecord,
137
+ renderObject,
138
+ renderMany,
139
+ renderOption,
140
+ }
141
+ /* No side effect */
@@ -0,0 +1,68 @@
1
+ // Shared data types between the runner loop and formatters.
2
+
3
+ type testStatus = Pass | Fail | Skip
4
+
5
+ type testResult = {
6
+ id: string,
7
+ name: string,
8
+ describePath: array<string>,
9
+ status: testStatus,
10
+ durationMs: float,
11
+ location: option<Collector.location>,
12
+ slice: option<string>,
13
+ mismatch: option<Outcome.mismatch>,
14
+ skipReason: option<string>,
15
+ }
16
+
17
+ type fileResult = {
18
+ path: string,
19
+ tests: array<testResult>,
20
+ }
21
+
22
+ type summary = {
23
+ total: int,
24
+ passed: int,
25
+ failed: int,
26
+ skipped: int,
27
+ files: int,
28
+ durationMs: float,
29
+ startedAt: string,
30
+ }
31
+
32
+ type runResult = {
33
+ summary: summary,
34
+ files: array<fileResult>,
35
+ }
36
+
37
+ let statusString = (s: testStatus) =>
38
+ switch s {
39
+ | Pass => "pass"
40
+ | Fail => "fail"
41
+ | Skip => "skip"
42
+ }
43
+
44
+ let summaryOf = (files: array<fileResult>, durationMs: float, startedAt: string): summary => {
45
+ let total = ref(0)
46
+ let passed = ref(0)
47
+ let failed = ref(0)
48
+ let skipped = ref(0)
49
+ files->Array.forEach(f =>
50
+ f.tests->Array.forEach(t => {
51
+ total := total.contents + 1
52
+ switch t.status {
53
+ | Pass => passed := passed.contents + 1
54
+ | Fail => failed := failed.contents + 1
55
+ | Skip => skipped := skipped.contents + 1
56
+ }
57
+ })
58
+ )
59
+ {
60
+ total: total.contents,
61
+ passed: passed.contents,
62
+ failed: failed.contents,
63
+ skipped: skipped.contents,
64
+ files: files->Array.length,
65
+ durationMs,
66
+ startedAt,
67
+ }
68
+ }