Skip to main content

Extend GraphQL API

Can I use this?

The Extend GraphQL API scaffold (previously GraphQL API Package) received a major overhaul in Webiny 5.9.0. Note that this guide is not relevant for projects that are using Webiny 5.8.0 and lower.

What you'll learn
  • main features of the Extend GraphQL API scaffold
  • how to continue developing on top of the generated application code

Overview#

The Extend GraphQL API scaffold extends your project's GraphQL HTTP API with a new CRUD query and mutation operations.

Note that, when we say GraphQL HTTP API, by default, we're referring to the one deployed as part of the API project application, located within the api/code/graphql folder. But, the scaffold can be used with any GraphQL API you might have in your project, especially the ones created with the GraphQL API scaffold.

info

Learn more about the API project application on the cloud infrastructure level in the Cloud Infrastructure key topics section.

Features#

New CRUD Query and Mutation Operations#

The Extend GraphQL API extends your GraphQL API with two query and three mutation operations.

The names of these depend on the name of the initial data model, which is specified during the scaffold's wizard. For example, by passing CarManufacturer as the initial data model name, the GraphQL API will be extended with the following queries and mutations:

type CarManufacturerQuery {
# Returns a single CarManufacturer entry by given ID.
getCarManufacturer(id: ID!): CarManufacturer
# Returns a list of CarManufacturer entries. Supports basic sorting and pagination.
listCarManufacturers(
limit: Int
before: String
after: String
sort: CarManufacturersListSort
): CarManufacturersList!
}
type CarManufacturerMutation {
# Creates and returns a new CarManufacturer entry.
createCarManufacturer(data: CarManufacturerCreateInput!): CarManufacturer!
# Updates and returns an existing CarManufacturer entry.
updateCarManufacturer(id: ID!, data: CarManufacturerUpdateInput!): CarManufacturer!
# Deletes and returns an existing CarManufacturer entry.
deleteCarManufacturer(id: ID!): CarManufacturer!
}
extend type Query {
carManufacturers: CarManufacturerQuery
}
extend type Mutation {
carManufacturers: CarManufacturerMutation
}
info

If you want to check out the full GraphQL schema that's generated during the scaffolding, take a look at the template that's used in the process.

Storing and Retrieving Data#

All of the generated GraphQL queries and mutations rely on a single database for storing and retrieving data. By default, this is Amazon DynamoDB, which is defined in api/pulumi/dev/dynamoDb.ts and api/pulumi/prod/dynamoDb.ts.

For all database interactions, the generated application code relies on a library called DynamoDB Toolbox:

The DynamoDB Toolbox is a set of tools that makes it easy to work with Amazon DynamoDB and the DocumentClient. It's designed with Single Tables in mind, but works just as well with multiple tables.

Note that if you prefer a different library, like for example the DynamoDB Document Client, you're free to use it, but it will require some manual migration work.

Multi-Locale Support Enabled#

By default, Webiny Admin Area is a multi-locale system, which means entries like pages, page categories, forms, settings, and so on, are always created for a specific locale.

The generated application code follows the same idea. There aren't any additional steps that you need to takefyo in order to enable multi-locale support.

Testing Setup#

With the application code, the scaffold also generates one unit, one integration, and one end-to-end (E2E) test, which you can use as a reference in further development. All of the tests can be found in the __tests__ folder located within the scaffolded application code. More on this in the Development section below.

tip

A brief overview of different types of tests can be found in the CI/CD / Testing key topic.

No Additional Cloud Infrastructure Resources#

The scaffold does not add any additional cloud infrastructure resources. The generated application code is simply added to the existing GraphQL API application code (api/code/graphql).

Of course, if additional cloud infrastructure resources are needed, you're free to amend the existing cloud infrastructure code, and reference the added and deployed resources in your application code.

Development#

Usage#

In order to use this scaffold, from your project root, simply run the webiny scaffold command:

yarn webiny scaffold

Then, from the list of all available scaffolds, select Extend GraphQL API and follow the on-screen instructions.

Essential Files#

The following are the most essential files and folders that are generated in the scaffolding process.

info

By default, all of the files are generated in a new folder, located at api/code/graphql/src/plugins/scaffolds/{dataModelName}, for example api/code/graphql/src/plugins/scaffolds/carManufacturers.

index.ts#

This is the entry file, which exports the GraphQLSchemaPlugin plugin responsible for extending the existing GraphQL API schema, using new type definitions and supporting resolvers.

typeDefs.ts#

A file that contains the schema with which we are extending our GraphQL API. This will usually be the starting point if you want to make further changes to the generated code, for example add new fields to the initial data model, add new GraphQL query or mutation operations, and more.

Note that in the case of the latter, you also need to define a standalone resolver function that is responsible for handling newly added query or mutation operation.

resolvers/#

This folder contains the GraphQL resolver classes that support the generated query and mutation GraphQL operations.

These will need to be updated as you make changes in the mentioned typeDefs.ts file. For example, if you were to introduce a new listPopularCarManufacturers GraphQL query, the same listPopularCarManufacturers method would need to be defined within the CarManufacturersQuery class.

entities/#

Contains DynamoDB Toolbox entities, which are used within GraphQL resolver functions. You are free to add additional entities, or modify the existing one (for example - add new entity attributes).

__tests__/#

Contains tests that ensure your application code is working as expected. As mentioned, three tests are included by default: one unit, one integration, and one end-to-end (E2E) test.

First Deploy#

Once you've completed the scaffold's wizard and the files have been generated, in order to actually see the changes made to your GraphQL API, you need to deploy them. This can be done as usual via the webiny deploy command, or, even easier, if you're about to jump straight into coding, by running the webiny watch command. This command will not only deploy the changes, but also start a new watch session, which will automatically redeploy further application code changes, as you perform them. More on this below.

Development Using the Watch Command#

The most straightforward way to further develop on top of the generated code would be via the webiny watch command.

In order to get started, from your project root, simply run the following command:

yarn webiny watch api/code/graphql --env {env}

With the new watch session initialized, every change you make in the code will automatically trigger a re-deploy of the code, enabling you to see the changes in the cloud almost immediately as you make them (every redeployment takes 2-4 seconds to complete).

And although developers often choose this approach when developing smaller features or proof of concepts, for anything larger in scope, we recommend the new code to be tested via one or more of the mentioned types of tests.

Writing and Running Tests#

As mentioned in the Features section, by default, the scaffold includes three tests: one unit, one integration, and one end-to-end (E2E) test. When generated, all three tests should be passing once you run them, but do note that in order for the integration and end-to-end (E2E) tests to pass, you have to have your API project application already deployed, preferably into a development environment, for example dev.

info

To run the tests, Webiny relies on Jest, a JavaScript testing framework with a focus on simplicity.

Initial Test Files#

typeDefs.unit.test.ts#

A simple unit test which simply ensures that the base GraphQL type exists. Might not be a super useful example, but still, this test is here more for awareness purposes (so that developers know these can be added too).

crud.integration.test.ts#

An integration test which ensures essential CRUD GraphQL query and mutation operations are working as expected. These tests are run against the application code that you have locally, but note that the code is still interacting with real cloud infrastructure resources.

crud.e2e.test.ts#

An end-to-end (E2E) test which ensures essential CRUD GraphQL query and mutation operations are working as expected.

Note that, although it may seem this test is testing the same functionality we've tested with the integration test, this test is run against the application code that's deployed into the actual cloud, by issuing HTTP requests to the deployed Cloudfront distribution, behind which our AWS Lambda function resides. In other words, this test makes sure not only our code is working as expected, but also that the cloud infrastructure resources are deployed and configured properly.

Running Tests#

All of the test-running scripts can already be found in your root package.json file.

In order to run all tests, use the yarn test command. Additionally, to only run tests of a specific type, use the yarn test:unit, yarn test:integration, and yarn test:e2e commands.

tip

Jest supports the --watch argument, which enables us to continuously re-run tests as we're making changes to them. You can use it with the above-shown commands.

Creating New Tests#

You are free to create new tests in the similar fashion, or amend the existing one.

FAQ#

How does security (authentication and authorization) work?#

Please note that, by default, the authentication and authorization logic isn't included in the generated code. In other words, all of the generated GraphQL query and mutation operations can be performed by anonymous (not logged-in) users, which is in most cases not the desired behaviour.

Luckily, with a couple of built-in utilities, this can be relatively easily added. Please check out the existing tutorials to learn how to implement these on your own.

I need more flexibility when it comes to data querying. Can I bring in a different database, for example ElasticSearch?#

Yes, you can. You can actually utilize the already deployed ElasticSearch cluster that's deployed with every Webiny project, by default.

Until we create a dedicated tutorial on the topic, feel free to ping us via our community Slack.

Can Webiny's multi-tenancy feature be utilized with this scaffold?#

Yes, but do note that since multi-tenancy is part of Webiny's enterprise offering, the relevant multi-tenancy code is not included in the generated application code.

For more information on multi-tenancy, we recommend you check out the Multi-Tenancy key topic. Also, for any implementation-related questions, feel free to contact us directly via our community Slack.

Last updated on by Adrian Smijulj