The Jaha GraphQL API allows you to define your own types and queries with the GraphQL Schema Definition Language (SDL). You can easily deploy it along with your module. To learn how to create a Jahia module, see Creating a new module which shows how to create a module in Studio or from scratch.
After you deploy your SDL schema, you can check the deployment status in Developer Tools>SDL Report Tool in Jahia. Jahia also has an integrated GraphQL console to let you view and test your custom schema definitions. You open the console from Developer Tools>GraphQL.
First, create and place your SDL file in your module under the following directory.
Since Jahia GraphQL API uses a fixed SDL file name to look up custom schema, you must use the graphql-extension.sdl file name to maintain all GraphQL types.
This example SDL defines two custom object types and queries that you could place into your module. If you are not familiar with the syntax of SDL don’t worry, more details are provided later.
The SDL file is plain text and you can use any text editor to create it.
extend type Query {
newsByTitle: NewsConnection
allNews: [News]
}
type hotel @mapping(node: "jnt:hotel"){
name: String! @mapping(property: "jcr:title")
city: String @mapping(property: "city")
address: String @mapping(property: "address")
country: String @mapping(property: "country")
}
type booking @mapping(node: "jnt:booking"){
title: String @mapping(property: "jcr:title")
room: Int @mapping(property: "roomNo")
created: Date @mapping(property: "date")
}
Once you create your SDL file and place it into your module, you are ready to deploy your own schema along with your module. Now your own SDL schema is deployed. You can use Jahia’s SDL Report Tool to check the deployment status.
Once module is deployed:
Jahia provides a tool for viewing all GraphQL types and running queries.
To test custom types and queries:
You should find the type and query definition documents in the current schema. You can also use this GraphQL console to run a query statement to test your types and queries.
SDL syntax is similar to JSON syntax. Jahia GraphQL API supports the standard syntax and provides some special directives for Jahia content type. The example that follows the data type descriptions shows how to create your own schema using Jahia GraphQL directives.
To start learning SDL syntax, first get to know the most basic data type. Then the most complex data types supported in Jahia GraphQL API. The following two tables provide a summary of these data types.
Type | Format | Example |
---|---|---|
ID |
^([a-zA-Z0-9]+[-])+ |
126e20ba-2599-49af-a6cd-b575b5417482 |
String |
A brown fox jumps over the lazy dog |
|
Int |
-2³¹ ~ 2³¹-1 |
1, 2, 342, -3, ... |
Float |
3.4E +/- 38 |
123.45 |
Double |
1.7E +/- 308 |
123.087223423554 |
Short |
An integer in between -32,768 ~ 32,767 |
123 |
Long |
-2⁶³ ~ 2⁶³-1 |
8746655929836 |
*BigInteger |
Any integer larger than Long type |
1234567890987654321 |
*BigDecimal |
0.33333333333 |
|
Boolean |
true | false |
|
Date | yyyy-MM-dd'T'hh:mm:ss.SSSXXX | 2016-01-06T18:49:45.308+01:00 |
Jahia GraphQL API provides a set of composite types which contains multiple basic data types.
Although you could define your own composite type, it is easier to reuse built-in composite types to make your definitions simpler. In addition, you could also define your type by extending one of these.
Type |
Format |
Metadata |
{ created: Date, createdBy: String, lastModified: Date, lastModifiedBy: String, lastPublished: Date, lastPublishedBy:String } |
Asset |
{ type: String, size: Long, metadata: Metadata } |
ImageAsset |
{ type: String, size: Long, height: Long, width: Long, metadata: Metadata } |
Category |
{ title: String metadata: Metadata description: String } |
To define your own type, you must define the content model in a CND file first. Usually you can create the definition in the definitions.cnd file under the same directory as the SDL file, for example:
You can deploy the CND file along with the module.
Here is a sample CND for a content model. For example, you want to publish hotel information on your website. In the CND, you define different fields for the content, such as address, city and country.
<jmix = 'http://www.jahia.org/jahia/mix/1.0'> <jnt = 'http://www.jahia.org/jahia/nt/1.0'> [jnt:hotel] > jnt:content, jmix:basicContent, mix:title - city (string) internationalized - country (string) internationalized - address (string) internationalized |
You can learn how to manage your content model in more detail here Content Structures.
This is an example of a GraphQL SDL without any directives. It just defines one type, hotel, with its own properties. However, if you upload this SDL along with your module, it won’t work because the Jahia GraphQL API doesn’t know how to map the type to its content node and node properties.
type hotel { name: String! city: String address: String country: String } |
Therefore, after creating a new type, you need to define the mapping directives.
Add the mapping directive to your types in graphql-extension.sdl file.
Note that @mapping directive supports: node and property arguments for a type and its fields.
type hotel @mapping(node: "jnt:hotel"){ name: String! @mapping(property: "jcr:title") city: String @mapping(property: "city") address: String @mapping(property: "address") country: String @mapping(property: "country") metadata: Metadata rooms: [Room] } type Room @mapping(node: "jnt:room"){ number: Int! @mapping(property: "roomNo") specification: String @mapping(property: "description") available: Boolean @mapping(property: "available") } |
Node mapping is used on a type to specify which JCR node type will be mapped.
type hotel @mapping(node: "jnt:hotel"){ ... } |
Here jnt:hotel is a specific JCR node type. By specifying the node type you enable Jahia to access the right content node.
Property mapping is used in the fields of a type.
type hotel @mapping(node: "jnt:hotel"){ name: String! @mapping(property: "jcr:title") city: String @mapping(property: "city") address: String @mapping(property: "address") country: String @mapping(property: "country") metadata: Metadata rooms: [Room] } |
In this type definition, you could define its fields, such as name, city, address and country. Use the property argument to map the field to the property of a content node. This allows Jahia's GraphQL API to resolve the field correctly
For the custom type Metadata, it maps to the fields in the type which are predefined in the system schema, you don’t need to specify the properties to be mapped here.
For the children of custom type, like Room, it maps to multiple references of the other type. You should get the references along with the main type, when you do the query.
Once you define your own types, you may want to query data for the new types. Jahia GraphQL API provides the Query extension for you to define your own query.
If you want to fetch all data set in a list, you could define an all query.
extend type Query { allHotel: [hotel] } |
Jahia GraphQL API provides queries for a single property.
extend type Query { hotelByCity: [hotel] hotelByCityConnection: hotelConnection hotelByCountry: [hotel] hotelByCountryConnection: hotelConnection } |
The Jahia GraphQL API will generate the default ByID and ByPath queries for your type, which returns a single unique record. You do not need to define the queries explicitly in your SDL.
You can define any By query for any single property in a type, which returns a list of records. Also make sure you use the exact type name as the query prefix, and the exact property name as suffix, for example, hotelByAddress, hotelByName, or hotelByCity.
Descriptions can be added to describe types and their associated fields. Descriptions are useful for communicating information with other developers i.e. consumers of the API.
In your SDL, you can use quotation marks to add descriptions as shown in the following example:
""" hotel content with contact """ type hotel { """unique name of hotel""" name: String! address: String city: String country: String } |
Whenever SDL markup is changed it is validated to make sure that it is syntactically correct, that JCR and GraphQL types are available etc. The SDL Report Tool displays a red indicator to indicate errors discovered during validation.
An SDL syntax error displays under SDL schema to help you find the line containing the error.
#missing end brace type hotel { uuid: ID! name: String! address: String city: String country: String |
If you encounter typo error in your SDL, you will see error message similar to this.
#typo error typo hotel { uuid: ID! name: String! address: String city: String country: String } |
If your SDL has an extension with a nonexisting type, you will see an error message similar to this.
#type ParagraphSDL does not exist extend type ParagraphSDL { content: @mapping(property: "jnt:content") } |
If a type contains an invalid field type in your SDL, you will see an error message similar to this.
#invalid field type type hotel @mapping(node: "jnt:hotel"){ uuid: ID! name: String @mapping(property: "jcr:title") address: String city: String country: String #field type Metadata does not exist metadata: Metadata } |
If a type maps to an invalid node type, you will see an error message similar to this.
#invalid node type mapping type hotel @mapping(node: "jnt:someInvalidNodeType"){ uuid: ID! name: String @mapping(property: "jcr:title") address: String city: String country: String } |
If a type contains a field which maps to invalid property, you will see an error message similar to this.
type hotel @mapping(node: "jnt:hotel"){ uuid: ID! name: String @mapping(property: "jcr:title") address: String city: String country: String #invalid node property mapping startDate: String @mapping(property: "jnt:checkinDate") } |
If you try to add a connection to an entry point which does not return a list you will see an error in the status tool.
extends type Query { #invalid connection hotelsByPropertyConnection: Hotel } |