@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,60 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function statusString(s) {
5
+ switch (s) {
6
+ case "Pass" :
7
+ return "pass";
8
+ case "Fail" :
9
+ return "fail";
10
+ case "Skip" :
11
+ return "skip";
12
+ }
13
+ }
14
+
15
+ function summaryOf(files, durationMs, startedAt) {
16
+ let total = {
17
+ contents: 0
18
+ };
19
+ let passed = {
20
+ contents: 0
21
+ };
22
+ let failed = {
23
+ contents: 0
24
+ };
25
+ let skipped = {
26
+ contents: 0
27
+ };
28
+ files.forEach(f => {
29
+ f.tests.forEach(t => {
30
+ total.contents = total.contents + 1 | 0;
31
+ let match = t.status;
32
+ switch (match) {
33
+ case "Pass" :
34
+ passed.contents = passed.contents + 1 | 0;
35
+ return;
36
+ case "Fail" :
37
+ failed.contents = failed.contents + 1 | 0;
38
+ return;
39
+ case "Skip" :
40
+ skipped.contents = skipped.contents + 1 | 0;
41
+ return;
42
+ }
43
+ });
44
+ });
45
+ return {
46
+ total: total.contents,
47
+ passed: passed.contents,
48
+ failed: failed.contents,
49
+ skipped: skipped.contents,
50
+ files: files.length,
51
+ durationMs: durationMs,
52
+ startedAt: startedAt
53
+ };
54
+ }
55
+
56
+ export {
57
+ statusString,
58
+ summaryOf,
59
+ }
60
+ /* No side effect */
@@ -0,0 +1,157 @@
1
+ open ReventlessCore
2
+
3
+ // Test DSL for aggregate-style egress (`SideEffect.T`). Mirrors
4
+ // `OutboundTranslation_GWT` adapted to the SideEffect runtime contract: the
5
+ // unit under test is `SE.execute`, which returns `promise<unit>` and reaches
6
+ // external services through direct module imports. Option C of the
7
+ // `sideeffect-gwt` plan: the framework stays out of the import mechanics —
8
+ // per-service `*_Mock.res` modules own the recording state and surface it
9
+ // through this `mock` handle. The GWT runs `execute`, then reads the snapshot
10
+ // and renders assertions against captured calls.
11
+
12
+ // Polymorphic mock handle a test passes to `whenExecuted`. The mock module
13
+ // owns the recording state (a `ref<array<call>>` mutated as the SE calls the
14
+ // service); `snapshot` reads it; `encode` is used to render mismatched calls
15
+ // in failure messages.
16
+ type mock<'call> = {
17
+ snapshot: unit => array<'call>,
18
+ encode: 'call => JSON.t,
19
+ }
20
+
21
+ // Stub `QueryEngine.operations` used when a test doesn't pass its own.
22
+ // Returns empty result sets — enough for SEs that never query, which is the
23
+ // idiomatic shape.
24
+ let stubQueryEngine: Reventless.QueryEngine.operations = {
25
+ scan: async (~readModelName as _, ~filterConfigs as _, ~limit as _) => [],
26
+ query: async (
27
+ ~readModelName as _,
28
+ ~key as _=?,
29
+ ~id as _,
30
+ ~subIdConfig as _=?,
31
+ ~filterConfigs as _=?,
32
+ ~ascending as _=?,
33
+ ~limit as _=?,
34
+ ) => [],
35
+ }
36
+
37
+ module type T = {
38
+ module SE: Reventless.SideEffect.T
39
+
40
+ let describe: (string, unit => unit) => unit
41
+ let test: (string, ~timeout: int=?, unit => promise<Outcome.outcome>) => unit
42
+
43
+ type input = {
44
+ id: SE.Source.Id.t,
45
+ meta: Message.meta,
46
+ event: SE.Source.event,
47
+ }
48
+
49
+ // Post-execution state the pipeline carries forward. Holds the inputs (so
50
+ // failure messages can quote them), the captured calls, and the encoder
51
+ // (passed through from the mock) used to render them.
52
+ type attempt<'call> = {
53
+ input: input,
54
+ captured: array<'call>,
55
+ encode: 'call => JSON.t,
56
+ }
57
+
58
+ // given*
59
+ let givenEvent: SE.Source.event => input
60
+ let givenEventForId: (SE.Source.Id.t, SE.Source.event) => input
61
+ let givenMeta: (input, Message.meta) => input
62
+
63
+ // when — runs `SE.execute` against a stub QueryEngine (override via
64
+ // ~queryEngine) and the supplied mock's snapshot. The mock module is
65
+ // expected to install itself into the service it shadows BEFORE this is
66
+ // called (the per-service `*_Mock.res` convention; see the example).
67
+ let whenExecuted: (
68
+ input,
69
+ mock<'call>,
70
+ ~queryEngine: Reventless.QueryEngine.operations=?,
71
+ ) => promise<attempt<'call>>
72
+
73
+ // then*
74
+ let thenNoExternalCalls: promise<attempt<'call>> => promise<Outcome.outcome>
75
+ let thenExternalCalls: (promise<attempt<'call>>, array<'call>) => promise<Outcome.outcome>
76
+ let thenExternalCallCount: (promise<attempt<'call>>, int) => promise<Outcome.outcome>
77
+ }
78
+
79
+ module Make = (SE: Reventless.SideEffect.T): (T with module SE = SE) => {
80
+ module SE = SE
81
+
82
+ S.enableJson()
83
+
84
+ let describe = JestBind.describe
85
+ let test = (name, ~timeout=?, body) =>
86
+ JestBind.testPromise(~slice=SE.Source.name, name, ~timeout?, body)
87
+
88
+ type input = {
89
+ id: SE.Source.Id.t,
90
+ meta: Message.meta,
91
+ event: SE.Source.event,
92
+ }
93
+
94
+ type attempt<'call> = {
95
+ input: input,
96
+ captured: array<'call>,
97
+ encode: 'call => JSON.t,
98
+ }
99
+
100
+ let defaultId = SE.Source.Id.makeFromString("test-id-1")
101
+ let defaultMeta: Message.meta = {
102
+ service: SE.Source.name,
103
+ time: "2024-01-01T00:00:00Z",
104
+ msgId: "test-msg-1",
105
+ correlationId: "test-msg-1",
106
+ }
107
+
108
+ let givenEvent = event => {id: defaultId, meta: defaultMeta, event}
109
+ let givenEventForId = (id, event) => {id, meta: defaultMeta, event}
110
+ let givenMeta = (input, meta) => {...input, meta}
111
+
112
+ let whenExecuted = async (input, mock, ~queryEngine=stubQueryEngine) => {
113
+ await SE.execute(input.id, input.meta, input.event, queryEngine)
114
+ {input, captured: mock.snapshot(), encode: mock.encode}
115
+ }
116
+
117
+ let encCalls = (calls, encode) => calls->Array.map(encode)
118
+
119
+ let thenNoExternalCalls = async pending => {
120
+ let {captured, encode, _} = await pending
121
+ if captured == [] {
122
+ Outcome.pass
123
+ } else {
124
+ Outcome.fail(NoEventExpected({actual: encCalls(captured, encode)}))
125
+ }
126
+ }
127
+
128
+ let thenExternalCalls = async (pending, expected) => {
129
+ let {captured, encode, _} = await pending
130
+ if captured == expected {
131
+ Outcome.pass
132
+ } else {
133
+ Outcome.fail(
134
+ EventsMismatch({
135
+ expected: encCalls(expected, encode),
136
+ actual: encCalls(captured, encode),
137
+ }),
138
+ )
139
+ }
140
+ }
141
+
142
+ let thenExternalCallCount = async (pending, expected) => {
143
+ let {captured, _} = await pending
144
+ let actual = Array.length(captured)
145
+ if actual == expected {
146
+ Outcome.pass
147
+ } else {
148
+ Outcome.fail(
149
+ StateMismatch({
150
+ key: "external-call-count",
151
+ expected: Some(JSON.Encode.int(expected)),
152
+ actual: Some(JSON.Encode.int(actual)),
153
+ }),
154
+ )
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,113 @@
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
+
8
+ async function stubQueryEngine_scan(param, param$1, param$2) {
9
+ return [];
10
+ }
11
+
12
+ async function stubQueryEngine_query(param, param$1, param$2, param$3, param$4, param$5, param$6) {
13
+ return [];
14
+ }
15
+
16
+ let stubQueryEngine = {
17
+ scan: stubQueryEngine_scan,
18
+ query: stubQueryEngine_query
19
+ };
20
+
21
+ function Make(SE) {
22
+ S.enableJson();
23
+ let test = (name, timeout, body) => JestBind$ReventlessGwt.testPromise(SE.Source.name, name, timeout, body);
24
+ let defaultId = SE.Source.Id.makeFromString("test-id-1");
25
+ let defaultMeta_service = SE.Source.name;
26
+ let defaultMeta = {
27
+ service: defaultMeta_service,
28
+ time: "2024-01-01T00:00:00Z",
29
+ msgId: "test-msg-1",
30
+ correlationId: "test-msg-1"
31
+ };
32
+ let givenEvent = event => ({
33
+ id: defaultId,
34
+ meta: defaultMeta,
35
+ event: event
36
+ });
37
+ let givenEventForId = (id, event) => ({
38
+ id: id,
39
+ meta: defaultMeta,
40
+ event: event
41
+ });
42
+ let givenMeta = (input, meta) => ({
43
+ id: input.id,
44
+ meta: meta,
45
+ event: input.event
46
+ });
47
+ let whenExecuted = async (input, mock, queryEngineOpt) => {
48
+ let queryEngine = queryEngineOpt !== undefined ? queryEngineOpt : stubQueryEngine;
49
+ await SE.execute(input.id, input.meta, input.event, queryEngine);
50
+ return {
51
+ input: input,
52
+ captured: mock.snapshot(),
53
+ encode: mock.encode
54
+ };
55
+ };
56
+ let thenNoExternalCalls = async pending => {
57
+ let match = await pending;
58
+ let captured = match.captured;
59
+ if (Primitive_object.equal(captured, [])) {
60
+ return Outcome$ReventlessGwt.pass;
61
+ } else {
62
+ return Outcome$ReventlessGwt.fail({
63
+ TAG: "NoEventExpected",
64
+ actual: captured.map(match.encode)
65
+ });
66
+ }
67
+ };
68
+ let thenExternalCalls = async (pending, expected) => {
69
+ let match = await pending;
70
+ let captured = match.captured;
71
+ if (Primitive_object.equal(captured, expected)) {
72
+ return Outcome$ReventlessGwt.pass;
73
+ }
74
+ let encode = match.encode;
75
+ return Outcome$ReventlessGwt.fail({
76
+ TAG: "EventsMismatch",
77
+ expected: expected.map(encode),
78
+ actual: captured.map(encode)
79
+ });
80
+ };
81
+ let thenExternalCallCount = async (pending, expected) => {
82
+ let match = await pending;
83
+ let actual = match.captured.length;
84
+ if (actual === expected) {
85
+ return Outcome$ReventlessGwt.pass;
86
+ } else {
87
+ return Outcome$ReventlessGwt.fail({
88
+ TAG: "StateMismatch",
89
+ key: "external-call-count",
90
+ expected: expected,
91
+ actual: actual
92
+ });
93
+ }
94
+ };
95
+ return {
96
+ SE: SE,
97
+ describe: JestBind$ReventlessGwt.describe,
98
+ test: test,
99
+ givenEvent: givenEvent,
100
+ givenEventForId: givenEventForId,
101
+ givenMeta: givenMeta,
102
+ whenExecuted: whenExecuted,
103
+ thenNoExternalCalls: thenNoExternalCalls,
104
+ thenExternalCalls: thenExternalCalls,
105
+ thenExternalCallCount: thenExternalCallCount
106
+ };
107
+ }
108
+
109
+ export {
110
+ stubQueryEngine,
111
+ Make,
112
+ }
113
+ /* S Not a pure module */
@@ -0,0 +1,25 @@
1
+ // Production-shaped StateChangeSlice Spec used by the external-Spec
2
+ // verification test at [tests/StateChange/ExternalAddCategorySlice_GWT.res].
3
+ // Mirrors the worked-example AddCategory slice shape: DCB-tagged categoryId
4
+ // on command + event, payload-less consumed events.
5
+ //
6
+ // Spec half (Plan 02 Phase 6) — types, schemas, name. The matching impl
7
+ // half lives in [ExternalAddCategorySlice_Behavior.res].
8
+
9
+ let name = "ExternalAddCategory"
10
+
11
+ @schema
12
+ type consumedEvent =
13
+ | CategoryAdded
14
+ | CategoryArchived
15
+
16
+ @schema
17
+ type command =
18
+ AddCategory({categoryId: @s.matches(Reventless.DcbTag.string) string, name: string})
19
+
20
+ @schema
21
+ type error = CategoryAlreadyExists
22
+
23
+ @schema
24
+ type event =
25
+ CategoryAdded({categoryId: @s.matches(Reventless.DcbTag.string) string, name: string})
@@ -0,0 +1,34 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
5
+
6
+ let consumedEventSchema = S.union([
7
+ S.literal("CategoryAdded"),
8
+ S.literal("CategoryArchived")
9
+ ]);
10
+
11
+ let commandSchema = S.schema(s => ({
12
+ TAG: "AddCategory",
13
+ categoryId: s.m(DcbTag$Reventless.string),
14
+ name: s.m(S.string)
15
+ }));
16
+
17
+ let errorSchema = S.literal("CategoryAlreadyExists");
18
+
19
+ let eventSchema = S.schema(s => ({
20
+ TAG: "CategoryAdded",
21
+ categoryId: s.m(DcbTag$Reventless.string),
22
+ name: s.m(S.string)
23
+ }));
24
+
25
+ let name = "ExternalAddCategory";
26
+
27
+ export {
28
+ name,
29
+ consumedEventSchema,
30
+ commandSchema,
31
+ errorSchema,
32
+ eventSchema,
33
+ }
34
+ /* consumedEventSchema Not a pure module */
@@ -0,0 +1,19 @@
1
+ // Implementation half — pure decision/projection functions for the external
2
+ // AddCategory StateChangeSlice. Pairs with [ExternalAddCategorySlice.res].
3
+
4
+ open ExternalAddCategorySlice
5
+
6
+ type state = {exists: bool, archived: bool}
7
+ let initialState: state = {exists: false, archived: false}
8
+
9
+ let evolve = (state: state, event: consumedEvent): state =>
10
+ switch event {
11
+ | CategoryAdded => {exists: true, archived: false}
12
+ | CategoryArchived => {...state, archived: true}
13
+ }
14
+
15
+ let decide = (state: state, command: command): result<array<event>, error> =>
16
+ switch command {
17
+ | AddCategory({categoryId, name}) =>
18
+ state.exists ? Error(CategoryAlreadyExists) : Ok([CategoryAdded({categoryId, name})])
19
+ }
@@ -0,0 +1,46 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function evolve(state, event) {
5
+ if (event === "CategoryAdded") {
6
+ return {
7
+ exists: true,
8
+ archived: false
9
+ };
10
+ } else {
11
+ return {
12
+ exists: state.exists,
13
+ archived: true
14
+ };
15
+ }
16
+ }
17
+
18
+ function decide(state, command) {
19
+ if (state.exists) {
20
+ return {
21
+ TAG: "Error",
22
+ _0: "CategoryAlreadyExists"
23
+ };
24
+ } else {
25
+ return {
26
+ TAG: "Ok",
27
+ _0: [{
28
+ TAG: "CategoryAdded",
29
+ categoryId: command.categoryId,
30
+ name: command.name
31
+ }]
32
+ };
33
+ }
34
+ }
35
+
36
+ let initialState = {
37
+ exists: false,
38
+ archived: false
39
+ };
40
+
41
+ export {
42
+ initialState,
43
+ evolve,
44
+ decide,
45
+ }
46
+ /* No side effect */
@@ -0,0 +1,22 @@
1
+ // Production-shaped Spec for the companion-fixtures auto-open verification
2
+ // tests at [tests/StateChange/WithFixtures_GWT.res] and
3
+ // [tests/StateChange/WithManualOpen_GWT.res].
4
+ //
5
+ // Spec half — pairs with [WithFixtures_Behavior.res].
6
+
7
+ let name = "WithFixtures"
8
+
9
+ @schema
10
+ type consumedEvent =
11
+ | CategoryAdded
12
+
13
+ @schema
14
+ type command =
15
+ AddCategory({categoryId: @s.matches(Reventless.DcbTag.string) string, name: string})
16
+
17
+ @schema
18
+ type error = CategoryAlreadyExists
19
+
20
+ @schema
21
+ type event =
22
+ CategoryAdded({categoryId: @s.matches(Reventless.DcbTag.string) string, name: string})
@@ -0,0 +1,31 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
5
+
6
+ let consumedEventSchema = S.literal("CategoryAdded");
7
+
8
+ let commandSchema = S.schema(s => ({
9
+ TAG: "AddCategory",
10
+ categoryId: s.m(DcbTag$Reventless.string),
11
+ name: s.m(S.string)
12
+ }));
13
+
14
+ let errorSchema = S.literal("CategoryAlreadyExists");
15
+
16
+ let eventSchema = S.schema(s => ({
17
+ TAG: "CategoryAdded",
18
+ categoryId: s.m(DcbTag$Reventless.string),
19
+ name: s.m(S.string)
20
+ }));
21
+
22
+ let name = "WithFixtures";
23
+
24
+ export {
25
+ name,
26
+ consumedEventSchema,
27
+ commandSchema,
28
+ errorSchema,
29
+ eventSchema,
30
+ }
31
+ /* consumedEventSchema Not a pure module */
@@ -0,0 +1,17 @@
1
+ // Implementation half — pairs with [WithFixtures.res].
2
+
3
+ open WithFixtures
4
+
5
+ type state = {exists: bool}
6
+ let initialState: state = {exists: false}
7
+
8
+ let evolve = (_state: state, event: consumedEvent): state =>
9
+ switch event {
10
+ | CategoryAdded => {exists: true}
11
+ }
12
+
13
+ let decide = (state: state, command: command): result<array<event>, error> =>
14
+ switch command {
15
+ | AddCategory({categoryId, name}) =>
16
+ state.exists ? Error(CategoryAlreadyExists) : Ok([CategoryAdded({categoryId, name})])
17
+ }
@@ -0,0 +1,37 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function evolve(_state, event) {
5
+ return {
6
+ exists: true
7
+ };
8
+ }
9
+
10
+ function decide(state, command) {
11
+ if (state.exists) {
12
+ return {
13
+ TAG: "Error",
14
+ _0: "CategoryAlreadyExists"
15
+ };
16
+ } else {
17
+ return {
18
+ TAG: "Ok",
19
+ _0: [{
20
+ TAG: "CategoryAdded",
21
+ categoryId: command.categoryId,
22
+ name: command.name
23
+ }]
24
+ };
25
+ }
26
+ }
27
+
28
+ let initialState = {
29
+ exists: false
30
+ };
31
+
32
+ export {
33
+ initialState,
34
+ evolve,
35
+ decide,
36
+ }
37
+ /* No side effect */
@@ -0,0 +1,23 @@
1
+ // Second Spec used by the companion-fixtures manual-open dedup verification
2
+ // test at [tests/StateChange/WithManualOpen_GWT.res]. Identical shape to
3
+ // [WithFixtures]; named differently so it gets its own companion
4
+ // [<Stem>_Fixtures] sibling that the PPX considers for auto-open.
5
+ //
6
+ // Spec half — pairs with [WithManualOpen_Behavior.res].
7
+
8
+ let name = "WithManualOpen"
9
+
10
+ @schema
11
+ type consumedEvent =
12
+ | CategoryAdded
13
+
14
+ @schema
15
+ type command =
16
+ AddCategory({categoryId: @s.matches(Reventless.DcbTag.string) string, name: string})
17
+
18
+ @schema
19
+ type error = CategoryAlreadyExists
20
+
21
+ @schema
22
+ type event =
23
+ CategoryAdded({categoryId: @s.matches(Reventless.DcbTag.string) string, name: string})
@@ -0,0 +1,31 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
5
+
6
+ let consumedEventSchema = S.literal("CategoryAdded");
7
+
8
+ let commandSchema = S.schema(s => ({
9
+ TAG: "AddCategory",
10
+ categoryId: s.m(DcbTag$Reventless.string),
11
+ name: s.m(S.string)
12
+ }));
13
+
14
+ let errorSchema = S.literal("CategoryAlreadyExists");
15
+
16
+ let eventSchema = S.schema(s => ({
17
+ TAG: "CategoryAdded",
18
+ categoryId: s.m(DcbTag$Reventless.string),
19
+ name: s.m(S.string)
20
+ }));
21
+
22
+ let name = "WithManualOpen";
23
+
24
+ export {
25
+ name,
26
+ consumedEventSchema,
27
+ commandSchema,
28
+ errorSchema,
29
+ eventSchema,
30
+ }
31
+ /* consumedEventSchema Not a pure module */
@@ -0,0 +1,17 @@
1
+ // Implementation half — pairs with [WithManualOpen.res].
2
+
3
+ open WithManualOpen
4
+
5
+ type state = {exists: bool}
6
+ let initialState: state = {exists: false}
7
+
8
+ let evolve = (_state: state, event: consumedEvent): state =>
9
+ switch event {
10
+ | CategoryAdded => {exists: true}
11
+ }
12
+
13
+ let decide = (state: state, command: command): result<array<event>, error> =>
14
+ switch command {
15
+ | AddCategory({categoryId, name}) =>
16
+ state.exists ? Error(CategoryAlreadyExists) : Ok([CategoryAdded({categoryId, name})])
17
+ }
@@ -0,0 +1,37 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function evolve(_state, event) {
5
+ return {
6
+ exists: true
7
+ };
8
+ }
9
+
10
+ function decide(state, command) {
11
+ if (state.exists) {
12
+ return {
13
+ TAG: "Error",
14
+ _0: "CategoryAlreadyExists"
15
+ };
16
+ } else {
17
+ return {
18
+ TAG: "Ok",
19
+ _0: [{
20
+ TAG: "CategoryAdded",
21
+ categoryId: command.categoryId,
22
+ name: command.name
23
+ }]
24
+ };
25
+ }
26
+ }
27
+
28
+ let initialState = {
29
+ exists: false
30
+ };
31
+
32
+ export {
33
+ initialState,
34
+ evolve,
35
+ decide,
36
+ }
37
+ /* No side effect */