@reventlessdev/reventless-local 3.0.0-alpha.288 → 3.0.0-alpha.290

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 (30) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +10 -10
  3. package/src/adapter/Webhook/LocalWebhookRegistry.res +64 -0
  4. package/src/adapter/Webhook/LocalWebhookRegistry.res.mjs +52 -0
  5. package/src/components/InboundTranslationSlice_Builder.res +10 -1
  6. package/src/components/InboundTranslationSlice_Builder.res.mjs +9 -1
  7. package/tests/adapter/InboundTranslationMutationTest.res.mjs +6 -4
  8. package/tests/components/automationslice/AutomationRescheduleFixtures.res +0 -1
  9. package/tests/components/automationslice/AutomationRescheduleFixtures.res.mjs +0 -1
  10. package/tests/components/automationslice/AutomationScheduleFixtures.res +0 -1
  11. package/tests/components/automationslice/AutomationScheduleFixtures.res.mjs +0 -5
  12. package/tests/components/automationslice/AutomationSliceFixtures.res +0 -2
  13. package/tests/components/automationslice/AutomationSliceFixtures.res.mjs +0 -2
  14. package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res +0 -1
  15. package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res.mjs +0 -1
  16. package/tests/components/automationslice/AutomationSweepFixtures.res +0 -1
  17. package/tests/components/automationslice/AutomationSweepFixtures.res.mjs +0 -1
  18. package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res +0 -1
  19. package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res.mjs +0 -1
  20. package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res +2 -0
  21. package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res.mjs +25 -20
  22. package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res +3 -0
  23. package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res.mjs +3 -0
  24. package/tests/components/inboundtranslationslice/InboundTranslationWebhookTest.res +305 -0
  25. package/tests/components/inboundtranslationslice/InboundTranslationWebhookTest.res.mjs +473 -0
  26. package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res.mjs +0 -2
  27. package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res +0 -2
  28. package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res.mjs +0 -2
  29. package/tests/components/outboundtranslationslice/OutboundTranslationSlicePlatformFixtures.res +0 -1
  30. package/tests/components/outboundtranslationslice/OutboundTranslationSlicePlatformFixtures.res.mjs +0 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
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.290 (2026-10-17)
7
+
8
+ **Note:** Version bump only for package @reventlessdev/reventless-local
9
+
10
+
11
+
12
+
13
+
14
+ # 3.0.0-alpha.289 (2026-10-16)
15
+
16
+ * feat!(inbound): a translation slice can declare a signed webhook URL ([0ad6994](https://github.com/ReventlessDev/reventless-core/commit/0ad69949fcc91c2756c60ca8cb120dd468841d8b))
17
+
18
+ ### BREAKING CHANGES
19
+
20
+ * InboundTranslationSlice.Spec requires `endpoint`. Specs under
21
+ @@reventless.spec get it from the PPX (republish reventless-ppx with this
22
+ release); hand-written specs add `let endpoint = None`.
23
+
24
+
25
+
6
26
  # 3.0.0-alpha.288 (2026-10-16)
7
27
 
8
28
  **Note:** Version bump only for package @reventlessdev/reventless-local
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-local",
3
- "version": "3.0.0-alpha.288",
3
+ "version": "3.0.0-alpha.290",
4
4
  "description": "Local platform for Reventless (in-memory or SQLite backend, for development and testing without AWS)",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -34,24 +34,24 @@
34
34
  "graphql-yoga": "^5.21.0",
35
35
  "sury": "11.0.0",
36
36
  "ws": "^8.18.0",
37
- "@reventlessdev/rescript-effect": "1.0.0-alpha.0",
38
37
  "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.29",
38
+ "@reventlessdev/rescript-effect": "1.0.0-alpha.0",
39
39
  "@reventlessdev/rescript-jest": "1.0.0-alpha.12",
40
40
  "@reventlessdev/rescript-node": "2.0.0-alpha.22",
41
41
  "@reventlessdev/rescript-mcp-sdk": "1.0.0-alpha.23",
42
- "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.23",
43
- "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.145",
44
- "@reventlessdev/reventless-gwt": "1.0.0-alpha.245",
45
- "@reventlessdev/reventless-infra": "3.0.0-alpha.194",
46
- "@reventlessdev/reventless-core": "3.0.0-alpha.297",
47
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.161",
42
+ "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
43
+ "@reventlessdev/reventless-core": "3.0.0-alpha.299",
44
+ "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.147",
45
+ "@reventlessdev/reventless-gwt": "1.0.0-alpha.247",
46
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.163",
47
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.196",
48
48
  "@reventlessdev/reventless-seed": "1.0.0-alpha.34",
49
- "@reventlessdev/reventless-spec": "3.0.0-alpha.166"
49
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.168"
50
50
  },
51
51
  "devDependencies": {
52
52
  "rescript": "12.3.1",
53
53
  "sury-ppx": "11.0.0",
54
- "@reventlessdev/reventless-ppx": "1.0.0-alpha.102"
54
+ "@reventlessdev/reventless-ppx": "1.0.0-alpha.103"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "rescript": "^12.3.1"
@@ -0,0 +1,64 @@
1
+ // The local platform's webhook routes, served in process: no HTTP server, so a
2
+ // test (or a dev tool) posts a raw body with `post`, which runs the same
3
+ // signature check and dispatch as the AWS Function URL.
4
+
5
+ open ReventlessCore
6
+
7
+ let slices: dict<InboundTranslationSlice_Webhook.slice> = Dict.make()
8
+
9
+ /** Register a slice's route now, and bind its operations when they resolve. A
10
+ request posted before then waits for them rather than failing. Two slices may
11
+ not share a path. */
12
+ let register = (
13
+ ~route: InboundTranslationSlice_Webhook.route,
14
+ ~operations: Pulumi.Output.t<ReventlessInfra.InboundTranslationSlice.operations>,
15
+ ) => {
16
+ switch slices->Dict.get(route.path) {
17
+ | Some({route: taken}) =>
18
+ JsError.throwWithMessage(
19
+ `webhook path /${route.path} is declared by both ${taken.slice} and ${route.slice}`,
20
+ )
21
+ | None => ()
22
+ }
23
+ let bind = ref(_ => ())
24
+ let bound: promise<ReventlessInfra.InboundTranslationSlice.operations> = Promise.make((
25
+ resolve,
26
+ _,
27
+ ) => bind := resolve)
28
+ let _ = operations->Pulumi.Output.apply(ops => bind.contents(ops))
29
+ slices->Dict.set(
30
+ route.path,
31
+ {
32
+ route,
33
+ receive: async (input, ~caller) => await (await bound).receive(input, ~caller, ~door=Webhook),
34
+ refuse: async (~body, ~errorCode, error) =>
35
+ await (await bound).refuse(~body, ~errorCode, error),
36
+ },
37
+ )
38
+ }
39
+
40
+ /** Serve one request. Header names are matched case-insensitively. */
41
+ let post = (
42
+ ~path: string,
43
+ ~method: string="POST",
44
+ ~headers: dict<string>=Dict.make(),
45
+ ~secretOf=?,
46
+ ~nowSeconds=?,
47
+ body: string,
48
+ ): promise<InboundTranslationSlice_Webhook.response> =>
49
+ InboundTranslationSlice_Webhook.dispatch(
50
+ slices->Dict.valuesToArray,
51
+ ~secretOf?,
52
+ ~nowSeconds?,
53
+ {
54
+ method,
55
+ path,
56
+ headers: headers
57
+ ->Dict.toArray
58
+ ->Array.map(((name, value)) => (name->String.toLowerCase, value))
59
+ ->Dict.fromArray,
60
+ body,
61
+ },
62
+ )
63
+
64
+ let reset = () => slices->Dict.keysToArray->Array.forEach(path => slices->Dict.delete(path))
@@ -0,0 +1,52 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
4
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
5
+ import * as InboundTranslationSlice_Webhook$ReventlessCore from "@reventlessdev/reventless-core/src/components/InboundTranslationSlice/InboundTranslationSlice_Webhook.res.mjs";
6
+
7
+ let slices = {};
8
+
9
+ function register(route, operations) {
10
+ let match = slices[route.path];
11
+ if (match !== undefined) {
12
+ Stdlib_JsError.throwWithMessage(`webhook path /` + route.path + ` is declared by both ` + match.route.slice + ` and ` + route.slice);
13
+ }
14
+ let bind = {
15
+ contents: param => {}
16
+ };
17
+ let bound = new Promise((resolve, param) => {
18
+ bind.contents = resolve;
19
+ });
20
+ operations.apply(ops => bind.contents(ops));
21
+ slices[route.path] = {
22
+ route: route,
23
+ receive: async (input, caller) => await (await bound).receive(input, caller, "Webhook"),
24
+ refuse: async (body, errorCode, error) => await (await bound).refuse(body, errorCode, error)
25
+ };
26
+ }
27
+
28
+ function post(path, methodOpt, headersOpt, secretOf, nowSeconds, body) {
29
+ let method = methodOpt !== undefined ? methodOpt : "POST";
30
+ let headers = headersOpt !== undefined ? headersOpt : ({});
31
+ return InboundTranslationSlice_Webhook$ReventlessCore.dispatch(Object.values(slices), secretOf, nowSeconds, {
32
+ method: method,
33
+ path: path,
34
+ headers: Object.fromEntries(Object.entries(headers).map(param => [
35
+ param[0].toLowerCase(),
36
+ param[1]
37
+ ])),
38
+ body: body
39
+ });
40
+ }
41
+
42
+ function reset() {
43
+ Object.keys(slices).forEach(path => Stdlib_Dict.$$delete(slices, path));
44
+ }
45
+
46
+ export {
47
+ slices,
48
+ register,
49
+ post,
50
+ reset,
51
+ }
52
+ /* InboundTranslationSlice_Webhook-ReventlessCore Not a pure module */
@@ -26,7 +26,16 @@ module Make = (Bus: LocalBus.T) => {
26
26
  module Translation = Translation
27
27
  type component = Inner.component
28
28
  let queryDbName = Inner.queryDbName
29
- let make = Inner.make
29
+ let make = (~publishJsons, ~runtime=?, ~opts=?) => {
30
+ let component = Inner.make(~publishJsons, ~runtime?, ~opts?)
31
+ Spec.endpoint->Option.forEach(endpoint =>
32
+ LocalWebhookRegistry.register(
33
+ ~route=ReventlessCore.InboundTranslationSlice_Webhook.routeOf(~slice=Spec.name, endpoint),
34
+ ~operations=component->ReventlessCore.Component.operations,
35
+ )
36
+ )
37
+ component
38
+ }
30
39
  // Re-expose operations for test resolution
31
40
  let operations: component => Pulumi.Output.t<
32
41
  ReventlessCore.InboundTranslationSlice.operations,
@@ -1,9 +1,12 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
3
4
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
4
5
  import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
6
+ import * as LocalWebhookRegistry$ReventlessLocal from "../adapter/Webhook/LocalWebhookRegistry.res.mjs";
5
7
  import * as QueryDbResolvers_GraphQL$ReventlessLocal from "../adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs";
6
8
  import * as InboundTranslationSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs";
9
+ import * as InboundTranslationSlice_Webhook$ReventlessCore from "@reventlessdev/reventless-core/src/components/InboundTranslationSlice/InboundTranslationSlice_Webhook.res.mjs";
7
10
 
8
11
  function Make(Bus) {
9
12
  let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
@@ -21,12 +24,17 @@ function Make(Bus) {
21
24
  })(Api);
22
25
  let Make$1 = Spec => (Translation => {
23
26
  let Inner = CoreMaker.Make(Spec)(Translation);
27
+ let make = (publishJsons, runtime, opts) => {
28
+ let component = Inner.make(publishJsons, runtime, opts);
29
+ Stdlib_Option.forEach(Spec.endpoint, endpoint => LocalWebhookRegistry$ReventlessLocal.register(InboundTranslationSlice_Webhook$ReventlessCore.routeOf(Spec.name, endpoint), Component$ReventlessCore.operations(component)));
30
+ return component;
31
+ };
24
32
  return {
25
33
  Inner: Inner,
26
34
  Spec: Spec,
27
35
  Translation: Translation,
28
36
  queryDbName: Inner.queryDbName,
29
- make: Inner.make,
37
+ make: make,
30
38
  operations: Component$ReventlessCore.operations
31
39
  };
32
40
  });
@@ -29,7 +29,8 @@ let Callback = InboundTranslationSlice_Callback$ReventlessCore.Make({
29
29
  commandSchema: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.commandSchema,
30
30
  targetName: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.targetName,
31
31
  externalSystem: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.externalSystem,
32
- authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.authorizationOf
32
+ authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.authorizationOf,
33
+ endpoint: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.endpoint
33
34
  })(PaymentWebhookTranslation);
34
35
 
35
36
  let scope = "Payments";
@@ -106,7 +107,7 @@ globalThis.describe("InboundTranslationSlice mutation — response envelope", ()
106
107
  DomainGraphQL_Server$ReventlessLocal.setScope(scope);
107
108
  InboundTranslationResolvers_GraphQL$ReventlessLocal.register(fieldName, InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.externalInputSchema, "AllowAuthenticated", DomainGraphQL_Server$ReventlessLocal.asInterface);
108
109
  DomainGraphQL_Server$ReventlessLocal.resetScope();
109
- InboundTranslationResolvers_GraphQL$ReventlessLocal.bindReceive(fieldName, (inputJson, caller) => Callback.receive(publishJsons, inputJson, caller));
110
+ InboundTranslationResolvers_GraphQL$ReventlessLocal.bindReceive(fieldName, (inputJson, caller) => Callback.receive(publishJsons, inputJson, caller, undefined));
110
111
  });
111
112
  globalThis.test("a successful translation resolves as CommandAccepted, with no errors", async () => {
112
113
  let result = await runMutation("completed");
@@ -157,7 +158,8 @@ let CatalogFeedCallback = InboundTranslationSlice_Callback$ReventlessCore.Make({
157
158
  commandSchema: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.commandSchema,
158
159
  targetName: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.targetName,
159
160
  externalSystem: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.externalSystem,
160
- authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.authorizationOf
161
+ authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.authorizationOf,
162
+ endpoint: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.endpoint
161
163
  })(CatalogFeedTranslation);
162
164
 
163
165
  let feedField = "Catalog_CatalogFeed";
@@ -173,7 +175,7 @@ globalThis.describe("InboundTranslationSlice mutation — the door", () => {
173
175
  DomainGraphQL_Server$ReventlessLocal.setScope("Catalog");
174
176
  InboundTranslationResolvers_GraphQL$ReventlessLocal.register(feedField, InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.externalInputSchema, Dcb_Builder$ReventlessCore.inboundDoorPermission(InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.commandSchema, InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.authorizationOf), DomainGraphQL_Server$ReventlessLocal.asInterface);
175
177
  DomainGraphQL_Server$ReventlessLocal.resetScope();
176
- InboundTranslationResolvers_GraphQL$ReventlessLocal.bindReceive(feedField, (inputJson, caller) => CatalogFeedCallback.receive(publishJsons, inputJson, caller));
178
+ InboundTranslationResolvers_GraphQL$ReventlessLocal.bindReceive(feedField, (inputJson, caller) => CatalogFeedCallback.receive(publishJsons, inputJson, caller, undefined));
177
179
  });
178
180
  globalThis.test("a caller holding none of the commands' roles is refused", async () => {
179
181
  let node = payload(await runFeed(signedIn(["Ops"]), "product"));
@@ -26,7 +26,6 @@ module DigestSpec = {
26
26
  type command = SendDigest({recipientId: @s.matches(DcbTag.string) string})
27
27
 
28
28
  let maxRetries = 2
29
- let heartbeatInterval = 60
30
29
  let targetName = "SendDigest"
31
30
  let schedule = None
32
31
  }
@@ -69,7 +69,6 @@ let DigestSpec = {
69
69
  todoItemSchema: todoItemSchema,
70
70
  commandSchema: commandSchema,
71
71
  maxRetries: 2,
72
- heartbeatInterval: 60,
73
72
  targetName: "SendDigest",
74
73
  schedule: undefined,
75
74
  authorizationOf: authorizationOf,
@@ -16,7 +16,6 @@ module DemandReportSpec = {
16
16
  type command = RequestDemandReport({day: float})
17
17
 
18
18
  let maxRetries = 2
19
- let heartbeatInterval = 60
20
19
  let targetName = "ReportSettings"
21
20
  let schedule = Some(Schedule.Calendar({calendar: Daily({hour: 6, minute: 0})}))
22
21
  }
@@ -54,7 +54,6 @@ let DemandReportSpec = {
54
54
  todoItemSchema: todoItemSchema,
55
55
  commandSchema: commandSchema,
56
56
  maxRetries: 2,
57
- heartbeatInterval: 60,
58
57
  targetName: targetName,
59
58
  schedule: DemandReportSpec_schedule,
60
59
  authorizationOf: authorizationOf,
@@ -124,7 +123,6 @@ let UnscheduledSpec = {
124
123
  todoItemSchema: todoItemSchema,
125
124
  commandSchema: commandSchema,
126
125
  maxRetries: 2,
127
- heartbeatInterval: 60,
128
126
  targetName: targetName,
129
127
  authorizationOf: authorizationOf,
130
128
  commandTransition: commandTransition,
@@ -155,7 +153,6 @@ let FromClockUnscheduled = AutomationSlice$Reventless.Mapping.Make({
155
153
  todoItemSchema: todoItemSchema,
156
154
  commandSchema: commandSchema,
157
155
  maxRetries: 2,
158
- heartbeatInterval: 60,
159
156
  targetName: targetName,
160
157
  schedule: undefined
161
158
  })({
@@ -180,7 +177,6 @@ AutomationSlice$Reventless.Mappings.Make({
180
177
  todoItemSchema: todoItemSchema,
181
178
  commandSchema: commandSchema,
182
179
  maxRetries: 2,
183
- heartbeatInterval: 60,
184
180
  targetName: targetName,
185
181
  schedule: undefined
186
182
  });
@@ -208,7 +204,6 @@ let Unscheduled = AutomationSliceMaker.Make({
208
204
  todoItemSchema: todoItemSchema,
209
205
  commandSchema: commandSchema,
210
206
  maxRetries: 2,
211
- heartbeatInterval: 60,
212
207
  targetName: targetName,
213
208
  schedule: undefined
214
209
  })(UnscheduledAutomation);
@@ -39,7 +39,6 @@ module ShipOrderSpec = {
39
39
  type command = CreateShipment({orderId: @s.matches(Reventless.DcbTag.string) string})
40
40
 
41
41
  let maxRetries = 3
42
- let heartbeatInterval = 60
43
42
  let targetName = "CreateShipment"
44
43
  let schedule = None
45
44
  }
@@ -55,7 +54,6 @@ module SkipProcessSpec = {
55
54
  type command = Noop
56
55
 
57
56
  let maxRetries = 0
58
- let heartbeatInterval = 60
59
57
  let targetName = "Noop"
60
58
  let schedule = None
61
59
  }
@@ -75,7 +75,6 @@ let ShipOrderSpec = {
75
75
  todoItemSchema: todoItemSchema,
76
76
  commandSchema: commandSchema,
77
77
  maxRetries: 3,
78
- heartbeatInterval: 60,
79
78
  targetName: "CreateShipment",
80
79
  schedule: undefined,
81
80
  authorizationOf: authorizationOf,
@@ -107,7 +106,6 @@ let SkipProcessSpec = {
107
106
  todoItemSchema: todoItemSchema$1,
108
107
  commandSchema: commandSchema$1,
109
108
  maxRetries: 0,
110
- heartbeatInterval: 60,
111
109
  targetName: "Noop",
112
110
  schedule: undefined,
113
111
  authorizationOf: authorizationOf$1,
@@ -134,7 +134,6 @@ module AutoShipSpec = {
134
134
  type command = Ship({orderId: @s.matches(Reventless.DcbTag.string) string})
135
135
 
136
136
  let maxRetries = 3
137
- let heartbeatInterval = 60
138
137
  let targetName = "Ship"
139
138
  let schedule = None
140
139
  }
@@ -241,7 +241,6 @@ let AutoShipSpec = {
241
241
  todoItemSchema: todoItemSchema,
242
242
  commandSchema: commandSchema$2,
243
243
  maxRetries: 3,
244
- heartbeatInterval: 60,
245
244
  targetName: "Ship",
246
245
  schedule: undefined,
247
246
  authorizationOf: authorizationOf$2,
@@ -24,7 +24,6 @@ module CancelUnshippedSpec = {
24
24
  type command = CancelOrder({orderId: @s.matches(DcbTag.string) string})
25
25
 
26
26
  let maxRetries = 2
27
- let heartbeatInterval = 60
28
27
  let targetName = "CancelOrder"
29
28
  let schedule = None
30
29
  }
@@ -62,7 +62,6 @@ let CancelUnshippedSpec = {
62
62
  todoItemSchema: todoItemSchema,
63
63
  commandSchema: commandSchema,
64
64
  maxRetries: 2,
65
- heartbeatInterval: 60,
66
65
  targetName: "CancelOrder",
67
66
  schedule: undefined,
68
67
  authorizationOf: authorizationOf,
@@ -53,7 +53,6 @@ module AutoFulfillSpec = {
53
53
  })
54
54
 
55
55
  let maxRetries = 3
56
- let heartbeatInterval = 60
57
56
  let targetName = "MarkFulfilled"
58
57
  let schedule = None
59
58
  }
@@ -80,7 +80,6 @@ let AutoFulfillSpec = {
80
80
  todoItemSchema: todoItemSchema,
81
81
  commandSchema: commandSchema,
82
82
  maxRetries: 3,
83
- heartbeatInterval: 60,
84
83
  targetName: "MarkFulfilled",
85
84
  schedule: undefined,
86
85
  authorizationOf: authorizationOf,
@@ -215,6 +215,7 @@ describe("InboundTranslationSlice Callback", () => {
215
215
 
216
216
  let targetName = "ConfirmPayment"
217
217
  let externalSystem = None
218
+ let endpoint = None
218
219
 
219
220
  let translate = (input: externalInput) => Ok(
220
221
  input.items->Array.map(
@@ -285,6 +286,7 @@ describe("InboundTranslationSlice Callback", () => {
285
286
 
286
287
  let targetName = "ConfirmPayment"
287
288
  let externalSystem = None
289
+ let endpoint = None
288
290
 
289
291
  let translate = (_input: externalInput) => Ok([])
290
292
 
@@ -26,7 +26,8 @@ let Callback = InboundTranslationSlice_Callback$ReventlessCore.Make({
26
26
  commandSchema: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.commandSchema,
27
27
  targetName: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.targetName,
28
28
  externalSystem: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.externalSystem,
29
- authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.authorizationOf
29
+ authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.authorizationOf,
30
+ endpoint: InboundTranslationSliceFixtures$ReventlessLocal.PaymentWebhookSpec.endpoint
30
31
  })(PaymentWebhookTranslation);
31
32
 
32
33
  globalThis.describe("InboundTranslationSlice Callback", () => {
@@ -46,7 +47,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
46
47
  orderId: "ord-1",
47
48
  status: "completed"
48
49
  };
49
- let result = await Callback.receive(mockPublish, inputJson, undefined);
50
+ let result = await Callback.receive(mockPublish, inputJson, undefined, undefined);
50
51
  if (result.TAG === "Ok") {
51
52
  let match = result._0;
52
53
  globalThis.expect(match.targetIds).toEqual(["ord-1"]);
@@ -77,7 +78,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
77
78
  orderId: "ord-1",
78
79
  status: "pending"
79
80
  };
80
- let result = await Callback.receive(mockPublish, inputJson, undefined);
81
+ let result = await Callback.receive(mockPublish, inputJson, undefined, undefined);
81
82
  if (result.TAG === "Ok") {
82
83
  globalThis.expect(true).toBe(false);
83
84
  } else {
@@ -94,7 +95,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
94
95
  let inputJson = {
95
96
  unexpected: "data"
96
97
  };
97
- let result = await Callback.receive(mockPublish, inputJson, undefined);
98
+ let result = await Callback.receive(mockPublish, inputJson, undefined, undefined);
98
99
  if (result.TAG === "Ok") {
99
100
  globalThis.expect(true).toBe(false);
100
101
  } else {
@@ -112,7 +113,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
112
113
  orderId: "ord-1",
113
114
  status: "completed"
114
115
  };
115
- let result = await Callback.receive(failingPublish, inputJson, undefined);
116
+ let result = await Callback.receive(failingPublish, inputJson, undefined, undefined);
116
117
  if (result.TAG === "Ok") {
117
118
  globalThis.expect(true).toBe(false);
118
119
  } else {
@@ -131,7 +132,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
131
132
  paymentId: "pay-1",
132
133
  orderId: "ord-1",
133
134
  status: "completed"
134
- }, undefined);
135
+ }, undefined, undefined);
135
136
  let firstId = InboundTranslationSlice_Callback$ReventlessCore.requestIdOf(first);
136
137
  globalThis.expect(Stdlib_Option.isSome(InboundTranslationSlice_Callback$ReventlessCore.takeAuditRow(Callback.auditLog, firstId))).toBe(true);
137
138
  globalThis.expect(Object.entries(Callback.auditLog).length).toBe(0);
@@ -139,7 +140,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
139
140
  paymentId: "pay-1",
140
141
  orderId: "ord-1",
141
142
  status: "completed"
142
- }, undefined);
143
+ }, undefined, undefined);
143
144
  let secondId = InboundTranslationSlice_Callback$ReventlessCore.requestIdOf(second);
144
145
  globalThis.expect(secondId === firstId).toBe(false);
145
146
  globalThis.expect(Object.entries(Callback.auditLog).length).toBe(1);
@@ -152,7 +153,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
152
153
  paymentId: "pay-1",
153
154
  orderId: "ord-1",
154
155
  status: "pending"
155
- }, undefined);
156
+ }, undefined, undefined);
156
157
  let id = InboundTranslationSlice_Callback$ReventlessCore.requestIdOf(result);
157
158
  let row = InboundTranslationSlice_Callback$ReventlessCore.takeAuditRow(Callback.auditLog, id);
158
159
  if (row !== undefined) {
@@ -198,7 +199,8 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
198
199
  commandSchema: commandSchema,
199
200
  targetName: "ConfirmPayment",
200
201
  externalSystem: undefined,
201
- authorizationOf: authorizationOf
202
+ authorizationOf: authorizationOf,
203
+ endpoint: undefined
202
204
  })(MultiTranslation);
203
205
  let publishedCommands = {
204
206
  contents: []
@@ -214,7 +216,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
214
216
  "pay-3"
215
217
  ]
216
218
  };
217
- let result = await MultiCallback.receive(mockPublish, inputJson, undefined);
219
+ let result = await MultiCallback.receive(mockPublish, inputJson, undefined, undefined);
218
220
  if (result.TAG === "Ok") {
219
221
  let match = result._0;
220
222
  globalThis.expect(match.targetIds).toEqual([
@@ -260,7 +262,8 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
260
262
  commandSchema: commandSchema,
261
263
  targetName: "ConfirmPayment",
262
264
  externalSystem: undefined,
263
- authorizationOf: authorizationOf
265
+ authorizationOf: authorizationOf,
266
+ endpoint: undefined
264
267
  })(EmptyTranslation);
265
268
  let publishedCommands = {
266
269
  contents: []
@@ -271,7 +274,7 @@ globalThis.describe("InboundTranslationSlice Callback", () => {
271
274
  let inputJson = {
272
275
  orderId: "ord-1"
273
276
  };
274
- let result = await EmptyCallback.receive(mockPublish, inputJson, undefined);
277
+ let result = await EmptyCallback.receive(mockPublish, inputJson, undefined, undefined);
275
278
  if (result.TAG === "Ok") {
276
279
  let match = result._0;
277
280
  globalThis.expect(match.targetIds).toEqual([]);
@@ -300,7 +303,8 @@ let CatalogFeedCallback = InboundTranslationSlice_Callback$ReventlessCore.Make({
300
303
  commandSchema: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.commandSchema,
301
304
  targetName: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.targetName,
302
305
  externalSystem: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.externalSystem,
303
- authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.authorizationOf
306
+ authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.authorizationOf,
307
+ endpoint: InboundTranslationSliceFixtures$ReventlessLocal.CatalogFeedSpec.endpoint
304
308
  })(CatalogFeedTranslation);
305
309
 
306
310
  function caller(groups) {
@@ -336,7 +340,7 @@ globalThis.describe("receive checks each command against its own rule", () => {
336
340
  published.contents = [];
337
341
  });
338
342
  globalThis.test("a caller lacking one command's role is refused, and nothing is published", async () => {
339
- let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), caller(["Merchandiser"]));
343
+ let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), caller(["Merchandiser"]), undefined);
340
344
  if (result.TAG === "Ok") {
341
345
  globalThis.expect(true).toBe(false);
342
346
  } else {
@@ -351,22 +355,22 @@ globalThis.describe("receive checks each command against its own rule", () => {
351
355
  let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), caller([
352
356
  "Merchandiser",
353
357
  "Admin"
354
- ]));
358
+ ]), undefined);
355
359
  globalThis.expect(Stdlib_Result.isOk(result)).toBe(true);
356
360
  globalThis.expect(published.contents.length).toBe(2);
357
361
  });
358
362
  globalThis.test("the role one command needs is enough when the input yields only it", async () => {
359
- let result = await CatalogFeedCallback.receive(publish, catalogInput("product"), caller(["Merchandiser"]));
363
+ let result = await CatalogFeedCallback.receive(publish, catalogInput("product"), caller(["Merchandiser"]), undefined);
360
364
  globalThis.expect(Stdlib_Result.isOk(result)).toBe(true);
361
365
  globalThis.expect(published.contents.length).toBe(1);
362
366
  });
363
367
  globalThis.test("no caller is the platform itself, and publishes", async () => {
364
- let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), undefined);
368
+ let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), undefined, undefined);
365
369
  globalThis.expect(Stdlib_Result.isOk(result)).toBe(true);
366
370
  globalThis.expect(published.contents.length).toBe(2);
367
371
  });
368
372
  globalThis.test("a refusal answers CommandRejected with Forbidden", async () => {
369
- let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), Identity$Reventless.anonymous);
373
+ let result = await CatalogFeedCallback.receive(publish, catalogInput("both"), Identity$Reventless.anonymous, undefined);
370
374
  let match = InboundTranslationSlice_Callback$ReventlessCore.receiveResultToOutcome(result);
371
375
  switch (match.TAG) {
372
376
  case "Rejected" :
@@ -396,7 +400,8 @@ let NoteFeedCallback = InboundTranslationSlice_Callback$ReventlessCore.Make({
396
400
  commandSchema: InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.commandSchema,
397
401
  targetName: InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.targetName,
398
402
  externalSystem: InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.externalSystem,
399
- authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.authorizationOf
403
+ authorizationOf: InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.authorizationOf,
404
+ endpoint: InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.endpoint
400
405
  })(NoteFeedTranslation);
401
406
 
402
407
  globalThis.describe("receive encodes commands with their schema", () => {
@@ -410,7 +415,7 @@ globalThis.describe("receive encodes commands with their schema", () => {
410
415
  await NoteFeedCallback.receive(publish, Object.fromEntries([[
411
416
  "orderId",
412
417
  "ord-1"
413
- ]]), undefined);
418
+ ]]), undefined, undefined);
414
419
  let commandJson = published.contents[0].commandJson;
415
420
  let decoded = Sury.parseOrThrow(commandJson, InboundTranslationSliceFixtures$ReventlessLocal.NoteFeedSpec.commandSchema);
416
421
  globalThis.expect(decoded).toEqual({
@@ -28,6 +28,7 @@ module PaymentWebhookSpec = {
28
28
 
29
29
  let targetName = "ConfirmPayment"
30
30
  let externalSystem = None
31
+ let endpoint = None
31
32
 
32
33
  let translate = (input: externalInput) =>
33
34
  switch input.status {
@@ -52,6 +53,7 @@ module CatalogFeedSpec = {
52
53
 
53
54
  let targetName = "AddProduct"
54
55
  let externalSystem = None
56
+ let endpoint = None
55
57
 
56
58
  type role = Reventless.Role.name
57
59
  let merchandiser = Reventless.Role.make("Merchandiser")
@@ -89,6 +91,7 @@ module NoteFeedSpec = {
89
91
 
90
92
  let targetName = "Annotate"
91
93
  let externalSystem = None
94
+ let endpoint = None
92
95
 
93
96
  let translate = (input: externalInput) => Ok([
94
97
  (input.orderId, Annotate({orderId: input.orderId, note: None})),