-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Expand file tree
/
Copy pathbase-graphql.js
More file actions
107 lines (101 loc) · 3.86 KB
/
Copy pathbase-graphql.js
File metadata and controls
107 lines (101 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* @module
*/
import { print } from 'graphql/language/printer.js'
import BaseService from './base.js'
import { InvalidResponse, ShieldsRuntimeError } from './errors.js'
import { parseJson } from './json.js'
function defaultTransformErrors(errors) {
return new InvalidResponse({ prettyMessage: errors[0].message })
}
/**
* Services which query a GraphQL endpoint should extend BaseGraphqlService
*
* @abstract
*/
class BaseGraphqlService extends BaseService {
/**
* Parse data from JSON endpoint
*
* @param {string} buffer JSON response from upstream API
* @returns {object} Parsed response
*/
_parseJson(buffer) {
return parseJson(buffer)
}
static headers = { Accept: 'application/json' }
/**
* Request data from an upstream GraphQL API,
* parse it and validate against a schema
*
* @param {object} attrs Refer to individual attrs
* @param {Joi} attrs.schema Joi schema to validate the response against
* @param {string} attrs.url URL to request
* @param {object} attrs.query Parsed GraphQL object
* representing the query clause of GraphQL POST body
* e.g. gql`{ query { ... } }`
* @param {object} attrs.variables Variables clause of GraphQL POST body
* @param {object} [attrs.options={}] Options to pass to Ky. See
* [documentation](https://github.com/sindresorhus/ky#options)
* @param {object} [attrs.httpErrorMessages={}] Key-value map of HTTP status codes
* and custom error messages e.g: `{ 404: 'package not found' }`.
* This can be used to extend or override the
* [default](https://github.com/badges/shields/blob/master/core/base-service/check-error-response.js#L5)
* @param {object} [attrs.systemErrors={}] Key-value map of underlying network error codes
* and an object of params to pass when we construct an Inaccessible exception object
* e.g: `{ ECONNRESET: { prettyMessage: 'connection reset' } }`.
* Codes are read from the error's cause chain. See
* {@link module:core/base-service/errors~RuntimeErrorProps} for allowed values
* @param {number[]} [attrs.logErrors=[429]] An array of http error codes
* that will be logged (to sentry, if configured).
* @param {Function} [attrs.transformJson=data => data] Function which takes the raw json and transforms it before
* further processing. In case of multiple query in a single graphql call and few of them
* throw error, partial data might be used ignoring the error.
* @param {Function} [attrs.transformErrors=defaultTransformErrors]
* Function which takes an errors object from a GraphQL
* response and returns an instance of ShieldsRuntimeError.
* The default is to return the first entry of the `errors` array as
* an InvalidResponse.
* @returns {object} Parsed response
* @see https://github.com/sindresorhus/ky#options
*/
async _requestGraphql({
schema,
url,
query,
variables = {},
options = {},
httpErrorMessages = {},
systemErrors = {},
logErrors = [429],
transformJson = data => data,
transformErrors = defaultTransformErrors,
}) {
const mergedOptions = {
...{ headers: this.constructor.headers },
...options,
}
mergedOptions.method = 'POST'
mergedOptions.json = { query: print(query), variables }
const { buffer } = await this._request({
url,
options: mergedOptions,
httpErrors: httpErrorMessages,
systemErrors,
logErrors,
})
const json = transformJson(this._parseJson(buffer))
if (json.errors) {
const exception = transformErrors(json.errors)
if (exception instanceof ShieldsRuntimeError) {
throw exception
} else {
throw Error(
`transformErrors() must return a ShieldsRuntimeError; got ${exception}`,
)
}
}
return this.constructor._validate(json, schema)
}
}
export default BaseGraphqlService