GraphqlApi L2 construct
An AppSync GraphQL API.
Example
const schema = new appsync.SchemaFile({ filePath: 'mySchemaFile' })
new appsync.GraphqlApi(this, 'api', {
name: 'myApi',
definition: appsync.Definition.fromSchema(schema),
enhancedMetricsConfig: {
dataSourceLevelMetricsBehavior: appsync.DataSourceLevelMetricsBehavior.FULL_REQUEST_DATA_SOURCE_METRICS,
operationLevelMetricsConfig: appsync.OperationLevelMetricsConfig.ENABLED,
resolverLevelMetricsBehavior: appsync.ResolverLevelMetricsBehavior.FULL_REQUEST_RESOLVER_METRICS,
},
});
schema = appsync.SchemaFile(file_path="mySchemaFile")
appsync.GraphqlApi(self, "api",
name="myApi",
definition=appsync.Definition.from_schema(schema),
enhanced_metrics_config=appsync.EnhancedMetricsConfig(
data_source_level_metrics_behavior=appsync.DataSourceLevelMetricsBehavior.FULL_REQUEST_DATA_SOURCE_METRICS,
operation_level_metrics_config=appsync.OperationLevelMetricsConfig.ENABLED,
resolver_level_metrics_behavior=appsync.ResolverLevelMetricsBehavior.FULL_REQUEST_RESOLVER_METRICS
)
)
SchemaFile schema = SchemaFile.Builder.create().filePath("mySchemaFile").build();
GraphqlApi.Builder.create(this, "api")
.name("myApi")
.definition(Definition.fromSchema(schema))
.enhancedMetricsConfig(EnhancedMetricsConfig.builder()
.dataSourceLevelMetricsBehavior(DataSourceLevelMetricsBehavior.FULL_REQUEST_DATA_SOURCE_METRICS)
.operationLevelMetricsConfig(OperationLevelMetricsConfig.ENABLED)
.resolverLevelMetricsBehavior(ResolverLevelMetricsBehavior.FULL_REQUEST_RESOLVER_METRICS)
.build())
.build();
// Install: dotnet add package Amazon.CDK.Lib
var schema = new SchemaFile(new SchemaProps { FilePath = "mySchemaFile" });
new GraphqlApi(this, "api", new GraphqlApiProps {
Name = "myApi",
Definition = Definition.FromSchema(schema),
EnhancedMetricsConfig = new EnhancedMetricsConfig {
DataSourceLevelMetricsBehavior = DataSourceLevelMetricsBehavior.FULL_REQUEST_DATA_SOURCE_METRICS,
OperationLevelMetricsConfig = OperationLevelMetricsConfig.ENABLED,
ResolverLevelMetricsBehavior = ResolverLevelMetricsBehavior.FULL_REQUEST_RESOLVER_METRICS
}
});
// Install: go get github.com/aws/aws-cdk-go/awscdk/v2
schema := appsync.NewSchemaFile(&SchemaProps{
FilePath: jsii.String("mySchemaFile"),
})
appsync.NewGraphqlApi(this, jsii.String("api"), &GraphqlApiProps{
Name: jsii.String("myApi"),
Definition: appsync.Definition_FromSchema(schema),
EnhancedMetricsConfig: &EnhancedMetricsConfig{
DataSourceLevelMetricsBehavior: appsync.DataSourceLevelMetricsBehavior_FULL_REQUEST_DATA_SOURCE_METRICS,
OperationLevelMetricsConfig: appsync.OperationLevelMetricsConfig_ENABLED,
ResolverLevelMetricsBehavior: appsync.ResolverLevelMetricsBehavior_FULL_REQUEST_RESOLVER_METRICS,
},
})
Initializer
new GraphqlApi(scope: Construct, id: string, props: GraphqlApiProps)
GraphqlApi(scope: Construct, id: str, props: GraphqlApiProps)
new GraphqlApi(Construct scope, String id, GraphqlApiProps props)
new GraphqlApi(Construct scope, string id, GraphqlApiProps props)
NewGraphqlApi(Scope Construct, Id *string, Props GraphqlApiProps)
Construct Props
authorizationConfigoptionalAuthorizationConfigauthorization_configoptionalAuthorizationConfigauthorizationConfigoptionalAuthorizationConfigAuthorizationConfigoptionalAuthorizationConfigAuthorizationConfigoptionalAuthorizationConfig#Default: API Key authorization
definitionoptionalDefinitiondefinitionoptionalDefinitiondefinitionoptionalDefinitionDefinitionoptionalDefinitionDefinitionoptionalDefinition#domainNameoptionalDomainOptionsdomain_nameoptionalDomainOptionsdomainNameoptionalDomainOptionsDomainNameoptionalDomainOptionsDomainNameoptionalDomainOptions#Default: no domain name
The Route 53 hosted zone and CName DNS record must be configured in addition to this setting to enable custom domain URL
enhancedMetricsConfigoptionalEnhancedMetricsConfigenhanced_metrics_configoptionalEnhancedMetricsConfigenhancedMetricsConfigoptionalEnhancedMetricsConfigEnhancedMetricsConfigoptionalEnhancedMetricsConfigEnhancedMetricsConfigoptionalEnhancedMetricsConfig#Default: Enhanced metrics disabled.
environmentVariablesoptional{ [key: string]: string }environment_variablesoptionaltyping.Mapping[str, str]environmentVariablesoptionalMap<String, String>EnvironmentVariablesoptionalIDictionary<string, string>EnvironmentVariablesoptional*map[string]*string#Default: No environment variables.
notes
There are a few rules you must follow when creating keys and values:
- Keys must begin with a letter.
- Keys must be between 2 and 64 characters long.
- Keys can only contain letters, numbers, and the underscore character (_).
- Values can be up to 512 characters long.
- You can configure up to 50 key-value pairs in a GraphQL API.
introspectionConfigoptionalIntrospectionConfigintrospection_configoptionalIntrospectionConfigintrospectionConfigoptionalIntrospectionConfigIntrospectionConfigoptionalIntrospectionConfigIntrospectionConfigoptionalIntrospectionConfig= IntrospectionConfig.ENABLED#logConfigoptionalLogConfiglog_configoptionalLogConfiglogConfigoptionalLogConfigLogConfigoptionalLogConfigLogConfigoptionalLogConfig= None#ownerContactoptionalstringowner_contactoptionalstrownerContactoptionalStringOwnerContactoptionalstringOwnerContactoptional*string#Default: No owner contact.
This field accepts any string input with a length of 0 - 256 characters.
queryDepthLimitoptionalnumberquery_depth_limitoptionalint | floatqueryDepthLimitoptionalNumberQueryDepthLimitoptionaldoubleQueryDepthLimitoptional*float64#Default: The default value is 0 (or unspecified) which indicates no maximum depth.
Value must be withing range of 0 to 75
resolverCountLimitoptionalnumberresolver_count_limitoptionalint | floatresolverCountLimitoptionalNumberResolverCountLimitoptionaldoubleResolverCountLimitoptional*float64#Default: The default value is 0 (or unspecified), which will set the limit to 10000
Value must be withing range of 0 to 10000
schemaoptionalISchemaschemaoptionalISchemaschemaoptionalISchemaSchemaoptionalISchemaSchemaoptionalISchemadeprecated#Default: schema will be generated code-first (i.e. addType, addObjectType, etc.)
SchemaFile.fromAsset(filePath: string) allows schema definition through schema.graphql file
visibilityoptionalVisibilityvisibilityoptionalVisibilityvisibilityoptionalVisibilityVisibilityoptionalVisibilityVisibilityoptionalVisibility= GLOBAL#xrayEnabledoptionalbooleanxray_enabledoptionalboolxrayEnabledoptionalBooleanXrayEnabledoptionalboolXrayEnabledoptional*bool= false#Properties
apiKeymay be undefinedstringapi_keymay be undefinedstrapiKeymay be undefinedStringApiKeymay be undefinedstringApiKeymay be undefined*string#Default: no api key
appSyncDomainNamestringapp_sync_domain_namestrappSyncDomainNameStringAppSyncDomainNamestringAppSyncDomainName*stringrequired#envResourceEnvironmentenvResourceEnvironmentenvResourceEnvironmentEnvResourceEnvironmentEnvResourceEnvironmentrequired#notes
For resources that are created and managed in a Stack (those created by creating new class instances like new Role(), new Bucket(), etc.), this is always the same as the environment of the stack they belong to.
For referenced resources (those obtained from referencing methods like Role.fromRoleArn(), Bucket.fromBucketName(), etc.), they might be different than the stack they were imported into.
graphQlApiRefGraphQLApiReferencegraph_ql_api_refGraphQLApiReferencegraphQlApiRefGraphQLApiReferenceGraphQlApiRefGraphQLApiReferenceGraphQlApiRefGraphQLApiReferencerequired#graphQLEndpointArnstringgraph_ql_endpoint_arnstrgraphQLEndpointArnStringGraphQLEndpointArnstringGraphQLEndpointArn*stringrequired#modesAuthorizationType[]modestyping.List[AuthorizationType]modesList<AuthorizationType>ModesAuthorizationType[]Modes*[]AuthorizationTyperequired#PROPERTY_INJECTION_IDstringproperty_injection_idstrPROPERTY_INJECTION_IDStringPROPERTY_INJECTION_IDstringPROPERTY_INJECTION_ID*stringrequiredstatic#visibilityVisibilityvisibilityVisibilityvisibilityVisibilityVisibilityVisibilityVisibilityVisibilityrequired#Methods
addDynamoDbDataSource(id: string, table: ITable, options?: DataSourceOptions): DynamoDbDataSourcedef add_dynamo_db_data_source(self, id: str, table: ITable, options: typing.Optional[DataSourceOptions] = None) -> DynamoDbDataSourcepublic DynamoDbDataSource addDynamoDbDataSource(String id, ITable table, DataSourceOptions options)public DynamoDbDataSource AddDynamoDbDataSource(string id, ITable table, DataSourceOptions? options = null)func AddDynamoDbDataSource(Id *string, Table ITable, Options DataSourceOptions) DynamoDbDataSource#3 parameters
Parameters
ididididId— The data source's id.tabletabletabletableTable— The DynamoDB table backing this data source.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addElasticsearchDataSource(id: string, domain: IDomain, options?: DataSourceOptions): ElasticsearchDataSourcedef add_elasticsearch_data_source(self, id: str, domain: IDomain, options: typing.Optional[DataSourceOptions] = None) -> ElasticsearchDataSourcepublic ElasticsearchDataSource addElasticsearchDataSource(String id, IDomain domain, DataSourceOptions options)public ElasticsearchDataSource AddElasticsearchDataSource(string id, IDomain domain, DataSourceOptions? options = null)func AddElasticsearchDataSource(Id *string, Domain IDomain, Options DataSourceOptions) ElasticsearchDataSourcedeprecated#3 parameters
Parameters
ididididId— The data source's id.domaindomaindomaindomainDomain— The elasticsearch domain for this data source.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addEnvironmentVariable(key: string, value: string): voiddef add_environment_variable(self, key: str, value: str) -> Nonepublic void addEnvironmentVariable(String key, String value)public void AddEnvironmentVariable(string key, string value)func AddEnvironmentVariable(Key *string, Value *string)#addEventBridgeDataSource(id: string, eventBus: IEventBus, options?: DataSourceOptions): EventBridgeDataSourcedef add_event_bridge_data_source(self, id: str, event_bus: IEventBus, options: typing.Optional[DataSourceOptions] = None) -> EventBridgeDataSourcepublic EventBridgeDataSource addEventBridgeDataSource(String id, IEventBus eventBus, DataSourceOptions options)public EventBridgeDataSource AddEventBridgeDataSource(string id, IEventBus eventBus, DataSourceOptions? options = null)func AddEventBridgeDataSource(Id *string, EventBus IEventBus, Options DataSourceOptions) EventBridgeDataSource#3 parameters
Parameters
ididididId— The data source's id.eventBusevent_buseventBuseventBusEventBus— The EventBridge EventBus on which to put events.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addHttpDataSource(id: string, endpoint: string, options?: HttpDataSourceOptions): HttpDataSourcedef add_http_data_source(self, id: str, endpoint: str, options: typing.Optional[HttpDataSourceOptions] = None) -> HttpDataSourcepublic HttpDataSource addHttpDataSource(String id, String endpoint, HttpDataSourceOptions options)public HttpDataSource AddHttpDataSource(string id, string endpoint, HttpDataSourceOptions? options = null)func AddHttpDataSource(Id *string, Endpoint *string, Options HttpDataSourceOptions) HttpDataSource#3 parameters
Parameters
ididididId— The data source's id.endpointendpointendpointendpointEndpoint— The http endpoint.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addLambdaDataSource(id: string, lambdaFunction: IFunction, options?: DataSourceOptions): LambdaDataSourcedef add_lambda_data_source(self, id: str, lambda_function: IFunction, options: typing.Optional[DataSourceOptions] = None) -> LambdaDataSourcepublic LambdaDataSource addLambdaDataSource(String id, IFunction lambdaFunction, DataSourceOptions options)public LambdaDataSource AddLambdaDataSource(string id, IFunction lambdaFunction, DataSourceOptions? options = null)func AddLambdaDataSource(Id *string, LambdaFunction IFunction, Options DataSourceOptions) LambdaDataSource#3 parameters
Parameters
ididididId— The data source's id.lambdaFunctionlambda_functionlambdaFunctionlambdaFunctionLambdaFunction— The Lambda function to call to interact with this data source.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addNoneDataSource(id: string, options?: DataSourceOptions): NoneDataSourcedef add_none_data_source(self, id: str, options: typing.Optional[DataSourceOptions] = None) -> NoneDataSourcepublic NoneDataSource addNoneDataSource(String id, DataSourceOptions options)public NoneDataSource AddNoneDataSource(string id, DataSourceOptions? options = null)func AddNoneDataSource(Id *string, Options DataSourceOptions) NoneDataSource#Useful for pipeline resolvers and for backend changes that don't require a data source.
2 parameters
Parameters
ididididId— The data source's id.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addOpenSearchDataSource(id: string, domain: IDomain, options?: DataSourceOptions): OpenSearchDataSourcedef add_open_search_data_source(self, id: str, domain: IDomain, options: typing.Optional[DataSourceOptions] = None) -> OpenSearchDataSourcepublic OpenSearchDataSource addOpenSearchDataSource(String id, IDomain domain, DataSourceOptions options)public OpenSearchDataSource AddOpenSearchDataSource(string id, IDomain domain, DataSourceOptions? options = null)func AddOpenSearchDataSource(Id *string, Domain IDomain, Options DataSourceOptions) OpenSearchDataSource#3 parameters
Parameters
ididididId— The data source's id.domaindomaindomaindomainDomain— The OpenSearch domain for this data source.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addRdsDataSource(id: string, serverlessCluster: IServerlessCluster, secretStore: ISecret, databaseName?: string, options?: DataSourceOptions): RdsDataSourcedef add_rds_data_source(self, id: str, serverless_cluster: IServerlessCluster, secret_store: ISecret, database_name: typing.Optional[str] = None, options: typing.Optional[DataSourceOptions] = None) -> RdsDataSourcepublic RdsDataSource addRdsDataSource(String id, IServerlessCluster serverlessCluster, ISecret secretStore, String databaseName, DataSourceOptions options)public RdsDataSource AddRdsDataSource(string id, IServerlessCluster serverlessCluster, ISecret secretStore, string? databaseName = null, DataSourceOptions? options = null)func AddRdsDataSource(Id *string, ServerlessCluster IServerlessCluster, SecretStore ISecret, DatabaseName *string, Options DataSourceOptions) RdsDataSource#5 parameters
Parameters
ididididId— The data source's id.serverlessClusterserverless_clusterserverlessClusterserverlessClusterServerlessCluster— The serverless cluster to interact with this data source.secretStoresecret_storesecretStoresecretStoreSecretStore— The secret store that contains the username and password for the serverless cluster.databaseNamedatabase_namedatabaseNamedatabaseNameDatabaseName— The optional name of the database to use within the cluster.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addRdsDataSourceV2(id: string, serverlessCluster: IDatabaseCluster, secretStore: ISecret, databaseName?: string, options?: DataSourceOptions): RdsDataSourcedef add_rds_data_source_v2(self, id: str, serverless_cluster: IDatabaseCluster, secret_store: ISecret, database_name: typing.Optional[str] = None, options: typing.Optional[DataSourceOptions] = None) -> RdsDataSourcepublic RdsDataSource addRdsDataSourceV2(String id, IDatabaseCluster serverlessCluster, ISecret secretStore, String databaseName, DataSourceOptions options)public RdsDataSource AddRdsDataSourceV2(string id, IDatabaseCluster serverlessCluster, ISecret secretStore, string? databaseName = null, DataSourceOptions? options = null)func AddRdsDataSourceV2(Id *string, ServerlessCluster IDatabaseCluster, SecretStore ISecret, DatabaseName *string, Options DataSourceOptions) RdsDataSource#5 parameters
Parameters
ididididId— The data source's id.serverlessClusterserverless_clusterserverlessClusterserverlessClusterServerlessCluster— The serverless V2 cluster to interact with this data source.secretStoresecret_storesecretStoresecretStoreSecretStore— The secret store that contains the username and password for the serverless cluster.databaseNamedatabase_namedatabaseNamedatabaseNameDatabaseName— The optional name of the database to use within the cluster.optionsoptionsoptionsoptionsOptions— The optional configuration for this data source.
addSchemaDependency(construct: CfnResource): booleandef add_schema_dependency(self, construct: CfnResource) -> boolpublic Boolean addSchemaDependency(CfnResource construct)public bool AddSchemaDependency(CfnResource construct)func AddSchemaDependency(Construct CfnResource) *bool#1 parameter
Parameters
constructconstructconstructconstructConstruct— the dependee.
applyCrossStackReferenceStrength(strength: ReferenceStrength): voiddef apply_cross_stack_reference_strength(self, strength: ReferenceStrength) -> Nonepublic void applyCrossStackReferenceStrength(ReferenceStrength strength)public void ApplyCrossStackReferenceStrength(ReferenceStrength strength)func ApplyCrossStackReferenceStrength(Strength ReferenceStrength)#notes · 1 parameter
When set, any cross-stack reference to this resource will use the specified mechanism instead of the global default determined by the @aws-cdk/core:defaultCrossStackReferences context key. This is useful for selectively weakening specific references to avoid the "deadly embrace" problem without changing the app-wide default.
Parameters
strengthstrengthstrengthstrengthStrength— - The reference strength to use for this resource.
applyRemovalPolicy(policy: RemovalPolicy): voiddef apply_removal_policy(self, policy: RemovalPolicy) -> Nonepublic void applyRemovalPolicy(RemovalPolicy policy)public void ApplyRemovalPolicy(RemovalPolicy policy)func ApplyRemovalPolicy(Policy RemovalPolicy)#notes
The Removal Policy controls what happens to this resource when it stops being managed by CloudFormation, either because you've removed it from the CDK application or because you've made a change that requires the resource to be replaced.
The resource can be deleted (RemovalPolicy.DESTROY), or left in your AWS account for data recovery and cleanup later (RemovalPolicy.RETAIN).
createResolver(id: string, props: ExtendedResolverProps): Resolverdef create_resolver(self, id: str, props: ExtendedResolverProps) -> Resolverpublic Resolver createResolver(String id, ExtendedResolverProps props)public Resolver CreateResolver(string id, ExtendedResolverProps props)func CreateResolver(Id *string, Props ExtendedResolverProps) Resolver#fromGraphqlApiAttributes(scope: Construct, id: string, attrs: GraphqlApiAttributes): IGraphqlApi@staticmethod def from_graphql_api_attributes(scope: Construct, id: str, attrs: GraphqlApiAttributes) -> IGraphqlApipublic static IGraphqlApi fromGraphqlApiAttributes(Construct scope, String id, GraphqlApiAttributes attrs)public static IGraphqlApi FromGraphqlApiAttributes(Construct scope, string id, GraphqlApiAttributes attrs)func FromGraphqlApiAttributes(Scope Construct, Id *string, Attrs GraphqlApiAttributes) IGraphqlApistatic#3 parameters
Parameters
scopescopescopescopeScope— scope.ididididId— id.attrsattrsattrsattrsAttrs— GraphQL API Attributes of an API.
grant(grantee: IGrantable, resources: IamResource, ...actions: string[]): Grantdef grant(self, grantee: IGrantable, resources: IamResource, actions: str) -> Grantpublic Grant grant(IGrantable grantee, IamResource resources, String actions)public Grant Grant(IGrantable grantee, IamResource resources, string actions)func Grant(Grantee IGrantable, Resources IamResource, Actions *string) Grant#[disable-awslint:no-grants]
3 parameters
Parameters
granteegranteegranteegranteeGrantee— The principal.resourcesresourcesresourcesresourcesResources— The set of resources to allow (i.e. ...:[region]:[accountId]:apis/GraphQLId/...).actionsactionsactionsactionsActions— The actions that should be granted to the principal (i.e. appsync:graphql ).
grantMutation(grantee: IGrantable, ...fields: string[]): Grantdef grant_mutation(self, grantee: IGrantable, fields: str) -> Grantpublic Grant grantMutation(IGrantable grantee, String fields)public Grant GrantMutation(IGrantable grantee, string fields)func GrantMutation(Grantee IGrantable, Fields *string) Grant#[disable-awslint:no-grants]
2 parameters
Parameters
granteegranteegranteegranteeGrantee— The principal.fieldsfieldsfieldsfieldsFields— The fields to grant access to that are Mutations (leave blank for all).
grantQuery(grantee: IGrantable, ...fields: string[]): Grantdef grant_query(self, grantee: IGrantable, fields: str) -> Grantpublic Grant grantQuery(IGrantable grantee, String fields)public Grant GrantQuery(IGrantable grantee, string fields)func GrantQuery(Grantee IGrantable, Fields *string) Grant#[disable-awslint:no-grants]
2 parameters
Parameters
granteegranteegranteegranteeGrantee— The principal.fieldsfieldsfieldsfieldsFields— The fields to grant access to that are Queries (leave blank for all).
grantSubscription(grantee: IGrantable, ...fields: string[]): Grantdef grant_subscription(self, grantee: IGrantable, fields: str) -> Grantpublic Grant grantSubscription(IGrantable grantee, String fields)public Grant GrantSubscription(IGrantable grantee, string fields)func GrantSubscription(Grantee IGrantable, Fields *string) Grant#[disable-awslint:no-grants]
2 parameters
Parameters
granteegranteegranteegranteeGrantee— The principal.fieldsfieldsfieldsfieldsFields— The fields to grant access to that are Subscriptions (leave blank for all).
isConstruct(x: any): boolean@staticmethod def is_construct(x: Any) -> boolpublic static Boolean isConstruct(Object x)public static bool IsConstruct(object x)func IsConstruct(X interface{}) *boolstatic#notes · 1 parameter · returns
Use this method instead of instanceof to properly detect Construct instances, even when the construct library is symlinked.
Explanation: in JavaScript, multiple copies of the constructs library on disk are seen as independent, completely different libraries. As a consequence, the class Construct in each copy of the constructs library is seen as a different class, and an instance of one class will not test as instanceof the other class. npm install will not create installations like this, but users may manually symlink construct libraries together or use a monorepo tool: in those cases, multiple copies of the constructs library can be accidentally installed, and instanceof will behave unpredictably. It is safest to avoid using instanceof, and using this type-testing method instead.
Parameters
xxxxX— Any object.
Returns: true if x is an object created from a class which extends Construct.
isOwnedResource(construct: IConstruct): boolean@staticmethod def is_owned_resource(construct: IConstruct) -> boolpublic static Boolean isOwnedResource(IConstruct construct)public static bool IsOwnedResource(IConstruct construct)func IsOwnedResource(Construct IConstruct) *boolstatic#isResource(construct: IConstruct): boolean@staticmethod def is_resource(construct: IConstruct) -> boolpublic static Boolean isResource(IConstruct construct)public static bool IsResource(IConstruct construct)func IsResource(Construct IConstruct) *boolstatic#toString(): stringdef to_string(self, ) -> strpublic String toString()public string ToString()func ToString() *string#with(...mixins: IMixin[]): IConstructdef with(self, mixins: IMixin) -> IConstructpublic IConstruct with(IMixin mixins)public IConstruct With(IMixin mixins)func With(Mixins IMixin) IConstruct#Mixins are applied in order. The list of constructs is captured at the start of the call, so constructs added by a mixin will not be visited. Use multiple with() calls if subsequent mixins should apply to added constructs.