@reventlessdev/reventless-core 3.0.0-alpha.170 → 3.0.0-alpha.172
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.
- package/CHANGELOG.md +14 -0
- package/package.json +14 -14
- package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +5 -2
- package/src/components/ExtensionPoint/ExtensionPoint_Builder.res.mjs +3 -3
- package/src/components/Heartbeat/Heartbeat.res +2 -2
- package/src/components/Heartbeat/Heartbeat_Builder.res +2 -2
- package/src/components/Heartbeat/Heartbeat_Builder.res.mjs +2 -4
- package/src/components/Task/Task_Builder.res +6 -4
- package/src/components/Task/Task_Builder.res.mjs +4 -4
- package/src/plugin/component/Plugin_Builder.res +5 -1
- package/src/plugin/component/Plugin_Builder.res.mjs +1 -1
- package/src/plugin/component/Plugin_Helpers.res +6 -1
- package/src/plugin/connect/PluginExtensionPoint_Builder.res +2 -0
- package/src/plugin/connect/PluginExtensionPoint_Builder.res.mjs +3 -3
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res +12 -5
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +8 -2
- package/tests/plugin/HeartbeatDisconnectGraceTest.res +98 -0
- package/tests/IdentityTest.res.mjs +0 -174
- package/tests/adapter/MonitoringTest.res.mjs +0 -82
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +0 -356
- package/tests/admin/Platform_UIFragmentsApiTest.res.mjs +0 -101
- package/tests/aggregate/AggregateCacheTest.res.mjs +0 -433
- package/tests/aggregate/AggregateCallbackTest.res.mjs +0 -143
- package/tests/aggregate/AggregateCausationTest.res.mjs +0 -47
- package/tests/aggregate/AggregateConflictTest.res.mjs +0 -386
- package/tests/aggregate/AggregateFixtures.res.mjs +0 -308
- package/tests/aggregate/AggregateRejectionTest.res.mjs +0 -166
- package/tests/aggregate/AggregateSnapshotTest.res.mjs +0 -645
- package/tests/api/ApiNoApiTest.res.mjs +0 -90
- package/tests/api/GraphQL_StitcherTest.res.mjs +0 -112
- package/tests/api/SimpleTest.res.mjs +0 -10
- package/tests/api/SuryToJsonSchemaTest.res.mjs +0 -674
- package/tests/commandgenerator/CommandGeneratorCallbackTest.res.mjs +0 -160
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +0 -197
- package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +0 -152
- package/tests/commandtopic/CommandTopicCallbackTest.res.mjs +0 -106
- package/tests/commandtopic/CommandTopicHelpersRejectionTest.res.mjs +0 -109
- package/tests/counter/CounterCallbackTest.res.mjs +0 -140
- package/tests/counter/CounterFixtures.res.mjs +0 -67
- package/tests/dcb/DcbDecodeTest.res.mjs +0 -194
- package/tests/dcb/DcbEventLogOperationsTest.res.mjs +0 -268
- package/tests/dcb/DcbFixtures.res.mjs +0 -534
- package/tests/dcb/DcbScopeInferenceTest.res.mjs +0 -480
- package/tests/dcb/DcbStateChangeSliceTest.res.mjs +0 -540
- package/tests/dcb/DcbTagTest.res.mjs +0 -867
- package/tests/dcb/DcbValidationTest.res.mjs +0 -476
- package/tests/eventlog/EventLogFixtures.res.mjs +0 -196
- package/tests/eventlog/EventLogOperationsTest.res.mjs +0 -192
- package/tests/eventlog/EventLogRetryTest.res.mjs +0 -195
- package/tests/eventmapper/EventMapperCallbackTest.res.mjs +0 -141
- package/tests/eventmapper/EventMapperFixtures.res.mjs +0 -440
- package/tests/eventmapper/EventMapperTest.res.mjs +0 -83
- package/tests/eventtopic/EventTopicFixtures.res.mjs +0 -65
- package/tests/eventtopic/EventTopicOperationsTest.res.mjs +0 -71
- package/tests/extensionpoint/ExtensionPointCallbackTest.res.mjs +0 -94
- package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +0 -205
- package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +0 -304
- package/tests/ftp/FTPTest.res.mjs +0 -88
- package/tests/logger/LogFormatTest.res.mjs +0 -309
- package/tests/logger/LoggerLazyTest.res.mjs +0 -40
- package/tests/message/MessageTest.res.mjs +0 -218
- package/tests/message/MetaEnvelopeTest.res.mjs +0 -188
- package/tests/plugin/ManifestVisibilityTest.res.mjs +0 -215
- package/tests/plugin/PluginSpecExperiment.res.mjs +0 -31
- package/tests/plugin/PluginStructureTest.res.mjs +0 -419
- package/tests/plugin/PluginVersionTest.res.mjs +0 -30
- package/tests/plugin/SchemaWalkerTest.res.mjs +0 -160
- package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +0 -62
- package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +0 -69
- package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +0 -95
- package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +0 -69
- package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +0 -69
- package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +0 -81
- package/tests/poc/StructuralSubtypingPoc.res.mjs +0 -61
- package/tests/projection/ProjectionOptimizeTest.res.mjs +0 -75
- package/tests/querydb/QueryDbFixtures.res.mjs +0 -135
- package/tests/querydb/QueryDbOperationsTest.res.mjs +0 -168
- package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res.mjs +0 -77
- package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +0 -139
- package/tests/util/CommandPublisherTest.res.mjs +0 -78
- package/tests/util/CsvStreamTest.res.mjs +0 -51
- package/tests/util/LruTest.res.mjs +0 -105
- package/tests/util/MetricsTest.res.mjs +0 -53
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
-
|
|
3
|
-
import * as S from "sury/src/S.res.mjs";
|
|
4
|
-
import * as JestGlobals from "@reventlessdev/rescript-jest/src/JestGlobals.res.mjs";
|
|
5
|
-
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
6
|
-
import * as DcbValidation$Reventless from "@reventlessdev/reventless-spec/src/components/DcbValidation.res.mjs";
|
|
7
|
-
|
|
8
|
-
let producedASchema = S.union([
|
|
9
|
-
S.schema(s => ({
|
|
10
|
-
TAG: "ItemCreated",
|
|
11
|
-
itemId: s.m(DcbTag$Reventless.string),
|
|
12
|
-
name: s.m(S.string)
|
|
13
|
-
})),
|
|
14
|
-
S.schema(s => ({
|
|
15
|
-
TAG: "ItemRenamed",
|
|
16
|
-
itemId: s.m(DcbTag$Reventless.string),
|
|
17
|
-
newName: s.m(S.string)
|
|
18
|
-
}))
|
|
19
|
-
]);
|
|
20
|
-
|
|
21
|
-
let producedBSchema = S.schema(s => ({
|
|
22
|
-
TAG: "ItemArchived",
|
|
23
|
-
itemId: s.m(DcbTag$Reventless.string)
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
let producedADuplicateSchema = S.schema(s => ({
|
|
27
|
-
TAG: "ItemCreated",
|
|
28
|
-
itemId: s.m(DcbTag$Reventless.string),
|
|
29
|
-
name: s.m(S.string)
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
let producedAMismatchFieldsSchema = S.schema(s => ({
|
|
33
|
-
TAG: "ItemCreated",
|
|
34
|
-
itemId: s.m(DcbTag$Reventless.string)
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
let producedAMismatchTagsSchema = S.schema(s => ({
|
|
38
|
-
TAG: "ItemCreated",
|
|
39
|
-
itemId: s.m(S.string),
|
|
40
|
-
name: s.m(S.string)
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
let producedAMismatchTypeSchema = S.schema(s => ({
|
|
44
|
-
TAG: "ItemCreated",
|
|
45
|
-
itemId: s.m(DcbTag$Reventless.string),
|
|
46
|
-
name: s.m(S.float)
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
|
-
let consumedFullSchema = S.union([
|
|
50
|
-
S.schema(s => ({
|
|
51
|
-
TAG: "ItemCreated",
|
|
52
|
-
itemId: s.m(S.string),
|
|
53
|
-
name: s.m(S.string)
|
|
54
|
-
})),
|
|
55
|
-
S.schema(s => ({
|
|
56
|
-
TAG: "ItemRenamed",
|
|
57
|
-
itemId: s.m(S.string),
|
|
58
|
-
newName: s.m(S.string)
|
|
59
|
-
}))
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
let consumedPartialSchema = S.schema(s => ({
|
|
63
|
-
TAG: "ItemCreated",
|
|
64
|
-
itemId: s.m(S.string)
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
|
-
let consumedPayloadLessSchema = S.union([
|
|
68
|
-
S.literal("ItemCreated"),
|
|
69
|
-
S.literal("ItemArchived")
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
let consumedDanglingSchema = S.schema(s => ({
|
|
73
|
-
TAG: "ItemDeleted",
|
|
74
|
-
itemId: s.m(S.string)
|
|
75
|
-
}));
|
|
76
|
-
|
|
77
|
-
let consumedBadFieldSchema = S.schema(s => ({
|
|
78
|
-
TAG: "ItemCreated",
|
|
79
|
-
itemId: s.m(S.string),
|
|
80
|
-
rating: s.m(S.float)
|
|
81
|
-
}));
|
|
82
|
-
|
|
83
|
-
let consumedBadTypeSchema = S.schema(s => ({
|
|
84
|
-
TAG: "ItemCreated",
|
|
85
|
-
itemId: s.m(S.string),
|
|
86
|
-
name: s.m(S.float)
|
|
87
|
-
}));
|
|
88
|
-
|
|
89
|
-
let recordDemandCommandSchema = S.schema(s => ({
|
|
90
|
-
TAG: "RecordDemand",
|
|
91
|
-
productId: s.m(DcbTag$Reventless.string),
|
|
92
|
-
orderId: s.m(DcbTag$Reventless.string)
|
|
93
|
-
}));
|
|
94
|
-
|
|
95
|
-
let touchDemandCommandSchema = S.schema(s => ({
|
|
96
|
-
TAG: "TouchDemand",
|
|
97
|
-
productId: s.m(DcbTag$Reventless.string)
|
|
98
|
-
}));
|
|
99
|
-
|
|
100
|
-
let placeOrderCommandSchema = S.schema(s => ({
|
|
101
|
-
TAG: "PlaceOrder",
|
|
102
|
-
orderId: s.m(DcbTag$Reventless.string),
|
|
103
|
-
productIds: s.m(S.array(DcbTag$Reventless.stringForKey("productId")))
|
|
104
|
-
}));
|
|
105
|
-
|
|
106
|
-
let demandConsumedSchema = S.union([
|
|
107
|
-
S.schema(s => ({
|
|
108
|
-
TAG: "ProductDemandRecorded",
|
|
109
|
-
productId: s.m(S.string),
|
|
110
|
-
orderId: s.m(S.string)
|
|
111
|
-
})),
|
|
112
|
-
S.schema(s => ({
|
|
113
|
-
TAG: "ProductDemandRevoked",
|
|
114
|
-
productId: s.m(S.string),
|
|
115
|
-
orderId: s.m(S.string)
|
|
116
|
-
}))
|
|
117
|
-
]);
|
|
118
|
-
|
|
119
|
-
let demandProducedSchema = S.union([
|
|
120
|
-
S.schema(s => ({
|
|
121
|
-
TAG: "ProductDemandRecorded",
|
|
122
|
-
productId: s.m(DcbTag$Reventless.string),
|
|
123
|
-
orderId: s.m(DcbTag$Reventless.string)
|
|
124
|
-
})),
|
|
125
|
-
S.schema(s => ({
|
|
126
|
-
TAG: "ProductDemandRevoked",
|
|
127
|
-
productId: s.m(DcbTag$Reventless.string),
|
|
128
|
-
orderId: s.m(DcbTag$Reventless.string),
|
|
129
|
-
customerId: s.m(DcbTag$Reventless.string)
|
|
130
|
-
}))
|
|
131
|
-
]);
|
|
132
|
-
|
|
133
|
-
function u(prim) {
|
|
134
|
-
return prim;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
let producedTagKeys = DcbTag$Reventless.extractTagKeysByEventType(demandProducedSchema);
|
|
138
|
-
|
|
139
|
-
let subscribedCrossPartitionSchema = S.schema(s => ({
|
|
140
|
-
TAG: "StudentSubscribed",
|
|
141
|
-
courseId: s.m(DcbTag$Reventless.partition),
|
|
142
|
-
studentId: s.m(DcbTag$Reventless.crossPartition)
|
|
143
|
-
}));
|
|
144
|
-
|
|
145
|
-
let unsubscribedCrossPartitionSchema = S.schema(s => ({
|
|
146
|
-
TAG: "StudentUnsubscribed",
|
|
147
|
-
courseId: s.m(DcbTag$Reventless.partition),
|
|
148
|
-
studentId: s.m(DcbTag$Reventless.crossPartition)
|
|
149
|
-
}));
|
|
150
|
-
|
|
151
|
-
let flaggedPartitionScopedSchema = S.schema(s => ({
|
|
152
|
-
TAG: "StudentFlagged",
|
|
153
|
-
studentId: s.m(DcbTag$Reventless.partition),
|
|
154
|
-
courseId: s.m(DcbTag$Reventless.string)
|
|
155
|
-
}));
|
|
156
|
-
|
|
157
|
-
globalThis.describe("DcbValidation:", () => {
|
|
158
|
-
globalThis.describe("validateProducedAndConsumed", () => {
|
|
159
|
-
globalThis.test("passes when all consumed events match produced events", () => {
|
|
160
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([
|
|
161
|
-
[
|
|
162
|
-
"AddItem",
|
|
163
|
-
producedASchema
|
|
164
|
-
],
|
|
165
|
-
[
|
|
166
|
-
"ArchiveItem",
|
|
167
|
-
producedBSchema
|
|
168
|
-
]
|
|
169
|
-
], [[
|
|
170
|
-
"ItemView",
|
|
171
|
-
consumedFullSchema
|
|
172
|
-
]]);
|
|
173
|
-
globalThis.expect(result).toEqual({
|
|
174
|
-
TAG: "Ok",
|
|
175
|
-
_0: undefined
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
globalThis.test("passes with partial field projection", () => {
|
|
179
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([[
|
|
180
|
-
"AddItem",
|
|
181
|
-
producedASchema
|
|
182
|
-
]], [[
|
|
183
|
-
"CheckExists",
|
|
184
|
-
consumedPartialSchema
|
|
185
|
-
]]);
|
|
186
|
-
globalThis.expect(result).toEqual({
|
|
187
|
-
TAG: "Ok",
|
|
188
|
-
_0: undefined
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
globalThis.test("passes with payload-less consumed events", () => {
|
|
192
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([
|
|
193
|
-
[
|
|
194
|
-
"AddItem",
|
|
195
|
-
producedASchema
|
|
196
|
-
],
|
|
197
|
-
[
|
|
198
|
-
"ArchiveItem",
|
|
199
|
-
producedBSchema
|
|
200
|
-
]
|
|
201
|
-
], [[
|
|
202
|
-
"CheckExists",
|
|
203
|
-
consumedPayloadLessSchema
|
|
204
|
-
]]);
|
|
205
|
-
globalThis.expect(result).toEqual({
|
|
206
|
-
TAG: "Ok",
|
|
207
|
-
_0: undefined
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
globalThis.test("passes when multiple producers have identical shapes and tags", () => {
|
|
211
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([
|
|
212
|
-
[
|
|
213
|
-
"AddItem",
|
|
214
|
-
producedASchema
|
|
215
|
-
],
|
|
216
|
-
[
|
|
217
|
-
"CloneItem",
|
|
218
|
-
producedADuplicateSchema
|
|
219
|
-
]
|
|
220
|
-
], []);
|
|
221
|
-
globalThis.expect(result).toEqual({
|
|
222
|
-
TAG: "Ok",
|
|
223
|
-
_0: undefined
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
globalThis.test("fails when consumed event has no producer", () => {
|
|
227
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([[
|
|
228
|
-
"AddItem",
|
|
229
|
-
producedASchema
|
|
230
|
-
]], [[
|
|
231
|
-
"DeleteHandler",
|
|
232
|
-
consumedDanglingSchema
|
|
233
|
-
]]);
|
|
234
|
-
if (result.TAG === "Ok") {
|
|
235
|
-
return JestGlobals.fail("Expected validation error");
|
|
236
|
-
}
|
|
237
|
-
let errors = result._0;
|
|
238
|
-
globalThis.expect(errors.length).toBe(1);
|
|
239
|
-
let err = errors[0];
|
|
240
|
-
globalThis.expect(err.sliceName).toBe("DeleteHandler");
|
|
241
|
-
globalThis.expect(err.message.includes("ItemDeleted")).toBe(true);
|
|
242
|
-
globalThis.expect(err.message.includes("no slice produces it")).toBe(true);
|
|
243
|
-
});
|
|
244
|
-
globalThis.test("fails when consumed event references field not in produced shape", () => {
|
|
245
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([[
|
|
246
|
-
"AddItem",
|
|
247
|
-
producedASchema
|
|
248
|
-
]], [[
|
|
249
|
-
"RatingView",
|
|
250
|
-
consumedBadFieldSchema
|
|
251
|
-
]]);
|
|
252
|
-
if (result.TAG === "Ok") {
|
|
253
|
-
return JestGlobals.fail("Expected validation error");
|
|
254
|
-
}
|
|
255
|
-
let errors = result._0;
|
|
256
|
-
globalThis.expect(errors.length).toBe(1);
|
|
257
|
-
let err = errors[0];
|
|
258
|
-
globalThis.expect(err.sliceName).toBe("RatingView");
|
|
259
|
-
globalThis.expect(err.message.includes("rating")).toBe(true);
|
|
260
|
-
globalThis.expect(err.message.includes("no field")).toBe(true);
|
|
261
|
-
});
|
|
262
|
-
globalThis.test("fails when consumed field type mismatches produced field type", () => {
|
|
263
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([[
|
|
264
|
-
"AddItem",
|
|
265
|
-
producedASchema
|
|
266
|
-
]], [[
|
|
267
|
-
"BadTypeView",
|
|
268
|
-
consumedBadTypeSchema
|
|
269
|
-
]]);
|
|
270
|
-
if (result.TAG === "Ok") {
|
|
271
|
-
return JestGlobals.fail("Expected validation error");
|
|
272
|
-
}
|
|
273
|
-
let errors = result._0;
|
|
274
|
-
globalThis.expect(errors.length).toBe(1);
|
|
275
|
-
let err = errors[0];
|
|
276
|
-
globalThis.expect(err.sliceName).toBe("BadTypeView");
|
|
277
|
-
globalThis.expect(err.message.includes("name")).toBe(true);
|
|
278
|
-
globalThis.expect(err.message.includes("float")).toBe(true);
|
|
279
|
-
globalThis.expect(err.message.includes("string")).toBe(true);
|
|
280
|
-
});
|
|
281
|
-
globalThis.test("fails when producers have different fields for same TAG", () => {
|
|
282
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([
|
|
283
|
-
[
|
|
284
|
-
"AddItem",
|
|
285
|
-
producedASchema
|
|
286
|
-
],
|
|
287
|
-
[
|
|
288
|
-
"ImportItem",
|
|
289
|
-
producedAMismatchFieldsSchema
|
|
290
|
-
]
|
|
291
|
-
], []);
|
|
292
|
-
if (result.TAG === "Ok") {
|
|
293
|
-
return JestGlobals.fail("Expected validation error");
|
|
294
|
-
}
|
|
295
|
-
let errors = result._0;
|
|
296
|
-
globalThis.expect(errors.length).toBeGreaterThanOrEqual(1);
|
|
297
|
-
let err = errors[0];
|
|
298
|
-
globalThis.expect(err.message.includes("AddItem")).toBe(true);
|
|
299
|
-
globalThis.expect(err.message.includes("ImportItem")).toBe(true);
|
|
300
|
-
globalThis.expect(err.message.includes("name")).toBe(true);
|
|
301
|
-
});
|
|
302
|
-
globalThis.test("fails when producers have different tag annotations for same TAG", () => {
|
|
303
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([
|
|
304
|
-
[
|
|
305
|
-
"AddItem",
|
|
306
|
-
producedASchema
|
|
307
|
-
],
|
|
308
|
-
[
|
|
309
|
-
"UntaggerItem",
|
|
310
|
-
producedAMismatchTagsSchema
|
|
311
|
-
]
|
|
312
|
-
], []);
|
|
313
|
-
if (result.TAG === "Ok") {
|
|
314
|
-
return JestGlobals.fail("Expected validation error");
|
|
315
|
-
}
|
|
316
|
-
let errors = result._0;
|
|
317
|
-
globalThis.expect(errors.length).toBeGreaterThanOrEqual(1);
|
|
318
|
-
let hasTagError = errors.some(err => err.message.includes("tag annotations"));
|
|
319
|
-
globalThis.expect(hasTagError).toBe(true);
|
|
320
|
-
});
|
|
321
|
-
globalThis.test("fails when producers have different field types for same TAG", () => {
|
|
322
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([
|
|
323
|
-
[
|
|
324
|
-
"AddItem",
|
|
325
|
-
producedASchema
|
|
326
|
-
],
|
|
327
|
-
[
|
|
328
|
-
"BadTypeItem",
|
|
329
|
-
producedAMismatchTypeSchema
|
|
330
|
-
]
|
|
331
|
-
], []);
|
|
332
|
-
if (result.TAG === "Ok") {
|
|
333
|
-
return JestGlobals.fail("Expected validation error");
|
|
334
|
-
}
|
|
335
|
-
let errors = result._0;
|
|
336
|
-
globalThis.expect(errors.length).toBeGreaterThanOrEqual(1);
|
|
337
|
-
let err = errors[0];
|
|
338
|
-
globalThis.expect(err.message.includes("name")).toBe(true);
|
|
339
|
-
globalThis.expect(err.message.includes("string")).toBe(true);
|
|
340
|
-
globalThis.expect(err.message.includes("float")).toBe(true);
|
|
341
|
-
});
|
|
342
|
-
globalThis.test("passes with empty produced and consumed", () => {
|
|
343
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([], []);
|
|
344
|
-
globalThis.expect(result).toEqual({
|
|
345
|
-
TAG: "Ok",
|
|
346
|
-
_0: undefined
|
|
347
|
-
});
|
|
348
|
-
});
|
|
349
|
-
globalThis.test("collects multiple errors at once", () => {
|
|
350
|
-
let result = DcbValidation$Reventless.validateProducedAndConsumed([[
|
|
351
|
-
"AddItem",
|
|
352
|
-
producedASchema
|
|
353
|
-
]], [
|
|
354
|
-
[
|
|
355
|
-
"DeleteHandler",
|
|
356
|
-
consumedDanglingSchema
|
|
357
|
-
],
|
|
358
|
-
[
|
|
359
|
-
"BadTypeView",
|
|
360
|
-
consumedBadTypeSchema
|
|
361
|
-
]
|
|
362
|
-
]);
|
|
363
|
-
if (result.TAG === "Ok") {
|
|
364
|
-
return JestGlobals.fail("Expected validation errors");
|
|
365
|
-
}
|
|
366
|
-
globalThis.expect(result._0.length).toBeGreaterThanOrEqual(2);
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
globalThis.describe("validateCompositeReads (Issue 5)", () => {
|
|
370
|
-
globalThis.test("warns when a composite read's consumed type carries an extra tag", () => {
|
|
371
|
-
let warnings = DcbValidation$Reventless.validateCompositeReads([[
|
|
372
|
-
"RecordDemand",
|
|
373
|
-
recordDemandCommandSchema,
|
|
374
|
-
demandConsumedSchema
|
|
375
|
-
]], producedTagKeys);
|
|
376
|
-
globalThis.expect(warnings.length).toBe(1);
|
|
377
|
-
let w = warnings[0];
|
|
378
|
-
globalThis.expect(w.sliceName).toBe("RecordDemand");
|
|
379
|
-
globalThis.expect(w.message.includes("ProductDemandRevoked")).toBe(true);
|
|
380
|
-
globalThis.expect(w.message.includes("customerId")).toBe(true);
|
|
381
|
-
});
|
|
382
|
-
globalThis.test("does not warn for an exact-match consumed type", () => {
|
|
383
|
-
let warnings = DcbValidation$Reventless.validateCompositeReads([[
|
|
384
|
-
"RecordDemand",
|
|
385
|
-
recordDemandCommandSchema,
|
|
386
|
-
demandConsumedSchema
|
|
387
|
-
]], producedTagKeys);
|
|
388
|
-
globalThis.expect(warnings.some(w => w.message.includes("ProductDemandRecorded"))).toBe(false);
|
|
389
|
-
});
|
|
390
|
-
globalThis.test("ignores single-tag commands (partition read, not composite)", () => {
|
|
391
|
-
let warnings = DcbValidation$Reventless.validateCompositeReads([[
|
|
392
|
-
"TouchDemand",
|
|
393
|
-
touchDemandCommandSchema,
|
|
394
|
-
demandConsumedSchema
|
|
395
|
-
]], producedTagKeys);
|
|
396
|
-
globalThis.expect(warnings).toEqual([]);
|
|
397
|
-
});
|
|
398
|
-
globalThis.test("ignores tagged-array commands (per-element OR, not composite)", () => {
|
|
399
|
-
let warnings = DcbValidation$Reventless.validateCompositeReads([[
|
|
400
|
-
"PlaceOrder",
|
|
401
|
-
placeOrderCommandSchema,
|
|
402
|
-
demandConsumedSchema
|
|
403
|
-
]], producedTagKeys);
|
|
404
|
-
globalThis.expect(warnings).toEqual([]);
|
|
405
|
-
});
|
|
406
|
-
globalThis.test("no warnings when nothing reads compositely", () => {
|
|
407
|
-
globalThis.expect(DcbValidation$Reventless.validateCompositeReads([], producedTagKeys)).toEqual([]);
|
|
408
|
-
});
|
|
409
|
-
});
|
|
410
|
-
globalThis.describe("validateCrossPartitionScope (Issue 13)", () => {
|
|
411
|
-
globalThis.test("no warning when every carrier of a key agrees on cross-partition scope", () => {
|
|
412
|
-
let warnings = DcbValidation$Reventless.validateCrossPartitionScope([
|
|
413
|
-
[
|
|
414
|
-
"Subscribe",
|
|
415
|
-
subscribedCrossPartitionSchema
|
|
416
|
-
],
|
|
417
|
-
[
|
|
418
|
-
"Unsubscribe",
|
|
419
|
-
unsubscribedCrossPartitionSchema
|
|
420
|
-
]
|
|
421
|
-
]);
|
|
422
|
-
globalThis.expect(warnings).toEqual([]);
|
|
423
|
-
});
|
|
424
|
-
globalThis.test("warns when one producer leaves a cross-partition key partition-scoped", () => {
|
|
425
|
-
let warnings = DcbValidation$Reventless.validateCrossPartitionScope([
|
|
426
|
-
[
|
|
427
|
-
"Subscribe",
|
|
428
|
-
subscribedCrossPartitionSchema
|
|
429
|
-
],
|
|
430
|
-
[
|
|
431
|
-
"Flag",
|
|
432
|
-
flaggedPartitionScopedSchema
|
|
433
|
-
]
|
|
434
|
-
]);
|
|
435
|
-
globalThis.expect(warnings.length).toBe(1);
|
|
436
|
-
let w = warnings[0];
|
|
437
|
-
globalThis.expect(w.sliceName).toBe("Flag");
|
|
438
|
-
globalThis.expect(w.message.includes("studentId")).toBe(true);
|
|
439
|
-
});
|
|
440
|
-
globalThis.test("no warning when no key is cross-partition anywhere", () => {
|
|
441
|
-
globalThis.expect(DcbValidation$Reventless.validateCrossPartitionScope([[
|
|
442
|
-
"Flag",
|
|
443
|
-
flaggedPartitionScopedSchema
|
|
444
|
-
]])).toEqual([]);
|
|
445
|
-
});
|
|
446
|
-
});
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
let validate = DcbValidation$Reventless.validateProducedAndConsumed;
|
|
450
|
-
|
|
451
|
-
export {
|
|
452
|
-
producedASchema,
|
|
453
|
-
producedBSchema,
|
|
454
|
-
producedADuplicateSchema,
|
|
455
|
-
producedAMismatchFieldsSchema,
|
|
456
|
-
producedAMismatchTagsSchema,
|
|
457
|
-
producedAMismatchTypeSchema,
|
|
458
|
-
consumedFullSchema,
|
|
459
|
-
consumedPartialSchema,
|
|
460
|
-
consumedPayloadLessSchema,
|
|
461
|
-
consumedDanglingSchema,
|
|
462
|
-
consumedBadFieldSchema,
|
|
463
|
-
consumedBadTypeSchema,
|
|
464
|
-
recordDemandCommandSchema,
|
|
465
|
-
touchDemandCommandSchema,
|
|
466
|
-
placeOrderCommandSchema,
|
|
467
|
-
demandConsumedSchema,
|
|
468
|
-
demandProducedSchema,
|
|
469
|
-
validate,
|
|
470
|
-
u,
|
|
471
|
-
producedTagKeys,
|
|
472
|
-
subscribedCrossPartitionSchema,
|
|
473
|
-
unsubscribedCrossPartitionSchema,
|
|
474
|
-
flaggedPartitionScopedSchema,
|
|
475
|
-
}
|
|
476
|
-
/* producedASchema Not a pure module */
|
|
@@ -1,196 +0,0 @@
|
|
|
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 Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
-
import * as Effect from "effect/Effect";
|
|
7
|
-
import * as Stream from "effect/Stream";
|
|
8
|
-
|
|
9
|
-
S.enableJson();
|
|
10
|
-
|
|
11
|
-
let eventSchema = S.union([
|
|
12
|
-
S.schema(s => ({
|
|
13
|
-
TAG: "ItemCreated",
|
|
14
|
-
name: s.m(S.string)
|
|
15
|
-
})),
|
|
16
|
-
S.schema(s => ({
|
|
17
|
-
TAG: "ItemDeleted",
|
|
18
|
-
id: s.m(S.string)
|
|
19
|
-
}))
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
let ItemEventLogSpec = {
|
|
23
|
-
Id: undefined,
|
|
24
|
-
name: "TestItemEventLog",
|
|
25
|
-
eventSchema: eventSchema
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
let storedEvents = {
|
|
29
|
-
contents: {}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
let storedSnapshots = {
|
|
33
|
-
contents: {}
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
let failNextAppend = {
|
|
37
|
-
contents: false
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
let failNextAppendsWithTransient = {
|
|
41
|
-
contents: 0
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
let appendCallCount = {
|
|
45
|
-
contents: 0
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
async function mockStorage_append(_seqNr, id, jsons) {
|
|
49
|
-
appendCallCount.contents = appendCallCount.contents + 1 | 0;
|
|
50
|
-
if (failNextAppend.contents) {
|
|
51
|
-
failNextAppend.contents = false;
|
|
52
|
-
return {
|
|
53
|
-
TAG: "Error",
|
|
54
|
-
_0: {
|
|
55
|
-
TAG: "StorageFailure",
|
|
56
|
-
_0: "mock storage failure"
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
if (failNextAppendsWithTransient.contents > 0) {
|
|
61
|
-
failNextAppendsWithTransient.contents = failNextAppendsWithTransient.contents - 1 | 0;
|
|
62
|
-
return {
|
|
63
|
-
TAG: "Error",
|
|
64
|
-
_0: {
|
|
65
|
-
TAG: "StorageFailure",
|
|
66
|
-
_0: "ThrottlingException: Rate exceeded"
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
let existing = Stdlib_Option.getOr(storedEvents.contents[id], []);
|
|
71
|
-
storedEvents.contents[id] = existing.concat(jsons);
|
|
72
|
-
return {
|
|
73
|
-
TAG: "Ok",
|
|
74
|
-
_0: undefined
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function mockStorage_replay(id) {
|
|
79
|
-
return Stdlib_Option.getOr(storedEvents.contents[id], []);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function mockStorage_replayStream(id, fromSeqOpt) {
|
|
83
|
-
let fromSeq = fromSeqOpt !== undefined ? fromSeqOpt : 0;
|
|
84
|
-
return Stream.fromIterable(Stdlib_Option.getOr(storedEvents.contents[id], []).slice(fromSeq));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function mockStorage_appendStream(_startingSeqNr, id, stream) {
|
|
88
|
-
return Stream.runForEach(stream, json => Effect.sync(() => {
|
|
89
|
-
let existing = Stdlib_Option.getOr(storedEvents.contents[id], []);
|
|
90
|
-
storedEvents.contents[id] = existing.concat([json]);
|
|
91
|
-
}));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async function mockStorage_latestSnapshot(id) {
|
|
95
|
-
return {
|
|
96
|
-
TAG: "Ok",
|
|
97
|
-
_0: storedSnapshots.contents[id]
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function mockStorage_writeSnapshot(id, snap) {
|
|
102
|
-
storedSnapshots.contents[id] = snap;
|
|
103
|
-
return {
|
|
104
|
-
TAG: "Ok",
|
|
105
|
-
_0: undefined
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
let mockStorage = {
|
|
110
|
-
append: mockStorage_append,
|
|
111
|
-
replay: mockStorage_replay,
|
|
112
|
-
replayStream: mockStorage_replayStream,
|
|
113
|
-
appendStream: mockStorage_appendStream,
|
|
114
|
-
latestSnapshot: mockStorage_latestSnapshot,
|
|
115
|
-
writeSnapshot: mockStorage_writeSnapshot
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
let capturedPublishes = {
|
|
119
|
-
contents: []
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
function make(param, param$1, param$2) {
|
|
123
|
-
return 0;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
let MockEventTopic_Spec = {
|
|
127
|
-
Id: Id$Reventless.StringPure,
|
|
128
|
-
name: "TestItem",
|
|
129
|
-
eventSchema: eventSchema
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
let MockEventTopic = {
|
|
133
|
-
Spec: MockEventTopic_Spec,
|
|
134
|
-
make: make
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
async function mockEventTopicOps_publish(events) {
|
|
138
|
-
capturedPublishes.contents = capturedPublishes.contents.concat(events);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async function mockEventTopicOps_publishJson(_service, _meta, _json) {
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function mockEventTopicOps_publishJsonStream(_stream) {
|
|
146
|
-
return Effect.succeed();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
let mockEventTopicOps = {
|
|
150
|
-
publish: mockEventTopicOps_publish,
|
|
151
|
-
publishJson: mockEventTopicOps_publishJson,
|
|
152
|
-
publishJsonStream: mockEventTopicOps_publishJsonStream
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
let testMeta = {
|
|
156
|
-
service: "test",
|
|
157
|
-
time: "2024-01-01T00:00:00.000Z",
|
|
158
|
-
ip: "127.0.0.1",
|
|
159
|
-
user: "testuser",
|
|
160
|
-
msgId: "msg-001",
|
|
161
|
-
correlationId: "corr-001"
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
function makeEvent$p(id, event) {
|
|
165
|
-
return {
|
|
166
|
-
id: id,
|
|
167
|
-
meta: testMeta,
|
|
168
|
-
event: event
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function reset() {
|
|
173
|
-
storedEvents.contents = {};
|
|
174
|
-
storedSnapshots.contents = {};
|
|
175
|
-
failNextAppend.contents = false;
|
|
176
|
-
failNextAppendsWithTransient.contents = 0;
|
|
177
|
-
appendCallCount.contents = 0;
|
|
178
|
-
capturedPublishes.contents = [];
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export {
|
|
182
|
-
ItemEventLogSpec,
|
|
183
|
-
storedEvents,
|
|
184
|
-
storedSnapshots,
|
|
185
|
-
failNextAppend,
|
|
186
|
-
failNextAppendsWithTransient,
|
|
187
|
-
appendCallCount,
|
|
188
|
-
mockStorage,
|
|
189
|
-
capturedPublishes,
|
|
190
|
-
MockEventTopic,
|
|
191
|
-
mockEventTopicOps,
|
|
192
|
-
testMeta,
|
|
193
|
-
makeEvent$p,
|
|
194
|
-
reset,
|
|
195
|
-
}
|
|
196
|
-
/* Not a pure module */
|