@reventlessdev/reventless-core 3.0.0-alpha.300 → 3.0.0-alpha.302
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 +32 -0
- package/README.md +3 -3
- package/package.json +10 -10
- package/src/{Behavior.res → Decision.res} +1 -1
- package/src/Message.res +1 -1
- package/src/ResourceAttribution.res +8 -8
- package/src/adapter/Auth/Auth_ActiveRole.res +1 -1
- package/src/adapter/Auth/Auth_RefusalVocabulary.res +1 -1
- package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder.res +2 -2
- package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +10 -5
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +2 -2
- package/src/adapter/Runtime/EventCollectorRuntime_Builder.res +1 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +8 -3
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder.res +1 -1
- package/src/adapter/Runtime/PluginRuntime_Builder.res +3 -3
- package/src/adapter/Runtime/Runtime.res +10 -9
- package/src/adapter/Runtime/TaskRuntime_Builder.res +1 -1
- package/src/adapter/RuntimeExtension/RuntimeExtension.res +3 -3
- package/src/admin/Platform_Admin_Structure.res +3 -3
- package/src/admin/Platform_Admin_Structure.res.mjs +1 -1
- package/src/admin/Platform_BakedManifest.res +8 -8
- package/src/admin/Platform_BakedManifest.res.mjs +2 -2
- package/src/admin/Platform_ComponentDefinitionsApi.res +12 -12
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +11 -11
- package/src/admin/Platform_PluginStructuresApi.res +7 -7
- package/src/admin/Platform_PluginStructuresApi.res.mjs +4 -4
- package/src/admin/UiFragmentRegistry/StateChange/{UiFragmentRegistry_Behavior.res → UiFragmentRegistry_Decision.res} +1 -1
- package/src/admin/UiFragmentRegistry/StateChange/{UiFragmentRegistry_Behavior.res.mjs → UiFragmentRegistry_Decision.res.mjs} +1 -1
- package/src/admin/UiFragmentRegistry/StateView/UiFragments.res.mjs +1 -4
- package/src/components/Aggregate/Aggregate_Builder.res +2 -2
- package/src/components/Aggregate/Aggregate_Builder.res.mjs +2 -2
- package/src/components/Aggregate/Aggregate_Callback.res +17 -17
- package/src/components/Aggregate/Aggregate_Callback.res.mjs +11 -11
- package/src/components/Api/ApiNoApiHelpers.res +1 -1
- package/src/components/Api/GraphQL_FragmentGenerator.res +1 -1
- package/src/components/Api/SchemaType.res +1 -1
- package/src/components/Api/SuryToJsonSchema.res +1 -1
- package/src/components/CommandGenerator/CommandGenerator.res +1 -1
- package/src/components/CommandGenerator/CommandGenerator_Adapter.res +6 -1
- package/src/components/CommandTopic/CommandTopic.res +2 -2
- package/src/components/CommandTopic/CommandTopic_Adapter.res +1 -1
- package/src/components/CommandTopic/CommandTopic_Helpers.res +4 -4
- package/src/components/EventCollector/EventCollector.res +1 -1
- package/src/components/EventCollector/EventCollector_Adapter.res +1 -1
- package/src/components/EventLog/EventLog_Operations.res +2 -2
- package/src/components/Heartbeat/Heartbeat.res +1 -1
- package/src/components/ReadModel/ReadModel.res +1 -1
- package/src/components/StateChangeSlice/StateChangeSlice.res +1 -1
- package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +3 -3
- package/src/components/StateChangeSlice/StateChangeSlice_Builder.res.mjs +3 -3
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +9 -9
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +4 -4
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +2 -2
- package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +1 -1
- package/src/components/StateViewSlice/StateViewSlice_Callback.res +2 -2
- package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +1 -1
- package/src/components/Task/Task_Adapter.res +1 -1
- package/src/components/Task/Task_Builder.res +1 -1
- package/src/plugin/component/Plugin_Builder.res +7 -7
- package/src/plugin/component/Plugin_Builder.res.mjs +3 -3
- package/src/plugin/component/Plugin_BuiltHook.res +1 -1
- package/src/plugin/component/Plugin_Structure.res +19 -19
- package/src/plugin/component/Plugin_Structure.res.mjs +8 -8
- package/src/plugin/lifecycle/{PluginBehavior.res → PluginDecision.res} +4 -4
- package/src/plugin/lifecycle/{PluginBehavior.res.mjs → PluginDecision.res.mjs} +1 -1
- package/tests/admin/AdminApiSchemaDriftTest.res +8 -8
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +54 -54
- package/tests/admin/Platform_Admin_StructureTest.res +10 -10
- package/tests/admin/Platform_Admin_StructureTest.res.mjs +5 -5
- package/tests/admin/Platform_BakedManifestTest.res +7 -7
- package/tests/admin/Platform_BakedManifestTest.res.mjs +9 -9
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +11 -11
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +5 -5
- package/tests/admin/Platform_PluginStructuresApiTest.res +3 -3
- package/tests/aggregate/AggregateCacheTest.res +4 -4
- package/tests/aggregate/AggregateCacheTest.res.mjs +2 -2
- package/tests/aggregate/AggregateCallbackTest.res +2 -2
- package/tests/aggregate/AggregateCallbackTest.res.mjs +1 -1
- package/tests/aggregate/AggregateConflictTest.res +4 -4
- package/tests/aggregate/AggregateConflictTest.res.mjs +2 -2
- package/tests/aggregate/AggregateFixtures.res +5 -5
- package/tests/aggregate/AggregateFixtures.res.mjs +2 -2
- package/tests/aggregate/AggregateRejectionTest.res +1 -1
- package/tests/aggregate/AggregateSnapshotTest.res +7 -7
- package/tests/aggregate/AggregateSnapshotTest.res.mjs +4 -4
- package/tests/api/PsInternalFieldsReadModel.res +1 -1
- package/tests/api/TaggedUnionSchemaTest.res +1 -1
- package/tests/commandgenerator/CommandGeneratorCallbackTest.res +1 -1
- package/tests/commandgenerator/CommandGeneratorFixtures.res +2 -2
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +2 -2
- package/tests/commandgenerator/OwnerActingTest.res +4 -4
- package/tests/commandgenerator/OwnerActingTest.res.mjs +4 -4
- package/tests/commandgenerator/OwnerStampingTest.res +1 -1
- package/tests/commandtopic/CommandOutcomeHookTest.res +2 -2
- package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +3 -3
- package/tests/dcb/DcbStateChangeSliceTest.res +5 -5
- package/tests/dcb/DcbStateChangeSliceTest.res.mjs +5 -5
- package/tests/message/MessageTest.res +1 -1
- package/tests/plugin/ManifestVisibilityTest.res +2 -2
- package/tests/plugin/PluginStructureAccessTest.res +1 -1
- package/tests/plugin/PluginStructureAccessTest.res.mjs +4 -4
- package/tests/plugin/PluginStructureTest.res +24 -24
- package/tests/plugin/PluginStructureTest.res.mjs +27 -27
- package/tests/plugin/StateView/PsAnnotatedView.res +1 -1
- package/tests/plugin/StateView/PsAnnotatedView.res.mjs +1 -4
- package/tests/plugin/StateView/PsAvailableProductsView.res.mjs +1 -4
- package/tests/plugin/StateView/PsCategoriesView.res.mjs +1 -4
- package/tests/plugin/StateView/PsCustomersView.res.mjs +1 -4
- package/tests/plugin/StateView/PsGatedView.res.mjs +1 -4
- package/tests/plugin/StateView/PsOrdersView.res.mjs +1 -4
- package/tests/plugin/StateView/PsShipmentsView.res.mjs +1 -4
- package/tests/projection/LifecycleTrailTest.res +1 -1
- /package/src/{Behavior.res.mjs → Decision.res.mjs} +0 -0
|
@@ -100,82 +100,82 @@ let err = {
|
|
|
100
100
|
references: err_references
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
let
|
|
103
|
+
let writeSide_commands = [cmd];
|
|
104
104
|
|
|
105
|
-
let
|
|
105
|
+
let writeSide_producedEventTypes = ["ProductAdded"];
|
|
106
106
|
|
|
107
|
-
let
|
|
107
|
+
let writeSide_consumedEventTypes = [];
|
|
108
108
|
|
|
109
|
-
let
|
|
109
|
+
let writeSide_linkedViews = ["Products"];
|
|
110
110
|
|
|
111
|
-
let
|
|
111
|
+
let writeSide_consistencyRead = "Products";
|
|
112
112
|
|
|
113
|
-
let
|
|
113
|
+
let writeSide_events = [evt];
|
|
114
114
|
|
|
115
|
-
let
|
|
115
|
+
let writeSide_errors = [err];
|
|
116
116
|
|
|
117
|
-
let
|
|
117
|
+
let writeSide_chapter = "Catalogue";
|
|
118
118
|
|
|
119
|
-
let
|
|
119
|
+
let writeSide = {
|
|
120
120
|
name: "Product",
|
|
121
|
-
commands:
|
|
122
|
-
producedEventTypes:
|
|
123
|
-
consumedEventTypes:
|
|
124
|
-
linkedViews:
|
|
125
|
-
consistencyRead:
|
|
126
|
-
events:
|
|
127
|
-
errors:
|
|
128
|
-
chapter:
|
|
121
|
+
commands: writeSide_commands,
|
|
122
|
+
producedEventTypes: writeSide_producedEventTypes,
|
|
123
|
+
consumedEventTypes: writeSide_consumedEventTypes,
|
|
124
|
+
linkedViews: writeSide_linkedViews,
|
|
125
|
+
consistencyRead: writeSide_consistencyRead,
|
|
126
|
+
events: writeSide_events,
|
|
127
|
+
errors: writeSide_errors,
|
|
128
|
+
chapter: writeSide_chapter
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
let
|
|
131
|
+
let readSide_consumedEventTypes = ["ProductAdded"];
|
|
132
132
|
|
|
133
|
-
let
|
|
133
|
+
let readSide_linkedWriteSide = ["Product"];
|
|
134
134
|
|
|
135
|
-
let
|
|
135
|
+
let readSide_searchableFields = ["displayName"];
|
|
136
136
|
|
|
137
|
-
let
|
|
137
|
+
let readSide_labelFieldSource = "annotation";
|
|
138
138
|
|
|
139
|
-
let
|
|
139
|
+
let readSide_lifecycleField = "lifecycle";
|
|
140
140
|
|
|
141
|
-
let
|
|
141
|
+
let readSide_ownerField = "ownerId";
|
|
142
142
|
|
|
143
|
-
let
|
|
143
|
+
let readSide_retiredField = "archived";
|
|
144
144
|
|
|
145
|
-
let
|
|
145
|
+
let readSide_retiredValues = ["Archived"];
|
|
146
146
|
|
|
147
|
-
let
|
|
147
|
+
let readSide_namedWhenRetired = true;
|
|
148
148
|
|
|
149
|
-
let
|
|
149
|
+
let readSide_chapter = "Catalogue";
|
|
150
150
|
|
|
151
|
-
let
|
|
151
|
+
let readSide_singleQueryField = "Catalog_Product";
|
|
152
152
|
|
|
153
|
-
let
|
|
153
|
+
let readSide_idField = "productId";
|
|
154
154
|
|
|
155
|
-
let
|
|
155
|
+
let readSide_idFieldSource = "convention";
|
|
156
156
|
|
|
157
|
-
let
|
|
157
|
+
let readSide_requiredAccess = ["catalog.read"];
|
|
158
158
|
|
|
159
|
-
let
|
|
159
|
+
let readSide = {
|
|
160
160
|
name: "Products",
|
|
161
161
|
queryField: "Catalog_Products",
|
|
162
162
|
schema: "{}",
|
|
163
|
-
consumedEventTypes:
|
|
164
|
-
linkedWriteSide:
|
|
163
|
+
consumedEventTypes: readSide_consumedEventTypes,
|
|
164
|
+
linkedWriteSide: readSide_linkedWriteSide,
|
|
165
165
|
labelField: "displayName",
|
|
166
|
-
searchableFields:
|
|
167
|
-
labelFieldSource:
|
|
168
|
-
lifecycleField:
|
|
169
|
-
ownerField:
|
|
170
|
-
retiredField:
|
|
171
|
-
retiredValues:
|
|
172
|
-
namedWhenRetired:
|
|
166
|
+
searchableFields: readSide_searchableFields,
|
|
167
|
+
labelFieldSource: readSide_labelFieldSource,
|
|
168
|
+
lifecycleField: readSide_lifecycleField,
|
|
169
|
+
ownerField: readSide_ownerField,
|
|
170
|
+
retiredField: readSide_retiredField,
|
|
171
|
+
retiredValues: readSide_retiredValues,
|
|
172
|
+
namedWhenRetired: readSide_namedWhenRetired,
|
|
173
173
|
visibility: undefined,
|
|
174
|
-
chapter:
|
|
175
|
-
singleQueryField:
|
|
176
|
-
idField:
|
|
177
|
-
idFieldSource:
|
|
178
|
-
requiredAccess:
|
|
174
|
+
chapter: readSide_chapter,
|
|
175
|
+
singleQueryField: readSide_singleQueryField,
|
|
176
|
+
idField: readSide_idField,
|
|
177
|
+
idFieldSource: readSide_idFieldSource,
|
|
178
|
+
requiredAccess: readSide_requiredAccess
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
let automation_consumedEventTypes = ["StockLow"];
|
|
@@ -293,13 +293,13 @@ let capabilityDecl = {
|
|
|
293
293
|
component: "GeocodeAddress"
|
|
294
294
|
};
|
|
295
295
|
|
|
296
|
-
let structure_readModels = [
|
|
296
|
+
let structure_readModels = [readSide];
|
|
297
297
|
|
|
298
298
|
let structure_stateViewSlices = [];
|
|
299
299
|
|
|
300
300
|
let structure_stateChangeSlices = [];
|
|
301
301
|
|
|
302
|
-
let structure_aggregates = [
|
|
302
|
+
let structure_aggregates = [writeSide];
|
|
303
303
|
|
|
304
304
|
let structure_automationSlices = [automation];
|
|
305
305
|
|
|
@@ -414,16 +414,16 @@ let guards = [
|
|
|
414
414
|
{
|
|
415
415
|
gqlType: "Platform_WriteSideDef",
|
|
416
416
|
sdlTypes: Platform_ComponentDefinitionsApi$ReventlessCore.sdlTypes,
|
|
417
|
-
recordFields: schemaKeys(Plugin$Reventless.
|
|
418
|
-
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.
|
|
417
|
+
recordFields: schemaKeys(Plugin$Reventless.writeSideDefSchema),
|
|
418
|
+
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.encodeWriteSideDef(writeSide)),
|
|
419
419
|
wireOnly: [],
|
|
420
420
|
recordOnly: []
|
|
421
421
|
},
|
|
422
422
|
{
|
|
423
423
|
gqlType: "Platform_ReadSideDef",
|
|
424
424
|
sdlTypes: Platform_ComponentDefinitionsApi$ReventlessCore.sdlTypes,
|
|
425
|
-
recordFields: schemaKeys(Plugin$Reventless.
|
|
426
|
-
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.
|
|
425
|
+
recordFields: schemaKeys(Plugin$Reventless.readSideDefSchema),
|
|
426
|
+
wireFields: jsonKeys(Platform_ComponentDefinitionsApi$ReventlessCore.encodeReadSideDef(readSide)),
|
|
427
427
|
wireOnly: [],
|
|
428
428
|
recordOnly: ["requiredRoles"]
|
|
429
429
|
},
|
|
@@ -604,8 +604,8 @@ export {
|
|
|
604
604
|
cmd,
|
|
605
605
|
evt,
|
|
606
606
|
err,
|
|
607
|
-
|
|
608
|
-
|
|
607
|
+
writeSide,
|
|
608
|
+
readSide,
|
|
609
609
|
automation,
|
|
610
610
|
outbound,
|
|
611
611
|
inbound,
|
|
@@ -27,7 +27,7 @@ let commandNamed = (name: string): commandDef =>
|
|
|
27
27
|
let activate = () => commandNamed("Activate")
|
|
28
28
|
|
|
29
29
|
describe("the Plugins read model declares its lifecycle", () => {
|
|
30
|
-
let rm:
|
|
30
|
+
let rm: readSideDef = Platform_Admin_Structure.pluginReadModel()
|
|
31
31
|
|
|
32
32
|
testSync("names the field commands branch on", () =>
|
|
33
33
|
expect(rm.lifecycleField)->toEqual(Some("status"))
|
|
@@ -44,14 +44,14 @@ describe("the Plugins read model declares its lifecycle", () => {
|
|
|
44
44
|
})
|
|
45
45
|
|
|
46
46
|
testSync("is served on the encoded def under the new key", () => {
|
|
47
|
-
let json = rm->Platform_ComponentDefinitionsApi.
|
|
47
|
+
let json = rm->Platform_ComponentDefinitionsApi.encodeReadSideDef->JSON.stringify
|
|
48
48
|
expect(json->String.includes(`"lifecycleField":"status"`))->toEqual(true)
|
|
49
49
|
})
|
|
50
50
|
|
|
51
51
|
testSync("and never under the old one", () =>
|
|
52
52
|
expect(
|
|
53
53
|
rm
|
|
54
|
-
->Platform_ComponentDefinitionsApi.
|
|
54
|
+
->Platform_ComponentDefinitionsApi.encodeReadSideDef
|
|
55
55
|
->JSON.stringify
|
|
56
56
|
->String.includes(`"statusField"`),
|
|
57
57
|
)->toEqual(false)
|
|
@@ -73,10 +73,10 @@ describe("the admin structure's declared transitions are checked", () => {
|
|
|
73
73
|
d
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
let raises =
|
|
76
|
+
let raises = writeSides =>
|
|
77
77
|
switch Plugin_Structure.checkDeclaredTransitions(
|
|
78
78
|
~pluginName="Platform",
|
|
79
|
-
~
|
|
79
|
+
~writeSides,
|
|
80
80
|
~lifecycleStatesByView=statesByView(),
|
|
81
81
|
) {
|
|
82
82
|
| () => false
|
|
@@ -95,7 +95,7 @@ describe("the admin structure's declared transitions are checked", () => {
|
|
|
95
95
|
|
|
96
96
|
// A check that cannot fail is indistinguishable from one that is not running.
|
|
97
97
|
testSync("and a state the view does not declare is caught", () => {
|
|
98
|
-
let bogus: Reventless.Plugin.
|
|
98
|
+
let bogus: Reventless.Plugin.writeSideDef = {
|
|
99
99
|
...Platform_Admin_Structure.pluginAggregate,
|
|
100
100
|
commands: [
|
|
101
101
|
{
|
|
@@ -193,7 +193,7 @@ describe("the internal commands declare the edges they move rows along", () => {
|
|
|
193
193
|
testSync("and no state is left unreachable", () =>
|
|
194
194
|
expect(
|
|
195
195
|
Plugin_Structure.lifecycleTopologyFindings(
|
|
196
|
-
~
|
|
196
|
+
~writeSides=[Platform_Admin_Structure.pluginAggregate],
|
|
197
197
|
~lifecycleStatesByView=statesByView(),
|
|
198
198
|
),
|
|
199
199
|
)->toEqual([])
|
|
@@ -239,14 +239,14 @@ describe("the Plugins view publishes the rule the server enforces", () => {
|
|
|
239
239
|
})
|
|
240
240
|
})
|
|
241
241
|
|
|
242
|
-
// The `
|
|
242
|
+
// The `readSideDef` is derived from the spec, not hand-written. The analysis
|
|
243
243
|
// that preceded this expected the admin's naming to be bespoke and it is not:
|
|
244
244
|
// `Api_Naming.queryFieldNamesForReadModel` returns byte-identical names, because
|
|
245
245
|
// `singularize` already handles the plural-spec-name / singular-type shape that
|
|
246
246
|
// looked special. Asserted rather than assumed — the whole case for deriving
|
|
247
247
|
// rests on the generic helpers reaching the same answers.
|
|
248
|
-
describe("the Plugins
|
|
249
|
-
let rm:
|
|
248
|
+
describe("the Plugins readSideDef is what the generic helpers produce", () => {
|
|
249
|
+
let rm: readSideDef = Platform_Admin_Structure.pluginReadModel()
|
|
250
250
|
|
|
251
251
|
testSync("the field names are the generic ones", () =>
|
|
252
252
|
expect((rm.queryField, rm.singleQueryField))->toEqual((
|
|
@@ -28,11 +28,11 @@ globalThis.describe("the Plugins read model declares its lifecycle", () => {
|
|
|
28
28
|
globalThis.expect(sdlDeclaresStatus).toEqual(true);
|
|
29
29
|
});
|
|
30
30
|
globalThis.test("is served on the encoded def under the new key", () => {
|
|
31
|
-
let json = JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.
|
|
31
|
+
let json = JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.encodeReadSideDef(rm));
|
|
32
32
|
globalThis.expect(json.includes(`"lifecycleField":"status"`)).toEqual(true);
|
|
33
33
|
});
|
|
34
34
|
globalThis.test("and never under the old one", () => {
|
|
35
|
-
globalThis.expect(JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.
|
|
35
|
+
globalThis.expect(JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.encodeReadSideDef(rm)).includes(`"statusField"`)).toEqual(false);
|
|
36
36
|
});
|
|
37
37
|
});
|
|
38
38
|
|
|
@@ -45,9 +45,9 @@ globalThis.describe("the admin structure's declared transitions are checked", ()
|
|
|
45
45
|
});
|
|
46
46
|
return d;
|
|
47
47
|
};
|
|
48
|
-
let raises =
|
|
48
|
+
let raises = writeSides => {
|
|
49
49
|
try {
|
|
50
|
-
Plugin_Structure$ReventlessCore.checkDeclaredTransitions("Platform",
|
|
50
|
+
Plugin_Structure$ReventlessCore.checkDeclaredTransitions("Platform", writeSides, statesByView());
|
|
51
51
|
return false;
|
|
52
52
|
} catch (exn) {
|
|
53
53
|
return true;
|
|
@@ -187,7 +187,7 @@ globalThis.describe("the Plugins view publishes the rule the server enforces", (
|
|
|
187
187
|
});
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
-
globalThis.describe("the Plugins
|
|
190
|
+
globalThis.describe("the Plugins readSideDef is what the generic helpers produce", () => {
|
|
191
191
|
let rm = Platform_Admin_Structure$ReventlessCore.pluginReadModel();
|
|
192
192
|
globalThis.test("the field names are the generic ones", () => {
|
|
193
193
|
globalThis.expect([
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
open JestGlobals
|
|
7
7
|
open Reventless.Plugin
|
|
8
8
|
|
|
9
|
-
let
|
|
9
|
+
let readSide = (~name, ~visibility=?, ~ownerField=?, ()): readSideDef => {
|
|
10
10
|
name,
|
|
11
11
|
queryField: `Ordering_${name}`,
|
|
12
12
|
schema: "{}",
|
|
@@ -42,7 +42,7 @@ let command = (~name, ~references=[], ~ownerField=?, ()): commandDef => {
|
|
|
42
42
|
ownerField,
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
let
|
|
45
|
+
let writeSide = (~name, ~commands): writeSideDef => {
|
|
46
46
|
name,
|
|
47
47
|
commands,
|
|
48
48
|
linkedViews: [],
|
|
@@ -58,13 +58,13 @@ let writable = (~name, ~commands): writableDef => {
|
|
|
58
58
|
// denormalised product mirror a command @refs, one end-user command and one
|
|
59
59
|
// operator command.
|
|
60
60
|
let structure: pluginStructure = {
|
|
61
|
-
readModels: [
|
|
61
|
+
readModels: [readSide(~name="Customers", ())],
|
|
62
62
|
stateViewSlices: [
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
readSide(~name="Orders", ~ownerField="customerId", ()),
|
|
64
|
+
readSide(~name="AvailableProducts", ~visibility="Internal", ()),
|
|
65
65
|
],
|
|
66
66
|
stateChangeSlices: [
|
|
67
|
-
|
|
67
|
+
writeSide(
|
|
68
68
|
~name="PlaceOrder",
|
|
69
69
|
~commands=[
|
|
70
70
|
command(
|
|
@@ -75,7 +75,7 @@ let structure: pluginStructure = {
|
|
|
75
75
|
),
|
|
76
76
|
],
|
|
77
77
|
),
|
|
78
|
-
|
|
78
|
+
writeSide(~name="ImportOrders", ~commands=[command(~name="ImportOrders", ())]),
|
|
79
79
|
],
|
|
80
80
|
aggregates: [],
|
|
81
81
|
automationSlices: [],
|
|
@@ -8,7 +8,7 @@ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js
|
|
|
8
8
|
import * as Platform_BakedManifest$ReventlessCore from "../../src/admin/Platform_BakedManifest.res.mjs";
|
|
9
9
|
import * as Platform_ComponentDefinitionsApi$ReventlessCore from "../../src/admin/Platform_ComponentDefinitionsApi.res.mjs";
|
|
10
10
|
|
|
11
|
-
function
|
|
11
|
+
function readSide(name, visibility, ownerField, param) {
|
|
12
12
|
return {
|
|
13
13
|
name: name,
|
|
14
14
|
queryField: `Ordering_` + name,
|
|
@@ -49,7 +49,7 @@ function command(name, referencesOpt, ownerField, param) {
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function
|
|
52
|
+
function writeSide(name, commands) {
|
|
53
53
|
return {
|
|
54
54
|
name: name,
|
|
55
55
|
commands: commands,
|
|
@@ -63,20 +63,20 @@ function writable(name, commands) {
|
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
let structure_readModels = [
|
|
66
|
+
let structure_readModels = [readSide("Customers", undefined, undefined, undefined)];
|
|
67
67
|
|
|
68
68
|
let structure_stateViewSlices = [
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
readSide("Orders", undefined, "customerId", undefined),
|
|
70
|
+
readSide("AvailableProducts", "Internal", undefined, undefined)
|
|
71
71
|
];
|
|
72
72
|
|
|
73
73
|
let structure_stateChangeSlices = [
|
|
74
|
-
|
|
74
|
+
writeSide("PlaceOrder", [command("PlaceOrder", [{
|
|
75
75
|
fieldName: "productIds",
|
|
76
76
|
entity: "AvailableProducts",
|
|
77
77
|
plugin: undefined
|
|
78
78
|
}], "customerId", undefined)]),
|
|
79
|
-
|
|
79
|
+
writeSide("ImportOrders", [command("ImportOrders", undefined, undefined, undefined)])
|
|
80
80
|
];
|
|
81
81
|
|
|
82
82
|
let structure_aggregates = [];
|
|
@@ -296,9 +296,9 @@ globalThis.describe("curate", () => {
|
|
|
296
296
|
});
|
|
297
297
|
|
|
298
298
|
export {
|
|
299
|
-
|
|
299
|
+
readSide,
|
|
300
300
|
command,
|
|
301
|
-
|
|
301
|
+
writeSide,
|
|
302
302
|
structure,
|
|
303
303
|
structures,
|
|
304
304
|
bake,
|
|
@@ -19,7 +19,7 @@ let cmd: commandDef = {
|
|
|
19
19
|
ownerField: None,
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
let qbl:
|
|
22
|
+
let qbl: readSideDef = {
|
|
23
23
|
name: "Products",
|
|
24
24
|
queryField: "Catalog_Products",
|
|
25
25
|
schema: "{}",
|
|
@@ -41,7 +41,7 @@ let qbl: queryableDef = {
|
|
|
41
41
|
namedWhenRetired: None,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
let wbl:
|
|
44
|
+
let wbl: writeSideDef = {
|
|
45
45
|
name: "Product",
|
|
46
46
|
commands: [cmd],
|
|
47
47
|
linkedViews: ["Products"],
|
|
@@ -152,7 +152,7 @@ describe("encodePluginStructureEntry", () => {
|
|
|
152
152
|
expect(json->String.includes("\"plugin\":\"Catalog\""))->toEqual(true)
|
|
153
153
|
)
|
|
154
154
|
|
|
155
|
-
testSync("includes the
|
|
155
|
+
testSync("includes the readSideDef name", () =>
|
|
156
156
|
expect(json->String.includes("\"name\":\"Products\""))->toEqual(true)
|
|
157
157
|
)
|
|
158
158
|
|
|
@@ -177,12 +177,12 @@ describe("encodePluginStructureEntry", () => {
|
|
|
177
177
|
)
|
|
178
178
|
|
|
179
179
|
// Phase 6.3: write-side emitted-event field schemas.
|
|
180
|
-
testSync("encodes
|
|
180
|
+
testSync("encodes writeSideDef events", () =>
|
|
181
181
|
expect(json->String.includes("\"events\":[{\"name\":\"ProductAdded\""))->toEqual(true)
|
|
182
182
|
)
|
|
183
183
|
|
|
184
184
|
// The refusals a caller has to handle travel beside the facts it can observe.
|
|
185
|
-
testSync("encodes
|
|
185
|
+
testSync("encodes writeSideDef errors", () =>
|
|
186
186
|
expect(json->String.includes("\"errors\":[{\"name\":\"ProductAlreadyExists\""))->toEqual(true)
|
|
187
187
|
)
|
|
188
188
|
|
|
@@ -258,7 +258,7 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
|
|
|
258
258
|
// Internal ReadModels / StateViewSlices are carried in pluginStructure for developer
|
|
259
259
|
// tooling but must not surface in the UI definitions the deployed AutoUI builds its
|
|
260
260
|
// menu / pages from — see Plugin_Structure.res / Visibility.res.
|
|
261
|
-
let internalQbl:
|
|
261
|
+
let internalQbl: readSideDef = {
|
|
262
262
|
name: "AvailableProducts",
|
|
263
263
|
queryField: "Ordering_AvailableProducts",
|
|
264
264
|
schema: "{}",
|
|
@@ -281,7 +281,7 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
|
|
|
281
281
|
}
|
|
282
282
|
// A distinct name per source array: the complement has to be fed by both, and
|
|
283
283
|
// reusing one def would hide a version that only walks `readModels`.
|
|
284
|
-
let internalSlice:
|
|
284
|
+
let internalSlice: readSideDef = {
|
|
285
285
|
...internalQbl,
|
|
286
286
|
name: "PendingShipments",
|
|
287
287
|
queryField: "Ordering_PendingShipments",
|
|
@@ -314,12 +314,12 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
|
|
|
314
314
|
->Option.flatMap(JSON.Decode.string)
|
|
315
315
|
)
|
|
316
316
|
|
|
317
|
-
testSync("excludes an Internal
|
|
317
|
+
testSync("excludes an Internal readSideDef from the encoded read-side", () => {
|
|
318
318
|
expect(mixedEntry->namesAt("readModels"))->toEqual(["Products"])
|
|
319
319
|
expect(mixedEntry->namesAt("stateViewSlices"))->toEqual([])
|
|
320
320
|
})
|
|
321
321
|
|
|
322
|
-
testSync("keeps a Public
|
|
322
|
+
testSync("keeps a Public readSideDef", () =>
|
|
323
323
|
expect(mixedEntry->namesAt("readModels")->Array.includes("Products"))->toEqual(true)
|
|
324
324
|
)
|
|
325
325
|
|
|
@@ -364,7 +364,7 @@ describe("allowedStates + lifecycleField populated", () => {
|
|
|
364
364
|
ownerField: None,
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
let qblWithStatus:
|
|
367
|
+
let qblWithStatus: readSideDef = {
|
|
368
368
|
name: "Plugin",
|
|
369
369
|
queryField: "Platform_Plugins",
|
|
370
370
|
schema: "{}",
|
|
@@ -386,7 +386,7 @@ describe("allowedStates + lifecycleField populated", () => {
|
|
|
386
386
|
namedWhenRetired: None,
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
let wblWithStates:
|
|
389
|
+
let wblWithStates: writeSideDef = {
|
|
390
390
|
name: "Plugin",
|
|
391
391
|
commands: [cmdWithStates],
|
|
392
392
|
linkedViews: ["Plugin"],
|
|
@@ -197,7 +197,7 @@ globalThis.describe("encodePluginStructureEntry", () => {
|
|
|
197
197
|
globalThis.test("encodes Some plugin reference as its inner string", () => {
|
|
198
198
|
globalThis.expect(json.includes("\"plugin\":\"Catalog\"")).toEqual(true);
|
|
199
199
|
});
|
|
200
|
-
globalThis.test("includes the
|
|
200
|
+
globalThis.test("includes the readSideDef name", () => {
|
|
201
201
|
globalThis.expect(json.includes("\"name\":\"Products\"")).toEqual(true);
|
|
202
202
|
});
|
|
203
203
|
globalThis.test("includes the automation slice name", () => {
|
|
@@ -215,10 +215,10 @@ globalThis.describe("encodePluginStructureEntry", () => {
|
|
|
215
215
|
globalThis.test("encodes None lifecycleField as null", () => {
|
|
216
216
|
globalThis.expect(json.includes("\"lifecycleField\":null")).toEqual(true);
|
|
217
217
|
});
|
|
218
|
-
globalThis.test("encodes
|
|
218
|
+
globalThis.test("encodes writeSideDef events", () => {
|
|
219
219
|
globalThis.expect(json.includes("\"events\":[{\"name\":\"ProductAdded\"")).toEqual(true);
|
|
220
220
|
});
|
|
221
|
-
globalThis.test("encodes
|
|
221
|
+
globalThis.test("encodes writeSideDef errors", () => {
|
|
222
222
|
globalThis.expect(json.includes("\"errors\":[{\"name\":\"ProductAlreadyExists\"")).toEqual(true);
|
|
223
223
|
});
|
|
224
224
|
globalThis.test("declares Platform_ErrorDef and the errors field in the shared write-side SDL", () => {
|
|
@@ -342,11 +342,11 @@ globalThis.describe("visibility filtering (deployed AutoUI hides Internal)", ()
|
|
|
342
342
|
};
|
|
343
343
|
let mixedEntry = Platform_ComponentDefinitionsApi$ReventlessCore.encodePluginStructureEntry("Ordering", undefined, mixed);
|
|
344
344
|
let namesAt = (entry, key) => Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(entry), o => o[key]), Stdlib_JSON.Decode.array), []), c => Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(c), o => o["name"]), Stdlib_JSON.Decode.string));
|
|
345
|
-
globalThis.test("excludes an Internal
|
|
345
|
+
globalThis.test("excludes an Internal readSideDef from the encoded read-side", () => {
|
|
346
346
|
globalThis.expect(namesAt(mixedEntry, "readModels")).toEqual(["Products"]);
|
|
347
347
|
globalThis.expect(namesAt(mixedEntry, "stateViewSlices")).toEqual([]);
|
|
348
348
|
});
|
|
349
|
-
globalThis.test("keeps a Public
|
|
349
|
+
globalThis.test("keeps a Public readSideDef", () => {
|
|
350
350
|
globalThis.expect(namesAt(mixedEntry, "readModels").includes("Products")).toEqual(true);
|
|
351
351
|
});
|
|
352
352
|
globalThis.test("carries what the filter removed on internalQueryables", () => {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
open JestGlobals
|
|
8
8
|
open Reventless.Plugin
|
|
9
9
|
|
|
10
|
-
let publicRm:
|
|
10
|
+
let publicRm: readSideDef = {
|
|
11
11
|
name: "Products",
|
|
12
12
|
queryField: "Catalog_Products",
|
|
13
13
|
schema: "{}",
|
|
@@ -30,7 +30,7 @@ let publicRm: queryableDef = {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// The component `Platform_ComponentDefinitions` drops and this query must keep.
|
|
33
|
-
let internalRm:
|
|
33
|
+
let internalRm: readSideDef = {
|
|
34
34
|
...publicRm,
|
|
35
35
|
name: "ProductAudit",
|
|
36
36
|
queryField: "Catalog_ProductAudit",
|
|
@@ -138,7 +138,7 @@ describe("Platform_PluginStructures entry", () => {
|
|
|
138
138
|
)->toEqual(true)
|
|
139
139
|
)
|
|
140
140
|
|
|
141
|
-
// Both read-side queries share `
|
|
141
|
+
// Both read-side queries share `encodeReadSideDef`, so this asserts the singular
|
|
142
142
|
// name is not a ComponentDefinitions-only field: a developer tool building a detail
|
|
143
143
|
// query reads it from here.
|
|
144
144
|
testSync("encodes the singular query field beside the list one", () =>
|
|
@@ -33,14 +33,14 @@ module AggSpec = {
|
|
|
33
33
|
let moduleUrl: string = %raw(`import.meta.url`)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
module
|
|
36
|
+
module TestDecision = {
|
|
37
37
|
module Spec = AggSpec
|
|
38
38
|
type state = {names: array<string>}
|
|
39
39
|
|
|
40
40
|
let initialState = {names: []}
|
|
41
41
|
|
|
42
|
-
// Hand-written
|
|
43
|
-
//
|
|
42
|
+
// Hand-written decision (no @@reventless.decision PPX) — satisfy the
|
|
43
|
+
// Decision.T snapshot field manually.
|
|
44
44
|
let snapshot = None
|
|
45
45
|
|
|
46
46
|
let moduleUrl: string = %raw(`import.meta.url`)
|
|
@@ -176,7 +176,7 @@ module TestOps = {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
module TestHandler = Aggregate_Callback.Make(AggSpec,
|
|
179
|
+
module TestHandler = Aggregate_Callback.Make(AggSpec, TestDecision, TestOps)
|
|
180
180
|
|
|
181
181
|
let makeTopicItem = (reference, command): CommandTopic.topicItem<
|
|
182
182
|
Message.command'<string, AggSpec.command>,
|
|
@@ -98,7 +98,7 @@ function decide(state, command) {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
let
|
|
101
|
+
let TestDecision = {
|
|
102
102
|
Spec: undefined,
|
|
103
103
|
initialState: initialState,
|
|
104
104
|
snapshot: undefined,
|
|
@@ -430,7 +430,7 @@ let OuterEventLog;
|
|
|
430
430
|
|
|
431
431
|
export {
|
|
432
432
|
AggSpec,
|
|
433
|
-
|
|
433
|
+
TestDecision,
|
|
434
434
|
testMeta,
|
|
435
435
|
makeMockEL,
|
|
436
436
|
mock,
|
|
@@ -40,11 +40,11 @@ describe("Aggregate_Callback.handleCommands:", () => {
|
|
|
40
40
|
)
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
describe("
|
|
43
|
+
describe("decision returns no events", () => {
|
|
44
44
|
testPromise(
|
|
45
45
|
"Rename on new aggregate returns Ok with no event stored",
|
|
46
46
|
async () => {
|
|
47
|
-
// Rename on empty history:
|
|
47
|
+
// Rename on empty history: Decision.decide(NotCreated, Rename) returns Error(NotFound)
|
|
48
48
|
let results = await Stream.fromIterable([
|
|
49
49
|
makeTopicItem("ref-1", AggSpec.Rename({newName: "Gadget"})),
|
|
50
50
|
])
|
|
@@ -50,7 +50,7 @@ globalThis.describe("Aggregate_Callback.handleCommands:", () => {
|
|
|
50
50
|
]);
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
|
-
globalThis.describe("
|
|
53
|
+
globalThis.describe("decision returns no events", () => {
|
|
54
54
|
globalThis.test("Rename on new aggregate returns Ok with no event stored", async () => {
|
|
55
55
|
let results = await Effect.runPromise(AggregateFixtures$ReventlessCore.TestHandler.handleCommands(Stream.fromIterable([AggregateFixtures$ReventlessCore.makeTopicItem(undefined, "ref-1", {
|
|
56
56
|
TAG: "Rename",
|
|
@@ -19,14 +19,14 @@ module AggSpec = {
|
|
|
19
19
|
let moduleUrl: string = %raw(`import.meta.url`)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
module
|
|
22
|
+
module TestDecision = {
|
|
23
23
|
module Spec = AggSpec
|
|
24
24
|
type state = {name: string}
|
|
25
25
|
|
|
26
26
|
let initialState = {name: ""}
|
|
27
27
|
|
|
28
|
-
// Hand-written
|
|
29
|
-
//
|
|
28
|
+
// Hand-written decision (no @@reventless.decision PPX) — satisfy the
|
|
29
|
+
// Decision.T snapshot field manually.
|
|
30
30
|
let snapshot = None
|
|
31
31
|
|
|
32
32
|
let moduleUrl: string = %raw(`import.meta.url`)
|
|
@@ -151,7 +151,7 @@ module TestOps = {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
module TestHandler = Aggregate_Callback.Make(AggSpec,
|
|
154
|
+
module TestHandler = Aggregate_Callback.Make(AggSpec, TestDecision, TestOps)
|
|
155
155
|
|
|
156
156
|
let testMeta: Message.meta = {
|
|
157
157
|
service: "ConflictTestAggregate",
|
|
@@ -66,7 +66,7 @@ function decide(_state, command) {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
let
|
|
69
|
+
let TestDecision = {
|
|
70
70
|
Spec: undefined,
|
|
71
71
|
initialState: initialState,
|
|
72
72
|
snapshot: undefined,
|
|
@@ -384,7 +384,7 @@ let OuterEventLog;
|
|
|
384
384
|
|
|
385
385
|
export {
|
|
386
386
|
AggSpec,
|
|
387
|
-
|
|
387
|
+
TestDecision,
|
|
388
388
|
makeMockEL,
|
|
389
389
|
mock,
|
|
390
390
|
OuterEventLog,
|