@reventlessdev/reventless-core 3.0.0-alpha.250 → 3.0.0-alpha.252
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 +40 -0
- package/package.json +7 -7
- package/src/admin/Platform_Admin_Structure.res +4 -1
- package/src/admin/Platform_Admin_Structure.res.mjs +4 -2
- package/src/admin/Platform_BakedManifest.res.mjs +3 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res +31 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +29 -1
- package/src/admin/Platform_PluginStructuresApi.res +80 -8
- package/src/admin/Platform_PluginStructuresApi.res.mjs +76 -2
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +8 -0
- package/src/components/Api/ApiNoApiHelpers.res +37 -3
- package/src/components/Api/ApiNoApiHelpers.res.mjs +29 -2
- package/src/components/AutomationSlice/AutomationSlice_Callback.res +4 -4
- package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +3 -3
- package/src/plugin/api/PluginBaseFragment.res +3 -3
- package/src/plugin/component/Plugin_Structure.res +787 -384
- package/src/plugin/component/Plugin_Structure.res.mjs +430 -20
- package/src/plugin/connect/PluginConnectExtension_Mapping.res +3 -6
- package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +14 -2
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res +0 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +63 -3
- package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +22 -3
- package/src/plugin/lifecycle/PluginBehavior.res +11 -11
- package/src/plugin/lifecycle/PluginBehavior.res.mjs +11 -11
- package/src/plugin/lifecycle/PluginSpec.res +11 -3
- package/src/plugin/lifecycle/PluginSpec.res.mjs +11 -3
- package/tests/admin/AdminApiSchemaDriftTest.res +486 -0
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +619 -0
- package/tests/admin/Platform_Admin_StructureTest.res +8 -3
- package/tests/admin/Platform_Admin_StructureTest.res.mjs +8 -2
- package/tests/admin/Platform_BakedManifestTest.res +2 -0
- package/tests/admin/Platform_BakedManifestTest.res.mjs +3 -1
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +10 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +30 -8
- package/tests/admin/Platform_PluginStructuresApiTest.res +28 -1
- package/tests/admin/Platform_PluginStructuresApiTest.res.mjs +27 -5
- package/tests/aggregate/AggregateCacheTest.res.mjs +15 -3
- package/tests/aggregate/AggregateConflictTest.res.mjs +15 -3
- package/tests/aggregate/AggregateFixtures.res.mjs +15 -3
- package/tests/aggregate/AggregateSnapshotTest.res.mjs +21 -5
- package/tests/api/ApiNoApiTest.res +46 -0
- package/tests/api/ApiNoApiTest.res.mjs +49 -1
- package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +27 -3
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +12 -2
- package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +2 -0
- package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +12 -2
- package/tests/dcb/DcbFixtures.res.mjs +8 -0
- package/tests/dcb/DcbStateChangeSliceTest.res.mjs +18 -0
- package/tests/eventmapper/EventMapperFixtures.res.mjs +15 -3
- package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +9 -1
- package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +9 -1
- package/tests/message/MessageTest.res +2 -0
- package/tests/message/MessageTest.res.mjs +3 -1
- package/tests/plugin/PluginStructureAccessTest.res.mjs +2 -0
- package/tests/plugin/PluginStructureTest.res +294 -1
- package/tests/plugin/PluginStructureTest.res.mjs +373 -3
- package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res +59 -0
- package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs +115 -0
- package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +8 -0
- package/tests/plugin/pluginDefinitionRequiredScalars.txt +26 -0
- package/tests/util/CommandPublisherTest.res.mjs +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,46 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.252 (2026-09-01)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **api:** [@no](https://github.com/no)Api was lost when a command variant was spliced into another type ([00403fb](https://github.com/ReventlessDev/reventless-core/commit/00403fb4b8873a68a69558829e598339a5012833))
|
|
11
|
+
* **automation:** a mapping is handed the envelope's id ([9ee482c](https://github.com/ReventlessDev/reventless-core/commit/9ee482c5ad0aae09efd1259eeb7f39b781867b91))
|
|
12
|
+
* **capabilities:** a plugin's geocoding need was declared nowhere and failed silently ([67917dd](https://github.com/ReventlessDev/reventless-core/commit/67917dd504b43fa78b7c6a51644c9eae656b7f6b))
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **plugin:** refuse two DCB slices that declare one command name ([8c6ec39](https://github.com/ReventlessDev/reventless-core/commit/8c6ec39cb3c6768446f46d0fc6dc04c256e2e9d9))
|
|
16
|
+
* **plugin:** the admin lifecycle commands name their argument ([ea552ec](https://github.com/ReventlessDev/reventless-core/commit/ea552ec64e5db0b3dc465c0d9a80cac89627f727))
|
|
17
|
+
* **spec:** a command declares its lifecycle edge as a value ([40eee9f](https://github.com/ReventlessDev/reventless-core/commit/40eee9f7723dc05e418be680528f01967d074da4))
|
|
18
|
+
* **spec:** a graft leaves a trace the deployed plugin can read ([c08ff6c](https://github.com/ReventlessDev/reventless-core/commit/c08ff6c0f6177d58603e7ae1e5cec392d9bac16a))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 3.0.0-alpha.251 (2026-08-27)
|
|
22
|
+
|
|
23
|
+
* feat(spec)!: reflect the command direction across a port, both halves ([f2fe258](https://github.com/ReventlessDev/reventless-core/commit/f2fe258d195b74f4a61488edee305665341020ea))
|
|
24
|
+
* feat(spec)!: drop the plugin protocol's reconnect event, which nothing published ([7549db6](https://github.com/ReventlessDev/reventless-core/commit/7549db6aac6ad3f94dbb8d72dac4b4e783756ad1))
|
|
25
|
+
* feat(spec)!: read the port's translation table off the mapping's arms ([956348a](https://github.com/ReventlessDev/reventless-core/commit/956348a9fcb256cfff9db51809bdc27d73360e6c))
|
|
26
|
+
|
|
27
|
+
### BREAKING CHANGES
|
|
28
|
+
|
|
29
|
+
* `ExtensionPointMapping.Mapping` gains `acceptedCommands` and
|
|
30
|
+
`ExtensionMapping.Mapping` gains `issuedCommands`; both are derived, so a
|
|
31
|
+
mapping the ppx can read needs no source change, and one it cannot names itself
|
|
32
|
+
at compile time. Definitions persisted before the two new def fields must be
|
|
33
|
+
re-emitted before a consumer can read them as present — and until then they
|
|
34
|
+
decode as None, which means unknown, not "issues nothing".
|
|
35
|
+
* `PluginExtensionPointSpec.event` no longer declares
|
|
36
|
+
`PluginReconnected`. An extension matching on it was matching an event it could
|
|
37
|
+
never receive; drop the arm.
|
|
38
|
+
* `ExtensionPointMapping.Mapping` requires `publishedEvents` and
|
|
39
|
+
`ExtensionMapping.Mapping` requires `handledEvents`; the ppx injects both for
|
|
40
|
+
mappings it can read, so app code must build against the matching ppx. Plugin
|
|
41
|
+
definitions persisted before the new fields must be re-emitted before a consumer
|
|
42
|
+
reads them as present.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
6
46
|
# 3.0.0-alpha.250 (2026-08-23)
|
|
7
47
|
|
|
8
48
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.252",
|
|
4
4
|
"description": "Core package for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -28,22 +28,22 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"sury": "11.0.0-rc.2",
|
|
30
30
|
"uuid": "^13.0.0",
|
|
31
|
-
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
32
31
|
"@reventlessdev/rescript-fast-csv": "2.0.0-alpha.8",
|
|
32
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
33
33
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
34
34
|
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.14",
|
|
35
|
-
"@reventlessdev/rescript-node": "2.0.0-alpha.8",
|
|
36
35
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.19",
|
|
36
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.8",
|
|
37
37
|
"@reventlessdev/rescript-ssh2": "2.0.0-alpha.8",
|
|
38
38
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
39
|
-
"@reventlessdev/reventless-
|
|
40
|
-
"@reventlessdev/reventless-
|
|
41
|
-
"@reventlessdev/reventless-
|
|
39
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.153",
|
|
40
|
+
"@reventlessdev/reventless-interop": "3.0.0-alpha.34",
|
|
41
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.125"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"rescript": "12.3.0",
|
|
45
45
|
"sury-ppx": "11.0.0-rc.2",
|
|
46
|
-
"@reventlessdev/reventless-ppx": "1.0.0-alpha.
|
|
46
|
+
"@reventlessdev/reventless-ppx": "1.0.0-alpha.75"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"rescript": "12.3.0"
|
|
@@ -24,7 +24,7 @@ let commandSchema = PluginSpec.commandSchema->S.castToUnknown
|
|
|
24
24
|
// Every variant of `PluginSpec.command`, walked by the same `extractCommandDefs`
|
|
25
25
|
// an ordinary aggregate goes through. The hand-written alternative described the
|
|
26
26
|
// arguments with a local `{id}` schema while the generated SDL declared
|
|
27
|
-
// `Platform_Plugin_Activate(
|
|
27
|
+
// `Platform_Plugin_Activate(id: ID!, version: String!)`, so AutoUI built a mutation
|
|
28
28
|
// missing a required argument and every admin row action was rejected before it
|
|
29
29
|
// reached the aggregate. Deriving from `commandSchema` — the same schema the SDL
|
|
30
30
|
// is generated from — cannot reproduce that class of fault.
|
|
@@ -38,6 +38,7 @@ let pluginCommands: array<commandDef> = Plugin_Structure.extractCommandDefs(
|
|
|
38
38
|
~mutationFieldFor=variantName =>
|
|
39
39
|
Api_Naming.adminField(~name=PluginSpec.name ++ "_" ++ variantName),
|
|
40
40
|
~commandAuthorization=PluginSpec.commandAuthorization->Obj.magic,
|
|
41
|
+
~commandTransition=PluginSpec.commandTransition->Obj.magic,
|
|
41
42
|
commandSchema,
|
|
42
43
|
)
|
|
43
44
|
|
|
@@ -76,6 +77,8 @@ let structure: pluginStructure = {
|
|
|
76
77
|
extensionPoints: None,
|
|
77
78
|
requiredStores: None,
|
|
78
79
|
requiredStoreDeclarations: None,
|
|
80
|
+
requiredCapabilities: None,
|
|
81
|
+
traitDeclarations: None,
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
/** The definition the platform's own EventCollector ships as its
|
|
@@ -7,7 +7,7 @@ import * as PluginsReadModelSpec$ReventlessCore from "../plugin/lifecycle/Plugin
|
|
|
7
7
|
|
|
8
8
|
let pluginId = "Platform";
|
|
9
9
|
|
|
10
|
-
let pluginCommands = Plugin_Structure$ReventlessCore.extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.adminField(PluginSpec$ReventlessCore.name + "_" + variantName), PluginSpec$ReventlessCore.commandAuthorization, PluginSpec$ReventlessCore.commandSchema);
|
|
10
|
+
let pluginCommands = Plugin_Structure$ReventlessCore.extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.adminField(PluginSpec$ReventlessCore.name + "_" + variantName), PluginSpec$ReventlessCore.commandAuthorization, PluginSpec$ReventlessCore.commandTransition, PluginSpec$ReventlessCore.commandSchema);
|
|
11
11
|
|
|
12
12
|
let pluginAggregate_producedEventTypes = [];
|
|
13
13
|
|
|
@@ -60,7 +60,9 @@ let structure = {
|
|
|
60
60
|
extensions: structure_extensions,
|
|
61
61
|
extensionPoints: undefined,
|
|
62
62
|
requiredStores: undefined,
|
|
63
|
-
requiredStoreDeclarations: undefined
|
|
63
|
+
requiredStoreDeclarations: undefined,
|
|
64
|
+
requiredCapabilities: undefined,
|
|
65
|
+
traitDeclarations: undefined
|
|
64
66
|
};
|
|
65
67
|
|
|
66
68
|
let internalPluginDefinition = {
|
|
@@ -134,7 +134,9 @@ function curateStructure(pluginId, def, sel) {
|
|
|
134
134
|
extensions: def.extensions,
|
|
135
135
|
extensionPoints: def.extensionPoints,
|
|
136
136
|
requiredStores: def.requiredStores,
|
|
137
|
-
requiredStoreDeclarations: def.requiredStoreDeclarations
|
|
137
|
+
requiredStoreDeclarations: def.requiredStoreDeclarations,
|
|
138
|
+
requiredCapabilities: def.requiredCapabilities,
|
|
139
|
+
traitDeclarations: def.traitDeclarations
|
|
138
140
|
};
|
|
139
141
|
});
|
|
140
142
|
}
|
|
@@ -33,7 +33,11 @@ let sdlTypes: array<string> = [
|
|
|
33
33
|
`type Platform_AutomationSliceDef {\n name: String!\n consumedEventTypes: [String!]!\n producedCommandTypes: [String!]!\n targetName: String\n chapter: String\n}`,
|
|
34
34
|
`type Platform_OutboundTranslationSliceDef {\n name: String!\n consumedEventTypes: [String!]!\n inboundCommandTypes: [String!]!\n targetName: String\n externalSystem: String\n chapter: String\n}`,
|
|
35
35
|
`type Platform_InboundTranslationSliceDef {\n name: String!\n commandTypes: [String!]!\n targetName: String\n externalSystem: String\n chapter: String\n}`,
|
|
36
|
-
|
|
36
|
+
// The subscriber's half of the port's translation table — see `handledEventDef`.
|
|
37
|
+
`type Platform_HandledEventDef {\n name: String!\n toCommandTypes: [String!]!\n}`,
|
|
38
|
+
// Its command-direction mirror — see `issuedCommandDef`.
|
|
39
|
+
`type Platform_IssuedCommandDef {\n name: String!\n fromEventTypes: [String!]!\n}`,
|
|
40
|
+
`type Platform_ExtensionDef {\n name: String!\n delegateNames: [String!]!\n eventTypes: [String!]!\n commandTypes: [String!]!\n handledEvents: [Platform_HandledEventDef!]\n issuedCommands: [Platform_IssuedCommandDef!]\n}`,
|
|
37
41
|
// `internalQueryables` is the complement of the `readModels` / `stateViewSlices`
|
|
38
42
|
// filter, not an addition to either: it carries exactly the components the
|
|
39
43
|
// filter removed. A consumer enumerating surfaces reads the two filtered lists
|
|
@@ -208,6 +212,32 @@ let encodeExtensionDef = (e: extensionDef): JSON.t =>
|
|
|
208
212
|
("delegateNames", encodeStrings(e.delegateNames)),
|
|
209
213
|
("eventTypes", encodeStrings(e.eventTypes)),
|
|
210
214
|
("commandTypes", encodeStrings(e.commandTypes)),
|
|
215
|
+
(
|
|
216
|
+
"handledEvents",
|
|
217
|
+
e.handledEvents->Option.mapOr(JSON.Encode.null, handled =>
|
|
218
|
+
handled
|
|
219
|
+
->Array.map(h =>
|
|
220
|
+
Dict.fromArray([
|
|
221
|
+
("name", JSON.Encode.string(h.name)),
|
|
222
|
+
("toCommandTypes", encodeStrings(h.toCommandTypes)),
|
|
223
|
+
])->JSON.Encode.object
|
|
224
|
+
)
|
|
225
|
+
->JSON.Encode.array
|
|
226
|
+
),
|
|
227
|
+
),
|
|
228
|
+
(
|
|
229
|
+
"issuedCommands",
|
|
230
|
+
e.issuedCommands->Option.mapOr(JSON.Encode.null, issued =>
|
|
231
|
+
issued
|
|
232
|
+
->Array.map(i =>
|
|
233
|
+
Dict.fromArray([
|
|
234
|
+
("name", JSON.Encode.string(i.name)),
|
|
235
|
+
("fromEventTypes", encodeStrings(i.fromEventTypes)),
|
|
236
|
+
])->JSON.Encode.object
|
|
237
|
+
)
|
|
238
|
+
->JSON.Encode.array
|
|
239
|
+
),
|
|
240
|
+
),
|
|
211
241
|
])->JSON.Encode.object
|
|
212
242
|
|
|
213
243
|
// `derived` is curation, not structure: it says which of the pages a shell
|
|
@@ -14,7 +14,9 @@ let sdlTypes = [
|
|
|
14
14
|
`type Platform_AutomationSliceDef {\n name: String!\n consumedEventTypes: [String!]!\n producedCommandTypes: [String!]!\n targetName: String\n chapter: String\n}`,
|
|
15
15
|
`type Platform_OutboundTranslationSliceDef {\n name: String!\n consumedEventTypes: [String!]!\n inboundCommandTypes: [String!]!\n targetName: String\n externalSystem: String\n chapter: String\n}`,
|
|
16
16
|
`type Platform_InboundTranslationSliceDef {\n name: String!\n commandTypes: [String!]!\n targetName: String\n externalSystem: String\n chapter: String\n}`,
|
|
17
|
-
`type
|
|
17
|
+
`type Platform_HandledEventDef {\n name: String!\n toCommandTypes: [String!]!\n}`,
|
|
18
|
+
`type Platform_IssuedCommandDef {\n name: String!\n fromEventTypes: [String!]!\n}`,
|
|
19
|
+
`type Platform_ExtensionDef {\n name: String!\n delegateNames: [String!]!\n eventTypes: [String!]!\n commandTypes: [String!]!\n handledEvents: [Platform_HandledEventDef!]\n issuedCommands: [Platform_IssuedCommandDef!]\n}`,
|
|
18
20
|
`type Platform_ComponentDefinitionEntry {\n pluginId: String!\n readModels: [Platform_ReadSideDef!]!\n stateViewSlices: [Platform_ReadSideDef!]!\n internalQueryables: [Platform_ReadSideDef!]!\n stateChangeSlices: [Platform_WriteSideDef!]!\n aggregates: [Platform_WriteSideDef!]!\n automationSlices: [Platform_AutomationSliceDef!]!\n outboundTranslationSlices: [Platform_OutboundTranslationSliceDef!]!\n inboundTranslationSlices: [Platform_InboundTranslationSliceDef!]!\n extensions: [Platform_ExtensionDef!]!\n}`
|
|
19
21
|
];
|
|
20
22
|
|
|
@@ -347,6 +349,32 @@ function encodeExtensionDef(e) {
|
|
|
347
349
|
[
|
|
348
350
|
"commandTypes",
|
|
349
351
|
e.commandTypes.map(prim => prim)
|
|
352
|
+
],
|
|
353
|
+
[
|
|
354
|
+
"handledEvents",
|
|
355
|
+
Stdlib_Option.mapOr(e.handledEvents, null, handled => handled.map(h => Object.fromEntries([
|
|
356
|
+
[
|
|
357
|
+
"name",
|
|
358
|
+
h.name
|
|
359
|
+
],
|
|
360
|
+
[
|
|
361
|
+
"toCommandTypes",
|
|
362
|
+
h.toCommandTypes.map(prim => prim)
|
|
363
|
+
]
|
|
364
|
+
])))
|
|
365
|
+
],
|
|
366
|
+
[
|
|
367
|
+
"issuedCommands",
|
|
368
|
+
Stdlib_Option.mapOr(e.issuedCommands, null, issued => issued.map(i => Object.fromEntries([
|
|
369
|
+
[
|
|
370
|
+
"name",
|
|
371
|
+
i.name
|
|
372
|
+
],
|
|
373
|
+
[
|
|
374
|
+
"fromEventTypes",
|
|
375
|
+
i.fromEventTypes.map(prim => prim)
|
|
376
|
+
]
|
|
377
|
+
])))
|
|
350
378
|
]
|
|
351
379
|
]);
|
|
352
380
|
}
|
|
@@ -28,21 +28,43 @@
|
|
|
28
28
|
open Reventless.Plugin
|
|
29
29
|
|
|
30
30
|
let sdlTypes: array<string> = [
|
|
31
|
+
// The port's translation table — see `publishedEventDef`.
|
|
32
|
+
`type Platform_PublishedEventDef {\n name: String!\n fromEventTypes: [String!]!\n}`,
|
|
33
|
+
// Its command-direction mirror — see `acceptedCommandDef`.
|
|
34
|
+
`type Platform_AcceptedCommandDef {\n name: String!\n toCommandTypes: [String!]!\n}`,
|
|
31
35
|
// Producer side of an extension point. `commandTypes` is null for a
|
|
32
36
|
// notification-only (`command = unit`) extension point — see `extensionPointDef`.
|
|
33
|
-
`type Platform_ExtensionPointDef {\n name: String!\n delegateNames: [String!]!\n sourceEventTypes: [String!]!\n commandTypes: [String!]\n}`,
|
|
37
|
+
`type Platform_ExtensionPointDef {\n name: String!\n delegateNames: [String!]!\n sourceEventTypes: [String!]!\n commandTypes: [String!]\n publishedEvents: [Platform_PublishedEventDef!]\n acceptedCommands: [Platform_AcceptedCommandDef!]\n}`,
|
|
34
38
|
`type Platform_RequiredStoreDeclaration {\n store: String!\n component: String!\n field: String!\n annotation: String\n}`,
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
|
|
39
|
+
// The capability a component declares its translate reaches for. No `field`:
|
|
40
|
+
// unlike a store, this need is not expressible as an annotation on one.
|
|
41
|
+
`type Platform_RequiredCapabilityDeclaration {\n capability: String!\n component: String!\n}`,
|
|
42
|
+
// One graft's provenance. `posture` is a String rather than an enum for the
|
|
43
|
+
// reason the capability above is: a plugin built against a newer framework,
|
|
44
|
+
// naming a posture this schema has never heard of, still decodes.
|
|
45
|
+
//
|
|
46
|
+
// It records ORIGIN, never behaviour — a grafted file is the host's to edit
|
|
47
|
+
// afterwards — so a reader must not paint a declared graft as a verified one.
|
|
48
|
+
`type Platform_TraitDeclaration {\n trait: String!\n version: String!\n posture: String!\n component: String!\n}`,
|
|
49
|
+
// `extensionPoints` / `requiredStores` / `requiredStoreDeclarations` /
|
|
50
|
+
// `requiredCapabilities` / `traitDeclarations` are nullable lists, not `[T!]!`: all five are optional on
|
|
51
|
+
// `pluginStructure` so that plugin definitions persisted before the field existed
|
|
52
|
+
// still decode. A structure written by an older deploy sends null, and null is the
|
|
53
|
+
// honest answer — an empty list would claim the plugin has no extension points when
|
|
54
|
+
// the truth is that the deployment cannot say.
|
|
55
|
+
`type Platform_PluginStructureEntry {\n pluginId: String!\n readModels: [Platform_ReadSideDef!]!\n stateViewSlices: [Platform_ReadSideDef!]!\n stateChangeSlices: [Platform_WriteSideDef!]!\n aggregates: [Platform_WriteSideDef!]!\n automationSlices: [Platform_AutomationSliceDef!]!\n outboundTranslationSlices: [Platform_OutboundTranslationSliceDef!]!\n inboundTranslationSlices: [Platform_InboundTranslationSliceDef!]!\n extensions: [Platform_ExtensionDef!]!\n extensionPoints: [Platform_ExtensionPointDef!]\n requiredStores: [String!]\n requiredStoreDeclarations: [Platform_RequiredStoreDeclaration!]\n requiredCapabilities: [Platform_RequiredCapabilityDeclaration!]\n traitDeclarations: [Platform_TraitDeclaration!]\n}`,
|
|
42
56
|
]
|
|
43
57
|
|
|
44
58
|
let sdlQueryField: string = ` Platform_PluginStructures: [Platform_PluginStructureEntry!]!`
|
|
45
59
|
|
|
60
|
+
let encodeTraitDeclaration = (d: traitDeclaration): JSON.t =>
|
|
61
|
+
Dict.fromArray([
|
|
62
|
+
("trait", JSON.Encode.string(d.trait)),
|
|
63
|
+
("version", JSON.Encode.string(d.version)),
|
|
64
|
+
("posture", JSON.Encode.string(d.posture)),
|
|
65
|
+
("component", JSON.Encode.string(d.component)),
|
|
66
|
+
])->JSON.Encode.object
|
|
67
|
+
|
|
46
68
|
let encodeExtensionPointDef = (e: extensionPointDef): JSON.t =>
|
|
47
69
|
Dict.fromArray([
|
|
48
70
|
("name", JSON.Encode.string(e.name)),
|
|
@@ -52,6 +74,38 @@ let encodeExtensionPointDef = (e: extensionPointDef): JSON.t =>
|
|
|
52
74
|
"commandTypes",
|
|
53
75
|
e.commandTypes->Option.mapOr(JSON.Encode.null, Platform_ComponentDefinitionsApi.encodeStrings),
|
|
54
76
|
),
|
|
77
|
+
(
|
|
78
|
+
"publishedEvents",
|
|
79
|
+
e.publishedEvents->Option.mapOr(JSON.Encode.null, published =>
|
|
80
|
+
published
|
|
81
|
+
->Array.map(p =>
|
|
82
|
+
Dict.fromArray([
|
|
83
|
+
("name", JSON.Encode.string(p.name)),
|
|
84
|
+
(
|
|
85
|
+
"fromEventTypes",
|
|
86
|
+
Platform_ComponentDefinitionsApi.encodeStrings(p.fromEventTypes),
|
|
87
|
+
),
|
|
88
|
+
])->JSON.Encode.object
|
|
89
|
+
)
|
|
90
|
+
->JSON.Encode.array
|
|
91
|
+
),
|
|
92
|
+
),
|
|
93
|
+
(
|
|
94
|
+
"acceptedCommands",
|
|
95
|
+
e.acceptedCommands->Option.mapOr(JSON.Encode.null, accepted =>
|
|
96
|
+
accepted
|
|
97
|
+
->Array.map(a =>
|
|
98
|
+
Dict.fromArray([
|
|
99
|
+
("name", JSON.Encode.string(a.name)),
|
|
100
|
+
(
|
|
101
|
+
"toCommandTypes",
|
|
102
|
+
Platform_ComponentDefinitionsApi.encodeStrings(a.toCommandTypes),
|
|
103
|
+
),
|
|
104
|
+
])->JSON.Encode.object
|
|
105
|
+
)
|
|
106
|
+
->JSON.Encode.array
|
|
107
|
+
),
|
|
108
|
+
),
|
|
55
109
|
])->JSON.Encode.object
|
|
56
110
|
|
|
57
111
|
let encodeRequiredStoreDeclaration = (d: requiredStoreDeclaration): JSON.t =>
|
|
@@ -62,6 +116,12 @@ let encodeRequiredStoreDeclaration = (d: requiredStoreDeclaration): JSON.t =>
|
|
|
62
116
|
("annotation", d.annotation->Option.mapOr(JSON.Encode.null, JSON.Encode.string)),
|
|
63
117
|
])->JSON.Encode.object
|
|
64
118
|
|
|
119
|
+
let encodeRequiredCapabilityDeclaration = (d: requiredCapabilityDeclaration): JSON.t =>
|
|
120
|
+
Dict.fromArray([
|
|
121
|
+
("capability", JSON.Encode.string(d.capability)),
|
|
122
|
+
("component", JSON.Encode.string(d.component)),
|
|
123
|
+
])->JSON.Encode.object
|
|
124
|
+
|
|
65
125
|
// Deliberately NOT filtered by `isPublicQueryable`: that filter is the AutoUI
|
|
66
126
|
// contract, and applying it here would silently drop Internal components from the
|
|
67
127
|
// graph a developer tool draws.
|
|
@@ -129,4 +189,16 @@ let encodePluginStructureEntry = (~pluginId: string, def: pluginStructure): JSON
|
|
|
129
189
|
ds->Array.map(encodeRequiredStoreDeclaration)->JSON.Encode.array
|
|
130
190
|
),
|
|
131
191
|
),
|
|
192
|
+
(
|
|
193
|
+
"requiredCapabilities",
|
|
194
|
+
def.requiredCapabilities->Option.mapOr(JSON.Encode.null, ds =>
|
|
195
|
+
ds->Array.map(encodeRequiredCapabilityDeclaration)->JSON.Encode.array
|
|
196
|
+
),
|
|
197
|
+
),
|
|
198
|
+
(
|
|
199
|
+
"traitDeclarations",
|
|
200
|
+
def.traitDeclarations->Option.mapOr(JSON.Encode.null, ds =>
|
|
201
|
+
ds->Array.map(encodeTraitDeclaration)->JSON.Encode.array
|
|
202
|
+
),
|
|
203
|
+
),
|
|
132
204
|
])->JSON.Encode.object
|
|
@@ -5,11 +5,36 @@ import * as Plugin$ReventlessCore from "../plugin/component/Plugin.res.mjs";
|
|
|
5
5
|
import * as Platform_ComponentDefinitionsApi$ReventlessCore from "./Platform_ComponentDefinitionsApi.res.mjs";
|
|
6
6
|
|
|
7
7
|
let sdlTypes = [
|
|
8
|
-
`type
|
|
8
|
+
`type Platform_PublishedEventDef {\n name: String!\n fromEventTypes: [String!]!\n}`,
|
|
9
|
+
`type Platform_AcceptedCommandDef {\n name: String!\n toCommandTypes: [String!]!\n}`,
|
|
10
|
+
`type Platform_ExtensionPointDef {\n name: String!\n delegateNames: [String!]!\n sourceEventTypes: [String!]!\n commandTypes: [String!]\n publishedEvents: [Platform_PublishedEventDef!]\n acceptedCommands: [Platform_AcceptedCommandDef!]\n}`,
|
|
9
11
|
`type Platform_RequiredStoreDeclaration {\n store: String!\n component: String!\n field: String!\n annotation: String\n}`,
|
|
10
|
-
`type
|
|
12
|
+
`type Platform_RequiredCapabilityDeclaration {\n capability: String!\n component: String!\n}`,
|
|
13
|
+
`type Platform_TraitDeclaration {\n trait: String!\n version: String!\n posture: String!\n component: String!\n}`,
|
|
14
|
+
`type Platform_PluginStructureEntry {\n pluginId: String!\n readModels: [Platform_ReadSideDef!]!\n stateViewSlices: [Platform_ReadSideDef!]!\n stateChangeSlices: [Platform_WriteSideDef!]!\n aggregates: [Platform_WriteSideDef!]!\n automationSlices: [Platform_AutomationSliceDef!]!\n outboundTranslationSlices: [Platform_OutboundTranslationSliceDef!]!\n inboundTranslationSlices: [Platform_InboundTranslationSliceDef!]!\n extensions: [Platform_ExtensionDef!]!\n extensionPoints: [Platform_ExtensionPointDef!]\n requiredStores: [String!]\n requiredStoreDeclarations: [Platform_RequiredStoreDeclaration!]\n requiredCapabilities: [Platform_RequiredCapabilityDeclaration!]\n traitDeclarations: [Platform_TraitDeclaration!]\n}`
|
|
11
15
|
];
|
|
12
16
|
|
|
17
|
+
function encodeTraitDeclaration(d) {
|
|
18
|
+
return Object.fromEntries([
|
|
19
|
+
[
|
|
20
|
+
"trait",
|
|
21
|
+
d.trait
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
"version",
|
|
25
|
+
d.version
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
"posture",
|
|
29
|
+
d.posture
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
"component",
|
|
33
|
+
d.component
|
|
34
|
+
]
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
|
|
13
38
|
function encodeExtensionPointDef(e) {
|
|
14
39
|
return Object.fromEntries([
|
|
15
40
|
[
|
|
@@ -27,6 +52,32 @@ function encodeExtensionPointDef(e) {
|
|
|
27
52
|
[
|
|
28
53
|
"commandTypes",
|
|
29
54
|
Stdlib_Option.mapOr(e.commandTypes, null, Platform_ComponentDefinitionsApi$ReventlessCore.encodeStrings)
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
"publishedEvents",
|
|
58
|
+
Stdlib_Option.mapOr(e.publishedEvents, null, published => published.map(p => Object.fromEntries([
|
|
59
|
+
[
|
|
60
|
+
"name",
|
|
61
|
+
p.name
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
"fromEventTypes",
|
|
65
|
+
Platform_ComponentDefinitionsApi$ReventlessCore.encodeStrings(p.fromEventTypes)
|
|
66
|
+
]
|
|
67
|
+
])))
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
"acceptedCommands",
|
|
71
|
+
Stdlib_Option.mapOr(e.acceptedCommands, null, accepted => accepted.map(a => Object.fromEntries([
|
|
72
|
+
[
|
|
73
|
+
"name",
|
|
74
|
+
a.name
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
"toCommandTypes",
|
|
78
|
+
Platform_ComponentDefinitionsApi$ReventlessCore.encodeStrings(a.toCommandTypes)
|
|
79
|
+
]
|
|
80
|
+
])))
|
|
30
81
|
]
|
|
31
82
|
]);
|
|
32
83
|
}
|
|
@@ -52,6 +103,19 @@ function encodeRequiredStoreDeclaration(d) {
|
|
|
52
103
|
]);
|
|
53
104
|
}
|
|
54
105
|
|
|
106
|
+
function encodeRequiredCapabilityDeclaration(d) {
|
|
107
|
+
return Object.fromEntries([
|
|
108
|
+
[
|
|
109
|
+
"capability",
|
|
110
|
+
d.capability
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
"component",
|
|
114
|
+
d.component
|
|
115
|
+
]
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
|
|
55
119
|
function encodePluginStructureEntry(pluginId, def) {
|
|
56
120
|
return Object.fromEntries([
|
|
57
121
|
[
|
|
@@ -101,6 +165,14 @@ function encodePluginStructureEntry(pluginId, def) {
|
|
|
101
165
|
[
|
|
102
166
|
"requiredStoreDeclarations",
|
|
103
167
|
Stdlib_Option.mapOr(def.requiredStoreDeclarations, null, ds => ds.map(encodeRequiredStoreDeclaration))
|
|
168
|
+
],
|
|
169
|
+
[
|
|
170
|
+
"requiredCapabilities",
|
|
171
|
+
Stdlib_Option.mapOr(def.requiredCapabilities, null, ds => ds.map(encodeRequiredCapabilityDeclaration))
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
"traitDeclarations",
|
|
175
|
+
Stdlib_Option.mapOr(def.traitDeclarations, null, ds => ds.map(encodeTraitDeclaration))
|
|
104
176
|
]
|
|
105
177
|
]);
|
|
106
178
|
}
|
|
@@ -110,8 +182,10 @@ let sdlQueryField = ` Platform_PluginStructures: [Platform_PluginStructureEntry
|
|
|
110
182
|
export {
|
|
111
183
|
sdlTypes,
|
|
112
184
|
sdlQueryField,
|
|
185
|
+
encodeTraitDeclaration,
|
|
113
186
|
encodeExtensionPointDef,
|
|
114
187
|
encodeRequiredStoreDeclaration,
|
|
188
|
+
encodeRequiredCapabilityDeclaration,
|
|
115
189
|
encodePluginStructureEntry,
|
|
116
190
|
}
|
|
117
191
|
/* No side effect */
|
|
@@ -46,6 +46,12 @@ function commandAuthorization(param) {
|
|
|
46
46
|
return "AllowAuthenticated";
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
function commandTransition(param) {
|
|
50
|
+
return "Unrestricted";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let traits = [];
|
|
54
|
+
|
|
49
55
|
let name = "UiFragmentRegistry";
|
|
50
56
|
|
|
51
57
|
let Id;
|
|
@@ -66,5 +72,7 @@ export {
|
|
|
66
72
|
moduleUrl,
|
|
67
73
|
commandAuthorization,
|
|
68
74
|
readConsistency,
|
|
75
|
+
commandTransition,
|
|
76
|
+
traits,
|
|
69
77
|
}
|
|
70
78
|
/* commandSchema Not a pure module */
|
|
@@ -3,11 +3,45 @@ open ReventlessInfra.Api
|
|
|
3
3
|
let isNoApi = (commandSchema: S.t<unknown>): bool =>
|
|
4
4
|
commandSchema->S.Metadata.get(~id=noApiId)->Option.getOr(false)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// Variants excluded by a mark on the member itself. This is the half that
|
|
7
|
+
// survives a spread: splicing copies members, not the metadata of the union they
|
|
8
|
+
// came from, so a command a trait marked internal is only still recognisable here.
|
|
9
|
+
let excludedByMembers = (commandSchema: S.t<unknown>): array<string> =>
|
|
10
|
+
switch commandSchema {
|
|
11
|
+
| AnyOf({anyOf}) =>
|
|
12
|
+
anyOf->Array.filterMap(member =>
|
|
13
|
+
member->S.Metadata.get(~id=noApiVariantId)->Option.getOr(false)
|
|
14
|
+
? variantNameOf(member)
|
|
15
|
+
: None
|
|
16
|
+
)
|
|
17
|
+
| _ => []
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
Every variant excluded from the API, from both records of the fact.
|
|
22
|
+
|
|
23
|
+
The union's own set covers variants the schema's author declared; the members'
|
|
24
|
+
marks cover variants spliced in from another type, whose author's declaration is
|
|
25
|
+
in a file this one never mentions. A reader that consulted only the first
|
|
26
|
+
published someone else's internal commands.
|
|
27
|
+
|
|
28
|
+
`None` still means "nothing is excluded", so a caller's existing branch is
|
|
29
|
+
unchanged.
|
|
30
|
+
*/
|
|
31
|
+
let getExcludedVariants = (commandSchema: S.t<unknown>): option<Set.t<string>> => {
|
|
32
|
+
let fromMembers = excludedByMembers(commandSchema)
|
|
33
|
+
switch (commandSchema->S.Metadata.get(~id=noApiVariantsId), fromMembers) {
|
|
34
|
+
| (None, []) => None
|
|
35
|
+
| (None, members) => Some(Set.fromArray(members))
|
|
36
|
+
| (Some(declared), []) => Some(declared)
|
|
37
|
+
| (Some(declared), members) =>
|
|
38
|
+
let all = declared->Set.toArray->Array.concat(members)
|
|
39
|
+
Some(Set.fromArray(all))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
8
42
|
|
|
9
43
|
let filterNoApiVariants = (fieldNames: array<string>, commandSchema: S.t<unknown>): array<string> =>
|
|
10
|
-
switch commandSchema
|
|
44
|
+
switch getExcludedVariants(commandSchema) {
|
|
11
45
|
| None => fieldNames
|
|
12
46
|
| Some(excluded) => fieldNames->Array.filter(name => !(excluded->Set.has(name)))
|
|
13
47
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Sury from "sury";
|
|
4
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
4
5
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
6
|
import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
|
|
6
7
|
|
|
@@ -8,12 +9,37 @@ function isNoApi(commandSchema) {
|
|
|
8
9
|
return Stdlib_Option.getOr(Sury.$Metadata_get(commandSchema, Api$ReventlessInfra.noApiId), false);
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
function excludedByMembers(commandSchema) {
|
|
13
|
+
if (commandSchema.type === "anyOf") {
|
|
14
|
+
return Stdlib_Array.filterMap(commandSchema.anyOf, member => {
|
|
15
|
+
if (Stdlib_Option.getOr(Sury.$Metadata_get(member, Api$ReventlessInfra.noApiVariantId), false)) {
|
|
16
|
+
return Api$ReventlessInfra.variantNameOf(member);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
} else {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
function getExcludedVariants(commandSchema) {
|
|
12
|
-
|
|
25
|
+
let fromMembers = excludedByMembers(commandSchema);
|
|
26
|
+
let match = Sury.$Metadata_get(commandSchema, Api$ReventlessInfra.noApiVariantsId);
|
|
27
|
+
if (match === undefined) {
|
|
28
|
+
if (fromMembers.length !== 0) {
|
|
29
|
+
return new Set(fromMembers);
|
|
30
|
+
} else {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (fromMembers.length === 0) {
|
|
35
|
+
return match;
|
|
36
|
+
}
|
|
37
|
+
let all = Array.from(match).concat(fromMembers);
|
|
38
|
+
return new Set(all);
|
|
13
39
|
}
|
|
14
40
|
|
|
15
41
|
function filterNoApiVariants(fieldNames, commandSchema) {
|
|
16
|
-
let excluded =
|
|
42
|
+
let excluded = getExcludedVariants(commandSchema);
|
|
17
43
|
if (excluded !== undefined) {
|
|
18
44
|
return fieldNames.filter(name => !excluded.has(name));
|
|
19
45
|
} else {
|
|
@@ -23,6 +49,7 @@ function filterNoApiVariants(fieldNames, commandSchema) {
|
|
|
23
49
|
|
|
24
50
|
export {
|
|
25
51
|
isNoApi,
|
|
52
|
+
excludedByMembers,
|
|
26
53
|
getExcludedVariants,
|
|
27
54
|
filterNoApiVariants,
|
|
28
55
|
}
|
|
@@ -169,19 +169,19 @@ module Make = (
|
|
|
169
169
|
// Per-source erased dispatch — pre-compile decoders once at module init.
|
|
170
170
|
type dispatch = {
|
|
171
171
|
sourceName: string,
|
|
172
|
-
handle: (JSON.t, Reventless.AutomationSlice.context) => unit,
|
|
172
|
+
handle: (JSON.t, ~sourceId: string, Reventless.AutomationSlice.context) => unit,
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
let dispatches: array<dispatch> = Automation.mappings->Array.map((
|
|
176
176
|
module(M: Automation.Mapping),
|
|
177
177
|
) => {
|
|
178
178
|
let decoder = Reventless.DcbDecode.makeDecoder(M.sourceEventSchema)
|
|
179
|
-
let handle = (json: JSON.t, ctx: Reventless.AutomationSlice.context) => {
|
|
179
|
+
let handle = (json: JSON.t, ~sourceId: string, ctx: Reventless.AutomationSlice.context) => {
|
|
180
180
|
let (eventType, dataDict) = json->Message.splitMessage
|
|
181
181
|
switch decoder.decode(~eventType, ~data=dataDict) {
|
|
182
182
|
| Some(event) =>
|
|
183
183
|
// Collect — append new items keyed by ID; first writer wins (idempotent).
|
|
184
|
-
M.collect(event, ctx)->Array.forEach(((id, item)) => {
|
|
184
|
+
M.collect(event, ~sourceId, ctx)->Array.forEach(((id, item)) => {
|
|
185
185
|
switch todoItems->Dict.get(id) {
|
|
186
186
|
| Some(_) => () // Already exists — skip
|
|
187
187
|
| None =>
|
|
@@ -225,7 +225,7 @@ module Make = (
|
|
|
225
225
|
// Multiple mappings can share a sourceName; all matching dispatches run.
|
|
226
226
|
dispatches->Array.forEach(d => {
|
|
227
227
|
if d.sourceName == sourceName {
|
|
228
|
-
d.handle(eventPayload, ctx)
|
|
228
|
+
d.handle(eventPayload, ~sourceId=context.id, ctx)
|
|
229
229
|
}
|
|
230
230
|
})
|
|
231
231
|
})
|
|
@@ -57,14 +57,14 @@ function Make(Spec) {
|
|
|
57
57
|
};
|
|
58
58
|
let dispatches = Automation.mappings.map(M => {
|
|
59
59
|
let decoder = DcbDecode$Reventless.makeDecoder(M.sourceEventSchema);
|
|
60
|
-
let handle = (json, ctx) => {
|
|
60
|
+
let handle = (json, sourceId, ctx) => {
|
|
61
61
|
let match = Message$ReventlessCore.splitMessage(json);
|
|
62
62
|
let event = decoder.decode(match[0], match[1]);
|
|
63
63
|
if (event === undefined) {
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
let event$1 = Primitive_option.valFromOption(event);
|
|
67
|
-
M.collect(event$1, ctx).forEach(param => {
|
|
67
|
+
M.collect(event$1, sourceId, ctx).forEach(param => {
|
|
68
68
|
let id = param[0];
|
|
69
69
|
let match = todoItems[id];
|
|
70
70
|
if (match !== undefined) {
|
|
@@ -105,7 +105,7 @@ function Make(Spec) {
|
|
|
105
105
|
let eventPayload = dict !== undefined ? Stdlib_Option.getOr(dict["event"], json) : json;
|
|
106
106
|
dispatches.forEach(d => {
|
|
107
107
|
if (d.sourceName === sourceName) {
|
|
108
|
-
return d.handle(eventPayload, ctx);
|
|
108
|
+
return d.handle(eventPayload, context.id, ctx);
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
111
|
});
|