@reventlessdev/reventless-infra 3.0.0-alpha.162 → 3.0.0-alpha.164

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 CHANGED
@@ -3,6 +3,34 @@
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.164 (2026-09-16)
7
+
8
+ * feat(spec)!: infer the DCB partition key per slice, and drop @partitionTag where inference agrees ([6c10161](https://github.com/ReventlessDev/reventless-core/commit/6c101611d438beea4bc9175ae8ea0ea1f6f7493b))
9
+ ### Features
10
+
11
+ * **core:** fail the build when an extension cannot find its slice's partition key ([cf2b093](https://github.com/ReventlessDev/reventless-core/commit/cf2b093dd5dc7cf9425cdac919cd3910fc4aeefd))
12
+ * **spec:** let a slice's chapter break a partition-key tie ([2b9ae77](https://github.com/ReventlessDev/reventless-core/commit/2b9ae77e98eb42177d2bdd4977bc62bb7c7911aa))
13
+
14
+ ### BREAKING CHANGES
15
+
16
+ * DcbTag.derivePartitionTag is removed; a boundary whose
17
+ partition cannot be inferred no longer deploys.
18
+
19
+
20
+
21
+ # 3.0.0-alpha.163 (2026-09-11)
22
+
23
+ * feat(spec)!: making a principal is a capability, so the provider is replaceable ([3e59b9b](https://github.com/ReventlessDev/reventless-core/commit/3e59b9b665cc7e4b6b6f156b63b1b6bd0c6181ca))
24
+
25
+ ### BREAKING CHANGES
26
+
27
+ * Capabilities.t gains an identityProvider member. A platform
28
+ that builds the record literally no longer compiles until it supplies one;
29
+ Capabilities.none.identityProvider is the refusing value to pass while no
30
+ backend exists. Code that spreads Capabilities.none is unaffected.
31
+
32
+
33
+
6
34
  # 3.0.0-alpha.162 (2026-09-09)
7
35
 
8
36
  **Note:** Version bump only for package @reventlessdev/reventless-infra
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-infra",
3
- "version": "3.0.0-alpha.162",
3
+ "version": "3.0.0-alpha.164",
4
4
  "description": "Infrastructure types for Reventless framework",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -17,8 +17,8 @@
17
17
  "sury-ppx": "11.0.0-rc.2",
18
18
  "uuid": "^13.0.0",
19
19
  "@reventlessdev/rescript-effect": "0.1.0-alpha.33",
20
- "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.20",
21
- "@reventlessdev/reventless-spec": "3.0.0-alpha.134",
20
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.136",
21
+ "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.21",
22
22
  "@reventlessdev/rescript-uuid": "2.0.0-alpha.0"
23
23
  },
24
24
  "devDependencies": {
@@ -40,6 +40,8 @@ module type T = {
40
40
  a cross-partition scalar command tag fans out into its own single-tag
41
41
  decision-read clause. */
42
42
  ~crossPartitionTagKeys: array<string>=?,
43
+ /** This slice's partition, as `Dcb_Builder` derives it for the whole boundary. */
44
+ ~partitionTag: Reventless.DcbTag.derivedPartitionTag=?,
43
45
  ~runtime: RuntimeHints.t=?,
44
46
  ~opts: Pulumi.ComponentResource.options=?,
45
47
  ) => component
@@ -10,7 +10,7 @@ type id = string
10
10
 
11
11
  /** What `mapIncomingEvent` can do with a published event: command the wrapped
12
12
  aggregate or slice, command the extension point, forward, or run a directive.
13
- The slice forms take no id — the FIFO group comes from `@partitionTag`. */
13
+ The slice forms take no id — the FIFO group is the slice's partition key. */
14
14
  type incomingCommandAction<'aggregateCommand, 'extensionPointCommand, 'directive> =
15
15
  | PublishAggregateCommand(id, 'aggregateCommand)
16
16
  | PublishAggregateCommandAsync(promise<(id, 'aggregateCommand)>)
@@ -182,6 +182,11 @@ module type T = {
182
182
  let delegateCommandNames: array<string>
183
183
  let delegateEventNames: array<string>
184
184
 
185
+ /** The partition key slice commands to the Delegate are grouped by, inferred
186
+ from the Delegate alone — or why it cannot tell. Checked at assembly against
187
+ the plugin's own derivation, which sees what the slice reads. */
188
+ let delegatePartition: unit => result<Reventless.DcbTag.derivedPartitionTag, string>
189
+
185
190
  let mapIncomingEvent: (
186
191
  Reventless.Message.event'<string, ExtensionPoint.event>,
187
192
  pluginDefinition,
@@ -216,28 +221,35 @@ module Make = (MappingImpl: Mapping): (
216
221
  let acceptedTags = Reventless.DcbTag.extractAllVariantNames(Delegate.eventSchema)
217
222
  let delegateEventNames = acceptedTags
218
223
 
219
- // Partition tag for `PublishStateChangeSliceCommand*`. Throws when the Delegate
220
- // declares none — an Aggregate, where `PublishAggregateCommand` is the right form.
224
+ // Partition for `PublishStateChangeSliceCommand*`, which becomes the command's
225
+ // FIFO group. Inferred from the Delegate alone: its consumed arms are not in
226
+ // view, so a slice whose key only they decide needs `@partitionTag`. Throws
227
+ // when unresolved — an Aggregate, where `PublishAggregateCommand` is right.
221
228
  let derivedPartitionTagLazy = ref(None)
222
229
  let getDerivedPartitionTag = () =>
223
230
  switch derivedPartitionTagLazy.contents {
224
231
  | Some(d) => d
225
232
  | None =>
226
- let d = Reventless.DcbTag.derivePartitionTag([
227
- (Delegate.name, Delegate.moduleUrl, Delegate.commandSchema->S.castToUnknown),
228
- ])
233
+ let d = Reventless.DcbTag.deriveSlicePartition({
234
+ name: Delegate.name,
235
+ commandSchema: Delegate.commandSchema->S.castToUnknown,
236
+ consumedEventSchema: S.unknown,
237
+ eventSchema: Delegate.eventSchema->S.castToUnknown,
238
+ moduleUrl: Delegate.moduleUrl,
239
+ })
229
240
  derivedPartitionTagLazy := Some(d)
230
241
  d
231
242
  }
232
- let derivePartitionId = (targetCmd: Delegate.command): string =>
243
+ let delegatePartition = () =>
233
244
  switch getDerivedPartitionTag() {
234
- | Simple(pt) =>
235
- let tags = Reventless.DcbTag.extractTags(Delegate.commandSchema, targetCmd)
236
- Reventless.DcbTag.getPartitionTagValue([{tags: tags}], pt)->Option.getOr("")
237
- | Composite(spec) =>
238
- let tags = Reventless.DcbTag.extractTags(Delegate.commandSchema, targetCmd)
239
- Reventless.DcbTag.getCompositePartitionKeyValue(tags, spec)
245
+ | tag => Ok(tag)
246
+ | exception JsExn(err) => Error(err->JsExn.message->Option.getOr("no partition key"))
240
247
  }
248
+ let derivePartitionId = (targetCmd: Delegate.command): string =>
249
+ Reventless.DcbTag.extractTags(
250
+ Delegate.commandSchema,
251
+ targetCmd,
252
+ )->Reventless.DcbTag.partitionValueOfTags(getDerivedPartitionTag())
241
253
 
242
254
  // `comp` as an Effect log annotation; EffectLogger.install lifts it to the
243
255
  // top-level JSON field.
@@ -3,12 +3,14 @@
3
3
  import * as Sury from "sury";
4
4
  import * as Uuid from "uuid";
5
5
  import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
6
+ import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
6
7
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
8
  import * as Effect from "effect/Effect";
8
9
  import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
9
10
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
10
11
  import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
11
12
  import * as AnsiStyle$Reventless from "@reventlessdev/reventless-spec/src/AnsiStyle.res.mjs";
13
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
12
14
  import * as PluginExtensionPointSpec$ReventlessInfra from "./PluginExtensionPointSpec.res.mjs";
13
15
 
14
16
  let schema = Sury.string;
@@ -65,25 +67,36 @@ function Make(MappingImpl) {
65
67
  if (d !== undefined) {
66
68
  return d;
67
69
  }
68
- let d$1 = DcbTag$Reventless.derivePartitionTag([[
69
- Delegate.name,
70
- Delegate.moduleUrl,
71
- Delegate.commandSchema
72
- ]]);
70
+ let d$1 = DcbTag$Reventless.deriveSlicePartition({
71
+ name: Delegate.name,
72
+ commandSchema: Delegate.commandSchema,
73
+ consumedEventSchema: Sury.unknown,
74
+ eventSchema: Delegate.eventSchema,
75
+ moduleUrl: Delegate.moduleUrl
76
+ });
73
77
  derivedPartitionTagLazy.contents = d$1;
74
78
  return d$1;
75
79
  };
76
- let derivePartitionId = targetCmd => {
77
- let pt = getDerivedPartitionTag();
78
- if (pt.TAG === "Simple") {
79
- let tags = DcbTag$Reventless.extractTags(Delegate.commandSchema, targetCmd);
80
- return Stdlib_Option.getOr(DcbTag$Reventless.getPartitionTagValue([{
81
- tags: tags
82
- }], pt._0), "");
80
+ let delegatePartition = () => {
81
+ let tag;
82
+ try {
83
+ tag = getDerivedPartitionTag();
84
+ } catch (raw_err) {
85
+ let err = Primitive_exceptions.internalToException(raw_err);
86
+ if (err.RE_EXN_ID === "JsExn") {
87
+ return {
88
+ TAG: "Error",
89
+ _0: Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), "no partition key")
90
+ };
91
+ }
92
+ throw err;
83
93
  }
84
- let tags$1 = DcbTag$Reventless.extractTags(Delegate.commandSchema, targetCmd);
85
- return DcbTag$Reventless.getCompositePartitionKeyValue(tags$1, pt._0);
94
+ return {
95
+ TAG: "Ok",
96
+ _0: tag
97
+ };
86
98
  };
99
+ let derivePartitionId = targetCmd => DcbTag$Reventless.partitionValueOfTags(DcbTag$Reventless.extractTags(Delegate.commandSchema, targetCmd), getDerivedPartitionTag());
87
100
  let compLog = (comp, msg) => Effect.runSync(Effect.annotateLogs(Effect.logInfo(msg), "comp", comp));
88
101
  let encodeMeta = (meta, service) => {
89
102
  let newrecord = {...meta};
@@ -261,6 +274,7 @@ function Make(MappingImpl) {
261
274
  issuedCommands: MappingImpl.issuedCommands,
262
275
  delegateCommandNames: delegateCommandNames,
263
276
  delegateEventNames: acceptedTags,
277
+ delegatePartition: delegatePartition,
264
278
  mapIncomingEvent: mapIncomingEvent,
265
279
  mapOutgoingEvent: mapOutgoingEvent
266
280
  };
@@ -109,6 +109,7 @@ type capability =
109
109
  | ObjectStore({plugin: string, store: string})
110
110
  | Geocoding
111
111
  | Messaging
112
+ | IdentityProvider
112
113
 
113
114
  // A provisioned geocoding place index, as returned by the framework's geocoding
114
115
  // capability helper. A record rather than a bare name so the handle can grow