in packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts [610:741]
constructor(scope: Construct, id: string, props: GraphqlApiProps) {
super(scope, id);
// Enhanced CDK Analytics Telemetry
addConstructMetadata(this, props);
const defaultMode = props.authorizationConfig?.defaultAuthorization ??
{ authorizationType: AuthorizationType.API_KEY };
const additionalModes = props.authorizationConfig?.additionalAuthorizationModes ?? [];
const modes = [defaultMode, ...additionalModes];
this.modes = modes.map((mode) => mode.authorizationType);
this.validateAuthorizationProps(modes);
if (!props.schema && !props.definition) {
throw new ValidationError('You must specify a GraphQL schema or source APIs in property definition.', this);
}
if ((props.schema !== undefined) === (props.definition !== undefined)) {
throw new ValidationError('You cannot specify both properties schema and definition.', this);
}
if (props.queryDepthLimit !== undefined && (props.queryDepthLimit < 0 || props.queryDepthLimit > 75)) {
throw new ValidationError('You must specify a query depth limit between 0 and 75.', this);
}
if (props.resolverCountLimit !== undefined && (props.resolverCountLimit < 0 || props.resolverCountLimit > 10000)) {
throw new ValidationError('You must specify a resolver count limit between 0 and 10000.', this);
}
if (!Token.isUnresolved(props.ownerContact) && props.ownerContact !== undefined && (props.ownerContact.length > 256)) {
throw new ValidationError('You must specify `ownerContact` as a string of 256 characters or less.', this);
}
this.definition = props.schema ? Definition.fromSchema(props.schema) : props.definition!;
if (this.definition.sourceApiOptions) {
this.setupMergedApiExecutionRole(this.definition.sourceApiOptions);
}
if (props.environmentVariables !== undefined) {
Object.entries(props.environmentVariables).forEach(([key, value]) => {
this.addEnvironmentVariable(key, value);
});
}
this.node.addValidation({ validate: () => this.validateEnvironmentVariables() });
this.visibility = props.visibility ?? Visibility.GLOBAL;
this.api = new CfnGraphQLApi(this, 'Resource', {
name: props.name,
authenticationType: defaultMode.authorizationType,
logConfig: this.setupLogConfig(props.logConfig),
openIdConnectConfig: this.setupOpenIdConnectConfig(defaultMode.openIdConnectConfig),
userPoolConfig: this.setupUserPoolConfig(defaultMode.userPoolConfig),
lambdaAuthorizerConfig: this.setupLambdaAuthorizerConfig(defaultMode.lambdaAuthorizerConfig),
additionalAuthenticationProviders: this.setupAdditionalAuthorizationModes(additionalModes),
xrayEnabled: props.xrayEnabled,
visibility: props.visibility,
mergedApiExecutionRoleArn: this.mergedApiExecutionRole?.roleArn,
apiType: this.definition.sourceApiOptions ? 'MERGED' : undefined,
introspectionConfig: props.introspectionConfig,
queryDepthLimit: props.queryDepthLimit,
resolverCountLimit: props.resolverCountLimit,
environmentVariables: Lazy.any({ produce: () => this.renderEnvironmentVariables() }),
ownerContact: props.ownerContact,
});
this.apiId = this.api.attrApiId;
this.arn = this.api.attrArn;
this.graphqlUrl = this.api.attrGraphQlUrl;
this.name = this.api.name;
this.graphQLEndpointArn = this.api.attrGraphQlEndpointArn;
if (this.definition.schema) {
this.schemaResource = new CfnGraphQLSchema(this, 'Schema', this.definition.schema.bind(this));
} else {
this.setupSourceApiAssociations();
}
if (props.domainName) {
this.domainNameResource = new CfnDomainName(this, 'DomainName', {
domainName: props.domainName.domainName,
certificateArn: props.domainName.certificate.certificateArn,
description: `domain for ${this.name} at ${this.graphqlUrl}`,
});
const domainNameAssociation = new CfnDomainNameApiAssociation(this, 'DomainAssociation', {
domainName: props.domainName.domainName,
apiId: this.apiId,
});
domainNameAssociation.addDependency(this.domainNameResource);
}
if (modes.some((mode) => mode.authorizationType === AuthorizationType.API_KEY)) {
const config = modes.find((mode: AuthorizationMode) => {
return mode.authorizationType === AuthorizationType.API_KEY && mode.apiKeyConfig;
})?.apiKeyConfig;
this.apiKeyResource = this.createAPIKey(config);
if (this.schemaResource) {
this.apiKeyResource.addDependency(this.schemaResource);
}
this.apiKey = this.apiKeyResource.attrApiKey;
}
if (modes.some((mode) => mode.authorizationType === AuthorizationType.LAMBDA)) {
const config = modes.find((mode: AuthorizationMode) => {
return mode.authorizationType === AuthorizationType.LAMBDA && mode.lambdaAuthorizerConfig;
})?.lambdaAuthorizerConfig;
if (FeatureFlags.of(this).isEnabled(cxapi.APPSYNC_GRAPHQLAPI_SCOPE_LAMBDA_FUNCTION_PERMISSION)) {
config?.handler.addPermission(`${id}-appsync`, {
principal: new ServicePrincipal('appsync.amazonaws.com'),
action: 'lambda:InvokeFunction',
sourceArn: this.arn,
});
} else {
config?.handler.addPermission(`${id}-appsync`, {
principal: new ServicePrincipal('appsync.amazonaws.com'),
action: 'lambda:InvokeFunction',
});
}
}
const logGroupName = `/aws/appsync/apis/${this.apiId}`;
if (props.logConfig) {
const logRetention = new LogRetention(this, 'LogRetention', {
logGroupName: logGroupName,
retention: props.logConfig?.retention ?? RetentionDays.INFINITE,
});
this.logGroup = LogGroup.fromLogGroupArn(this, 'LogGroup', logRetention.logGroupArn);
} else {
this.logGroup = LogGroup.fromLogGroupName(this, 'LogGroup', logGroupName);
}
}