@reventlessdev/reventless-core 3.0.0-alpha.251 → 3.0.0-alpha.253
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 +23 -0
- package/package.json +8 -8
- 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_PluginStructuresApi.res +43 -7
- package/src/admin/Platform_PluginStructuresApi.res.mjs +47 -1
- 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 +158 -25
- package/src/plugin/component/Plugin_Structure.res.mjs +82 -18
- package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +3 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +3 -1
- package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +3 -1
- package/src/plugin/lifecycle/PluginBehavior.res +11 -11
- package/src/plugin/lifecycle/PluginBehavior.res.mjs +11 -11
- package/src/plugin/lifecycle/PluginSpec.res +39 -16
- package/src/plugin/lifecycle/PluginSpec.res.mjs +54 -56
- package/tests/admin/AdminApiSchemaDriftTest.res +27 -1
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +22 -2
- 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 +4 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +21 -7
- package/tests/admin/Platform_PluginStructuresApiTest.res +16 -0
- package/tests/admin/Platform_PluginStructuresApiTest.res.mjs +17 -3
- 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 +191 -12
- package/tests/plugin/PluginStructureTest.res.mjs +246 -6
- package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +8 -0
- package/tests/plugin/StateChangeSlice/PsDispatchShipment.res +17 -7
- package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +12 -11
- 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 +17 -13
- package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +17 -11
- package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res +54 -0
- package/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs +104 -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/StateViewSlice/PsShipmentsView.res +1 -1
- package/tests/plugin/pluginDefinitionRequiredScalars.txt +18 -0
- package/tests/util/CommandPublisherTest.res.mjs +9 -1
- package/src/components/Api/ApiAllowedStatesHelpers.res +0 -18
- package/src/components/Api/ApiAllowedStatesHelpers.res.mjs +0 -16
- package/src/components/Api/ApiTargetStateHelpers.res +0 -21
- package/src/components/Api/ApiTargetStateHelpers.res.mjs +0 -16
|
@@ -185,6 +185,19 @@ module PsDispatchShipmentSlice: ReventlessInfra.StateChangeSlice.T = {
|
|
|
185
185
|
type component = scsComponent
|
|
186
186
|
let make = (~dcbEventLog as _, ~publishJsons as _, ~tagKeysByEventType as _=?, ~crossPartitionTagKeys as _=?, ~runtime as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
187
187
|
}
|
|
188
|
+
module PsTransitionSwitchSlice: ReventlessInfra.StateChangeSlice.T = {
|
|
189
|
+
module Spec = PsTransitionSwitch
|
|
190
|
+
module Behavior = {
|
|
191
|
+
type state = PsTransitionSwitch.state
|
|
192
|
+
let initialState = PsTransitionSwitch.initialState
|
|
193
|
+
let evolve = PsTransitionSwitch.evolve
|
|
194
|
+
let decide = PsTransitionSwitch.decide
|
|
195
|
+
let moduleUrl = PsTransitionSwitch.moduleUrl
|
|
196
|
+
}
|
|
197
|
+
let isAsync = false
|
|
198
|
+
type component = scsComponent
|
|
199
|
+
let make = (~dcbEventLog as _, ~publishJsons as _, ~tagKeysByEventType as _=?, ~crossPartitionTagKeys as _=?, ~runtime as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
200
|
+
}
|
|
188
201
|
module PsShipmentsViewSlice: ReventlessInfra.StateViewSlice.T = {
|
|
189
202
|
module Spec = PsShipmentsView
|
|
190
203
|
module Projection = {
|
|
@@ -290,12 +303,89 @@ describe("lifecycle topology", () => {
|
|
|
290
303
|
})
|
|
291
304
|
})
|
|
292
305
|
|
|
293
|
-
describe("
|
|
306
|
+
describe("commandTransition — the edge as a switch", () => {
|
|
307
|
+
// The seam a variant spread needs. The removed attribute lowered to a dict on
|
|
308
|
+
// the parent union keyed by variant name, and a spread splices members, so a
|
|
309
|
+
// command a host did not declare could not be annotated at all. A switch over
|
|
310
|
+
// the command reaches every constructor, spliced or not, and the compiler
|
|
311
|
+
// makes it exhaustive.
|
|
312
|
+
let structure = Plugin_Structure.make(
|
|
313
|
+
~name="TransitionSwitchPlugin",
|
|
314
|
+
~stateChangeSlices=[module(PsTransitionSwitchSlice)],
|
|
315
|
+
~stateViewSlices=[],
|
|
316
|
+
)
|
|
317
|
+
let slice = structure.stateChangeSlices->Array.getUnsafe(0)
|
|
318
|
+
let byName = name => slice.commands->Array.find(c => c.name == name)
|
|
319
|
+
|
|
320
|
+
testSync("the switch fills allowedStates and targetState", () => {
|
|
321
|
+
expect((
|
|
322
|
+
byName("Book")->Option.flatMap(c => c.allowedStates),
|
|
323
|
+
byName("Book")->Option.flatMap(c => c.targetState),
|
|
324
|
+
))->toEqual((Some(["Draft"]), Some("Booked")))
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
testSync("a guard declares its from-set and no target", () => {
|
|
328
|
+
// A positive claim rather than an omission: legal in these states, and it
|
|
329
|
+
// moves the row nowhere. Distinguishable on the wire from both fields being
|
|
330
|
+
// None, and consumers are expected to honour it.
|
|
331
|
+
expect((
|
|
332
|
+
byName("Rebook")->Option.flatMap(c => c.allowedStates),
|
|
333
|
+
byName("Rebook")->Option.flatMap(c => c.targetState),
|
|
334
|
+
))->toEqual((Some(["Booked"]), None))
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
testSync("Unrestricted declares nothing, leaving the command unconstrained", () => {
|
|
338
|
+
// Distinct from a from-set naming every state, which says the same thing to
|
|
339
|
+
// a menu and something different to a reader.
|
|
340
|
+
expect((
|
|
341
|
+
byName("Abandon")->Option.flatMap(c => c.allowedStates),
|
|
342
|
+
byName("Abandon")->Option.flatMap(c => c.targetState),
|
|
343
|
+
))->toEqual((None, None))
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
describe("traitDeclarations — a graft leaves a trace", () => {
|
|
348
|
+
// The one signal a graft leaves that survives into a deployed plugin. Every
|
|
349
|
+
// other one — the package dependency, the variant spread, the rules alias, the
|
|
350
|
+
// conformance binding — is source-side and invisible to a running estate.
|
|
351
|
+
let structure = Plugin_Structure.make(
|
|
352
|
+
~name="TraitPlugin",
|
|
353
|
+
~stateChangeSlices=[module(PsTransitionSwitchSlice), module(PsShipOrderSlice)],
|
|
354
|
+
~stateViewSlices=[],
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
testSync("a declaring component's trait reaches the structure", () => {
|
|
358
|
+
expect(
|
|
359
|
+
structure.traitDeclarations->Option.getOr([])->Array.map(d => (d.trait, d.component)),
|
|
360
|
+
)->toEqual([("@reventlessdev/trait-booking", "TransitionSwitch")])
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
testSync("the component name is filled in by the structure, not declared", () => {
|
|
364
|
+
// The trait exports its identity and posture; it cannot know which component a
|
|
365
|
+
// host grafted it onto, and a host writing that name down would be the one
|
|
366
|
+
// hand-typed string this mechanism exists to avoid.
|
|
367
|
+
expect(
|
|
368
|
+
structure.traitDeclarations
|
|
369
|
+
->Option.getOr([])
|
|
370
|
+
->Array.map(d => (d.version, d.posture, d.component)),
|
|
371
|
+
)->toEqual([("9.9.9", "SelfContained", "TransitionSwitch")])
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
testSync("a component that is nobody's graft contributes nothing", () => {
|
|
375
|
+
// `PsShipOrder` declares no traits, and the injected default is empty — so the
|
|
376
|
+
// absence of a graft is silence rather than a row.
|
|
377
|
+
expect(structure.traitDeclarations->Option.getOr([])->Array.length)->toBe(1)
|
|
378
|
+
})
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
describe("declared-edge cross-check", () => {
|
|
294
382
|
// The exit criterion: a state no linked view declares stops the build, and the
|
|
295
383
|
// message says which command, which state, and what it was checked against.
|
|
296
384
|
// `DispatchShipment` produces `ShipmentDispatched`, which the `Shipments` view
|
|
297
385
|
// consumes — so the two are linked, the view's lifecycle is in hand, and
|
|
298
|
-
// "Dispatchd" has somewhere to be wrong.
|
|
386
|
+
// "Dispatchd" has somewhere to be wrong. It compiles because the switch names
|
|
387
|
+
// the slice's OWN enum: the typechecker cannot see that the wrong lifecycle
|
|
388
|
+
// was picked, and this is the check that can.
|
|
299
389
|
let buildBad = () =>
|
|
300
390
|
try {
|
|
301
391
|
Plugin_Structure.make(
|
|
@@ -410,11 +500,10 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
410
500
|
))->toEqual((Some(true), Some(false)))
|
|
411
501
|
})
|
|
412
502
|
|
|
413
|
-
testSync("ShipOrder:
|
|
414
|
-
// End-to-end: the
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
// name-stem).
|
|
503
|
+
testSync("ShipOrder: the switch's target flows through to commandDef.targetState", () => {
|
|
504
|
+
// End-to-end: the spec's `commandTransition`, evaluated per constructor
|
|
505
|
+
// against a synthetic command → commandDef. `CancelShipment` answers
|
|
506
|
+
// `Unrestricted` and carries None (resolver falls back to name-stem).
|
|
418
507
|
let shipOrder = structure.stateChangeSlices->Array.getUnsafe(1)
|
|
419
508
|
let byName = name => shipOrder.commands->Array.find(c => c.name == name)
|
|
420
509
|
expect((
|
|
@@ -423,10 +512,10 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
423
512
|
))->toEqual((Some("Shipped"), None))
|
|
424
513
|
})
|
|
425
514
|
|
|
426
|
-
testSync("ShipOrder:
|
|
427
|
-
// The other half of the same
|
|
428
|
-
//
|
|
429
|
-
//
|
|
515
|
+
testSync("ShipOrder: the switch's from-set flows through to commandDef.allowedStates", () => {
|
|
516
|
+
// The other half of the same declaration. An edge is one value, so a
|
|
517
|
+
// command that declares a target cannot end up without the states it may
|
|
518
|
+
// run from — the two fields are read off it together.
|
|
430
519
|
let shipOrder = structure.stateChangeSlices->Array.getUnsafe(1)
|
|
431
520
|
let byName = name => shipOrder.commands->Array.find(c => c.name == name)
|
|
432
521
|
expect((
|
|
@@ -1366,6 +1455,45 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
1366
1455
|
expect(Reventless.CapabilityManifest.fromStructure(structure).capabilities)->toEqual([])
|
|
1367
1456
|
)
|
|
1368
1457
|
|
|
1458
|
+
// A capability a slice declares rides the same manifest as the stores, so
|
|
1459
|
+
// the platform generator reads one file. It carries no `field`: nothing
|
|
1460
|
+
// annotated it, and naming one would be a fiction.
|
|
1461
|
+
describe("declared capabilities", () => {
|
|
1462
|
+
let withCapability = {
|
|
1463
|
+
...structure,
|
|
1464
|
+
requiredCapabilities: Some([
|
|
1465
|
+
({capability: "Geocoding", component: "GeocodeAddress"}: Reventless.Plugin.requiredCapabilityDeclaration),
|
|
1466
|
+
{capability: "Geocoding", component: "GeocodeDropOff"},
|
|
1467
|
+
]),
|
|
1468
|
+
traitDeclarations: None,
|
|
1469
|
+
}
|
|
1470
|
+
let entries = Reventless.CapabilityManifest.fromStructure(withCapability).capabilities
|
|
1471
|
+
|
|
1472
|
+
testSync("two components needing one capability yield one entry", () =>
|
|
1473
|
+
expect(entries->Array.map(e => e.key))->toEqual(["Geocoding"])
|
|
1474
|
+
)
|
|
1475
|
+
|
|
1476
|
+
testSync("both declaring components are kept, with no field", () =>
|
|
1477
|
+
expect((entries->Array.getUnsafe(0)).declaredBy)->toEqual([
|
|
1478
|
+
({component: "GeocodeAddress"}: Reventless.CapabilityManifest.provenance),
|
|
1479
|
+
{component: "GeocodeDropOff"},
|
|
1480
|
+
])
|
|
1481
|
+
)
|
|
1482
|
+
|
|
1483
|
+
// The generator downstream renders a real `Platform.capability` arm, and
|
|
1484
|
+
// a name this build cannot map has no arm to render — so it is dropped
|
|
1485
|
+
// here rather than passed through as an unrenderable key.
|
|
1486
|
+
testSync("a capability this build does not know is dropped", () =>
|
|
1487
|
+
expect(
|
|
1488
|
+
Reventless.CapabilityManifest.fromStructure({
|
|
1489
|
+
...structure,
|
|
1490
|
+
requiredCapabilities: Some([{capability: "Telepathy", component: "Guess"}]),
|
|
1491
|
+
traitDeclarations: None,
|
|
1492
|
+
}).capabilities,
|
|
1493
|
+
)->toEqual([])
|
|
1494
|
+
)
|
|
1495
|
+
})
|
|
1496
|
+
|
|
1369
1497
|
testSync("rendering is deterministic and newline-terminated", () => {
|
|
1370
1498
|
let rendered = Reventless.CapabilityManifest.renderForStructure(withStores)
|
|
1371
1499
|
expect(rendered)->toBe(
|
|
@@ -1671,7 +1799,7 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
1671
1799
|
let manifest = Reventless.CapabilityManifest.fromStructure(withHeuristicField)
|
|
1672
1800
|
expect(
|
|
1673
1801
|
manifest.capabilities->Array.every(entry =>
|
|
1674
|
-
entry.declaredBy->Array.every(site => site.field != "photoUrl")
|
|
1802
|
+
entry.declaredBy->Array.every(site => site.field != Some("photoUrl"))
|
|
1675
1803
|
),
|
|
1676
1804
|
)->toBe(true)
|
|
1677
1805
|
})
|
|
@@ -1856,3 +1984,54 @@ describe("the subscriber's half of the table", () => {
|
|
|
1856
1984
|
)->toBe(1)
|
|
1857
1985
|
)
|
|
1858
1986
|
})
|
|
1987
|
+
|
|
1988
|
+
// ── One command name, one handler ────────────────────────────────────────────
|
|
1989
|
+
//
|
|
1990
|
+
// A DCB plugin routes a command by its bare type name, so two slices declaring
|
|
1991
|
+
// one name have one handler between them. The runtime notices only when it goes
|
|
1992
|
+
// to stamp owner fields — by which point the deploy has succeeded and the losing
|
|
1993
|
+
// slice is silently unreachable — so the structure refuses it instead.
|
|
1994
|
+
|
|
1995
|
+
describe("duplicate DCB command names", () => {
|
|
1996
|
+
// The same slice twice is the smallest possible collision, and it needs no
|
|
1997
|
+
// fixture that exists only to collide.
|
|
1998
|
+
testSync("two slices declaring one command are refused", () =>
|
|
1999
|
+
expect(
|
|
2000
|
+
switch Plugin_Structure.make(
|
|
2001
|
+
~name="TestPlugin",
|
|
2002
|
+
~stateChangeSlices=[module(PsShipOrderSlice), module(PsShipOrderSlice)],
|
|
2003
|
+
) {
|
|
2004
|
+
| _ => false
|
|
2005
|
+
| exception _ => true
|
|
2006
|
+
},
|
|
2007
|
+
)->toBe(true)
|
|
2008
|
+
)
|
|
2009
|
+
|
|
2010
|
+
testSync("the refusal names the command and both slices", () =>
|
|
2011
|
+
switch Plugin_Structure.make(
|
|
2012
|
+
~name="TestPlugin",
|
|
2013
|
+
~stateChangeSlices=[module(PsShipOrderSlice), module(PsShipOrderSlice)],
|
|
2014
|
+
) {
|
|
2015
|
+
| _ => expect("no refusal")->toBe("a refusal naming the command")
|
|
2016
|
+
| exception JsExn(e) =>
|
|
2017
|
+
let message = e->JsExn.message->Option.getOr("")
|
|
2018
|
+
expect((
|
|
2019
|
+
message->String.includes("ShipOrder"),
|
|
2020
|
+
message->String.includes("routes a command by its bare name"),
|
|
2021
|
+
))->toEqual((true, true))
|
|
2022
|
+
}
|
|
2023
|
+
)
|
|
2024
|
+
|
|
2025
|
+
// Distinct names are the ordinary case and must stay silent.
|
|
2026
|
+
testSync("distinct command names are fine", () =>
|
|
2027
|
+
expect(
|
|
2028
|
+
switch Plugin_Structure.make(
|
|
2029
|
+
~name="TestPlugin",
|
|
2030
|
+
~stateChangeSlices=[module(PsPlaceOrderSlice), module(PsShipOrderSlice)],
|
|
2031
|
+
) {
|
|
2032
|
+
| _ => true
|
|
2033
|
+
| exception _ => false
|
|
2034
|
+
},
|
|
2035
|
+
)->toBe(true)
|
|
2036
|
+
)
|
|
2037
|
+
})
|
|
@@ -30,6 +30,7 @@ import * as PsShipmentsView$ReventlessCore from "./StateViewSlice/PsShipmentsVie
|
|
|
30
30
|
import * as Plugin_Structure$ReventlessCore from "../../src/plugin/component/Plugin_Structure.res.mjs";
|
|
31
31
|
import * as PsCategoriesView$ReventlessCore from "./StateViewSlice/PsCategoriesView.res.mjs";
|
|
32
32
|
import * as PsDispatchShipment$ReventlessCore from "./StateChangeSlice/PsDispatchShipment.res.mjs";
|
|
33
|
+
import * as PsTransitionSwitch$ReventlessCore from "./StateChangeSlice/PsTransitionSwitch.res.mjs";
|
|
33
34
|
import * as Capability_Inference$ReventlessCore from "../../src/plugin/component/Capability_Inference.res.mjs";
|
|
34
35
|
import * as PsAvailableProductsView$ReventlessCore from "./StateViewSlice/PsAvailableProductsView.res.mjs";
|
|
35
36
|
|
|
@@ -53,6 +54,8 @@ let PsPlaceOrderSlice_Spec = {
|
|
|
53
54
|
eventSchema: PsPlaceOrder$ReventlessCore.eventSchema,
|
|
54
55
|
commandSchema: PsPlaceOrder$ReventlessCore.commandSchema,
|
|
55
56
|
commandAuthorization: PsPlaceOrder$ReventlessCore.commandAuthorization,
|
|
57
|
+
commandTransition: PsPlaceOrder$ReventlessCore.commandTransition,
|
|
58
|
+
traits: PsPlaceOrder$ReventlessCore.traits,
|
|
56
59
|
readConsistency: PsPlaceOrder$ReventlessCore.readConsistency
|
|
57
60
|
};
|
|
58
61
|
|
|
@@ -83,6 +86,8 @@ let PsShipOrderSlice_Spec = {
|
|
|
83
86
|
eventSchema: PsShipOrder$ReventlessCore.eventSchema,
|
|
84
87
|
commandSchema: PsShipOrder$ReventlessCore.commandSchema,
|
|
85
88
|
commandAuthorization: PsShipOrder$ReventlessCore.commandAuthorization,
|
|
89
|
+
commandTransition: PsShipOrder$ReventlessCore.commandTransition,
|
|
90
|
+
traits: PsShipOrder$ReventlessCore.traits,
|
|
86
91
|
readConsistency: PsShipOrder$ReventlessCore.readConsistency
|
|
87
92
|
};
|
|
88
93
|
|
|
@@ -243,6 +248,8 @@ let PsAttachInvoiceSlice_Spec = {
|
|
|
243
248
|
eventSchema: PsAttachInvoice$ReventlessCore.eventSchema,
|
|
244
249
|
commandSchema: PsAttachInvoice$ReventlessCore.commandSchema,
|
|
245
250
|
commandAuthorization: PsAttachInvoice$ReventlessCore.commandAuthorization,
|
|
251
|
+
commandTransition: PsAttachInvoice$ReventlessCore.commandTransition,
|
|
252
|
+
traits: PsAttachInvoice$ReventlessCore.traits,
|
|
246
253
|
readConsistency: PsAttachInvoice$ReventlessCore.readConsistency
|
|
247
254
|
};
|
|
248
255
|
|
|
@@ -273,6 +280,8 @@ let PsUploadAvatarSlice_Spec = {
|
|
|
273
280
|
eventSchema: PsUploadAvatar$ReventlessCore.eventSchema,
|
|
274
281
|
commandSchema: PsUploadAvatar$ReventlessCore.commandSchema,
|
|
275
282
|
commandAuthorization: PsUploadAvatar$ReventlessCore.commandAuthorization,
|
|
283
|
+
commandTransition: PsUploadAvatar$ReventlessCore.commandTransition,
|
|
284
|
+
traits: PsUploadAvatar$ReventlessCore.traits,
|
|
276
285
|
readConsistency: PsUploadAvatar$ReventlessCore.readConsistency
|
|
277
286
|
};
|
|
278
287
|
|
|
@@ -303,6 +312,8 @@ let PsUploadImagesSlice_Spec = {
|
|
|
303
312
|
eventSchema: PsUploadImages$ReventlessCore.eventSchema,
|
|
304
313
|
commandSchema: PsUploadImages$ReventlessCore.commandSchema,
|
|
305
314
|
commandAuthorization: PsUploadImages$ReventlessCore.commandAuthorization,
|
|
315
|
+
commandTransition: PsUploadImages$ReventlessCore.commandTransition,
|
|
316
|
+
traits: PsUploadImages$ReventlessCore.traits,
|
|
306
317
|
readConsistency: PsUploadImages$ReventlessCore.readConsistency
|
|
307
318
|
};
|
|
308
319
|
|
|
@@ -333,6 +344,8 @@ let PsTypoStoreSlice_Spec = {
|
|
|
333
344
|
eventSchema: PsTypoStore$ReventlessCore.eventSchema,
|
|
334
345
|
commandSchema: PsTypoStore$ReventlessCore.commandSchema,
|
|
335
346
|
commandAuthorization: PsTypoStore$ReventlessCore.commandAuthorization,
|
|
347
|
+
commandTransition: PsTypoStore$ReventlessCore.commandTransition,
|
|
348
|
+
traits: PsTypoStore$ReventlessCore.traits,
|
|
336
349
|
readConsistency: PsTypoStore$ReventlessCore.readConsistency
|
|
337
350
|
};
|
|
338
351
|
|
|
@@ -363,6 +376,8 @@ let PsChangePhotoSlice_Spec = {
|
|
|
363
376
|
eventSchema: PsChangePhoto$ReventlessCore.eventSchema,
|
|
364
377
|
commandSchema: PsChangePhoto$ReventlessCore.commandSchema,
|
|
365
378
|
commandAuthorization: PsChangePhoto$ReventlessCore.commandAuthorization,
|
|
379
|
+
commandTransition: PsChangePhoto$ReventlessCore.commandTransition,
|
|
380
|
+
traits: PsChangePhoto$ReventlessCore.traits,
|
|
366
381
|
readConsistency: PsChangePhoto$ReventlessCore.readConsistency
|
|
367
382
|
};
|
|
368
383
|
|
|
@@ -393,6 +408,8 @@ let PsReserveStockSlice_Spec = {
|
|
|
393
408
|
eventSchema: PsReserveStock$ReventlessCore.eventSchema,
|
|
394
409
|
commandSchema: PsReserveStock$ReventlessCore.commandSchema,
|
|
395
410
|
commandAuthorization: PsReserveStock$ReventlessCore.commandAuthorization,
|
|
411
|
+
commandTransition: PsReserveStock$ReventlessCore.commandTransition,
|
|
412
|
+
traits: PsReserveStock$ReventlessCore.traits,
|
|
396
413
|
readConsistency: PsReserveStock$ReventlessCore.readConsistency
|
|
397
414
|
};
|
|
398
415
|
|
|
@@ -423,6 +440,8 @@ let PsDispatchShipmentSlice_Spec = {
|
|
|
423
440
|
eventSchema: PsDispatchShipment$ReventlessCore.eventSchema,
|
|
424
441
|
commandSchema: PsDispatchShipment$ReventlessCore.commandSchema,
|
|
425
442
|
commandAuthorization: PsDispatchShipment$ReventlessCore.commandAuthorization,
|
|
443
|
+
commandTransition: PsDispatchShipment$ReventlessCore.commandTransition,
|
|
444
|
+
traits: PsDispatchShipment$ReventlessCore.traits,
|
|
426
445
|
readConsistency: PsDispatchShipment$ReventlessCore.readConsistency
|
|
427
446
|
};
|
|
428
447
|
|
|
@@ -433,12 +452,44 @@ let PsDispatchShipmentSlice = {
|
|
|
433
452
|
make: make$13
|
|
434
453
|
};
|
|
435
454
|
|
|
455
|
+
let Behavior$9 = {
|
|
456
|
+
initialState: false,
|
|
457
|
+
evolve: PsTransitionSwitch$ReventlessCore.evolve,
|
|
458
|
+
decide: PsTransitionSwitch$ReventlessCore.decide,
|
|
459
|
+
moduleUrl: PsTransitionSwitch$ReventlessCore.moduleUrl
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
function make$14(param, param$1, param$2, param$3, param$4, param$5) {
|
|
463
|
+
return 0;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
let PsTransitionSwitchSlice_Spec = {
|
|
467
|
+
name: PsTransitionSwitch$ReventlessCore.name,
|
|
468
|
+
moduleUrl: PsTransitionSwitch$ReventlessCore.moduleUrl,
|
|
469
|
+
Id: Id$Reventless.$$String,
|
|
470
|
+
consumedEventSchema: PsTransitionSwitch$ReventlessCore.consumedEventSchema,
|
|
471
|
+
errorSchema: PsTransitionSwitch$ReventlessCore.errorSchema,
|
|
472
|
+
eventSchema: PsTransitionSwitch$ReventlessCore.eventSchema,
|
|
473
|
+
commandSchema: PsTransitionSwitch$ReventlessCore.commandSchema,
|
|
474
|
+
commandAuthorization: PsTransitionSwitch$ReventlessCore.commandAuthorization,
|
|
475
|
+
commandTransition: PsTransitionSwitch$ReventlessCore.commandTransition,
|
|
476
|
+
traits: PsTransitionSwitch$ReventlessCore.traits,
|
|
477
|
+
readConsistency: PsTransitionSwitch$ReventlessCore.readConsistency
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
let PsTransitionSwitchSlice = {
|
|
481
|
+
Spec: PsTransitionSwitchSlice_Spec,
|
|
482
|
+
Behavior: Behavior$9,
|
|
483
|
+
isAsync: false,
|
|
484
|
+
make: make$14
|
|
485
|
+
};
|
|
486
|
+
|
|
436
487
|
let Projection$5 = {
|
|
437
488
|
project: PsShipmentsView$ReventlessCore.project,
|
|
438
489
|
moduleUrl: PsShipmentsView$ReventlessCore.moduleUrl
|
|
439
490
|
};
|
|
440
491
|
|
|
441
|
-
function make$
|
|
492
|
+
function make$15(param, param$1, param$2) {
|
|
442
493
|
return 0;
|
|
443
494
|
}
|
|
444
495
|
|
|
@@ -456,7 +507,7 @@ let PsShipmentsViewSlice_Spec = {
|
|
|
456
507
|
let PsShipmentsViewSlice = {
|
|
457
508
|
Spec: PsShipmentsViewSlice_Spec,
|
|
458
509
|
Projection: Projection$5,
|
|
459
|
-
make: make$
|
|
510
|
+
make: make$15
|
|
460
511
|
};
|
|
461
512
|
|
|
462
513
|
let structure = Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, [
|
|
@@ -529,7 +580,70 @@ globalThis.describe("lifecycle topology", () => {
|
|
|
529
580
|
});
|
|
530
581
|
});
|
|
531
582
|
|
|
532
|
-
globalThis.describe("
|
|
583
|
+
globalThis.describe("commandTransition — the edge as a switch", () => {
|
|
584
|
+
let structure = Plugin_Structure$ReventlessCore.make("TransitionSwitchPlugin", undefined, undefined, [], [PsTransitionSwitchSlice], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
585
|
+
let slice = structure.stateChangeSlices[0];
|
|
586
|
+
let byName = name => slice.commands.find(c => c.name === name);
|
|
587
|
+
globalThis.test("the switch fills allowedStates and targetState", () => {
|
|
588
|
+
globalThis.expect([
|
|
589
|
+
Stdlib_Option.flatMap(byName("Book"), c => c.allowedStates),
|
|
590
|
+
Stdlib_Option.flatMap(byName("Book"), c => c.targetState)
|
|
591
|
+
]).toEqual([
|
|
592
|
+
["Draft"],
|
|
593
|
+
"Booked"
|
|
594
|
+
]);
|
|
595
|
+
});
|
|
596
|
+
globalThis.test("a guard declares its from-set and no target", () => {
|
|
597
|
+
globalThis.expect([
|
|
598
|
+
Stdlib_Option.flatMap(byName("Rebook"), c => c.allowedStates),
|
|
599
|
+
Stdlib_Option.flatMap(byName("Rebook"), c => c.targetState)
|
|
600
|
+
]).toEqual([
|
|
601
|
+
["Booked"],
|
|
602
|
+
undefined
|
|
603
|
+
]);
|
|
604
|
+
});
|
|
605
|
+
globalThis.test("Unrestricted declares nothing, leaving the command unconstrained", () => {
|
|
606
|
+
globalThis.expect([
|
|
607
|
+
Stdlib_Option.flatMap(byName("Abandon"), c => c.allowedStates),
|
|
608
|
+
Stdlib_Option.flatMap(byName("Abandon"), c => c.targetState)
|
|
609
|
+
]).toEqual([
|
|
610
|
+
undefined,
|
|
611
|
+
undefined
|
|
612
|
+
]);
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
globalThis.describe("traitDeclarations — a graft leaves a trace", () => {
|
|
617
|
+
let structure = Plugin_Structure$ReventlessCore.make("TraitPlugin", undefined, undefined, [], [
|
|
618
|
+
PsTransitionSwitchSlice,
|
|
619
|
+
PsShipOrderSlice
|
|
620
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
621
|
+
globalThis.test("a declaring component's trait reaches the structure", () => {
|
|
622
|
+
globalThis.expect(Stdlib_Option.getOr(structure.traitDeclarations, []).map(d => [
|
|
623
|
+
d.trait,
|
|
624
|
+
d.component
|
|
625
|
+
])).toEqual([[
|
|
626
|
+
"@reventlessdev/trait-booking",
|
|
627
|
+
"TransitionSwitch"
|
|
628
|
+
]]);
|
|
629
|
+
});
|
|
630
|
+
globalThis.test("the component name is filled in by the structure, not declared", () => {
|
|
631
|
+
globalThis.expect(Stdlib_Option.getOr(structure.traitDeclarations, []).map(d => [
|
|
632
|
+
d.version,
|
|
633
|
+
d.posture,
|
|
634
|
+
d.component
|
|
635
|
+
])).toEqual([[
|
|
636
|
+
"9.9.9",
|
|
637
|
+
"SelfContained",
|
|
638
|
+
"TransitionSwitch"
|
|
639
|
+
]]);
|
|
640
|
+
});
|
|
641
|
+
globalThis.test("a component that is nobody's graft contributes nothing", () => {
|
|
642
|
+
globalThis.expect(Stdlib_Option.getOr(structure.traitDeclarations, []).length).toBe(1);
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
globalThis.describe("declared-edge cross-check", () => {
|
|
533
647
|
let buildBad = () => {
|
|
534
648
|
try {
|
|
535
649
|
Plugin_Structure$ReventlessCore.make("TransitionPlugin", undefined, undefined, [PsShipmentsViewSlice], [PsDispatchShipmentSlice], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
@@ -642,7 +756,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
642
756
|
false
|
|
643
757
|
]);
|
|
644
758
|
});
|
|
645
|
-
globalThis.test("ShipOrder:
|
|
759
|
+
globalThis.test("ShipOrder: the switch's target flows through to commandDef.targetState", () => {
|
|
646
760
|
let shipOrder = structure.stateChangeSlices[1];
|
|
647
761
|
let byName = name => shipOrder.commands.find(c => c.name === name);
|
|
648
762
|
globalThis.expect([
|
|
@@ -653,7 +767,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
653
767
|
undefined
|
|
654
768
|
]);
|
|
655
769
|
});
|
|
656
|
-
globalThis.test("ShipOrder:
|
|
770
|
+
globalThis.test("ShipOrder: the switch's from-set flows through to commandDef.allowedStates", () => {
|
|
657
771
|
let shipOrder = structure.stateChangeSlices[1];
|
|
658
772
|
let byName = name => shipOrder.commands.find(c => c.name === name);
|
|
659
773
|
globalThis.expect([
|
|
@@ -1448,6 +1562,78 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
1448
1562
|
globalThis.test("a structure declaring nothing yields an empty list, not a missing manifest", () => {
|
|
1449
1563
|
globalThis.expect(CapabilityManifest$Reventless.fromStructure(structure).capabilities).toEqual([]);
|
|
1450
1564
|
});
|
|
1565
|
+
globalThis.describe("declared capabilities", () => {
|
|
1566
|
+
let withCapability_readModels = structure.readModels;
|
|
1567
|
+
let withCapability_stateViewSlices = structure.stateViewSlices;
|
|
1568
|
+
let withCapability_stateChangeSlices = structure.stateChangeSlices;
|
|
1569
|
+
let withCapability_aggregates = structure.aggregates;
|
|
1570
|
+
let withCapability_automationSlices = structure.automationSlices;
|
|
1571
|
+
let withCapability_outboundTranslationSlices = structure.outboundTranslationSlices;
|
|
1572
|
+
let withCapability_inboundTranslationSlices = structure.inboundTranslationSlices;
|
|
1573
|
+
let withCapability_extensions = structure.extensions;
|
|
1574
|
+
let withCapability_extensionPoints = structure.extensionPoints;
|
|
1575
|
+
let withCapability_requiredStores = structure.requiredStores;
|
|
1576
|
+
let withCapability_requiredStoreDeclarations = structure.requiredStoreDeclarations;
|
|
1577
|
+
let withCapability_requiredCapabilities = [
|
|
1578
|
+
{
|
|
1579
|
+
capability: "Geocoding",
|
|
1580
|
+
component: "GeocodeAddress"
|
|
1581
|
+
},
|
|
1582
|
+
{
|
|
1583
|
+
capability: "Geocoding",
|
|
1584
|
+
component: "GeocodeDropOff"
|
|
1585
|
+
}
|
|
1586
|
+
];
|
|
1587
|
+
let withCapability = {
|
|
1588
|
+
readModels: withCapability_readModels,
|
|
1589
|
+
stateViewSlices: withCapability_stateViewSlices,
|
|
1590
|
+
stateChangeSlices: withCapability_stateChangeSlices,
|
|
1591
|
+
aggregates: withCapability_aggregates,
|
|
1592
|
+
automationSlices: withCapability_automationSlices,
|
|
1593
|
+
outboundTranslationSlices: withCapability_outboundTranslationSlices,
|
|
1594
|
+
inboundTranslationSlices: withCapability_inboundTranslationSlices,
|
|
1595
|
+
extensions: withCapability_extensions,
|
|
1596
|
+
extensionPoints: withCapability_extensionPoints,
|
|
1597
|
+
requiredStores: withCapability_requiredStores,
|
|
1598
|
+
requiredStoreDeclarations: withCapability_requiredStoreDeclarations,
|
|
1599
|
+
requiredCapabilities: withCapability_requiredCapabilities,
|
|
1600
|
+
traitDeclarations: undefined
|
|
1601
|
+
};
|
|
1602
|
+
let entries = CapabilityManifest$Reventless.fromStructure(withCapability).capabilities;
|
|
1603
|
+
globalThis.test("two components needing one capability yield one entry", () => {
|
|
1604
|
+
globalThis.expect(entries.map(e => e.key)).toEqual(["Geocoding"]);
|
|
1605
|
+
});
|
|
1606
|
+
globalThis.test("both declaring components are kept, with no field", () => {
|
|
1607
|
+
globalThis.expect(entries[0].declaredBy).toEqual([
|
|
1608
|
+
{
|
|
1609
|
+
component: "GeocodeAddress"
|
|
1610
|
+
},
|
|
1611
|
+
{
|
|
1612
|
+
component: "GeocodeDropOff"
|
|
1613
|
+
}
|
|
1614
|
+
]);
|
|
1615
|
+
});
|
|
1616
|
+
globalThis.test("a capability this build does not know is dropped", () => {
|
|
1617
|
+
globalThis.expect(CapabilityManifest$Reventless.fromStructure({
|
|
1618
|
+
readModels: structure.readModels,
|
|
1619
|
+
stateViewSlices: structure.stateViewSlices,
|
|
1620
|
+
stateChangeSlices: structure.stateChangeSlices,
|
|
1621
|
+
aggregates: structure.aggregates,
|
|
1622
|
+
automationSlices: structure.automationSlices,
|
|
1623
|
+
outboundTranslationSlices: structure.outboundTranslationSlices,
|
|
1624
|
+
inboundTranslationSlices: structure.inboundTranslationSlices,
|
|
1625
|
+
extensions: structure.extensions,
|
|
1626
|
+
extensionPoints: structure.extensionPoints,
|
|
1627
|
+
requiredStores: structure.requiredStores,
|
|
1628
|
+
requiredStoreDeclarations: structure.requiredStoreDeclarations,
|
|
1629
|
+
requiredCapabilities: [{
|
|
1630
|
+
capability: "Telepathy",
|
|
1631
|
+
component: "Guess"
|
|
1632
|
+
}],
|
|
1633
|
+
traitDeclarations: undefined
|
|
1634
|
+
}).capabilities).toEqual([]);
|
|
1635
|
+
});
|
|
1636
|
+
});
|
|
1451
1637
|
globalThis.test("rendering is deterministic and newline-terminated", () => {
|
|
1452
1638
|
let rendered = CapabilityManifest$Reventless.renderForStructure(withStores);
|
|
1453
1639
|
globalThis.expect(rendered).toBe(`{
|
|
@@ -1662,7 +1848,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
|
|
|
1662
1848
|
let withHeuristicField = Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [PsChangePhotoSlice], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
1663
1849
|
globalThis.expect(withHeuristicField.requiredStores).toEqual(["TestPlugin.productPhotos"]);
|
|
1664
1850
|
let manifest = CapabilityManifest$Reventless.fromStructure(withHeuristicField);
|
|
1665
|
-
globalThis.expect(manifest.capabilities.every(entry => entry.declaredBy.every(site => site.field
|
|
1851
|
+
globalThis.expect(manifest.capabilities.every(entry => entry.declaredBy.every(site => Primitive_object.notequal(site.field, "photoUrl")))).toBe(true);
|
|
1666
1852
|
});
|
|
1667
1853
|
globalThis.test("the warning names the field and the settling annotation", () => {
|
|
1668
1854
|
let text = Capability_Inference$ReventlessCore.message(commandWarnings[0]);
|
|
@@ -1858,6 +2044,59 @@ globalThis.describe("the subscriber's half of the table", () => {
|
|
|
1858
2044
|
});
|
|
1859
2045
|
});
|
|
1860
2046
|
|
|
2047
|
+
globalThis.describe("duplicate DCB command names", () => {
|
|
2048
|
+
globalThis.test("two slices declaring one command are refused", () => {
|
|
2049
|
+
let tmp;
|
|
2050
|
+
try {
|
|
2051
|
+
Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [
|
|
2052
|
+
PsShipOrderSlice,
|
|
2053
|
+
PsShipOrderSlice
|
|
2054
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
2055
|
+
tmp = false;
|
|
2056
|
+
} catch (exn) {
|
|
2057
|
+
tmp = true;
|
|
2058
|
+
}
|
|
2059
|
+
globalThis.expect(tmp).toBe(true);
|
|
2060
|
+
});
|
|
2061
|
+
globalThis.test("the refusal names the command and both slices", () => {
|
|
2062
|
+
let val;
|
|
2063
|
+
try {
|
|
2064
|
+
val = Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [
|
|
2065
|
+
PsShipOrderSlice,
|
|
2066
|
+
PsShipOrderSlice
|
|
2067
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
2068
|
+
} catch (raw_e) {
|
|
2069
|
+
let e = Primitive_exceptions.internalToException(raw_e);
|
|
2070
|
+
if (e.RE_EXN_ID === "JsExn") {
|
|
2071
|
+
let message = Stdlib_Option.getOr(Stdlib_JsExn.message(e._1), "");
|
|
2072
|
+
globalThis.expect([
|
|
2073
|
+
message.includes("ShipOrder"),
|
|
2074
|
+
message.includes("routes a command by its bare name")
|
|
2075
|
+
]).toEqual([
|
|
2076
|
+
true,
|
|
2077
|
+
true
|
|
2078
|
+
]);
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
throw e;
|
|
2082
|
+
}
|
|
2083
|
+
globalThis.expect("no refusal").toBe("a refusal naming the command");
|
|
2084
|
+
});
|
|
2085
|
+
globalThis.test("distinct command names are fine", () => {
|
|
2086
|
+
let tmp;
|
|
2087
|
+
try {
|
|
2088
|
+
Plugin_Structure$ReventlessCore.make("TestPlugin", undefined, undefined, undefined, [
|
|
2089
|
+
PsPlaceOrderSlice,
|
|
2090
|
+
PsShipOrderSlice
|
|
2091
|
+
], undefined, undefined, undefined, undefined, undefined, undefined);
|
|
2092
|
+
tmp = true;
|
|
2093
|
+
} catch (exn) {
|
|
2094
|
+
tmp = false;
|
|
2095
|
+
}
|
|
2096
|
+
globalThis.expect(tmp).toBe(true);
|
|
2097
|
+
});
|
|
2098
|
+
});
|
|
2099
|
+
|
|
1861
2100
|
export {
|
|
1862
2101
|
PsPlaceOrderSlice,
|
|
1863
2102
|
PsShipOrderSlice,
|
|
@@ -1873,6 +2112,7 @@ export {
|
|
|
1873
2112
|
PsChangePhotoSlice,
|
|
1874
2113
|
PsReserveStockSlice,
|
|
1875
2114
|
PsDispatchShipmentSlice,
|
|
2115
|
+
PsTransitionSwitchSlice,
|
|
1876
2116
|
PsShipmentsViewSlice,
|
|
1877
2117
|
structure,
|
|
1878
2118
|
}
|
|
@@ -36,6 +36,12 @@ function commandAuthorization(param) {
|
|
|
36
36
|
return "AllowAuthenticated";
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
function commandTransition(param) {
|
|
40
|
+
return "Unrestricted";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let traits = [];
|
|
44
|
+
|
|
39
45
|
let name = "AttachInvoice";
|
|
40
46
|
|
|
41
47
|
let Id;
|
|
@@ -59,5 +65,7 @@ export {
|
|
|
59
65
|
moduleUrl,
|
|
60
66
|
commandAuthorization,
|
|
61
67
|
readConsistency,
|
|
68
|
+
commandTransition,
|
|
69
|
+
traits,
|
|
62
70
|
}
|
|
63
71
|
/* consumedEventSchema Not a pure module */
|
|
@@ -37,6 +37,12 @@ function commandAuthorization(param) {
|
|
|
37
37
|
return "AllowAuthenticated";
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
function commandTransition(param) {
|
|
41
|
+
return "Unrestricted";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let traits = [];
|
|
45
|
+
|
|
40
46
|
let name = "ChangePhoto";
|
|
41
47
|
|
|
42
48
|
let Id;
|
|
@@ -60,5 +66,7 @@ export {
|
|
|
60
66
|
moduleUrl,
|
|
61
67
|
commandAuthorization,
|
|
62
68
|
readConsistency,
|
|
69
|
+
commandTransition,
|
|
70
|
+
traits,
|
|
63
71
|
}
|
|
64
72
|
/* consumedEventSchema Not a pure module */
|