@chargetrip/mcp
Version:
Chargetrip MCP server
149 lines (132 loc) • 4.21 kB
text/typescript
import {
Client,
createClient,
fetchExchange,
OperationResult,
subscriptionExchange,
} from '@urql/core';
import fetch from 'cross-fetch';
import { gql } from 'graphql-tag';
import { createClient as wsCreateClient } from 'graphql-ws';
import WebSocket from 'ws';
export class GraphQLClient {
/**
* @description GraphQL client instance for making requests to the GraphQL API.
*/
private client: Client;
/**
* @description The unique id of each request
*/
private key = 1;
/**
* @description Singleton instances for the GraphQLClient.
*/
protected static instance: GraphQLClient = new GraphQLClient();
constructor() {
const graphqlEndpoint = process.env.GRAPHQL_ENDPOINT ?? 'https://api.chargetrip.io/graphql';
const graphqlWsEndpoint =
process.env.GRAPHQL_WS_ENDPOINT ?? 'wss://api.chargetrip.io/subscription';
const headers: Record<string, string> = {
'x-client-id': process.env.CLIENT_ID!,
'x-app-id': process.env.APP_ID!,
};
if (process.env.APP_IDENTIFIER !== undefined) {
headers['x-app-identifier'] = process.env.APP_IDENTIFIER!;
}
if (process.env.APP_FINGERPRINT !== undefined) {
headers['x-app-fingerprint'] = process.env.APP_FINGERPRINT!;
}
const wsClient = wsCreateClient({
url: graphqlWsEndpoint,
webSocketImpl: WebSocket,
lazy: true,
keepAlive: 5000,
connectionParams: headers,
shouldRetry: () => true,
});
this.client = createClient({
url: graphqlEndpoint,
requestPolicy: 'network-only',
preferGetMethod: false,
fetch,
fetchOptions: () => ({ headers, cache: 'no-cache', method: 'POST' }),
exchanges: [
fetchExchange,
subscriptionExchange({
forwardSubscription(request) {
const input = { ...request, query: request.query ?? '' };
return {
subscribe(sink) {
const unsubscribe = wsClient.subscribe(input, sink);
return { unsubscribe };
},
};
},
}),
],
});
}
/**
* @description Singleton instance getter for GraphQLClient.
*
* @returns {GraphQLClient} The singleton instance of GraphQLClient.
*/
public static getInstance(): GraphQLClient {
return GraphQLClient.instance;
}
/**
* @description Executes a GraphQL query.
*
* @param {string} query The GraphQL query string to execute.
* @param {Record<string, any>} [variables] Optional variables for the query.
* @returns {Promise<OperationResult<T>>} A promise that resolves to the result of the query.
*/
async query<T>(query: string, variables?: Record<string, any>): Promise<OperationResult<T>> {
const parsedQuery = gql`
${query}
`;
return this.client
.executeQuery<T>({
key: this.key++,
query: parsedQuery,
variables,
})
.toPromise();
}
/**
* @description Executes a GraphQL mutation.
*
* @param {string} mutation The GraphQL mutation string to execute.
* @param {Record<string, any>} [variables] Optional variables for the mutation.
* @returns {Promise<OperationResult<T>>} A promise that resolves to the result of the mutation.
*/
async mutate<T>(mutation: string, variables?: Record<string, any>): Promise<OperationResult<T>> {
const parsedMutation = gql`
${mutation}
`;
return this.client
.executeMutation<T>({
key: this.key++,
query: parsedMutation,
variables,
})
.toPromise();
}
/**
* @description Executes a GraphQL subscription.
*
* @param {string} subscription The GraphQL subscription string to execute.
* @param {Record<string, any>} [variables] Optional variables for the subscription.
* @returns {Observable<OperationResult<T>>} An observable that emits the results of the subscription.
*/
subscription<T>(subscription: string, variables?: Record<string, any>) {
const parsedSubscription = gql`
${subscription}
`;
return this.client.executeSubscription<T>({
key: this.key++,
query: parsedSubscription,
variables,
});
}
}