@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
|
@@ -5,55 +5,75 @@ open JestGlobals
|
|
|
5
5
|
// to JsExn.t so we can call isFieldNotFoundError without a real throw/catch.
|
|
6
6
|
type testError = {name: string, message: string}
|
|
7
7
|
|
|
8
|
-
let mkErr = (~name, ~message): JsExn.t =>
|
|
9
|
-
Obj.magic(({name, message}: testError))
|
|
8
|
+
let mkErr = (~name, ~message): JsExn.t => Obj.magic(({name, message}: testError))
|
|
10
9
|
|
|
11
10
|
describe("AppSync_Resolver_Retrying.isFieldNotFoundError", () => {
|
|
12
11
|
describe("returns true", () => {
|
|
13
|
-
testSync(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
testSync(
|
|
13
|
+
"NotFoundException with 'No field named' message",
|
|
14
|
+
() => {
|
|
15
|
+
let err = mkErr(
|
|
16
|
+
~name="NotFoundException",
|
|
17
|
+
~message="No field named createFoo found on type Mutation",
|
|
18
|
+
)
|
|
19
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(err))->toBe(true)
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
testSync(
|
|
24
|
+
"NotFoundException with 'No field named' on Query type",
|
|
25
|
+
() => {
|
|
26
|
+
let err = mkErr(
|
|
27
|
+
~name="NotFoundException",
|
|
28
|
+
~message="No field named bar found on type Query",
|
|
29
|
+
)
|
|
30
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(err))->toBe(true)
|
|
31
|
+
},
|
|
32
|
+
)
|
|
28
33
|
})
|
|
29
34
|
|
|
30
35
|
describe("returns false", () => {
|
|
31
|
-
testSync(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
36
|
+
testSync(
|
|
37
|
+
"NotFoundException with 'No resolver found' (delete-path — must not retry)",
|
|
38
|
+
() => {
|
|
39
|
+
let err = mkErr(
|
|
40
|
+
~name="NotFoundException",
|
|
41
|
+
~message="No resolver found for type Query field foo",
|
|
42
|
+
)
|
|
43
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(err))->toBe(false)
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
testSync(
|
|
48
|
+
"ThrottlingException",
|
|
49
|
+
() => {
|
|
50
|
+
let err = mkErr(~name="ThrottlingException", ~message="Rate exceeded")
|
|
51
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(err))->toBe(false)
|
|
52
|
+
},
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
testSync(
|
|
56
|
+
"NotFoundException with unrelated message",
|
|
57
|
+
() => {
|
|
58
|
+
let err = mkErr(~name="NotFoundException", ~message="API not found")
|
|
59
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(err))->toBe(false)
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
testSync(
|
|
64
|
+
"non-exception value (integer)",
|
|
65
|
+
() => {
|
|
66
|
+
let notErr: JsExn.t = Obj.magic(42)
|
|
67
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(notErr))->toBe(false)
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
testSync(
|
|
72
|
+
"non-exception value (plain object without name)",
|
|
73
|
+
() => {
|
|
74
|
+
let notErr: JsExn.t = Obj.magic({"message": "something went wrong"})
|
|
75
|
+
expect(AppSync_Resolver_Retrying.isFieldNotFoundError(notErr))->toBe(false)
|
|
76
|
+
},
|
|
77
|
+
)
|
|
58
78
|
})
|
|
59
79
|
})
|
|
@@ -25,15 +25,18 @@ let shelf = (~includeOwner: bool) =>
|
|
|
25
25
|
describe("the single-entity door", () => {
|
|
26
26
|
testSync("withholds a retired row until an exempt caller asks", () => {
|
|
27
27
|
let code = shelf(~includeOwner=false)
|
|
28
|
-
expect(
|
|
29
|
-
|
|
28
|
+
expect(
|
|
29
|
+
code->String.includes("const _wantsRetired = _exempt && ctx.args.includeRetired === true"),
|
|
30
|
+
)->Expect.toBe(true)
|
|
30
31
|
expect(code->String.includes("_live(ctx.result) ? ctx.result : null"))->Expect.toBe(true)
|
|
31
32
|
})
|
|
32
33
|
|
|
33
34
|
// Absent attribute keeps the row: a row written before the annotation existed
|
|
34
35
|
// is not retired, which is what stops a view emptying the day it lands.
|
|
35
36
|
testSync("reads a missing attribute as not retired", () =>
|
|
36
|
-
expect(shelf(~includeOwner=false)->String.includes("row['shelfStatus'] == null"))->Expect.toBe(
|
|
37
|
+
expect(shelf(~includeOwner=false)->String.includes("row['shelfStatus'] == null"))->Expect.toBe(
|
|
38
|
+
true,
|
|
39
|
+
)
|
|
37
40
|
)
|
|
38
41
|
|
|
39
42
|
testSync("tests membership of the retiring states, not equality with one", () =>
|
|
@@ -48,16 +51,19 @@ describe("the single-entity door", () => {
|
|
|
48
51
|
// preamble's copy is the only one when both guards are present.
|
|
49
52
|
testSync("declares the exemption test once when owner scoping is also on", () => {
|
|
50
53
|
let code = shelf(~includeOwner=true)
|
|
51
|
-
let occurrences =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
let occurrences = code->String.split("const _exempt =")->Array.length - 1
|
|
55
|
+
expect((
|
|
56
|
+
occurrences,
|
|
57
|
+
code->String.includes("_owns(ctx.result) && _live(ctx.result)"),
|
|
58
|
+
))->Expect.toEqual((1, true))
|
|
55
59
|
})
|
|
56
60
|
|
|
57
61
|
testSync("is unchanged for a view that declares no retirement", () => {
|
|
58
62
|
let code = F.getItemById(~elevatedGroups=elevated)->asString
|
|
59
|
-
expect((
|
|
60
|
-
|
|
63
|
+
expect((
|
|
64
|
+
code->String.includes("_wantsRetired"),
|
|
65
|
+
code->String.includes("includeRetired"),
|
|
66
|
+
))->Expect.toEqual((false, false))
|
|
61
67
|
})
|
|
62
68
|
})
|
|
63
69
|
|
|
@@ -79,19 +85,19 @@ describe("the by-ids door", () => {
|
|
|
79
85
|
)
|
|
80
86
|
|
|
81
87
|
testSync("is unchanged for a view that declares no retirement", () =>
|
|
82
|
-
expect(F.batchGetItemsByIds()("ProductsTable")->String.includes("_live"))
|
|
83
|
-
->Expect.toBe(false)
|
|
88
|
+
expect(F.batchGetItemsByIds()("ProductsTable")->String.includes("_live"))->Expect.toBe(false)
|
|
84
89
|
)
|
|
85
90
|
})
|
|
86
91
|
|
|
87
92
|
describe("the by-index door", () => {
|
|
88
|
-
let code =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
let code =
|
|
94
|
+
F.queryByIndexFiltered(
|
|
95
|
+
~index="byCategory",
|
|
96
|
+
~idField="categoryId",
|
|
97
|
+
~retiredField="shelfStatus",
|
|
98
|
+
~retiredValues=["Archived", "Discontinued"],
|
|
99
|
+
~elevatedGroups=elevated,
|
|
100
|
+
)->asString
|
|
95
101
|
|
|
96
102
|
// A Query takes a FilterExpression, so the predicate is pushed into the read.
|
|
97
103
|
// Narrowing after it would hand back fewer rows than `limit` asked for and say
|
|
@@ -121,8 +127,7 @@ describe("the by-index door", () => {
|
|
|
121
127
|
|
|
122
128
|
describe("the boolean form", () => {
|
|
123
129
|
testSync("tests the flag rather than a set of states", () => {
|
|
124
|
-
let code =
|
|
125
|
-
F.getItemById(~elevatedGroups=elevated, ~retiredField="archived")->asString
|
|
130
|
+
let code = F.getItemById(~elevatedGroups=elevated, ~retiredField="archived")->asString
|
|
126
131
|
expect((
|
|
127
132
|
code->String.includes("row['archived'] === true"),
|
|
128
133
|
code->String.includes("indexOf(row["),
|
|
@@ -153,18 +158,21 @@ describe("the by-ids door's owner scoping", () => {
|
|
|
153
158
|
|
|
154
159
|
testSync("is unchanged for a view with neither rule", () => {
|
|
155
160
|
let plain = F.batchGetItemsByIds()("Orders")
|
|
156
|
-
expect((plain->String.includes("_owns"), plain->String.includes("_live")))
|
|
157
|
-
|
|
161
|
+
expect((plain->String.includes("_owns"), plain->String.includes("_live")))->Expect.toEqual((
|
|
162
|
+
false,
|
|
163
|
+
false,
|
|
164
|
+
))
|
|
158
165
|
})
|
|
159
166
|
})
|
|
160
167
|
|
|
161
168
|
describe("the by-index door's owner scoping", () => {
|
|
162
|
-
let code =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
let code =
|
|
170
|
+
F.queryByIndexFiltered(
|
|
171
|
+
~index="byCategory",
|
|
172
|
+
~idField="categoryId",
|
|
173
|
+
~ownerField="customerId",
|
|
174
|
+
~elevatedGroups=elevated,
|
|
175
|
+
)->asString
|
|
168
176
|
|
|
169
177
|
testSync("pushes the owner predicate into the read", () =>
|
|
170
178
|
expect(code->String.includes("names['#owner'] = 'customerId'"))->Expect.toBe(true)
|
|
@@ -178,7 +186,9 @@ describe("the by-index door's owner scoping", () => {
|
|
|
178
186
|
|
|
179
187
|
testSync("exempts an elevated caller and an IAM service call", () =>
|
|
180
188
|
expect(
|
|
181
|
-
code->String.includes(
|
|
189
|
+
code->String.includes(
|
|
190
|
+
"if (!(_osub == null || _ogroups.some(g => _oelevated.indexOf(g) >= 0)))",
|
|
191
|
+
),
|
|
182
192
|
)->Expect.toBe(true)
|
|
183
193
|
)
|
|
184
194
|
|
|
@@ -196,8 +206,7 @@ describe("the by-index door's owner scoping", () => {
|
|
|
196
206
|
// field that promised a Connection. These assert the two halves that were wrong,
|
|
197
207
|
// beside the paging arguments the field actually offers.
|
|
198
208
|
describe("the by-index door answers the field it is attached to", () => {
|
|
199
|
-
let code =
|
|
200
|
-
F.queryByIndexFiltered(~index="byCategory", ~idField="categoryId")->asString
|
|
209
|
+
let code = F.queryByIndexFiltered(~index="byCategory", ~idField="categoryId")->asString
|
|
201
210
|
|
|
202
211
|
testSync("keys the read on the index column the SDL offers", () =>
|
|
203
212
|
expect(code->String.includes("util.dynamodb.toDynamoDB(args.categoryId)"))->Expect.toBe(true)
|
|
@@ -226,8 +235,8 @@ describe("the by-index door answers the field it is attached to", () => {
|
|
|
226
235
|
// reaching the generic filter loop would filter on an attribute no row has.
|
|
227
236
|
testSync("keeps every paging argument out of the filter loop", () =>
|
|
228
237
|
expect(
|
|
229
|
-
["first", "after", "last", "before", "includeRetired"]->Array.every(
|
|
230
|
-
code->String.includes(`key === '${arg}'`)
|
|
238
|
+
["first", "after", "last", "before", "includeRetired"]->Array.every(
|
|
239
|
+
arg => code->String.includes(`key === '${arg}'`),
|
|
231
240
|
),
|
|
232
241
|
)->Expect.toBe(true)
|
|
233
242
|
)
|
|
@@ -264,8 +273,10 @@ describe("the by-index door's backward paging", () => {
|
|
|
264
273
|
let code = F.queryByIndexFiltered(~index="byCategory", ~idField="categoryId")->asString
|
|
265
274
|
let guardAt = code->String.indexOf("args.before != null")
|
|
266
275
|
let queryAt = code->String.indexOf("expressionValues")
|
|
267
|
-
expect((
|
|
268
|
-
|
|
276
|
+
expect((
|
|
277
|
+
guardAt >= 0 && guardAt < queryAt,
|
|
278
|
+
code->String.includes("'UnsupportedPagination'"),
|
|
279
|
+
))->Expect.toEqual((true, true))
|
|
269
280
|
})
|
|
270
281
|
})
|
|
271
282
|
|
|
@@ -280,13 +291,12 @@ describe("the unowned stub is callable where the door calls it", () => {
|
|
|
280
291
|
// calls it: with neither rule the guard is not emitted at all, and with an
|
|
281
292
|
// owner the real one-parameter test replaces it.
|
|
282
293
|
testSync("declares a parameter on the single-entity door", () => {
|
|
283
|
-
let code =
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
)
|
|
294
|
+
let code = F.ownerScopedResultResponse(
|
|
295
|
+
~ownerField=None,
|
|
296
|
+
~elevatedGroups=elevated,
|
|
297
|
+
~retiredField="lifecycle",
|
|
298
|
+
~retiredValues=["Archived"],
|
|
299
|
+
)
|
|
290
300
|
expect((
|
|
291
301
|
code->String.includes("const _owns = (row) => true;"),
|
|
292
302
|
code->String.includes("const _owns = () => true;"),
|
|
@@ -363,8 +373,9 @@ describe("the cross-table single door", () => {
|
|
|
363
373
|
)
|
|
364
374
|
|
|
365
375
|
testSync("narrows the one row it hands back", () =>
|
|
366
|
-
expect(
|
|
367
|
-
|
|
376
|
+
expect(
|
|
377
|
+
response(~multi=false)->String.includes("_owns(_row) && _live(_row) ? _row : null"),
|
|
378
|
+
)->Expect.toBe(true)
|
|
368
379
|
)
|
|
369
380
|
|
|
370
381
|
testSync("narrows every row of the list form", () =>
|
|
@@ -380,7 +391,9 @@ describe("the cross-table single door", () => {
|
|
|
380
391
|
|
|
381
392
|
testSync("a target with neither rule keeps the plain response", () => {
|
|
382
393
|
let plain = F.resolvedFieldResponse(~multi=false, ~ownerField=None, ~elevatedGroups=elevated)
|
|
383
|
-
expect((
|
|
384
|
-
|
|
394
|
+
expect((
|
|
395
|
+
plain->String.includes("_owns"),
|
|
396
|
+
plain->String.includes("ctx.result.items[0]"),
|
|
397
|
+
))->toEqual((false, true))
|
|
385
398
|
})
|
|
386
399
|
})
|
|
@@ -38,19 +38,22 @@ type Subscription {
|
|
|
38
38
|
describe("AppSync_SdlDecorate.injectAwsSubscribe", () => {
|
|
39
39
|
testSync("appends @aws_subscribe on a 1:1 mutation-sourced field (with args)", () => {
|
|
40
40
|
let sdl = AppSync_SdlDecorate.injectAwsSubscribe(stitchedSdl, ~sources)
|
|
41
|
-
expect(
|
|
42
|
-
|
|
43
|
-
)
|
|
41
|
+
expect(
|
|
42
|
+
sdl,
|
|
43
|
+
)->toContain(`onCatalog_AddProduct(id: ID): CommandResult\n @aws_subscribe(mutations: ["Catalog_AddProduct"])`)
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
-
testSync(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
testSync(
|
|
47
|
+
"appends the many-mutations fan-in on a no-arg field, keeping the group directive",
|
|
48
|
+
() => {
|
|
49
|
+
let sdl = AppSync_SdlDecorate.injectAwsSubscribe(stitchedSdl, ~sources)
|
|
50
|
+
expect(
|
|
51
|
+
sdl,
|
|
52
|
+
)->toContain(`onUIFragmentChange: UIFragmentChangeEvent\n @aws_subscribe(mutations: ["Platform_UIFragmentRegistered", "Platform_UIFragmentUpdated", "Platform_UIFragmentDeregistered"])`)
|
|
53
|
+
// The auth directive line appended by injectAwsAuthAll survives.
|
|
54
|
+
expect(sdl)->toContain(`@aws_cognito_user_pools(cognito_groups: ["Admin"])`)
|
|
55
|
+
},
|
|
56
|
+
)
|
|
54
57
|
|
|
55
58
|
testSync("leaves unmapped fields (Source A) and non-Subscription blocks untouched", () => {
|
|
56
59
|
let sdl = AppSync_SdlDecorate.injectAwsSubscribe(stitchedSdl, ~sources)
|
|
@@ -71,7 +74,9 @@ describe("AppSync_Adapter.stitchStandaloneWithAwsDirectives", () => {
|
|
|
71
74
|
testSync("assembles a neutral fragment into an AWS-dialect standalone document", () => {
|
|
72
75
|
let fragment = ReventlessCore.GraphQL_Stitcher.encode({
|
|
73
76
|
types: [`type PluginStatusChangeEvent {\n pluginId: ID!\n}`],
|
|
74
|
-
mutations: [
|
|
77
|
+
mutations: [
|
|
78
|
+
` Platform_PluginStatusChanged(pluginId: ID!, status: PluginStatus!): PluginStatusChangeEvent`,
|
|
79
|
+
],
|
|
75
80
|
queries: [],
|
|
76
81
|
subscriptions: [` onPluginStatusChange: PluginStatusChangeEvent`],
|
|
77
82
|
subscriptionSources: [
|
|
@@ -118,7 +123,6 @@ describe("AppSync_SdlDecorate.injectAwsAuthAll", () => {
|
|
|
118
123
|
})
|
|
119
124
|
})
|
|
120
125
|
|
|
121
|
-
|
|
122
126
|
describe("AppSync_SdlDecorate.stampSharedIamTypes", () => {
|
|
123
127
|
testSync("stamps the CommandResult members", () => {
|
|
124
128
|
let sdl = AppSync_SdlDecorate.stampSharedIamTypes("type CommandAccepted {\n id: ID!\n}")
|
|
@@ -236,9 +240,9 @@ describe("AppSync_SdlDecorate.stampUndirectivedFields", () => {
|
|
|
236
240
|
testSync("does not strip an @aws_iam arm", () => {
|
|
237
241
|
let dual = " Sys_Sync: String\n @aws_cognito_user_pools @aws_iam"
|
|
238
242
|
let out = AppSync_SdlDecorate.stampUndirectivedFields(frag(~mutations=[dual], ()))
|
|
239
|
-
expect(
|
|
240
|
-
|
|
241
|
-
)
|
|
243
|
+
expect(ReventlessCore.GraphQL_Stitcher.decode(out).mutations->Array.getUnsafe(0))->toContain(
|
|
244
|
+
"@aws_iam",
|
|
245
|
+
)
|
|
242
246
|
})
|
|
243
247
|
|
|
244
248
|
testSync("is idempotent", () => {
|
|
@@ -277,8 +281,7 @@ describe("AppSync_SdlDecorate.assertGateable", () => {
|
|
|
277
281
|
})
|
|
278
282
|
|
|
279
283
|
testSync("refuses an object type carrying no enforced directive", () => {
|
|
280
|
-
let sdl =
|
|
281
|
-
"type Query @aws_cognito_user_pools {\n a: String @aws_cognito_user_pools\n}\ntype Product {\n id: ID!\n}"
|
|
284
|
+
let sdl = "type Query @aws_cognito_user_pools {\n a: String @aws_cognito_user_pools\n}\ntype Product {\n id: ID!\n}"
|
|
282
285
|
expect(refuses(sdl))->toBe(true)
|
|
283
286
|
})
|
|
284
287
|
|
|
@@ -289,8 +292,7 @@ describe("AppSync_SdlDecorate.assertGateable", () => {
|
|
|
289
292
|
})
|
|
290
293
|
|
|
291
294
|
testSync("accepts a group-gated field and an @aws_iam-only field", () => {
|
|
292
|
-
let sdl =
|
|
293
|
-
`type Mutation @aws_cognito_user_pools {\n Gated: String\n @aws_cognito_user_pools(cognito_groups: ["Admin"])\n Sys: String\n @aws_cognito_user_pools @aws_iam\n}`
|
|
295
|
+
let sdl = `type Mutation @aws_cognito_user_pools {\n Gated: String\n @aws_cognito_user_pools(cognito_groups: ["Admin"])\n Sys: String\n @aws_cognito_user_pools @aws_iam\n}`
|
|
294
296
|
expect(refuses(sdl))->toBe(false)
|
|
295
297
|
})
|
|
296
298
|
|
|
@@ -9,7 +9,10 @@ module Assoc = AppSync_SourceApiAssociation_Retrying
|
|
|
9
9
|
|
|
10
10
|
describe("AppSync_SourceApiAssociation_Retrying.isConcurrentModificationError", () => {
|
|
11
11
|
testSync("true for ConcurrentModificationException by name", () => {
|
|
12
|
-
let err = mkErr(
|
|
12
|
+
let err = mkErr(
|
|
13
|
+
~name="ConcurrentModificationException",
|
|
14
|
+
~message="Schema is currently being merged",
|
|
15
|
+
)
|
|
13
16
|
expect(Assoc.isConcurrentModificationError(err))->toBe(true)
|
|
14
17
|
})
|
|
15
18
|
|
|
@@ -32,32 +35,47 @@ describe("AppSync_SourceApiAssociation_Retrying.isRetryableAssociationError", ()
|
|
|
32
35
|
"TooManyRequestsException",
|
|
33
36
|
"InternalFailureException",
|
|
34
37
|
"ServiceUnavailableException",
|
|
35
|
-
]->Array.forEach(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
]->Array.forEach(
|
|
39
|
+
name =>
|
|
40
|
+
testSync(
|
|
41
|
+
name,
|
|
42
|
+
() => {
|
|
43
|
+
expect(Assoc.isRetryableAssociationError(mkErr(~name, ~message="x")))->toBe(true)
|
|
44
|
+
},
|
|
45
|
+
),
|
|
39
46
|
)
|
|
40
47
|
})
|
|
41
48
|
|
|
42
49
|
describe("returns false", () => {
|
|
43
|
-
testSync(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
),
|
|
54
|
-
)->toBe(false)
|
|
55
|
-
})
|
|
50
|
+
testSync(
|
|
51
|
+
"permanent ValidationException",
|
|
52
|
+
() => {
|
|
53
|
+
expect(
|
|
54
|
+
Assoc.isRetryableAssociationError(
|
|
55
|
+
mkErr(~name="ValidationException", ~message="bad input"),
|
|
56
|
+
),
|
|
57
|
+
)->toBe(false)
|
|
58
|
+
},
|
|
59
|
+
)
|
|
56
60
|
|
|
57
|
-
testSync(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
testSync(
|
|
62
|
+
"NotFoundException (a delete no-op, not a retry)",
|
|
63
|
+
() => {
|
|
64
|
+
expect(
|
|
65
|
+
Assoc.isRetryableAssociationError(
|
|
66
|
+
mkErr(~name="NotFoundException", ~message="association not found"),
|
|
67
|
+
),
|
|
68
|
+
)->toBe(false)
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
testSync(
|
|
73
|
+
"non-exception value",
|
|
74
|
+
() => {
|
|
75
|
+
let notErr: JsExn.t = Obj.magic(42)
|
|
76
|
+
expect(Assoc.isRetryableAssociationError(notErr))->toBe(false)
|
|
77
|
+
},
|
|
78
|
+
)
|
|
61
79
|
})
|
|
62
80
|
})
|
|
63
81
|
|