@reventlessdev/reventless-aws 3.0.0-alpha.421 → 3.0.0-alpha.423

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,22 @@
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.423 (2026-11-05)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **aws:** a line logged outside its invocation's fiber still names the plugin ([8e6f553](https://github.com/ReventlessDev/reventless-core/commit/8e6f553cc8ac2e439862bf1f3636ac86a4a22137))
11
+ * **aws:** an extension's lines name its extension point once ([b448c59](https://github.com/ReventlessDev/reventless-core/commit/b448c5976feafd7d49ae8c04a67dcfbb72e973b5))
12
+
13
+
14
+ # 3.0.0-alpha.422 (2026-11-05)
15
+
16
+ **Note:** Version bump only for package @reventlessdev/reventless-aws
17
+
18
+
19
+
20
+
21
+
6
22
  # 3.0.0-alpha.421 (2026-11-02)
7
23
 
8
24
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-aws",
3
- "version": "3.0.0-alpha.421",
3
+ "version": "3.0.0-alpha.423",
4
4
  "description": "AWS adapters for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -23,18 +23,18 @@
23
23
  "uuid": "^13.0.0",
24
24
  "yaml": "^2.8.3",
25
25
  "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.39",
26
- "@reventlessdev/rescript-node": "2.0.0-alpha.26",
27
26
  "@reventlessdev/rescript-effect": "1.0.0-alpha.1",
28
- "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.39",
29
27
  "@reventlessdev/rescript-jest": "1.0.0-alpha.13",
30
- "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
28
+ "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.39",
29
+ "@reventlessdev/rescript-node": "2.0.0-alpha.26",
31
30
  "@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
31
+ "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
32
32
  "@reventlessdev/rescript-web": "1.0.0-alpha.8",
33
- "@reventlessdev/reventless-core": "3.0.0-alpha.328",
33
+ "@reventlessdev/reventless-core": "3.0.0-alpha.330",
34
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.223",
34
35
  "@reventlessdev/reventless-interop": "3.0.0-alpha.42",
35
- "@reventlessdev/reventless-spec": "3.0.0-alpha.193",
36
- "@reventlessdev/reventless-infra": "3.0.0-alpha.222",
37
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.192"
36
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.194",
37
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.194"
38
38
  },
39
39
  "devDependencies": {
40
40
  "rescript": "12.3.1",
@@ -218,7 +218,7 @@ async function buildHandler() {
218
218
  };
219
219
  const transformedMapping = extensionMappingMake(fullMapping);
220
220
  const mappingsModule = {
221
- name: ext.name,
221
+ name: Ops.mappingsName(ext),
222
222
  moduleUrl: ext.mappingsModule,
223
223
  mappings: [transformedMapping],
224
224
  };
@@ -561,6 +561,16 @@ let extensionPublishDicts = (names: queueUrlNames, ext: extensionConfig): extens
561
561
  {publishToAggregates: resolve(ext.aggregateNames, names.publishToAggregates)}
562
562
  }
563
563
 
564
+ /** The name an extension's mappings carry, as at deploy: its plugin's. The config names the
565
+ extension component, `<extension point>.<plugin>`, and `Extension_Operations` prefixes the
566
+ extension point itself. */
567
+ let mappingsName = (ext: extensionConfig): string => {
568
+ let prefix = ext.extensionPointName ++ "."
569
+ ext.name->String.startsWith(prefix)
570
+ ? ext.name->String.slice(~start=prefix->String.length, ~end=ext.name->String.length)
571
+ : ext.name
572
+ }
573
+
564
574
  let warnSkippedExtension = (ext: extensionConfig) =>
565
575
  logWarn(
566
576
  `extension '${ext.name}' missing module specifier(s); skipping. specModule=${ext.specModule}, mappingsModule=${ext.mappingsModule}, delegateModule=${ext.delegateModule}`,
@@ -445,6 +445,15 @@ function extensionPublishDicts(names, ext) {
445
445
  };
446
446
  }
447
447
 
448
+ function mappingsName(ext) {
449
+ let prefix = ext.extensionPointName + ".";
450
+ if (ext.name.startsWith(prefix)) {
451
+ return ext.name.slice(prefix.length, ext.name.length);
452
+ } else {
453
+ return ext.name;
454
+ }
455
+ }
456
+
448
457
  function warnSkippedExtension(ext) {
449
458
  HandlerFactoryHelpersMjs.log.warn(`extension '` + ext.name + `' missing module specifier(s); skipping. specModule=` + ext.specModule + `, mappingsModule=` + ext.mappingsModule + `, delegateModule=` + ext.delegateModule, {
450
459
  comp: "EventCollectorEntryPoint"
@@ -592,6 +601,7 @@ export {
592
601
  makePublishJsons,
593
602
  buildPublishToAggregates,
594
603
  extensionPublishDicts,
604
+ mappingsName,
595
605
  warnSkippedExtension,
596
606
  assetPath,
597
607
  loadPluginDefinition,
@@ -6,6 +6,7 @@ import {
6
6
  tag as requestContextTag,
7
7
  fromOptions as makeRequestContext,
8
8
  } from "@reventlessdev/reventless-core/src/RequestContext.res.mjs";
9
+ import { currentPluginName } from "@reventlessdev/reventless-spec/src/LogPrefix.res.mjs";
9
10
  import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
10
11
  import { DynamoDBDocumentClient, ScanCommand } from "@aws-sdk/lib-dynamodb";
11
12
 
@@ -120,6 +121,19 @@ export function runEffect(effect, opts = {}) {
120
121
  // Only annotate a redelivery. A constant "1" on every line is noise, and its
121
122
  // absence is what makes `filter retryCount > 1` a usable query.
122
123
  if (retryCount > 1) e = e.pipe(Effect.annotateLogs("retryCount", String(retryCount)));
124
+ // A line run on a fiber of its own (`->Effect.runSync`) misses these annotations, and the
125
+ // component→plugin registry is empty in a Lambda: it names its plugin from the ambient one,
126
+ // set for the invocation and restored after it.
127
+ if (resolvedPlugin) {
128
+ const inner = e;
129
+ e = Effect.suspend(() => {
130
+ const before = currentPluginName.contents;
131
+ currentPluginName.contents = resolvedPlugin;
132
+ return inner.pipe(
133
+ Effect.ensuring(Effect.sync(() => { currentPluginName.contents = before; })),
134
+ );
135
+ });
136
+ }
123
137
  return e
124
138
  .pipe(
125
139
  Effect.provideService(
@@ -226,3 +226,23 @@ describe("EventCollectorEntryPoint_Ops.parseHandlerConfig", () => {
226
226
  expect((c.extensions->Array.getUnsafe(0)).extensionPointName)->toBe("Ordering.Orders")
227
227
  })
228
228
  })
229
+
230
+ describe("EventCollectorEntryPoint_Ops.mappingsName", () => {
231
+ let ext = (~name): EventCollectorEntryPoint_Ops.extensionConfig => {
232
+ name,
233
+ specModule: "",
234
+ mappingsModule: "",
235
+ delegateModule: "",
236
+ extensionPointName: "Ordering.Orders",
237
+ aggregateNames: [],
238
+ }
239
+ // The component is `Extension(<point>.<name>)`: the point is not named twice.
240
+ testSync("is the plugin's name, as at deploy", () =>
241
+ expect(EventCollectorEntryPoint_Ops.mappingsName(ext(~name="Ordering.Orders.Catalog")))->toBe(
242
+ "Catalog",
243
+ )
244
+ )
245
+ testSync("keeps a name that does not start with its extension point", () =>
246
+ expect(EventCollectorEntryPoint_Ops.mappingsName(ext(~name="Catalog")))->toBe("Catalog")
247
+ )
248
+ })
@@ -315,6 +315,29 @@ globalThis.describe("EventCollectorEntryPoint_Ops.parseHandlerConfig", () => {
315
315
  });
316
316
  });
317
317
 
318
+ globalThis.describe("EventCollectorEntryPoint_Ops.mappingsName", () => {
319
+ globalThis.test("is the plugin's name, as at deploy", () => {
320
+ globalThis.expect(EventCollectorEntryPoint_Ops$ReventlessAws.mappingsName({
321
+ name: "Ordering.Orders.Catalog",
322
+ specModule: "",
323
+ mappingsModule: "",
324
+ delegateModule: "",
325
+ extensionPointName: "Ordering.Orders",
326
+ aggregateNames: []
327
+ })).toBe("Catalog");
328
+ });
329
+ globalThis.test("keeps a name that does not start with its extension point", () => {
330
+ globalThis.expect(EventCollectorEntryPoint_Ops$ReventlessAws.mappingsName({
331
+ name: "Catalog",
332
+ specModule: "",
333
+ mappingsModule: "",
334
+ delegateModule: "",
335
+ extensionPointName: "Ordering.Orders",
336
+ aggregateNames: []
337
+ })).toBe("Catalog");
338
+ });
339
+ });
340
+
318
341
  let project = EventCollectorEntryPoint_Ops$ReventlessAws.projectPluginRow;
319
342
 
320
343
  export {
@@ -200,6 +200,23 @@ describe("entry-point dispatch boundary", () => {
200
200
  },
201
201
  )
202
202
 
203
+ // A line run on a fiber of its own (`->Effect.runSync`) misses the invocation's annotations,
204
+ // and a Lambda's component→plugin registry is empty: the ambient plugin names it.
205
+ test(
206
+ "a line logged on a fiber of its own names the invocation's plugin",
207
+ async () => {
208
+ let before = Reventless.LogPrefix.currentPluginName.contents
209
+ let seen = await runEffect(
210
+ Effect.sync(
211
+ () => Reventless.LogPrefix.resolvePlugin(~comp="StateChangeSlice(PlaceOrder)", ()),
212
+ ),
213
+ {correlationId: "c", comp: "StateChangeSlice(PlaceOrder)", plugin: "Ordering"},
214
+ )
215
+ expect(seen)->Expect.toEqual(Some("Ordering"))
216
+ expect(Reventless.LogPrefix.currentPluginName.contents)->Expect.toEqual(before)
217
+ },
218
+ )
219
+
203
220
  // A constant "1" on every line is noise; its absence is what makes
204
221
  // `filter retryCount > 1` a usable CloudWatch query.
205
222
  test(
@@ -3,6 +3,7 @@
3
3
  import * as Effect from "@reventlessdev/rescript-effect/src/Effect.res.mjs";
4
4
  import * as Effect$1 from "effect/Effect";
5
5
  import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
6
+ import * as LogPrefix$Reventless from "@reventlessdev/reventless-spec/src/LogPrefix.res.mjs";
6
7
  import * as RequestContext$ReventlessCore from "@reventlessdev/reventless-core/src/RequestContext.res.mjs";
7
8
  import * as HandlerFactoryHelpersMjs from "@reventlessdev/reventless-aws/src/adapter/Runtime/HandlerFactoryHelpers.mjs";
8
9
 
@@ -112,6 +113,16 @@ globalThis.describe("entry-point dispatch boundary", () => {
112
113
  globalThis.expect(annotated$1["correlationId"]).toEqual("corr-1");
113
114
  globalThis.expect(annotated$1["requestId"]).toEqual("req-abc");
114
115
  });
116
+ globalThis.test("a line logged on a fiber of its own names the invocation's plugin", async () => {
117
+ let before = LogPrefix$Reventless.currentPluginName.contents;
118
+ let seen = await HandlerFactoryHelpersMjs.runEffect(Effect$1.sync(() => LogPrefix$Reventless.resolvePlugin("StateChangeSlice(PlaceOrder)", undefined)), {
119
+ correlationId: "c",
120
+ comp: "StateChangeSlice(PlaceOrder)",
121
+ plugin: "Ordering"
122
+ });
123
+ globalThis.expect(seen).toEqual("Ordering");
124
+ globalThis.expect(LogPrefix$Reventless.currentPluginName.contents).toEqual(before);
125
+ });
115
126
  globalThis.test("annotates retryCount only on a redelivery", async () => {
116
127
  let first = await HandlerFactoryHelpersMjs.runEffect(Effect$1.logAnnotations, {
117
128
  correlationId: "c",