@reventlessdev/reventless-core 3.0.0-alpha.180 → 3.0.0-alpha.182

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/package.json +7 -7
  3. package/src/Message.res +2 -1
  4. package/src/Message.res.mjs +5 -1
  5. package/src/admin/Platform_Admin_Structure.res +2 -0
  6. package/src/admin/Platform_Admin_Structure.res.mjs +2 -0
  7. package/src/admin/Platform_ComponentDefinitionsApi.res +2 -1
  8. package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
  9. package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res +1 -1
  10. package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res.mjs +2 -1
  11. package/src/components/Api/ApiTargetStateHelpers.res +20 -0
  12. package/src/components/Api/ApiTargetStateHelpers.res.mjs +16 -0
  13. package/src/components/Api/GraphQL_FragmentGenerator.res +1 -0
  14. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +1 -0
  15. package/src/components/Api/SchemaType.res +6 -1
  16. package/src/components/Api/SchemaType.res.mjs +22 -4
  17. package/src/components/Api/SuryToJsonSchema.res +16 -0
  18. package/src/components/Api/SuryToJsonSchema.res.mjs +28 -0
  19. package/src/components/Dcb/Dcb_Builder.res +4 -5
  20. package/src/components/Dcb/Dcb_Builder.res.mjs +3 -5
  21. package/src/components/DcbEventLog/DcbEventLog_Operations.res +6 -1
  22. package/src/components/DcbEventLog/DcbEventLog_Operations.res.mjs +2 -1
  23. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +25 -0
  24. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res.mjs +31 -0
  25. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res +8 -8
  26. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs +26 -6
  27. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +44 -37
  28. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +17 -25
  29. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +27 -2
  30. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +4 -0
  31. package/src/components/StateViewSlice/StateViewSlice_Builder.res +20 -6
  32. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +23 -5
  33. package/src/components/StateViewSlice/StateViewSlice_Callback.res +1 -1
  34. package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +5 -1
  35. package/src/plugin/component/Plugin_Helpers.res +4 -1
  36. package/src/plugin/component/Plugin_Structure.res +15 -1
  37. package/src/plugin/component/Plugin_Structure.res.mjs +4 -1
  38. package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +2 -0
  39. package/tests/IdentityTest.res.mjs +174 -0
  40. package/tests/ResourceAttributionTest.res.mjs +75 -0
  41. package/tests/adapter/MonitoringTest.res.mjs +116 -0
  42. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +10 -0
  43. package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +365 -0
  44. package/tests/admin/Platform_UIFragmentsApiTest.res.mjs +101 -0
  45. package/tests/aggregate/AggregateCacheTest.res.mjs +433 -0
  46. package/tests/aggregate/AggregateCallbackTest.res.mjs +143 -0
  47. package/tests/aggregate/AggregateCausationTest.res.mjs +47 -0
  48. package/tests/aggregate/AggregateConflictTest.res.mjs +386 -0
  49. package/tests/aggregate/AggregateFixtures.res.mjs +308 -0
  50. package/tests/aggregate/AggregateRejectionTest.res.mjs +166 -0
  51. package/tests/aggregate/AggregateSnapshotTest.res.mjs +645 -0
  52. package/tests/api/ApiNoApiTest.res.mjs +90 -0
  53. package/tests/api/GraphQL_StitcherTest.res.mjs +112 -0
  54. package/tests/api/SimpleTest.res.mjs +10 -0
  55. package/tests/api/SuryToJsonSchemaTest.res +68 -0
  56. package/tests/api/SuryToJsonSchemaTest.res.mjs +843 -0
  57. package/tests/commandgenerator/CommandGeneratorCallbackTest.res.mjs +160 -0
  58. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +197 -0
  59. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +152 -0
  60. package/tests/commandtopic/CommandTopicCallbackTest.res.mjs +106 -0
  61. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res.mjs +109 -0
  62. package/tests/counter/CounterCallbackTest.res.mjs +140 -0
  63. package/tests/counter/CounterFixtures.res.mjs +67 -0
  64. package/tests/dcb/DcbDecodeTest.res.mjs +194 -0
  65. package/tests/dcb/DcbEventLogOperationsTest.res.mjs +268 -0
  66. package/tests/dcb/DcbFixtures.res.mjs +534 -0
  67. package/tests/dcb/DcbScopeInferenceTest.res.mjs +480 -0
  68. package/tests/dcb/DcbStateChangeSliceTest.res.mjs +540 -0
  69. package/tests/dcb/DcbTagTest.res.mjs +867 -0
  70. package/tests/dcb/DcbValidationTest.res.mjs +476 -0
  71. package/tests/eventlog/EventLogFixtures.res.mjs +196 -0
  72. package/tests/eventlog/EventLogOperationsTest.res.mjs +192 -0
  73. package/tests/eventlog/EventLogRetryTest.res.mjs +195 -0
  74. package/tests/eventmapper/EventMapperCallbackTest.res.mjs +141 -0
  75. package/tests/eventmapper/EventMapperFixtures.res.mjs +440 -0
  76. package/tests/eventmapper/EventMapperTest.res.mjs +83 -0
  77. package/tests/eventtopic/EventTopicFixtures.res.mjs +65 -0
  78. package/tests/eventtopic/EventTopicOperationsTest.res.mjs +71 -0
  79. package/tests/extensionpoint/ExtensionPointCallbackTest.res.mjs +94 -0
  80. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +205 -0
  81. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +304 -0
  82. package/tests/extensionpoint/PluginDisconnectScheduleTest.res.mjs +92 -0
  83. package/tests/ftp/FTPTest.res.mjs +88 -0
  84. package/tests/logger/LogFormatTest.res.mjs +329 -0
  85. package/tests/logger/LoggerLazyTest.res.mjs +40 -0
  86. package/tests/message/MessageTest.res.mjs +218 -0
  87. package/tests/message/MetaEnvelopeTest.res.mjs +188 -0
  88. package/tests/plugin/HeartbeatDisconnectGraceTest.res.mjs +91 -0
  89. package/tests/plugin/ManifestVisibilityTest.res.mjs +215 -0
  90. package/tests/plugin/PluginSpecExperiment.res.mjs +31 -0
  91. package/tests/plugin/PluginStructureTest.res +55 -0
  92. package/tests/plugin/PluginStructureTest.res.mjs +467 -0
  93. package/tests/plugin/PluginVersionTest.res.mjs +30 -0
  94. package/tests/plugin/SchemaWalkerTest.res.mjs +160 -0
  95. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +62 -0
  96. package/tests/plugin/StateChangeSlice/PsShipOrder.res +4 -1
  97. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +77 -0
  98. package/tests/plugin/StateViewSlice/PsAnnotatedView.res +5 -4
  99. package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +110 -0
  100. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res +1 -1
  101. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +70 -0
  102. package/tests/plugin/StateViewSlice/PsCustomersView.res +1 -1
  103. package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +70 -0
  104. package/tests/plugin/StateViewSlice/PsOrdersView.res +1 -1
  105. package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +82 -0
  106. package/tests/poc/StructuralSubtypingPoc.res.mjs +61 -0
  107. package/tests/projection/ProjectionOptimizeTest.res.mjs +75 -0
  108. package/tests/querydb/QueryDbFixtures.res.mjs +135 -0
  109. package/tests/querydb/QueryDbOperationsTest.res.mjs +168 -0
  110. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res.mjs +77 -0
  111. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +139 -0
  112. package/tests/util/CommandPublisherTest.res.mjs +78 -0
  113. package/tests/util/CsvStreamTest.res.mjs +51 -0
  114. package/tests/util/LruTest.res.mjs +105 -0
  115. package/tests/util/MetricsTest.res.mjs +53 -0
@@ -0,0 +1,174 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
5
+ import * as RequestContext$ReventlessCore from "../src/RequestContext.res.mjs";
6
+
7
+ S.enableJson();
8
+
9
+ globalThis.describe("Identity", () => {
10
+ globalThis.describe("anonymous", () => {
11
+ globalThis.test("has userId 'anonymous'", () => {
12
+ globalThis.expect(Identity$Reventless.anonymous.userId).toBe("anonymous");
13
+ });
14
+ globalThis.test("has empty groups", () => {
15
+ globalThis.expect(Identity$Reventless.anonymous.groups).toEqual([]);
16
+ });
17
+ globalThis.test("has InMemory provider", () => {
18
+ globalThis.expect(Identity$Reventless.anonymous.provider).toEqual("InMemory");
19
+ });
20
+ });
21
+ globalThis.describe("hasGroup", () => {
22
+ let identity_groups = [
23
+ "admin",
24
+ "editors"
25
+ ];
26
+ let identity = {
27
+ userId: "user-1",
28
+ username: "alice",
29
+ groups: identity_groups,
30
+ provider: "Cognito"
31
+ };
32
+ globalThis.test("returns true when group is present", () => {
33
+ globalThis.expect(Identity$Reventless.hasGroup(identity, "admin")).toBe(true);
34
+ });
35
+ globalThis.test("returns false when group is absent", () => {
36
+ globalThis.expect(Identity$Reventless.hasGroup(identity, "viewers")).toBe(false);
37
+ });
38
+ });
39
+ globalThis.describe("getClaim", () => {
40
+ let identity_groups = [];
41
+ let identity_claims = Object.fromEntries([
42
+ [
43
+ "tenant",
44
+ "acme"
45
+ ],
46
+ [
47
+ "role",
48
+ "manager"
49
+ ]
50
+ ]);
51
+ let identity = {
52
+ userId: "user-1",
53
+ username: "alice",
54
+ groups: identity_groups,
55
+ claims: identity_claims,
56
+ provider: "InMemory"
57
+ };
58
+ globalThis.test("returns Some for existing claim", () => {
59
+ globalThis.expect(Identity$Reventless.getClaim(identity, "tenant")).toEqual("acme");
60
+ });
61
+ globalThis.test("returns None for missing claim", () => {
62
+ globalThis.expect(Identity$Reventless.getClaim(identity, "missing")).toEqual(undefined);
63
+ });
64
+ globalThis.test("returns None when claims are absent", () => {
65
+ let noClaims_groups = [];
66
+ let noClaims = {
67
+ userId: "user-2",
68
+ username: "bob",
69
+ groups: noClaims_groups,
70
+ provider: "InMemory"
71
+ };
72
+ globalThis.expect(Identity$Reventless.getClaim(noClaims, "tenant")).toEqual(undefined);
73
+ });
74
+ });
75
+ globalThis.describe("schema roundtrip", () => {
76
+ globalThis.test("encode then decode preserves identity", () => {
77
+ let identity_groups = ["admin"];
78
+ let identity_claims = Object.fromEntries([[
79
+ "tenant",
80
+ "acme"
81
+ ]]);
82
+ let identity = {
83
+ userId: "user-1",
84
+ username: "alice",
85
+ groups: identity_groups,
86
+ claims: identity_claims,
87
+ provider: "Cognito"
88
+ };
89
+ let json = S.reverseConvertToJsonOrThrow(identity, Identity$Reventless.schema);
90
+ let decoded = S.parseJsonOrThrow(json, Identity$Reventless.schema);
91
+ globalThis.expect(decoded).toEqual(identity);
92
+ });
93
+ globalThis.test("roundtrip with Custom provider", () => {
94
+ let identity_groups = [];
95
+ let identity_provider = {
96
+ TAG: "Custom",
97
+ _0: "oauth2"
98
+ };
99
+ let identity = {
100
+ userId: "ext-1",
101
+ username: "external",
102
+ groups: identity_groups,
103
+ provider: identity_provider
104
+ };
105
+ let json = S.reverseConvertToJsonOrThrow(identity, Identity$Reventless.schema);
106
+ let decoded = S.parseJsonOrThrow(json, Identity$Reventless.schema);
107
+ globalThis.expect(decoded).toEqual(identity);
108
+ });
109
+ globalThis.test("roundtrip without optional claims", () => {
110
+ let identity_groups = [];
111
+ let identity = {
112
+ userId: "user-3",
113
+ username: "charlie",
114
+ groups: identity_groups,
115
+ provider: "InMemory"
116
+ };
117
+ let json = S.reverseConvertToJsonOrThrow(identity, Identity$Reventless.schema);
118
+ let decoded = S.parseJsonOrThrow(json, Identity$Reventless.schema);
119
+ globalThis.expect(decoded.userId).toBe("user-3");
120
+ globalThis.expect(decoded.provider).toEqual("InMemory");
121
+ });
122
+ });
123
+ });
124
+
125
+ globalThis.describe("RequestContext", () => {
126
+ globalThis.describe("test() constructor", () => {
127
+ globalThis.test("defaults to anonymous identity", () => {
128
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, undefined, undefined);
129
+ globalThis.expect(ctx.identity.userId).toBe("anonymous");
130
+ });
131
+ globalThis.test("accepts custom identity", () => {
132
+ let identity_groups = ["admin"];
133
+ let identity = {
134
+ userId: "user-1",
135
+ username: "alice",
136
+ groups: identity_groups,
137
+ provider: "Cognito"
138
+ };
139
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, identity, undefined);
140
+ globalThis.expect(ctx.identity.userId).toBe("user-1");
141
+ });
142
+ globalThis.test("defaults to empty claims", () => {
143
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, undefined, undefined);
144
+ globalThis.expect(Object.keys(ctx.claims)).toEqual([]);
145
+ });
146
+ });
147
+ globalThis.describe("getClaim", () => {
148
+ globalThis.test("returns claim value when present", () => {
149
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, undefined, Object.fromEntries([[
150
+ "tenant",
151
+ "acme"
152
+ ]]));
153
+ globalThis.expect(RequestContext$ReventlessCore.getClaim(ctx, "tenant")).toEqual("acme");
154
+ });
155
+ globalThis.test("returns None when absent", () => {
156
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, undefined, undefined);
157
+ globalThis.expect(RequestContext$ReventlessCore.getClaim(ctx, "missing")).toEqual(undefined);
158
+ });
159
+ });
160
+ globalThis.describe("withClaim", () => {
161
+ globalThis.test("adds a claim to the context", () => {
162
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, undefined, undefined);
163
+ let updated = RequestContext$ReventlessCore.withClaim(ctx, "tenant", "acme");
164
+ globalThis.expect(RequestContext$ReventlessCore.getClaim(updated, "tenant")).toEqual("acme");
165
+ });
166
+ globalThis.test("does not mutate the original context", () => {
167
+ let ctx = RequestContext$ReventlessCore.test(undefined, undefined, undefined, undefined, undefined);
168
+ RequestContext$ReventlessCore.withClaim(ctx, "tenant", "acme");
169
+ globalThis.expect(RequestContext$ReventlessCore.getClaim(ctx, "tenant")).toEqual(undefined);
170
+ });
171
+ });
172
+ });
173
+
174
+ /* Not a pure module */
@@ -0,0 +1,75 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as ComponentType$ReventlessCore from "../src/ComponentType.res.mjs";
4
+ import * as ResourceAttribution$ReventlessCore from "../src/ResourceAttribution.res.mjs";
5
+
6
+ globalThis.describe("ResourceAttribution.Scope — wire spellings", () => {
7
+ globalThis.test("scopes render lower-case", () => {
8
+ globalThis.expect([
9
+ "Component",
10
+ "Plugin",
11
+ "Platform"
12
+ ].map(ResourceAttribution$ReventlessCore.Scope.toString)).toEqual([
13
+ "component",
14
+ "plugin",
15
+ "platform"
16
+ ]);
17
+ });
18
+ });
19
+
20
+ globalThis.describe("ResourceAttribution.Role — wire spellings", () => {
21
+ globalThis.test("piece roles render as their constructor name", () => {
22
+ globalThis.expect([
23
+ "EventLog",
24
+ "QueryDb",
25
+ "Runtime",
26
+ "DeadLetter"
27
+ ].map(ResourceAttribution$ReventlessCore.Role.toString)).toEqual([
28
+ "EventLog",
29
+ "QueryDb",
30
+ "Runtime",
31
+ "DeadLetter"
32
+ ]);
33
+ });
34
+ globalThis.test("Other carries the caller's name verbatim", () => {
35
+ globalThis.expect(ResourceAttribution$ReventlessCore.Role.toString({
36
+ TAG: "Other",
37
+ _0: "ChangeFeed"
38
+ })).toBe("ChangeFeed");
39
+ });
40
+ globalThis.test("platform-level things are Platform, not Core", () => {
41
+ globalThis.expect(ComponentType$ReventlessCore.toString("Platform")).toBe("Platform");
42
+ globalThis.expect(ComponentType$ReventlessCore.ofString("Platform")).toEqual("Platform");
43
+ });
44
+ globalThis.test("a role is NOT a component kind — Runtime has no ComponentType twin", () => {
45
+ globalThis.expect(ComponentType$ReventlessCore.ofString("Runtime")).toEqual(undefined);
46
+ });
47
+ });
48
+
49
+ globalThis.describe("ResourceAttribution — ambient plugin context", () => {
50
+ globalThis.test("outside any plugin construct, nothing is attributed", () => {
51
+ globalThis.expect(ResourceAttribution$ReventlessCore.current.contents.plugin).toEqual(undefined);
52
+ globalThis.expect(ResourceAttribution$ReventlessCore.current.contents.platform).toEqual(undefined);
53
+ });
54
+ globalThis.test("enter publishes the plugin and platform under construction", () => {
55
+ let previous = ResourceAttribution$ReventlessCore.enter("online-shop", "Ordering");
56
+ globalThis.expect(ResourceAttribution$ReventlessCore.current.contents.plugin).toEqual("Ordering");
57
+ globalThis.expect(ResourceAttribution$ReventlessCore.current.contents.platform).toEqual("online-shop");
58
+ ResourceAttribution$ReventlessCore.restore(previous);
59
+ });
60
+ globalThis.test("restore unwinds to the previous context, so plugins don't leak", () => {
61
+ let outer = ResourceAttribution$ReventlessCore.enter("online-shop", "Catalog");
62
+ let inner = ResourceAttribution$ReventlessCore.enter("online-shop", "Ordering");
63
+ ResourceAttribution$ReventlessCore.restore(inner);
64
+ globalThis.expect(ResourceAttribution$ReventlessCore.current.contents.plugin).toEqual("Catalog");
65
+ ResourceAttribution$ReventlessCore.restore(outer);
66
+ globalThis.expect(ResourceAttribution$ReventlessCore.current.contents.plugin).toEqual(undefined);
67
+ });
68
+ });
69
+
70
+ let Attribution;
71
+
72
+ export {
73
+ Attribution,
74
+ }
75
+ /* Not a pure module */
@@ -0,0 +1,116 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Monitoring$ReventlessCore from "../../src/adapter/Monitoring/Monitoring.res.mjs";
4
+ import * as ResourceAttribution$ReventlessCore from "../../src/ResourceAttribution.res.mjs";
5
+
6
+ let stubResource = {};
7
+
8
+ globalThis.describe("Monitoring", () => {
9
+ globalThis.test("Noop default: notify is silent and does not throw", () => {
10
+ Monitoring$ReventlessCore.notify("CommandHandler", "before", stubResource);
11
+ globalThis.expect(true).toBe(true);
12
+ });
13
+ globalThis.test("use registers a backend that receives every notify, role and name", () => {
14
+ let recorded = [];
15
+ let onProvisioned = (kind, name, param, param$1, param$2) => {
16
+ recorded.push([
17
+ kind,
18
+ name
19
+ ]);
20
+ };
21
+ let Recorder = {
22
+ onProvisioned: onProvisioned
23
+ };
24
+ Monitoring$ReventlessCore.use(Recorder);
25
+ Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource);
26
+ Monitoring$ReventlessCore.notify("Projection", "AllStateViewSlices", stubResource);
27
+ Monitoring$ReventlessCore.notify("DeadLetterSink", "DeadLetterQueue", stubResource);
28
+ Monitoring$ReventlessCore.notify({
29
+ TAG: "Other",
30
+ _0: "Counter"
31
+ }, "ProductCounter", stubResource);
32
+ globalThis.expect(recorded).toEqual([
33
+ [
34
+ "CommandHandler",
35
+ "AllAggregatesCmdHandler"
36
+ ],
37
+ [
38
+ "Projection",
39
+ "AllStateViewSlices"
40
+ ],
41
+ [
42
+ "DeadLetterSink",
43
+ "DeadLetterQueue"
44
+ ],
45
+ [
46
+ {
47
+ TAG: "Other",
48
+ _0: "Counter"
49
+ },
50
+ "ProductCounter"
51
+ ]
52
+ ]);
53
+ Monitoring$ReventlessCore.use(Monitoring$ReventlessCore.Noop);
54
+ });
55
+ globalThis.test("notify forwards the static name and component resource to the backend", () => {
56
+ let seen = {
57
+ contents: undefined
58
+ };
59
+ let onProvisioned = (param, name, component, param$1, param$2) => {
60
+ seen.contents = [
61
+ name,
62
+ component
63
+ ];
64
+ };
65
+ let Capture = {
66
+ onProvisioned: onProvisioned
67
+ };
68
+ Monitoring$ReventlessCore.use(Capture);
69
+ Monitoring$ReventlessCore.notify("Scheduler", "HeartbeatUnit", stubResource);
70
+ let match = seen.contents;
71
+ if (match !== undefined) {
72
+ globalThis.expect(match[0]).toBe("HeartbeatUnit");
73
+ } else {
74
+ globalThis.expect("no notify received").toBe("a notify");
75
+ }
76
+ Monitoring$ReventlessCore.use(Monitoring$ReventlessCore.Noop);
77
+ });
78
+ globalThis.test("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
79
+ let seen = [];
80
+ let onProvisioned = (param, param$1, param$2, plugin, platform) => {
81
+ seen.push([
82
+ plugin,
83
+ platform
84
+ ]);
85
+ };
86
+ let OwnerCapture = {
87
+ onProvisioned: onProvisioned
88
+ };
89
+ Monitoring$ReventlessCore.use(OwnerCapture);
90
+ Monitoring$ReventlessCore.notify("CommandHandler", "ApiRouter", stubResource);
91
+ let prev = ResourceAttribution$ReventlessCore.enter("online-shop", "Ordering");
92
+ Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource);
93
+ ResourceAttribution$ReventlessCore.restore(prev);
94
+ Monitoring$ReventlessCore.notify("Projection", "AllStateViewSlices", stubResource);
95
+ globalThis.expect(seen).toEqual([
96
+ [
97
+ undefined,
98
+ undefined
99
+ ],
100
+ [
101
+ "Ordering",
102
+ "online-shop"
103
+ ],
104
+ [
105
+ undefined,
106
+ undefined
107
+ ]
108
+ ]);
109
+ Monitoring$ReventlessCore.use(Monitoring$ReventlessCore.Noop);
110
+ });
111
+ });
112
+
113
+ export {
114
+ stubResource,
115
+ }
116
+ /* Not a pure module */
@@ -15,6 +15,7 @@ let cmd: commandDef = {
15
15
  {fieldName: "categoryId", entity: "Category", plugin: Some("Catalog")},
16
16
  ],
17
17
  allowedStates: None,
18
+ targetState: None,
18
19
  apiExposed: Some(true),
19
20
  }
20
21
 
@@ -141,6 +142,10 @@ describe("encodePluginStructureEntry", () => {
141
142
  expect(json->String.includes("\"allowedStates\":null"))->toEqual(true)
142
143
  )
143
144
 
145
+ testSync("encodes None targetState as null (back-compat: resolver falls back to name-stem)", () =>
146
+ expect(json->String.includes("\"targetState\":null"))->toEqual(true)
147
+ )
148
+
144
149
  testSync("encodes the command's apiExposed flag (drives the event-graph API badge)", () =>
145
150
  expect(json->String.includes("\"apiExposed\":true"))->toEqual(true)
146
151
  )
@@ -252,6 +257,7 @@ describe("allowedStates + statusField populated", () => {
252
257
  mutationField: "Platform_Plugin_Activate",
253
258
  references: [],
254
259
  allowedStates: Some(["Inactive"]),
260
+ targetState: Some("Active"),
255
261
  apiExposed: Some(true),
256
262
  }
257
263
 
@@ -300,6 +306,10 @@ describe("allowedStates + statusField populated", () => {
300
306
  expect(json->String.includes("\"allowedStates\":[\"Inactive\"]"))->toEqual(true)
301
307
  )
302
308
 
309
+ testSync("round-trips a declared targetState as the status string", () =>
310
+ expect(json->String.includes("\"targetState\":\"Active\""))->toEqual(true)
311
+ )
312
+
303
313
  testSync("encodes populated statusField as the field name string", () =>
304
314
  expect(json->String.includes("\"statusField\":\"status\""))->toEqual(true)
305
315
  )