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
anchor

The Extend GraphQL API scaffold extends your project’s GraphQL HTTP API with a new CRUD external link 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/graphql external link 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.
Learn more about the API project application on the cloud infrastructure level in the Cloud Infrastructure key topics section.

Features
anchor

New CRUD Query and Mutation Operations
anchor

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
}

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

Storing and Retrieving Data
anchor

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

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

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 external link, you’re free to use it, but it will require some manual migration work.

Multi-Locale Support Enabled
anchor

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 take in order to enable multi-locale support.

Testing Setup
anchor

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__ external link folder located within the scaffolded application code. More on this in the Development section below.
A brief overview of different types of tests can be found in the CI/CD / Testing key topic.

No Additional Cloud Infrastructure Resources
anchor

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/graphql external link).

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

Development
anchor

Usage
anchor

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
anchor

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

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

index.ts external link
anchor

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

typeDefs.ts external link
anchor

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/ external link
anchor

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

These will need to be updated as you make changes in the mentioned typeDefs.ts external link 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 external link class.

entities/ external link
anchor

Contains DynamoDB Toolbox external link 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__/ external link
anchor

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
anchor

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
anchor

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 apps/api/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
anchor

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.
To run the tests, Webiny relies on Jest, a JavaScript testing framework with a focus on simplicity.

Initial Test Files
anchor

typeDefs.unit.test.ts external link
anchor

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 external link
anchor

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 external link
anchor

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
anchor

All of the test-running scripts can already be found in your root package.json external link 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.

Jest supports the --watch external link 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
anchor

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

FAQ
anchor

How Does Security (Authentication and Authorization) Work?
anchor

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 behavior.

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?
anchor

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 external link.

Can Webiny's Multi-Tenancy Feature Be Utilized With This Scaffold?
anchor

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 external link.