Skip to main content

API Package

WHAT YOU’LL LEARN
  • how to quickly create a functional API package

Prerequisites#

Before you start this tutorial, make sure that you have Webiny installed and to read our Introduction tutorial.

Overview#

The API scaffold is our boilerplate GraphQL API that works out of the box without you needing to actually write any code. It will enable you to create, update and delete the data in the database and fetch it via get and list API endpoints. In this article we will go through the process of generating the code.

The command you will run is yarn webiny scaffold, and you run it from the project root.

You will get a set of simple questions to answer and, in the end, an API package will be generated.

Also note that in this tutorial we will use CarManufacturer as our data model name.

Running the Scaffold#

Run the scaffold command and follow the questions. Select the GraphQL API package option and let's go through all the questions in detail:

1. Enter the name of the initial data model#

This is the name of your API data model, so type it in. As mentioned before, we will use CarManufacturer in this tutorial.

The GraphQL queries, mutations, responses, and variable names in the code will use this value in singular and plural, kebab-case, camel-case or some other form.

graphql.ts
type CarManufacturer {
id: ID!
createdOn: DateTime!
savedOn: DateTime!
createdBy: CreatedByResponse!
title: String!
description: String
isNice: Boolean!
}
type CarManufacturerListResponse {
data: [CarManufacturer]
meta: CarManufacturerListMeta
error: CarManufacturerError
}

The name value is also used to create both the defaults for the package location and the package name.

The initial data model has 3 fields (title, description and isNice) to show you how to structure your data model.

Validation of the data model name allows only a-z and A-Z. You can name your model all lowercase or all uppercase. It is up to you - but try to keep it in pascal-case.

2. Enter the package location#

A full location of the package, where the package files will be generated, from the root of the project.

info

The value given in the previous question is used to create the default package location.

We think it is best to organize your packages in packages directory, so by default it is set into that directory, but you can type whatever location you want.

note

To learn more about Webiny's project organization, checkout this article.

The default value is packages/car-manufacturers/api, and notice that the data model name CarManufacturer is in plural and kebab-cased.

3. Enter the package name#

The package name that you will reference to in the code.

info

As in the location step, the value from the first question is used to create the default package name.

The default value is @car-manufacturers/api as we like scoping packages. You can set it to what ever you want, providing it is passing the validation.

The Code#

Generated code contains:

  1. src/index.ts with GraphQLSchemaPlugin plugin type which defines the GraphQL schema and resolvers.
  2. src/configuration.ts with the configuration for DynamoDB table, Elasticsearch DynamoDB stream table and Elasticsearch index.
  3. src/es.ts with helpers to build the Elasticsearch query out of the GraphQL query arguments.
  4. src/types.ts with interfaces for resolvers, application context, arguments.
  5. __tests__/useGqlHandler.ts with the setup of the test runners.
  6. __tests__/graphql/carManufacturers.ts with GraphQL queries and mutations to be run.
  7. __tests__/crud.test.ts with the tests for the resolvers.

Elasticsearch#

In the generated code we provide some basic Elasticsearch functionality. Although the DynamoDB is the database the data is being stored to, it does not provide a lot of search capabilities so we introduced the Elasticsearch.

If you do not want to use it you will need to modify the code a bit for it to work without the Elasticsearch.

If you want to use the Elasticsearch functionality, that is provided with the generated code, you must run a GraphQL install mutation described in the information after the code was generated. This will create the Elasticsearch index for your data.

Testing#

The API scaffold generates initial GraphQL API tests for you. As you add or remove functionality from the code, tests should reflect those changes, so you can be sure that API is working as intended.

You can run tests locally with command ELASTICSEARCH_PORT=9200 LOCAL_ELASTICSEARCH=true yarn test packages/car-manufacturers/api or yarn test packages/car-manufacturers/api, if you removed the Elasticsearch.

Tests are Jest based and files must end in .test.ts to be run.

If you are using the Elasticsearch, you must have local Elasticsearch started for this to work. Port can be something other than 9200.

Generated tests cover CRUD operations and sorting by createdOn and title fields.

Using the Generated Code in Your Project#

In the main GraphQL file you need to import your package and include it in the existing handler.

api/code/graphql/src/index.ts
// at the top of the file
import carManufacturerPlugin from "@car-manufacturers/api";
// somewhere after headlessCmsPlugins() in the end of the createHandler() function
carManufacturerPlugin()

Deploy the API#

To use the generated GraphQL API, you must deploy it. To deploy, use the command:

yarn webiny deploy api --env YOUR_ENVIRONMENT

Accessing the API#

When you deploy the code you will get a URL of the API, it should look something like https://m19ckhk09hc31l.cloudfront.net.

GraphQL is accessible on that url with addition of /graphql, so it is https://m19ckhk09hc31l.cloudfront.net/graphql.

To create new CarManufacturer entry, the mutation is:

mutation CreateCarManufacturerMutation {
carManufacturers {
createCarManufacturer(data: {
title: "Mercedes",
isNice: true,
description: "A nice car manufacturer"
}) {
data {
id
title
isNice
description
createdOn
savedOn
createdBy {
id
displayName
type
}
}
error {
message
code
data
}
}
}
}

To list all the CarManufacturer entries, the query is:

query ListCarManufacturerQuery {
carManufacturers {
listCarManufacturers {
data {
id
title
isNice
description
createdOn
savedOn
createdBy {
id
displayName
type
}
}
meta {
cursor
hasMoreItems
totalCount
}
error {
message
code
data
}
}
}
}

Adding Additional Schema to the Code#

When you want to extend the GraphQL schema you should add it to the typeDefs property of the GraphQLSchemaPlugin in packages/car-manufacturers/api/src/index.ts file.

Adding Additional Resolvers to the Code#

When you add some additional schema, you also must add the resolver for it. You should add it to the resolvers property of the GraphQLSchemaPlugin in packages/car-manufacturers/api/src/index.ts file.

Be aware that the resolver should be under the CarManufacturerQuery or CarManufacturerMutation properties, if you added schema into those.

Building the Code#

When you make changes to the code, make sure you run yarn webiny ws run build --folder=packages/car-manufacturers/api to actually compile your code for the deployment.

You can even have a watcher running for your code with yarn webiny ws run watch --folder=packages/car-manufacturers/api.

Of course, the folder value is your package location.

Next Step...#

Now that you have a functioning API, let's move onto the Admin area.

Last updated on by Bruno Zorić