Serverless appsync

Serverless appsync DEFAULT

Serverless Appsync Plugin

TestsAll Contributors

Deploy AppSync API's in minutes using this Serverless plugin.

Be sure to check out all that AWS AppSync has to offer. Here are a few resources to help you understand everything needed to get started!

  • Mapping Templates - Not sure how to create Mapping Templates for DynamoDB, Lambda or Elasticsearch? Here's a great place to start!
  • Data Sources and Resolvers - Get more information on what data sources are supported and how to set them up!
  • Security - Checkout this guide to find out more information on securing your API endpoints with AWS_IAM or Cognito User Pools!

Install the plugin via Yarn

or via NPM

Configuring the plugin

Add to the plugins section of

Add the following config to the custom section of and update it accordingly to your needs

Be sure to replace all variables that have been commented out, or have an empty value.

Working with existing APIs

If you already have an API created in AppSync through the UI or from a different CF stack and want to manage it via Serverless then the plugin can also support that.

There is an optional apiId parameter that you can use to specify the ID of an existing AppSync API:

Without apiId parameter the plugin will create a different endpoint with the same name alongside the original one.

You can find the apiId value in the AppSync console, just open your existing AppSync API and go to Settings.

In that case, the plugin will not attempt to create a new endpoint for you, instead, it will attach all newly configured resources to the existing endpoint.

The following configuration options are only associated with the creation of a new AppSync endpoint and will be ignored if you provide apiId parameter:

  • name
  • authenticationType
  • userPoolConfig
  • openIdConnectConfig
  • additionalAuthenticationProviders
  • logConfig
  • tags
  • xrayEnabled
  • apiKeys
  • wafConfig

So later, if you wanted to change the name of the API, or add some tags, or change the logging configuration, anything from the list above you would have to do that via a different method, for example from the UI.

If the existing API already contains schema and resolvers those will be completely replaced by the new schema and resolvers from the code.

If the existing API already contains data sources, those data sources will remain untouched unless they have the same names as the data sources in the code, in which case they will be replaced with the ones from the code.

Note: You should never set the apiId of an API that was previously deployed with the same serverless stack, otherwise, it would be deleted. That is because the resource would be removed from the stack.

Only use the apiId parameter if you know what you are doing.

Multiple APIs

If you have multiple APIs and do not want to split this up into another CloudFormation stack, simply change the configuration property from an object into an array of objects:

Note: CloudFormation stack outputs and logical IDs will be changed from the defaults to api name prefixed. This allows you to differentiate the APIs on your stack if you want to work with multiple APIs.

Direct Lambda Resolvers

Amazon supports direct lambda resolvers

With a direct lambda resolver, no VTL mapping template is required for either request or response. This can be an option if you would like to avoid usage of the Apache VTL langauge or require a complex resolver. You can enable direct Lambda resolvers by setting as the and/or value.

Example:

Furthermore, direct resolution can be enabled separately for the request and response templates.

Pipeline Resolvers

Amazon supports pipeline resolvers

They allow you to perform more than one mapping template in sequence, so you can do multiple queries to multiple sources. These queries are called function configurations ('AWS::AppSync::FunctionConfiguration') and are children of a resolver.

Here is an example of how to configure a resolver with function configurations. The key here is to provide a 'kind' of 'PIPELINE' to the mapping template of the parent resolver. Then provide the names of the functions in the mappingTemplate to match the names of the functionConfigurations.

Managing API keys

Since v, api keys management is supported. You can pass one or more api keys configuration as an array in the property.

The keys can either be a string (name of the key with defaults) or an object of the following shape:

| property | default | description| || || | name | auto-generated | Name of the key. This is used under the hood to differentiate keys in the deployment process.

Names are used in the Cfn resource name. Please, keep them short and without spaces or special characters to avoid issues. Key names are case sensitive. | | description | name of the key | A short description for that key | | expiresAfter | d | Expiration time for the key.
Can be expressed in hours or in "human" format (As in momentjs add).
eg: , , , ,
Min: 1d, max: 1y | | expiresAt | one year from now | A specific expiration date in ISO format. Or as a unix timestamp | | apiKeyId | | the id if the api to update. Useful for when an api key has been created manually in the AWS console. |

If both and are specified, takes precedence.

When naming keys, you need to be aware that changing the value will require the replacement of the api key.

Unnamed keys are named automatically sequentially Key1, Key2, Key3 and so forth.

:warning: Be careful when removing unnamed keys!!!. For exemple, if you have 3 unnamed keys and you remove the second one in your list, Key3 will become Key2. As a result, it is former Key3 that will be removed. To workaround that, you could specify their auto-generated names before removing any unnamed keys (Key1, Key2 and Key3 in our example. Then remove Key2). As a rule of thumb, all keys should be named to avoid issues.

:bulb: If you have already deployed and an api key was previously auto-generated for you (either in version < or if you deployed without specifying the property), you can add it to your yml template by naming it (case sensitive!!). Starting from there, you can add additional API keys.

:bulb: If you want to revoke a key, delete it, or rename it.

:bulb: If a key expires, or you have manually deleted it from the cosole, subsequent deployments will fail (after 60 days in the case it expires). You can fix that by simply removing the key from your yml file, or by renaming it (in which case, a new key will be generated).

Example:

:bulb: Finally, if you dont't want serverless to handle keys for you, just pass an empty array:

WAF Web ACL

AppSync supports WAF. WAF is an Application Firewall that helps you protect your API against common web exploits.

This plugin comes with some handy pre-defined rules that you can enable in just a few lines of code.

Throttling

Throttling will disallow requests coming from the same ip address when a limit is reached within a 5-minutes period.

There are several ways to enable it. Here are some examples:

Disable Introspection

Sometimes, you want to disable introspection to disallow untrusted consumers to discover the structure of your API.

Using AWS Managed Rules

You can use AWS Managed Rules using this configuration:

Managed rules require set and not set.

For more information view the AWS Managed Rule Groups List.

Per Api Key rules

In some cases, you might want to enable a rule only for a given API key only. You can specify under the configuration. The rules will apply only to the api key under which the rule is set.

Adding a rule to an API key without any statement will add a "match-all" rule for that key. This is usefull for example to exclude api keys from high-level rules. In that case, you need to make sure to attribute a higher priority to that rule.

Example:

  • Block all requests by default
  • Add a rule to allow US requests
  • Except for the key, that should have worldwide access.

About priority

The priorities don't need to be consecutive, but they must all be different.

Setting a priority to the rules is not required, but recommended. If you don't set priority, it will be automatically attributed (sequentially) according to the following rules:

First the global rules (under ), in the order that they are defined. Then, the api key rules, in order of api key definitions, then rule definition. Auto-generated priorities start at This gives you some room () to add other rules that should get a higher priority, if you need to.

For more info about how rules are executed, pease refer to the documentation

Example:

Advanced usage

You can also specify custom rules. For more info on how to define a rule, see the Cfn documentation

Example:

In some cases you want to enable usage of old-style comments (#) in appSync. setting the setting to true, will enable this.

Example:

Stack Outputs & Exports

and are exported to allow cross-stack resource reference using . Output Exports are named with a prefix to the logical IDs. For example, .

Note: CloudFormation stack outputs and logical IDs will be changed from the defaults to api name prefixed. This allows you to differentiate the APIs on your stack if you want to work with multiple APIs.

This command will deploy all AppSync resources in the same CloudFormation template used by the other serverless resources.

  • Providing the option will conceal the API keys from the output when the authentication type of is used.

Validates your GraphQL Schema(s) without deploying.

This command will start a local graphql-playground server which is connected to your deployed AppSync endpoint (in the cloud). The required options for the command are different depending on your AppSync authenticationType.

For API_KEY, either the GraphQLApiKeyDefault output or the --apiKey option is required

For AMAZON_COGNITO_USER_POOLS, the -u/--username and -p/--password arguments are required. The cognito user pool client id can be provided with the --clientId option or directly in the yaml file ()

For OPENID_CONNECT, the --jwtToken option is required.

The AWS_IAM authenticationType is not currently supported.

There are 2 ways to work with offline development for serverless appsync.

serverless-appsync-simulator

serverless-appsync-simulator is a wrapper of aws's amplify-cli for serverless and this plugin. Both are actively maintained.

serverless-appsync-simulator (deprecated/unmaintained)

serverless-appsync-offline is based on AppSync Emulator. Both these packages are currently unmaintained.

You can use serverless-plugin-split-stacks to migrate AppSync resources in nested stacks in order to work around the ~~~~ resource limit.

  1. Install serverless-plugin-split-stacks
  1. Follow the installation instructions

  2. Place after

  1. Create in the root folder
  1. Enjoy :beers:

If you have any questions, issue, feature request, please feel free to open an issue.

You are also very welcome to open a PR and we will gladely review it.

VSCode extensions

Video tutorials

Blog tutorial

Thanks goes to these wonderful people :clap:

This project follows the all-contributors specification. Contributions of any kind welcome!

Sours: https://www.serverless.com/plugins/serverless-appsync-plugin

Building a chat application using AWS AppSync and Serverless

GraphQL gets a lot of praise for its expressiveness, for the idea of batching requests for data, and for its great development tooling. But there is an additional benefit that mostly goes unnoticed.

Namely—many frontend GraphQL frameworks make a distinction between the data in the app state and the data on a remote server. This is what allows React apps powered by GraphQL APIs to seem so fast, even if they are moving a lot of data: the moving of data happens in the background.

Users get from more responsive frontend apps, while also saving bandwidth. Developers can now model the data better, and deliver a more pleasant experience to the end user.

AppSync, AWS’s managed GraphQL layer, builds on the benefits of GraphQL and adds a few more cool things in its mobile and web SDKs: subscriptions, convenient authentication via Cognito Pools, and the ability to plug in directly to a bunch of AWS services for data.

AppSync can do a lot while still being a fully managed service, which works out great for Serverless applications. No more GraphQL resolvers in Lambda functions. No more hand-rolled authentication. It’s the best of GraphQL with less complexity than before.

In this article, we show how you can get started with AWS AppSync in a Serverless project, and talk about the benefits and drawbacks of using AppSync for your Serverless applications. Let’s get to it!

Building a chat app with AppSync

We broadly divided the process of getting a chat app running on Serverless with AWS AppSync into two parts: setting up the backend part of the service to fetch the data and deliver it via the GraphQL API, and creating a simple frontend to consume the API.

The backend

We start by defining how we will be using AppSync in our Serverless project. We are using the Serverless AppSync plugin to simplify the configuration, and all we need to provide, in addition to the authentication config, is:

  • A set of mapping templates that will help AppSync understand how to resolve each GraphQL you send out
  • A GraphQL schema that describes our API
  • A data source, in our case a DynamoDB database.

The AppSync section in our serverless.yml looks like this:

Our mapping templates for DynamoDB are almost an identical copy of the example from the AppSync docs, and allow us to get and create items in the Messages table. We place all mapping templates in the subdirectory.

For our GraphQL schema, we are starting simple, with only a few actions that are strictly necessary for a useful chat app:

  • A way to create a message — in this case, the createMessage mutation.
  • A way to get all messages — the getMessages query.
  • A subscription for all incoming messages, addMessage.
  • A description of the fields of the Message object — in this case, we want a message ID, the text of the message, the date it was posted, and the handle of the person who posted it.

With all those things our schema looks like this:

This is all we need on the backend side to get AppSync up and running. We can now deploy the service:

And then watch all resources get created.

Frontend

On the frontend, we use the GraphQL operations and the Authentication module from AWS Amplify. The core of the app is the file where we configure Amplify with all our authentication settings and point it to our GraphQL endpoint.

The whole user interface, in addition to the login / sign up screens provided by Amplify, consists of two components: and . We use for the messages list:

We then create our own Send Message box that allows us to type in it and save the contents in the component’s state:

We then use the two components in . We use the info that’s coming from Amplify to get the username that we need to associate each sent message with. The subscription that we defined before plugs into the component neatly, and the action from the component triggers a GraphQL mutation that sends the message to the backend:

This is all for our frontend! Once we install all the dependencies we can run it via:

We land on the authentication screen provided by AppSync, where we can pick a username and a password. We can then sign in and see the list of messages, send some messages, and get responses from other users:

Subscribe to Our Newsletter Packed with Tips, Guide and Good Development Inspiration

Thank you! Your submission has been received!

Oops! Something went wrong while submitting the form.

Sours: https://www.serverless.com/blog/building-chat-appliation-aws-appsync-serverless
  1. Trick puzzles
  2. Goku clothes
  3. Lift support bracket
  4. Speed boat svg free

npm

npm versionLicense: MIT

This is a wrapper for the excellent AppSync Emulator.

This Plugin Requires

Features

  • Emulate Appsync with AppSync Emulator and depends on Serverless-AppSync-Plugin
  • Connect to any DynamoDB or install DynamoDB Local
  • Start DynamoDB Local with all the parameters supported (e.g port, inMemory, sharedDb)
  • Table Creation for DynamoDB Local

This plugin is updated by its users, I just do maintenance and ensure that PRs are relevant to the community. In other words, if you find a bug or want a new feature, please help us by becoming one of the contributors.

Install Plugin

Then in add following entry to the plugins array:

plugins:

  - serverless-appsync-offline

Using the Plugin

  1. Add Appsync Resource definitions to your Serverless configuration, as defined here: https://github.com/sid88in/serverless-appsync-plugin#configuring-the-plugin

Start appsync-offline

All CLI options are optional:

All the above options can be added to serverless.yml to set default configuration: e.g.

Minimum Options:

custom:

  appsync-offline:

    port: 

    dynamodb:

      server:

        port: 

All Options:

custom:

  appsync-offline:

    port: 

    dynamodb:

      client:

        # if endpoint is provided, no local database server is started and and appsync connects to the endpoint - e.g. serverless-dynamodb-local

        endpoint: "http://localhost"

        region: localhost

        accessKeyId: a

        secretAccessKey: a

      server:

        port: 

        dbPath: "./.dynamodb"

        inMemory: false,

        sharedDb: false,

        delayTransientStatuses: false,

        optimizeDbBeforeStartup: false,

How to Query:

curl -X POST \

  http://localhost/graphql \

  -H 'Content-Type: application/json' \

  -H 'x-api-key: APIKEY' \

  -d '{

    "query": "{ hello { world } }"

}'

Note: If you're using as your authenticationType, then a header has to be present in the request. The value of the key doesn't really matter.

Using DynamoDB Local in your code

You need to add the following parameters to the AWS NODE SDK dynamodb constructor

e.g. for dynamodb document client sdk

e.g. for dynamodb document client sdk

Using with serverless-offline plugin

When using this plugin with serverless-offline, it is difficult to use above syntax since the code should use DynamoDB Local for development, and use DynamoDB Online after provisioning in AWS. Therefore we suggest you to use serverless-dynamodb-client plugin in your code.

The command can be triggered automatically when using plugin.

Add both plugins to your file:

plugins:

-serverless-appsync-offline

-serverless-offline

Make sure that is above so it will be loaded earlier.

Now your local Appsync and the DynamoDB database will be automatically started before running .

Debugging

or

Using with serverless-offline and serverless-webpack plugin

Run . In comparison with , the command will fire an and a lifecycle hook which is needed for serverless-offline and serverless-appsync-offline to switch off both resources.

Add plugins to your file:

plugins:

-serverless-webpack

-serverless-appsync-offline

-serverless-offline 

custom:

appsync-emulator:

buildPrefix:.webpack/service

Notes

The AppSync Emulator does not support CloudFormation syntax (e.g. ) in .

License

MIT

Sours: https://www.npmjs.com/package/serverless-appsync-offline
How to build a low-latency serverless GraphQL API on AWS with Node.js, AppSync, Lambda, and DynamoDB

Serverless Appsync Plugin

Build Status

Tired of 🚀 deploying, ✏️ updating, and ❌ deleting your AppSync API’s using the AWS AppSync dashboard? You can now develop all of your AppSync API’s locally using Serverless + Serverless-AppSync-Plugin! With support for AWS DynamoDB, AWS Lambda, and AWS Elasticsearch; you have everything you need to get started developing your AppSync API’s locally.

Find AppSync examples in the Serverless-GraphQL Repo 👈

Part 1:Running a scalable & reliable GraphQL endpoint with Serverless

Part 2:AppSync Backend: AWS Managed GraphQL Service

Part 3:AppSync Frontend: AWS Managed GraphQL Service

AWS Mobile BlogHow to deploy a GraphQL API on AWS using the Serverless Framework

appsync architecture

⚡️ Getting Started

Be sure to check out all that AWS AppSync has to offer. Here are a few resources to help you understand everything needed to get started!

  • Mapping Templates - Not sure how to create Mapping Templates for DynamoDB, Lambda or Elasticsearch? Here’s a great place to start!
  • Data Sources and Resolvers - Get more information on what data sources are supported and how to set them up!
  • Security - Checkout this guide to find out more information on securing your API endpoints with AWS_IAM or Cognito User Pools!

🛠 Minimum requirements

💾 Installation

Install the plugin via Yarn (recommended)

or via NPM

Configuring the plugin

Add to the plugins section of

Add the following example config to the custom section of

Be sure to replace all variables that have been commented out, or have an empty value.

Multiple APIs

If you have multiple APIs and do not want to split this up into another CloudFormation stack, simply change the configuration property from an object into an array of objects:

Note: CloudFormation stack outputs and logical IDs will be changed from the defaults to api name prefixed. This allows you to differentiate the APIs on your stack if you want to work with multiple APIs.

Pipeline Resolvers

Amazon recently released the new pipeline resolvers: https://aws.amazon.com/blogs/mobile/aws-appsync-releases-pipeline-resolvers-aurora-serverless-support-delta-sync/

These changes allow you to perform more than one mapping template in sequence, so you can do multiple queries to multiple sources. These queries are called function configurations (‘AWS::AppSync::FunctionConfiguration’) and are children of a resolver.

Here is an example of how to configure a resolver with function configurations. The key here is to provide a ‘kind’ of ‘PIPELINE’ to the mapping template of the parent resolver. Then provide the names of the functions in the mappingTemplate to match the names of the functionConfigurations.

▶️ Usage

This command will deploy all AppSync resources in the same CloudFormation template used by the other serverless resources.

This command will start a local graphql-playground server which is connected to your AppSync endpoint. The required options for the command are different depending on your AppSync authenticationType.

For API_KEY, either the GraphQLApiKeyDefault output or the –apiKey option is required

For AMAZON_COGNITO_USER_POOLS, the -u/–username and -p/–password arguments are required. The cognito user pool client id can be provided with the –clientId option or directly in the yaml file ()

For OPENID_CONNECT, the –jwtToken option is required.

The AWS_IAM authenticationType is not currently supported.

📝 Notes

  • If you are planning on using AWS Elasticsearch, you will need to create an Elasticsearch domain/endpoint on AWS and set it as the option in before deploying.

Offline support

You can use serverless-appsync-offline to autostart an AppSync Emulator which depends on Serverless-AppSync-Plugin with DynamoDB and Lambda resolver support:

Install Plugin

Minimal Options (serverless.yml)

Start local enviroment

If you use :

otherwise:

the result is:

Go to serverless-appsync-offline to get further configuration options.

Split Stacks Plugin

You can use serverless-plugin-split-stacks to migrate AppSync resources in nested stacks in order to work around the resource limit.

  1. Install serverless-plugin-split-stacks
  1. Follow the installation instructions

  2. Place after

  1. Create in the root folder
  1. Enjoy :beers:

🎁 Contributing

If you have any questions, please feel free to reach out to me directly on Twitter Sid Gupta.

👷 Migration from versions prior to

If you have previously used versions of this plugin prior to , you will need to perform some additional manual steps in order to continue use of this plugin (it will be worth it). This change removes the commands in favor of adding AppSync resources directly to the serverless cloudformation stack. What this means for your existing APIs is that they can no longer be updated. The good news is that you will no longer need to use separate commands to deploy vs update and update your serverless config with the created .

The rough steps for migration are as follows:

  1. Run to create the new AppSync api and make note of the endpoint returned as part of the stack outputs. If you were using an auth type, you will also need the new api key which is also included in the stack outputs.
  2. Update existing consumers of your API to use the new endpoint. If you’re using an api key, this will also need updated
  3. After verifying all existing consumers are updated, run to cleanup the old resources
  4. Remove the line from in
  5. 🍹

Youtube Video by Foo Bar :)

[![Building an AppSync + Serverless Framework BackendFooBar](https://www.youtube.com/watch?v=eTUYqI_LCQ4)](https://www.youtube.com/watch?v=eTUYqI_LCQ4)

❤️ Credits

Big Thanks to Nik Graf, Philipp Müns, Jon Patel and my favourite coolest kat ever for helping to build this plugin!

We are always looking for open source contributions. So, feel free to create issues/contribute to this repo.

Sours: https://www.serverlessconsultants.com/plugins/serverless-appsync-plugin/

Appsync serverless

Serverless Appsync Simulator

semantic-releaseReleaseAll Contributors

This serverless plugin is a wrapper for amplify-appsync-simulator made for testing AppSync APIs built with serverless-appsync-plugin.

This plugin relies on your serverless yml file and on the plugin.

Note: Order is important must go before

To start the simulator, run the following command:

You should see in the logs something like:

Put options under in your file

| option | default | description | | | | | | apiKey | | When using as authentication type, the key to authenticate to the endpoint. | | port | | AppSync operations port; if using multiple APIs, the value of this option will be used as a starting point, and each other API will have a port of lastPort + 10 (e.g. , , , etc.) | | wsPort | | AppSync subscriptions port; if using multiple APIs, the value of this option will be used as a starting point, and each other API will have a port of lastPort + 10 (e.g. , , , etc.) | | location | . (base directory) | Location of the lambda functions handlers. | | refMap | {} | A mapping of resource resolutions for the function | | getAttMap | {} | A mapping of resource resolutions for the function | | importValueMap | {} | A mapping of resource resolutions for the function | | functions | {} | A mapping of external functions for providing invoke url for external fucntions | | dynamoDb.endpoint | http://localhost | Dynamodb endpoint. Specify it if you're not using serverless-dynamodb-local. Otherwise, port is taken from dynamodb-local conf | | dynamoDb.region | localhost | Dynamodb region. Specify it if you're connecting to a remote Dynamodb intance. | | dynamoDb.accessKeyId | DEFAULT_ACCESS_KEY | AWS Access Key ID to access DynamoDB | | dynamoDb.secretAccessKey | DEFAULT_SECRET | AWS Secret Key to access DynamoDB | | dynamoDb.sessionToken | DEFAULT_ACCESS_TOKEEN | AWS Session Token to access DynamoDB, only if you have temporary security credentials configured on AWS | | dynamoDb.* | | You can add every configuration accepted by DynamoDB SDK | | watch | - *.graphql
- *.vtl | Array of glob patterns to watch for hot-reloading. |

Example:

By default, the simulator will hot-relad when changes to or files are detected. Changes to files are not supported (yet? - this is a Serverless Framework limitation). You will need to restart the simulator each time you change yml files.

Hot-reloading relies on watchman. Make sure it is installed on your system.

You can change the files being watched with the option, which is then passed to watchman as the match expression.

e.g.

Or you can opt-out by leaving an empty array or set the option to

Note: Functions should not require hot-reloading, unless you are using a transpiler or a bundler (such as webpack, babel or typescript), un which case you should delegate hot-reloading to that instead.

This plugin supports some resources resolution from the , and functions in your yaml file. It also supports some other Cfn functions such as , , etc.

Note: Under the hood, this features relies on the cfn-resolver-lib package. For more info on supported cfn functions, refer to the documentation

Basic usage

You can reference resources in your functions' environment variables (that will be accessible from your lambda functions) or datasource definitions. The plugin will automatically resolve them for you.

Override (or mock) values

Sometimes, some references cannot be resolved, as they come from an Output from Cloudformation; or you might want to use mocked values in your local environment.

In those cases, you can define (or override) those values using the , and options.

  • takes a mapping of resource name to value pairs
  • takes a mapping of resource name to attribute/values pairs
  • takes a mapping of import name to values pairs

Example:

Key-value mock notation

In some special cases you will need to use key-value mock nottation. Good example can be case when you need to include serverless stage value () in the import name.

This notation can be used with all mocks - , and

Limitations

This plugin only tries to resolve the following parts of the yml tree:

    If you have the need of resolving others, feel free to open an issue and explain your use case.

    For now, the supported resources to be automatically resovled by are:

    • DynamoDb tables
    • S3 Buckets

    Feel free to open a PR or an issue to extend them as well.

    When a function is not defined withing the current serverless file you can still call it by providing an invoke url which should point to a REST method. Make sure you specify "get" or "post" for the method. Default is "get", but you probably want "post".

    This plugin supports resolvers implemented by , as well as custom resolvers.

    From Aws Amplify:

    • NONE
    • AWS_LAMBDA
    • AMAZON_DYNAMODB
    • PIPELINE

    Implemented by this plugin

    • AMAZON_ELASTIC_SEARCH
    • HTTP

    Not Supported / TODO

    Contributors ✨

    Thanks goes to these wonderful people (emoji key):

    This project follows the all-contributors specification. Contributions of any kind welcome!

    Sours: https://www.serverless.com/plugins/serverless-appsync-simulator
    How to Query your GraphQL API with AppSync - Serverless SaaS Build Series 2.2

    The Power of Serverless GraphQL with AWS AppSync

    Slobodan Stojanović in Serverless 20 minutes Last updated Nov 12,

    Every story needs a hero. But, not all heroes are the same. Some of them have superpowers, and some are ordinary people. This story’s hero is just a regular software developer who works in a small team on a medium-size application. Our hero loves his job most of the time, except when he sends a test push notification to thousands of their customers in production, like a few minutes ago.

    One day, his boss came with a new project. “We need to build a new complex application for our new important customer.” Nice, our hero loves challenges! “But we need to do it fast, as we have a short deadline because they have an important marketing event!” Ok, how fast do we need to build an app? “It needs to be ready for yesterday. And it needs to be real-time and scalable!”

    The new project is a big challenge for our hero, as he never did that kind of project. Can he even do it?

    “You can do it,” his boss says. “I also hired a famous consultant to help you.” That’s awesome! Challenge accepted.

    After a full-day meeting with the consultant, and a whiteboard full of weird diagrams, the plan was simple: “Just use Kubernetes!”

    But our hero doesn’t know Kubernetes. And there’s no time to learn it now. What should he do?

    He started wondering if he is the only one who doesn’t know Kubernetes. Is he good enough for this job?

    Our hero spent a sleepless night in front of his computer with his faithful sidekick, a rubber duck. He tried to learn as much as he can about this new technology. But he ended up more confused and tired.

    You should try Serverless GraphQL

    In the middle of the night, our hero’s faithful sidekick said, “you should try serverless GraphQL.”

    Was he dreaming? And what the heck is serverless GraphQL? He knows what serverless is, but what’s GraphQL?

    What’s GraphQL

    Do you remember when Mark Zuckerberg said, “our biggest mistake was betting too much on HTML5?” It was a long time ago, back in , when HTML5 was in its early days.

    At that moment, the Facebook mobile app was an HTML5 web app embedded in the native mobile shell. They served all the news feed updates as HTML data from the server. However, HTML5 was in its early days, and the mobile web views were not performant enough, so the app wasn’t stable and scalable enough.

    In , Facebook’s engineering team started rebuilding their mobile and switching to the native iOS and Android apps. They evaluated different options for delivering the news feed data, including RESTful services and Facebook Query Language (FQL).

    In the “GraphQL: A data query language” article in , Lee Byron wrote:

    We were frustrated with the differences between the data we wanted to use in our apps and the server queries they required. We don’t think of data in terms of resource URLs, secondary keys, or join tables; we think about it in terms of a graph of objects and the models we ultimately use in our apps like NSObjects or JSON.

    This frustration led the Facebook engineering team to rethink the way they serve data to their mobile application. Instead of returning a full model with a lot of unnecessary data, they tried to develop a new system to return only the data the application needed.

    In , they announced GraphQL, an open-source data query language. The idea behind GraphQL was simple, the client defines the data structure, and the server provides a JSON response with precisely the same format.

    For example, the client wants to get the user with a specified ID. However, the application needs only the user’s name, a profile photo with a specific size, and the first five friend connections. Instead of sending two or three different requests to the RESTful API, with GraphQL, you can send a request similar to the one in the image below. And the response will be the JSON with the same structure, as you can see on the right side of the same image.

    That sounds nice and smart. But why should our hero care about GraphQL? He doesn’t have the same problem Facebook had.

    The problem Facebook’s engineering team had was the leading cause for inventing GraphQL. However, that’s not the only problem GraphQL solves. If you have one of the following symptoms, GraphQL might be the cure for the problems your application faces, too:

    • Distinct front end clients for multiple platforms, such as web and mobile, have different data requirements.
    • Your back end serves data to your client apps from different sources. For example, your app has SQL and NoSQL databases, and it connects to some external systems.
    • Your app has a complex state and caching managements for both front end and back end.
    • Slow pages, especially on mobile, caused by multiple dependant HTTP requests.

    This list is not complete, and GraphQL can bring even more benefits to your application. Some of the main characteristics of GraphQL are:

    • It defines a data shape. The request always specifies the response’s form, which makes requests more predictable and easier to use.
    • It’s hierarchical. Its strict relation between objects with graph-structured data simplifies getting data from multiple sources.
    • It’s strongly typed. It can give you descriptive error messages before you run a query.
    • It’s a protocol, not storage. Each GraphQL field is backed by a function on the back end, which allows you to connect it to any storage you want in the background.
    • It’s introspective. You can query the GraphQL server for the types it supports. This gives you built-in documentation and also a base for a powerful toolset.
    • It’s version free. The shape of the data is always defined by the client’s request, which means adding additional fields to your model will not affect your client application until you change the query itself.

    To combine data from multiple sources using RESTful API, you often send multiple HTTP requests and then connect data on the client-side. This works fine in perfect conditions. However, users don’t always use your app in ideal conditions. They are often on mobile with a limited or unstable network. Or they live in Australia, and each request is a few hundred milliseconds slower.

    With GraphQL, you can archive the same with a single request. This will push a bit more load to the server-side, but that works just fine in most cases. It’s even better when you don’t own the server.

    Where to start with GraphQL

    With GraphQL, you start by shaping your data using types. For example, if you are building a blog, you will have an author and a post, similar to the following code snippet. Each post will have its id, a name, a title, and an author. Authors have their ids, names, and a list of their posts.

    As you can see, types also define a relation between an author and posts.

    Once you have types, you can build your GraphQL schema. In the code snippet below, we define two queries: get author by ID and get posts by title. Each of these queries defines input parameters with their types and a return type.

    As GraphQL is not storage but a protocol, we need to tell GraphQL where and how it can read the data by creating resolvers. In the following code snippet, we define two resolvers: one for the author that connects to the SQL database and one for a list of posts sends an HTTP request to the blog platform API.

    Finally, we can run the query. As we defined queries, we can ask for an author by their ID. Relations allow us to get a list of all author’s posts in the same request. And if we ask for the author’s name for each blog post, that name will be the same as the author’s name above because it points to the same author.

    Once we run the query, GraphQL will parse the request, then validate the types and data shape, and finally, if the first two steps are correct, it will run the query and our resolvers. Once we receive the data, it’ll look similar to the following JSON data:

    By GraphQL specification, queries read the data. GraphQL specification also defines mutations and subscriptions. Mutations modify the existing data (i.e., add a new author or edit post), and subscriptions can notify you whenever the data is changed (i.e., it’ll run whenever the post is published).

    Why do we need serverless GraphQL?

    “You can always deploy your GraphQL using Kubernetes and write your resolvers by hand,” the rubber duck said, “but there’s an easier way.”

    GraphQL makes retrieving your data from the client-side effortless, but you still need to manage and scale your infrastructure. And now, you have one central place that controls all of your requests. Unless you do the same you do with the other web applications – make your application serverless. Serverless GraphQL brings the best of both worlds: GraphQL makes you client-to-server connection effortless, and serverless simplifies maintenance of your infrastructure.

    “Interesting, but how do I make GraphQL application serverless?”

    “There are many ways to do that,” the rubber duck said. “You can do that manually using the familiar serverless services. For example, on AWS, you can use Amazon API Gateway and AWS Lambda.”

    “Or you can use AWS AppSync.” Wait, what’s AppSync?

    AWS AppSync

    AWS AppSync is a managed service that uses GraphQL to make it easy for applications to get exactly the data they need. AppSync helps you to develop your application faster.

    To build your app using AppSync and GraphQL, you’ll need to do the following:

    1. Define GraphQL schema.

    2. Automatically provision a DynamoDB data source and connect resolvers.

    3. Write GraphQL queries and mutations.

    4. Connect your front end app to the GraphQL server.

    “Let’s give it a try,” the rubber duck said. “You can start with the guided schema wizard on the AWS Web Console, but you should use AWS Amplify, AWS CloudFormation, or AWS Cloud Development Kit (CDK) for more complex apps.”

    After a few hours of playing with the AWS Amplify CLI, our hero managed to build a simple app. AWS Amplify CLI helped him to get started with the following three simple commands:

    “Wow, that was fast!” our hero said.

    A week or so later, he created a working prototype of the application. “We should show this to consultant!”

    The power of AppSync

    “That will never work!” the consultant said, “this Amplify is not good enough for our complex project.”

    AWS Amplify is very good, and it’s especially useful for front-end heavy web applications. However, if you have a complex back end, it’s probably better to start with AWS CloudFormation or AWS CDK. Alternatively, you can begin with Amplify and then migrate to CloudFormation or CDK because Amplify generates CloudFormation files under the hood for you.

    AWS AppSync works fine with CDK and CloudFormation. Here’s a simple CDK example using TypeScript:

    “Ok, that might work for us.” said the consultant, “but our app needs to be real-time.”

    Remember GraphQL subscriptions? AWS AppSync supports them out-of-the-box. It lets you specify which part of your data should be available in a real-time manner. To activate the real-time subscriptions, you can add something similar to the following code snippet to your GraphQL schema. This code snippet will allow you to get real-time notifications whenever “addPost,” “updatePost,” or “deletePost” mutation is triggered.

    “Nice, but it also needs to be scalable!” the consultant reminded our hero.

    AppSync is serverless, and it connects to familiar serverless services under the hood, such as Amazon DynamoDB. Real-time subscriptions are scalable, too. What does it mean to be scalable? According to this article, the AppSync GraphQL Subscriptions were load-tested with more than ten million parallel connections! And you do not need to do anything to enable that. Everything is already set up for you. Impressive, right?

    “That’s impressive! But we also need search functionality? As far as I know, DynamoDB is not ideal for the search. Can AppSync do something for that?”

    AppSync has direct integration with Amazon ElasticSearch Service! Not sure if there’s an acronym for that one. You can do operations such as simple lookups, complex queries & mappings, full-text searches, fuzzy/keyword searches, or geo lookups directly from your GraphQL. AWS Amplify will handle this for you out-of-the-box, and if you use AWS CloudFormation or CDK, you’ll need to create your Amazon ElsasticSearch Service instance and send data to it.

    “Ok,” the consultant said, “but we also need to connect to an existing service. Can your AppSync do that?”

    You can connect AWS AppSync to AWS Lambda! AWS AppSync lets you use AWS Lambda to resolve any GraphQL field, which allows you to query or send mutations to any storage engine or a third-party service.

    “What about roles and permissions? Do we need to use Lambda resolvers to add access control?”

    AppSync has the following four built-in authorization mechanisms:

    • API_KEY authorization lets you specify API keys, hardcoded values, that the client needs to send with their GraphQL requests. API keys are especially useful for controlling throttling.
    • AWS_IAM authorization lets you associate Identity and Access Management (IAM) access policies with your GraphQL endpoint.
    • OPENID_CONNECT authorization enforces OpenID Connect (OIDC) tokens provided by an OIDC-compliant service. It allows you to use the third-party OIDC service to authorize your users.
    • AMAZON_COGNITO_USER_POOLS authorization enforces OIDC tokens provided by Amazon Cognito User Pools. A user pool is your user directory in Amazon Cognito.

    “I am a bit confused,” the consultant said. “Can you use this for our multi-tenant application?”

    You can use Cognito Groups. Each group represents different user types and app usage permissions. With AppSync, you can customize each groups’ permissions for every query or mutation. For example, if you are building a blog platform, you can add your users to the “Bloggers” and “Readers” groups, and then allow “Readers” to read posts and “Bloggers” to add or edit posts.

    “If you need more flexibility that Cognito Groups can offer,” the rubber duck said, “you can use Resolver Mapping Templates and VTL.”

    “What, your rubber duck talks?” the consultant said, but he was quickly distracted by the weirdest thing he saw in a long time. “What’s VTL template?” the consultant and our hero asked at the same time.

    Resolvers connect GraphQL and a data source. AppSync lets you use VTL to write a Resolver Mapping Template and tell GraphQL how to connect to the DynamoDB and ElasticSearch Service.

    Apache Velocity Template Language (VTL) is a Java-based alien language. Pardon, its Java-based templating engine. VTL allows you to write request and response Resolver Mapping Templates. You can embed these templates in your CloudFormation template or put them in your Amazon S3 bucket. Whatever you do, VTL templates will be hard to test in isolation. However, they are useful. Here’s the example of the VTL template that allows the owner only to do the selected action:

    “Ok, but you mentioned testing,” the consultant said. “So, how do you test your VTL templates?”

    Testing VTL templates is not easy. The more business logic you have in your VTL templates, the more you need end-to-end tests. With end-to-end tests, you’ll be sure that your application works correctly. However, these tests are slow and expensive. Having unit tests would speed up your development a lot, mainly because you need to deploy your application to check if your template is valid. Using few minutes long CloudFormation deployments as a VTL template linting tool is far from practical.

    As VTL templates are Java-based templates invented many years ago, you can use the Apache Velocity Template Engine to test your templates in isolation. However, AppSync VTL has a lot of utility functions that you would need to mock.

    Fortunately, there’s a better way to test your VTL templates in isolation. With AWS Amplify CLI open-source modules, your tests can look similar to the following code snippet.

    The code snippet above uses Jest, a popular JavaScript testing tool, but you can use your favorite JavaScript framework.

    Testing AppSync apps is a complex topic that deserves a dedicated article. Be patient; it’s on its way. Or even better, subscribe to the mailing list and get notified when we publish that article.

    “I don’t like these VTL templates,” the consultant said. “Me neither,” our hero agreed.

    You can use Direct Lambda Resolvers and skip VTL entirely. AppSync sends the Context object directly to your Lambda function.

    “Ok, that’s better,” says the consultant, “is there a way to reuse some parts of the business logic?”

    If you use Direct Lambda Resolvers, you can share the logic between multiple Lambda functions the same way you do in any Lambda function. The other option that also works with VTL templates is using Pipeline Resolvers. A pipeline resolver allows you to compose operations and run them in sequence.

    A pipeline resolver contains a “Before” mapping template, an “After” mapping template, and a series of operations (called Functions). An operation can be a VTL template connected to some data source, such as a DynamoDB table, or a Lambda function if you use Direct Lambda Resolvers.

    “I bet this is too complex for the front end!”

    Remember AWS Amplify? It has a collection of excellent front end libraries for vanilla JavaScript and all the popular front end frameworks, such as React, Angular, and Vue. It also has libraries for native iOS and Android mobile apps!

    “Fine, but I think we decided not to use AWS Amplify for our app. Why are you mentioning Amplify front end libraries now?”

    You can use AppSync with CloudFormation or CDK and use the AWS Amplify front end libraries! They work great together.

    Amplify can also automatically generate queries, mutations, subscriptions, and TypeScript types for us and help our front end team.

    Amplify also supports offline data synchronization with its Amplify DataStore, which gives you even more power on the front end. And AppSync supports caching, which can make our front end applications faster.

    “All these things sound great,” the consultant says, “but I guess you need to deploy the app to the AWS whenever you want to test it. That will slow us down, right?”

    Amplify lets you mock GraphQL APIs, including resolver mapping templates with the DynamoDB storage.

    “Ok, fine. But our app architecture is a bit more complex. What if we need event sourcing, CQRS, or some other slightly more complex architecture?”

    You can use GraphQL with event sourcing and CQRS. AppSync will help you with its integration with other AWS services, such as DynamoDB and AWS Lambda.

    For example, Vacation Tracker uses AppSync the following way:

    • The client (React application) sends commands (mutations) to the AppSync.
    • All events are stored in the DynamoDB table.
    • The DynamoDB table sends the stream to the Lambda function that publishes them to the EventBridge. EventBridge now supports replays, which allows Vacation Tracker to replay a group of events.
    • EventBridge events trigger a series of Lambda functions that apply some business logic.
    • AppSync subscription events tell the front end that the business logic is applied and if the event was successful or failed. The business logic also creates a new read-optimized snapshot.
    • The client use GraphQL queries to query the data from one of the read-optimized DynamoDB tables.

    “Ok, I give up!” the consultant said. “Let’s use GraphQL and AWS AppSync!”

    And they lived happily ever after

    Our story hero became the project hero. He delivered the project within the deadline and made his boss and customers happy.

    But what about you? Why would you use GraphQL and AppSync?

    • GraphQL makes your frontend and backend connection effortless.
    • AppSync makes GraphQL management effortless.
    • Serverless GraphQL makes you a superhero.

    If you want to learn more about serverless GraphQL with AppSync or testing serverless applications, you might want to join my mailing list and catch the new articles and free courses that we are working on.

    Sours: https://serverless.pub/the-power-of-serverless-graphql-with-appsync/

    Similar news:

    npm

    TestsAll Contributors

    Deploy AppSync API's in minutes using this Serverless plugin.

    Be sure to check out all that AWS AppSync has to offer. Here are a few resources to help you understand everything needed to get started!

    • Mapping Templates - Not sure how to create Mapping Templates for DynamoDB, Lambda or Elasticsearch? Here's a great place to start!
    • Data Sources and Resolvers - Get more information on what data sources are supported and how to set them up!
    • Security - Checkout this guide to find out more information on securing your API endpoints with AWS_IAM or Cognito User Pools!

    Install the plugin via Yarn

    or via NPM

    Configuring the plugin

    Add to the plugins section of

    Add the following config to the custom section of and update it accordingly to your needs

    custom: appSync: name: # defaults to api# apiKey # only required for update-appsync/delete-appsync# apiId # if provided, will update the specified API.authenticationType: API_KEY or AWS_IAM or AMAZON_COGNITO_USER_POOLS or OPENID_CONNECT or AWS_LAMBDAschema: # schema file or array of files to merge, defaults to schema.graphql (glob pattern is acceptable)# Caching options. Disabled by default# read more at https://aws.amazon.com/blogs/mobile/appsync-caching-transactions/# and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-apicache.htmlcaching: behavior: FULL_REQUEST_CACHING # or PER_RESOLVER_CACHING. Requiredttl: # The TTL of the cache. Optional. Default: atRestEncryption: # Bool, Optional. Enable at rest encryption. disabled by default.transitEncryption: # Bool, Optional. Enable transit encryption. disabled by default.type: 'T2_SMALL'# Cache instance size. Optional. Default: 'T2_SMALL'# if AMAZON_COGNITO_USER_POOLSuserPoolConfig: awsRegion: # defaults to provider regiondefaultAction: # required # ALLOW or DENYuserPoolId: # required # user pool IDappIdClientRegex: # optional # if AWS_LAMBDAlambdaAuthorizerConfig: functionName: # The function name in your serverless.yml. Ignored if lambdaFunctionArn is provided.functionAlias: # optional, used with functionNamelambdaFunctionArn: # required if functionName is not definedidentityValidationExpression: # optionalauthorizerResultTtlInSeconds: # optional# if OPENID_CONNECTopenIdConnectConfig: issuer: clientId: iatTTL: authTTL: apiKeys: - name: john # name of the api keydescription: 'My api key'expiresAfter: 30d# api key life time - name: janedescription: "Jane's api key"expiresAt: 'T+'# Array of additional authentication providersadditionalAuthenticationProviders: - authenticationType: API_KEY - authenticationType: AWS_IAM - authenticationType: OPENID_CONNECTopenIdConnectConfig: issuer: clientId: iatTTL: authTTL: - authenticationType: AMAZON_COGNITO_USER_POOLSuserPoolConfig: awsRegion: # defaults to provider regionuserPoolId: # required # user pool IDappIdClientRegex: # optional - authenticationType: AWS_LAMBDAlambdaAuthorizerConfig: functionName: # The function name in your serverless.yml. Ignored if lambdaFunctionArn is provided.functionAlias: # optional, used with functionNamelambdaFunctionArn: # required if functionName is not definedidentityValidationExpression: # optionalauthorizerResultTtlInSeconds: # optionallogConfig: loggingRoleArn: { Fn::GetAtt: [AppSyncLoggingServiceRole, Arn] } # Where AppSyncLoggingServiceRole is a role with CloudWatch Logs write accesslevel: ERROR # Logging Level: NONE | ERROR | ALLexcludeVerboseContent: falsedefaultMappingTemplates: # default templates. Useful for Lambda templates that are often repetitive. Will be used if the template is not specified in a resolverrequest: my.request.template.tpl # or, e.g: false for Direct lambdasresponse: my.response.template.tpl # or e.g.: false for Direct lambdasmappingTemplatesLocation: # defaults to mapping-templatesmappingTemplates: - dataSource: # data source nametype: # type name in schema (e.g. Query, Mutation, Subscription, or a custom type e.g. User)field: getUserInfo# kind: UNIT (default, not required) or PIPELINE (required for pipeline resolvers)functions: # array of functions if kind === 'PIPELINE' - # function namerequest: # request mapping template name | defaults to `defaultMappingTemplates.request` or {type}.{field}.request.vtlresponse: # response mapping template name | defaults to `defaultMappingTemplates.response` or {type}.{field}.response.vtl# When caching is enaled with `PER_RESOLVER_CACHING`,# the caching options of the resolver.# Disabled by default.# Accepted values:# - `true`: cache enabled with global `ttl` and default `keys`# - an object with the following keys:# - ttl: The ttl of this particular resolver. Optional. Defaults to global ttl# - keys: The keys to use for the cache. Optionnal. Defaults to a hash of the# $context.arguments and $context.identitycaching: keys: # array. A list of VTL variables to use as cache key. - "$context.identity.sub" - "$context.arguments.id"ttl: # override the ttl for this resolver. (default comes from global config)# When versioning is enabled with `versioned` on the datasource,# the datasync options of the resolver.# Disabled by default.# Accepted values:# - `true`: sync enabled with default ConflictDetection VERSION# - an object with the following keys:# - conflictDetection: The Conflict Detection strategy to use.# - functionName: The function name in your serverless.yml. Ignored if lambdaFunctionArn is provided.# - lambdaFunctionArn: The Arn for the Lambda function to use as the Conflict Handler.# - conflictHandler: The Conflict Resolution strategy to perform in the event of a conflict.sync: conflictDetection: VERSION # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-resolver-syncconfig.htmlconflictHandler: OPTIMISTIC_CONCURRENCY # when not using lambda conflict handler choose The Conflict Resolution strategy to perform in the event of a conflict. OPTIMISTIC_CONCURRENCY / AUTOMERGE / LAMBDAfunctionName: graphql # The function name in your serverless.yml. Ignored if lambdaFunctionArn is provided.lambdaFunctionArn: "arn:aws:lambda:{REGION}:{ACCOUNT_ID}:myFunction" - ${file({fileLocation}.yml)} # link to a file with arrays of mapping templatesfunctionConfigurationsLocation: # defaults to mappingTemplatesLocation (mapping-templates)functionConfigurations: - name: # function namedataSource: # data source namerequest: # request mapping template name | defaults to {name}.request.vtlresponse: # reponse mapping template name | defaults to {name}.response.vtldataSources: - type: NONEname: none - type: AMAZON_DYNAMODBname: # data source namedescription: # DynamoDB Table Descriptionconfig: tableName: { Ref: MyTable } # Where MyTable is a dynamodb table defined in ResourcesserviceRoleArn: { Fn::GetAtt: [AppSyncDynamoDBServiceRole, Arn] } # Where AppSyncDynamoDBServiceRole is an IAM role defined in ResourcesiamRoleStatements: # custom IAM Role statements for this DataSource. Ignored if `serviceRoleArn` is present. Auto-generated if both `serviceRoleArn` and `iamRoleStatements` are omitted - Effect: "Allow"Action: - "dynamodb:GetItem"Resource: - "arn:aws:dynamodb:{REGION}:{ACCOUNT_ID}:myTable" - "arn:aws:dynamodb:{REGION}:{ACCOUNT_ID}:myTable/*"# Versioned DataSource configurationversioned: false # (default, not required)# When you enable versioning on a DynamoDB data source, you specify the following fields# read more at https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-datasource-deltasyncconfig.html# deltaSyncConfig:# baseTableTTL: 0 # (default, not required) # The amount of time (in minutes) items should be kept in the base table when deleted. Set to 0 to delete items in the base table immediately# deltaSyncTableName: { Ref: MyTableDelta } # required # The Delta Sync table name# deltaSyncTableTTL: 60 # (default, not required) # The amount of time (in minutes) the delta sync table will keep track of changesregion: # Overwrite default region for this data source - type: RELATIONAL_DATABASEname: # data source namedescription: # data source descriptionconfig: dbClusterIdentifier: { Ref: RDSCluster } # The identifier for RDSCluster. Where RDSCluster is the cluster defined in ResourcesawsSecretStoreArn: { Ref: RDSClusterSecret } # The RDSClusterSecret ARN. Where RDSClusterSecret is the cluster secret defined in ResourcesserviceRoleArn: { Fn::GetAtt: [RelationalDbServiceRole, Arn] } # Where RelationalDbServiceRole is an IAM role defined in ResourcesdatabaseName: # optional database nameschema: # optional database schemaiamRoleStatements: # custom IAM Role statements for this DataSource. Ignored if `serviceRoleArn` is present. Auto-generated if both `serviceRoleArn` and `iamRoleStatements` are omitted - Effect: "Allow"Action: - "rds-data:DeleteItems" - "rds-data:ExecuteSql" - "rds-data:ExecuteStatement" - "rds-data:GetItems" - "rds-data:InsertItems" - "rds-data:UpdateItems"Resource: - "arn:aws:rds:{REGION}:{ACCOUNT_ID}:cluster:mydbcluster" - "arn:aws:rds:{REGION}:{ACCOUNT_ID}:cluster:mydbcluster:*" - Effect: "Allow"Action: - "secretsmanager:GetSecretValue"Resource: - "arn:aws:secretsmanager:{REGION}:{ACCOUNT_ID}:secret:mysecret" - "arn:aws:secretsmanager:{REGION}:{ACCOUNT_ID}:secret:mysecret:*"region: # Overwrite default region for this data source - type: AMAZON_ELASTICSEARCHname: # data source namedescription: 'ElasticSearch'config: domain: # a reference to a resource of type `AWS::Elasticsearch::Domain`endpoint: # required if `domain` not provided. Ex: "https://{XXX}.{REGION}.es.amazonaws.com"serviceRoleArn: { Fn::GetAtt: [AppSyncESServiceRole, Arn] } # Where AppSyncESServiceRole is an IAM role defined in ResourcesiamRoleStatements: # custom IAM Role statements for this DataSource. Ignored if `serviceRoleArn` is present. Auto-generated if both `serviceRoleArn` and `iamRoleStatements` are omitted - Effect: "Allow"Action: - "es:ESHttpGet"Resource: - "arn:aws:es:{REGION}:{ACCOUNT_ID}:{DOMAIN}" - type: AWS_LAMBDAname: # data source namedescription: 'Lambda DataSource'config: functionName: graphql # The function name in your serverless.yml. Ignored if lambdaFunctionArn is provided.lambdaFunctionArn: { Fn::GetAtt: [GraphqlLambdaFunction, Arn] } # Where GraphqlLambdaFunction is the lambda function cloudformation resource created by serverless for the serverless function named graphqlserviceRoleArn: { Fn::GetAtt: [AppSyncLambdaServiceRole, Arn] } # Where AppSyncLambdaServiceRole is an IAM role defined in ResourcesiamRoleStatements: # custom IAM Role statements for this DataSource. Ignored if `serviceRoleArn` is present. Auto-generated if both `serviceRoleArn` and `iamRoleStatements` are omitted - Effect: "Allow"Action: - "lambda:invokeFunction"Resource: - "arn:aws:lambda:{REGION}:{ACCOUNT_ID}:myFunction" - "arn:aws:lambda:{REGION}:{ACCOUNT_ID}:myFunction:*" - type: HTTPname: # data source namedescription: 'Http endpoint'config: endpoint: # required # "https://{DOMAIN}/{PATH}" - ${file({dataSources}.yml)} # link to a file with an array or object of datasourcessubstitutions: # allows to pass variables from here to velocity templates# ${exampleVar1} will be replaced with given value in all mapping templatesexampleVar1: "${self:service.name}"exampleVar2: {'Fn::ImportValue': 'Some-external-stuff'}xrayEnabled: true # Bool, Optional. Enable X-Ray. disabled by default.wafConfig: enabled: truename: AppSyncWafdefaultAction: Allow # or Block. Defaults to Allowdescription: 'My AppSync Waf rules'rules: - throttle: - disableIntrospection - name: UsOnlyaction: Block # Allow, Block, or Countstatement: NotStatement: Statement: GeoMatchStatement: CountryCodes: - UStags: # Tags to be added to AppSynckey1: value1key2: value2

    Be sure to replace all variables that have been commented out, or have an empty value.

    Working with existing APIs

    If you already have an API created in AppSync through the UI or from a different CF stack and want to manage it via Serverless then the plugin can also support that.

    There is an optional apiId parameter that you can use to specify the ID of an existing AppSync API:

    custom: appSync: # apiId: abcd#

    Without apiId parameter the plugin will create a different endpoint with the same name alongside the original one.

    You can find the apiId value in the AppSync console, just open your existing AppSync API and go to Settings.

    In that case, the plugin will not attempt to create a new endpoint for you, instead, it will attach all newly configured resources to the existing endpoint.

    The following configuration options are only associated with the creation of a new AppSync endpoint and will be ignored if you provide apiId parameter:

    • name
    • authenticationType
    • userPoolConfig
    • openIdConnectConfig
    • additionalAuthenticationProviders
    • logConfig
    • tags
    • xrayEnabled
    • apiKeys
    • wafConfig

    So later, if you wanted to change the name of the API, or add some tags, or change the logging configuration, anything from the list above you would have to do that via a different method, for example from the UI.

    If the existing API already contains schema and resolvers those will be completely replaced by the new schema and resolvers from the code.

    If the existing API already contains data sources, those data sources will remain untouched unless they have the same names as the data sources in the code, in which case they will be replaced with the ones from the code.

    Note: You should never set the apiId of an API that was previously deployed with the same serverless stack, otherwise, it would be deleted. That is because the resource would be removed from the stack.

    Only use the apiId parameter if you know what you are doing.

    Multiple APIs

    If you have multiple APIs and do not want to split this up into another CloudFormation stack, simply change the configuration property from an object into an array of objects:

    custom: appSync: - name: private-appsync-endpointschema: AppSync/schema.graphql # or something like AppSync/private/schema.graphqlauthenticationType: OPENID_CONNECTopenIdConnectConfig: serviceRole: AuthenticatedAppSyncServiceRoledataSources: mappingTemplatesLocation: mappingTemplates: - name: public-appsync-endpointschema: AppSync/schema.graphql # or something like AppSync/public/schema.graphqlauthenticationType: API_KEYserviceRole: PublicAppSyncServiceRoledataSources: mappingTemplatesLocation: mappingTemplates:

    Note: CloudFormation stack outputs and logical IDs will be changed from the defaults to api name prefixed. This allows you to differentiate the APIs on your stack if you want to work with multiple APIs.

    Direct Lambda Resolvers

    Amazon supports direct lambda resolvers

    With a direct lambda resolver, no VTL mapping template is required for either request or response. This can be an option if you would like to avoid usage of the Apache VTL langauge or require a complex resolver. You can enable direct Lambda resolvers by setting as the and/or value.

    Example:

    custom: appsync: mappingTemplates: - type: Queryrequest: falseresponse: falsedataSource: myLambdaSourcefield: getMyData

    Furthermore, direct resolution can be enabled separately for the request and response templates.

    Pipeline Resolvers

    Amazon supports pipeline resolvers

    They allow you to perform more than one mapping template in sequence, so you can do multiple queries to multiple sources. These queries are called function configurations ('AWS::AppSync::FunctionConfiguration') and are children of a resolver.

    Here is an example of how to configure a resolver with function configurations. The key here is to provide a 'kind' of 'PIPELINE' to the mapping template of the parent resolver. Then provide the names of the functions in the mappingTemplate to match the names of the functionConfigurations.

    custom: appSync: mappingTemplates: - type: Queryfield: testPipelineQueryrequest: './mapping-templates/before.vtl'# the pipeline's "before" mapping template, defaults to {type}.{field).request.vtlresponse: './mapping-templates/after.vtl'# the pipeline's "after" mapping template, defaults to {type}.{field}.response.vtlkind: PIPELINEfunctions: - authorizeFunction - fetchDataFunctionfunctionConfigurations: - dataSource: graphqlLambdaname: 'authorizeFunction'request: './mapping-templates/authorize-request.vtl'# defaults to {name}.request.vtlresponse: './mapping-templates/common-response.vtl'# defaults to {name}.response.vtl - dataSource: dataTablename: 'fetchDataFunction'request: './mapping-templates/fetchData.vtl'# defaults to {name}.request.vtlresponse: './mapping-templates/common-response.vtl'# defaults to {name}.response.vtl

    Managing API keys

    Since v, api keys management is supported. You can pass one or more api keys configuration as an array in the property.

    The keys can either be a string (name of the key with defaults) or an object of the following shape:

    propertydefaultdescription
    nameauto-generatedName of the key. This is used under the hood to differentiate keys in the deployment process.

    Names are used in the Cfn resource name. Please, keep them short and without spaces or special characters to avoid issues. Key names are case sensitive.
    descriptionname of the keyA short description for that key
    expiresAfterdExpiration time for the key.
    Can be expressed in hours or in "human" format (As in momentjs add).
    eg: , , , ,
    Min: 1d, max: 1y
    expiresAtone year from nowA specific expiration date in ISO format. Or as a unix timestamp
    apiKeyIdthe id if the api to update. Useful for when an api key has been created manually in the AWS console.

    If both and are specified, takes precedence.

    When naming keys, you need to be aware that changing the value will require the replacement of the api key.

    Unnamed keys are named automatically sequentially Key1, Key2, Key3 and so forth.

    Be careful when removing unnamed keys!!!. For exemple, if you have 3 unnamed keys and you remove the second one in your list, Key3 will become Key2. As a result, it is former Key3 that will be removed. To workaround that, you could specify their auto-generated names before removing any unnamed keys (Key1, Key2 and Key3 in our example. Then remove Key2). As a rule of thumb, all keys should be named to avoid issues.

    If you have already deployed and an api key was previously auto-generated for you (either in version < or if you deployed without specifying the property), you can add it to your yml template by naming it (case sensitive!!). Starting from there, you can add additional API keys.

    If you want to revoke a key, delete it, or rename it.

    If a key expires, or you have manually deleted it from the cosole, subsequent deployments will fail (after 60 days in the case it expires). You can fix that by simply removing the key from your yml file, or by renaming it (in which case, a new key will be generated).

    Example:

    apiKeys: - name: Default # default API key. Use this name if you already have an auto-generated API keydescription: Default api keyexpires: 1y# 1 year timelife - Mark # inline named key, with defaults (1 year duration) - name: Johndescription: John api keyexpires: 30d - name: Janeexpires: 2d - description: Unnamed key # first unnamed key (Key1) - expires: 30d# second unnamed key (Key2) - name: ThrottledAPIKeywafRules: - throttle # throttle this API key to requests per 5 min - name: GeoApiKeydescription: Us Only# Disallow this Api key outsite the USwafRules: - action: Blockname: UsOnlystatement: NotStatement: Statement: GeoMatchStatement: CountryCodes: - US

    Finally, if you dont't want serverless to handle keys for you, just pass an empty array:

    # Handle keys manually in the aws console.apiKeys: []

    WAF Web ACL

    AppSync supports WAF. WAF is an Application Firewall that helps you protect your API against common web exploits.

    This plugin comes with some handy pre-defined rules that you can enable in just a few lines of code.

    Throttling

    Throttling will disallow requests coming from the same ip address when a limit is reached within a 5-minutes period.

    There are several ways to enable it. Here are some examples:

    wafConfig: enabled: truerules: - throttle # limit to requests per 5 minutes period - throttle: # limit to requests per 5 minutes period - throttle: limit: priority: 10aggregateKeyType: FORWARDED_IPforwardedIPConfig: headerName: 'X-Forwarded-For'fallbackBehavior: 'MATCH'

    Disable Introspection

    Sometimes, you want to disable introspection to disallow untrusted consumers to discover the structure of your API.

    wafConfig: enabled: truerules: - disableIntrospection # disables introspection for everyone

    Using AWS Managed Rules

    You can use AWS Managed Rules using this configuration:

    wafConfig: enabled: truerules: - name: MyRule1 # this is your rule nameoverrideAction: none: {}statement: managedRuleGroupStatement: vendorName: AWSname: AWSManagedRulesCommonRuleSet # this is the name of the managed rule

    Managed rules require set and not set.

    For more information view the AWS Managed Rule Groups List.

    Per Api Key rules

    In some cases, you might want to enable a rule only for a given API key only. You can specify under the configuration. The rules will apply only to the api key under which the rule is set.

    apiKeys: - name: MyApiKeyexpiresAfter: dwafRules: - throttle # throttles this API key - disableIntrospection # disables introspection for this API key

    Adding a rule to an API key without any statement will add a "match-all" rule for that key. This is usefull for example to exclude api keys from high-level rules. In that case, you need to make sure to attribute a higher priority to that rule.

    Example:

    • Block all requests by default
    • Add a rule to allow US requests
    • Except for the key, that should have worldwide access.
    wafConfig: enabled: truedefaultAction: Block # Block all by defaultrules: # allow US requests - action: Allowname: UsOnlypriority: 5statement: geoMatchStatement: countryCodes: - USapiKeys: - name: Key1 # no rule is set, the top-level rule applies (Us only) - name: Key1 # no rule is set, the top-level rule applies (Us only) - name: WorldWideApiKeywafRules: - name: WorldWideApiKeyRuleaction: Allowpriority: 1# Make sure the priority is higher (lower number) to evaluate it first

    About priority

    The priorities don't need to be consecutive, but they must all be different.

    Setting a priority to the rules is not required, but recommended. If you don't set priority, it will be automatically attributed (sequentially) according to the following rules:

    First the global rules (under ), in the order that they are defined. Then, the api key rules, in order of api key definitions, then rule definition. Auto-generated priorities start at This gives you some room () to add other rules that should get a higher priority, if you need to.

    For more info about how rules are executed, pease refer to the documentation

    Example:

    wafConfig: enabled: truerules: - name: Rule1# (no-set) Priority = - name: Rule2priority: 5# Priority = 5 - name: Rule3# (no-set) Priority = apiKeys: - name: Key1wafRules: - name: Rule4# (no-set) Priority = - name: Rule5# (no-set) Priority = - name: KeywafRules: - name: Rule6priority: 1# Priority = 1 - name: Rule7# (no-set) Priority =

    Advanced usage

    You can also specify custom rules. For more info on how to define a rule, see the Cfn documentation

    Example:

    wafConfig: enabled: truedefaultAction: Blockrules: # Only allow US users - action: Allowname: UsOnlystatement: geoMatchStatement: countryCodes: - US

    Schema Comments

    In some cases you want to enable usage of old-style comments (#) in appSync. setting the setting to true, will enable this.

    Example:

    custom: appSync: name: # defaults to apiallowHashDescription: true# other settings

    Stack Outputs & Exports

    and are exported to allow cross-stack resource reference using . Output Exports are named with a prefix to the logical IDs. For example, .

    Note: CloudFormation stack outputs and logical IDs will be changed from the defaults to api name prefixed. This allows you to differentiate the APIs on your stack if you want to work with multiple APIs.

    This command will deploy all AppSync resources in the same CloudFormation template used by the other serverless resources.

    • Providing the option will conceal the API keys from the output when the authentication type of is used.

    Validates your GraphQL Schema(s) without deploying.

    This command will start a local graphql-playground server which is connected to your deployed AppSync endpoint (in the cloud). The required options for the command are different depending on your AppSync authenticationType.

    For API_KEY, either the GraphQLApiKeyDefault output or the --apiKey option is required

    For AMAZON_COGNITO_USER_POOLS, the -u/--username and -p/--password arguments are required. The cognito user pool client id can be provided with the --clientId option or directly in the yaml file ()

    For OPENID_CONNECT, the --jwtToken option is required.

    The AWS_IAM authenticationType is not currently supported.

    There are 2 ways to work with offline development for serverless appsync.

    serverless-appsync-simulator

    serverless-appsync-simulator is a wrapper of aws's amplify-cli for serverless and this plugin. Both are actively maintained.

    serverless-appsync-simulator (deprecated/unmaintained)

    serverless-appsync-offline is based on AppSync Emulator. Both these packages are currently unmaintained.

    You can use serverless-plugin-split-stacks to migrate AppSync resources in nested stacks in order to work around the resource limit.

    1. Install serverless-plugin-split-stacks
    1. Follow the installation instructions

    2. Place after

    plugins: - serverless-appsync-plugin - serverless-plugin-split-stacks
    1. Create in the root folder
    module.exports={'AWS::AppSync::ApiKey': {destination: 'AppSync',allowSuffix: true},'AWS::AppSync::DataSource': {destination: 'AppSync',allowSuffix: true},'AWS::AppSync::FunctionConfiguration': {destination: 'AppSync',allowSuffix: true},'AWS::AppSync::GraphQLApi': {destination: 'AppSync',allowSuffix: true},'AWS::AppSync::GraphQLSchema': {destination: 'AppSync',allowSuffix: true},'AWS::AppSync::Resolver': {destination: 'AppSync',allowSuffix: true}}
    1. Enjoy

    If you have any questions, issue, feature request, please feel free to open an issue.

    You are also very welcome to open a PR and we will gladely review it.

    VSCode extensions

    Video tutorials

    Blog tutorial

    Thanks goes to these wonderful people

    This project follows the all-contributors specification. Contributions of any kind welcome!

    Sours: https://www.npmjs.com/package/serverless-appsync-plugin


    419 420 421 422 423