@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.
Files changed (184) hide show
  1. package/CHANGELOG.md +916 -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 +569 -0
  10. package/src/Behavior_GWT.res.mjs +523 -0
  11. package/src/Bind.res +29 -0
  12. package/src/Bind.res.mjs +22 -0
  13. package/src/BuildClassifier.res +147 -0
  14. package/src/BuildClassifier.res.mjs +136 -0
  15. package/src/Cancellation.res +37 -0
  16. package/src/Cancellation.res.mjs +46 -0
  17. package/src/ChildProcess.res +102 -0
  18. package/src/ChildProcess.res.mjs +107 -0
  19. package/src/Cli.res +905 -0
  20. package/src/Cli.res.mjs +952 -0
  21. package/src/Collector.res +212 -0
  22. package/src/Collector.res.mjs +218 -0
  23. package/src/ComponentMeta.res +77 -0
  24. package/src/ComponentMeta.res.mjs +91 -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 +99 -0
  33. package/src/DomainDeadCode.res +98 -0
  34. package/src/DomainDeadCode.res.mjs +72 -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 +45 -0
  40. package/src/Filter.res.mjs +47 -0
  41. package/src/Flow_GWT.res +664 -0
  42. package/src/Flow_GWT.res.mjs +604 -0
  43. package/src/FormatterHuman.res +109 -0
  44. package/src/FormatterHuman.res.mjs +115 -0
  45. package/src/FormatterJson.res +264 -0
  46. package/src/FormatterJson.res.mjs +322 -0
  47. package/src/FormatterJunit.res +93 -0
  48. package/src/FormatterJunit.res.mjs +90 -0
  49. package/src/FormatterTap.res +100 -0
  50. package/src/FormatterTap.res.mjs +131 -0
  51. package/src/FormatterVsCode.res +352 -0
  52. package/src/FormatterVsCode.res.mjs +546 -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 +119 -0
  62. package/src/LocalHost.res.mjs +99 -0
  63. package/src/Mapping_GWT.res +474 -0
  64. package/src/Mapping_GWT.res.mjs +322 -0
  65. package/src/MismatchRender.res +72 -0
  66. package/src/MismatchRender.res.mjs +127 -0
  67. package/src/MultiSourceProjection_GWT.res +316 -0
  68. package/src/MultiSourceProjection_GWT.res.mjs +354 -0
  69. package/src/OutboundTranslation_GWT.res +238 -0
  70. package/src/OutboundTranslation_GWT.res.mjs +186 -0
  71. package/src/Outcome.res +97 -0
  72. package/src/Outcome.res.mjs +93 -0
  73. package/src/PackageScan.res +80 -0
  74. package/src/PackageScan.res.mjs +81 -0
  75. package/src/PlatformRunner.res +181 -0
  76. package/src/PlatformRunner.res.mjs +176 -0
  77. package/src/PlatformScan.res +142 -0
  78. package/src/PlatformScan.res.mjs +132 -0
  79. package/src/ProcessManager.res +135 -0
  80. package/src/ProcessManager.res.mjs +119 -0
  81. package/src/Projection_GWT.res +312 -0
  82. package/src/Projection_GWT.res.mjs +332 -0
  83. package/src/Query_GWT.res +379 -0
  84. package/src/Query_GWT.res.mjs +367 -0
  85. package/src/RenderRescript.res +125 -0
  86. package/src/RenderRescript.res.mjs +141 -0
  87. package/src/RunWorker.res +24 -0
  88. package/src/RunWorker.res.mjs +16 -0
  89. package/src/RunnerTypes.res +68 -0
  90. package/src/RunnerTypes.res.mjs +60 -0
  91. package/src/SideEffect_GWT.res +157 -0
  92. package/src/SideEffect_GWT.res.mjs +113 -0
  93. package/src/StateChange/ExternalAddCategorySlice.res +25 -0
  94. package/src/StateChange/ExternalAddCategorySlice.res.mjs +34 -0
  95. package/src/StateChange/ExternalAddCategorySlice_Behavior.res +19 -0
  96. package/src/StateChange/ExternalAddCategorySlice_Behavior.res.mjs +46 -0
  97. package/src/StateChange/WithFixtures.res +22 -0
  98. package/src/StateChange/WithFixtures.res.mjs +31 -0
  99. package/src/StateChange/WithFixtures_Behavior.res +17 -0
  100. package/src/StateChange/WithFixtures_Behavior.res.mjs +37 -0
  101. package/src/StateChange/WithManualOpen.res +23 -0
  102. package/src/StateChange/WithManualOpen.res.mjs +31 -0
  103. package/src/StateChange/WithManualOpen_Behavior.res +17 -0
  104. package/src/StateChange/WithManualOpen_Behavior.res.mjs +37 -0
  105. package/src/StubRuntime.res +54 -0
  106. package/src/StubRuntime.res.mjs +55 -0
  107. package/src/TestFixtures.res +16 -0
  108. package/src/TestFixtures.res.mjs +34 -0
  109. package/src/Watch.res +108 -0
  110. package/src/Watch.res.mjs +85 -0
  111. package/src/WatcherProbe.res +56 -0
  112. package/src/WatcherProbe.res.mjs +59 -0
  113. package/src/Worker.res +24 -0
  114. package/src/Worker.res.mjs +9 -0
  115. package/tests/AutomationGwtTest.res +71 -0
  116. package/tests/AutomationGwtTest.res.mjs +189 -0
  117. package/tests/BuildClassifierTest.res +133 -0
  118. package/tests/BuildClassifierTest.res.mjs +176 -0
  119. package/tests/CliRunEntryTest.res +57 -0
  120. package/tests/CliRunEntryTest.res.mjs +65 -0
  121. package/tests/CliWatchScopeTest.res +62 -0
  122. package/tests/CliWatchScopeTest.res.mjs +95 -0
  123. package/tests/ComponentMetaTest.res +67 -0
  124. package/tests/ComponentMetaTest.res.mjs +71 -0
  125. package/tests/DelegateGwtTest.res +487 -0
  126. package/tests/DelegateGwtTest.res.mjs +891 -0
  127. package/tests/DiscoveryTest.res +42 -0
  128. package/tests/DiscoveryTest.res.mjs +43 -0
  129. package/tests/DomainDeadCodeTest.res +119 -0
  130. package/tests/DomainDeadCodeTest.res.mjs +158 -0
  131. package/tests/DomainGraphTest.res +448 -0
  132. package/tests/DomainGraphTest.res.mjs +505 -0
  133. package/tests/FlowAggregateGwtTest.res +171 -0
  134. package/tests/FlowAggregateGwtTest.res.mjs +273 -0
  135. package/tests/FlowCrossPluginGwtTest.res +340 -0
  136. package/tests/FlowCrossPluginGwtTest.res.mjs +798 -0
  137. package/tests/FlowGwtTest.res +222 -0
  138. package/tests/FlowGwtTest.res.mjs +433 -0
  139. package/tests/FormatterGoldenTest.res +125 -0
  140. package/tests/FormatterGoldenTest.res.mjs +162 -0
  141. package/tests/FormatterVsCodeMessageTest.res +41 -0
  142. package/tests/FormatterVsCodeMessageTest.res.mjs +42 -0
  143. package/tests/InboundTranslationGwtTest.res +34 -0
  144. package/tests/InboundTranslationGwtTest.res.mjs +99 -0
  145. package/tests/LocalHostIntegration.res +70 -0
  146. package/tests/LocalHostIntegration.res.mjs +64 -0
  147. package/tests/LocalHostTest.res +71 -0
  148. package/tests/LocalHostTest.res.mjs +63 -0
  149. package/tests/MappingGwtTest.res +350 -0
  150. package/tests/MappingGwtTest.res.mjs +596 -0
  151. package/tests/OutboundTranslationGwtTest.res +59 -0
  152. package/tests/OutboundTranslationGwtTest.res.mjs +139 -0
  153. package/tests/PlatformRunnerTest.res +66 -0
  154. package/tests/PlatformRunnerTest.res.mjs +85 -0
  155. package/tests/PlatformScanTest.res +61 -0
  156. package/tests/PlatformScanTest.res.mjs +56 -0
  157. package/tests/QueryGwtTest.res +161 -0
  158. package/tests/QueryGwtTest.res.mjs +314 -0
  159. package/tests/QueryResolverGwtTest.res +71 -0
  160. package/tests/QueryResolverGwtTest.res.mjs +136 -0
  161. package/tests/RunnerUnitTest.res +219 -0
  162. package/tests/RunnerUnitTest.res.mjs +244 -0
  163. package/tests/SideEffect/FakeOrderNotification.res +23 -0
  164. package/tests/SideEffect/FakeOrderNotification.res.mjs +36 -0
  165. package/tests/SideEffect/FakeOrderNotificationGwtTest.res +35 -0
  166. package/tests/SideEffect/FakeOrderNotificationGwtTest.res.mjs +73 -0
  167. package/tests/SideEffect/MockEmail.res +18 -0
  168. package/tests/SideEffect/MockEmail.res.mjs +47 -0
  169. package/tests/StateChange/ExternalAddCategorySlice_GWT.res +27 -0
  170. package/tests/StateChange/ExternalAddCategorySlice_GWT.res.mjs +70 -0
  171. package/tests/StateChange/WithFixtures_Fixtures.res +9 -0
  172. package/tests/StateChange/WithFixtures_Fixtures.res.mjs +20 -0
  173. package/tests/StateChange/WithFixtures_GWT.res +23 -0
  174. package/tests/StateChange/WithFixtures_GWT.res.mjs +56 -0
  175. package/tests/StateChange/WithManualOpen_Fixtures.res +7 -0
  176. package/tests/StateChange/WithManualOpen_Fixtures.res.mjs +20 -0
  177. package/tests/StateChange/WithManualOpen_GWT.res +17 -0
  178. package/tests/StateChange/WithManualOpen_GWT.res.mjs +56 -0
  179. package/tests/StateChangeSliceGwtTest.res +160 -0
  180. package/tests/StateChangeSliceGwtTest.res.mjs +280 -0
  181. package/tests/StateViewSliceGwtTest.res +64 -0
  182. package/tests/StateViewSliceGwtTest.res.mjs +161 -0
  183. package/tests/WatchDebounceTest.res +106 -0
  184. package/tests/WatchDebounceTest.res.mjs +128 -0
@@ -0,0 +1,596 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
5
+ import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
6
+ import * as Mapping_GWT$ReventlessGwt from "../src/Mapping_GWT.res.mjs";
7
+
8
+ S.enableJson();
9
+
10
+ let name = "Category";
11
+
12
+ let commandSchema = S.schema(s => ({
13
+ TAG: "AddCategory",
14
+ categoryId: s.m(S.string),
15
+ name: s.m(S.string)
16
+ }));
17
+
18
+ let eventSchema = S.schema(s => ({
19
+ TAG: "CategoryAdded",
20
+ categoryId: s.m(S.string),
21
+ name: s.m(S.string)
22
+ }));
23
+
24
+ let errorSchema = S.literal("CategoryAlreadyExists");
25
+
26
+ let moduleUrl = "";
27
+
28
+ function commandAuthorization(param) {
29
+ return "AllowAuthenticated";
30
+ }
31
+
32
+ let CategorySpec = {
33
+ Id: undefined,
34
+ name: name,
35
+ commandSchema: commandSchema,
36
+ eventSchema: eventSchema,
37
+ errorSchema: errorSchema,
38
+ moduleUrl: moduleUrl,
39
+ commandAuthorization: commandAuthorization
40
+ };
41
+
42
+ function evolve(_state, event) {
43
+ return "Created";
44
+ }
45
+
46
+ function decide(state, cmd) {
47
+ if (state === "NotCreated") {
48
+ return {
49
+ TAG: "Ok",
50
+ _0: [{
51
+ TAG: "CategoryAdded",
52
+ categoryId: cmd.categoryId,
53
+ name: cmd.name
54
+ }]
55
+ };
56
+ } else {
57
+ return {
58
+ TAG: "Error",
59
+ _0: "CategoryAlreadyExists"
60
+ };
61
+ }
62
+ }
63
+
64
+ let moduleUrl$1 = "";
65
+
66
+ let CategoryBehavior = {
67
+ Spec: undefined,
68
+ initialState: "NotCreated",
69
+ snapshot: undefined,
70
+ evolve: evolve,
71
+ decide: decide,
72
+ moduleUrl: moduleUrl$1
73
+ };
74
+
75
+ let name$1 = "Product";
76
+
77
+ let commandSchema$1 = S.schema(s => ({
78
+ TAG: "MirrorCategory",
79
+ productId: s.m(S.string),
80
+ categoryId: s.m(S.string),
81
+ name: s.m(S.string)
82
+ }));
83
+
84
+ let eventSchema$1 = S.schema(s => ({
85
+ TAG: "ProductCategoryMirrored",
86
+ productId: s.m(S.string),
87
+ categoryId: s.m(S.string),
88
+ name: s.m(S.string)
89
+ }));
90
+
91
+ let errorSchema$1 = S.literal("ProductAlreadyMirrored");
92
+
93
+ let moduleUrl$2 = "";
94
+
95
+ function commandAuthorization$1(param) {
96
+ return "AllowAuthenticated";
97
+ }
98
+
99
+ let ProductSpec = {
100
+ Id: undefined,
101
+ name: name$1,
102
+ commandSchema: commandSchema$1,
103
+ eventSchema: eventSchema$1,
104
+ errorSchema: errorSchema$1,
105
+ moduleUrl: moduleUrl$2,
106
+ commandAuthorization: commandAuthorization$1
107
+ };
108
+
109
+ function evolve$1(_state, event) {
110
+ return "Mirrored";
111
+ }
112
+
113
+ function decide$1(state, cmd) {
114
+ if (state === "Pristine") {
115
+ return {
116
+ TAG: "Ok",
117
+ _0: [{
118
+ TAG: "ProductCategoryMirrored",
119
+ productId: cmd.productId,
120
+ categoryId: cmd.categoryId,
121
+ name: cmd.name
122
+ }]
123
+ };
124
+ } else {
125
+ return {
126
+ TAG: "Error",
127
+ _0: "ProductAlreadyMirrored"
128
+ };
129
+ }
130
+ }
131
+
132
+ let moduleUrl$3 = "";
133
+
134
+ let ProductBehavior = {
135
+ Spec: undefined,
136
+ initialState: "Pristine",
137
+ snapshot: undefined,
138
+ evolve: evolve$1,
139
+ decide: decide$1,
140
+ moduleUrl: moduleUrl$3
141
+ };
142
+
143
+ let consumedEventSchema = S.schema(s => ({
144
+ TAG: "NotificationSent",
145
+ notificationId: s.m(DcbTag$Reventless.string)
146
+ }));
147
+
148
+ function evolve$2(_state, event) {
149
+ return {
150
+ sent: true
151
+ };
152
+ }
153
+
154
+ let commandSchema$2 = S.schema(s => ({
155
+ TAG: "SendNotification",
156
+ notificationId: s.m(DcbTag$Reventless.string),
157
+ message: s.m(S.string)
158
+ }));
159
+
160
+ let errorSchema$2 = S.literal("NotificationAlreadySent");
161
+
162
+ let eventSchema$2 = S.schema(s => ({
163
+ TAG: "NotificationSent",
164
+ notificationId: s.m(DcbTag$Reventless.string),
165
+ message: s.m(S.string)
166
+ }));
167
+
168
+ function decide$2(state, command) {
169
+ if (state.sent) {
170
+ return {
171
+ TAG: "Error",
172
+ _0: "NotificationAlreadySent"
173
+ };
174
+ } else {
175
+ return {
176
+ TAG: "Ok",
177
+ _0: [{
178
+ TAG: "NotificationSent",
179
+ notificationId: command.notificationId,
180
+ message: command.message
181
+ }]
182
+ };
183
+ }
184
+ }
185
+
186
+ function commandAuthorization$2(param) {
187
+ return "AllowAuthenticated";
188
+ }
189
+
190
+ let NotificationSlice_initialState = {
191
+ sent: false
192
+ };
193
+
194
+ let NotificationSlice = {
195
+ name: "Notification",
196
+ initialState: NotificationSlice_initialState,
197
+ consumedEventSchema: consumedEventSchema,
198
+ evolve: evolve$2,
199
+ commandSchema: commandSchema$2,
200
+ errorSchema: errorSchema$2,
201
+ eventSchema: eventSchema$2,
202
+ decide: decide$2,
203
+ commandAuthorization: commandAuthorization$2,
204
+ readConsistency: "EscalateOnRetry"
205
+ };
206
+
207
+ let consumedEventSchema$1 = S.schema(s => ({
208
+ TAG: "StockReserved",
209
+ itemId: s.m(DcbTag$Reventless.string)
210
+ }));
211
+
212
+ function evolve$3(_state, event) {
213
+ return {
214
+ reserved: true
215
+ };
216
+ }
217
+
218
+ let commandSchema$3 = S.schema(s => ({
219
+ TAG: "ReserveStock",
220
+ itemId: s.m(DcbTag$Reventless.string),
221
+ quantity: s.m(S.int)
222
+ }));
223
+
224
+ let errorSchema$3 = S.literal("OutOfStock");
225
+
226
+ let eventSchema$3 = S.schema(s => ({
227
+ TAG: "StockReserved",
228
+ itemId: s.m(DcbTag$Reventless.string),
229
+ quantity: s.m(S.int)
230
+ }));
231
+
232
+ function decide$3(state, command) {
233
+ if (state.reserved) {
234
+ return {
235
+ TAG: "Error",
236
+ _0: "OutOfStock"
237
+ };
238
+ } else {
239
+ return {
240
+ TAG: "Ok",
241
+ _0: [{
242
+ TAG: "StockReserved",
243
+ itemId: command.itemId,
244
+ quantity: command.quantity
245
+ }]
246
+ };
247
+ }
248
+ }
249
+
250
+ function commandAuthorization$3(param) {
251
+ return "AllowAuthenticated";
252
+ }
253
+
254
+ let InventorySlice_initialState = {
255
+ reserved: false
256
+ };
257
+
258
+ let InventorySlice = {
259
+ name: "Inventory",
260
+ initialState: InventorySlice_initialState,
261
+ consumedEventSchema: consumedEventSchema$1,
262
+ evolve: evolve$3,
263
+ commandSchema: commandSchema$3,
264
+ errorSchema: errorSchema$3,
265
+ eventSchema: eventSchema$3,
266
+ decide: decide$3,
267
+ commandAuthorization: commandAuthorization$3,
268
+ readConsistency: "EscalateOnRetry"
269
+ };
270
+
271
+ let CategorySource = Mapping_GWT$ReventlessGwt.FromBehavior({
272
+ Id: {
273
+ schema: Id$Reventless.StringPure.schema,
274
+ make: prim => prim,
275
+ makeFromString: prim => prim,
276
+ toString: prim => prim,
277
+ cmp: Id$Reventless.StringPure.cmp
278
+ },
279
+ name: name,
280
+ eventSchema: eventSchema,
281
+ errorSchema: errorSchema,
282
+ commandSchema: commandSchema,
283
+ moduleUrl: moduleUrl,
284
+ commandAuthorization: commandAuthorization
285
+ })({
286
+ Spec: {
287
+ Id: {
288
+ schema: Id$Reventless.StringPure.schema,
289
+ make: prim => prim,
290
+ makeFromString: prim => prim,
291
+ toString: prim => prim,
292
+ cmp: Id$Reventless.StringPure.cmp
293
+ },
294
+ name: name,
295
+ eventSchema: eventSchema,
296
+ errorSchema: errorSchema,
297
+ commandSchema: commandSchema,
298
+ moduleUrl: moduleUrl,
299
+ commandAuthorization: commandAuthorization
300
+ },
301
+ initialState: "NotCreated",
302
+ evolve: evolve,
303
+ decide: decide,
304
+ snapshot: undefined,
305
+ moduleUrl: moduleUrl$1
306
+ });
307
+
308
+ let ProductTarget = Mapping_GWT$ReventlessGwt.FromBehavior({
309
+ Id: {
310
+ schema: Id$Reventless.StringPure.schema,
311
+ make: prim => prim,
312
+ makeFromString: prim => prim,
313
+ toString: prim => prim,
314
+ cmp: Id$Reventless.StringPure.cmp
315
+ },
316
+ name: name$1,
317
+ eventSchema: eventSchema$1,
318
+ errorSchema: errorSchema$1,
319
+ commandSchema: commandSchema$1,
320
+ moduleUrl: moduleUrl$2,
321
+ commandAuthorization: commandAuthorization$1
322
+ })({
323
+ Spec: {
324
+ Id: {
325
+ schema: Id$Reventless.StringPure.schema,
326
+ make: prim => prim,
327
+ makeFromString: prim => prim,
328
+ toString: prim => prim,
329
+ cmp: Id$Reventless.StringPure.cmp
330
+ },
331
+ name: name$1,
332
+ eventSchema: eventSchema$1,
333
+ errorSchema: errorSchema$1,
334
+ commandSchema: commandSchema$1,
335
+ moduleUrl: moduleUrl$2,
336
+ commandAuthorization: commandAuthorization$1
337
+ },
338
+ initialState: "Pristine",
339
+ evolve: evolve$1,
340
+ decide: decide$1,
341
+ snapshot: undefined,
342
+ moduleUrl: moduleUrl$3
343
+ });
344
+
345
+ let NotificationSource = Mapping_GWT$ReventlessGwt.FromStateChangeSlice(NotificationSlice);
346
+
347
+ let NotificationTarget = Mapping_GWT$ReventlessGwt.FromStateChangeSlice(NotificationSlice);
348
+
349
+ let InventoryTarget = Mapping_GWT$ReventlessGwt.FromStateChangeSlice(InventorySlice);
350
+
351
+ function map(_sourceId, event, _q) {
352
+ let categoryId = event.categoryId;
353
+ return [{
354
+ TAG: "Publish",
355
+ _0: "prod-for-" + categoryId,
356
+ _1: {
357
+ TAG: "MirrorCategory",
358
+ productId: "prod-for-" + categoryId,
359
+ categoryId: categoryId,
360
+ name: event.name
361
+ }
362
+ }];
363
+ }
364
+
365
+ let AggrToAggrMapping = {
366
+ Source: undefined,
367
+ Target: undefined,
368
+ map: map
369
+ };
370
+
371
+ let AggrToAggrGwt = Mapping_GWT$ReventlessGwt.Make({
372
+ Source: CategorySource,
373
+ Target: ProductTarget,
374
+ map: map
375
+ });
376
+
377
+ AggrToAggrGwt.describe("Category → Product (Aggr → Aggr)", () => AggrToAggrGwt.test("AddCategory produces ProductCategoryMirrored on product", undefined, () => AggrToAggrGwt.thenTargetEvent(AggrToAggrGwt.whenSourceCmd(AggrToAggrGwt.andTargetEvents(AggrToAggrGwt.givenSourceEvents([]), []), "c1", {
378
+ TAG: "AddCategory",
379
+ categoryId: "c1",
380
+ name: "Books"
381
+ }), "prod-for-c1", {
382
+ TAG: "ProductCategoryMirrored",
383
+ productId: "prod-for-c1",
384
+ categoryId: "c1",
385
+ name: "Books"
386
+ })));
387
+
388
+ function map$1(_sourceId, event, _q) {
389
+ let categoryId = event.categoryId;
390
+ return [{
391
+ TAG: "Publish",
392
+ _0: "notif-" + categoryId,
393
+ _1: {
394
+ TAG: "SendNotification",
395
+ notificationId: "notif-" + categoryId,
396
+ message: `Category ` + event.name + ` was created`
397
+ }
398
+ }];
399
+ }
400
+
401
+ let AggrToDcbMapping = {
402
+ Source: undefined,
403
+ Target: undefined,
404
+ map: map$1
405
+ };
406
+
407
+ let AggrToDcbGwt = Mapping_GWT$ReventlessGwt.Make({
408
+ Source: CategorySource,
409
+ Target: {
410
+ name: NotificationTarget.name,
411
+ Id: {
412
+ schema: Id$Reventless.StringPure.schema,
413
+ make: prim => prim,
414
+ makeFromString: prim => prim,
415
+ toString: prim => prim,
416
+ cmp: Id$Reventless.StringPure.cmp
417
+ },
418
+ initialState: NotificationTarget.initialState,
419
+ consumedEventSchema: NotificationTarget.consumedEventSchema,
420
+ evolve: NotificationTarget.evolve,
421
+ commandSchema: NotificationTarget.commandSchema,
422
+ eventSchema: NotificationTarget.eventSchema,
423
+ errorSchema: NotificationTarget.errorSchema,
424
+ decide: NotificationTarget.decide
425
+ },
426
+ map: map$1
427
+ });
428
+
429
+ AggrToDcbGwt.describe("Category → Notification (Aggr → DCB)", () => AggrToDcbGwt.test("AddCategory triggers NotificationSent on the DCB slice", undefined, () => AggrToDcbGwt.thenTargetEvent(AggrToDcbGwt.whenSourceCmd(AggrToDcbGwt.andTargetEvents(AggrToDcbGwt.givenSourceEvents([]), []), "c2", {
430
+ TAG: "AddCategory",
431
+ categoryId: "c2",
432
+ name: "Media"
433
+ }), "notif-c2", {
434
+ TAG: "NotificationSent",
435
+ notificationId: "notif-c2",
436
+ message: "Category Media was created"
437
+ })));
438
+
439
+ let InventorySource = Mapping_GWT$ReventlessGwt.FromStateChangeSlice(InventorySlice);
440
+
441
+ function map$2(_sourceId, event, _q) {
442
+ let itemId = event.itemId;
443
+ return [{
444
+ TAG: "Publish",
445
+ _0: "prod-" + itemId,
446
+ _1: {
447
+ TAG: "MirrorCategory",
448
+ productId: "prod-" + itemId,
449
+ categoryId: itemId,
450
+ name: itemId
451
+ }
452
+ }];
453
+ }
454
+
455
+ let DcbToAggrMapping = {
456
+ Source: undefined,
457
+ Target: undefined,
458
+ map: map$2
459
+ };
460
+
461
+ let DcbToAggrGwt = Mapping_GWT$ReventlessGwt.Make({
462
+ Source: {
463
+ name: InventorySource.name,
464
+ Id: {
465
+ schema: Id$Reventless.StringPure.schema,
466
+ make: prim => prim,
467
+ makeFromString: prim => prim,
468
+ toString: prim => prim,
469
+ cmp: Id$Reventless.StringPure.cmp
470
+ },
471
+ initialState: InventorySource.initialState,
472
+ consumedEventSchema: InventorySource.consumedEventSchema,
473
+ evolve: InventorySource.evolve,
474
+ commandSchema: InventorySource.commandSchema,
475
+ eventSchema: InventorySource.eventSchema,
476
+ errorSchema: InventorySource.errorSchema,
477
+ decide: InventorySource.decide
478
+ },
479
+ Target: ProductTarget,
480
+ map: map$2
481
+ });
482
+
483
+ DcbToAggrGwt.describe("Inventory → Product (DCB → Aggr)", () => DcbToAggrGwt.test("ReserveStock triggers ProductCategoryMirrored", undefined, () => DcbToAggrGwt.thenTargetEvent(DcbToAggrGwt.whenSourceCmd(DcbToAggrGwt.andTargetEvents(DcbToAggrGwt.givenSourceEvents([]), []), "i1", {
484
+ TAG: "ReserveStock",
485
+ itemId: "i1",
486
+ quantity: 5
487
+ }), "prod-i1", {
488
+ TAG: "ProductCategoryMirrored",
489
+ productId: "prod-i1",
490
+ categoryId: "i1",
491
+ name: "i1"
492
+ })));
493
+
494
+ function map$3(_sourceId, event, _q) {
495
+ let itemId = event.itemId;
496
+ return [{
497
+ TAG: "Publish",
498
+ _0: "reserved-" + itemId,
499
+ _1: {
500
+ TAG: "SendNotification",
501
+ notificationId: "reserved-" + itemId,
502
+ message: `Reserved ` + event.quantity.toString() + ` of ` + itemId
503
+ }
504
+ }];
505
+ }
506
+
507
+ let DcbToDcbMapping = {
508
+ Source: undefined,
509
+ Target: undefined,
510
+ map: map$3
511
+ };
512
+
513
+ let DcbToDcbGwt = Mapping_GWT$ReventlessGwt.Make({
514
+ Source: {
515
+ name: InventorySource.name,
516
+ Id: {
517
+ schema: Id$Reventless.StringPure.schema,
518
+ make: prim => prim,
519
+ makeFromString: prim => prim,
520
+ toString: prim => prim,
521
+ cmp: Id$Reventless.StringPure.cmp
522
+ },
523
+ initialState: InventorySource.initialState,
524
+ consumedEventSchema: InventorySource.consumedEventSchema,
525
+ evolve: InventorySource.evolve,
526
+ commandSchema: InventorySource.commandSchema,
527
+ eventSchema: InventorySource.eventSchema,
528
+ errorSchema: InventorySource.errorSchema,
529
+ decide: InventorySource.decide
530
+ },
531
+ Target: {
532
+ name: NotificationTarget.name,
533
+ Id: {
534
+ schema: Id$Reventless.StringPure.schema,
535
+ make: prim => prim,
536
+ makeFromString: prim => prim,
537
+ toString: prim => prim,
538
+ cmp: Id$Reventless.StringPure.cmp
539
+ },
540
+ initialState: NotificationTarget.initialState,
541
+ consumedEventSchema: NotificationTarget.consumedEventSchema,
542
+ evolve: NotificationTarget.evolve,
543
+ commandSchema: NotificationTarget.commandSchema,
544
+ eventSchema: NotificationTarget.eventSchema,
545
+ errorSchema: NotificationTarget.errorSchema,
546
+ decide: NotificationTarget.decide
547
+ },
548
+ map: map$3
549
+ });
550
+
551
+ DcbToDcbGwt.describe("Inventory → Notification (DCB → DCB)", () => {
552
+ DcbToDcbGwt.test("ReserveStock triggers NotificationSent", undefined, () => DcbToDcbGwt.thenTargetEvent(DcbToDcbGwt.whenSourceCmd(DcbToDcbGwt.andTargetEvents(DcbToDcbGwt.givenSourceEvents([]), []), "i7", {
553
+ TAG: "ReserveStock",
554
+ itemId: "i7",
555
+ quantity: 2
556
+ }), "reserved-i7", {
557
+ TAG: "NotificationSent",
558
+ notificationId: "reserved-i7",
559
+ message: "Reserved 2 of i7"
560
+ }));
561
+ DcbToDcbGwt.test("existing NotificationSent causes target decide to reject", undefined, () => DcbToDcbGwt.thenTargetError(DcbToDcbGwt.whenSourceCmd(DcbToDcbGwt.andTargetEvents(DcbToDcbGwt.givenSourceEvents([]), [[
562
+ "reserved-i7",
563
+ [{
564
+ TAG: "NotificationSent",
565
+ notificationId: "reserved-i7"
566
+ }]
567
+ ]]), "i7", {
568
+ TAG: "ReserveStock",
569
+ itemId: "i7",
570
+ quantity: 2
571
+ }), "NotificationAlreadySent"));
572
+ });
573
+
574
+ export {
575
+ CategorySpec,
576
+ CategoryBehavior,
577
+ ProductSpec,
578
+ ProductBehavior,
579
+ NotificationSlice,
580
+ InventorySlice,
581
+ CategorySource,
582
+ ProductTarget,
583
+ NotificationSource,
584
+ NotificationTarget,
585
+ InventoryTarget,
586
+ AggrToAggrMapping,
587
+ AggrToAggrGwt,
588
+ AggrToDcbMapping,
589
+ AggrToDcbGwt,
590
+ InventorySource,
591
+ DcbToAggrMapping,
592
+ DcbToAggrGwt,
593
+ DcbToDcbMapping,
594
+ DcbToDcbGwt,
595
+ }
596
+ /* Not a pure module */
@@ -0,0 +1,59 @@
1
+ // Worked example for OutboundTranslationSlice_GWT — a "send tracking email"
2
+ // slice. Collect builds a TODO from OrderShipped; translate is mocked to
3
+ // exercise both happy path (fire-and-forget success) and failure (retry).
4
+
5
+ @@reventless.gwt
6
+
7
+ module SendTrackingEmailSlice = {
8
+ let name = "SendTrackingEmail"
9
+
10
+ @schema
11
+ type consumedEvent = OrderShipped({orderId: string, email: string})
12
+
13
+ @schema
14
+ type outboundItem = {orderId: string, email: string}
15
+
16
+ @schema
17
+ type inboundCommand = NoOp
18
+
19
+ let collect = event =>
20
+ switch event {
21
+ | OrderShipped({orderId, email}) => [(orderId, {orderId, email})]
22
+ }
23
+ }
24
+
25
+ describe("SendTrackingEmail OutboundTranslationSlice", () => {
26
+ test("collect: OrderShipped queues an outbound TODO", async () =>
27
+ givenEvent(OrderShipped({orderId: "o1", email: "x@y"}))
28
+ ->whenCollect
29
+ ->thenTodos([("o1", {orderId: "o1", email: "x@y"})])
30
+ )
31
+
32
+ test("translate success is fire-and-forget → #Completed", () =>
33
+ givenTodo("o1", {orderId: "o1", email: "x@y"})
34
+ ->whenTranslateMocked((_id, _item) => Promise.resolve(Ok(None)))
35
+ ->thenTodoStatus("o1", #Completed)
36
+ )
37
+
38
+ test("translate failure records a retry → #Pending", () =>
39
+ givenTodo("o1", {orderId: "o1", email: "x@y"})
40
+ ->whenTranslateMocked((_id, _item) => Promise.resolve(Error("smtp down")))
41
+ ->thenTodoStatus("o1", #Pending)
42
+ )
43
+
44
+ test("retrying translate succeeds on the third attempt → 2 retries recorded", () => {
45
+ let calls = ref(0)
46
+ givenTodo("o1", {orderId: "o1", email: "x@y"})
47
+ ->whenTranslateRetrying(~maxRetries=3, (_id, _item) => {
48
+ calls := calls.contents + 1
49
+ Promise.resolve(calls.contents < 3 ? Error("smtp down") : Ok(None))
50
+ })
51
+ ->thenRetryRecorded(2)
52
+ })
53
+
54
+ test("translate that keeps failing exhausts maxRetries", () =>
55
+ givenTodo("o1", {orderId: "o1", email: "x@y"})
56
+ ->whenTranslateRetrying(~maxRetries=3, (_id, _item) => Promise.resolve(Error("smtp down")))
57
+ ->thenRetryRecorded(3)
58
+ )
59
+ })