This module adds a GraphQL schema extension and relevant resolvers to enable CRUD (Create, Read, Update, Delete) operations for Drupal Books. In particular, it allows creating book outlines and attaching book pages to other pages, which is currently unsupported via other methods, like JSON:API.
Features
The module adds 2 kinds of queries: books returns all stored books and book(id) returns a particular book given its node ID.
It also adds 3 mutations: createBook(data), updateBook(id, data), and deleteBook(id).
Additional Requirements
To use the module, you will need to install and enable Book, GraphQL, and GraphQL Book modules. All pre-requisites should be installed automatically if this module is installed using composer.
Note: GraphQL 4.5 dependencies have a minimum stability bug in the requirements, so if it throws an error about specifying minimum stability, you may need to manually install its dependency `typed_data` module first:
composer require 'drupal/typed_data:^1.0@beta'
Post-Installation
Configure a GraphQL server as follows:
- In the Drupal administrator dashboard, go to Configuration -> GraphQL -> Servers
- Click "Create server"
- Give it a name, e.g. "Book endpoint"
- Choose schema to be "Composable Book schema"
- Under Schema configuration > Enabled extensions, tick the "Composable Book extension" (due to a bug in the GraphQL module, sometimes this gets reset on the first server save, so after saving it, click edit and come back to check this is still ticked)
- For endpoint, add "/graphql" unless you already have another GraphQL server running and want to separate them
- Set the remaining settings for your use case (it's also fine to leave them as default) and click "Save"
See the GraphQL module documentation for general usage guidance: README - GraphQL
For details about the GraphQL schema made available by this project, see the files under graphql/ in the project source code.
Supporting documentation
Book link fields exposed by this module are documented in BookOutlineStorageInterface::loadMultiple
Example usage
All Python code is prefixed with:
graphql_endpoint = "https://your_drupal.site/graphql"
from requests import session
with session() as session:
List all books
GraphQL query Python request Example responsequery GetAllBooks {
books {
id,
title,
body {
value,
summary
},
links {
bid
}
}
}
res = session.post(graphql_endpoint, json={
"query": """query GetAllBooks {
books {
id,
title,
body {
value,
summary
},
links {
bid
}
}
}""",
})
res.json()
{
"data": {
"books": [
{
"id": "118",
"title": "Test Book from GraphQL",
"body": {
"value": "",
"summary": null
},
"links": {
"bid": "0"
}
}
]
}
}
Create a new book page
GraphQL query Python request Example responsemutation CreateTestBook {
createBook(data: { title: "My Course Name", body: { value: "<h2>Welcome to my course<h2><br><p>It will be amazing.</p>" } }) {
book {
id,
title,
body {
value,
summary
},
links {
nid
}
}
}
}
res = session.post(graphql_endpoint, json={
"query": """mutation CreateCourseBookPage($data: BookInput!) {
createBook(data: $data) {
errors,
book {
id,
title,
body {
value,
summary,
format
}
}
}
}""",
"variables": {
"data": {
"title": "My Course Name",
"body": {
"value": "<h2>Welcome to my course<h2><br><p>It will be amazing.</p>",
},
}
}
})
new_book_id = res.json()['data']['createBook']['book']['id']
res.json()
{
"data": {
"createBook": {
"book": {
"id": "1",
"title": "My Course Name",
"body": {
"value": "<h2>Welcome to my course<h2><br><p>It will be amazing.</p>",
"summary": null,
"format": "full_html"
},
"links": {
"nid": null
}
}
}
}
}
Make the new course page into a book (creating a new book outline)
GraphQL query Python request Example responsemutation CreateLinkedBook {
createBook(data: {
title: "My Course Name",
links: {
bid: 1,
pid: 1,
p1: 1
}
}) {
errors,
book {
id,
links {
nid,
bid
}
}
}
}
res = session.post(graphql_endpoint, json={
"query": """mutation AddCourseBookOutline($id: ID!, $data: BookInput!) {
updateBook(id: $id, data: $data) {
errors,
book {
id,
links {
nid,
bid
}
}
}
}""",
"variables": {
"id": new_book_id,
"data": {
"title": "My Course Name",
"links": {
"bid": new_book_id
}
}
}
})
res.json()
{
"data": {
"createBook": {
"errors": [],
"book": {
"id": "1",
"links": {
"nid": "1",
"bid": "1"
}
}
}
}
}
Create a child content page
GraphQL query Python request Example responsemutation CreateLinkedBook {
createBook(data: {
title: "Another book page from GraphQL",
body: {
value: "don't read me",
summary: "dangerous",
},
links: {
bid: 1,
pid: 1,
p1: 1,
}
}) {
errors,
book {
id,
links {
nid,
bid
}
}
}
}
def create_content_page(title, summary, body, book_id, parent_id):
res = session.post(graphql_endpoint, json={
"query": """mutation CreateCourseContentPage($data: BookInput!) {
createBook(data: $data) {
errors,
book {
id,
title,
body {
value,
summary,
format
},
links {
bid,
pid
}
}
}
}""",
"variables": {
"data": {
"title": title,
"body": {
"summary": summary,
"value": body,
},
"links": {
"bid": book_id,
"pid": parent_id,
}
}
}
})
print(res.json())
return res.json()['data']['createBook']['book']['id']
{
"data": {
"createBook": {
"errors": [],
"book": {
"id": "2",
"links": {
"nid": "2",
"bid": "1"
}
}
}
}
}
Depends on
Dependencies of the latest stable release
No dependencies recorded for this project.
Required by
Tracked projects that depend on this one
No tracked projects depend on this one yet.
More in the Graphql ecosystem
Most installed first
Activity
Releases
| Version | Type | Core | Release date | |
|---|---|---|---|---|
| 1.0.x-dev | Dev | Jul 11, 2023 |