Etapa 4: Usando um AWS AppSync API com o AWS CDK - AWS AppSync

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Etapa 4: Usando um AWS AppSync API com o AWS CDK

dica

Antes de usar oCDK, recomendamos revisar a documentação CDK oficial e a CDKreferência AWS AppSync do.

Também recomendamos garantir que suas NPMinstalações AWS CLIe instalações estejam funcionando em seu sistema.

Nesta seção, vamos criar um CDK aplicativo simples que pode adicionar e buscar itens de uma tabela do DynamoDB. Esse é um exemplo de início rápido usando parte do código das seções Projetando seu esquema, Anexando uma fonte de dados e Configurando resolvers (). JavaScript

Configurando um CDK projeto

Atenção

Essas etapas podem não ser totalmente precisas, dependendo do seu ambiente. Presumimos que seu sistema tenha os utilitários necessários instalados, uma forma de interagir com AWS os serviços e as configurações adequadas.

A primeira etapa é instalar AWS CDK o. No seuCLI, você pode inserir o seguinte comando:

npm install -g aws-cdk

Depois, você precisa criar um diretório de projeto e navegar até ele. Um exemplo de conjunto de comandos para criar e navegar até um diretório é:

mkdir example-cdk-app cd example-cdk-app

Em seguida, você precisa criar um aplicativo. Nosso serviço usa principalmente TypeScript. No diretório do seu projeto, digite o seguinte comando:

cdk init app --language typescript

Quando você fizer isso, um CDK aplicativo junto com seus arquivos de inicialização será instalado:

Terminal output showing Git initialization messages. (AI generated)

A estrutura do seu projeto pode ser semelhante a esta:

Project directory structure with folders and files. (AI generated)

Você notará que temos vários diretórios importantes:

  • bin: o arquivo bin inicial criará o aplicativo. Não abordaremos esse tema neste guia.

  • lib: o diretório lib contém seus arquivos de pilha. Você pode pensar nos arquivos de pilha como unidades individuais de execução. As estruturas estarão dentro de nossos arquivos de pilha. Basicamente, esses são recursos para um serviço que será ativado AWS CloudFormation quando o aplicativo for implantado. É aqui que a maior parte da nossa codificação acontecerá.

  • node_modules: esse diretório é criado NPM e contém todas as dependências de pacotes que você instalou usando o npm comando.

Nosso arquivo de pilha inicial pode conter algo assim:

import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; // import * as sqs from 'aws-cdk-lib/aws-sqs'; export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // The code that defines your stack goes here // example resource // const queue = new sqs.Queue(this, 'ExampleCdkAppQueue', { // visibilityTimeout: cdk.Duration.seconds(300) // }); } }

Esse é o código clichê para criar uma pilha em nosso aplicativo. A maior parte do nosso código neste exemplo estará dentro do escopo dessa classe.

Para verificar se seu arquivo de pilha está no aplicativo, no diretório do seu aplicativo, execute o seguinte comando no terminal:

cdk ls

Uma lista de suas pilhas deve aparecer. Caso contrário, talvez seja necessário executar as etapas novamente ou verificar a documentação oficial para obter ajuda.

Se quiser criar suas alterações de código antes da implantação, você sempre pode executar o seguinte comando no terminal:

npm run build

E para ver as mudanças antes da implantação:

cdk diff

Antes de adicionarmos nosso código ao arquivo de pilha, vamos realizar um bootstrap. O bootstrapping nos permite provisionar recursos para CDK antes da implantação do aplicativo. Mais informações sobre esse processo podem ser encontradas aqui. Para criar um bootstrap, o comando é:

cdk bootstrap aws://ACCOUNT-NUMBER/REGION
dica

Essa etapa requer várias IAM permissões em sua conta. Seu bootstrap será negado se você não as tiver. Se isso acontecer, talvez seja necessário excluir recursos incompletos causados pelo bootstrap, como o bucket S3 que ele gera.

O bootstrap criará vários recursos. A mensagem final terá a aparência a seguir:

Terminal output showing bootstrapping environment. (AI generated)

Como isso é feito uma vez por conta por região, você não precisará fazer com frequência. Os principais recursos do bootstrap são a AWS CloudFormation pilha e o bucket Amazon S3.

O bucket do Amazon S3 é usado para armazenar arquivos e IAM funções que concedem as permissões necessárias para realizar implantações. Os recursos necessários são definidos em uma AWS CloudFormation pilha, chamada pilha de bootstrap, que geralmente é nomeada. CDKToolkit Como qualquer AWS CloudFormation pilha, ela aparece no AWS CloudFormation console depois de implantada:

AWS CloudFormation stack list with CDKToolkit stack details. (AI generated)

Isso também se aplica ao bucket:

AWS S3 bucket details showing name, region, access level, and creation date. (AI generated)

Para importar os serviços que precisamos em nosso arquivo de pilha, podemos usar o seguinte comando:

npm install aws-cdk-lib # V2 command
dica

Se você estiver tendo problemas com a V2, poderá instalar as bibliotecas individuais usando os comandos da V1:

npm install @aws-cdk/aws-appsync @aws-cdk/aws-dynamodb

Não recomendamos isso porque a V1 foi descontinuada.

Implementando um CDK projeto - Esquema

Agora podemos começar a implementar nosso código. Primeiro, precisamos criar nosso esquema. Você pode simplesmente criar um arquivo .graphql no seu aplicativo:

mkdir schema touch schema.graphql

Em nosso exemplo, incluímos um diretório de nível superior chamado schema que contém nosso schema.graphql:

Directory structure showing a schema.graphql file. (AI generated)

Dentro do nosso esquema, vamos incluir um exemplo simples:

input CreatePostInput { title: String content: String } type Post { id: ID! title: String content: String } type Mutation { createPost(input: CreatePostInput!): Post } type Query { getPost: [Post] }

De volta ao nosso arquivo de pilha, precisamos garantir que as seguintes diretivas de importação estejam definidas:

import * as cdk from 'aws-cdk-lib'; import * as appsync from 'aws-cdk-lib/aws-appsync'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import { Construct } from 'constructs';

Dentro da classe, adicionaremos código para criar nosso GraphQL API e conectá-lo ao nosso schema.graphql arquivo:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // makes a GraphQL API const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); } }

Também adicionaremos alguns códigos para imprimir o GraphQLURL, a API chave e a região:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Makes a GraphQL API construct const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); // Prints out URL new cdk.CfnOutput(this, "GraphQLAPIURL", { value: api.graphqlUrl }); // Prints out the AppSync GraphQL API key to the terminal new cdk.CfnOutput(this, "GraphQLAPIKey", { value: api.apiKey || '' }); // Prints out the stack region to the terminal new cdk.CfnOutput(this, "Stack Region", { value: this.region }); } }

Neste momento, usaremos a implantação do nosso aplicativo novamente:

cdk deploy

Este é o resultado:

Terminal output showing a successful CloudFormation deployment. (AI generated)

Parece que nosso exemplo foi bem-sucedido, mas vamos verificar o AWS AppSync console apenas para confirmar:

AWS AppSync console showing the api-to-process-posts GraphQL API. (AI generated)

Parece que o nosso API foi criado. Agora, verificaremos o esquema anexado aoAPI:

Schema showing input type, Post type, Mutation type with createPost, and Query type with getPost. (AI generated)

Como parece corresponder ao nosso código de esquema, então foi bem-sucedido. Outra forma de confirmar isso do ponto de vista dos metadados é examinar a pilha: AWS CloudFormation

AWS CloudFormation stack showing CREATE_COMPLETE and UPDATE_COMPLETE statuses. (AI generated)

Quando implantamos nosso CDK aplicativo, ele usa recursos como o bootstrap. AWS CloudFormation Cada pilha em nosso aplicativo mapeia 1:1 com uma AWS CloudFormation pilha. Se você voltar ao código da pilha, o nome da pilha foi retirado do nome da classe ExampleCdkAppStack. Você pode ver os recursos que ele criou, que também correspondem às nossas convenções de nomenclatura em nossa construção GraphQL: API

AWS CloudFormation stack resources and naming conventions. (AI generated)

Implementando um CDK projeto - Fonte de dados

Depois, precisamos adicionar nossa fonte de dados. Nosso exemplo usará uma tabela do DynamoDB. Dentro da classe de pilha, adicionaremos códigos para criar uma tabela:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Makes a GraphQL API construct const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); //creates a DDB table const add_ddb_table = new dynamodb.Table(this, 'posts-table', { partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING, }, }); // Prints out URL new cdk.CfnOutput(this, "GraphQLAPIURL", { value: api.graphqlUrl }); // Prints out the AppSync GraphQL API key to the terminal new cdk.CfnOutput(this, "GraphQLAPIKey", { value: api.apiKey || '' }); // Prints out the stack region to the terminal new cdk.CfnOutput(this, "Stack Region", { value: this.region }); } }

Neste momento, vamos implantar novamente:

cdk deploy

Devemos verificar nossa nova tabela no console do DynamoDB:

DynamoDB console showing the ExampleCdkAppStack-poststabledbtable. (AI generated)

O nome da nossa pilha está correto e o nome da tabela corresponde ao nosso código. Se verificarmos nossa AWS CloudFormation pilha novamente, agora veremos a nova tabela:

AWS CloudFormation stack resources including posts-apis, posts-table, and poststableCCB5A2E6. (AI generated)

Implementando um CDK projeto - Resolver

Este exemplo usará dois resolvedores: um para consultar a tabela e outro para adicioná-la. Como estamos usando resolvedores de pipeline, precisaremos declarar dois resolvedores de pipeline com uma função em cada um. Na consulta, adicionaremos o seguinte código:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Makes a GraphQL API construct const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); //creates a DDB table const add_ddb_table = new dynamodb.Table(this, 'posts-table', { partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING, }, }); // Creates a function for query const add_func = new appsync.AppsyncFunction(this, 'func-get-post', { name: 'get_posts_func_1', api, dataSource: api.addDynamoDbDataSource('table-for-posts', add_ddb_table), code: appsync.Code.fromInline(` export function request(ctx) { return { operation: 'Scan' }; } export function response(ctx) { return ctx.result.items; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, }); // Creates a function for mutation const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', { name: 'add_posts_func_1', api, dataSource: api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table), code: appsync.Code.fromInline(` export function request(ctx) { return { operation: 'PutItem', key: util.dynamodb.toMapValues({id: util.autoId()}), attributeValues: util.dynamodb.toMapValues(ctx.args.input), }; } export function response(ctx) { return ctx.result; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, }); // Adds a pipeline resolver with the get function new appsync.Resolver(this, 'pipeline-resolver-get-posts', { api, typeName: 'Query', fieldName: 'getPost', code: appsync.Code.fromInline(` export function request(ctx) { return {}; } export function response(ctx) { return ctx.prev.result; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, pipelineConfig: [add_func], }); // Adds a pipeline resolver with the create function new appsync.Resolver(this, 'pipeline-resolver-create-posts', { api, typeName: 'Mutation', fieldName: 'createPost', code: appsync.Code.fromInline(` export function request(ctx) { return {}; } export function response(ctx) { return ctx.prev.result; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, pipelineConfig: [add_func_2], }); // Prints out URL new cdk.CfnOutput(this, "GraphQLAPIURL", { value: api.graphqlUrl }); // Prints out the AppSync GraphQL API key to the terminal new cdk.CfnOutput(this, "GraphQLAPIKey", { value: api.apiKey || '' }); // Prints out the stack region to the terminal new cdk.CfnOutput(this, "Stack Region", { value: this.region }); } }

Neste trecho, adicionamos um resolvedor de pipeline chamado pipeline-resolver-create-posts com uma função chamada func-add-post anexada a ele. Esse é o código que adicionará Posts à tabela. O outro resolvedor de pipeline foi chamado pipeline-resolver-get-posts com uma função chamada func-get-post que recupera Posts adicionado à tabela.

Vamos implantar isso para adicioná-lo ao AWS AppSync serviço:

cdk deploy

Vamos verificar o AWS AppSync console para ver se eles estavam conectados ao nosso GraphQLAPI:

Diagram showing mutation and query resolvers for a GraphQL API. (AI generated)

Parece estar correto. No código, esses dois resolvedores foram anexados ao API GraphQL que criamos (indicado pelo api valor props presente nos resolvedores e nas funções). No GraphQLAPI, os campos aos quais anexamos nossos resolvedores também foram especificados nas props (definidas pelas props typename e fieldname em cada resolvedor).

Vamos ver se o conteúdo dos resolvedores está correto começando com pipeline-resolver-get-posts:

Code editor showing two resolver functions for request and response. (AI generated)

Os manipuladores de antes e depois correspondem ao valor de nossos props code. Também podemos ver que uma função chamada add_posts_func_1 corresponde ao nome da função que anexamos no resolvedor.

Vamos dar uma olhada no conteúdo do código dessa função:

Code snippet showing a request function that returns an operation and key/attribute values. (AI generated)

Isso corresponde aos props code da função add_posts_func_1. Como nossa consulta foi enviada com sucesso, vamos verificar a consulta:

Code editor showing two exported functions for request and response. (AI generated)

Eles também correspondem ao código. Se observarmos get_posts_func_1:

Code snippet showing two functions: request and response. (AI generated)

Tudo parece estar no lugar certo. Para confirmar isso do ponto de vista dos metadados, podemos verificar nossa pilha no AWS CloudFormation novamente:

AWS CloudFormation stack with logical IDs for resources. (AI generated)

Agora, precisamos testar esse código executando algumas solicitações.

Implementando um CDK projeto - Solicitações

Para testar nosso aplicativo no AWS AppSync console, fizemos uma consulta e uma mutação:

Code snippet showing a GraphQL query and mutation. (AI generated)

MyMutation contém uma operação createPost com os argumentos 1970-01-01T12:30:00.000Z e first post. Retorna date e title que passamos, bem como o valor id gerado automaticamente. Executar a mutação produz o seguinte resultado:

{ "data": { "createPost": { "date": "1970-01-01T12:30:00.000Z", "id": "4dc1c2dd-0aa3-4055-9eca-7c140062ada2", "title": "first post" } } }

Se verificarmos a tabela do DynamoDB rapidamente, poderemos ver nossa entrada na tabela quando a verificarmos:

DynamoDB table with id, date, and title columns showing an entry. (AI generated)

De volta ao AWS AppSync console, se executarmos a consulta para recuperar issoPost, obteremos o seguinte resultado:

{ "data": { "getPost": [ { "id": "9f62c4dd-49d5-48d5-b835-143284c72fe0", "date": "1970-01-01T12:30:00.000Z", "title": "first post" } ] } }