@@ -7,6 +7,21 @@ const { handleReferences, handleWebhookUpdate } = require(`./utils`)
7
7
const asyncPool = require ( `tiny-async-pool` )
8
8
const bodyParser = require ( `body-parser` )
9
9
10
+ function gracefullyRethrow ( activity , error ) {
11
+ // activity.panicOnBuild was implemented at some point in gatsby@2
12
+ // but plugin can still be used with older version of gatsby core
13
+ // so need to do some checking here
14
+ if ( activity . panicOnBuild ) {
15
+ activity . panicOnBuild ( error )
16
+ }
17
+
18
+ activity . end ( )
19
+
20
+ if ( ! activity . panicOnBuild ) {
21
+ throw error
22
+ }
23
+ }
24
+
10
25
exports . sourceNodes = async (
11
26
{
12
27
actions,
@@ -44,41 +59,45 @@ exports.sourceNodes = async (
44
59
)
45
60
changesActivity . start ( )
46
61
47
- const { secret, action, id, data } = webhookBody
48
- if ( pluginOptions . secret && pluginOptions . secret !== secret ) {
49
- reporter . warn (
50
- `The secret in this request did not match your plugin options secret.`
51
- )
52
- return
53
- }
54
- if ( action === `delete` ) {
55
- actions . deleteNode ( { node : getNode ( createNodeId ( id ) ) } )
56
- reporter . log ( `Deleted node: ${ id } ` )
57
- return
58
- }
62
+ try {
63
+ const { secret, action, id, data } = webhookBody
64
+ if ( pluginOptions . secret && pluginOptions . secret !== secret ) {
65
+ reporter . warn (
66
+ `The secret in this request did not match your plugin options secret.`
67
+ )
68
+ return
69
+ }
70
+ if ( action === `delete` ) {
71
+ actions . deleteNode ( { node : getNode ( createNodeId ( id ) ) } )
72
+ reporter . log ( `Deleted node: ${ id } ` )
73
+ return
74
+ }
59
75
60
- let nodesToUpdate = data
61
- if ( ! Array . isArray ( data ) ) {
62
- nodesToUpdate = [ data ]
63
- }
76
+ let nodesToUpdate = data
77
+ if ( ! Array . isArray ( data ) ) {
78
+ nodesToUpdate = [ data ]
79
+ }
64
80
65
- for ( const nodeToUpdate of nodesToUpdate ) {
66
- await handleWebhookUpdate (
67
- {
68
- nodeToUpdate,
69
- actions,
70
- cache,
71
- createNodeId,
72
- createContentDigest,
73
- getCache,
74
- getNode,
75
- reporter,
76
- store,
77
- } ,
78
- pluginOptions
79
- )
81
+ for ( const nodeToUpdate of nodesToUpdate ) {
82
+ await handleWebhookUpdate (
83
+ {
84
+ nodeToUpdate,
85
+ actions,
86
+ cache,
87
+ createNodeId,
88
+ createContentDigest,
89
+ getCache,
90
+ getNode,
91
+ reporter,
92
+ store,
93
+ } ,
94
+ pluginOptions
95
+ )
96
+ }
97
+ } catch ( e ) {
98
+ gracefullyRethrow ( changesActivity , e )
99
+ return
80
100
}
81
-
82
101
changesActivity . end ( )
83
102
return
84
103
}
@@ -118,74 +137,80 @@ exports.sourceNodes = async (
118
137
119
138
drupalFetchActivity . start ( )
120
139
121
- const data = await axios . get ( `${ baseUrl } /${ apiBase } ` , {
122
- auth : basicAuth ,
123
- headers,
124
- params,
125
- } )
126
- const allData = await Promise . all (
127
- _ . map ( data . data . links , async ( url , type ) => {
128
- if ( disallowedLinkTypes . includes ( type ) ) return
129
- if ( ! url ) return
130
- if ( ! type ) return
131
- const getNext = async ( url , data = [ ] ) => {
132
- if ( typeof url === `object` ) {
133
- // url can be string or object containing href field
134
- url = url . href
135
-
136
- // Apply any filters configured in gatsby-config.js. Filters
137
- // can be any valid JSON API filter query string.
138
- // See https://www.drupal.org/docs/8/modules/jsonapi/filtering
139
- if ( typeof filters === `object` ) {
140
- if ( filters . hasOwnProperty ( type ) ) {
141
- url = url + `?${ filters [ type ] } `
140
+ let allData
141
+ try {
142
+ const data = await axios . get ( `${ baseUrl } /${ apiBase } ` , {
143
+ auth : basicAuth ,
144
+ headers,
145
+ params,
146
+ } )
147
+ allData = await Promise . all (
148
+ _ . map ( data . data . links , async ( url , type ) => {
149
+ if ( disallowedLinkTypes . includes ( type ) ) return
150
+ if ( ! url ) return
151
+ if ( ! type ) return
152
+ const getNext = async ( url , data = [ ] ) => {
153
+ if ( typeof url === `object` ) {
154
+ // url can be string or object containing href field
155
+ url = url . href
156
+
157
+ // Apply any filters configured in gatsby-config.js. Filters
158
+ // can be any valid JSON API filter query string.
159
+ // See https://www.drupal.org/docs/8/modules/jsonapi/filtering
160
+ if ( typeof filters === `object` ) {
161
+ if ( filters . hasOwnProperty ( type ) ) {
162
+ url = url + `?${ filters [ type ] } `
163
+ }
142
164
}
143
165
}
144
- }
145
166
146
- let d
147
- try {
148
- d = await axios . get ( url , {
149
- auth : basicAuth ,
150
- headers,
151
- params,
152
- } )
153
- } catch ( error ) {
154
- if ( error . response && error . response . status == 405 ) {
155
- // The endpoint doesn't support the GET method, so just skip it.
156
- return [ ]
157
- } else {
158
- console . error ( `Failed to fetch ${ url } ` , error . message )
159
- console . log ( error . data )
160
- throw error
167
+ let d
168
+ try {
169
+ d = await axios . get ( url , {
170
+ auth : basicAuth ,
171
+ headers,
172
+ params,
173
+ } )
174
+ } catch ( error ) {
175
+ if ( error . response && error . response . status == 405 ) {
176
+ // The endpoint doesn't support the GET method, so just skip it.
177
+ return [ ]
178
+ } else {
179
+ console . error ( `Failed to fetch ${ url } ` , error . message )
180
+ console . log ( error . data )
181
+ throw error
182
+ }
183
+ }
184
+ data = data . concat ( d . data . data )
185
+ // Add support for includes. Includes allow entity data to be expanded
186
+ // based on relationships. The expanded data is exposed as `included`
187
+ // in the JSON API response.
188
+ // See https://www.drupal.org/docs/8/modules/jsonapi/includes
189
+ if ( d . data . included ) {
190
+ data = data . concat ( d . data . included )
191
+ }
192
+ if ( d . data . links && d . data . links . next ) {
193
+ data = await getNext ( d . data . links . next , data )
161
194
}
162
- }
163
- data = data . concat ( d . data . data )
164
- // Add support for includes. Includes allow entity data to be expanded
165
- // based on relationships. The expanded data is exposed as `included`
166
- // in the JSON API response.
167
- // See https://www.drupal.org/docs/8/modules/jsonapi/includes
168
- if ( d . data . included ) {
169
- data = data . concat ( d . data . included )
170
- }
171
- if ( d . data . links && d . data . links . next ) {
172
- data = await getNext ( d . data . links . next , data )
173
- }
174
195
175
- return data
176
- }
196
+ return data
197
+ }
177
198
178
- const data = await getNext ( url )
199
+ const data = await getNext ( url )
179
200
180
- const result = {
181
- type,
182
- data,
183
- }
201
+ const result = {
202
+ type,
203
+ data,
204
+ }
184
205
185
- // eslint-disable-next-line consistent-return
186
- return result
187
- } )
188
- )
206
+ // eslint-disable-next-line consistent-return
207
+ return result
208
+ } )
209
+ )
210
+ } catch ( e ) {
211
+ gracefullyRethrow ( drupalFetchActivity , e )
212
+ return
213
+ }
189
214
190
215
drupalFetchActivity . end ( )
191
216
@@ -216,17 +241,31 @@ exports.sourceNodes = async (
216
241
217
242
// Download all files (await for each pool to complete to fix concurrency issues)
218
243
const fileNodes = [ ...nodes . values ( ) ] . filter ( isFileNode )
244
+
219
245
if ( fileNodes . length ) {
220
246
const downloadingFilesActivity = reporter . activityTimer (
221
247
`Remote file download`
222
248
)
223
249
downloadingFilesActivity . start ( )
224
- await asyncPool ( concurrentFileRequests , fileNodes , async node => {
225
- await downloadFile (
226
- { node, store, cache, createNode, createNodeId, getCache, reporter } ,
227
- pluginOptions
228
- )
229
- } )
250
+ try {
251
+ await asyncPool ( concurrentFileRequests , fileNodes , async node => {
252
+ await downloadFile (
253
+ {
254
+ node,
255
+ store,
256
+ cache,
257
+ createNode,
258
+ createNodeId,
259
+ getCache,
260
+ reporter,
261
+ } ,
262
+ pluginOptions
263
+ )
264
+ } )
265
+ } catch ( e ) {
266
+ gracefullyRethrow ( downloadingFilesActivity , e )
267
+ return
268
+ }
230
269
downloadingFilesActivity . end ( )
231
270
}
232
271
}
0 commit comments