@reventlessdev/reventless-aws 3.0.0-alpha.171 → 3.0.0-alpha.173
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 +6 -5
- package/rescript.json +2 -1
- package/src/Platform.res.mjs +5 -5
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res.mjs +1 -1
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +12 -6
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +17 -5
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Postgres_Runtime.res +26 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Postgres_Runtime.res.mjs +15 -0
- package/src/adapter/EventLog/EventLogStorage_Postgres_Runtime.res +23 -0
- package/src/adapter/EventLog/EventLogStorage_Postgres_Runtime.res.mjs +14 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +181 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res.mjs +135 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +64 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res.mjs +36 -0
- package/src/adapter/Postgres/PgConnection.res +169 -0
- package/src/adapter/Postgres/PgConnection.res.mjs +112 -0
- package/src/adapter/Postgres/PgRuntime.res +71 -0
- package/src/adapter/Postgres/PgRuntime.res.mjs +71 -0
- package/src/adapter/Runtime/AggregateEntryPoint.mjs +27 -9
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +3 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res.mjs +3 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res.mjs +1 -1
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +20 -6
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +1 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +1 -1
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs +52 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +38 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +20 -2
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res.mjs +1 -1
- package/src/components/Api/AppSync_Adapter.res +72 -8
- package/src/components/Api/AppSync_Adapter.res.mjs +45 -6
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +2 -2
- package/src/util/Util_AppSync_Caller.res +24 -4
- package/src/util/Util_AppSync_Caller.res.mjs +7 -4
- package/tests/AppSync_AdapterTest.res +140 -0
- package/tests/AppSync_AdapterTest.res.mjs +182 -6
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +7 -3
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res.mjs +18 -3
- package/tests/PgChangeFeedRelay_RuntimeTest.res +44 -0
- package/tests/PgChangeFeedRelay_RuntimeTest.res.mjs +70 -0
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +2 -1
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res.mjs +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
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.173 (2026-07-05)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **reventless-aws:** aggregate EventLog Postgres runtime + entry-point branch ([fd81ece](https://github.com/ReventlessDev/reventless-core/commit/fd81ece65c2bf6aebf227d74ec2d0f002833d351))
|
|
11
|
+
* **reventless-aws:** DCB EventLog Postgres runtime + entry-point branch (B2.1) ([a6b4f8d](https://github.com/ReventlessDev/reventless-core/commit/a6b4f8d34509ff7213273a1f71f31705b625ff40)), closes [#4](https://github.com/ReventlessDev/reventless-core/issues/4)
|
|
12
|
+
* **reventless-aws:** opt-in [@aws](https://github.com/aws)_iam dual-auth for deploy-time AppSync callers ([94037f1](https://github.com/ReventlessDev/reventless-core/commit/94037f17ae48a33415b02e8e7b178906be8b59a4))
|
|
13
|
+
* **reventless-aws:** Postgres change-feed relay deploy builder + Lambda VPC (B2.3a/b, C1) ([64d67f3](https://github.com/ReventlessDev/reventless-core/commit/64d67f3ecd2c42d59ba814d6d821683ae8c81612))
|
|
14
|
+
* **reventless-aws:** Postgres change-feed relay runtime (B2.2) ([9ccb601](https://github.com/ReventlessDev/reventless-core/commit/9ccb60192457e9da21869e0d1c98fe8dbfb42178))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# 3.0.0-alpha.172 (2026-07-05)
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* **reventless-aws:** sub-select CommandResult in AppSync mutation caller ([24cf37c](https://github.com/ReventlessDev/reventless-core/commit/24cf37cc537215b9523d1eac4a0f8ac6c610257d))
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* **postgres:** add reventless-postgres backend + local-platform integration ([6913200](https://github.com/ReventlessDev/reventless-core/commit/69132001f9271e832a5af33416acd5b645feaf47))
|
|
25
|
+
* **postgres:** cold-start pool foundation for AWS Postgres adapters ([b393449](https://github.com/ReventlessDev/reventless-core/commit/b393449769b6cd92abd03d2d5e7f564fe092938e))
|
|
26
|
+
* **reventless-aws:** add PgConnection component + wire reventless-postgres dep ([a403a62](https://github.com/ReventlessDev/reventless-core/commit/a403a6292381513cfe679a2f7a967fda0ab00c0e))
|
|
27
|
+
|
|
28
|
+
|
|
6
29
|
# 3.0.0-alpha.171 (2026-07-04)
|
|
7
30
|
|
|
8
31
|
**Note:** Version bump only for package @reventlessdev/reventless-aws
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-aws",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.173",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -11,13 +11,14 @@
|
|
|
11
11
|
"@reventlessdev/rescript-aws-sdk": "2.2.0-alpha.20",
|
|
12
12
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.5",
|
|
13
13
|
"@reventlessdev/rescript-effect": "0.1.0-alpha.24",
|
|
14
|
-
"@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.
|
|
14
|
+
"@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.45",
|
|
15
15
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.14",
|
|
16
16
|
"@reventlessdev/rescript-uuid": "1.1.0-alpha.13",
|
|
17
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.
|
|
17
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.140",
|
|
18
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.86",
|
|
18
19
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.23",
|
|
19
|
-
"@reventlessdev/reventless-
|
|
20
|
-
"@reventlessdev/reventless-
|
|
20
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.2",
|
|
21
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.64"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"rescript": "^12.3.0",
|
package/rescript.json
CHANGED
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"@reventlessdev/reventless-infra",
|
|
33
33
|
"@reventlessdev/reventless-interop",
|
|
34
34
|
"@reventlessdev/reventless-spec",
|
|
35
|
-
"@reventlessdev/reventless-core"
|
|
35
|
+
"@reventlessdev/reventless-core",
|
|
36
|
+
"@reventlessdev/reventless-postgres"
|
|
36
37
|
],
|
|
37
38
|
"compiler-flags": [],
|
|
38
39
|
"suffix": ".res.mjs"
|
package/src/Platform.res.mjs
CHANGED
|
@@ -598,7 +598,7 @@ function MakeWithConfig(Config) {
|
|
|
598
598
|
return Output$Pulumi.flatMap(targetApi, api => Output$Pulumi.flatMap(api.id, apiId => {
|
|
599
599
|
let runSchemaPush = () => writeAndScanFragments().then(async allPluginFragments => {
|
|
600
600
|
let baseFragment;
|
|
601
|
-
baseFragment = capturedDeployTarget === "Domain" && Config.splitApi ? emptyBaseFragment : AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin");
|
|
601
|
+
baseFragment = capturedDeployTarget === "Domain" && Config.splitApi ? emptyBaseFragment : AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin", undefined);
|
|
602
602
|
let sdl = GraphQL_Stitcher$ReventlessCore.stitch(baseFragment, allPluginFragments);
|
|
603
603
|
let currentHash = AppSync_Adapter$ReventlessAws.sha256Hex(sdl);
|
|
604
604
|
let storedHash = tableNameOpt !== undefined ? await readSchemaHash(tableNameOpt, apiId) : undefined;
|
|
@@ -653,7 +653,7 @@ function MakeWithConfig(Config) {
|
|
|
653
653
|
let hooks_preAdminResolversSchemaHook = adminBarrier => {
|
|
654
654
|
let match = splitApiOutputsRef.contents;
|
|
655
655
|
let targetApi = match !== undefined ? match.platformApi : domainApi;
|
|
656
|
-
let adminBaseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin");
|
|
656
|
+
let adminBaseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin", undefined);
|
|
657
657
|
let sdl = GraphQL_Stitcher$ReventlessCore.stitch(adminBaseFragment, []);
|
|
658
658
|
return Output$Pulumi.flatMap(Pulumi.all([
|
|
659
659
|
targetApi,
|
|
@@ -920,7 +920,7 @@ function MakeWithConfig(Config) {
|
|
|
920
920
|
return;
|
|
921
921
|
}
|
|
922
922
|
});
|
|
923
|
-
let baseFragment = Config.splitApi ? emptyBaseFragment : AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin");
|
|
923
|
+
let baseFragment = Config.splitApi ? emptyBaseFragment : AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin", undefined);
|
|
924
924
|
let sdl = GraphQL_Stitcher$ReventlessCore.stitch(baseFragment, fragments);
|
|
925
925
|
return await AppSync_Adapter$ReventlessAws.startSchemaCreationRetrying(AppSync_Adapter$ReventlessAws.getClient(), {
|
|
926
926
|
apiId: apiId,
|
|
@@ -1686,7 +1686,7 @@ function Make($star) {
|
|
|
1686
1686
|
return Output$Pulumi.flatMap(targetApi, api => Output$Pulumi.flatMap(api.id, apiId => {
|
|
1687
1687
|
let runSchemaPush = () => writeAndScanFragments().then(async allPluginFragments => {
|
|
1688
1688
|
let baseFragment;
|
|
1689
|
-
baseFragment = capturedDeployTarget === "Domain" ? emptyBaseFragment : AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(false), "Admin");
|
|
1689
|
+
baseFragment = capturedDeployTarget === "Domain" ? emptyBaseFragment : AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(false), "Admin", undefined);
|
|
1690
1690
|
let sdl = GraphQL_Stitcher$ReventlessCore.stitch(baseFragment, allPluginFragments);
|
|
1691
1691
|
let currentHash = AppSync_Adapter$ReventlessAws.sha256Hex(sdl);
|
|
1692
1692
|
let storedHash = tableNameOpt !== undefined ? await readSchemaHash(tableNameOpt, apiId) : undefined;
|
|
@@ -1741,7 +1741,7 @@ function Make($star) {
|
|
|
1741
1741
|
let hooks_preAdminResolversSchemaHook = adminBarrier => {
|
|
1742
1742
|
let match = splitApiOutputsRef.contents;
|
|
1743
1743
|
let targetApi = match !== undefined ? match.platformApi : domainApi;
|
|
1744
|
-
let adminBaseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(false), "Admin");
|
|
1744
|
+
let adminBaseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(false), "Admin", undefined);
|
|
1745
1745
|
let sdl = GraphQL_Stitcher$ReventlessCore.stitch(adminBaseFragment, []);
|
|
1746
1746
|
return Output$Pulumi.flatMap(Pulumi.all([
|
|
1747
1747
|
targetApi,
|
|
@@ -52,7 +52,7 @@ function make(name, referencesName, referencesDb, countsName, countsDb, param, s
|
|
|
52
52
|
let componentOpts = {
|
|
53
53
|
parent: componentOpts_parent
|
|
54
54
|
};
|
|
55
|
-
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(name, code, sourceCodeHash, envVars, 1024, 30, undefined, undefined, undefined, undefined, componentOpts);
|
|
55
|
+
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(name, code, sourceCodeHash, envVars, 1024, 30, undefined, undefined, undefined, undefined, undefined, componentOpts);
|
|
56
56
|
let lambda = runtime.parts.lambda;
|
|
57
57
|
let subscribe = (sourceName, source) => Util_EventSourceMapping$ReventlessAws.subscribe(undefined, lambda, name, sourceName, source, opts);
|
|
58
58
|
subscribe(referencesName, referencesStream);
|
|
@@ -595,7 +595,7 @@ let read = (table: resolvedTable, ~crossPartitionTagKeys: array<string>=[]) =>
|
|
|
595
595
|
//
|
|
596
596
|
// All Puts and Updates ride a single `TransactWriteItems` call — atomic by
|
|
597
597
|
// DynamoDB. Conflicts surface as `TransactionCanceledException` →
|
|
598
|
-
// `DynamoDb_Error.StaleState` → `Error(
|
|
598
|
+
// `DynamoDb_Error.StaleState` → `Error(DcbEventLog.Conflict)`.
|
|
599
599
|
|
|
600
600
|
let fenceSortKey = "FENCE"
|
|
601
601
|
|
|
@@ -861,9 +861,9 @@ let runTransactWrite = async (
|
|
|
861
861
|
->Effect.map(_ => Ok(basePosition))
|
|
862
862
|
->Effect.catchAll(err =>
|
|
863
863
|
switch err {
|
|
864
|
-
| DynamoDb_Error.StaleState(
|
|
864
|
+
| DynamoDb_Error.StaleState(_msg) => Effect.succeed(Error(ReventlessInfra.DcbEventLog.Conflict))
|
|
865
865
|
| Transient(msg) | Permanent(msg) =>
|
|
866
|
-
Effect.succeed(Error(`${errorPrefix}: ${msg}`))
|
|
866
|
+
Effect.succeed(Error(ReventlessInfra.DcbEventLog.StorageFailure(`${errorPrefix}: ${msg}`)))
|
|
867
867
|
}
|
|
868
868
|
)
|
|
869
869
|
->Effect.runPromise
|
|
@@ -886,7 +886,9 @@ let appendUnconditional = async (
|
|
|
886
886
|
Ok(generatePosition())
|
|
887
887
|
} else if totalItems > transactWriteItemsLimit {
|
|
888
888
|
Error(
|
|
889
|
-
|
|
889
|
+
ReventlessInfra.DcbEventLog.StorageFailure(
|
|
890
|
+
`DCB append: TransactWriteItems limit exceeded (${totalItems->Int.toString} > ${transactWriteItemsLimit->Int.toString}); reduce events or distinct tag values per command`,
|
|
891
|
+
),
|
|
890
892
|
)
|
|
891
893
|
} else {
|
|
892
894
|
let basePosition = generatePosition()
|
|
@@ -1211,7 +1213,9 @@ let appendConditional = async (
|
|
|
1211
1213
|
|
|
1212
1214
|
if queryTags->Array.length == 0 {
|
|
1213
1215
|
Error(
|
|
1214
|
-
|
|
1216
|
+
ReventlessInfra.DcbEventLog.StorageFailure(
|
|
1217
|
+
"DCB append: tagless conditions are not supported on DynamoDB — every queryItem must have at least one tag",
|
|
1218
|
+
),
|
|
1215
1219
|
)
|
|
1216
1220
|
} else {
|
|
1217
1221
|
let basePosition = generatePosition()
|
|
@@ -1219,7 +1223,9 @@ let appendConditional = async (
|
|
|
1219
1223
|
let totalItems = transactItems->Array.length
|
|
1220
1224
|
if totalItems > transactWriteItemsLimit {
|
|
1221
1225
|
Error(
|
|
1222
|
-
|
|
1226
|
+
ReventlessInfra.DcbEventLog.StorageFailure(
|
|
1227
|
+
`DCB append: TransactWriteItems limit exceeded (${totalItems->Int.toString} > ${transactWriteItemsLimit->Int.toString}); reduce events or distinct tag values per command`,
|
|
1228
|
+
),
|
|
1223
1229
|
)
|
|
1224
1230
|
} else {
|
|
1225
1231
|
let input: TransactWriteCommand.input = {transactItems: transactItems}
|
|
@@ -641,7 +641,7 @@ async function runTransactWrite(input, basePosition, errorPrefix) {
|
|
|
641
641
|
case "StaleState" :
|
|
642
642
|
return Effect$1.succeed({
|
|
643
643
|
TAG: "Error",
|
|
644
|
-
_0:
|
|
644
|
+
_0: "Conflict"
|
|
645
645
|
});
|
|
646
646
|
case "Transient" :
|
|
647
647
|
case "Permanent" :
|
|
@@ -649,7 +649,10 @@ async function runTransactWrite(input, basePosition, errorPrefix) {
|
|
|
649
649
|
}
|
|
650
650
|
return Effect$1.succeed({
|
|
651
651
|
TAG: "Error",
|
|
652
|
-
_0:
|
|
652
|
+
_0: {
|
|
653
|
+
TAG: "StorageFailure",
|
|
654
|
+
_0: errorPrefix + `: ` + err._0
|
|
655
|
+
}
|
|
653
656
|
});
|
|
654
657
|
}));
|
|
655
658
|
}
|
|
@@ -666,7 +669,10 @@ async function appendUnconditional(table, events, partitionTag) {
|
|
|
666
669
|
if (totalItems > 100) {
|
|
667
670
|
return {
|
|
668
671
|
TAG: "Error",
|
|
669
|
-
_0:
|
|
672
|
+
_0: {
|
|
673
|
+
TAG: "StorageFailure",
|
|
674
|
+
_0: `DCB append: TransactWriteItems limit exceeded (` + totalItems.toString() + ` > ` + (100).toString() + `); reduce events or distinct tag values per command`
|
|
675
|
+
}
|
|
670
676
|
};
|
|
671
677
|
}
|
|
672
678
|
let basePosition = generatePosition();
|
|
@@ -908,7 +914,10 @@ async function appendConditional(table, events, cond, partitionTag, crossPartiti
|
|
|
908
914
|
if (queryTags.length === 0) {
|
|
909
915
|
return {
|
|
910
916
|
TAG: "Error",
|
|
911
|
-
_0:
|
|
917
|
+
_0: {
|
|
918
|
+
TAG: "StorageFailure",
|
|
919
|
+
_0: "DCB append: tagless conditions are not supported on DynamoDB — every queryItem must have at least one tag"
|
|
920
|
+
}
|
|
912
921
|
};
|
|
913
922
|
}
|
|
914
923
|
let basePosition = generatePosition();
|
|
@@ -917,7 +926,10 @@ async function appendConditional(table, events, cond, partitionTag, crossPartiti
|
|
|
917
926
|
if (totalItems > 100) {
|
|
918
927
|
return {
|
|
919
928
|
TAG: "Error",
|
|
920
|
-
_0:
|
|
929
|
+
_0: {
|
|
930
|
+
TAG: "StorageFailure",
|
|
931
|
+
_0: `DCB append: TransactWriteItems limit exceeded (` + totalItems.toString() + ` > ` + (100).toString() + `); reduce events or distinct tag values per command`
|
|
932
|
+
}
|
|
921
933
|
};
|
|
922
934
|
}
|
|
923
935
|
let input = {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// AWS-side runtime DcbEventLog operations for the Postgres backend. The DCB
|
|
2
|
+
// analogue of EventLogStorage_Postgres_Runtime: turn a resolved connection config
|
|
3
|
+
// into the DCB operation set (`read`/`append`/`readStream`), bound to the
|
|
4
|
+
// container-lifetime pool from PgRuntime. Consumed by DcbCommandTopicEntryPoint.mjs
|
|
5
|
+
// (Postgres branch, selected when a PG_CONNECTION is present in HANDLER_CONFIG).
|
|
6
|
+
//
|
|
7
|
+
// The pg maker ignores `~indexes` / `~partitionTag` / `~crossPartitionTagKeys`
|
|
8
|
+
// (Postgres evaluates the real `DcbTag.query` atomically — no GSI routing), so
|
|
9
|
+
// they are passed empty here. `logName` is the `dcb_event.log_name` discriminator.
|
|
10
|
+
|
|
11
|
+
let opsFor = (
|
|
12
|
+
config: PgConnection.connectionConfig,
|
|
13
|
+
~logName: string,
|
|
14
|
+
~lockStrategy: ReventlessPostgres.DcbEventLogStorage_Postgres.lockStrategy=#AdvisoryLocks,
|
|
15
|
+
): ReventlessCore.DcbEventLog_Adapter.operations => {
|
|
16
|
+
let pool = PgRuntime.poolFor(config)
|
|
17
|
+
let (_name, ops, _storage) = ReventlessPostgres.DcbEventLogStorage_Postgres.makeStorage(
|
|
18
|
+
~pool,
|
|
19
|
+
~name=logName,
|
|
20
|
+
~indexes=[],
|
|
21
|
+
~partitionTag=(),
|
|
22
|
+
~opts=(),
|
|
23
|
+
~lockStrategy,
|
|
24
|
+
)
|
|
25
|
+
ops
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as PgRuntime$ReventlessAws from "../Postgres/PgRuntime.res.mjs";
|
|
4
|
+
import * as DcbEventLogStorage_Postgres$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/DcbEventLogStorage_Postgres.res.mjs";
|
|
5
|
+
|
|
6
|
+
function opsFor(config, logName, lockStrategyOpt) {
|
|
7
|
+
let lockStrategy = lockStrategyOpt !== undefined ? lockStrategyOpt : "AdvisoryLocks";
|
|
8
|
+
let pool = PgRuntime$ReventlessAws.poolFor(config);
|
|
9
|
+
return DcbEventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, logName, [], undefined, undefined, undefined, lockStrategy, undefined)[1];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
opsFor,
|
|
14
|
+
}
|
|
15
|
+
/* PgRuntime-ReventlessAws Not a pure module */
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// AWS-side runtime EventLog operations for the Postgres backend. Mirrors the
|
|
2
|
+
// role of EventLogStorage_DynamoDb_Runtime: turn a resolved connection config
|
|
3
|
+
// into the classic EventLog operation set, bound to the container-lifetime pool
|
|
4
|
+
// from PgRuntime. Consumed by AggregateEntryPoint.mjs (Postgres branch, selected
|
|
5
|
+
// when a PG_CONNECTION is present in HANDLER_CONFIG).
|
|
6
|
+
//
|
|
7
|
+
// Unlike DynamoDB (table-per-aggregate), all aggregates share the single
|
|
8
|
+
// Postgres `event_log` table, discriminated by `log_name`. `logName` is that
|
|
9
|
+
// per-aggregate discriminator — the same stable identifier the builder would
|
|
10
|
+
// otherwise use as the DynamoDB table name.
|
|
11
|
+
|
|
12
|
+
let opsFor = (
|
|
13
|
+
config: PgConnection.connectionConfig,
|
|
14
|
+
~logName: string,
|
|
15
|
+
): ReventlessCore.EventLog_Adapter.operations => {
|
|
16
|
+
let pool = PgRuntime.poolFor(config)
|
|
17
|
+
let (_name, ops, _storage) = ReventlessPostgres.EventLogStorage_Postgres.makeStorage(
|
|
18
|
+
~pool,
|
|
19
|
+
~name=logName,
|
|
20
|
+
~opts=(),
|
|
21
|
+
)
|
|
22
|
+
ops
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as PgRuntime$ReventlessAws from "../Postgres/PgRuntime.res.mjs";
|
|
4
|
+
import * as EventLogStorage_Postgres$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/EventLogStorage_Postgres.res.mjs";
|
|
5
|
+
|
|
6
|
+
function opsFor(config, logName) {
|
|
7
|
+
let pool = PgRuntime$ReventlessAws.poolFor(config);
|
|
8
|
+
return EventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, logName, undefined, undefined)[1];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
opsFor,
|
|
13
|
+
}
|
|
14
|
+
/* PgRuntime-ReventlessAws Not a pure module */
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// Deploy-time builder for the Postgres change-feed relay (B2.3b).
|
|
2
|
+
//
|
|
3
|
+
// Provisions a scheduled, in-VPC Lambda that drains each Postgres DCB log via
|
|
4
|
+
// PgChangeFeed and relays events to the plugin EventCollector SQS queue — which
|
|
5
|
+
// fans out to read-model projections, aggregate command topics, and the
|
|
6
|
+
// cross-plugin SNS EventTopic. The platform (D1, B2.3c) calls this with the set of
|
|
7
|
+
// Postgres-backed DCB logs and points the EventCollector's event source at the
|
|
8
|
+
// relay-fed queue.
|
|
9
|
+
//
|
|
10
|
+
// NOTE: EventBridge rate rules have a 1-minute floor, so v1 poll latency is
|
|
11
|
+
// >= 1 minute. Sub-minute latency needs a self-invoking loop / EventBridge
|
|
12
|
+
// Scheduler (follow-up) or the Fargate-LISTEN upgrade.
|
|
13
|
+
|
|
14
|
+
// One Postgres-backed DCB log to relay.
|
|
15
|
+
type relayLog = {
|
|
16
|
+
connectionConfig: Pulumi.Output.t<PgConnection.connectionConfig>,
|
|
17
|
+
/** dcb_event.log_name — also the DCB `event_log` discriminator. */
|
|
18
|
+
logName: string,
|
|
19
|
+
/** dcb_subscription checkpoint key for this relay. */
|
|
20
|
+
subscriber: string,
|
|
21
|
+
/** Plugin EventCollector SQS queue this log's events are relayed to. */
|
|
22
|
+
targetQueueUrl: Pulumi.Output.t<string>,
|
|
23
|
+
targetQueueArn: Pulumi.Output.t<string>,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ~securityGroupId: DB-access SG the relay Lambda attaches (PgConnection.securityGroupId).
|
|
27
|
+
// ~subnetIds: private subnets for the relay Lambda (PgConnection.subnetIds).
|
|
28
|
+
let make = (
|
|
29
|
+
~name: string,
|
|
30
|
+
~logs: array<relayLog>,
|
|
31
|
+
~securityGroupId: Pulumi.Output.t<string>,
|
|
32
|
+
~subnetIds: array<Pulumi.Input.t<string>>,
|
|
33
|
+
~intervalMinutes: int=1,
|
|
34
|
+
~opts=?,
|
|
35
|
+
): array<ReventlessInfra.Adapter.resource> => {
|
|
36
|
+
open PulumiAws
|
|
37
|
+
let customOpts =
|
|
38
|
+
opts->Option.map(ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions)
|
|
39
|
+
|
|
40
|
+
let {code, sourceCodeHash} = Util_Bundle.buildCodeArchive(
|
|
41
|
+
~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs",
|
|
42
|
+
~packageDirs=Dict.make(),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
// HANDLER_CONFIG.logs[], serialized from the deploy-time-resolved Outputs.
|
|
46
|
+
let logJsonOutputs = logs->Array.map(l =>
|
|
47
|
+
(l.connectionConfig, l.targetQueueUrl)
|
|
48
|
+
->Pulumi.Output.all2
|
|
49
|
+
->Pulumi.Output.apply(((cc, queueUrl)) => {
|
|
50
|
+
let pgConnectionJson =
|
|
51
|
+
[
|
|
52
|
+
("host", cc.host->JSON.Encode.string),
|
|
53
|
+
("port", cc.port->Int.toFloat->JSON.Encode.float),
|
|
54
|
+
("database", cc.database->JSON.Encode.string),
|
|
55
|
+
("username", cc.username->JSON.Encode.string),
|
|
56
|
+
("secretArn", cc.secretArn->JSON.Encode.string),
|
|
57
|
+
]
|
|
58
|
+
->Dict.fromArray
|
|
59
|
+
->JSON.Encode.object
|
|
60
|
+
[
|
|
61
|
+
("pgConnection", pgConnectionJson),
|
|
62
|
+
("logName", l.logName->JSON.Encode.string),
|
|
63
|
+
("subscriber", l.subscriber->JSON.Encode.string),
|
|
64
|
+
("targetQueueUrl", queueUrl->JSON.Encode.string),
|
|
65
|
+
]
|
|
66
|
+
->Dict.fromArray
|
|
67
|
+
->JSON.Encode.object
|
|
68
|
+
->JSON.stringify
|
|
69
|
+
})
|
|
70
|
+
)
|
|
71
|
+
let handlerConfigOutput =
|
|
72
|
+
Pulumi.Output.all(logJsonOutputs)->Pulumi.Output.apply(items =>
|
|
73
|
+
`{"logs":[${items->Array.join(",")}]}`
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
let envVars = Dict.fromArray([("HANDLER_CONFIG", handlerConfigOutput->Pulumi.Output.asInput)])
|
|
77
|
+
|
|
78
|
+
let vpcConfig =
|
|
79
|
+
securityGroupId
|
|
80
|
+
->Pulumi.Output.apply(sgId =>
|
|
81
|
+
(
|
|
82
|
+
{
|
|
83
|
+
Lambda.Function.subnetIds: subnetIds->Pulumi.Input.make,
|
|
84
|
+
securityGroupIds: [sgId->Pulumi.Input.make]->Pulumi.Input.make,
|
|
85
|
+
}: Lambda.Function.vpcConfig
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
->Pulumi.Output.asInput
|
|
89
|
+
|
|
90
|
+
let runtime = RuntimeEnvironment_Lambda.makeFromCodeAsset(
|
|
91
|
+
~name,
|
|
92
|
+
~code,
|
|
93
|
+
~sourceCodeHash,
|
|
94
|
+
~envVars,
|
|
95
|
+
~vpcConfig,
|
|
96
|
+
~opts?,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// IAM: GetSecretValue on each log's DB secret + SendMessage on each target queue.
|
|
100
|
+
let secretArns =
|
|
101
|
+
logs->Array.map(l => l.connectionConfig->Pulumi.Output.apply(cc => cc.secretArn))
|
|
102
|
+
let queueArns = logs->Array.map(l => l.targetQueueArn)
|
|
103
|
+
let _iam =
|
|
104
|
+
(Pulumi.Output.all(secretArns), Pulumi.Output.all(queueArns), runtime.parts.lambdaRole.id)
|
|
105
|
+
->Pulumi.Output.all3
|
|
106
|
+
->Pulumi.Output.apply(((secretArns, queueArns, roleId)) => {
|
|
107
|
+
open PulumiAws.PolicyDocument
|
|
108
|
+
let _ = PulumiAws.IAM.RolePolicy.make(
|
|
109
|
+
~name=`${name}RelayAccess`,
|
|
110
|
+
~args={
|
|
111
|
+
policy: PulumiAws.PolicyDocument.make(
|
|
112
|
+
~id=`${name}RelayAccessPolicy`,
|
|
113
|
+
~statements=[
|
|
114
|
+
{
|
|
115
|
+
sid: "AllowGetSecret",
|
|
116
|
+
effect: Allow,
|
|
117
|
+
actions: Action("secretsmanager:GetSecretValue"),
|
|
118
|
+
resources: Resources(secretArns),
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
sid: "AllowSendSqs",
|
|
122
|
+
effect: Allow,
|
|
123
|
+
actions: Action("sqs:SendMessage"),
|
|
124
|
+
resources: Resources(queueArns),
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
)
|
|
128
|
+
->PulumiAws.PolicyDocument.toJsonString
|
|
129
|
+
->Pulumi.Input.make,
|
|
130
|
+
role: roleId->Pulumi.Input.make,
|
|
131
|
+
},
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// Scheduled poll: EventRule (rate) → Permission → EventTarget.
|
|
136
|
+
let rule = {
|
|
137
|
+
open PulumiAws.Cloudwatch
|
|
138
|
+
EventRule.make(
|
|
139
|
+
~name=`${Pulumi.Pulumi.getStackName()}-${name}`,
|
|
140
|
+
~args={
|
|
141
|
+
description: "Poll Postgres DCB change feed and relay to EventCollector"->Pulumi.Input.make,
|
|
142
|
+
scheduleExpression: EventRule.ScheduleExpression.every(Minutes(intervalMinutes)),
|
|
143
|
+
},
|
|
144
|
+
~opts=?customOpts,
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let lambda = runtime.parts.lambda
|
|
149
|
+
let _wire =
|
|
150
|
+
(lambda->Pulumi.Output.flatMap(l => l.arn), lambda->Pulumi.Output.flatMap(l => l.name))
|
|
151
|
+
->Pulumi.Output.all2
|
|
152
|
+
->Pulumi.Output.apply(((lambdaArn, lambdaName)) => {
|
|
153
|
+
let _permission = PulumiAws.Lambda.Permission.make(
|
|
154
|
+
~name=`${name}SchedulePermission`,
|
|
155
|
+
~args={
|
|
156
|
+
action: "lambda:InvokeFunction",
|
|
157
|
+
function: lambdaName->Pulumi.Input.make,
|
|
158
|
+
principal: AWS.CloudwatchEventRule.principal,
|
|
159
|
+
},
|
|
160
|
+
~opts=?customOpts,
|
|
161
|
+
)
|
|
162
|
+
let _target = {
|
|
163
|
+
open PulumiAws.Cloudwatch
|
|
164
|
+
EventTarget.make(
|
|
165
|
+
~name,
|
|
166
|
+
~args={
|
|
167
|
+
rule: EventTarget.Rule.ofEventRule(rule),
|
|
168
|
+
arn: lambdaArn->Pulumi.Input.make,
|
|
169
|
+
},
|
|
170
|
+
~opts=?customOpts,
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
[
|
|
176
|
+
lambda
|
|
177
|
+
->Pulumi.Output.apply(l => l->Util_Lambda.toResource)
|
|
178
|
+
->ReventlessCore.Adapter.outputToResource,
|
|
179
|
+
rule->Util_Cloudwatch.EventRule.toResource,
|
|
180
|
+
]
|
|
181
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Aws from "@pulumi/aws";
|
|
4
|
+
import * as Output$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/Output.res.mjs";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
7
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
8
|
+
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
9
|
+
import * as Adapter$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Adapter.res.mjs";
|
|
10
|
+
import * as PolicyDocument$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/PolicyDocument.res.mjs";
|
|
11
|
+
import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
|
|
12
|
+
import * as Util_Lambda$ReventlessAws from "../../util/Util_Lambda.res.mjs";
|
|
13
|
+
import * as Util_Pulumi$ReventlessCore from "@reventlessdev/reventless-core/src/util/Util_Pulumi.res.mjs";
|
|
14
|
+
import * as Util_Cloudwatch$ReventlessAws from "../../util/Util_Cloudwatch.res.mjs";
|
|
15
|
+
import * as Cloudwatch_EventRule$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Cloudwatch/Cloudwatch_EventRule.res.mjs";
|
|
16
|
+
import * as Cloudwatch_EventTarget$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Cloudwatch/Cloudwatch_EventTarget.res.mjs";
|
|
17
|
+
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
18
|
+
|
|
19
|
+
function make(name, logs, securityGroupId, subnetIds, intervalMinutesOpt, opts) {
|
|
20
|
+
let intervalMinutes = intervalMinutesOpt !== undefined ? intervalMinutesOpt : 1;
|
|
21
|
+
let customOpts = Stdlib_Option.map(opts, Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions);
|
|
22
|
+
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs", {}, undefined);
|
|
23
|
+
let logJsonOutputs = logs.map(l => Pulumi.all([
|
|
24
|
+
l.connectionConfig,
|
|
25
|
+
l.targetQueueUrl
|
|
26
|
+
]).apply(param => {
|
|
27
|
+
let cc = param[0];
|
|
28
|
+
let pgConnectionJson = Object.fromEntries([
|
|
29
|
+
[
|
|
30
|
+
"host",
|
|
31
|
+
cc.host
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"port",
|
|
35
|
+
cc.port
|
|
36
|
+
],
|
|
37
|
+
[
|
|
38
|
+
"database",
|
|
39
|
+
cc.database
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"username",
|
|
43
|
+
cc.username
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
"secretArn",
|
|
47
|
+
cc.secretArn
|
|
48
|
+
]
|
|
49
|
+
]);
|
|
50
|
+
return JSON.stringify(Object.fromEntries([
|
|
51
|
+
[
|
|
52
|
+
"pgConnection",
|
|
53
|
+
pgConnectionJson
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
"logName",
|
|
57
|
+
l.logName
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
"subscriber",
|
|
61
|
+
l.subscriber
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
"targetQueueUrl",
|
|
65
|
+
param[1]
|
|
66
|
+
]
|
|
67
|
+
]));
|
|
68
|
+
}));
|
|
69
|
+
let handlerConfigOutput = Pulumi.all(logJsonOutputs).apply(items => `{"logs":[` + items.join(",") + `]}`);
|
|
70
|
+
let envVars = Object.fromEntries([[
|
|
71
|
+
"HANDLER_CONFIG",
|
|
72
|
+
handlerConfigOutput
|
|
73
|
+
]]);
|
|
74
|
+
let vpcConfig = securityGroupId.apply(sgId => ({
|
|
75
|
+
subnetIds: subnetIds,
|
|
76
|
+
securityGroupIds: [sgId]
|
|
77
|
+
}));
|
|
78
|
+
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(name, match.code, match.sourceCodeHash, envVars, undefined, undefined, undefined, undefined, undefined, undefined, vpcConfig, opts);
|
|
79
|
+
let secretArns = logs.map(l => l.connectionConfig.apply(cc => cc.secretArn));
|
|
80
|
+
let queueArns = logs.map(l => l.targetQueueArn);
|
|
81
|
+
Pulumi.all([
|
|
82
|
+
Pulumi.all(secretArns),
|
|
83
|
+
Pulumi.all(queueArns),
|
|
84
|
+
runtime.parts.lambdaRole.id
|
|
85
|
+
]).apply(param => {
|
|
86
|
+
new (Aws.iam.RolePolicy)(name + `RelayAccess`, {
|
|
87
|
+
policy: PolicyDocument$PulumiAws.toJsonString(PolicyDocument$PulumiAws.make(undefined, name + `RelayAccessPolicy`, [
|
|
88
|
+
{
|
|
89
|
+
Sid: "AllowGetSecret",
|
|
90
|
+
Effect: "Allow",
|
|
91
|
+
Action: "secretsmanager:GetSecretValue",
|
|
92
|
+
Resource: param[0]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
Sid: "AllowSendSqs",
|
|
96
|
+
Effect: "Allow",
|
|
97
|
+
Action: "sqs:SendMessage",
|
|
98
|
+
Resource: param[1]
|
|
99
|
+
}
|
|
100
|
+
])),
|
|
101
|
+
role: param[2]
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
let rule = new (Aws.cloudwatch.EventRule)(Pulumi.getStack() + `-` + name, {
|
|
105
|
+
description: "Poll Postgres DCB change feed and relay to EventCollector",
|
|
106
|
+
scheduleExpression: Primitive_option.some(Cloudwatch_EventRule$PulumiAws.ScheduleExpression.every({
|
|
107
|
+
TAG: "Minutes",
|
|
108
|
+
_0: intervalMinutes
|
|
109
|
+
}))
|
|
110
|
+
}, customOpts !== undefined ? Primitive_option.valFromOption(customOpts) : undefined);
|
|
111
|
+
let lambda = runtime.parts.lambda;
|
|
112
|
+
Pulumi.all([
|
|
113
|
+
Output$Pulumi.flatMap(lambda, l => l.arn),
|
|
114
|
+
Output$Pulumi.flatMap(lambda, l => l.name)
|
|
115
|
+
]).apply(param => {
|
|
116
|
+
new (Aws.lambda.Permission)(name + `SchedulePermission`, {
|
|
117
|
+
action: "lambda:InvokeFunction",
|
|
118
|
+
function: param[1],
|
|
119
|
+
principal: AWS$ReventlessAws.CloudwatchEventRule.principal
|
|
120
|
+
}, customOpts !== undefined ? Primitive_option.valFromOption(customOpts) : undefined);
|
|
121
|
+
new (Aws.cloudwatch.EventTarget)(name, {
|
|
122
|
+
rule: Cloudwatch_EventTarget$PulumiAws.Rule.ofEventRule(rule),
|
|
123
|
+
arn: param[0]
|
|
124
|
+
}, customOpts !== undefined ? Primitive_option.valFromOption(customOpts) : undefined);
|
|
125
|
+
});
|
|
126
|
+
return [
|
|
127
|
+
Adapter$ReventlessCore.outputToResource(lambda.apply(l => Util_Lambda$ReventlessAws.toResource(undefined, l))),
|
|
128
|
+
Util_Cloudwatch$ReventlessAws.EventRule.toResource(rule)
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export {
|
|
133
|
+
make,
|
|
134
|
+
}
|
|
135
|
+
/* @pulumi/aws Not a pure module */
|