@reventlessdev/reventless-aws 3.0.0-alpha.343 → 3.0.0-alpha.345
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 +15 -0
- package/package.json +11 -11
- package/scripts/ProvisionIdentity.res +8 -3
- package/src/Platform.res +327 -328
- package/src/Platform.res.mjs +4 -2
- package/src/Platform_Casts.res +13 -4
- package/src/adapter/Api/AppSyncEventsSigner_Ops.res +8 -4
- package/src/adapter/Api/AppSync_EventsApi.res +12 -14
- package/src/adapter/Api/AppSync_Resolver_Native.res +3 -4
- package/src/adapter/Api/AppSync_Resolver_Retrying.res +78 -70
- package/src/adapter/Api/AppSync_SourceApiAssociation_Retrying.res +11 -8
- package/src/adapter/Api/Platform_AdminScan_Ops.res +15 -14
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +10 -2
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +40 -50
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +39 -32
- package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +5 -2
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +0 -1
- package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +1 -4
- package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +5 -2
- package/src/adapter/Auth/Auth_Cognito.res +3 -9
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +1 -4
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +3 -1
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +1 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +7 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +6 -1
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +7 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +24 -18
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +9 -4
- package/src/adapter/CommandTopic/CommandTopicRegistry.res +1 -4
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +15 -15
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +9 -5
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +179 -213
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +5 -5
- package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +6 -2
- package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +14 -7
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +14 -7
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +6 -3
- package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +6 -1
- package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +13 -17
- package/src/adapter/EventLog/EventLogStorage_Postgres.res +7 -4
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +12 -7
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +4 -2
- package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +3 -2
- package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +20 -12
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +21 -9
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -3
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +6 -3
- package/src/adapter/Mcp/MCP_Lambda.res +31 -46
- package/src/adapter/Messaging/Messaging_Ses_Backend.res +11 -7
- package/src/adapter/Messaging/Messaging_Ses_Backend.res.mjs +2 -4
- package/src/adapter/Monitoring/Monitoring_CloudWatch.res +16 -16
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +5 -10
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +4 -2
- package/src/adapter/Postgres/PgConnection.res +6 -5
- package/src/adapter/Postgres/PgMigration_Builder.res +4 -8
- package/src/adapter/Postgres/PgRuntime.res +4 -7
- package/src/adapter/QueryDb/PgQueryResolver_Builder.res +9 -11
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +22 -21
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +114 -111
- package/src/adapter/QueryDb/QueryDbResolvers_Lambda.res +1 -7
- package/src/adapter/QueryDb/QueryDbStorage.res +4 -2
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +23 -24
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +8 -2
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +71 -73
- package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +5 -2
- package/src/adapter/QueryDb/QueryInterceptor_Provisioning.res +1 -4
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +8 -2
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +73 -81
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +72 -78
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +44 -67
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +44 -67
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +53 -82
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +47 -77
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +18 -11
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -97
- package/src/adapter/Runtime/CounterEntryPoint_Ops.res +2 -7
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -10
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +24 -15
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +17 -37
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +31 -57
- package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +18 -24
- package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -5
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +4 -3
- package/src/adapter/Runtime/HeartbeatEntryPoint.res +0 -1
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +4 -2
- package/src/adapter/Runtime/PgMigrationEntryPoint.res +0 -1
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +3 -2
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -2
- package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +4 -5
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +22 -10
- package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +8 -2
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +14 -31
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +16 -17
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +10 -9
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +46 -52
- package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +36 -41
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +31 -37
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +6 -7
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +4 -6
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +2 -6
- package/src/adapter/StateTopic/StateTopic_AppSync.res +21 -16
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +36 -32
- package/src/adapter/Task/TaskBucket_S3.res +6 -1
- package/src/adapter/Upload/Upload_Claim_S3.res +17 -20
- package/src/adapter/Upload/Upload_Claim_S3_Ops.res +5 -2
- package/src/adapter/Upload/Upload_Presign_S3.res +51 -49
- package/src/capability/Capability_Geocoding_AwsLocation.res +4 -1
- package/src/capability/Capability_Messaging.res +4 -5
- package/src/capability/Capability_Messaging_Ses.res +3 -1
- package/src/capability/Capability_ObjectStore_S3.res +1 -7
- package/src/components/Api/AppSync_Adapter.res +28 -41
- package/src/components/Api/AppSync_SdlDecorate.res +38 -30
- package/src/components/AutomationSlice_Builder.res +6 -4
- package/src/components/ExtensionPoint_Builder.res +9 -10
- package/src/components/InboundTranslationSlice_Builder.res +7 -8
- package/src/components/OutboundTranslationSlice_Builder.res +14 -8
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
- package/src/components/SideEffectHandler_Single.res +4 -4
- package/src/components/StateViewSlice_Builder.res +6 -4
- package/src/components/StateViewSlice_Builder_Stream.res +6 -4
- package/src/components/Task_Builder_PerBucket.res +10 -11
- package/src/plugin/cloner/ClonerRunner_Fargate.res +3 -10
- package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +1 -4
- package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +5 -5
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +19 -21
- package/src/plugin/runtime/PluginRuntime_Builder.res +167 -188
- package/src/plugin/runtime/Util_PluginMessage_Runtime.res +6 -5
- package/src/plugin/stack/Plugin_Stack.res +104 -103
- package/src/util/Util_AlarmSpec.res +2 -1
- package/src/util/Util_AppSync.res +8 -2
- package/src/util/Util_AppSync_Caller.res +15 -14
- package/src/util/Util_Bundle.res +144 -67
- package/src/util/Util_Bundle.res.mjs +64 -13
- package/src/util/Util_CognitoGroupUser_Runtime.res +32 -34
- package/src/util/Util_Cognito_Runtime.res +11 -7
- package/src/util/Util_DeadLetterQueue.res +12 -2
- package/src/util/Util_DynamoDb.res +5 -3
- package/src/util/Util_DynamoDbStream.res +7 -3
- package/src/util/Util_DynamoDbStream_Runtime.res +1 -2
- package/src/util/Util_DynamoDb_Runtime.res +23 -41
- package/src/util/Util_HostUiDomain.res +6 -1
- package/src/util/Util_Kinesis_Runtime.res +10 -11
- package/src/util/Util_Lambda.res +12 -5
- package/src/util/Util_LambdaEnvBudget.res +5 -5
- package/src/util/Util_LambdaLogging.res +1 -2
- package/src/util/Util_LogGroup_Adopting.res +1 -4
- package/src/util/Util_ResourceNaming.res +1 -2
- package/src/util/Util_SNS.res +8 -3
- package/src/util/Util_SNS_FIFO.res +1 -1
- package/src/util/Util_SNS_Runtime.res +11 -10
- package/src/util/Util_SQS.res +4 -2
- package/src/util/Util_SQS_FIFO.res +5 -2
- package/src/util/Util_SQS_Runtime.res +37 -36
- package/src/util/Util_ShellConfig.res +3 -2
- package/src/util/Util_StaticBundle.res +1 -3
- package/src/util/Util_StoreLayout.res +4 -1
- package/tests/AWS_TagsTest.res +16 -5
- package/tests/AppSyncEventsSigner_OpsTest.res +11 -2
- package/tests/AppSync_AdapterTest.res +203 -224
- package/tests/AppSync_Resolver_RetryingTest.res +64 -44
- package/tests/AppSync_RetirementNarrowingTest.res +59 -46
- package/tests/AppSync_SdlDecorateTest.res +22 -20
- package/tests/AppSync_SourceApiAssociation_RetryingTest.res +40 -22
- package/tests/Auth_ActiveRolePoolAttachmentTest.res +114 -107
- package/tests/Auth_ActiveRoleStoreTest.res +12 -9
- package/tests/Auth_ActiveRoleStore_SchemaTest.res +2 -1
- package/tests/Auth_ActiveRoleTrigger_OpsTest.res +20 -16
- package/tests/Auth_CognitoTest.res +31 -46
- package/tests/AutomationSliceEntryPoint_OpsTest.res +69 -67
- package/tests/BakeConvergenceTest.res +22 -25
- package/tests/Capability_MessagingTest.res +28 -12
- package/tests/CommandTopicQueuePolicyTest.res +1 -2
- package/tests/CounterEntryPoint_OpsTest.res +3 -7
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +306 -210
- package/tests/EventCollectorConnectLambdaPreviewTest.res +14 -7
- package/tests/EventCollectorEntryPoint_OpsTest.res +12 -4
- package/tests/EventCollectorPluginDefinitionAssetTest.res +18 -11
- package/tests/EventCollectorReadyGateTest.res +5 -4
- package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -2
- package/tests/EventMapperEntryPoint_OpsTest.res +1 -3
- package/tests/ExtensionPointEntryPoint_OpsTest.res +1 -4
- package/tests/HandlerFactoryDispatchTest.res +97 -70
- package/tests/MCP_LambdaTest.res +16 -27
- package/tests/PgChangeFeedRelay_IntegrationTest.res +123 -93
- package/tests/PgChangeFeedRelay_RuntimeTest.res +13 -10
- package/tests/PgMigrationEntryPoint_IntegrationTest.res +0 -1
- package/tests/PgPipeline_IntegrationTest.res +80 -66
- package/tests/PgQueryDbUnion_IntegrationTest.res +1 -2
- package/tests/PgQueryResolverEntryPoint_OpsTest.res +2 -6
- package/tests/PgQueryResolver_LambdaTest.res +41 -24
- package/tests/Platform_AdminScan_OpsTest.res +4 -1
- package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +137 -129
- package/tests/ProjectionEntryPoint_DisplayNameTest.res +7 -3
- package/tests/ProjectionEntryPoint_UnionStampTest.res +3 -2
- package/tests/ProvisionIdentityTest.res +2 -6
- package/tests/QueryDbOwnerIndexTableTest.res +6 -4
- package/tests/QueryDbResolvers_AppSyncTest.res +23 -16
- package/tests/QueryInterceptor_LambdaTest.res +11 -13
- package/tests/ReadModelEntryPoint_OpsTest.res +43 -41
- package/tests/RuntimeExtensionEntryPoint_OpsTest.res +4 -3
- package/tests/SideEffectEntryPoint_OpsTest.res +23 -18
- package/tests/StateChangeDescriptorParityTest.res +28 -26
- package/tests/StateTopicKeySchemaTest.res +18 -15
- package/tests/StateViewSliceEntryPoint_OpsTest.res +55 -44
- package/tests/TaskBucketEntryPoint_OpsTest.res +13 -13
- package/tests/Upload_ClaimTest.res +3 -3
- package/tests/Util_AwsErrorTest.res +4 -7
- package/tests/Util_BundleDependencyClosureTest.res +41 -3
- package/tests/Util_BundleDependencyClosureTest.res.mjs +11 -0
- package/tests/Util_BundleEsmLoaderTest.res +3 -3
- package/tests/Util_BundleResolveTest.res +4 -6
- package/tests/Util_BundleRuntimeExtensionTest.res +17 -18
- package/tests/Util_DcbMetricsTest.res +6 -6
- package/tests/Util_DynamoDbStreamTest.res +4 -5
- package/tests/Util_DynamoDbTest.res +3 -2
- package/tests/Util_LambdaEnvBudgetTest.res +22 -18
- package/tests/Util_LambdaLoggingTest.res +9 -8
- package/tests/Util_LogGroup_AdoptingTest.res +10 -5
- package/tests/Util_LogRetentionTest.res +6 -2
- package/tests/Util_OwnerScopeEnvTest.res +10 -8
- package/tests/Util_SQS_RuntimeTest.res +5 -7
- package/tests/Util_ShellConfigTest.res +7 -17
- package/tests/Util_StaticBundleTest.res +3 -8
- package/tests/Util_StoreLayoutTest.res +17 -12
- package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -4
- package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +15 -15
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +296 -232
- package/tests/integration/DcbIntegrationHarness.res +8 -8
- package/tests/integration/EpCompositeSlice.res +16 -8
- package/tests/integration/QueryDbUnion_DynamoDb_IntegrationTest.res +8 -10
- package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +10 -10
- package/tests/integration/SvsTestSlice_Projection.res +1 -3
- package/tests/util/Util_AlarmSpecTest.res +62 -49
|
@@ -69,12 +69,12 @@ beforeAll(() =>
|
|
|
69
69
|
)
|
|
70
70
|
|
|
71
71
|
// Pulumi registers resources asynchronously; give the runtime a few ticks.
|
|
72
|
-
let settle = async () =>
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
let settle = async () =>
|
|
73
|
+
await Promise.make((resolve, _) => {
|
|
74
|
+
let _ = setTimeout(() => resolve(), 300)
|
|
75
|
+
})
|
|
75
76
|
|
|
76
|
-
let wasRegistered = (type_, name) =>
|
|
77
|
-
registered->Array.some(((t, n)) => t == type_ && n == name)
|
|
77
|
+
let wasRegistered = (type_, name) => registered->Array.some(((t, n)) => t == type_ && n == name)
|
|
78
78
|
|
|
79
79
|
// ── Fixtures ─────────────────────────────────────────────────────────────────
|
|
80
80
|
|
|
@@ -124,7 +124,9 @@ describe("EventCollectorChannel_Helpers.connectLambda under an unknown view tabl
|
|
|
124
124
|
name,
|
|
125
125
|
lambdaRole,
|
|
126
126
|
[],
|
|
127
|
-
Dict.fromArray([
|
|
127
|
+
Dict.fromArray([
|
|
128
|
+
("DcbEventLog", {ReventlessInfra.EventTopic.resources: [knownEventLogStream]}),
|
|
129
|
+
]),
|
|
128
130
|
[unknownViewTable],
|
|
129
131
|
{},
|
|
130
132
|
)
|
|
@@ -139,6 +141,11 @@ describe("EventCollectorChannel_Helpers.connectLambda under an unknown view tabl
|
|
|
139
141
|
})
|
|
140
142
|
|
|
141
143
|
test("still registers the event-log mapping, which never reads a view table", async () => {
|
|
142
|
-
expect(
|
|
144
|
+
expect(
|
|
145
|
+
wasRegistered(
|
|
146
|
+
"aws:lambda/eventSourceMapping:EventSourceMapping",
|
|
147
|
+
"CatalogDcbEventLog2" ++ name,
|
|
148
|
+
),
|
|
149
|
+
)->toBe(true)
|
|
143
150
|
})
|
|
144
151
|
})
|
|
@@ -16,7 +16,7 @@ let project = EventCollectorEntryPoint_Ops.projectPluginRow
|
|
|
16
16
|
|
|
17
17
|
describe("EventCollectorEntryPoint_Ops.projectPluginRow", () => {
|
|
18
18
|
testSync("rejects a non-object row", () => {
|
|
19
|
-
expect(
|
|
19
|
+
expect(project(JSON.Encode.string("nope"))->Option.isNone)->toBe(true)
|
|
20
20
|
})
|
|
21
21
|
|
|
22
22
|
testSync("rejects a row missing id or status", () => {
|
|
@@ -25,7 +25,8 @@ describe("EventCollectorEntryPoint_Ops.projectPluginRow", () => {
|
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
testSync("projects the id/status/eventCollector subset with defaults", () => {
|
|
28
|
-
let p =
|
|
28
|
+
let p =
|
|
29
|
+
project(obj([("id", str("Catalog@1")), ("status", str("Connected"))]))->Option.getOrThrow
|
|
29
30
|
expect(p.id)->toBe("Catalog@1")
|
|
30
31
|
expect(p.status)->toBe("Connected")
|
|
31
32
|
expect(p.eventCollector)->toBe("") // defaulted when absent
|
|
@@ -42,7 +43,11 @@ describe("EventCollectorEntryPoint_Ops.projectPluginRow", () => {
|
|
|
42
43
|
(
|
|
43
44
|
"extensions",
|
|
44
45
|
JSON.Encode.array([
|
|
45
|
-
obj([
|
|
46
|
+
obj([
|
|
47
|
+
("name", str("OrdersExt")),
|
|
48
|
+
("extensionPointName", str("Catalog.Products")),
|
|
49
|
+
("dcbSources", JSON.Encode.array([str("prod"), JSON.Encode.int(7)])),
|
|
50
|
+
]),
|
|
46
51
|
obj([("name", str("Malformed"))]), // no extensionPointName -> dropped
|
|
47
52
|
]),
|
|
48
53
|
),
|
|
@@ -127,7 +132,10 @@ describe("EventCollectorEntryPoint_Ops.parseHandlerConfig", () => {
|
|
|
127
132
|
let msgOf = raw => throws(() => EventCollectorEntryPoint_Ops.parseHandlerConfig(raw))
|
|
128
133
|
expect(msgOf(""))->toEqual(Some("HANDLER_CONFIG env var is empty"))
|
|
129
134
|
expect(
|
|
130
|
-
msgOf("{nope")->Option.mapOr(
|
|
135
|
+
msgOf("{nope")->Option.mapOr(
|
|
136
|
+
false,
|
|
137
|
+
m => m->String.startsWith("HANDLER_CONFIG JSON parse error:"),
|
|
138
|
+
),
|
|
131
139
|
)->toBe(true)
|
|
132
140
|
expect(msgOf(`{"queueUrl":"q"}`))->toEqual(
|
|
133
141
|
Some("HANDLER_CONFIG missing required field: pluginExtensionPointCmdTopicUrl"),
|
|
@@ -80,16 +80,22 @@ describe("pluginDefinition.json write/read symmetry", () => {
|
|
|
80
80
|
}
|
|
81
81
|
})
|
|
82
82
|
|
|
83
|
-
testSync(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
83
|
+
testSync(
|
|
84
|
+
"a definition read back from the asset can be published to the Connect handshake",
|
|
85
|
+
() => {
|
|
86
|
+
// The encode the old cast broke. Both arms, because only Offloaded diverges
|
|
87
|
+
// between wire and runtime shape and an Inline-only test would stay green.
|
|
88
|
+
[offloadedFragment, inlineFragment]->Array.forEach(
|
|
89
|
+
def => {
|
|
90
|
+
let published =
|
|
91
|
+
ReventlessInfra.PluginExtensionPointSpec.ConnectPlugin(
|
|
92
|
+
def->writeAsset->readAsset,
|
|
93
|
+
)->Reventless.Util_Sury.toJson(ReventlessInfra.PluginExtensionPointSpec.commandSchema)
|
|
94
|
+
expect(published->JSON.Decode.object->Option.isSome)->toBe(true)
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
},
|
|
98
|
+
)
|
|
93
99
|
|
|
94
100
|
testSync("the asset round-trips byte-identically, so no stored message shifts", () => {
|
|
95
101
|
let once = offloadedFragment->writeAsset
|
|
@@ -108,7 +114,8 @@ describe("pluginDefinition.json write/read symmetry", () => {
|
|
|
108
114
|
// hand-written JSON literal in PluginRuntime_Builder and fell two fields behind
|
|
109
115
|
// (dcbEventLog, kind) with nothing to notice.
|
|
110
116
|
testSync("the platform's own placeholder asset survives the same round trip", () => {
|
|
111
|
-
let def =
|
|
117
|
+
let def =
|
|
118
|
+
ReventlessCore.Platform_Admin_Structure.internalPluginDefinition->writeAsset->readAsset
|
|
112
119
|
expect(def.id)->toBe(ReventlessCore.Platform_Admin_Structure.pluginId ++ "@INTERNAL")
|
|
113
120
|
expect(def.kind)->toBe(Reventless.Plugin.Domain)
|
|
114
121
|
})
|
|
@@ -32,7 +32,7 @@ external makeOutput: (
|
|
|
32
32
|
|
|
33
33
|
let pending = (value: 'a): (Pulumi.Output.t<'a>, unit => unit) => {
|
|
34
34
|
let settle = ref(() => ())
|
|
35
|
-
let p = Promise.make((resolve, _) => settle := () => resolve(value))
|
|
35
|
+
let p = Promise.make((resolve, _) => settle := (() => resolve(value)))
|
|
36
36
|
(
|
|
37
37
|
makeOutput(
|
|
38
38
|
Set.make(),
|
|
@@ -45,9 +45,10 @@ let pending = (value: 'a): (Pulumi.Output.t<'a>, unit => unit) => {
|
|
|
45
45
|
)
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
let ticks = async () =>
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
let ticks = async () =>
|
|
49
|
+
await Promise.make((resolve, _) => {
|
|
50
|
+
let _ = setTimeout(() => resolve(), 50)
|
|
51
|
+
})
|
|
51
52
|
|
|
52
53
|
/** A collector mid-update, the way the engine presents one: the identifiers are
|
|
53
54
|
already known — they do not change across a code update — and only
|
|
@@ -117,8 +117,7 @@ describe("Runtime snapshot item codec", () => {
|
|
|
117
117
|
// The DynamoDB stream decoder drops rows without an `event` column (same
|
|
118
118
|
// mechanism that filters DCB FENCE rows), so snapshot writes are invisible
|
|
119
119
|
// to event collectors.
|
|
120
|
-
let asDict =
|
|
121
|
-
Runtime.snapshotItem("agg-1", snap)->JSON.Decode.object->Option.getOr(Dict.make())
|
|
120
|
+
let asDict = Runtime.snapshotItem("agg-1", snap)->JSON.Decode.object->Option.getOr(Dict.make())
|
|
122
121
|
expect(Util_DynamoDbStream_Runtime.buildJsonEvent'(asDict))->toEqual(None)
|
|
123
122
|
})
|
|
124
123
|
})
|
|
@@ -37,9 +37,7 @@ let context: PulumiAws.Lambda.context = {
|
|
|
37
37
|
|
|
38
38
|
describe("EventMapperEntryPoint_Ops.parseHandlerConfig", () => {
|
|
39
39
|
testSync("reads the builder's field names", () => {
|
|
40
|
-
let config = EventMapperEntryPoint_Ops.parseHandlerConfig(
|
|
41
|
-
`{"targetSpecModule":"@x/p/src/Aggregate/Product.res.mjs","mappingsModule":"@x/p/src/Aggregate/Product_Mappings.res.mjs","queueUrl":"https://sqs/q"}`,
|
|
42
|
-
)
|
|
40
|
+
let config = EventMapperEntryPoint_Ops.parseHandlerConfig(`{"targetSpecModule":"@x/p/src/Aggregate/Product.res.mjs","mappingsModule":"@x/p/src/Aggregate/Product_Mappings.res.mjs","queueUrl":"https://sqs/q"}`)
|
|
43
41
|
expect(config.targetSpecModule)->toEqual(Some("@x/p/src/Aggregate/Product.res.mjs"))
|
|
44
42
|
expect(config.mappingsModule)->toEqual(Some("@x/p/src/Aggregate/Product_Mappings.res.mjs"))
|
|
45
43
|
expect(config.queueUrl)->toEqual(Some("https://sqs/q"))
|
|
@@ -9,12 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
open JestGlobals
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
describe("ExtensionPointEntryPoint_Ops.parseHandlerConfig", () => {
|
|
14
13
|
testSync("reads the builder's field names", () => {
|
|
15
|
-
let config = ExtensionPointEntryPoint_Ops.parseHandlerConfig(
|
|
16
|
-
`{"specModule":"@x/spec/src/Products_ExtensionPoint.res.mjs","mappingsModule":"@x/p/src/ExtensionPoint/Products_ExtensionPointMapping.res.mjs","queueUrl":"https://sqs/ep","publishToAggregates":{"Product":"EP_TEST_PRODUCT_QUEUE"}}`,
|
|
17
|
-
)
|
|
14
|
+
let config = ExtensionPointEntryPoint_Ops.parseHandlerConfig(`{"specModule":"@x/spec/src/Products_ExtensionPoint.res.mjs","mappingsModule":"@x/p/src/ExtensionPoint/Products_ExtensionPointMapping.res.mjs","queueUrl":"https://sqs/ep","publishToAggregates":{"Product":"EP_TEST_PRODUCT_QUEUE"}}`)
|
|
18
15
|
expect(config.specModule)->toEqual(Some("@x/spec/src/Products_ExtensionPoint.res.mjs"))
|
|
19
16
|
expect(config.queueUrl)->toEqual(Some("https://sqs/ep"))
|
|
20
17
|
expect(config.publishToAggregates->Option.flatMap(d => d->Dict.get("Product")))->toEqual(
|
|
@@ -85,106 +85,133 @@ let capture = (): Effect.t<ReventlessCore.RequestContext.t, string, _> =>
|
|
|
85
85
|
|
|
86
86
|
describe("entry-point dispatch boundary", () => {
|
|
87
87
|
describe("SQS records", () => {
|
|
88
|
-
testSync(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
testSync(
|
|
89
|
+
"reads the envelope out of the body",
|
|
90
|
+
() => {
|
|
91
|
+
expect(extractMetaField(sqsRecords, "correlationId"))->Expect.toEqual(Some("corr-1"))
|
|
92
|
+
expect(extractMetaField(sqsRecords, "causationId"))->Expect.toEqual(Some("cause-1"))
|
|
93
|
+
},
|
|
94
|
+
)
|
|
92
95
|
|
|
93
|
-
testSync(
|
|
94
|
-
|
|
96
|
+
testSync(
|
|
97
|
+
"reads SentTimestamp as ms since epoch",
|
|
98
|
+
() => expect(extractSentTimestamp(sqsRecords))->Expect.toEqual(Some(1750000000000.0)),
|
|
95
99
|
)
|
|
96
100
|
|
|
97
|
-
testSync(
|
|
98
|
-
|
|
101
|
+
testSync(
|
|
102
|
+
"reads ApproximateReceiveCount as the delivery attempt",
|
|
103
|
+
() => expect(extractRetryCount(sqsRecords))->Expect.toBe(3),
|
|
99
104
|
)
|
|
100
105
|
})
|
|
101
106
|
|
|
102
107
|
describe("DynamoDB stream records", () => {
|
|
103
108
|
// EventLog rows store meta keys flat as top-level attributes
|
|
104
109
|
// (Message.composeMeta rebuilds `meta` from them) — not as a nested map.
|
|
105
|
-
testSync(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
testSync(
|
|
111
|
+
"reads the envelope off the flat NewImage attributes",
|
|
112
|
+
() => {
|
|
113
|
+
expect(extractMetaField(streamRecords, "correlationId"))->Expect.toEqual(Some("corr-2"))
|
|
114
|
+
expect(extractMetaField(streamRecords, "causationId"))->Expect.toEqual(Some("cause-2"))
|
|
115
|
+
},
|
|
116
|
+
)
|
|
109
117
|
|
|
110
|
-
testSync(
|
|
111
|
-
|
|
118
|
+
testSync(
|
|
119
|
+
"converts ApproximateCreationDateTime from seconds to ms",
|
|
120
|
+
() => expect(extractSentTimestamp(streamRecords))->Expect.toEqual(Some(1750000001000.0)),
|
|
112
121
|
)
|
|
113
122
|
|
|
114
|
-
testSync(
|
|
115
|
-
|
|
123
|
+
testSync(
|
|
124
|
+
"reports a first delivery — streams have no receive count",
|
|
125
|
+
() => expect(extractRetryCount(streamRecords))->Expect.toBe(1),
|
|
116
126
|
)
|
|
117
127
|
})
|
|
118
128
|
|
|
119
129
|
describe("absent or malformed input", () => {
|
|
120
|
-
testSync(
|
|
121
|
-
|
|
130
|
+
testSync(
|
|
131
|
+
"an empty batch has no send time",
|
|
132
|
+
() => expect(extractSentTimestamp([]))->Expect.toEqual(None),
|
|
122
133
|
)
|
|
123
134
|
|
|
124
|
-
testSync(
|
|
125
|
-
|
|
135
|
+
testSync(
|
|
136
|
+
"an unparseable body yields no envelope field",
|
|
137
|
+
() => expect(extractMetaField([{body: "not json"}], "correlationId"))->Expect.toEqual(None),
|
|
126
138
|
)
|
|
127
139
|
})
|
|
128
140
|
|
|
129
141
|
describe("RequestContext provided at dispatch", () => {
|
|
130
|
-
test(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
test(
|
|
143
|
+
"carries the full record, not a bare correlationId literal",
|
|
144
|
+
async () => {
|
|
145
|
+
let ctx = await runEffect(
|
|
146
|
+
capture(),
|
|
147
|
+
{
|
|
148
|
+
correlationId: "corr-1",
|
|
149
|
+
causationId: "cause-1",
|
|
150
|
+
comp: "AggregateRuntime(Customer)",
|
|
151
|
+
plugin: "Catalog",
|
|
152
|
+
timestamp: 1750000000000.0,
|
|
153
|
+
retryCount: 3,
|
|
154
|
+
},
|
|
155
|
+
)
|
|
156
|
+
expect(ctx.correlationId)->Expect.toBe("corr-1")
|
|
157
|
+
expect(ctx.causationId)->Expect.toEqual(Some("cause-1"))
|
|
158
|
+
expect(ctx.component)->Expect.toEqual(Some("AggregateRuntime(Customer)"))
|
|
159
|
+
expect(ctx.pluginName)->Expect.toEqual(Some("Catalog"))
|
|
160
|
+
expect(ctx.timestamp)->Expect.toEqual(Some(1750000000000.0))
|
|
161
|
+
expect(ctx.retryCount)->Expect.toEqual(Some(3))
|
|
162
|
+
},
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
test(
|
|
166
|
+
"fills identity and claims, which the record declares non-optional",
|
|
167
|
+
async () => {
|
|
168
|
+
let ctx = await runEffect(capture(), {correlationId: "corr-1"})
|
|
169
|
+
expect(ctx.identity.userId)->Expect.toBe(Reventless.Identity.anonymous.userId)
|
|
170
|
+
expect(ctx.claims->Dict.keysToArray)->Expect.toEqual([])
|
|
171
|
+
},
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
test(
|
|
175
|
+
"falls back to a placeholder when no correlationId is on the message",
|
|
176
|
+
async () => {
|
|
177
|
+
let ctx = await runEffect(capture(), {comp: "X(Y)"})
|
|
178
|
+
expect(ctx.correlationId)->Expect.toBe("unknown")
|
|
179
|
+
},
|
|
180
|
+
)
|
|
160
181
|
})
|
|
161
182
|
|
|
162
183
|
describe("log annotations", () => {
|
|
163
184
|
// Effect keeps annotations in a HashMap; read it as a dict.
|
|
164
185
|
let annotations = (): Effect.t<Effect.logAnnotationMap, string, _> => Effect.logAnnotations
|
|
165
186
|
|
|
166
|
-
test(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
187
|
+
test(
|
|
188
|
+
"promotes comp, causationId and the request id onto every line",
|
|
189
|
+
async () => {
|
|
190
|
+
setRequestId("req-abc")
|
|
191
|
+
let annotated = await runEffect(
|
|
192
|
+
annotations(),
|
|
193
|
+
{correlationId: "corr-1", causationId: "cause-1", comp: "EventCollector(Customers)"},
|
|
194
|
+
)
|
|
195
|
+
let annotated = annotated->Effect.annotationsToDict
|
|
196
|
+
expect(annotated->Dict.get("comp"))->Expect.toEqual(Some("EventCollector(Customers)"))
|
|
197
|
+
expect(annotated->Dict.get("causationId"))->Expect.toEqual(Some("cause-1"))
|
|
198
|
+
expect(annotated->Dict.get("correlationId"))->Expect.toEqual(Some("corr-1"))
|
|
199
|
+
expect(annotated->Dict.get("requestId"))->Expect.toEqual(Some("req-abc"))
|
|
200
|
+
},
|
|
201
|
+
)
|
|
178
202
|
|
|
179
203
|
// A constant "1" on every line is noise; its absence is what makes
|
|
180
204
|
// `filter retryCount > 1` a usable CloudWatch query.
|
|
181
|
-
test(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
205
|
+
test(
|
|
206
|
+
"annotates retryCount only on a redelivery",
|
|
207
|
+
async () => {
|
|
208
|
+
let first = await runEffect(annotations(), {correlationId: "c", retryCount: 1})
|
|
209
|
+
expect(first->Effect.annotationsToDict->Dict.get("retryCount"))->Expect.toEqual(None)
|
|
210
|
+
let redelivered = await runEffect(annotations(), {correlationId: "c", retryCount: 2})
|
|
211
|
+
expect(redelivered->Effect.annotationsToDict->Dict.get("retryCount"))->Expect.toEqual(
|
|
212
|
+
Some("2"),
|
|
213
|
+
)
|
|
214
|
+
},
|
|
215
|
+
)
|
|
189
216
|
})
|
|
190
217
|
})
|
package/tests/MCP_LambdaTest.res
CHANGED
|
@@ -22,27 +22,18 @@ describe("MCP_Lambda.generateAdminConfig", () => {
|
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
testSync("produces resources from admin query entries", () => {
|
|
25
|
-
let config = MCP_Lambda.generateAdminConfig(
|
|
26
|
-
~serverName="test",
|
|
27
|
-
~serverVersion="1.0.0",
|
|
28
|
-
)
|
|
25
|
+
let config = MCP_Lambda.generateAdminConfig(~serverName="test", ~serverVersion="1.0.0")
|
|
29
26
|
// PluginBaseFragment has one query entry → generates resources for single + list
|
|
30
27
|
expect(config.resources->Array.length)->toBeGreaterThan(0)
|
|
31
28
|
})
|
|
32
29
|
|
|
33
30
|
testSync("server name has -admin suffix", () => {
|
|
34
|
-
let config = MCP_Lambda.generateAdminConfig(
|
|
35
|
-
~serverName="my-platform",
|
|
36
|
-
~serverVersion="2.0.0",
|
|
37
|
-
)
|
|
31
|
+
let config = MCP_Lambda.generateAdminConfig(~serverName="my-platform", ~serverVersion="2.0.0")
|
|
38
32
|
expect(config.serverName)->toBe("my-platform-admin")
|
|
39
33
|
})
|
|
40
34
|
|
|
41
35
|
testSync("server version is passed through", () => {
|
|
42
|
-
let config = MCP_Lambda.generateAdminConfig(
|
|
43
|
-
~serverName="test",
|
|
44
|
-
~serverVersion="3.1.4",
|
|
45
|
-
)
|
|
36
|
+
let config = MCP_Lambda.generateAdminConfig(~serverName="test", ~serverVersion="3.1.4")
|
|
46
37
|
expect(config.serverVersion)->toBe("3.1.4")
|
|
47
38
|
})
|
|
48
39
|
|
|
@@ -52,21 +43,22 @@ describe("MCP_Lambda.generateAdminConfig", () => {
|
|
|
52
43
|
~serverVersion="1.0.0",
|
|
53
44
|
~cloner=true,
|
|
54
45
|
)
|
|
55
|
-
config.tools->Array.forEach(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
config.tools->Array.forEach(
|
|
47
|
+
tool => {
|
|
48
|
+
expect(tool.name->String.length)->toBeGreaterThan(0)
|
|
49
|
+
expect(tool.description->String.length)->toBeGreaterThan(0)
|
|
50
|
+
},
|
|
51
|
+
)
|
|
59
52
|
})
|
|
60
53
|
|
|
61
54
|
testSync("resources have non-empty names and URI templates", () => {
|
|
62
|
-
let config = MCP_Lambda.generateAdminConfig(
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
let config = MCP_Lambda.generateAdminConfig(~serverName="test", ~serverVersion="1.0.0")
|
|
56
|
+
config.resources->Array.forEach(
|
|
57
|
+
resource => {
|
|
58
|
+
expect(resource.name->String.length)->toBeGreaterThan(0)
|
|
59
|
+
expect(resource.uriTemplate->String.length)->toBeGreaterThan(0)
|
|
60
|
+
},
|
|
65
61
|
)
|
|
66
|
-
config.resources->Array.forEach(resource => {
|
|
67
|
-
expect(resource.name->String.length)->toBeGreaterThan(0)
|
|
68
|
-
expect(resource.uriTemplate->String.length)->toBeGreaterThan(0)
|
|
69
|
-
})
|
|
70
62
|
})
|
|
71
63
|
|
|
72
64
|
testSync("commandTopicArns are mapped to tools", () => {
|
|
@@ -92,10 +84,7 @@ describe("MCP_Lambda.generateAdminConfig", () => {
|
|
|
92
84
|
})
|
|
93
85
|
|
|
94
86
|
testSync("event history resources default to empty", () => {
|
|
95
|
-
let config = MCP_Lambda.generateAdminConfig(
|
|
96
|
-
~serverName="test",
|
|
97
|
-
~serverVersion="1.0.0",
|
|
98
|
-
)
|
|
87
|
+
let config = MCP_Lambda.generateAdminConfig(~serverName="test", ~serverVersion="1.0.0")
|
|
99
88
|
expect(config.eventHistoryResources)->toHaveLength(0)
|
|
100
89
|
})
|
|
101
90
|
})
|