Functions EAP
Table of contents
What are Functions?
Functions are serverless functions that run on Contentful’s delivery infrastructure. Some of our marketplace apps already have out-of-the-box support for External references such as Shopify, Commercetools and Cloudinary. If you want to fetch additional content from different resources, you can use the Functions feature to connect to external systems and enrich the response of the GraphQL request issued through Contentful's GraphQL API.
Examples
Function | Command | Description |
---|---|---|
function-potterdb | npx create-contentful-app --example function-potterdb |
This example serves as a Function for Contentful. It is designed to proxy GraphQL requests to PotterDB. |
function-potterdb-rest-api | npx create-contentful-app --example function-potterdb-rest-api |
This example also serves as a Function but is specifically tailored for wrapping a REST API in a GraphQL response. It's useful when you have a RESTful service, and you want to provide a GraphQL interface for it in your Function. |
function-mock-shop | npx create-contentful-app --example function-mock-shop |
This Function example uses Mock Shop API which is a fake e-commerce platform built by Shopify. You can also follow the our tutorial for this example. |
The following diagram displays the Function request flow:
The Function event handler can parse two different types of events:
- GraphQL field mapping event – the information returned by your function for this event is used to decide which GraphQL type is exposed on the additional
_data
field. - GraphQL query event - your function will receive this event whenever we want to get data for a GraphQL request. This includes introspection queries.
The Function event handler can return two different types of responses:
Each field that is configured with Functions, must map to a schema. We need to know the relation with the field and the corresponding GraphQL type in the Function. Therefore, the field mapping response should include a field mapping for each field.
Given the schema below:
type Query {
product(id: String!): Product
}
type Product {
title: String!
description: String
inStock: Int!
}
Here is the typing for GraphQLFieldMapping
:
type GraphQLFieldTypeMapping = {
contentTypeId: string
fieldId: string
graphQLOutputType: string
graphQLQueryField: string
graphQLQueryArguments: Record<string, string>
}
GraphQLFieldTypeMapping
would have the following values for the product
field:
Value | Description |
---|---|
contentTypeId: 'Shop' |
Content type ID that includes the field with Resolve content on delivery checkbox enabled. |
fieldId: 'product' |
Field ID that includes the field with Resolve content on delivery checkbox enabled. |
graphQLQueryField: 'product' |
Field name in the query object of the given GraphQL schema. |
graphQLOutputType: 'Product' |
The GraphQL type that you want to attach to our _data field. |
graphQLQueryArguments: { id: '' } |
Arguments that match for the field. id matches the argument for the product field and the empty value states that the data from the field should be passed as is. |
The information coming in the event.fields
array in the field mapping event is driven by the annotations that are added to the field once you enable Resolve content on delivery checkbox
.
To get the schema, we run an introspection query that ends up triggering the graphql.query
event. Note that this might happen repeatedly, and not when you install an app.
Limitations
- You can only have one Function per custom Contentful App defined.
- A Function has a maximum execution time of 5 seconds.
- Functions run only for uncached requests.
- Functions are only available for private apps.
- Functions can only be used with short Text or JSON object field types.
- This feature allows you to integrate with external GraphQL APIs. It is also possible to integrate with external REST APIs, but you will need to provide your own GraphQL server implementation. You can look at our PotterDB for REST example example to see the REST API implementation.
Get started with Functions
To build a custom Function:
- Create a custom Contentful App.
- Generate a Content Management API (CMA) Access Token.
- Set up your app. To scaffold a new Contentful app with TypeScript support and a Function, run the following command:
npx @contentful/create-contentful-app@latest my-fn --function external-references
. Note thatmy-fn
is the name of your app. You can replace this with your desired name. - Define your schema.
- Add your environment variables (like the CMA token) to an
.env
file in the root of your project. To keep your secrets safe, make sure you include the.env
line in your.gitignore
file. - Build your app by running the following command:
npm run build
. - Upload your app to Contentful by running the following command:
npm run upload-ci
. - Install your app.
- Create a content type.
IMPORTANT: To use the Functions, make sure you select your app while configuring your content type and enable the Resolve content on delivery checkbox.
- Create an entry.
- Make a GraphQL request. You can use the GraphQL Playground app to try this easily.
query {
topicProduct(id: "ENTRY_ID") {
myField
myField_data {
foo
}
}
}
Within the topicProduct
content type, there is a field named myField
which represents the content within topicProduct
.
The query also contains a reference to myField_data
. The _data
suffix in the field name implies that it is intended for use with functions. Functions are custom functions that retrieve content, and the _data
suffix is a convention to signify that the field is designed to access content fetched through these functions. The foo
type comes from the schema used in the function implementation.
Here is an example Response with resolved data from the function:
{
"data": {
"topicProduct": {
"myField": "this is a test",
"myField_data": {
"foo": "hello world"
}
}
}
}
Inspect Function invocations and logs
To get a better understanding of how your Function is performing, you can inspect the invocations and log output. You can do this by navigating to the App configuration page in the Contentful web app and selecting the Functions tab. Open the menu of the function you want to inspect and select View logs.
On the Function logs page you will need to select the space and environment you have installed the app in. This will load a list of all invocations of the function in the selected space and environment. You can click on an invocation to see the log output of the function.
At the top of the drawer you can expand the Event section to see the event that triggered the function. Below that you will see the log output of the function.
The log severity is based on the log method used in the function. console.log
will show severity info
, console.warn
will show severity warn
, and console.error
will show severity error
. You can utilise this to quickly find relevant logs in the table that lists all the invocations.
Feedback
Our Product team highly welcomes feedback for all our features. To share your feedback, you can fill in this form.