@reventlessdev/reventless-aws 3.0.0-alpha.344 → 3.0.0-alpha.346
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 +36 -0
- package/package.json +15 -12
- package/run-provision-accounts.mjs +3 -0
- package/run-provision-admin.mjs +3 -0
- package/scripts/ProvisionAccounts.res +325 -0
- package/scripts/ProvisionAccounts.res.mjs +337 -0
- package/scripts/ProvisionAdmin.res +275 -0
- package/scripts/ProvisionAdmin.res.mjs +289 -0
- package/scripts/ProvisionCognito.res +149 -0
- package/scripts/ProvisionCognito.res.mjs +98 -0
- package/scripts/ProvisionIdentity.res +84 -14
- package/scripts/ProvisionIdentity.res.mjs +72 -7
- package/scripts/ProvisionProvider.res +104 -0
- package/scripts/ProvisionProvider.res.mjs +123 -0
- package/src/Platform.res +358 -329
- package/src/Platform.res.mjs +24 -12
- package/src/Platform_Casts.res +13 -4
- package/src/Platform_Stack.res +119 -9
- package/src/Platform_Stack.res.mjs +42 -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/Auth/Auth_LoginIdentifier.res +66 -0
- package/src/adapter/Auth/Auth_LoginIdentifier.res.mjs +70 -0
- package/src/adapter/Auth/Auth_SignUpMode.res +78 -0
- package/src/adapter/Auth/Auth_SignUpMode.res.mjs +56 -0
- 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 +23 -11
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +5 -1
- 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 +80 -109
- package/src/components/Api/AppSync_Adapter.res.mjs +26 -60
- package/src/components/Api/AppSync_SdlDecorate.res +118 -31
- package/src/components/Api/AppSync_SdlDecorate.res.mjs +45 -0
- 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 +46 -42
- 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 +286 -224
- package/tests/AppSync_AdapterTest.res.mjs +69 -0
- 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/Auth_LoginIdentifierTest.res +51 -0
- package/tests/Auth_LoginIdentifierTest.res.mjs +51 -0
- package/tests/Auth_SignUpModeTest.res +56 -0
- package/tests/Auth_SignUpModeTest.res.mjs +53 -0
- 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/ProvisionAccountsTest.res +142 -0
- package/tests/ProvisionAccountsTest.res.mjs +153 -0
- package/tests/ProvisionAdminTest.res +55 -0
- package/tests/ProvisionAdminTest.res.mjs +66 -0
- package/tests/ProvisionIdentityTest.res +91 -9
- package/tests/ProvisionIdentityTest.res.mjs +66 -1
- 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 +15 -3
- 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 +35 -8
- package/tests/Util_OwnerScopeEnvTest.res.mjs +13 -0
- 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
|
@@ -33,34 +33,39 @@ describe("StateViewSliceEntryPoint_Ops.parseHandlerConfig", () => {
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
testSync("expands compact-v2 entries against shared base/sourceUrn/pgConnection", () => {
|
|
36
|
-
let config =
|
|
37
|
-
(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
("host", str("db.local")),
|
|
44
|
-
("port", JSON.Encode.int(5432)),
|
|
45
|
-
("database", str("app")),
|
|
46
|
-
("username", str("master")),
|
|
47
|
-
("secretArn", str("arn:secret")),
|
|
48
|
-
]),
|
|
49
|
-
),
|
|
50
|
-
(
|
|
51
|
-
"handlers",
|
|
52
|
-
JSON.Encode.array([
|
|
53
|
-
obj([("s", str("Carts.res.mjs")), ("p", str("Carts_Projection.res.mjs")), ("q", str("qdb_Carts"))]),
|
|
36
|
+
let config =
|
|
37
|
+
obj([
|
|
38
|
+
("v", JSON.Encode.int(2)),
|
|
39
|
+
("base", str("@x/plugin/src/StateViewSlice/")),
|
|
40
|
+
("sourceUrn", str("arn:shared")),
|
|
41
|
+
(
|
|
42
|
+
"pgConnection",
|
|
54
43
|
obj([
|
|
55
|
-
("
|
|
56
|
-
("
|
|
57
|
-
("
|
|
58
|
-
("
|
|
59
|
-
("
|
|
44
|
+
("host", str("db.local")),
|
|
45
|
+
("port", JSON.Encode.int(5432)),
|
|
46
|
+
("database", str("app")),
|
|
47
|
+
("username", str("master")),
|
|
48
|
+
("secretArn", str("arn:secret")),
|
|
60
49
|
]),
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
),
|
|
51
|
+
(
|
|
52
|
+
"handlers",
|
|
53
|
+
JSON.Encode.array([
|
|
54
|
+
obj([
|
|
55
|
+
("s", str("Carts.res.mjs")),
|
|
56
|
+
("p", str("Carts_Projection.res.mjs")),
|
|
57
|
+
("q", str("qdb_Carts")),
|
|
58
|
+
]),
|
|
59
|
+
obj([
|
|
60
|
+
("s", str("Totals.res.mjs")),
|
|
61
|
+
("p", str("Totals_Projection.res.mjs")),
|
|
62
|
+
("q", str("qdb_Totals")),
|
|
63
|
+
("u", str("arn:override")),
|
|
64
|
+
("t", str("cartTotals")),
|
|
65
|
+
]),
|
|
66
|
+
]),
|
|
67
|
+
),
|
|
68
|
+
])->JSON.stringify
|
|
64
69
|
let entries = StateViewSliceEntryPoint_Ops.parseHandlerConfig(config)
|
|
65
70
|
expect(entries->Array.length)->toBe(2)
|
|
66
71
|
let first = entries->Array.getUnsafe(0)
|
|
@@ -76,21 +81,22 @@ describe("StateViewSliceEntryPoint_Ops.parseHandlerConfig", () => {
|
|
|
76
81
|
})
|
|
77
82
|
|
|
78
83
|
testSync("passes legacy full-key entries through with per-entry fields", () => {
|
|
79
|
-
let config =
|
|
80
|
-
(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
let config =
|
|
85
|
+
obj([
|
|
86
|
+
("base", str("ignored/")),
|
|
87
|
+
("sourceUrn", str("arn:shared")),
|
|
88
|
+
(
|
|
89
|
+
"handlers",
|
|
90
|
+
JSON.Encode.array([
|
|
91
|
+
obj([
|
|
92
|
+
("specModule", str("full/Carts.res.mjs")),
|
|
93
|
+
("projectionModule", str("full/Carts_Projection.res.mjs")),
|
|
94
|
+
("queryDbTableName", str("qdb_Carts")),
|
|
95
|
+
("sourceUrn", str("arn:own")),
|
|
96
|
+
]),
|
|
90
97
|
]),
|
|
91
|
-
|
|
92
|
-
)
|
|
93
|
-
])->JSON.stringify
|
|
98
|
+
),
|
|
99
|
+
])->JSON.stringify
|
|
94
100
|
let e = StateViewSliceEntryPoint_Ops.parseHandlerConfig(config)->Array.getUnsafe(0)
|
|
95
101
|
// Legacy entries are NOT base-prefixed and keep their own sourceUrn.
|
|
96
102
|
expect(e.specModule)->toBe("full/Carts.res.mjs")
|
|
@@ -142,9 +148,9 @@ describe("StateViewSliceEntryPoint_Ops.makeJsonEventsHandler", () => {
|
|
|
142
148
|
|
|
143
149
|
// String-typed consumed events keep the pipeline test independent of any
|
|
144
150
|
// real slice: each event value becomes the row id, `recordedAt` the state.
|
|
145
|
-
let project = (
|
|
146
|
-
|
|
147
|
-
|
|
151
|
+
let project = ({event, recordedAt, _}: Reventless.StateViewSlice.consumed<string>): array<
|
|
152
|
+
Reventless.Projection.action<string, JSON.t>,
|
|
153
|
+
> => [Set(event, str(recordedAt))]
|
|
148
154
|
|
|
149
155
|
test("decodes envelopes, projects, and runs actions against the ops", async () => {
|
|
150
156
|
let saved = []
|
|
@@ -205,7 +211,12 @@ describe("StateViewSliceEntryPoint_Ops.makeJsonEventsHandler", () => {
|
|
|
205
211
|
"row-1",
|
|
206
212
|
obj([
|
|
207
213
|
("lifecycle", str("Placed")),
|
|
208
|
-
(
|
|
214
|
+
(
|
|
215
|
+
"trail",
|
|
216
|
+
JSON.Encode.array([
|
|
217
|
+
obj([("state", str("Placed")), ("at", str("2026-03-02T09:00:00Z"))]),
|
|
218
|
+
]),
|
|
219
|
+
),
|
|
209
220
|
]),
|
|
210
221
|
),
|
|
211
222
|
])
|
|
@@ -11,7 +11,6 @@ open JestGlobals
|
|
|
11
11
|
let str = JSON.Encode.string
|
|
12
12
|
let obj = pairs => JSON.Encode.object(Dict.fromArray(pairs))
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
describe("TaskBucketEntryPoint_Ops.parseHandlerConfig", () => {
|
|
16
15
|
testSync("empty raw config decodes to empty defaults", () => {
|
|
17
16
|
let c = TaskBucketEntryPoint_Ops.parseHandlerConfig("")
|
|
@@ -21,18 +20,19 @@ describe("TaskBucketEntryPoint_Ops.parseHandlerConfig", () => {
|
|
|
21
20
|
})
|
|
22
21
|
|
|
23
22
|
testSync("decodes callbackModule, publishToAggregates, and scheduler env names", () => {
|
|
24
|
-
let config =
|
|
25
|
-
(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
let config =
|
|
24
|
+
obj([
|
|
25
|
+
("callbackModule", str("@x/plugin/src/Task/ImportCatalog.res.mjs")),
|
|
26
|
+
("publishToAggregates", obj([("Product", str("PTA_Product_QUEUE_URL"))])),
|
|
27
|
+
(
|
|
28
|
+
"scheduler",
|
|
29
|
+
obj([
|
|
30
|
+
("roleArnEnv", str("SCHEDULER_ROLE_ARN")),
|
|
31
|
+
("targetArnEnv", str("SCHEDULER_TARGET_ARN")),
|
|
32
|
+
("targetNameEnv", str("SCHEDULER_TARGET_NAME")),
|
|
33
|
+
]),
|
|
34
|
+
),
|
|
35
|
+
])->JSON.stringify
|
|
36
36
|
let c = TaskBucketEntryPoint_Ops.parseHandlerConfig(config)
|
|
37
37
|
expect(c.callbackModule)->toBe("@x/plugin/src/Task/ImportCatalog.res.mjs")
|
|
38
38
|
expect(c.publishToAggregates->Dict.get("Product"))->toEqual(Some("PTA_Product_QUEUE_URL"))
|
|
@@ -29,9 +29,9 @@ describe("Upload_Claim_S3_Ops.tableNameFromEventSourceArn", () => {
|
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
testSync("returns None for an ARN that is not a table stream", () =>
|
|
32
|
-
expect(
|
|
33
|
-
|
|
34
|
-
)
|
|
32
|
+
expect(
|
|
33
|
+
Ops.tableNameFromEventSourceArn("arn:aws:sqs:eu-west-1:123456789012:SomeQueue"),
|
|
34
|
+
)->toEqual(None)
|
|
35
35
|
)
|
|
36
36
|
})
|
|
37
37
|
|
|
@@ -52,9 +52,7 @@ describe("Util_AwsError.isNotFound", () => {
|
|
|
52
52
|
// the original guard tested, and it is false for the real error.
|
|
53
53
|
testSync("...and its message does not carry the code, which is why", () =>
|
|
54
54
|
expect(
|
|
55
|
-
AwsError.describe(dynamoNotFound)->String.includes(
|
|
56
|
-
"Requested resource not found",
|
|
57
|
-
),
|
|
55
|
+
AwsError.describe(dynamoNotFound)->String.includes("Requested resource not found"),
|
|
58
56
|
)->toBe(true)
|
|
59
57
|
)
|
|
60
58
|
|
|
@@ -118,10 +116,9 @@ describe("Util_AwsError.describe", () => {
|
|
|
118
116
|
// failure with another.
|
|
119
117
|
testSync("every shape yields something an operator can read", () =>
|
|
120
118
|
expect(
|
|
121
|
-
[
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
]->Array.every(e => AwsError.describe(e)->String.length > 0),
|
|
119
|
+
[awsError(~name="X", ~message="y"), Not_found]->Array.every(
|
|
120
|
+
e => AwsError.describe(e)->String.length > 0,
|
|
121
|
+
),
|
|
125
122
|
)->toBe(true)
|
|
126
123
|
)
|
|
127
124
|
})
|
|
@@ -62,8 +62,17 @@ export const rule = () => Rules.check();
|
|
|
62
62
|
),
|
|
63
63
|
],
|
|
64
64
|
)
|
|
65
|
-
let _ = writePkg(
|
|
66
|
-
|
|
65
|
+
let _ = writePkg(
|
|
66
|
+
~root=rulesRoot,
|
|
67
|
+
~name=rulesName,
|
|
68
|
+
[
|
|
69
|
+
(
|
|
70
|
+
"src/Rules.res.mjs",
|
|
71
|
+
`export const check = () => true;
|
|
72
|
+
`,
|
|
73
|
+
),
|
|
74
|
+
],
|
|
75
|
+
)
|
|
67
76
|
|
|
68
77
|
let closureOf = (packageDirs: dict<string>) => {
|
|
69
78
|
Util_Bundle.addImportedPackageClosure(packageDirs)
|
|
@@ -130,7 +139,10 @@ describe("Util_Bundle — bundled user packages carry their imports", () => {
|
|
|
130
139
|
// Walking reventless-aws would reach its deploy-time-only imports (the
|
|
131
140
|
// @pulumi bindings) and add tens of megabytes to every archive.
|
|
132
141
|
let packageDirs = Dict.fromArray([
|
|
133
|
-
(
|
|
142
|
+
(
|
|
143
|
+
"@reventlessdev/reventless-aws",
|
|
144
|
+
Util_Bundle.resolvePackageRoot("@reventlessdev/reventless-aws"),
|
|
145
|
+
),
|
|
134
146
|
])
|
|
135
147
|
expect(closureOf(packageDirs)->Dict.keysToArray->Array.length)->toBe(1)
|
|
136
148
|
})
|
|
@@ -22,9 +22,9 @@ describe("Util_Bundle ESM loader — env-var contract", () => {
|
|
|
22
22
|
|
|
23
23
|
describe("Util_Bundle ESM loader — file cross-references", () => {
|
|
24
24
|
testSync("register-hook registers exactly the layer-resolver filename", () => {
|
|
25
|
-
expect(
|
|
26
|
-
|
|
27
|
-
)
|
|
25
|
+
expect(
|
|
26
|
+
Util_Bundle.registerHookSource->String.includes(Util_Bundle.layerResolverFileName),
|
|
27
|
+
)->toBe(true)
|
|
28
28
|
expect(Util_Bundle.registerHookSource->String.includes("register("))->toBe(true)
|
|
29
29
|
})
|
|
30
30
|
|
|
@@ -5,14 +5,12 @@ open JestGlobals
|
|
|
5
5
|
// than one of reventless-aws's own dependencies. realpath because macOS hands
|
|
6
6
|
// out /var/... symlinks for tmpdir while require.resolve reports /private/var.
|
|
7
7
|
let makeProject = (pkgName: string): (string, string) => {
|
|
8
|
-
let project =
|
|
9
|
-
NodeFs.
|
|
8
|
+
let project = NodeFs.realpathSync(
|
|
9
|
+
NodeFs.mkdtempSync(NodePath.join([NodeOs.tmpdir(), "pulumi-project-"])),
|
|
10
|
+
)
|
|
10
11
|
let pkgDir = NodePath.join([NodePath.join([project, "node_modules"]), pkgName])
|
|
11
12
|
NodeFs.mkdirSync(pkgDir, {recursive: true})
|
|
12
|
-
NodeFs.writeFileSync(
|
|
13
|
-
NodePath.join([pkgDir, "package.json"]),
|
|
14
|
-
`{"name":"","version":"9.9.9"}`,
|
|
15
|
-
)
|
|
13
|
+
NodeFs.writeFileSync(NodePath.join([pkgDir, "package.json"]), `{"name":"","version":"9.9.9"}`)
|
|
16
14
|
(project, pkgDir)
|
|
17
15
|
}
|
|
18
16
|
|
|
@@ -24,9 +24,10 @@ let makePkg = (name: string, files: array<(string, string)>): string => {
|
|
|
24
24
|
|
|
25
25
|
let fileUrl = (absPath: string) => "file://" ++ absPath
|
|
26
26
|
|
|
27
|
-
let extensionModule = (
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
let extensionModule = (
|
|
28
|
+
~companions: array<string>=[],
|
|
29
|
+
url: string,
|
|
30
|
+
): module(ReventlessCore.RuntimeExtension.Extension) => {
|
|
30
31
|
module E = {
|
|
31
32
|
let moduleUrl = url
|
|
32
33
|
let companionModuleUrls = companions
|
|
@@ -104,8 +105,8 @@ describe("Util_Bundle — runtime-extension companion packages", () => {
|
|
|
104
105
|
beforeEach(() => ReventlessCore.RuntimeExtension.reset())
|
|
105
106
|
afterAll(() => {
|
|
106
107
|
ReventlessCore.RuntimeExtension.reset()
|
|
107
|
-
[extRoot, companionRoot, badRoot]->Array.forEach(
|
|
108
|
-
NodeFs.rmSync(root, {recursive: true, force: true})
|
|
108
|
+
[extRoot, companionRoot, badRoot]->Array.forEach(
|
|
109
|
+
root => NodeFs.rmSync(root, {recursive: true, force: true}),
|
|
109
110
|
)
|
|
110
111
|
})
|
|
111
112
|
|
|
@@ -135,10 +136,7 @@ describe("Util_Bundle — runtime-extension companion packages", () => {
|
|
|
135
136
|
|
|
136
137
|
let companionFile = NodePath.join([companionRoot, "src/Companion.res.mjs"])
|
|
137
138
|
let original = NodeFs.readFileSync(companionFile)
|
|
138
|
-
NodeFs.writeFileSync(
|
|
139
|
-
companionFile,
|
|
140
|
-
original ++ "export const changed = true;\n",
|
|
141
|
-
)
|
|
139
|
+
NodeFs.writeFileSync(companionFile, original ++ "export const changed = true;\n")
|
|
142
140
|
let after = build().sourceCodeHash
|
|
143
141
|
NodeFs.writeFileSync(companionFile, original)
|
|
144
142
|
|
|
@@ -147,21 +145,22 @@ describe("Util_Bundle — runtime-extension companion packages", () => {
|
|
|
147
145
|
|
|
148
146
|
testSync("an empty registry leaves the archive byte-identical", () => {
|
|
149
147
|
let withSeam = build().sourceCodeHash
|
|
150
|
-
let withoutSeam =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
).sourceCodeHash
|
|
148
|
+
let withoutSeam = Util_Bundle.buildCodeArchive(
|
|
149
|
+
~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Runtime/Entry.res.mjs",
|
|
150
|
+
~packageDirs=Dict.make(),
|
|
151
|
+
~bundleRuntimeExtensions=false,
|
|
152
|
+
).sourceCodeHash
|
|
156
153
|
expect(withSeam)->toBe(withoutSeam)
|
|
157
154
|
})
|
|
158
155
|
|
|
159
156
|
testSync("an undeclared, un-bundled import fails the archive build, naming the remedy", () => {
|
|
160
157
|
ReventlessCore.RuntimeExtension.use(extensionModule(badUrl))
|
|
161
158
|
|
|
162
|
-
switch caughtMessage(
|
|
163
|
-
|
|
164
|
-
|
|
159
|
+
switch caughtMessage(
|
|
160
|
+
() => {
|
|
161
|
+
let _ = build()
|
|
162
|
+
},
|
|
163
|
+
) {
|
|
165
164
|
| None => JsError.throwWithMessage("expected buildCodeArchive to throw")
|
|
166
165
|
| Some(message) =>
|
|
167
166
|
expect(message->String.includes(badPkgName))->toBe(true)
|
|
@@ -8,15 +8,13 @@ open JestGlobals
|
|
|
8
8
|
|
|
9
9
|
describe("Util_DcbMetrics.transformationFor", () => {
|
|
10
10
|
testSync("never sets defaultValue — it is mutually exclusive with dimensions", () =>
|
|
11
|
-
Util_DcbMetrics.metricNames->Array.forEach(
|
|
12
|
-
expect(Util_DcbMetrics.transformationFor(m).defaultValue)->toBe(None)
|
|
11
|
+
Util_DcbMetrics.metricNames->Array.forEach(
|
|
12
|
+
m => expect(Util_DcbMetrics.transformationFor(m).defaultValue)->toBe(None),
|
|
13
13
|
)
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
testSync("dimensions the metric by slice", () =>
|
|
17
|
-
expect(
|
|
18
|
-
Util_DcbMetrics.transformationFor("AppendRetry").dimensions->Option.isSome,
|
|
19
|
-
)->toBe(true)
|
|
17
|
+
expect(Util_DcbMetrics.transformationFor("AppendRetry").dimensions->Option.isSome)->toBe(true)
|
|
20
18
|
)
|
|
21
19
|
|
|
22
20
|
testSync("counts into the DCB namespace", () =>
|
|
@@ -30,6 +28,8 @@ describe("Util_DcbMetrics.transformationFor", () => {
|
|
|
30
28
|
|
|
31
29
|
describe("Util_DcbMetrics.patternFor", () => {
|
|
32
30
|
testSync("selects one metric's lines by its marker", () =>
|
|
33
|
-
expect(
|
|
31
|
+
expect(
|
|
32
|
+
Util_DcbMetrics.patternFor("AppendRetry"),
|
|
33
|
+
)->toBe(`{ $.reventlessMetric = "AppendRetry" }`)
|
|
34
34
|
)
|
|
35
35
|
})
|
|
@@ -33,11 +33,10 @@ describe("Util_DynamoDbStream.toStreamResource", () => {
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
test("answers its own stream ARN", async () => {
|
|
36
|
-
let arn =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
->resolve
|
|
36
|
+
let arn = await tableResource
|
|
37
|
+
->Util_DynamoDbStream.toStreamResource
|
|
38
|
+
->Util_DynamoDbStream.streamArnFromDynamoDbTableResource
|
|
39
|
+
->resolve
|
|
41
40
|
expect(arn)->toBe(streamArn)
|
|
42
41
|
})
|
|
43
42
|
})
|
|
@@ -35,8 +35,9 @@ describe("Util_DynamoDb.toResourceInfo", () => {
|
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
test("carries a sort key when the table has one", async () => {
|
|
38
|
-
let resourceInfo =
|
|
39
|
-
|
|
38
|
+
let resourceInfo = await table(~rangeKey=Nullable.make("seq"))
|
|
39
|
+
->Util_DynamoDb.toResourceInfo
|
|
40
|
+
->resolve
|
|
40
41
|
expect(resourceInfo)->toEqual(
|
|
41
42
|
ReventlessInfra.Adapter.StorageKeys({partitionKey: "id", sortKey: Some("seq")}),
|
|
42
43
|
)
|
|
@@ -21,8 +21,8 @@ let throws = (f: unit => 'a): option<string> =>
|
|
|
21
21
|
|
|
22
22
|
describe("Util_LambdaEnvBudget.check", () => {
|
|
23
23
|
testSync("passes a small environment", () => {
|
|
24
|
-
let msg = throws(
|
|
25
|
-
Util_LambdaEnvBudget.check(~lambdaName="Small", ~handlerConfigJson=`{"queueUrl":"q"}`)
|
|
24
|
+
let msg = throws(
|
|
25
|
+
() => Util_LambdaEnvBudget.check(~lambdaName="Small", ~handlerConfigJson=`{"queueUrl":"q"}`),
|
|
26
26
|
)
|
|
27
27
|
expect(msg)->toEqual(None)
|
|
28
28
|
})
|
|
@@ -39,19 +39,21 @@ describe("Util_LambdaEnvBudget.check", () => {
|
|
|
39
39
|
testSync("counts the queue-URL var names toward the exact total", () => {
|
|
40
40
|
// Sized so HANDLER_CONFIG alone fits and the var NAMES alone push it over —
|
|
41
41
|
// the names are known at check time, so this must throw rather than warn.
|
|
42
|
-
let keys =
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
let keys =
|
|
43
|
+
Array.make(~length=40, "")->Array.mapWithIndex(
|
|
44
|
+
(_, i) => `PTA_AVeryLongAggregateNameNumber${i->Int.toString}_QUEUE_URL`,
|
|
45
|
+
)
|
|
45
46
|
let keyBytes = keys->Array.reduce(0, (acc, k) => acc + String.length(k))
|
|
46
47
|
let fixed = Util_LambdaEnvBudget.frameworkVarsBytes + String.length("HANDLER_CONFIG")
|
|
47
48
|
// Just past the limit on the exact total alone — the names are enough.
|
|
48
49
|
let json = String.repeat("a", budget - fixed - keyBytes + 1)
|
|
49
|
-
let msg = throws(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
let msg = throws(
|
|
51
|
+
() =>
|
|
52
|
+
Util_LambdaEnvBudget.check(
|
|
53
|
+
~lambdaName="ManyTargets",
|
|
54
|
+
~handlerConfigJson=json,
|
|
55
|
+
~outputValuedKeys=keys,
|
|
56
|
+
),
|
|
55
57
|
)
|
|
56
58
|
expect(msg->Option.isSome)->toBe(true)
|
|
57
59
|
})
|
|
@@ -59,19 +61,21 @@ describe("Util_LambdaEnvBudget.check", () => {
|
|
|
59
61
|
testSync("only estimating over the limit warns rather than throwing", () => {
|
|
60
62
|
// Exact total sits under the limit; it is the per-URL allowance that crosses
|
|
61
63
|
// it. The deploy must be allowed to proceed and find out.
|
|
62
|
-
let keys =
|
|
64
|
+
let keys =
|
|
65
|
+
Array.make(~length=20, "")->Array.mapWithIndex((_, i) => `PTA_A${i->Int.toString}_URL`)
|
|
63
66
|
let exact =
|
|
64
67
|
Util_LambdaEnvBudget.frameworkVarsBytes +
|
|
65
68
|
String.length("HANDLER_CONFIG") +
|
|
66
69
|
keys->Array.reduce(0, (acc, k) => acc + String.length(k))
|
|
67
70
|
let room = budget - exact - 100
|
|
68
71
|
let json = String.repeat("a", room)
|
|
69
|
-
let msg = throws(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
let msg = throws(
|
|
73
|
+
() =>
|
|
74
|
+
Util_LambdaEnvBudget.check(
|
|
75
|
+
~lambdaName="Estimated",
|
|
76
|
+
~handlerConfigJson=json,
|
|
77
|
+
~outputValuedKeys=keys,
|
|
78
|
+
),
|
|
75
79
|
)
|
|
76
80
|
expect(msg)->toEqual(None)
|
|
77
81
|
})
|
|
@@ -21,9 +21,9 @@ describe("Util_LambdaLogging.logGroupNameFor", () => {
|
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
testSync("is stack-scoped, so environments of one project cannot collide", () =>
|
|
24
|
-
expect(nameFor(~stack="pr-42", ~name="AllReadModels"))
|
|
25
|
-
|
|
26
|
-
)
|
|
24
|
+
expect(nameFor(~stack="pr-42", ~name="AllReadModels"))
|
|
25
|
+
->not_
|
|
26
|
+
->toBe(nameFor(~stack="alpha", ~name="AllReadModels"))
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
// The regression this scoping exists for. Every plugin of one platform is its
|
|
@@ -54,17 +54,18 @@ describe("Util_LambdaLogging.logGroupNameFor", () => {
|
|
|
54
54
|
// the estate and send an operator to a nonexistent group on the other half.
|
|
55
55
|
describe("Util_LambdaLogging.autoCreatedLogGroupNameFor", () => {
|
|
56
56
|
testSync("is the group Lambda makes from the PHYSICAL name, suffix and all", () =>
|
|
57
|
-
expect(
|
|
58
|
-
|
|
57
|
+
expect(
|
|
58
|
+
Util_LambdaLogging.autoCreatedLogGroupNameFor(~physicalName="AllReadModels-0287438"),
|
|
59
|
+
)->toBe("/aws/lambda/AllReadModels-0287438")
|
|
59
60
|
)
|
|
60
61
|
|
|
61
62
|
// The two shapes must not converge: the managed name is chosen from the static
|
|
62
63
|
// name so it survives a replacement, the auto-created one is not. If these ever
|
|
63
64
|
// matched, the managed group would be racing the auto-create it exists to avoid.
|
|
64
65
|
testSync("never equals the managed name for the same unit", () =>
|
|
65
|
-
expect(
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
expect(Util_LambdaLogging.autoCreatedLogGroupNameFor(~physicalName="AllReadModels-0287438"))
|
|
67
|
+
->not_
|
|
68
|
+
->toBe(
|
|
68
69
|
Util_LambdaLogging.logGroupNameFor(
|
|
69
70
|
~project="online-shop-catalog-aws",
|
|
70
71
|
~stack="alpha",
|
|
@@ -27,7 +27,10 @@ describe("Util_LogGroup_Adopting.isAlreadyExistsError", () => {
|
|
|
27
27
|
testSync("true for the error this provider exists to absorb", () =>
|
|
28
28
|
expect(
|
|
29
29
|
Adopting.isAlreadyExistsError(
|
|
30
|
-
mkErr(
|
|
30
|
+
mkErr(
|
|
31
|
+
~name="ResourceAlreadyExistsException",
|
|
32
|
+
~message="The specified log group already exists",
|
|
33
|
+
),
|
|
31
34
|
),
|
|
32
35
|
)->toBe(true)
|
|
33
36
|
)
|
|
@@ -42,7 +45,9 @@ describe("Util_LogGroup_Adopting.isAlreadyExistsError", () => {
|
|
|
42
45
|
|
|
43
46
|
testSync("false for a permission failure, which must still fail loudly", () =>
|
|
44
47
|
expect(
|
|
45
|
-
Adopting.isAlreadyExistsError(
|
|
48
|
+
Adopting.isAlreadyExistsError(
|
|
49
|
+
mkErr(~name="AccessDeniedException", ~message="not authorized"),
|
|
50
|
+
),
|
|
46
51
|
)->toBe(false)
|
|
47
52
|
)
|
|
48
53
|
})
|
|
@@ -85,9 +90,9 @@ describe("Util_LogGroup_Adopting.sameTags", () => {
|
|
|
85
90
|
)
|
|
86
91
|
|
|
87
92
|
testSync("sees a changed value", () =>
|
|
88
|
-
expect(
|
|
89
|
-
|
|
90
|
-
)
|
|
93
|
+
expect(Adopting.sameTags(Dict.fromArray([("a", "1")]), Dict.fromArray([("a", "2")])))->toBe(
|
|
94
|
+
false,
|
|
95
|
+
)
|
|
91
96
|
)
|
|
92
97
|
|
|
93
98
|
testSync("sees an added key", () =>
|
|
@@ -39,11 +39,15 @@ describe("Util_LogRetention.retentionDaysFor", () => {
|
|
|
39
39
|
// The config key is the escape hatch — a stack dialled without a code change,
|
|
40
40
|
// including `0` (never expire) as an explicit opt-in.
|
|
41
41
|
testSync("a config override wins over the tier default", () =>
|
|
42
|
-
expect(
|
|
42
|
+
expect(
|
|
43
|
+
Util_LogRetention.retentionDaysFor(~stack="alpha", ~prodStacks, ~configOverride=14),
|
|
44
|
+
)->toBe(14)
|
|
43
45
|
)
|
|
44
46
|
|
|
45
47
|
testSync("0 = never expire is expressible via the override", () =>
|
|
46
|
-
expect(Util_LogRetention.retentionDaysFor(~stack="prod", ~prodStacks, ~configOverride=0))->toBe(
|
|
48
|
+
expect(Util_LogRetention.retentionDaysFor(~stack="prod", ~prodStacks, ~configOverride=0))->toBe(
|
|
49
|
+
0,
|
|
50
|
+
)
|
|
47
51
|
)
|
|
48
52
|
})
|
|
49
53
|
|
|
@@ -19,11 +19,13 @@ let withElevated = (groups, f) => {
|
|
|
19
19
|
|
|
20
20
|
describe("Util_OwnerScopeEnv — the elevated-groups carrier", () => {
|
|
21
21
|
testSync("writes what OwnerScope reads back", () => {
|
|
22
|
-
let encoded = withElevated(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
let encoded = withElevated(
|
|
23
|
+
["Admin", "Support"],
|
|
24
|
+
() =>
|
|
25
|
+
switch Util_OwnerScopeEnv.entry() {
|
|
26
|
+
| Some((_, value)) => value->Obj.magic
|
|
27
|
+
| None => ""
|
|
28
|
+
},
|
|
27
29
|
)
|
|
28
30
|
// The round trip, not the spelling: a separator change on either side fails.
|
|
29
31
|
expect(Reventless.OwnerScope.parseElevatedGroups(encoded))->toEqual(["Admin", "Support"])
|
|
@@ -47,9 +49,9 @@ describe("Util_OwnerScopeEnv — the elevated-groups carrier", () => {
|
|
|
47
49
|
testSync("a caller that pinned the variable wins", () => {
|
|
48
50
|
let variables = Dict.fromArray([(Util_OwnerScopeEnv.key, "Pinned"->Obj.magic)])
|
|
49
51
|
withElevated(["Admin"], () => Util_OwnerScopeEnv.applyElevatedGroupsDefault(variables))
|
|
50
|
-
expect(
|
|
51
|
-
"
|
|
52
|
-
)
|
|
52
|
+
expect(
|
|
53
|
+
variables->Dict.get(Util_OwnerScopeEnv.key)->Option.getOr(""->Obj.magic)->Obj.magic,
|
|
54
|
+
)->toBe("Pinned")
|
|
53
55
|
})
|
|
54
56
|
|
|
55
57
|
testSync("adds nothing when the deployment named no elevated groups", () => {
|
|
@@ -57,4 +59,29 @@ describe("Util_OwnerScopeEnv — the elevated-groups carrier", () => {
|
|
|
57
59
|
withElevated([], () => Util_OwnerScopeEnv.applyElevatedGroupsDefault(variables))
|
|
58
60
|
expect(variables->Dict.get(Util_OwnerScopeEnv.key)->Option.isNone)->toBe(true)
|
|
59
61
|
})
|
|
62
|
+
|
|
63
|
+
// The whole path the "administrator sees empty screens" trap ran through: the
|
|
64
|
+
// platform entry point defaults the list, and this composes it into a Lambda's
|
|
65
|
+
// environment. Asserted end to end rather than at either half, because both
|
|
66
|
+
// halves were already correct while the trap was open — the pipe was laid and
|
|
67
|
+
// nothing ever put a value in.
|
|
68
|
+
testSync("the platform's administrator default reaches a composed environment", () => {
|
|
69
|
+
Reventless.OwnerScope.clearElevatedGroups()
|
|
70
|
+
NodeProcess.env->Dict.delete(Util_OwnerScopeEnv.key)
|
|
71
|
+
Reventless.OwnerScope.defaultElevatedGroups([Reventless.AdminGroup.name])
|
|
72
|
+
|
|
73
|
+
let variables = Dict.make()
|
|
74
|
+
Util_OwnerScopeEnv.applyElevatedGroupsDefault(variables)
|
|
75
|
+
let encoded = switch variables->Dict.get(Util_OwnerScopeEnv.key) {
|
|
76
|
+
| Some(value) => value->Obj.magic
|
|
77
|
+
| None => ""
|
|
78
|
+
}
|
|
79
|
+
Reventless.OwnerScope.clearElevatedGroups()
|
|
80
|
+
|
|
81
|
+
// Round-tripped, like the first case above: the runtime reads this back with
|
|
82
|
+
// `parseElevatedGroups`, so the encoding is asserted rather than the spelling.
|
|
83
|
+
expect(Reventless.OwnerScope.parseElevatedGroups(encoded))->toEqual([
|
|
84
|
+
Reventless.AdminGroup.name,
|
|
85
|
+
])
|
|
86
|
+
})
|
|
60
87
|
})
|