@amazeelabs/silverback-gatsby 3.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/drupal/silverback_gatsby/.prettierignore +1 -0
- package/drupal/silverback_gatsby/CHANGELOG.md +1216 -0
- package/drupal/silverback_gatsby/README.md +297 -0
- package/drupal/silverback_gatsby/composer.json +15 -0
- package/drupal/silverback_gatsby/directives.gql +63 -0
- package/drupal/silverback_gatsby/directives.graphql +62 -0
- package/drupal/silverback_gatsby/drush.services.yml +9 -0
- package/drupal/silverback_gatsby/graphql/entity.directive.graphqls +2 -0
- package/drupal/silverback_gatsby/graphql/menu.directive.graphqls +17 -0
- package/drupal/silverback_gatsby/graphql/silverback_gatsby.base.graphqls +25 -0
- package/drupal/silverback_gatsby/graphql/silverback_gatsby.extension.graphqls +10 -0
- package/drupal/silverback_gatsby/graphql/stringTranslation.directive.graphqls +4 -0
- package/drupal/silverback_gatsby/graphql/translatableString.directive.graphqls +2 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/directives.gql +6 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/graphql/.graphqlrc.json +4 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/graphql/silverback_gatsby_example.graphqls +39 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/silverback_gatsby_example.info.yml +7 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/silverback_gatsby_example.module +16 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/src/Directives.php +24 -0
- package/drupal/silverback_gatsby/silverback_gatsby.info.yml +8 -0
- package/drupal/silverback_gatsby/silverback_gatsby.install +180 -0
- package/drupal/silverback_gatsby/silverback_gatsby.links.task.yml +6 -0
- package/drupal/silverback_gatsby/silverback_gatsby.module +119 -0
- package/drupal/silverback_gatsby/silverback_gatsby.permissions.yml +8 -0
- package/drupal/silverback_gatsby/silverback_gatsby.post_update.php +15 -0
- package/drupal/silverback_gatsby/silverback_gatsby.routing.yml +28 -0
- package/drupal/silverback_gatsby/silverback_gatsby.services.yml +50 -0
- package/drupal/silverback_gatsby/src/Annotation/GatsbyFeed.php +41 -0
- package/drupal/silverback_gatsby/src/Commands/SilverbackGatsbyCommands.php +102 -0
- package/drupal/silverback_gatsby/src/Controller/BuildController.php +45 -0
- package/drupal/silverback_gatsby/src/Controller/PublisherController.php +34 -0
- package/drupal/silverback_gatsby/src/Directives.php +51 -0
- package/drupal/silverback_gatsby/src/GatsbyBuildTrigger.php +230 -0
- package/drupal/silverback_gatsby/src/GatsbyBuildTriggerInterface.php +52 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdate.php +38 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateHandler.php +181 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTracker.php +98 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTrackerInterface.php +59 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTrigger.php +69 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTriggerInterface.php +22 -0
- package/drupal/silverback_gatsby/src/GraphQL/Build.php +235 -0
- package/drupal/silverback_gatsby/src/GraphQL/ComposableSchema.php +73 -0
- package/drupal/silverback_gatsby/src/LocaleStorageDecorator.php +181 -0
- package/drupal/silverback_gatsby/src/MenuTreeStorageDecorator.php +139 -0
- package/drupal/silverback_gatsby/src/Plugin/FeedBase.php +121 -0
- package/drupal/silverback_gatsby/src/Plugin/FeedInterface.php +132 -0
- package/drupal/silverback_gatsby/src/Plugin/FeedPluginManager.php +39 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/EntityFeed.php +252 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/MenuFeed.php +292 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/StringTranslationFeed.php +171 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/TranslatableStringFeed.php +128 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/CurrentUserEntity.php +43 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/EntityQueryBase.php +40 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FetchEntity.php +371 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FetchString.php +64 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FetchTranslatableString.php +74 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FocalPoint.php +47 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/GatsbyBuildId.php +36 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/GatsbyExtractId.php +28 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/GatsbyExtractLangcode.php +28 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/ImageProps.php +149 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/ListEntities.php +88 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/ListStrings.php +87 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/StringId.php +37 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/StringTranslations.php +94 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/EntityFetch.php +51 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/EntityTranslationsWithDefault.php +30 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/FocalPoint.php +27 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/ImageProps.php +27 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/MenuLangcode.php +27 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/MenuTranslations.php +36 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/SilverbackGatsbyEntityId.php +39 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/SchemaExtension/SilverbackGatsbySchemaExtension.php +384 -0
- package/drupal/silverback_gatsby/src/SilverbackGatsbyServiceProvider.php +43 -0
- package/drupal/silverback_gatsby/src/SilverbackGatsbySessionConfiguration.php +30 -0
- package/drupal/silverback_gatsby/src/SilverbackReverseProxyMiddleware.php +49 -0
- package/drupal/silverback_gatsby/tests/queries/create-page-fields.gql +12 -0
- package/drupal/silverback_gatsby/tests/queries/current-user.gql +6 -0
- package/drupal/silverback_gatsby/tests/queries/feed_info.gql +12 -0
- package/drupal/silverback_gatsby/tests/queries/load-entity.gql +5 -0
- package/drupal/silverback_gatsby/tests/queries/menus.gql +31 -0
- package/drupal/silverback_gatsby/tests/queries/multilingual-menus.gql +11 -0
- package/drupal/silverback_gatsby/tests/queries/revisionable-translatable.gql +15 -0
- package/drupal/silverback_gatsby/tests/queries/revisionable.gql +8 -0
- package/drupal/silverback_gatsby/tests/queries/translatable.gql +14 -0
- package/drupal/silverback_gatsby/tests/queries/untranslatable.gql +10 -0
- package/drupal/silverback_gatsby/tests/schema/.graphqlrc.json +4 -0
- package/drupal/silverback_gatsby/tests/schema/translatable-strings.graphql +7 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/CurrentUserTest.php +37 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/EntityFeedTest.php +490 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/EntityFeedTestBase.php +178 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyBuildTriggerTest.php +155 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyFeedInfoTest.php +319 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyUpdateHandlerTest.php +131 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyUpdateTrackerTest.php +196 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyUpdateTriggerTest.php +177 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/MenuFeedTest.php +192 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/TranslatableStringFeedTest.php +210 -0
- package/drupal/silverback_gatsby/tests/src/Traits/NotificationCheckTrait.php +43 -0
- package/package.json +15 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# Silverback Gatsby
|
|
2
|
+
|
|
3
|
+
A Drupal module that provides integration endpoints for the
|
|
4
|
+
[`@amazeelabs/gatsby-source-silverback`][gatsby-source-silverback] Gatsby
|
|
5
|
+
plugin. Allows writing custom GraphQL schema definitions based on GraphQL V4 and
|
|
6
|
+
automatically send incremental updates to Gatsby.
|
|
7
|
+
|
|
8
|
+
[gatsby-source-silverback]:
|
|
9
|
+
https://www.npmjs.com/package/@amazeelabs/gatsby-source-silverback
|
|
10
|
+
|
|
11
|
+
## BREAKING CHANGES
|
|
12
|
+
|
|
13
|
+
In version 2, a couple of breaking changes have been introduced due to the new
|
|
14
|
+
dependency on the `graphql_directives` module.
|
|
15
|
+
|
|
16
|
+
- `@resolveEntityReference` and `@resolveEntityReferenceRevisions` do not
|
|
17
|
+
support the `single` parameter any more. They can be chained with `@seek`
|
|
18
|
+
instead.
|
|
19
|
+
- Gutenberg directives moved to the `silverback_gutenberg` module and changed in
|
|
20
|
+
naming and parameters. Refer to the generated directives for more information.
|
|
21
|
+
- New default value handling requires either nullable custom type invocations,
|
|
22
|
+
or `@default` directives on them. Refer to the `graphql_directives` module for
|
|
23
|
+
more information.
|
|
24
|
+
|
|
25
|
+
## Getting started
|
|
26
|
+
|
|
27
|
+
First, simply install and enable the module.
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
composer require amazeelabs/silverback_gatsby
|
|
31
|
+
drush en -y silverback_gatsby
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Create a GraphQL folder at the root of your project. This will contain all the
|
|
35
|
+
schema definitions. To improve IDE support, you can export all the schema
|
|
36
|
+
definitions in a single file:
|
|
37
|
+
|
|
38
|
+
```shell
|
|
39
|
+
drush graphql:directives > graphql/directives.graphqls
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
It is advised to ignore this file in version control and rather re-create it
|
|
43
|
+
when needed.
|
|
44
|
+
|
|
45
|
+
Now you can start to create the project schema defintion and fill in resolvers
|
|
46
|
+
by using the directives provided.
|
|
47
|
+
|
|
48
|
+
```graphql
|
|
49
|
+
schema {
|
|
50
|
+
query: Query
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type Query {
|
|
54
|
+
page(id: String!): Page @loadEntity(type: "node", id: "$id")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type Page @entity(type: "node", bundle: "page") {
|
|
58
|
+
path: String! @resolveEntityPath
|
|
59
|
+
title: String! @resolveEntityLabel
|
|
60
|
+
body: String @resolveProperty(path: "body.value")
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Now create a new GraphQL server configuration, use the `Directable` schema
|
|
65
|
+
plugin and make sure to enable the "Silverback Gatsby" extension. The _Explorer_
|
|
66
|
+
or _Voyager_ screens should show root level fields for loading and querying our
|
|
67
|
+
type (`loadPage`, `queryPages`) that you should be able to test now.
|
|
68
|
+
|
|
69
|
+
## Automatic creation of Gatsby pages
|
|
70
|
+
|
|
71
|
+
Available using `@isPath` and `@isTemplate` field directives. See
|
|
72
|
+
[`@amazeelabs/gatsby-source-silverback`](../../../npm/@amazeelabs/gatsby-source-silverback)
|
|
73
|
+
plugin README for details.
|
|
74
|
+
|
|
75
|
+
## Automatic resolvers
|
|
76
|
+
|
|
77
|
+
There are directives which create GraphQL resolvers automatically.
|
|
78
|
+
|
|
79
|
+
### @resolveProperty
|
|
80
|
+
|
|
81
|
+
This field directive is a shortcut for `property_path` data producer.
|
|
82
|
+
|
|
83
|
+
For example, this schema
|
|
84
|
+
|
|
85
|
+
```graphql
|
|
86
|
+
type Page @entity(type: "node", bundle: "page") {
|
|
87
|
+
body: String @resolveProperty(path: "field_body.0.processed")
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Will create the following resolver for `Page.body` field
|
|
92
|
+
|
|
93
|
+
```php
|
|
94
|
+
$builder->produce('property_path', [
|
|
95
|
+
'path' => $builder->fromValue('field_body.0.processed'),
|
|
96
|
+
'value' => $builder->fromParent(),
|
|
97
|
+
'type' => $builder->fromValue('entity:node:page'),
|
|
98
|
+
])
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### @resolveEntityPath
|
|
102
|
+
|
|
103
|
+
Resolves the relative path to an entity. A shortcut for `entity_url`+`url_path`
|
|
104
|
+
data producers.
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
|
|
108
|
+
```graphql
|
|
109
|
+
type Page @entity(type: "node", bundle: "page") {
|
|
110
|
+
path: String! @resolveEntityPath
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### @resolveEntityReference
|
|
115
|
+
|
|
116
|
+
Resolves the references entities. A shortcut for `entity_reference` data
|
|
117
|
+
producer.
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
|
|
121
|
+
<!-- prettier-ignore-start -->
|
|
122
|
+
```graphql
|
|
123
|
+
type Page @entity(type: "node", bundle: "page") {
|
|
124
|
+
relatedArticles: [Article]! @resolveEntityReference(field: "field_related_articles", single: false)
|
|
125
|
+
parentPage: Page @resolveEntityReference(field: "field_related_articles", single: true)
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
<!-- prettier-ignore-end -->
|
|
129
|
+
|
|
130
|
+
### @resolveEntityReferenceRevisions
|
|
131
|
+
|
|
132
|
+
Resolves the entity reference revisions fields, e.g. Paragraphs. A shortcut for
|
|
133
|
+
`entity_reference_revisions` data producer.
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
|
|
137
|
+
<!-- prettier-ignore-start -->
|
|
138
|
+
```graphql
|
|
139
|
+
type Page @entity(type: "node", bundle: "page") {
|
|
140
|
+
paragraphs: [PageParagraphs!]! @resolveEntityReferenceRevisions(field: "field_paragraphs", single: false)
|
|
141
|
+
singleParagraph: ParagraphText @resolveEntityReferenceRevisions(field: "field_single_paragraph", single: true)
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
<!-- prettier-ignore-end -->
|
|
145
|
+
|
|
146
|
+
## Menus
|
|
147
|
+
|
|
148
|
+
To expose Drupal menus to Gatsby, one can use the `@menu` directive.
|
|
149
|
+
|
|
150
|
+
```graphql
|
|
151
|
+
type MainMenu @menu(menu_id: "main") {
|
|
152
|
+
items: [MenuItem!]! @resolveMenuItems
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
type MenuItem {
|
|
156
|
+
id: String! @resolveMenuItemId
|
|
157
|
+
parent: String! @resolveMenuItemId
|
|
158
|
+
label: String! @resolveMenuItemLabel
|
|
159
|
+
url: String! @resolveMenuItemUrl
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
GraphQL does not allow recursive fragments, so something like this would not be
|
|
164
|
+
possible:
|
|
165
|
+
|
|
166
|
+
```graphql
|
|
167
|
+
query Menu {
|
|
168
|
+
drupalMainMenu {
|
|
169
|
+
items {
|
|
170
|
+
...MenuItem
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
fragment MenuItem on MenuItem {
|
|
175
|
+
label
|
|
176
|
+
url
|
|
177
|
+
children {
|
|
178
|
+
# Fragment recursion, not allowed in GraphQL!
|
|
179
|
+
...MenuItem
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
That's why the menu tree is automatically flattened, and `id` and `parent`
|
|
185
|
+
properties are added to each item, so the tree can easily be reconstructed in
|
|
186
|
+
the consuming application.
|
|
187
|
+
|
|
188
|
+
```graphql
|
|
189
|
+
query MainMenu {
|
|
190
|
+
drupalMainMenu(langcode: { eq: "en" }) {
|
|
191
|
+
items {
|
|
192
|
+
id
|
|
193
|
+
parent
|
|
194
|
+
label
|
|
195
|
+
url
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The `@menu` directive also takes an optional `max_level` argument. It can be
|
|
202
|
+
used to restrict the number of levels a type will include, which in turn can
|
|
203
|
+
optimize caching and Gatsby build times. In many cases, the main page layout
|
|
204
|
+
only displays the first level of menu items. When a new page is created and
|
|
205
|
+
attached to the third level, Gatsby will still re-render all pages, because the
|
|
206
|
+
menu that is used in the header changed. By separating this into two levels, we
|
|
207
|
+
can make sure the outer layout really only changes when menu levels are changed
|
|
208
|
+
that are displayed.
|
|
209
|
+
|
|
210
|
+
```graphql
|
|
211
|
+
type MainMenu @menu(menu_id: "main") {...}
|
|
212
|
+
# Will only include the first level and trigger updates when a first level item
|
|
213
|
+
# changes.
|
|
214
|
+
type LayoutMainMenu @menu(menu_id: "main", max_level: 1) {...}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Menu negotiation
|
|
218
|
+
|
|
219
|
+
In some cases, the same GraphQL field might have to return different menus,
|
|
220
|
+
based on the current context. A prominent use case would be a multi-site setup
|
|
221
|
+
where different menus should be displayed based on the current account Gatsby is
|
|
222
|
+
using to fetch data with.
|
|
223
|
+
|
|
224
|
+
In this case, multiple menu id's can be passed to the `@menu` directive, and the
|
|
225
|
+
resolver will pick **the first one** that is accessible to the user account.
|
|
226
|
+
|
|
227
|
+
```graphql
|
|
228
|
+
type MainMenu
|
|
229
|
+
@menu(menu_ids: ["site_a_main", "site_b_main"], item_type: "MenuItem")
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
It checks access for the `view label` operation on the `Menu` entity, which is
|
|
233
|
+
allowed for everybody by default. The consuming project has to implement other
|
|
234
|
+
mechanisms to restrict access therefore control which menus are used for which
|
|
235
|
+
site.
|
|
236
|
+
|
|
237
|
+
## Configuring update notifications
|
|
238
|
+
|
|
239
|
+
The last thing to do is to tell Gatsby whenever something noteworthy changes. By
|
|
240
|
+
using the `@entity` directive in our schema, we already told Drupal to keep
|
|
241
|
+
track of all changes related to the entity types we care about. All there is
|
|
242
|
+
missing is a Gatsby webhook url to trigger a refresh. We provide this via an
|
|
243
|
+
environment variable that is named after our configured GraphQL server.
|
|
244
|
+
|
|
245
|
+
```dotenv
|
|
246
|
+
GATSBY_BUILD_HOOK_[uppercased-server-id]=https://...
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
So if the server was called `My Server` and the automatically generated machine
|
|
250
|
+
name is `my_server`, then the environment variable would look like this:
|
|
251
|
+
|
|
252
|
+
```dotenv
|
|
253
|
+
GATSBY_BUILD_HOOK_MY_SERVER=https://...
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The value is a semicolon-separated list of urls that will be called in case of
|
|
257
|
+
an update. This can be `http://localhost:8000/__refresh`, for local testing a
|
|
258
|
+
Gatsby environment with `ENABLE_GATSBY_REFRESH_ENDPOINT=true`, or the build and
|
|
259
|
+
preview webhooks provided by Gatsby Cloud.
|
|
260
|
+
|
|
261
|
+
The Gatsby site has to contain the
|
|
262
|
+
[`@amazeelabs/gatsby-source-silverback`][gatsby-source-silverback] plugin for
|
|
263
|
+
this to work.
|
|
264
|
+
|
|
265
|
+
## Access control
|
|
266
|
+
|
|
267
|
+
By default, [`@amazeelabs/gatsby-source-silverback`][gatsby-source-silverback]
|
|
268
|
+
behaves like an anonymous user. To change that, simply create a user account
|
|
269
|
+
with the required permissions and pass the credentials to the `auth_user` and
|
|
270
|
+
`auth_pass` configuration options of the plugin.
|
|
271
|
+
|
|
272
|
+
A very common use case would be to create a "preview" user that bypasses content
|
|
273
|
+
access control and use it for the "Preview" environment on Gatsby cloud, so
|
|
274
|
+
unpublished content can be previewed. Another sensible case would be to create a
|
|
275
|
+
"build" user that has access to published content and block anonymous access to
|
|
276
|
+
Drupal entirely.
|
|
277
|
+
|
|
278
|
+
## Trigger a build
|
|
279
|
+
|
|
280
|
+
There are multiple ways to trigger a Gatsby build:
|
|
281
|
+
|
|
282
|
+
- on entity save
|
|
283
|
+
- via the Drupal UI or Drush.
|
|
284
|
+
|
|
285
|
+
### On entity save
|
|
286
|
+
|
|
287
|
+
On the _Build_ tab of the schema configuration, check the _Trigger a build on
|
|
288
|
+
entity save_ checkbox.
|
|
289
|
+
|
|
290
|
+
### Drupal UI
|
|
291
|
+
|
|
292
|
+
On the same _Build_ tab, click the _Gatsby Build_ button.
|
|
293
|
+
|
|
294
|
+
### Drush
|
|
295
|
+
|
|
296
|
+
This command can be configured in the system cron.
|
|
297
|
+
`drush silverback-gatsby:build [server_id]`
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "amazeelabs/silverback_gatsby",
|
|
3
|
+
"type": "drupal-module",
|
|
4
|
+
"version": "dev-main",
|
|
5
|
+
"description": "Bridge module between Gatsby and Drupal.",
|
|
6
|
+
"homepage": "https://silverback.netlify.app",
|
|
7
|
+
"license": "GPL-2.0+",
|
|
8
|
+
"extra": {
|
|
9
|
+
"drush": {
|
|
10
|
+
"services": {
|
|
11
|
+
"drush.services.yml": "^10"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
directive @sourceFrom(fn: String) on OBJECT
|
|
2
|
+
directive @resolveBy(fn: String) repeatable on FIELD_DEFINITION
|
|
3
|
+
directive @gatsbyNodes(type: String) on FIELD_DEFINITION
|
|
4
|
+
directive @gatsbyNode(type: String, id: String) on FIELD_DEFINITION
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Associate a type with a Drupal entity type.
|
|
8
|
+
"""
|
|
9
|
+
directive @entity(type: String!, bundle: String, access: Boolean) on OBJECT
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
Directive for the "MenuFeed" plugin.
|
|
13
|
+
menu_id: The internal menu id.
|
|
14
|
+
menu_ids: Internal menu id's. The first one the current user has access to will be picked.
|
|
15
|
+
item_type: GraphQL type for menu items.
|
|
16
|
+
**DEPRECATED**: Explicitly define Menu item types with `resolveMenu*`
|
|
17
|
+
directives instead.
|
|
18
|
+
max_level: The maximum level to be fetched.
|
|
19
|
+
This can be used to optimizing caching. Most of the time only one or two
|
|
20
|
+
levels of menus are immediately visible on the page. By declaring multiple
|
|
21
|
+
types, we can generate different cache buckets, so a new menu item on a low
|
|
22
|
+
level does not require a full rebuild of every page.
|
|
23
|
+
"""
|
|
24
|
+
directive @menu(
|
|
25
|
+
menu_id: String
|
|
26
|
+
menu_ids: [String!]
|
|
27
|
+
item_type: String
|
|
28
|
+
max_level: Int
|
|
29
|
+
) on OBJECT
|
|
30
|
+
|
|
31
|
+
directive @isPath on FIELD_DEFINITION
|
|
32
|
+
directive @isTemplate on FIELD_DEFINITION
|
|
33
|
+
directive @stringTranslation(contextPrefix: String) on OBJECT
|
|
34
|
+
directive @translatableString(contextPrefix: String) on OBJECT
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
Fetch an entity or entity revision based on id, rid or route
|
|
38
|
+
|
|
39
|
+
implementation(drupal): \Drupal\silverback_gatsby\Directives::fetchEntity
|
|
40
|
+
"""
|
|
41
|
+
directive @fetchEntity(
|
|
42
|
+
type: String
|
|
43
|
+
id: String
|
|
44
|
+
rid: String
|
|
45
|
+
language: String
|
|
46
|
+
operation: String
|
|
47
|
+
loadLatestRevision: Boolean
|
|
48
|
+
) repeatable on FIELD_DEFINITION | SCALAR | UNION | ENUM | INTERFACE | OBJECT
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
Retrieve the properties of an image.
|
|
52
|
+
|
|
53
|
+
implementation(drupal): \Drupal\silverback_gatsby\Directives::imageProps
|
|
54
|
+
implementation(gatsby): ./image.js#imageProps
|
|
55
|
+
"""
|
|
56
|
+
directive @imageProps repeatable on FIELD_DEFINITION | SCALAR | UNION | ENUM | INTERFACE | OBJECT
|
|
57
|
+
|
|
58
|
+
"""
|
|
59
|
+
Retrieve focal point coordinates for an image source.
|
|
60
|
+
|
|
61
|
+
implementation(drupal): \Drupal\silverback_gatsby\Directives::focalPoint
|
|
62
|
+
"""
|
|
63
|
+
directive @focalPoint repeatable on FIELD_DEFINITION | SCALAR | UNION | ENUM | INTERFACE | OBJECT
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Associate a type with a Drupal entity type.
|
|
3
|
+
"""
|
|
4
|
+
directive @entity(type: String!, bundle: String, access: Boolean) on OBJECT
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Directive for the "MenuFeed" plugin.
|
|
8
|
+
menu_id: The internal menu id.
|
|
9
|
+
menu_ids: Internal menu id's. The first one the current user has access to will be picked.
|
|
10
|
+
item_type: GraphQL type for menu items.
|
|
11
|
+
**DEPRECATED**: Explicitly define Menu item types with `resolveMenu*`
|
|
12
|
+
directives instead.
|
|
13
|
+
max_level: The maximum level to be fetched.
|
|
14
|
+
This can be used to optimizing caching. Most of the time only one or two
|
|
15
|
+
levels of menus are immediately visible on the page. By declaring multiple
|
|
16
|
+
types, we can generate different cache buckets, so a new menu item on a low
|
|
17
|
+
level does not require a full rebuild of every page.
|
|
18
|
+
"""
|
|
19
|
+
directive @menu(
|
|
20
|
+
menu_id: String
|
|
21
|
+
menu_ids: [String!]
|
|
22
|
+
item_type: String
|
|
23
|
+
max_level: Int
|
|
24
|
+
) on OBJECT
|
|
25
|
+
|
|
26
|
+
directive @isPath on FIELD_DEFINITION
|
|
27
|
+
|
|
28
|
+
directive @isTemplate on FIELD_DEFINITION
|
|
29
|
+
|
|
30
|
+
directive @stringTranslation(contextPrefix: String) on OBJECT
|
|
31
|
+
|
|
32
|
+
directive @translatableString(contextPrefix: String) on OBJECT
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
Fetch an entity or entity revision based on id, rid or route
|
|
36
|
+
|
|
37
|
+
Provided by the "silverback_gatsby" module.
|
|
38
|
+
Implemented in "Drupal\silverback_gatsby\Plugin\GraphQL\Directive\EntityFetch".
|
|
39
|
+
"""
|
|
40
|
+
directive @fetchEntity(
|
|
41
|
+
type: String
|
|
42
|
+
id: String
|
|
43
|
+
rid: String
|
|
44
|
+
language: String
|
|
45
|
+
operation: String
|
|
46
|
+
loadLatestRevision: Boolean
|
|
47
|
+
) repeatable on FIELD_DEFINITION | SCALAR | UNION | ENUM | INTERFACE | OBJECT
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
Retrieve the properties of an image.
|
|
51
|
+
|
|
52
|
+
Provided by the "silverback_gatsby" module.
|
|
53
|
+
Implemented in "Drupal\silverback_gatsby\Plugin\GraphQL\Directive\ImageProps".
|
|
54
|
+
"""
|
|
55
|
+
directive @imageProps repeatable on FIELD_DEFINITION | SCALAR | UNION | ENUM | INTERFACE | OBJECT
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
Retrieve focal point coordinates for an image source.
|
|
59
|
+
Provided by the "silverback_gatsby" module.
|
|
60
|
+
Implemented in "Drupal\silverback_gatsby\Plugin\GraphQL\Directive\FocalPoint".
|
|
61
|
+
"""
|
|
62
|
+
directive @focalPoint repeatable on FIELD_DEFINITION | SCALAR | UNION | ENUM | INTERFACE | OBJECT
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Directive for the "MenuFeed" plugin.
|
|
2
|
+
# menu_id: The internal menu id.
|
|
3
|
+
# menu_ids: Internal menu id's. The first one the current user has access to will be picked.
|
|
4
|
+
# item_type: GraphQL type for menu items.
|
|
5
|
+
# **DEPRECATED**: Explicitly define Menu item types with `resolveMenu*`
|
|
6
|
+
# directives instead.
|
|
7
|
+
# max_level: The maximum level to be fetched.
|
|
8
|
+
# This can be used to optimizing caching. Most of the time only one or two
|
|
9
|
+
# levels of menus are immediately visible on the page. By declaring multiple
|
|
10
|
+
# types, we can generate different cache buckets, so a new menu item on a low
|
|
11
|
+
# level does not require a full rebuild of every page.
|
|
12
|
+
directive @menu(
|
|
13
|
+
menu_id: String
|
|
14
|
+
menu_ids: [String!]
|
|
15
|
+
item_type: String
|
|
16
|
+
max_level: Int
|
|
17
|
+
) on OBJECT
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type _Feed {
|
|
2
|
+
typeName: String!
|
|
3
|
+
translatable: Boolean!
|
|
4
|
+
singleFieldName: String!
|
|
5
|
+
listFieldName: String!
|
|
6
|
+
changes(lastBuild: Int, currentBuild: Int): [String!]!
|
|
7
|
+
pathFieldName: String
|
|
8
|
+
templateFieldName: String
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
################################################################################
|
|
12
|
+
# Directives for the automatic Gatsby pages creation.
|
|
13
|
+
################################################################################
|
|
14
|
+
|
|
15
|
+
directive @isPath on FIELD_DEFINITION
|
|
16
|
+
"""
|
|
17
|
+
DEPRECATED, use @isPath
|
|
18
|
+
"""
|
|
19
|
+
directive @path on FIELD_DEFINITION
|
|
20
|
+
|
|
21
|
+
directive @isTemplate on FIELD_DEFINITION
|
|
22
|
+
"""
|
|
23
|
+
DEPRECATED, use @isTemplate
|
|
24
|
+
"""
|
|
25
|
+
directive @template on FIELD_DEFINITION
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
schema {
|
|
2
|
+
query: Query
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
type Query
|
|
6
|
+
|
|
7
|
+
union WithPath = Page | Post
|
|
8
|
+
|
|
9
|
+
type Page @entity(type: "node", bundle: "page") {
|
|
10
|
+
path: String! @isPath @entityPath
|
|
11
|
+
title: String! @property(path: "title.value")
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type Post @entity(type: "node", bundle: "blog") {
|
|
15
|
+
path: String! @isPath @entityPath
|
|
16
|
+
title: String! @property(path: "title.value")
|
|
17
|
+
template: String @isTemplate @layout
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type MenuItem {
|
|
21
|
+
id: String! @menuItemId
|
|
22
|
+
parent: String @menuItemParentId
|
|
23
|
+
label: String! @menuItemLabel
|
|
24
|
+
url: String! @menuItemUrl
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
All menu items, for the sitemap or being post-loaded.
|
|
29
|
+
"""
|
|
30
|
+
type MainMenu @menu(menu_ids: ["access_denied", "main"]) {
|
|
31
|
+
items: [MenuItem]! @menuItems
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
Menu items up to level 2, to be rendered directly into the page layout.
|
|
36
|
+
"""
|
|
37
|
+
type VisibleMainMenu @menu(menu_ids: ["access_denied", "main"], max_level: 2) {
|
|
38
|
+
items: [MenuItem]! @menuItems
|
|
39
|
+
}
|
package/drupal/silverback_gatsby/modules/silverback_gatsby_example/silverback_gatsby_example.module
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Drupal\Core\Access\AccessResult;
|
|
4
|
+
use Drupal\Core\Entity\EntityInterface;
|
|
5
|
+
use Drupal\Core\Session\AccountInterface;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Implements hook_entity_access().
|
|
9
|
+
*/
|
|
10
|
+
function silverback_gatsby_example_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
|
|
11
|
+
// If the entity is labeled "Access denied", we block access. This way we
|
|
12
|
+
// simulate unpredictable access scenarios in tests.
|
|
13
|
+
if ($entity->label() === 'Access denied') {
|
|
14
|
+
return AccessResult::forbidden();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby_example;
|
|
4
|
+
|
|
5
|
+
use Drupal\graphql_directives\Api;
|
|
6
|
+
use Drupal\node\NodeInterface;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Directive implementations for the example module.
|
|
10
|
+
*/
|
|
11
|
+
class Directives {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the layout/template value for a node.
|
|
15
|
+
*/
|
|
16
|
+
public static function layout(Api $api): ?string {
|
|
17
|
+
$node = $api->parent;
|
|
18
|
+
if (!$node instanceof NodeInterface) {
|
|
19
|
+
return NULL;
|
|
20
|
+
}
|
|
21
|
+
return $node->get('promote')->value ? 'blog-promoted' : NULL;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|