# GraphQL

The source GraphQL connector will sync content that can be read by a GraphQL endpoint. This requires the ability to write GraphQL queries and use [dot notation pathing](https://github.com/tidwall/gjson#path-syntax) for JSON objects to get and map the data.&#x20;

## Configuration walkthrough

{% embed url="<https://drive.google.com/file/d/1RSPpELBwct17zFGXn-x7BNpaJRf1CoPj/view?usp=share_link>" %}

## Specifics

The GraphQL connector takes a couple GraphQL queries to get the content. Then it takes a set of mappings to put the returned JSON into a Motation file. There are two specific queries that need to be provided.&#x20;

1. A query to get IDs
2. A query to get each content by ID

***Note:*** Queries cannot include `,` instead, use white space to separate attributes in the GraphQL query.&#x20;

### **IDs Query**

This is a query that can return multiple pieces of content often in an array. The query needs to return a couple attributes of the content.&#x20;

1. ID
2. Modification date

In addition, the pathing to these attributes also need to be provided as **Job Options**.&#x20;

First provide the path to the contents using **contentPath**. Then provide the path to the **ID** and **Mod date** by using the **idPath** and **modDatePath** options. Note that idPath and modDatePath are both relative to inside the content. Meaning the full path to the content ID would be akin to contentPath.idPath.&#x20;

#### Example

*Based on Wordpress GraphQL plugin support*

```
idsQuery:query { pages { nodes { id title content modified}} posts { nodes { id title } }}
contentPath:data.pages.nodes
idPath:id
modDatePath:modified
```

### **Content Query**

This is a query that can return a single piece of content by ID. The ID passed into the query will be the same ID gotten from the ID query. In the query, where the ID would go, you use `<|replace_id|>` instead. The connector will then replace that string with the content's ID.

This query must return a few values.&#x20;

1. The ID of the content
2. The definition name for the content
3. Any attribute to be transformed to Motation
4. All necessary data for any picked up Motation Object

The path to the ID and definition name must also be provided as **Job Options**.

Use **idMapping** to path to the ID of the content.&#x20;

Use **definitionNamePath** to path to the name of the definition of the content.&#x20;

Both options are relative to the root of the Content Query.&#x20;

If the job is expected to pick up categories, the content query must include the array of categories for the content and all necessary data for those categories.&#x20;

#### Example

*Based on Wordpress GraphQL plugin support*

```
contentQuery:query { page(id: \"<|replace_id|>\") { id title content __typename }}
idMapping:data.page.id
definitionNamePath:data.page.__typename
```

### Attribute/Field Mapping

Additional attributes to be mapped into Motation fields need the **mapping** job option set. The mapping job option can be broken into two parts.&#x20;

1. The path to the attribute
2. The field type

Both parts need to be provided in the same option separated by a `:`formatted as follows. `path:fieldType`

#### Example

*Based on Wordpress GraphQL plugin support*

```
mapping:data.page.title:String
mapping:data.page.content:WYSIWYG
```

The available field types can be found in the [dev manual's Motation documentation](https://motivlabs.gitbook.io/impulse-dev-manual/motation/content-motation#motation-fields). Use the `String Name` columns values.&#x20;

### Binary Field Type Mapping

When setting a binary field type you must include additional pathing data for the parent path and file name. There are three options to set these values with.&#x20;

* filepath
  * A combination of parent path and file name separated by a `/`&#x20;
  * i.e., `path/to/file/filename`
* parentpath
  * The parent path of the file.&#x20;
  * i.e., `path/to/file`
* filename
  * The file name.&#x20;
  * i.e., `filename`&#x20;

The pathing can be added to a **mapping option** separated by `:`&#x20;

#### Example

*Based on Wordpress GraphQL plugin support*

```
mapping:data.mediaItem.mediaDetails:Binary:data.mediaItem.mediaItemUrl:filepath
OR
mapping:data.mediaItem.mediaDetails:Binary:data.mediaItem.mediaItemPath:parentpath:data.mediaItem.mediaItemName:filename
```

### Array Field Type Mapping

It is assumed that a field type `Array` is a value akin to the following.

```
["one", "two", "three"]
```

### Category/Tag Field Type Mapping

The path to either category or tag field types is expected to be an array.&#x20;

### Endpoint Config

When saving an endpoint for a GitHub repository via REST instead of the UI you must use the following key:value pairs in the payload.&#x20;

* `contentRepo:graphql`
* `contentRepoVersion:latest`

### Unsupported

GraphQL jobs have no dependency support. The best way to work around this is to create multiple jobs for each content type and use a pipeline the jobs together.&#x20;

GraphQL does not support relationships.&#x20;

GraphQL adapter does not support running as a remote adapter apart from Impulse.

## Adapter Properties

| Property        | Purpose                                                            | Required |
| --------------- | ------------------------------------------------------------------ | -------- |
| user            | The basic auth user to send the GraphQL query as.                  | false    |
| password        | The basic auth password for the user to send the GraphQL query as. | false    |
| token           | A token for authentication to send the GraphQL query.              | false    |
| graphqlEndpoint | The full URL path to send GraphQL queries to.                      | true     |

## Job Options

<table><thead><tr><th>Name</th><th width="417">Description</th><th>Data Type</th><th>Required</th><th>Default Value</th><th data-hidden></th></tr></thead><tbody><tr><td>idsQuery</td><td>The query to get IDs of all contents to be picked up.</td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>contentPath</td><td>The path to the contents array relative to the idsQuery root. </td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>idPath</td><td>The path to the ID of the content relative to the contentPath.</td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>modDatePath</td><td>The path to the mod date of the content relative to the contentPath.</td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>contentQuery</td><td>The query to get a single content by ID.</td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>idMapping</td><td>The path to the ID of a content relative to the contentQuery root.</td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>definitionNamePath</td><td>The path to the definintion name of a content relative to the contentQuery root.</td><td>Text</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>mapping</td><td>The path to an attribute of a content relative to the contentQuery root and the Motation field type of the attribute separated by <code>:</code> formatted as follows <code>path:fieldType</code></td><td>Array</td><td>Yes</td><td>No Default Value</td><td></td></tr><tr><td>binaryUrlPath</td><td>The path to the URL of a binary relative to the contentQuery root. The URL value will be used to get the binary directly. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainMapping</td><td>The path to the domain of a content relative to the contentQuery root. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>contentTypeFile</td><td>The path to the attribute to check the content's type. If the attribute is not empty and has any value other than false, the content type will be <strong>file</strong>. Otherwise it will be <strong>content</strong>. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>categoriesPath</td><td>The path to the categories of a content relative to the contentQuery root. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>categoriesIdPath</td><td>The path to the ID of a category relative to the categoriesPath. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>categoriesNamePath</td><td>The path to the name of a category relative to the categoriesPath. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>categoriesOrderPath</td><td>The path to the order of a category relative to the categoriesPath. </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>categoriesChildrenPath</td><td>The path to the children of a category relative to the categoriesPath. It is assumed children have the same structure as the parent and the same categoriesIdPath will be used.  </td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>tagsPath</td><td>The path to the tags of a content relative to the contnetQuery root.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>tagsIdPath</td><td>The path to the ID of a tag relative to the tagsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>tagsNamePath</td><td>The path to the name of a tag relative to the tagsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>tagsDomainIdPath</td><td>The path to the domain ID of a tag relative to the tagsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>tagsDomainNamePath</td><td>The path to the domian name of a tag relative to the tagsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>languagesPath</td><td>The path to the languages of a content relative to the contentQuery root.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>languagesIdPath</td><td>The path to the ID of a language relative to the languagesPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>languagesNamePath</td><td>The path to the name of a language relative to the languagesPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>languagesCodePath</td><td>The path to the code of a language relative to the languagesPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>languagesCountryNamePath</td><td>The path to the country name of a language relative to the languagesPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>languagesCountryCodePath</td><td>The path to the country code of a language relative to the languagesPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsPath</td><td>The path to the domains of a content relative to the contentQuery root.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsIdPath</td><td>The path to the ID of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsNamePath</td><td>The path to the name of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsUriPath</td><td>The path to the URI of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsActivePath</td><td>The path to the active attribute of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsDescriptionPath</td><td>The path to the description of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsSystemPath</td><td>The path to the system attribute of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsDefaultPath</td><td>The path to the default attribute of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsKeywordsPath</td><td>The path to the keywords array of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>domainsAliasesPath</td><td>The path to the aliases array of a domain relative to the domainsPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>foldersPath</td><td>The path to the folders of a content relative to the contentQuery root.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>foldersIdPath</td><td>The path to the ID of a folder relative to the foldersPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>foldersDomainIdPath</td><td>The path to the domain ID of a folder relative to the foldersPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr><tr><td>foldersDomainNamePath</td><td>The path to the domain name of a folder relative to the foldersPath.</td><td>Text</td><td>No</td><td>No Default Value</td><td></td></tr></tbody></table>

### Example Job Options

### Getting Motation Objects

Each Motation object has a set of job options to transform data. The following is an example, using categories and tags, of how to pickup and transform Motation objects.&#x20;

*Based on Wordpress GraphQL plugin support*

```
idsQuery: query {posts {nodes {id title content modified}} posts {nodes {id title}}}
contentQuery: query post {post(id: \"<|replace_id|>\") { __typename id title content modified categories {nodes {id name parent { node { id name}} children {nodes { id name}}}} tags {nodes {id name}} comments { nodes {id content}}}}
contentPath: data.posts.nodes
idPath: id
modDatePath: modified
mapping: data.post.title:String
mapping: data.post.content:WYSIWYG
mapping: data.post.categories:Category
mapping: data.post.tags:Tag
idMapping: data.post.id
definitionNamePath: data.post.__typename
categoriesPath: data.post.categories.nodes
categoriesIdPath: id
categoriesNamePath: name
categoriesChildrenPath: children.nodes
tagsPath: data.post.tags.nodes
tagsIdPath: id
tagsNamePath: name
```

### Getting Binary&#x20;

The following is an example of job options to be set for getting binary files.&#x20;

*Based on Wordpress GraphQL plugin support*

```
idsQuery: query medias { mediaItems { nodes { id modified uri}}}
contentQuery: query media { mediaItem(id: \"<|replace_id|>\") { id modified uri mediaItemUrl date fileSize parent { node { id uri}} __typename mediaDetails { file sizes { file fileSize height mimeType name sourceUrl width} __typename}}}
contentPath: data.mediaItems.nodes
idPath: id
modDatePath: modified
mapping: data.mediaItem.mediaDetails:Binary:data.mediaItem.mediaItemUrl:filepath
idMapping: data.mediaItem.id
definitionNamePath: data.mediaItem.__typename
binaryUrlPath: data.mediaItem.mediaItemUrl
contentTypeFile: data.mediaItem.fileSize
```

## Motation Object Support

| Object       | Supported |
| ------------ | --------- |
| Category     | Yes       |
| Definition   | Yes       |
| Domain       | Yes       |
| Folder       | Yes       |
| Language     | Yes       |
| Relationship | No        |
| Tag          | Yes       |

## Content Mapper

Below are details on how to find the appropriate values to use in the content mapper.

* `origin.uniqueId`
  * Value obtained from **definitionNamePath** option.&#x20;
* `fields.origin.uniqueId`
  * Path used for **mapping** option.&#x20;

## Troubleshooting

*
