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

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 +14 -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 +3 -0
  16. package/src/components/Api/SchemaType.res.mjs +10 -2
  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,160 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Effect from "effect/Effect";
6
+ import * as CommandGeneratorFixtures$ReventlessCore from "./CommandGeneratorFixtures.res.mjs";
7
+
8
+ globalThis.beforeEach(() => CommandGeneratorFixtures$ReventlessCore.reset());
9
+
10
+ globalThis.describe("CommandGenerator_Callback.generateCommand:", () => {
11
+ globalThis.describe("zero-param command", () => {
12
+ globalThis.test("publishJsons called with plain string commandJson", async () => {
13
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeZeroParamPayload("agg-1", "Create");
14
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
15
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
16
+ globalThis.expect(publishedCmd.commandJson).toEqual("Create");
17
+ });
18
+ globalThis.test("returns a Pending outcome with non-empty msgId", async () => {
19
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeZeroParamPayload("agg-1", "Create");
20
+ let outcome = await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
21
+ let msgId;
22
+ switch (outcome.TAG) {
23
+ case "Accepted" :
24
+ case "Rejected" :
25
+ msgId = "";
26
+ break;
27
+ case "Pending" :
28
+ msgId = outcome.msgId;
29
+ break;
30
+ }
31
+ globalThis.expect(msgId.length > 0).toBe(true);
32
+ });
33
+ globalThis.test("meta.service equals AggregateSpec.name", async () => {
34
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeZeroParamPayload("agg-1", "Create");
35
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
36
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
37
+ globalThis.expect(publishedCmd.meta.service).toBe(CommandGeneratorFixtures$ReventlessCore.CmdGenAggSpec.name);
38
+ });
39
+ globalThis.test("meta.msgId equals meta.correlationId", async () => {
40
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeZeroParamPayload("agg-1", "Create");
41
+ let outcome = await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
42
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
43
+ let msgId;
44
+ switch (outcome.TAG) {
45
+ case "Accepted" :
46
+ case "Rejected" :
47
+ msgId = "";
48
+ break;
49
+ case "Pending" :
50
+ msgId = outcome.msgId;
51
+ break;
52
+ }
53
+ globalThis.expect([
54
+ publishedCmd.meta.msgId,
55
+ publishedCmd.meta.correlationId
56
+ ]).toEqual([
57
+ msgId,
58
+ msgId
59
+ ]);
60
+ });
61
+ });
62
+ globalThis.describe("multi-param command", () => {
63
+ globalThis.test("publishJsons called with object commandJson {TAG, param}", async () => {
64
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeOneParamPayload("agg-1", "CreateWithName", "name", "Widget");
65
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
66
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
67
+ let cmdObj = Stdlib_Option.getOrThrow(Stdlib_JSON.Decode.object(publishedCmd.commandJson), undefined);
68
+ globalThis.expect(cmdObj["TAG"]).toEqual("CreateWithName");
69
+ globalThis.expect(cmdObj["name"]).toEqual("Widget");
70
+ });
71
+ });
72
+ globalThis.describe("schema validation failure", () => {
73
+ globalThis.test("invalid command name throws an error", async () => {
74
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeZeroParamPayload("agg-1", "NonExistentCommand");
75
+ let threw = false;
76
+ try {
77
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
78
+ } catch (exn) {
79
+ threw = true;
80
+ }
81
+ globalThis.expect(threw).toBe(true);
82
+ });
83
+ });
84
+ globalThis.describe("StateChangeSlice envelope id derivation", () => {
85
+ globalThis.test("single @partitionTag: id derived from tagged field when args have no id", async () => {
86
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeSlicePayload("CreateItem", Object.fromEntries([
87
+ [
88
+ "itemId",
89
+ "item-42"
90
+ ],
91
+ [
92
+ "name",
93
+ "Widget"
94
+ ]
95
+ ]));
96
+ let outcome = await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.singleTagSliceGen(payload));
97
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
98
+ globalThis.expect(publishedCmd.id).toBe("item-42");
99
+ let msgId;
100
+ switch (outcome.TAG) {
101
+ case "Accepted" :
102
+ case "Rejected" :
103
+ msgId = "";
104
+ break;
105
+ case "Pending" :
106
+ msgId = outcome.msgId;
107
+ break;
108
+ }
109
+ globalThis.expect(msgId.length > 0).toBe(true);
110
+ });
111
+ globalThis.test("composite @compositePartitionTag: id is joined partition-key value", async () => {
112
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeSlicePayload("DeployVersion", Object.fromEntries([
113
+ [
114
+ "environment",
115
+ "prod"
116
+ ],
117
+ [
118
+ "service",
119
+ "checkout"
120
+ ],
121
+ [
122
+ "version",
123
+ "1.2.3"
124
+ ]
125
+ ]));
126
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.compositeTagSliceGen(payload));
127
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
128
+ globalThis.expect(publishedCmd.id).toBe("prod-checkout");
129
+ });
130
+ globalThis.test("explicit id in args wins over derivation (regression check)", async () => {
131
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeSlicePayload("CreateItem", Object.fromEntries([
132
+ [
133
+ "id",
134
+ "explicit-id"
135
+ ],
136
+ [
137
+ "itemId",
138
+ "item-99"
139
+ ],
140
+ [
141
+ "name",
142
+ "Gadget"
143
+ ]
144
+ ]));
145
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.singleTagSliceGen(payload));
146
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
147
+ globalThis.expect(publishedCmd.id).toBe("explicit-id");
148
+ });
149
+ });
150
+ globalThis.describe("Aggregate envelope id (regression)", () => {
151
+ globalThis.test("explicit id in args is preserved unchanged", async () => {
152
+ let payload = CommandGeneratorFixtures$ReventlessCore.makeZeroParamPayload("agg-7", "Create");
153
+ await Effect.runPromise(CommandGeneratorFixtures$ReventlessCore.TestGenerator.generateCommand(payload));
154
+ let publishedCmd = CommandGeneratorFixtures$ReventlessCore.capturedCmds.contents[0];
155
+ globalThis.expect(publishedCmd.id).toBe("agg-7");
156
+ });
157
+ });
158
+ });
159
+
160
+ /* Not a pure module */
@@ -0,0 +1,197 @@
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 CommandGenerator_Callback$ReventlessCore from "../../src/components/CommandGenerator/CommandGenerator_Callback.res.mjs";
7
+
8
+ S.enableJson();
9
+
10
+ let name = "TestCmdGenAgg";
11
+
12
+ let commandSchema = S.union([
13
+ S.literal("Create"),
14
+ S.schema(s => ({
15
+ TAG: "CreateWithName",
16
+ name: s.m(S.string)
17
+ })),
18
+ S.literal("Invalid")
19
+ ]);
20
+
21
+ let eventSchema = S.union([
22
+ S.literal("Created"),
23
+ S.schema(s => ({
24
+ TAG: "CreatedWithName",
25
+ name: s.m(S.string)
26
+ }))
27
+ ]);
28
+
29
+ let errorSchema = S.literal("InvalidCommand");
30
+
31
+ let moduleUrl = import.meta.url;
32
+
33
+ function commandAuthorization(param) {
34
+ return "AllowAuthenticated";
35
+ }
36
+
37
+ let CmdGenAggSpec = {
38
+ Id: undefined,
39
+ name: name,
40
+ commandSchema: commandSchema,
41
+ eventSchema: eventSchema,
42
+ errorSchema: errorSchema,
43
+ moduleUrl: moduleUrl,
44
+ commandAuthorization: commandAuthorization
45
+ };
46
+
47
+ let moduleUrl$1 = import.meta.url;
48
+
49
+ function evolve(_state, _event) {
50
+
51
+ }
52
+
53
+ function decide(_state, command) {
54
+ if (typeof command !== "object") {
55
+ if (command === "Create") {
56
+ return {
57
+ TAG: "Ok",
58
+ _0: ["Created"]
59
+ };
60
+ } else {
61
+ return {
62
+ TAG: "Ok",
63
+ _0: []
64
+ };
65
+ }
66
+ } else {
67
+ return {
68
+ TAG: "Ok",
69
+ _0: [{
70
+ TAG: "CreatedWithName",
71
+ name: command.name
72
+ }]
73
+ };
74
+ }
75
+ }
76
+
77
+ let CmdGenBehavior = {
78
+ Spec: undefined,
79
+ moduleUrl: moduleUrl$1,
80
+ initialState: undefined,
81
+ evolve: evolve,
82
+ decide: decide
83
+ };
84
+
85
+ let capturedCmds = {
86
+ contents: []
87
+ };
88
+
89
+ async function publishJsons(cmds) {
90
+ capturedCmds.contents = capturedCmds.contents.concat(cmds);
91
+ }
92
+
93
+ let MockPublishSpec = {
94
+ publishJsons: publishJsons,
95
+ publishJsonsAndWait: undefined
96
+ };
97
+
98
+ let TestGenerator = CommandGenerator_Callback$ReventlessCore.Make(MockPublishSpec)({
99
+ Id: {
100
+ schema: Id$Reventless.StringPure.schema,
101
+ make: prim => prim,
102
+ makeFromString: prim => prim,
103
+ toString: prim => prim,
104
+ cmp: Id$Reventless.StringPure.cmp
105
+ },
106
+ name: name,
107
+ eventSchema: eventSchema,
108
+ errorSchema: errorSchema,
109
+ commandSchema: commandSchema,
110
+ moduleUrl: moduleUrl,
111
+ commandAuthorization: commandAuthorization
112
+ });
113
+
114
+ let singleTagCommandSchema = S.schema(s => ({
115
+ TAG: "CreateItem",
116
+ itemId: s.m(DcbTag$Reventless.string),
117
+ name: s.m(S.string)
118
+ }));
119
+
120
+ let compositeTagCommandSchema = S.schema(s => ({
121
+ TAG: "DeployVersion",
122
+ environment: s.m(DcbTag$Reventless.compositePartitionMember(0, "-")),
123
+ service: s.m(DcbTag$Reventless.compositePartitionMember(1, undefined)),
124
+ version: s.m(S.string)
125
+ }));
126
+
127
+ let singleTagSliceGen = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(publishJsons, undefined, "SingleTagSlice", singleTagCommandSchema, "StateChangeSlice", false);
128
+
129
+ let compositeTagSliceGen = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(publishJsons, undefined, "CompositeTagSlice", compositeTagCommandSchema, "StateChangeSlice", false);
130
+
131
+ function makeSlicePayload(command, args) {
132
+ return {
133
+ command: command,
134
+ arguments: args,
135
+ meta: {
136
+ ip: ["127.0.0.1"],
137
+ user: "test-user",
138
+ info: ""
139
+ }
140
+ };
141
+ }
142
+
143
+ function makeZeroParamPayload(id, command) {
144
+ return {
145
+ command: command,
146
+ arguments: {
147
+ id: id
148
+ },
149
+ meta: {
150
+ ip: ["127.0.0.1"],
151
+ user: "test-user",
152
+ info: ""
153
+ }
154
+ };
155
+ }
156
+
157
+ function makeOneParamPayload(id, command, paramName, paramValue) {
158
+ return {
159
+ command: command,
160
+ arguments: Object.fromEntries([
161
+ [
162
+ "id",
163
+ id
164
+ ],
165
+ [
166
+ paramName,
167
+ paramValue
168
+ ]
169
+ ]),
170
+ meta: {
171
+ ip: ["127.0.0.1"],
172
+ user: "test-user",
173
+ info: ""
174
+ }
175
+ };
176
+ }
177
+
178
+ function reset() {
179
+ capturedCmds.contents = [];
180
+ }
181
+
182
+ export {
183
+ CmdGenAggSpec,
184
+ CmdGenBehavior,
185
+ capturedCmds,
186
+ MockPublishSpec,
187
+ TestGenerator,
188
+ singleTagCommandSchema,
189
+ compositeTagCommandSchema,
190
+ singleTagSliceGen,
191
+ compositeTagSliceGen,
192
+ makeSlicePayload,
193
+ makeZeroParamPayload,
194
+ makeOneParamPayload,
195
+ reset,
196
+ }
197
+ /* Not a pure module */
@@ -0,0 +1,152 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Stream from "@reventlessdev/rescript-effect/src/Stream.res.mjs";
5
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
6
+ import * as Effect from "effect/Effect";
7
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
8
+ import * as Message$ReventlessCore from "../../src/Message.res.mjs";
9
+ import * as CommandTopic_Callback$ReventlessCore from "../../src/components/CommandTopic/CommandTopic_Callback.res.mjs";
10
+
11
+ S.enableJson();
12
+
13
+ let name = "TestCommandTopic";
14
+
15
+ let commandSchema = S.union([
16
+ S.schema(s => ({
17
+ TAG: "CreateItem",
18
+ itemId: s.m(S.string)
19
+ })),
20
+ S.schema(s => ({
21
+ TAG: "DeleteItem",
22
+ itemId: s.m(S.string)
23
+ }))
24
+ ]);
25
+
26
+ function commandAuthorization(param) {
27
+ return "AllowAuthenticated";
28
+ }
29
+
30
+ let TestSpec = {
31
+ Id: undefined,
32
+ name: name,
33
+ commandSchema: commandSchema,
34
+ commandAuthorization: commandAuthorization
35
+ };
36
+
37
+ let capturedItems = {
38
+ contents: []
39
+ };
40
+
41
+ let commandHandlerResults = {
42
+ contents: [{
43
+ TAG: "Ok",
44
+ _0: "ref-1"
45
+ }]
46
+ };
47
+
48
+ let commandHandlerShouldThrow = {
49
+ contents: false
50
+ };
51
+
52
+ function commandsHandler(stream) {
53
+ return Effect.map(Stream.runCollect(stream), items => {
54
+ if (commandHandlerShouldThrow.contents) {
55
+ Stdlib_JsError.throwWithMessage("commandsHandler failed");
56
+ }
57
+ capturedItems.contents = capturedItems.contents.concat(items.map(item => ({
58
+ reference: item.reference,
59
+ command: item.command.command
60
+ })));
61
+ return commandHandlerResults.contents;
62
+ });
63
+ }
64
+
65
+ let TestOps_Spec = {
66
+ Id: Id$Reventless.StringPure,
67
+ name: name,
68
+ commandSchema: commandSchema,
69
+ commandAuthorization: commandAuthorization
70
+ };
71
+
72
+ let TestOps = {
73
+ Spec: TestOps_Spec,
74
+ commandsHandler: commandsHandler
75
+ };
76
+
77
+ let $$let = TestOps_Spec;
78
+
79
+ let $$let$1 = $$let.Id;
80
+
81
+ let TestHandler = CommandTopic_Callback$ReventlessCore.Make({
82
+ Id: {
83
+ schema: Id$Reventless.StringPure.schema,
84
+ make: prim => prim,
85
+ makeFromString: prim => prim,
86
+ toString: prim => prim,
87
+ cmp: Id$Reventless.StringPure.cmp
88
+ },
89
+ name: name,
90
+ commandSchema: commandSchema
91
+ })({
92
+ Spec: {
93
+ Id: {
94
+ schema: $$let$1.schema,
95
+ make: prim => prim,
96
+ makeFromString: prim => prim,
97
+ toString: prim => prim,
98
+ cmp: $$let$1.cmp
99
+ },
100
+ name: $$let.name,
101
+ commandSchema: $$let.commandSchema
102
+ },
103
+ commandsHandler: commandsHandler
104
+ });
105
+
106
+ let testMeta = {
107
+ service: "TestService",
108
+ time: "2024-01-01T00:00:00Z",
109
+ ip: "127.0.0.1",
110
+ user: "test-user",
111
+ msgId: "cmd-msg-1",
112
+ correlationId: "cmd-corr-1"
113
+ };
114
+
115
+ function makeCommandJson(id, command) {
116
+ let cmd$p = {
117
+ id: id,
118
+ meta: testMeta,
119
+ command: command
120
+ };
121
+ return Message$ReventlessCore.encodeCommand$p(cmd$p, Id$Reventless.StringPure.schema, commandSchema);
122
+ }
123
+
124
+ function makeTopicItem(id, command) {
125
+ return {
126
+ command: makeCommandJson(id, command),
127
+ reference: id
128
+ };
129
+ }
130
+
131
+ function reset() {
132
+ capturedItems.contents = [];
133
+ commandHandlerResults.contents = [{
134
+ TAG: "Ok",
135
+ _0: "ref-1"
136
+ }];
137
+ commandHandlerShouldThrow.contents = false;
138
+ }
139
+
140
+ export {
141
+ TestSpec,
142
+ capturedItems,
143
+ commandHandlerResults,
144
+ commandHandlerShouldThrow,
145
+ TestOps,
146
+ TestHandler,
147
+ testMeta,
148
+ makeCommandJson,
149
+ makeTopicItem,
150
+ reset,
151
+ }
152
+ /* Not a pure module */
@@ -0,0 +1,106 @@
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 CommandTopicCallbackFixtures$ReventlessCore from "./CommandTopicCallbackFixtures.res.mjs";
6
+
7
+ globalThis.beforeEach(() => CommandTopicCallbackFixtures$ReventlessCore.reset());
8
+
9
+ globalThis.describe("CommandTopic_Callback.handleJsonCommands:", () => {
10
+ globalThis.describe("valid command JSON", () => {
11
+ globalThis.test("decoded command passed to commandsHandler", async () => {
12
+ let item = CommandTopicCallbackFixtures$ReventlessCore.makeTopicItem("agg-1", {
13
+ TAG: "CreateItem",
14
+ itemId: "item-1"
15
+ });
16
+ await Effect.runPromise(CommandTopicCallbackFixtures$ReventlessCore.TestHandler.handleJsonCommands(Stream.fromIterable([item])));
17
+ globalThis.expect(CommandTopicCallbackFixtures$ReventlessCore.capturedItems.contents.length).toBe(1);
18
+ let captured = CommandTopicCallbackFixtures$ReventlessCore.capturedItems.contents[0];
19
+ globalThis.expect(captured.reference).toBe("agg-1");
20
+ globalThis.expect(captured.command).toEqual({
21
+ TAG: "CreateItem",
22
+ itemId: "item-1"
23
+ });
24
+ });
25
+ });
26
+ globalThis.describe("results returned from commandsHandler", () => {
27
+ globalThis.test("handler results propagated as return value", async () => {
28
+ CommandTopicCallbackFixtures$ReventlessCore.commandHandlerResults.contents = [
29
+ {
30
+ TAG: "Ok",
31
+ _0: "agg-1"
32
+ },
33
+ {
34
+ TAG: "Error",
35
+ _0: "agg-2"
36
+ }
37
+ ];
38
+ let item = CommandTopicCallbackFixtures$ReventlessCore.makeTopicItem("agg-1", {
39
+ TAG: "CreateItem",
40
+ itemId: "item-1"
41
+ });
42
+ let results = await Effect.runPromise(CommandTopicCallbackFixtures$ReventlessCore.TestHandler.handleJsonCommands(Stream.fromIterable([item])));
43
+ globalThis.expect(results).toEqual([
44
+ {
45
+ TAG: "Ok",
46
+ _0: "agg-1"
47
+ },
48
+ {
49
+ TAG: "Error",
50
+ _0: "agg-2"
51
+ }
52
+ ]);
53
+ });
54
+ });
55
+ globalThis.describe("malformed command JSON", () => {
56
+ globalThis.test("skipped gracefully — commandsHandler called with empty array", async () => {
57
+ let invalidItem = {
58
+ command: "not-a-command-object",
59
+ reference: "ref-1"
60
+ };
61
+ await Effect.runPromise(CommandTopicCallbackFixtures$ReventlessCore.TestHandler.handleJsonCommands(Stream.fromIterable([invalidItem])));
62
+ globalThis.expect(CommandTopicCallbackFixtures$ReventlessCore.capturedItems.contents.length).toBe(0);
63
+ });
64
+ });
65
+ globalThis.describe("multiple commands in batch", () => {
66
+ globalThis.test("all decodable commands reach commandsHandler", async () => {
67
+ let items = [
68
+ CommandTopicCallbackFixtures$ReventlessCore.makeTopicItem("agg-1", {
69
+ TAG: "CreateItem",
70
+ itemId: "item-1"
71
+ }),
72
+ CommandTopicCallbackFixtures$ReventlessCore.makeTopicItem("agg-2", {
73
+ TAG: "DeleteItem",
74
+ itemId: "item-2"
75
+ }),
76
+ CommandTopicCallbackFixtures$ReventlessCore.makeTopicItem("agg-3", {
77
+ TAG: "CreateItem",
78
+ itemId: "item-3"
79
+ })
80
+ ];
81
+ await Effect.runPromise(CommandTopicCallbackFixtures$ReventlessCore.TestHandler.handleJsonCommands(Stream.fromIterable(items)));
82
+ globalThis.expect(CommandTopicCallbackFixtures$ReventlessCore.capturedItems.contents.length).toBe(3);
83
+ });
84
+ });
85
+ globalThis.describe("mixed valid and invalid commands", () => {
86
+ globalThis.test("only valid commands reach commandsHandler", async () => {
87
+ let validItem = CommandTopicCallbackFixtures$ReventlessCore.makeTopicItem("agg-1", {
88
+ TAG: "CreateItem",
89
+ itemId: "item-1"
90
+ });
91
+ let invalidItem_command = null;
92
+ let invalidItem = {
93
+ command: invalidItem_command,
94
+ reference: "ref-bad"
95
+ };
96
+ await Effect.runPromise(CommandTopicCallbackFixtures$ReventlessCore.TestHandler.handleJsonCommands(Stream.fromIterable([
97
+ validItem,
98
+ invalidItem
99
+ ])));
100
+ globalThis.expect(CommandTopicCallbackFixtures$ReventlessCore.capturedItems.contents.length).toBe(1);
101
+ globalThis.expect(CommandTopicCallbackFixtures$ReventlessCore.capturedItems.contents[0].reference).toBe("agg-1");
102
+ });
103
+ });
104
+ });
105
+
106
+ /* Not a pure module */