@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,88 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as FTP$ReventlessCore from "../../src/util/FTP.res.mjs";
4
+
5
+ globalThis.describe("FTP.SSH2 should", () => {
6
+ globalThis.test("parse valid url, only url given", () => {
7
+ let t = FTP$ReventlessCore.parseUrl("example.com");
8
+ globalThis.expect(t).toEqual([
9
+ "example.com",
10
+ undefined,
11
+ ""
12
+ ]);
13
+ });
14
+ globalThis.test("parse valid url, url and relative path given", () => {
15
+ let t = FTP$ReventlessCore.parseUrl("example.com/some/path");
16
+ globalThis.expect(t).toEqual([
17
+ "example.com",
18
+ undefined,
19
+ "some/path"
20
+ ]);
21
+ });
22
+ globalThis.test("parse valid url, url and absolute path given", () => {
23
+ let t = FTP$ReventlessCore.parseUrl("example.com//some/path");
24
+ globalThis.expect(t).toEqual([
25
+ "example.com",
26
+ undefined,
27
+ "/some/path"
28
+ ]);
29
+ });
30
+ globalThis.test("parse valid url, url and port given", () => {
31
+ let t = FTP$ReventlessCore.parseUrl("example.com:8080");
32
+ globalThis.expect(t).toEqual([
33
+ "example.com",
34
+ 8080,
35
+ ""
36
+ ]);
37
+ });
38
+ globalThis.test("parse valid url, all parts given (relative path)", () => {
39
+ let t = FTP$ReventlessCore.parseUrl("reventless.example.com:8025/some/path");
40
+ globalThis.expect(t).toEqual([
41
+ "reventless.example.com",
42
+ 8025,
43
+ "some/path"
44
+ ]);
45
+ });
46
+ globalThis.test("parse valid url, all parts given (absolute path)", () => {
47
+ let t = FTP$ReventlessCore.parseUrl("reventless.example.com:8025//some/path");
48
+ globalThis.expect(t).toEqual([
49
+ "reventless.example.com",
50
+ 8025,
51
+ "/some/path"
52
+ ]);
53
+ });
54
+ globalThis.test("parse valid url, all parts given (relative path first)", () => {
55
+ let t = FTP$ReventlessCore.parseUrl("example.com/some/path:8080");
56
+ globalThis.expect(t).toEqual([
57
+ "example.com",
58
+ 8080,
59
+ "some/path"
60
+ ]);
61
+ });
62
+ globalThis.test("parse valid url, all parts given (absolute path first)", () => {
63
+ let t = FTP$ReventlessCore.parseUrl("example.com//some/path:8080");
64
+ globalThis.expect(t).toEqual([
65
+ "example.com",
66
+ 8080,
67
+ "/some/path"
68
+ ]);
69
+ });
70
+ globalThis.test("parse url with invalid port (relative path)", () => {
71
+ let t = FTP$ReventlessCore.parseUrl("example.com/some/path:invalidPort");
72
+ globalThis.expect(t).toEqual([
73
+ "example.com",
74
+ undefined,
75
+ "some/path"
76
+ ]);
77
+ });
78
+ globalThis.test("parse url with invalid port (absolute path)", () => {
79
+ let t = FTP$ReventlessCore.parseUrl("example.com//some/path:invalidPort");
80
+ globalThis.expect(t).toEqual([
81
+ "example.com",
82
+ undefined,
83
+ "/some/path"
84
+ ]);
85
+ });
86
+ });
87
+
88
+ /* Not a pure module */
@@ -0,0 +1,329 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
5
+ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
6
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
9
+ import * as AnsiStyle$Reventless from "@reventlessdev/reventless-spec/src/AnsiStyle.res.mjs";
10
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
11
+ import * as Logger$ReventlessCore from "../../src/util/Logger.res.mjs";
12
+ import * as Message$ReventlessCore from "../../src/Message.res.mjs";
13
+ import * as Runtime$ReventlessCore from "../../src/adapter/Runtime/Runtime.res.mjs";
14
+ import * as LogFormat$ReventlessCore from "../../src/util/LogFormat.res.mjs";
15
+ import * as PluginSpec$ReventlessCore from "../../src/plugin/lifecycle/PluginSpec.res.mjs";
16
+ import * as EffectLogger$ReventlessCore from "../../src/util/EffectLogger.res.mjs";
17
+
18
+ S.enableJson();
19
+
20
+ process.env["REVENTLESS_LOG_FORMAT"] = "text";
21
+
22
+ AnsiStyle$Reventless.reload();
23
+
24
+ globalThis.describe("LogFormat", () => {
25
+ globalThis.describe("commandJsonsToLogMessages", () => {
26
+ globalThis.test("empty", () => {
27
+ let arr = [];
28
+ globalThis.expect(LogFormat$ReventlessCore.commandJsonsToLogMessages(arr)).toEqual([]);
29
+ });
30
+ globalThis.test("simple", () => {
31
+ let commands = [{
32
+ TAG: "Heartbeat",
33
+ _0: "0.0.0"
34
+ }];
35
+ let meta = {
36
+ service: "testService",
37
+ time: "testTime",
38
+ ip: "testIp",
39
+ user: "testUser",
40
+ msgId: "testMsgId",
41
+ correlationId: "testCorrelationId"
42
+ };
43
+ let metaStr = JSON.stringify(Message$ReventlessCore.encode(meta, Message$ReventlessCore.metaSchema));
44
+ let arr = commands.map((command, idx) => ({
45
+ id: idx.toString(),
46
+ meta: meta,
47
+ commandJson: Message$ReventlessCore.encode(command, PluginSpec$ReventlessCore.commandSchema)
48
+ }));
49
+ let expected = `1/1: \x1b[1mHeartbeat\x1b[0m(0): {"command":{"TAG":"Heartbeat","_0":"0.0.0"},"meta":` + metaStr + `,"id":"0"}`;
50
+ globalThis.expect(LogFormat$ReventlessCore.commandJsonsToLogMessages(arr)).toEqual([expected]);
51
+ });
52
+ globalThis.test("complex", () => {
53
+ let commands = [
54
+ {
55
+ TAG: "Heartbeat",
56
+ _0: "0.0.0"
57
+ },
58
+ {
59
+ TAG: "Connect",
60
+ _0: {
61
+ id: "id",
62
+ name: "testName",
63
+ version: "testVersion",
64
+ extensionPoints: [{
65
+ name: "testExtensionPoint",
66
+ commandTopic: "testCommandTopic",
67
+ eventTopic: "testEventTopic"
68
+ }],
69
+ extensions: [{
70
+ name: "testExtension",
71
+ extensionPointName: "testExtensionPoint",
72
+ dcbSources: []
73
+ }],
74
+ eventCollector: "testEventCollector",
75
+ extensionProtocols: [],
76
+ apiSchemaFragment: undefined,
77
+ apiTarget: undefined,
78
+ structure: undefined,
79
+ dcbEventLog: undefined,
80
+ kind: "Domain"
81
+ }
82
+ }
83
+ ];
84
+ let meta = {
85
+ service: "testService",
86
+ time: "testTime",
87
+ ip: "testIp",
88
+ user: "testUser",
89
+ msgId: "testMsgId",
90
+ correlationId: "testCorrelationId"
91
+ };
92
+ let metaStr = JSON.stringify(Message$ReventlessCore.encode(meta, Message$ReventlessCore.metaSchema));
93
+ let arr = commands.map((command, idx) => ({
94
+ id: idx.toString(),
95
+ meta: meta,
96
+ commandJson: Message$ReventlessCore.encode(command, PluginSpec$ReventlessCore.commandSchema)
97
+ }));
98
+ let expected1 = `1/2: \x1b[1mHeartbeat\x1b[0m(0): {"command":{"TAG":"Heartbeat","_0":"0.0.0"},"meta":` + metaStr + `,"id":"0"}`;
99
+ let expected2 = `2/2: \x1b[1mConnect\x1b[0m(1): {"command":{"TAG":"Connect","_0":{"id":"id","name":"testName","version":"testVersion","extensionPoints":[{"name":"testExtensionPoint","commandTopic":"testCommandTopic","eventTopic":"testEventTopic"}],"extensions":[{"name":"testExtension","extensionPointName":"testExtensionPoint","dcbSources":[]}],"eventCollector":"testEventCollector","extensionProtocols":[],"apiSchemaFragment":null,"apiTarget":null,"structure":null,"dcbEventLog":null,"kind":"Domain"}},"meta":` + metaStr + `,"id":"1"}`;
100
+ globalThis.expect(LogFormat$ReventlessCore.commandJsonsToLogMessages(arr)).toEqual([
101
+ expected1,
102
+ expected2
103
+ ]);
104
+ });
105
+ });
106
+ globalThis.describe("event'JsonToLogMessage", () => {
107
+ globalThis.test("simple", () => {
108
+ let eventJson$p = Message$ReventlessCore.encodeEvent$p({
109
+ id: "testId",
110
+ meta: {
111
+ service: "testService",
112
+ time: "testTime",
113
+ ip: "testIp",
114
+ user: "testUser",
115
+ msgId: "testMsgId",
116
+ correlationId: "testCorrelationId"
117
+ },
118
+ event: {
119
+ TAG: "VersionDetected",
120
+ _0: "0.0.0"
121
+ }
122
+ }, S.string, PluginSpec$ReventlessCore.eventSchema);
123
+ let msg = LogFormat$ReventlessCore.event$pJsonToLogMessage(eventJson$p);
124
+ globalThis.expect(msg).toEqual(`\x1b[1mVersionDetected\x1b[0m(testId): {"event":{"TAG":"VersionDetected","_0":"0.0.0"},"meta":{"service":"testService","time":"testTime","ip":"testIp","user":"testUser","msgId":"testMsgId","correlationId":"testCorrelationId"},"id":"testId"}`);
125
+ });
126
+ });
127
+ });
128
+
129
+ function hasAnsi(s) {
130
+ return s.includes("\x1b");
131
+ }
132
+
133
+ function captureLogs(fn) {
134
+ let captured = [];
135
+ let original = console.log;
136
+ console.log = s => {
137
+ captured.push(s);
138
+ };
139
+ let result;
140
+ try {
141
+ fn();
142
+ result = {
143
+ TAG: "Ok",
144
+ _0: undefined
145
+ };
146
+ } catch (raw_e) {
147
+ let e = Primitive_exceptions.internalToException(raw_e);
148
+ result = {
149
+ TAG: "Error",
150
+ _0: e
151
+ };
152
+ }
153
+ console.log = original;
154
+ if (result.TAG === "Ok") {
155
+ return captured;
156
+ }
157
+ throw result._0;
158
+ }
159
+
160
+ let validLevels = [
161
+ "DEBUG",
162
+ "INFO",
163
+ "WARN",
164
+ "ERROR"
165
+ ];
166
+
167
+ function isCleanRecord(line) {
168
+ if (line.includes("\x1b")) {
169
+ return false;
170
+ }
171
+ try {
172
+ let obj = Stdlib_JSON.Decode.object(JSON.parse(line));
173
+ if (obj === undefined) {
174
+ return false;
175
+ }
176
+ let levelOk = Stdlib_Option.mapOr(Stdlib_Option.flatMap(obj["level"], Stdlib_JSON.Decode.string), false, l => validLevels.includes(l));
177
+ let msgOk = Stdlib_Option.isSome(Stdlib_Option.flatMap(obj["message"], Stdlib_JSON.Decode.string));
178
+ if (levelOk) {
179
+ return msgOk;
180
+ } else {
181
+ return false;
182
+ }
183
+ } catch (exn) {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ function fieldOf(line, key) {
189
+ let obj = Stdlib_JSON.Decode.object(JSON.parse(line));
190
+ if (obj !== undefined) {
191
+ return Stdlib_Option.flatMap(obj[key], Stdlib_JSON.Decode.string);
192
+ }
193
+ }
194
+
195
+ globalThis.describe("JSON sink", () => {
196
+ globalThis.beforeAll(() => {
197
+ process.env["REVENTLESS_LOG_FORMAT"] = "json";
198
+ AnsiStyle$Reventless.reload();
199
+ });
200
+ globalThis.afterAll(() => {
201
+ process.env["REVENTLESS_LOG_FORMAT"] = "text";
202
+ AnsiStyle$Reventless.reload();
203
+ });
204
+ let log = Logger$ReventlessCore.makeLogger("Debug");
205
+ globalThis.test("Logger.info emits one clean JSON record with comp as a top-level field", () => {
206
+ let lines = captureLogs(() => log.info("Aggregate(Product)", undefined, "handling command"));
207
+ let line = lines.length === 1 ? lines[0] : "";
208
+ let ok = lines.length === 1 && isCleanRecord(line) && Primitive_object.equal(fieldOf(line, "comp"), "Aggregate(Product)") && Primitive_object.equal(fieldOf(line, "message"), "handling command");
209
+ globalThis.expect(ok).toBe(true);
210
+ });
211
+ globalThis.test("Logger.info resolves plugin to a top-level field when the comp is registered", () => {
212
+ Logger$ReventlessCore.registerComponentPlugin("Product", "Catalog");
213
+ let lines = captureLogs(() => log.info("Aggregate(Product)", undefined, "handling command"));
214
+ let line = lines.length === 1 ? lines[0] : "";
215
+ globalThis.expect(lines.length === 1 && Primitive_object.equal(fieldOf(line, "plugin"), "Catalog")).toBe(true);
216
+ });
217
+ globalThis.test("Logger.info resolves plugin from a kind-suffixed component name", () => {
218
+ Logger$ReventlessCore.registerComponentPlugin("Products", "Catalog");
219
+ let lines = captureLogs(() => log.info("EventCollector(ProductsReadModel)", undefined, "projecting event"));
220
+ let line = lines.length === 1 ? lines[0] : "";
221
+ globalThis.expect(lines.length === 1 && Primitive_object.equal(fieldOf(line, "plugin"), "Catalog")).toBe(true);
222
+ });
223
+ globalThis.test("Plugin resolution prefers the longest registered prefix", () => {
224
+ Logger$ReventlessCore.registerComponentPlugin("Order", "Ordering");
225
+ Logger$ReventlessCore.registerComponentPlugin("OrderLines", "Billing");
226
+ let lines = captureLogs(() => log.info("EventCollector(OrderLinesReadModel)", undefined, "projecting event"));
227
+ let line = lines.length === 1 ? lines[0] : "";
228
+ globalThis.expect(lines.length === 1 && Primitive_object.equal(fieldOf(line, "plugin"), "Billing")).toBe(true);
229
+ });
230
+ globalThis.test("dispatch annotation carries comp onto a handler line that passes none", () => {
231
+ let lines = captureLogs(() => Effect.runSync(Runtime$ReventlessCore.annotateInvocation(EffectLogger$ReventlessCore.logInfo(undefined, undefined, "projected"), "cid-1", "parent-1", "EventCollector(ProductsReadModel)", undefined, undefined, undefined, undefined, undefined)));
232
+ let line = lines.length >= 1 ? lines[0] : "";
233
+ let ok = Primitive_object.equal(fieldOf(line, "comp"), "EventCollector(ProductsReadModel)") && Primitive_object.equal(fieldOf(line, "correlationId"), "cid-1") && Primitive_object.equal(fieldOf(line, "causationId"), "parent-1") && Primitive_object.equal(fieldOf(line, "message"), "projected");
234
+ globalThis.expect(ok).toBe(true);
235
+ });
236
+ globalThis.test("Logger.warn emits one clean JSON record", () => {
237
+ let lines = captureLogs(() => log.warn("Platform", undefined, "heartbeat skipped"));
238
+ globalThis.expect(lines.length === 1 && isCleanRecord(lines[0])).toBe(true);
239
+ });
240
+ globalThis.test("Logger.error with ~data emits one clean JSON record", () => {
241
+ let lines = captureLogs(() => log.error("Util_AppSync_Caller", JSON.parse(`{"errors":["boom"]}`), "query errors"));
242
+ globalThis.expect(lines.length === 1 && isCleanRecord(lines[0])).toBe(true);
243
+ });
244
+ globalThis.test("EffectLogger.logInfo emits clean JSON through install()", () => {
245
+ let lines = captureLogs(() => Effect.runSync(EffectLogger$ReventlessCore.logInfo("Aggregate(Product)", undefined, "replay done")));
246
+ let allClean = lines.filter(l => !isCleanRecord(l)).length === 0;
247
+ globalThis.expect(lines.length >= 1 && allClean).toBe(true);
248
+ });
249
+ globalThis.test("EffectLogger.logInfo carries ~comp + ~detail as structured fields (no \\x00)", () => {
250
+ let lines = captureLogs(() => Effect.runSync(EffectLogger$ReventlessCore.logInfo("Aggregate(Product)", JSON.parse(`{"id":"p-1"}`), "added")));
251
+ let ok = lines.some(line => {
252
+ let obj = Stdlib_JSON.Decode.object(JSON.parse(line));
253
+ if (obj !== undefined && Primitive_object.equal(Stdlib_Option.flatMap(obj["comp"], Stdlib_JSON.Decode.string), "Aggregate(Product)")) {
254
+ return Primitive_object.equal(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(obj["detail"], Stdlib_JSON.Decode.object), d => d["id"]), Stdlib_JSON.Decode.string), "p-1");
255
+ } else {
256
+ return false;
257
+ }
258
+ });
259
+ globalThis.expect(ok).toBe(true);
260
+ });
261
+ globalThis.test("Effect.annotateLogs(correlationId) surfaces as a top-level field", () => {
262
+ let lines = captureLogs(() => Effect.runSync(Effect.annotateLogs(EffectLogger$ReventlessCore.logInfo("Aggregate(Product)", undefined, "handling"), "correlationId", "c-123")));
263
+ globalThis.expect(lines.some(line => Primitive_object.equal(fieldOf(line, "correlationId"), "c-123"))).toBe(true);
264
+ });
265
+ globalThis.test("Effect.annotateLogs(plugin) overrides registry resolution", () => {
266
+ let lines = captureLogs(() => Effect.runSync(Effect.annotateLogs(EffectLogger$ReventlessCore.logInfo("Aggregate(Unregistered)", undefined, "handling"), "plugin", "Ordering")));
267
+ globalThis.expect(lines.some(line => Primitive_object.equal(fieldOf(line, "plugin"), "Ordering"))).toBe(true);
268
+ });
269
+ globalThis.test("every JSON record carries an RFC 3339 time field", () => {
270
+ let lines = captureLogs(() => log.info("Platform", undefined, "tick"));
271
+ let t = Stdlib_Option.flatMap(lines[0], l => fieldOf(l, "time"));
272
+ let ok = t !== undefined ? t.includes("T") && t.endsWith("Z") : false;
273
+ globalThis.expect(ok).toBe(true);
274
+ });
275
+ globalThis.test("service field is emitted when REVENTLESS_SERVICE is set", () => {
276
+ process.env["REVENTLESS_SERVICE"] = "TestService";
277
+ let lines = captureLogs(() => log.info("Platform", undefined, "tick"));
278
+ let got = Stdlib_Option.flatMap(lines[0], l => fieldOf(l, "service"));
279
+ Stdlib_Dict.$$delete(process.env, "REVENTLESS_SERVICE");
280
+ globalThis.expect(got).toEqual("TestService");
281
+ });
282
+ globalThis.test("oversized detail is truncated to a preview stub", () => {
283
+ let big = "x".repeat(40000);
284
+ let detail = Object.fromEntries([[
285
+ "blob",
286
+ big
287
+ ]]);
288
+ let direct = captureLogs(() => Logger$ReventlessCore.emit("Info", "Platform", undefined, detail, undefined, "big"));
289
+ let obj = Stdlib_Option.flatMap(direct[0], l => Stdlib_JSON.Decode.object(JSON.parse(l)));
290
+ let ok;
291
+ if (obj !== undefined) {
292
+ let d = Stdlib_Option.flatMap(obj["detail"], Stdlib_JSON.Decode.object);
293
+ ok = d !== undefined ? Primitive_object.equal(Stdlib_Option.flatMap(d["truncated"], Stdlib_JSON.Decode.bool), true) && Stdlib_Option.mapOr(Stdlib_Option.flatMap(d["preview"], Stdlib_JSON.Decode.string), false, p => p.length <= 512) : false;
294
+ } else {
295
+ ok = false;
296
+ }
297
+ globalThis.expect(ok).toBe(true);
298
+ });
299
+ globalThis.test("LogFormat.cmdName carries no ANSI in a JSON sink", () => {
300
+ let cmd_meta = {
301
+ service: "testService",
302
+ time: "testTime",
303
+ ip: "testIp",
304
+ user: "testUser",
305
+ msgId: "testMsgId",
306
+ correlationId: "testCorrelationId"
307
+ };
308
+ let cmd_commandJson = Message$ReventlessCore.encode({
309
+ TAG: "Heartbeat",
310
+ _0: "0.0.0"
311
+ }, PluginSpec$ReventlessCore.commandSchema);
312
+ let cmd = {
313
+ id: "0",
314
+ meta: cmd_meta,
315
+ commandJson: cmd_commandJson
316
+ };
317
+ let name = LogFormat$ReventlessCore.cmdName(cmd);
318
+ globalThis.expect(!name.includes("\x1b") && name === "Heartbeat").toBe(true);
319
+ });
320
+ });
321
+
322
+ export {
323
+ hasAnsi,
324
+ captureLogs,
325
+ validLevels,
326
+ isCleanRecord,
327
+ fieldOf,
328
+ }
329
+ /* Not a pure module */
@@ -0,0 +1,40 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Logger$ReventlessCore from "../../src/util/Logger.res.mjs";
4
+
5
+ globalThis.describe("Logger.debugLazy", () => {
6
+ globalThis.test("does NOT invoke the thunk at the default Info level", () => {
7
+ let called = {
8
+ contents: false
9
+ };
10
+ let log = Logger$ReventlessCore.makeLogger("Info");
11
+ log.debugLazy("Test", () => {
12
+ called.contents = true;
13
+ return "should never be built";
14
+ });
15
+ globalThis.expect(called.contents).toEqual(false);
16
+ });
17
+ globalThis.test("invokes the thunk when debug output is enabled", () => {
18
+ let called = {
19
+ contents: false
20
+ };
21
+ let log = Logger$ReventlessCore.makeLogger("Debug");
22
+ log.debugLazy("Test", () => {
23
+ called.contents = true;
24
+ return "built";
25
+ });
26
+ globalThis.expect(called.contents).toEqual(true);
27
+ });
28
+ globalThis.test("the silent logger never invokes the thunk", () => {
29
+ let called = {
30
+ contents: false
31
+ };
32
+ Logger$ReventlessCore.silent.debugLazy("Test", () => {
33
+ called.contents = true;
34
+ return "x";
35
+ });
36
+ globalThis.expect(called.contents).toEqual(false);
37
+ });
38
+ });
39
+
40
+ /* Not a pure module */
@@ -0,0 +1,218 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Message$ReventlessCore from "../../src/Message.res.mjs";
6
+ import * as PluginSpec$ReventlessCore from "../../src/plugin/lifecycle/PluginSpec.res.mjs";
7
+
8
+ globalThis.describe("Message should", () => {
9
+ globalThis.test("create a valid sequenceNr", () => {
10
+ globalThis.expect(Message$ReventlessCore.hrtimeToString([
11
+ 1,
12
+ 1
13
+ ], 123456789)).toBe("123456789-000000001");
14
+ });
15
+ globalThis.test("get variant name of json without payload", () => {
16
+ let variantJson = Message$ReventlessCore.encode({
17
+ TAG: "Heartbeat",
18
+ _0: "0.0.0"
19
+ }, PluginSpec$ReventlessCore.commandSchema);
20
+ let variantName = Message$ReventlessCore.variantNameOfJson(variantJson);
21
+ globalThis.expect(variantName).toBe("Heartbeat");
22
+ });
23
+ globalThis.test("get variant name of json with payload", () => {
24
+ let variant = {
25
+ TAG: "Connect",
26
+ _0: {
27
+ id: "id",
28
+ name: "testName",
29
+ version: "testVersion",
30
+ extensionPoints: [{
31
+ name: "testExtensionPoint",
32
+ commandTopic: "testCommandTopic",
33
+ eventTopic: "testEventTopic"
34
+ }],
35
+ extensions: [{
36
+ name: "testExtension",
37
+ extensionPointName: "testExtensionPoint",
38
+ dcbSources: []
39
+ }],
40
+ eventCollector: "testEventCollector",
41
+ extensionProtocols: [],
42
+ apiSchemaFragment: undefined,
43
+ apiTarget: undefined,
44
+ structure: undefined,
45
+ dcbEventLog: undefined,
46
+ kind: "Domain"
47
+ }
48
+ };
49
+ let variantJson = Message$ReventlessCore.encode(variant, PluginSpec$ReventlessCore.commandSchema);
50
+ let variantName = Message$ReventlessCore.variantNameOfJson(variantJson);
51
+ globalThis.expect(variantName).toBe("Connect");
52
+ });
53
+ globalThis.test("get event name of eventJson'", () => {
54
+ let eventJson$p = Message$ReventlessCore.encodeEvent$p({
55
+ id: "testId",
56
+ meta: {
57
+ service: "testService",
58
+ time: "testTime",
59
+ ip: "testIp",
60
+ user: "testUser",
61
+ msgId: "testMsgId",
62
+ correlationId: "testCorrelationId"
63
+ },
64
+ event: {
65
+ TAG: "VersionDetected",
66
+ _0: "0.0.0"
67
+ }
68
+ }, S.string, PluginSpec$ReventlessCore.eventSchema);
69
+ let eventName = Message$ReventlessCore.eventNameOfEvent$pJson(eventJson$p);
70
+ globalThis.expect(eventName).toBe("VersionDetected");
71
+ });
72
+ globalThis.test("get id of eventJson'", () => {
73
+ let eventJson$p = Message$ReventlessCore.encodeEvent$p({
74
+ id: "testId",
75
+ meta: {
76
+ service: "testService",
77
+ time: "testTime",
78
+ ip: "testIp",
79
+ user: "testUser",
80
+ msgId: "testMsgId",
81
+ correlationId: "testCorrelationId"
82
+ },
83
+ event: {
84
+ TAG: "VersionDetected",
85
+ _0: "0.0.0"
86
+ }
87
+ }, S.string, PluginSpec$ReventlessCore.eventSchema);
88
+ let eventId = Stdlib_Option.getOrThrow(Message$ReventlessCore.idOfEvent$pJson(eventJson$p), undefined);
89
+ globalThis.expect(eventId).toBe("testId");
90
+ });
91
+ globalThis.test("tolerantly decode a VersionConnected persisted before kind/structure fields existed", () => {
92
+ let def = {
93
+ id: "id",
94
+ name: "Ordering",
95
+ version: "1.0.0",
96
+ extensionPoints: [],
97
+ extensions: [],
98
+ eventCollector: "arn",
99
+ extensionProtocols: [],
100
+ apiSchemaFragment: undefined,
101
+ apiTarget: undefined,
102
+ structure: {
103
+ readModels: [],
104
+ stateViewSlices: [],
105
+ stateChangeSlices: [],
106
+ aggregates: [{
107
+ name: "Order",
108
+ commands: [],
109
+ producedEventTypes: [],
110
+ consumedEventTypes: [],
111
+ linkedViews: [],
112
+ consistencyRead: undefined,
113
+ events: [],
114
+ chapter: undefined
115
+ }],
116
+ automationSlices: [],
117
+ outboundTranslationSlices: [],
118
+ inboundTranslationSlices: [],
119
+ extensions: [],
120
+ extensionPoints: undefined
121
+ },
122
+ dcbEventLog: undefined,
123
+ kind: "Domain"
124
+ };
125
+ let event$p_meta = {
126
+ service: "svc",
127
+ time: "t",
128
+ ip: "ip",
129
+ user: "u",
130
+ msgId: "m",
131
+ correlationId: "c"
132
+ };
133
+ let event$p_event = {
134
+ TAG: "VersionConnected",
135
+ _0: def
136
+ };
137
+ let event$p = {
138
+ id: "id",
139
+ meta: event$p_meta,
140
+ event: event$p_event
141
+ };
142
+ let json = Message$ReventlessCore.encodeEvent$p(event$p, S.string, PluginSpec$ReventlessCore.eventSchema);
143
+ let oldJson = (function(j){
144
+ var c = JSON.parse(JSON.stringify(j));
145
+ var d = c.event._0;
146
+ delete d.kind;
147
+ delete d.apiSchemaFragment;
148
+ var agg = d.structure.aggregates[0];
149
+ delete agg.events;
150
+ delete agg.chapter;
151
+ return c;
152
+ })(json);
153
+ let strictThrew;
154
+ try {
155
+ S.parseJsonOrThrow(oldJson, Message$ReventlessCore.toEventSchema$p(S.string, PluginSpec$ReventlessCore.eventSchema));
156
+ strictThrew = false;
157
+ } catch (exn) {
158
+ strictThrew = true;
159
+ }
160
+ globalThis.expect(strictThrew).toBe(true);
161
+ let decoded = Message$ReventlessCore.decodeEvent$p(oldJson, S.string, PluginSpec$ReventlessCore.eventSchema);
162
+ let d = decoded.event;
163
+ if (d.TAG === "VersionConnected") {
164
+ let d$1 = d._0;
165
+ let match = d$1.kind;
166
+ let tmp;
167
+ tmp = match === "Domain" ? "Domain" : "other";
168
+ globalThis.expect(tmp).toBe("Domain");
169
+ globalThis.expect(Stdlib_Option.isNone(d$1.apiSchemaFragment)).toBe(true);
170
+ let structure = Stdlib_Option.getOrThrow(d$1.structure, undefined);
171
+ let agg = structure.aggregates[0];
172
+ globalThis.expect(agg.events.length).toBe(0);
173
+ globalThis.expect(Stdlib_Option.isNone(agg.chapter)).toBe(true);
174
+ return;
175
+ }
176
+ globalThis.expect("wrong-variant").toBe("VersionConnected");
177
+ });
178
+ globalThis.test("Message.decode heals a VersionConnected variant missing kind (the replay path)", () => {
179
+ let def = {
180
+ id: "id",
181
+ name: "Ordering",
182
+ version: "1.0.0",
183
+ extensionPoints: [],
184
+ extensions: [],
185
+ eventCollector: "arn",
186
+ extensionProtocols: [],
187
+ apiSchemaFragment: undefined,
188
+ apiTarget: undefined,
189
+ structure: undefined,
190
+ dcbEventLog: undefined,
191
+ kind: "Domain"
192
+ };
193
+ let variantJson = Message$ReventlessCore.encode({
194
+ TAG: "VersionConnected",
195
+ _0: def
196
+ }, PluginSpec$ReventlessCore.eventSchema);
197
+ let staleJson = (function(j){ var c = JSON.parse(JSON.stringify(j)); delete c._0.kind; return c; })(variantJson);
198
+ let strictThrew;
199
+ try {
200
+ S.parseJsonOrThrow(staleJson, PluginSpec$ReventlessCore.eventSchema);
201
+ strictThrew = false;
202
+ } catch (exn) {
203
+ strictThrew = true;
204
+ }
205
+ globalThis.expect(strictThrew).toBe(true);
206
+ let d = Message$ReventlessCore.decode(staleJson, PluginSpec$ReventlessCore.eventSchema);
207
+ if (d.TAG === "VersionConnected") {
208
+ let match = d._0.kind;
209
+ let tmp;
210
+ tmp = match === "Domain" ? "Domain" : "other";
211
+ globalThis.expect(tmp).toBe("Domain");
212
+ return;
213
+ }
214
+ globalThis.expect("wrong-variant").toBe("VersionConnected");
215
+ });
216
+ });
217
+
218
+ /* Not a pure module */