/** * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose * * Adapted from https://github.com/prisma/graphql-request, Copyright (c) 2017 Graphcool, MIT */ import { RuntimeContext } from '../mol-task'; import { AssetManager, Asset } from './assets'; type Variables = { [key: string]: any } interface GraphQLError { message: string locations: { line: number, column: number }[] path: string[] } interface GraphQLResponse { data?: any errors?: GraphQLError[] extensions?: any status: number [key: string]: any } interface GraphQLRequestContext { query: string variables?: Variables } export class ClientError extends Error { response: GraphQLResponse; request: GraphQLRequestContext; constructor(response: GraphQLResponse, request: GraphQLRequestContext) { const message = `${ClientError.extractMessage(response)}: ${JSON.stringify({ response, request })}`; super(message); this.response = response; this.request = request; // this is needed as Safari doesn't support .captureStackTrace if (typeof Error.captureStackTrace === 'function') { Error.captureStackTrace(this, ClientError); } } private static extractMessage(response: GraphQLResponse): string { return response.errors ? response.errors[0].message : `GraphQL Error (Code: ${response.status})`; } } export class GraphQLClient { constructor(private url: string, private assetManager: AssetManager) { } async request(ctx: RuntimeContext, query: string, variables?: Variables): Promise> { const body = JSON.stringify({ query, variables }, null, 2); const url = Asset.getUrlAsset(this.assetManager, this.url, body); const result = await this.assetManager.resolve(url, 'json').runInContext(ctx); if (!result.data.errors && result.data.data) { return { data: result.data.data, dispose: result.dispose }; } else { const errorResult = typeof result.data === 'string' ? { error: result.data } : result.data; throw new ClientError({ ...errorResult }, { query, variables }); } } }