constructor()

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);
    }
  }