@avantstay/graphql-ts-client 10.5.0
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/README.md +78 -0
- package/dist/endpoint.d.ts +13 -0
- package/dist/endpoint.js +836 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +985 -0
- package/dist/types-4ecbabdf.d.ts +69 -0
- package/package.json +85 -0
- package/src/__snapshots__/graphqlRequest.test.ts.snap +24 -0
- package/src/__testClient.d.ts +148 -0
- package/src/__testClient.js +118 -0
- package/src/endpoint.ts +117 -0
- package/src/generateTypescriptClient.test.ts +127 -0
- package/src/generateTypescriptClient.ts +547 -0
- package/src/graphqlRequest.test.ts +103 -0
- package/src/graphqlRequest.ts +95 -0
- package/src/index.ts +3 -0
- package/src/jsonToGraphQLQuery.test.ts +66 -0
- package/src/jsonToGraphQLQuery.ts +88 -0
- package/src/logging.ts +33 -0
- package/src/testServer.ts +71 -0
- package/src/types.ts +114 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import _axios, { AxiosStatic } from 'axios'
|
|
2
|
+
import { ClientConfig, GraphQLClientError, ResponseData } from './types'
|
|
3
|
+
|
|
4
|
+
const sleep = (ms = 0) =>
|
|
5
|
+
new Promise<void>(resolve => {
|
|
6
|
+
setTimeout(() => resolve(), ms)
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
export async function graphqlRequest({
|
|
10
|
+
shouldRetry = true,
|
|
11
|
+
axios = _axios,
|
|
12
|
+
queryName,
|
|
13
|
+
client,
|
|
14
|
+
query,
|
|
15
|
+
requestHeaders = {},
|
|
16
|
+
variables,
|
|
17
|
+
failureMode,
|
|
18
|
+
errorsParser,
|
|
19
|
+
}: {
|
|
20
|
+
shouldRetry?: boolean
|
|
21
|
+
failureMode: 'loud' | 'silent'
|
|
22
|
+
axios?: AxiosStatic
|
|
23
|
+
client: ClientConfig
|
|
24
|
+
queryName: string
|
|
25
|
+
query: string
|
|
26
|
+
requestHeaders?: { [_key: string]: any }
|
|
27
|
+
variables: { [_key: string]: any }
|
|
28
|
+
errorsParser?: (errors: any[]) => any
|
|
29
|
+
}) {
|
|
30
|
+
let lastResponse: ResponseData
|
|
31
|
+
|
|
32
|
+
const maxRetrials = shouldRetry ? client.retryConfig.max : 0
|
|
33
|
+
|
|
34
|
+
for (let trial = 0; true; trial++) {
|
|
35
|
+
const infoParams = {
|
|
36
|
+
_q: queryName,
|
|
37
|
+
...(trial > 0 ? { _retrial: trial + 1 } : {}),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
data: responseData = {} as any,
|
|
42
|
+
headers,
|
|
43
|
+
status,
|
|
44
|
+
} = await axios.post(
|
|
45
|
+
client.url,
|
|
46
|
+
{ query, variables, operationName: queryName },
|
|
47
|
+
{
|
|
48
|
+
params: infoParams,
|
|
49
|
+
headers: {
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
...client.headers,
|
|
52
|
+
...requestHeaders,
|
|
53
|
+
},
|
|
54
|
+
validateStatus: () => true,
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
let { data, errors, warnings } = responseData
|
|
59
|
+
|
|
60
|
+
if (status >= 400 && !errors?.length) {
|
|
61
|
+
errors = [{ message: `Request "${queryName}" failed with status ${status}` }]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
lastResponse = {
|
|
65
|
+
errors: errorsParser ? errorsParser(errors) : errors,
|
|
66
|
+
data,
|
|
67
|
+
warnings,
|
|
68
|
+
headers,
|
|
69
|
+
status,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!errors?.length) {
|
|
73
|
+
break
|
|
74
|
+
} else if (trial < maxRetrials && typeof client.retryConfig?.before === 'function') {
|
|
75
|
+
await client.retryConfig?.before({
|
|
76
|
+
queryName,
|
|
77
|
+
query,
|
|
78
|
+
variables,
|
|
79
|
+
response: lastResponse,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
if (client.retryConfig.waitBeforeRetry) {
|
|
83
|
+
await sleep(client.retryConfig.waitBeforeRetry)
|
|
84
|
+
}
|
|
85
|
+
} else if (trial >= maxRetrials) {
|
|
86
|
+
break
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (failureMode === 'loud' && lastResponse!.errors && lastResponse!.errors?.length) {
|
|
91
|
+
throw new GraphQLClientError(lastResponse)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return lastResponse!
|
|
95
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsonToGraphQLQuery } from './jsonToGraphQLQuery'
|
|
2
|
+
|
|
3
|
+
describe('jsonToGraphQLQuery', () => {
|
|
4
|
+
it('use args without mutating', () => {
|
|
5
|
+
const jsonQuery = {
|
|
6
|
+
__args: {
|
|
7
|
+
foo: 'Bar',
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
something: true,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const originalArgs = JSON.stringify(jsonQuery)
|
|
14
|
+
|
|
15
|
+
const response = jsonToGraphQLQuery({
|
|
16
|
+
kind: 'query',
|
|
17
|
+
queryName: 'testing',
|
|
18
|
+
jsonQuery,
|
|
19
|
+
typesTree: {
|
|
20
|
+
Query: {
|
|
21
|
+
get testing(): any {
|
|
22
|
+
return {
|
|
23
|
+
__args: {
|
|
24
|
+
foo: 'UUID!',
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
expect(response).not.toBeNull()
|
|
33
|
+
expect(originalArgs).toBe(JSON.stringify(jsonQuery))
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('variables are correctly named', () => {
|
|
37
|
+
const jsonQuery = {
|
|
38
|
+
__args: {
|
|
39
|
+
foo: 'Bar',
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
something: true,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const response = jsonToGraphQLQuery({
|
|
46
|
+
kind: 'query',
|
|
47
|
+
queryName: 'testing',
|
|
48
|
+
jsonQuery,
|
|
49
|
+
typesTree: {
|
|
50
|
+
Query: {
|
|
51
|
+
get testing(): any {
|
|
52
|
+
return {
|
|
53
|
+
__args: {
|
|
54
|
+
foo: 'UUID!',
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
Object.keys(response.variables).forEach(varName => {
|
|
63
|
+
expect(response.query.split(varName).length - 1).toBeGreaterThanOrEqual(2) //every variable name should be present at least 2 times
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import omit from 'lodash/omit'
|
|
2
|
+
|
|
3
|
+
const VAR_PREFIX = '@@VAR@@'
|
|
4
|
+
const VAR_PREFIX_LENGTH = VAR_PREFIX.length
|
|
5
|
+
|
|
6
|
+
const fromEntries: (arr: [string, any][]) => { [key: string]: any } = require('lodash/fromPairs')
|
|
7
|
+
const entries: (obj: { [key: string]: any }) => [string, any][] = require('lodash/toPairs')
|
|
8
|
+
const cloneDeep = require('lodash/cloneDeep')
|
|
9
|
+
|
|
10
|
+
export function jsonToGraphQLQuery({
|
|
11
|
+
kind,
|
|
12
|
+
queryName,
|
|
13
|
+
jsonQuery = {},
|
|
14
|
+
typesTree,
|
|
15
|
+
}: {
|
|
16
|
+
kind: 'query' | 'mutation'
|
|
17
|
+
queryName: string
|
|
18
|
+
jsonQuery: any
|
|
19
|
+
typesTree: any
|
|
20
|
+
}) {
|
|
21
|
+
const variablesData = {} as any
|
|
22
|
+
const alias = jsonQuery.__alias
|
|
23
|
+
const newJsonQuery = cloneDeep(omit(jsonQuery, ['__alias', '__headers']))
|
|
24
|
+
|
|
25
|
+
extractVariables({
|
|
26
|
+
jsonQuery: { [queryName]: newJsonQuery },
|
|
27
|
+
variables: variablesData,
|
|
28
|
+
parentType: kind === 'query' ? typesTree.Query : typesTree.Mutation,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const variablesQuery = Object.keys(variablesData).length
|
|
32
|
+
? `(${entries(variablesData)
|
|
33
|
+
.map(([queryName, { type }]: any) => `$${queryName}: ${type}`)
|
|
34
|
+
.join(', ')})`
|
|
35
|
+
: ''
|
|
36
|
+
|
|
37
|
+
const query = `${kind} ${alias || queryName}${variablesQuery} { ${alias ? `${alias}:` : ''}${queryName}${toGraphql(
|
|
38
|
+
newJsonQuery
|
|
39
|
+
)} }`
|
|
40
|
+
const variables = fromEntries(entries(variablesData).map(([k, v]: any) => [k, v.value]))
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
query,
|
|
44
|
+
variables,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function extractVariables({ jsonQuery, variables, parentType }: { jsonQuery: any; variables: any; parentType: any }) {
|
|
49
|
+
if (!parentType) return
|
|
50
|
+
|
|
51
|
+
if (jsonQuery.__args) {
|
|
52
|
+
Object.keys(jsonQuery.__args).forEach(k => {
|
|
53
|
+
if (typeof jsonQuery.__args[k] === 'string' && jsonQuery.__args[k].startsWith(VAR_PREFIX)) return
|
|
54
|
+
|
|
55
|
+
const variableName = `${k}_${Math.random().toString(36).substr(2, 4)}`
|
|
56
|
+
|
|
57
|
+
if (jsonQuery.__args[k] !== undefined) {
|
|
58
|
+
variables[variableName] = {
|
|
59
|
+
type: parentType.__args[k],
|
|
60
|
+
value: jsonQuery.__args[k],
|
|
61
|
+
}
|
|
62
|
+
jsonQuery.__args[k] = `${VAR_PREFIX}$${variableName}`
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Object.keys(jsonQuery)
|
|
68
|
+
.filter(k => k !== '__args' && typeof jsonQuery[k] === 'object')
|
|
69
|
+
.forEach(k =>
|
|
70
|
+
extractVariables({
|
|
71
|
+
jsonQuery: jsonQuery[k],
|
|
72
|
+
variables,
|
|
73
|
+
parentType: parentType.hasOwnProperty(k) ? parentType[k] : parentType.__fields ? parentType.__fields[k] : undefined,
|
|
74
|
+
})
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toGraphql(jsonQuery: any) {
|
|
79
|
+
const fields = entries(jsonQuery)
|
|
80
|
+
.filter(([k, v]) => k !== '__args' && v !== false && v !== undefined)
|
|
81
|
+
.map(([k, v]) => (typeof v === 'object' ? `${k}${toGraphql(v)}` : k))
|
|
82
|
+
.join(' ') as any
|
|
83
|
+
|
|
84
|
+
const validArgs = jsonQuery.__args ? entries(jsonQuery.__args).filter(([_, v]) => v !== undefined) : []
|
|
85
|
+
const argsQuery = validArgs.length ? `(${validArgs.map(([k, v]: any) => `${k}:${v.substr(VAR_PREFIX_LENGTH)}`).join(',')})` : ''
|
|
86
|
+
|
|
87
|
+
return `${argsQuery} ${fields ? `{ ${fields} }` : ''}`
|
|
88
|
+
}
|
package/src/logging.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { LogInfo } from './types'
|
|
2
|
+
|
|
3
|
+
export function logRequest(logInfo: LogInfo) {
|
|
4
|
+
let identifier = `%c#graphql-ts-client ${logInfo.kind} ${logInfo.queryName}`
|
|
5
|
+
let identifierStyles = 'color: transparent; font-size: 0px'
|
|
6
|
+
|
|
7
|
+
console.groupCollapsed(
|
|
8
|
+
`%c#graphql-ts-client %c${logInfo.kind} %c${logInfo.queryName} %c(${logInfo.duration.toFixed(2)}ms)`,
|
|
9
|
+
'color: #f90',
|
|
10
|
+
'color: #999',
|
|
11
|
+
`color: ${logInfo.response ? 'unset' : '#f00'}; font-weight: bold`,
|
|
12
|
+
'color: #999'
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
console.groupCollapsed(`%cQuery ${identifier}`, 'color: #999', identifierStyles)
|
|
16
|
+
console.log(logInfo.formatGraphQL(logInfo.query) + identifier, identifierStyles)
|
|
17
|
+
console.groupEnd()
|
|
18
|
+
console.groupCollapsed(`%cVariables ${identifier}`, 'color: #999', identifierStyles)
|
|
19
|
+
console.log(JSON.stringify(logInfo.variables, null, ' ') + identifier, identifierStyles)
|
|
20
|
+
console.groupEnd()
|
|
21
|
+
console.groupCollapsed(`%cTrace ${identifier}`, 'color: #999', identifierStyles)
|
|
22
|
+
console.trace(identifier, identifierStyles)
|
|
23
|
+
console.groupEnd()
|
|
24
|
+
|
|
25
|
+
if (logInfo.response) {
|
|
26
|
+
console.log('%cResponse'.padEnd(15, ' ') + identifier, 'color: #999', identifierStyles, logInfo.response)
|
|
27
|
+
}
|
|
28
|
+
if (logInfo.error) {
|
|
29
|
+
console.log('%cError'.padEnd(15, ' ') + identifier, 'color: #999', identifierStyles, logInfo.error)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.groupEnd()
|
|
33
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ApolloServer, gql } from 'apollo-server'
|
|
2
|
+
|
|
3
|
+
const typeDefs = gql`
|
|
4
|
+
scalar ISODate
|
|
5
|
+
|
|
6
|
+
enum BookType {
|
|
7
|
+
IPSUM
|
|
8
|
+
DOLOR
|
|
9
|
+
SIT
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type Book {
|
|
13
|
+
title: String
|
|
14
|
+
author: String
|
|
15
|
+
type: BookType
|
|
16
|
+
dateCreated: ISODate
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
input BookSearchParamsAllOptional {
|
|
20
|
+
title: String
|
|
21
|
+
author: String
|
|
22
|
+
createdAfter: ISODate
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
input BookSearchParamsSomeRequired {
|
|
26
|
+
title: String!
|
|
27
|
+
author: String
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type Query {
|
|
31
|
+
booksWithoutParams: [Book]
|
|
32
|
+
booksWithOptionalParams(params: BookSearchParamsAllOptional! = {}): [Book]
|
|
33
|
+
booksWithRequiredParams(params: BookSearchParamsSomeRequired!): [Book]
|
|
34
|
+
failingQuery(id: String!): String
|
|
35
|
+
}
|
|
36
|
+
`
|
|
37
|
+
|
|
38
|
+
const books = [
|
|
39
|
+
{
|
|
40
|
+
title: 'The Awakening',
|
|
41
|
+
author: 'Kate Chopin',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
title: 'City of Glass',
|
|
45
|
+
author: 'Paul Auster',
|
|
46
|
+
},
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
function filterBooks(params: { title?: string; author?: string }) {
|
|
50
|
+
return books.filter(
|
|
51
|
+
book => (!params.title || book.title.includes(params.title)) && (!params.author || book.author.includes(params.author))
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const resolvers = {
|
|
56
|
+
Query: {
|
|
57
|
+
booksWithoutParams: () => books,
|
|
58
|
+
booksWithOptionalParams: (_: any, { params = {} }: { params: { title?: string; author?: string } }) => filterBooks(params),
|
|
59
|
+
booksWithRequiredParams: (_: any, { params }: { params: { title: string; author?: string } }) => filterBooks(params),
|
|
60
|
+
failingQuery: () => {
|
|
61
|
+
throw new Error('Failed lorem ipsum dolor')
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const testServer = new ApolloServer({
|
|
67
|
+
typeDefs,
|
|
68
|
+
resolvers,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
export const startServer = () => testServer.listen(4123).then(({ url }) => ({ url, server: testServer }))
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export type Maybe<T> = null | undefined | T
|
|
2
|
+
export type Defined<T> = Exclude<T, undefined>
|
|
3
|
+
|
|
4
|
+
export type ResponseData = {
|
|
5
|
+
data: any
|
|
6
|
+
warnings: any
|
|
7
|
+
headers: any
|
|
8
|
+
status?: number
|
|
9
|
+
errors: {
|
|
10
|
+
message: string
|
|
11
|
+
}[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type ResponseListenerInfo = {
|
|
15
|
+
queryName: string
|
|
16
|
+
query: string
|
|
17
|
+
variables: any
|
|
18
|
+
response: ResponseData
|
|
19
|
+
}
|
|
20
|
+
export type IResponseListener = (info: ResponseListenerInfo) => void | Promise<void>
|
|
21
|
+
|
|
22
|
+
type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never
|
|
23
|
+
|
|
24
|
+
export type Projection<Selection, Base, E = never> = Base extends Array<any>
|
|
25
|
+
? ArrayElement<Base> extends Date | string | number | boolean | null | undefined | E
|
|
26
|
+
? ArrayElement<Base>[]
|
|
27
|
+
: Projection<Defined<Selection>, ArrayElement<Base>, E>[]
|
|
28
|
+
: Base extends Date | string | number | boolean | null | E
|
|
29
|
+
? // Is primitive and extends undefined
|
|
30
|
+
Selection extends undefined
|
|
31
|
+
? Base | undefined
|
|
32
|
+
: Base
|
|
33
|
+
: {
|
|
34
|
+
[k in keyof Selection & keyof Base]: Selection[k] extends boolean
|
|
35
|
+
? Base[k]
|
|
36
|
+
: Base[k] extends Array<infer A>
|
|
37
|
+
? Projection<Defined<Selection[k]>, A, E>[]
|
|
38
|
+
: Projection<Defined<Selection[k]>, Base[k], E>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type Unpacked<T> = T extends (infer U)[]
|
|
42
|
+
? U
|
|
43
|
+
: T extends (...args: any[]) => infer U
|
|
44
|
+
? U
|
|
45
|
+
: T extends Promise<infer U>
|
|
46
|
+
? U
|
|
47
|
+
: T
|
|
48
|
+
|
|
49
|
+
export type Replacement<M extends [any, any], T> = M extends any ? ([T] extends [M[0]] ? M[1] : never) : never
|
|
50
|
+
|
|
51
|
+
export type DeepReplace<T, Ignore, M extends [any, any]> = {
|
|
52
|
+
[P in keyof T]: T[P] extends M[0]
|
|
53
|
+
? T[P] extends Ignore
|
|
54
|
+
? T[P] extends object
|
|
55
|
+
? DeepReplace<T[P], Ignore, M>
|
|
56
|
+
: T[P]
|
|
57
|
+
: Replacement<M, T[P]>
|
|
58
|
+
: T[P] extends object
|
|
59
|
+
? DeepReplace<T[P], Ignore, M>
|
|
60
|
+
: T[P]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type RawEndpoint<I, O, E> = <S extends I>(
|
|
64
|
+
jsonQuery?: S
|
|
65
|
+
) => Promise<{ data: Projection<S, O, E>; errors: any[]; warnings: any[]; headers: any; status: any }>
|
|
66
|
+
|
|
67
|
+
export type JsonOutput<O, ToBeIgnored> = DeepReplace<O, ToBeIgnored, [string | Date, string]>
|
|
68
|
+
|
|
69
|
+
export type Endpoint<I, O, E> = (<S extends I>(jsonQuery?: S) => Promise<Projection<S, JsonOutput<O, E>, E>>) & {
|
|
70
|
+
memo: <S extends I>(jsonQuery?: S) => Promise<Projection<S, JsonOutput<O, E>, E>>
|
|
71
|
+
memoRaw: RawEndpoint<I, JsonOutput<O, E>, E>
|
|
72
|
+
raw: RawEndpoint<I, JsonOutput<O, E>, E>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type ClientConfig = {
|
|
76
|
+
url: string
|
|
77
|
+
headers: {
|
|
78
|
+
[key: string]: string
|
|
79
|
+
}
|
|
80
|
+
retryConfig: {
|
|
81
|
+
max: number
|
|
82
|
+
waitBeforeRetry?: number
|
|
83
|
+
before: IResponseListener
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type LogInfo = {
|
|
88
|
+
query: string
|
|
89
|
+
variables: any
|
|
90
|
+
formatGraphQL: any
|
|
91
|
+
kind: string
|
|
92
|
+
queryName: string
|
|
93
|
+
response?: any
|
|
94
|
+
error?: Error
|
|
95
|
+
duration: number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export class GraphQLClientError extends Error {
|
|
99
|
+
responseData: ResponseData
|
|
100
|
+
|
|
101
|
+
constructor(responseData: ResponseData) {
|
|
102
|
+
super()
|
|
103
|
+
this.responseData = responseData
|
|
104
|
+
Object.setPrototypeOf(this, GraphQLClientError.prototype)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get message(): string {
|
|
108
|
+
return this.response.errors.map(it => it.message).join(';\n')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get response(): ResponseData {
|
|
112
|
+
return this.responseData
|
|
113
|
+
}
|
|
114
|
+
}
|