@reventlessdev/reventless-core 3.0.0-alpha.180 → 3.0.0-alpha.182

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 (115) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/package.json +7 -7
  3. package/src/Message.res +2 -1
  4. package/src/Message.res.mjs +5 -1
  5. package/src/admin/Platform_Admin_Structure.res +2 -0
  6. package/src/admin/Platform_Admin_Structure.res.mjs +2 -0
  7. package/src/admin/Platform_ComponentDefinitionsApi.res +2 -1
  8. package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
  9. package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res +1 -1
  10. package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res.mjs +2 -1
  11. package/src/components/Api/ApiTargetStateHelpers.res +20 -0
  12. package/src/components/Api/ApiTargetStateHelpers.res.mjs +16 -0
  13. package/src/components/Api/GraphQL_FragmentGenerator.res +1 -0
  14. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +1 -0
  15. package/src/components/Api/SchemaType.res +6 -1
  16. package/src/components/Api/SchemaType.res.mjs +22 -4
  17. package/src/components/Api/SuryToJsonSchema.res +16 -0
  18. package/src/components/Api/SuryToJsonSchema.res.mjs +28 -0
  19. package/src/components/Dcb/Dcb_Builder.res +4 -5
  20. package/src/components/Dcb/Dcb_Builder.res.mjs +3 -5
  21. package/src/components/DcbEventLog/DcbEventLog_Operations.res +6 -1
  22. package/src/components/DcbEventLog/DcbEventLog_Operations.res.mjs +2 -1
  23. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +25 -0
  24. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res.mjs +31 -0
  25. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res +8 -8
  26. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs +26 -6
  27. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +44 -37
  28. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +17 -25
  29. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +27 -2
  30. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +4 -0
  31. package/src/components/StateViewSlice/StateViewSlice_Builder.res +20 -6
  32. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +23 -5
  33. package/src/components/StateViewSlice/StateViewSlice_Callback.res +1 -1
  34. package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +5 -1
  35. package/src/plugin/component/Plugin_Helpers.res +4 -1
  36. package/src/plugin/component/Plugin_Structure.res +15 -1
  37. package/src/plugin/component/Plugin_Structure.res.mjs +4 -1
  38. package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +2 -0
  39. package/tests/IdentityTest.res.mjs +174 -0
  40. package/tests/ResourceAttributionTest.res.mjs +75 -0
  41. package/tests/adapter/MonitoringTest.res.mjs +116 -0
  42. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +10 -0
  43. package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +365 -0
  44. package/tests/admin/Platform_UIFragmentsApiTest.res.mjs +101 -0
  45. package/tests/aggregate/AggregateCacheTest.res.mjs +433 -0
  46. package/tests/aggregate/AggregateCallbackTest.res.mjs +143 -0
  47. package/tests/aggregate/AggregateCausationTest.res.mjs +47 -0
  48. package/tests/aggregate/AggregateConflictTest.res.mjs +386 -0
  49. package/tests/aggregate/AggregateFixtures.res.mjs +308 -0
  50. package/tests/aggregate/AggregateRejectionTest.res.mjs +166 -0
  51. package/tests/aggregate/AggregateSnapshotTest.res.mjs +645 -0
  52. package/tests/api/ApiNoApiTest.res.mjs +90 -0
  53. package/tests/api/GraphQL_StitcherTest.res.mjs +112 -0
  54. package/tests/api/SimpleTest.res.mjs +10 -0
  55. package/tests/api/SuryToJsonSchemaTest.res +68 -0
  56. package/tests/api/SuryToJsonSchemaTest.res.mjs +843 -0
  57. package/tests/commandgenerator/CommandGeneratorCallbackTest.res.mjs +160 -0
  58. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +197 -0
  59. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +152 -0
  60. package/tests/commandtopic/CommandTopicCallbackTest.res.mjs +106 -0
  61. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res.mjs +109 -0
  62. package/tests/counter/CounterCallbackTest.res.mjs +140 -0
  63. package/tests/counter/CounterFixtures.res.mjs +67 -0
  64. package/tests/dcb/DcbDecodeTest.res.mjs +194 -0
  65. package/tests/dcb/DcbEventLogOperationsTest.res.mjs +268 -0
  66. package/tests/dcb/DcbFixtures.res.mjs +534 -0
  67. package/tests/dcb/DcbScopeInferenceTest.res.mjs +480 -0
  68. package/tests/dcb/DcbStateChangeSliceTest.res.mjs +540 -0
  69. package/tests/dcb/DcbTagTest.res.mjs +867 -0
  70. package/tests/dcb/DcbValidationTest.res.mjs +476 -0
  71. package/tests/eventlog/EventLogFixtures.res.mjs +196 -0
  72. package/tests/eventlog/EventLogOperationsTest.res.mjs +192 -0
  73. package/tests/eventlog/EventLogRetryTest.res.mjs +195 -0
  74. package/tests/eventmapper/EventMapperCallbackTest.res.mjs +141 -0
  75. package/tests/eventmapper/EventMapperFixtures.res.mjs +440 -0
  76. package/tests/eventmapper/EventMapperTest.res.mjs +83 -0
  77. package/tests/eventtopic/EventTopicFixtures.res.mjs +65 -0
  78. package/tests/eventtopic/EventTopicOperationsTest.res.mjs +71 -0
  79. package/tests/extensionpoint/ExtensionPointCallbackTest.res.mjs +94 -0
  80. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +205 -0
  81. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +304 -0
  82. package/tests/extensionpoint/PluginDisconnectScheduleTest.res.mjs +92 -0
  83. package/tests/ftp/FTPTest.res.mjs +88 -0
  84. package/tests/logger/LogFormatTest.res.mjs +329 -0
  85. package/tests/logger/LoggerLazyTest.res.mjs +40 -0
  86. package/tests/message/MessageTest.res.mjs +218 -0
  87. package/tests/message/MetaEnvelopeTest.res.mjs +188 -0
  88. package/tests/plugin/HeartbeatDisconnectGraceTest.res.mjs +91 -0
  89. package/tests/plugin/ManifestVisibilityTest.res.mjs +215 -0
  90. package/tests/plugin/PluginSpecExperiment.res.mjs +31 -0
  91. package/tests/plugin/PluginStructureTest.res +55 -0
  92. package/tests/plugin/PluginStructureTest.res.mjs +467 -0
  93. package/tests/plugin/PluginVersionTest.res.mjs +30 -0
  94. package/tests/plugin/SchemaWalkerTest.res.mjs +160 -0
  95. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +62 -0
  96. package/tests/plugin/StateChangeSlice/PsShipOrder.res +4 -1
  97. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +77 -0
  98. package/tests/plugin/StateViewSlice/PsAnnotatedView.res +5 -4
  99. package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +110 -0
  100. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res +1 -1
  101. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +70 -0
  102. package/tests/plugin/StateViewSlice/PsCustomersView.res +1 -1
  103. package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +70 -0
  104. package/tests/plugin/StateViewSlice/PsOrdersView.res +1 -1
  105. package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +82 -0
  106. package/tests/poc/StructuralSubtypingPoc.res.mjs +61 -0
  107. package/tests/projection/ProjectionOptimizeTest.res.mjs +75 -0
  108. package/tests/querydb/QueryDbFixtures.res.mjs +135 -0
  109. package/tests/querydb/QueryDbOperationsTest.res.mjs +168 -0
  110. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res.mjs +77 -0
  111. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +139 -0
  112. package/tests/util/CommandPublisherTest.res.mjs +78 -0
  113. package/tests/util/CsvStreamTest.res.mjs +51 -0
  114. package/tests/util/LruTest.res.mjs +105 -0
  115. package/tests/util/MetricsTest.res.mjs +53 -0
@@ -0,0 +1,192 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
6
+ import * as EventLogFixtures$ReventlessCore from "./EventLogFixtures.res.mjs";
7
+ import * as EventLog_Operations$ReventlessCore from "../../src/components/EventLog/EventLog_Operations.res.mjs";
8
+
9
+ let $$let = EventLogFixtures$ReventlessCore.MockEventTopic.Spec;
10
+
11
+ let $$let$1 = $$let.Id;
12
+
13
+ let TestOps_Spec = {
14
+ Id: Id$Reventless.StringPure,
15
+ name: EventLogFixtures$ReventlessCore.ItemEventLogSpec.name,
16
+ eventSchema: EventLogFixtures$ReventlessCore.ItemEventLogSpec.eventSchema
17
+ };
18
+
19
+ let TestOps_EventTopic = {
20
+ Spec: {
21
+ Id: {
22
+ schema: $$let$1.schema,
23
+ make: prim => prim,
24
+ makeFromString: prim => prim,
25
+ toString: prim => prim,
26
+ cmp: $$let$1.cmp
27
+ },
28
+ name: $$let.name,
29
+ eventSchema: $$let.eventSchema
30
+ },
31
+ make: EventLogFixtures$ReventlessCore.MockEventTopic.make
32
+ };
33
+
34
+ let TestOps = {
35
+ Spec: TestOps_Spec,
36
+ EventTopic: TestOps_EventTopic,
37
+ eventTopic: EventLogFixtures$ReventlessCore.mockEventTopicOps,
38
+ storage: EventLogFixtures$ReventlessCore.mockStorage
39
+ };
40
+
41
+ let $$let$2 = TestOps_Spec;
42
+
43
+ let $$let$3 = $$let$2.Id;
44
+
45
+ let Ops = EventLog_Operations$ReventlessCore.Make({
46
+ Id: {
47
+ schema: Id$Reventless.StringPure.schema,
48
+ make: prim => prim,
49
+ makeFromString: prim => prim,
50
+ toString: prim => prim,
51
+ cmp: Id$Reventless.StringPure.cmp
52
+ },
53
+ name: EventLogFixtures$ReventlessCore.ItemEventLogSpec.name,
54
+ eventSchema: EventLogFixtures$ReventlessCore.ItemEventLogSpec.eventSchema
55
+ })({
56
+ Spec: {
57
+ Id: {
58
+ schema: $$let$3.schema,
59
+ make: prim => prim,
60
+ makeFromString: prim => prim,
61
+ toString: prim => prim,
62
+ cmp: $$let$3.cmp
63
+ },
64
+ name: $$let$2.name,
65
+ eventSchema: $$let$2.eventSchema
66
+ },
67
+ EventTopic: TestOps_EventTopic,
68
+ eventTopic: EventLogFixtures$ReventlessCore.mockEventTopicOps,
69
+ storage: EventLogFixtures$ReventlessCore.mockStorage
70
+ });
71
+
72
+ globalThis.beforeEach(() => EventLogFixtures$ReventlessCore.reset());
73
+
74
+ globalThis.describe("EventLog_Operations:", () => {
75
+ globalThis.describe("append", () => {
76
+ globalThis.test("stores encoded events in storage", async () => {
77
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
78
+ TAG: "ItemCreated",
79
+ name: "Widget"
80
+ });
81
+ await Ops.append(1, "item-1", [event$p]);
82
+ let stored = Stdlib_Option.getOr(EventLogFixtures$ReventlessCore.storedEvents.contents["item-1"], []);
83
+ globalThis.expect(stored.length).toBe(1);
84
+ });
85
+ globalThis.test("publishes events to event topic", async () => {
86
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
87
+ TAG: "ItemCreated",
88
+ name: "Widget"
89
+ });
90
+ await Ops.append(1, "item-1", [event$p]);
91
+ globalThis.expect(EventLogFixtures$ReventlessCore.capturedPublishes.contents.length).toBe(1);
92
+ });
93
+ globalThis.test("storage failure returns Error result", async () => {
94
+ EventLogFixtures$ReventlessCore.failNextAppend.contents = true;
95
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
96
+ TAG: "ItemCreated",
97
+ name: "Widget"
98
+ });
99
+ let result = await Ops.append(1, "item-1", [event$p]);
100
+ globalThis.expect(Stdlib_Result.isError(result)).toBe(true);
101
+ });
102
+ globalThis.test("multiple events all stored and published", async () => {
103
+ let events$p = [
104
+ EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
105
+ TAG: "ItemCreated",
106
+ name: "First"
107
+ }),
108
+ EventLogFixtures$ReventlessCore.makeEvent$p("item-2", {
109
+ TAG: "ItemCreated",
110
+ name: "Second"
111
+ })
112
+ ];
113
+ await Ops.append(1, "agg-1", events$p);
114
+ let stored = Stdlib_Option.getOr(EventLogFixtures$ReventlessCore.storedEvents.contents["agg-1"], []);
115
+ globalThis.expect([
116
+ stored.length,
117
+ EventLogFixtures$ReventlessCore.capturedPublishes.contents.length
118
+ ]).toEqual([
119
+ 2,
120
+ 2
121
+ ]);
122
+ });
123
+ globalThis.test("returns Ok on success", async () => {
124
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
125
+ TAG: "ItemCreated",
126
+ name: "Widget"
127
+ });
128
+ let result = await Ops.append(1, "item-1", [event$p]);
129
+ globalThis.expect(Stdlib_Result.isOk(result)).toBe(true);
130
+ });
131
+ });
132
+ globalThis.describe("replay", () => {
133
+ globalThis.test("returns empty array for unknown id", async () => {
134
+ let events = await Ops.replay("unknown-id");
135
+ globalThis.expect(events.length).toBe(0);
136
+ });
137
+ globalThis.test("decodes stored events back to typed events", async () => {
138
+ let event = {
139
+ TAG: "ItemCreated",
140
+ name: "Widget"
141
+ };
142
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", event);
143
+ await Ops.append(1, "item-1", [event$p]);
144
+ let replayed = await Ops.replay("item-1");
145
+ globalThis.expect(replayed.length).toBe(1);
146
+ let first = replayed[0];
147
+ globalThis.expect(first).toEqual(event);
148
+ });
149
+ globalThis.test("decodes multiple events in order", async () => {
150
+ let events = [
151
+ {
152
+ TAG: "ItemCreated",
153
+ name: "Widget"
154
+ },
155
+ {
156
+ TAG: "ItemDeleted",
157
+ id: "item-1"
158
+ }
159
+ ];
160
+ let events$p = events.map(event => EventLogFixtures$ReventlessCore.makeEvent$p("item-1", event));
161
+ await Ops.append(1, "item-1", events$p);
162
+ let replayed = await Ops.replay("item-1");
163
+ globalThis.expect(replayed.length).toBe(2);
164
+ globalThis.expect(replayed).toEqual(events);
165
+ });
166
+ globalThis.test("separate aggregates have independent event logs", async () => {
167
+ await Ops.append(1, "agg-A", [EventLogFixtures$ReventlessCore.makeEvent$p("agg-A", {
168
+ TAG: "ItemCreated",
169
+ name: "A"
170
+ })]);
171
+ await Ops.append(1, "agg-B", [EventLogFixtures$ReventlessCore.makeEvent$p("agg-B", {
172
+ TAG: "ItemDeleted",
173
+ id: "B"
174
+ })]);
175
+ let eventsA = await Ops.replay("agg-A");
176
+ let eventsB = await Ops.replay("agg-B");
177
+ globalThis.expect([
178
+ eventsA.length,
179
+ eventsB.length
180
+ ]).toEqual([
181
+ 1,
182
+ 1
183
+ ]);
184
+ });
185
+ });
186
+ });
187
+
188
+ export {
189
+ TestOps,
190
+ Ops,
191
+ }
192
+ /* Ops Not a pure module */
@@ -0,0 +1,195 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
6
+ import * as EventLogFixtures$ReventlessCore from "./EventLogFixtures.res.mjs";
7
+ import * as EventLog_Operations$ReventlessCore from "../../src/components/EventLog/EventLog_Operations.res.mjs";
8
+
9
+ let $$let = EventLogFixtures$ReventlessCore.MockEventTopic.Spec;
10
+
11
+ let $$let$1 = $$let.Id;
12
+
13
+ let TestOps_Spec = {
14
+ Id: Id$Reventless.StringPure,
15
+ name: EventLogFixtures$ReventlessCore.ItemEventLogSpec.name,
16
+ eventSchema: EventLogFixtures$ReventlessCore.ItemEventLogSpec.eventSchema
17
+ };
18
+
19
+ let TestOps_EventTopic = {
20
+ Spec: {
21
+ Id: {
22
+ schema: $$let$1.schema,
23
+ make: prim => prim,
24
+ makeFromString: prim => prim,
25
+ toString: prim => prim,
26
+ cmp: $$let$1.cmp
27
+ },
28
+ name: $$let.name,
29
+ eventSchema: $$let.eventSchema
30
+ },
31
+ make: EventLogFixtures$ReventlessCore.MockEventTopic.make
32
+ };
33
+
34
+ let TestOps = {
35
+ Spec: TestOps_Spec,
36
+ EventTopic: TestOps_EventTopic,
37
+ eventTopic: EventLogFixtures$ReventlessCore.mockEventTopicOps,
38
+ storage: EventLogFixtures$ReventlessCore.mockStorage
39
+ };
40
+
41
+ let $$let$2 = TestOps_Spec;
42
+
43
+ let $$let$3 = $$let$2.Id;
44
+
45
+ let Ops = EventLog_Operations$ReventlessCore.Make({
46
+ Id: {
47
+ schema: Id$Reventless.StringPure.schema,
48
+ make: prim => prim,
49
+ makeFromString: prim => prim,
50
+ toString: prim => prim,
51
+ cmp: Id$Reventless.StringPure.cmp
52
+ },
53
+ name: EventLogFixtures$ReventlessCore.ItemEventLogSpec.name,
54
+ eventSchema: EventLogFixtures$ReventlessCore.ItemEventLogSpec.eventSchema
55
+ })({
56
+ Spec: {
57
+ Id: {
58
+ schema: $$let$3.schema,
59
+ make: prim => prim,
60
+ makeFromString: prim => prim,
61
+ toString: prim => prim,
62
+ cmp: $$let$3.cmp
63
+ },
64
+ name: $$let$2.name,
65
+ eventSchema: $$let$2.eventSchema
66
+ },
67
+ EventTopic: TestOps_EventTopic,
68
+ eventTopic: EventLogFixtures$ReventlessCore.mockEventTopicOps,
69
+ storage: EventLogFixtures$ReventlessCore.mockStorage
70
+ });
71
+
72
+ globalThis.beforeEach(() => EventLogFixtures$ReventlessCore.reset());
73
+
74
+ globalThis.describe("EventLog_Operations — retry:", () => {
75
+ globalThis.describe("isTransient predicate:", () => {
76
+ globalThis.test("ThrottlingException is transient", async () => {
77
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
78
+ TAG: "StorageFailure",
79
+ _0: "ThrottlingException: Rate exceeded"
80
+ })).toBe(true);
81
+ });
82
+ globalThis.test("ProvisionedThroughputExceededException is transient", async () => {
83
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
84
+ TAG: "StorageFailure",
85
+ _0: "ProvisionedThroughputExceededException"
86
+ })).toBe(true);
87
+ });
88
+ globalThis.test("ServiceUnavailable is transient", async () => {
89
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
90
+ TAG: "StorageFailure",
91
+ _0: "ServiceUnavailable"
92
+ })).toBe(true);
93
+ });
94
+ globalThis.test("RequestLimitExceeded is transient", async () => {
95
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
96
+ TAG: "StorageFailure",
97
+ _0: "RequestLimitExceeded"
98
+ })).toBe(true);
99
+ });
100
+ globalThis.test("InternalServerError is transient", async () => {
101
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
102
+ TAG: "StorageFailure",
103
+ _0: "InternalServerError: something went wrong"
104
+ })).toBe(true);
105
+ });
106
+ globalThis.test("ValidationException is not transient", async () => {
107
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
108
+ TAG: "StorageFailure",
109
+ _0: "ValidationException: invalid field"
110
+ })).toBe(false);
111
+ });
112
+ globalThis.test("generic mock storage failure is not transient", async () => {
113
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient({
114
+ TAG: "StorageFailure",
115
+ _0: "mock storage failure"
116
+ })).toBe(false);
117
+ });
118
+ globalThis.test("a Conflict is never transient (retried a layer up, not here)", async () => {
119
+ globalThis.expect(EventLog_Operations$ReventlessCore.isTransient("Conflict")).toBe(false);
120
+ });
121
+ });
122
+ globalThis.describe("permanent storage failure:", () => {
123
+ globalThis.test("returns Error immediately without retry", async () => {
124
+ EventLogFixtures$ReventlessCore.failNextAppend.contents = true;
125
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
126
+ TAG: "ItemCreated",
127
+ name: "Widget"
128
+ });
129
+ let result = await Ops.append(1, "item-1", [event$p]);
130
+ globalThis.expect(Stdlib_Result.isError(result)).toBe(true);
131
+ globalThis.expect(EventLogFixtures$ReventlessCore.appendCallCount.contents).toBe(1);
132
+ });
133
+ globalThis.test("does not publish events after permanent storage failure", async () => {
134
+ EventLogFixtures$ReventlessCore.failNextAppend.contents = true;
135
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
136
+ TAG: "ItemCreated",
137
+ name: "Widget"
138
+ });
139
+ await Ops.append(1, "item-1", [event$p]);
140
+ globalThis.expect(EventLogFixtures$ReventlessCore.capturedPublishes.contents.length).toBe(0);
141
+ });
142
+ });
143
+ globalThis.describe("transient storage failure — retry:", () => {
144
+ globalThis.test("1 transient failure retries and returns Ok", async () => {
145
+ EventLogFixtures$ReventlessCore.failNextAppendsWithTransient.contents = 1;
146
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
147
+ TAG: "ItemCreated",
148
+ name: "Widget"
149
+ });
150
+ let result = await Ops.append(1, "item-1", [event$p]);
151
+ globalThis.expect(Stdlib_Result.isOk(result)).toBe(true);
152
+ globalThis.expect(EventLogFixtures$ReventlessCore.appendCallCount.contents).toBe(2);
153
+ });
154
+ globalThis.test("events are stored and published after successful retry", async () => {
155
+ EventLogFixtures$ReventlessCore.failNextAppendsWithTransient.contents = 1;
156
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
157
+ TAG: "ItemCreated",
158
+ name: "Widget"
159
+ });
160
+ await Ops.append(1, "item-1", [event$p]);
161
+ let stored = Stdlib_Option.getOr(EventLogFixtures$ReventlessCore.storedEvents.contents["item-1"], []);
162
+ globalThis.expect(stored.length).toBe(1);
163
+ globalThis.expect(EventLogFixtures$ReventlessCore.capturedPublishes.contents.length).toBe(1);
164
+ });
165
+ globalThis.test("2 transient failures retry twice and return Ok", async () => {
166
+ EventLogFixtures$ReventlessCore.failNextAppendsWithTransient.contents = 2;
167
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
168
+ TAG: "ItemCreated",
169
+ name: "Widget"
170
+ });
171
+ let result = await Ops.append(1, "item-1", [event$p]);
172
+ globalThis.expect(Stdlib_Result.isOk(result)).toBe(true);
173
+ globalThis.expect(EventLogFixtures$ReventlessCore.appendCallCount.contents).toBe(3);
174
+ });
175
+ });
176
+ globalThis.describe("retry exhaustion:", () => {
177
+ globalThis.test("6 transient failures exhaust 5 retries and return Error", async () => {
178
+ EventLogFixtures$ReventlessCore.failNextAppendsWithTransient.contents = 6;
179
+ let event$p = EventLogFixtures$ReventlessCore.makeEvent$p("item-1", {
180
+ TAG: "ItemCreated",
181
+ name: "Widget"
182
+ });
183
+ let result = await Ops.append(1, "item-1", [event$p]);
184
+ globalThis.expect(Stdlib_Result.isError(result)).toBe(true);
185
+ globalThis.expect(EventLogFixtures$ReventlessCore.appendCallCount.contents).toBe(6);
186
+ globalThis.expect(EventLogFixtures$ReventlessCore.capturedPublishes.contents.length).toBe(0);
187
+ }, 12000);
188
+ });
189
+ });
190
+
191
+ export {
192
+ TestOps,
193
+ Ops,
194
+ }
195
+ /* Ops Not a pure module */
@@ -0,0 +1,141 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Effect from "effect/Effect";
4
+ import * as Stream from "effect/Stream";
5
+ import * as Message$ReventlessCore from "../../src/Message.res.mjs";
6
+ import * as EventMapperFixtures$ReventlessCore from "./EventMapperFixtures.res.mjs";
7
+
8
+ globalThis.beforeEach(() => EventMapperFixtures$ReventlessCore.resetMocks());
9
+
10
+ globalThis.describe("MakeCounterHandler.handleCounterEvents:", () => {
11
+ globalThis.describe("event with matching source mapping", () => {
12
+ globalThis.test("publishes command JSON for OrderPlaced", async () => {
13
+ let eventJson = EventMapperFixtures$ReventlessCore.makeEventJson(undefined, "src-1", Message$ReventlessCore.encode({
14
+ TAG: "OrderPlaced",
15
+ orderId: "order-1",
16
+ amount: 99.99
17
+ }, EventMapperFixtures$ReventlessCore.CmdSourceSpec.eventSchema));
18
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestCounterHandler.handleCounterEvents(Stream.fromIterable([eventJson])));
19
+ globalThis.expect(EventMapperFixtures$ReventlessCore.capturedCmds.contents.length).toBe(1);
20
+ });
21
+ });
22
+ globalThis.describe("event with unknown service", () => {
23
+ globalThis.test("skipped — no publish", async () => {
24
+ let eventJson = EventMapperFixtures$ReventlessCore.makeEventJson("UnknownService", "src-1", Message$ReventlessCore.encode({
25
+ TAG: "OrderPlaced",
26
+ orderId: "order-1",
27
+ amount: 50.0
28
+ }, EventMapperFixtures$ReventlessCore.CmdSourceSpec.eventSchema));
29
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestCounterHandler.handleCounterEvents(Stream.fromIterable([eventJson])));
30
+ globalThis.expect(EventMapperFixtures$ReventlessCore.capturedCmds.contents.length).toBe(0);
31
+ });
32
+ });
33
+ globalThis.describe("invalid event JSON", () => {
34
+ globalThis.test("skipped gracefully — no throw, no publish", async () => {
35
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestCounterHandler.handleCounterEvents(Stream.fromIterable(["not-an-object"])));
36
+ globalThis.expect(EventMapperFixtures$ReventlessCore.capturedCmds.contents.length).toBe(0);
37
+ });
38
+ });
39
+ });
40
+
41
+ globalThis.describe("MakeEventCollectorHandler.handleJsonEvents:", () => {
42
+ globalThis.describe("Count action", () => {
43
+ globalThis.test("calls count with the countItem", async () => {
44
+ let countItem = {
45
+ counterId: "c1",
46
+ reference: "ref-1",
47
+ inc: 1
48
+ };
49
+ EventMapperFixtures$ReventlessCore.mockCommonHandler.contents = async param => [
50
+ Promise.resolve([]),
51
+ [{
52
+ TAG: "Count",
53
+ _0: countItem
54
+ }]
55
+ ];
56
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestECHandler.handleJsonEvents(Stream.fromIterable([null])));
57
+ globalThis.expect(EventMapperFixtures$ReventlessCore.capturedCountItems.contents).toEqual([countItem]);
58
+ });
59
+ });
60
+ globalThis.describe("AddToCounterTarget action", () => {
61
+ globalThis.test("calls addToCounterTarget with the counterTargetRef", async () => {
62
+ let target = {
63
+ counterId: "c1",
64
+ target: 5,
65
+ targetRef: "ref-1"
66
+ };
67
+ EventMapperFixtures$ReventlessCore.mockCommonHandler.contents = async param => [
68
+ Promise.resolve([]),
69
+ [{
70
+ TAG: "AddToCounterTarget",
71
+ _0: target
72
+ }]
73
+ ];
74
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestECHandler.handleJsonEvents(Stream.fromIterable([null])));
75
+ globalThis.expect(EventMapperFixtures$ReventlessCore.capturedCounterTargets.contents).toEqual([target]);
76
+ });
77
+ });
78
+ globalThis.describe("Publisher action", () => {
79
+ globalThis.test("calls publishJsons with the command", async () => {
80
+ let cmd = {
81
+ id: "agg-1",
82
+ meta: EventMapperFixtures$ReventlessCore.evtMapTestMeta,
83
+ commandJson: "DoSomething"
84
+ };
85
+ EventMapperFixtures$ReventlessCore.mockCommonHandler.contents = async param => [
86
+ Promise.resolve([cmd]),
87
+ []
88
+ ];
89
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestECHandler.handleJsonEvents(Stream.fromIterable([null])));
90
+ globalThis.expect(EventMapperFixtures$ReventlessCore.capturedCmds.contents.length).toBe(1);
91
+ });
92
+ });
93
+ globalThis.describe("mixed actions", () => {
94
+ globalThis.test("both publish and count called", async () => {
95
+ let cmd = {
96
+ id: "agg-1",
97
+ meta: EventMapperFixtures$ReventlessCore.evtMapTestMeta,
98
+ commandJson: "Cmd"
99
+ };
100
+ EventMapperFixtures$ReventlessCore.mockCommonHandler.contents = async param => [
101
+ Promise.resolve([cmd]),
102
+ [{
103
+ TAG: "Count",
104
+ _0: {
105
+ counterId: "c1",
106
+ reference: "ref-1",
107
+ inc: 2
108
+ }
109
+ }]
110
+ ];
111
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestECHandler.handleJsonEvents(Stream.fromIterable([null])));
112
+ globalThis.expect([
113
+ EventMapperFixtures$ReventlessCore.capturedCmds.contents.length,
114
+ EventMapperFixtures$ReventlessCore.capturedCountItems.contents.length
115
+ ]).toEqual([
116
+ 1,
117
+ 1
118
+ ]);
119
+ });
120
+ });
121
+ globalThis.describe("doCount retry", () => {
122
+ globalThis.test("retries when count throws, eventually succeeds", async () => {
123
+ EventMapperFixtures$ReventlessCore.mockCountFailUntil.contents = 1;
124
+ EventMapperFixtures$ReventlessCore.mockCommonHandler.contents = async param => [
125
+ Promise.resolve([]),
126
+ [{
127
+ TAG: "Count",
128
+ _0: {
129
+ counterId: "c1",
130
+ reference: "ref-1",
131
+ inc: 1
132
+ }
133
+ }]
134
+ ];
135
+ await Effect.runPromise(EventMapperFixtures$ReventlessCore.TestECHandler.handleJsonEvents(Stream.fromIterable([null])));
136
+ globalThis.expect(EventMapperFixtures$ReventlessCore.mockCountCallCount.contents >= 2).toBe(true);
137
+ });
138
+ });
139
+ });
140
+
141
+ /* Not a pure module */