@gqlts/cli
Version:
Generate a client sdk from your GraphQl API
159 lines (137 loc) • 5.11 kB
text/typescript
import { RUNTIME_LIB_NAME } from '../../config';
import { RenderContext } from '../common/RenderContext';
import { requestTypeName } from '../requestTypes/requestTypeName';
import { renderEnumsMaps } from './renderClient';
import { GraphQLSchema } from 'graphql';
export function renderClientDefinition(schema: GraphQLSchema, ctx: RenderContext) {
const queryType = schema.getQueryType();
const mutationType = schema.getMutationType();
const subscriptionType = schema.getSubscriptionType();
const prefix = ctx.config?.methodPrefix || '';
const suffix = ctx.config?.methodSuffix || '';
ctx.addCodeBlock(`
import { FieldsSelection, GraphqlOperation, ClientOptions, ClientRequestConfig, Observable } from '${RUNTIME_LIB_NAME}'
import { Client as WSClient } from "graphql-ws"
import { AxiosInstance } from 'axios'
export * from './schema'
${renderClientTypesImports({ mutationType, queryType, subscriptionType })}
export declare const ${prefix}createClient${suffix}:(options?: ClientOptions) => Client
export declare const everything: { __scalar: boolean }
export declare const version: string
`);
// Client interface
ctx.addCodeBlock(renderClientType({ mutationType, queryType, subscriptionType }));
// generateQueryOp and QueryResult types
ctx.addCodeBlock(
renderSupportFunctionsTypes({
mutationType,
queryType,
subscriptionType,
}),
);
ctx.addCodeBlock(renderEnumsMaps(schema, 'type'));
}
function renderClientTypesImports({ queryType, mutationType, subscriptionType }) {
const imports: string[] = [];
if (queryType) {
imports.push(requestTypeName(queryType), queryType.name);
}
if (mutationType) {
imports.push(requestTypeName(mutationType), mutationType.name);
}
if (subscriptionType) {
imports.push(requestTypeName(subscriptionType), subscriptionType.name);
}
if (imports.length > 0) {
return `import {${imports.join(',')}} from './schema'`;
}
return '';
}
function renderClientType({ queryType, mutationType, subscriptionType }) {
let interfaceContent = '';
if (queryType) {
interfaceContent += `
query<R extends ${requestTypeName(queryType)}>(
request: R & { __name?: string },
config?: RC,
): Promise<GraphqlResponse<FieldsSelection<${queryType.name}, R>>>
`;
}
if (mutationType) {
interfaceContent += `
mutation<R extends ${requestTypeName(mutationType)}>(
request: R & { __name?: string },
config?: RC,
): Promise<GraphqlResponse<FieldsSelection<${mutationType.name}, R>>>
`;
}
if (subscriptionType) {
interfaceContent += `
subscription<R extends ${requestTypeName(subscriptionType)}>(
request: R & { __name?: string },
): Observable<GraphqlResponse<FieldsSelection<${subscriptionType.name}, R>>>
`;
}
return `
export type Head<T extends unknown | unknown[]> = T extends [infer H, ...unknown[]] ? H : never
export interface GraphQLError {
message: string
code?: string
locations?: {
line: number
column: number
}[]
path?: string | number[]
extensions?: {
[key: string]: unknown
}
[key: string]: unknown
}
export interface Extensions {
[key: string]: unknown
}
export interface GraphqlResponse<D = any, E = GraphQLError[], X = Extensions> {
data?: D;
errors?: E;
extensions?: X;
}
export interface Client<FI =AxiosInstance, RC =ClientRequestConfig> {
wsClient?: WSClient
fetcherInstance?: FI | undefined
fetcherMethod: (operation: GraphqlOperation | GraphqlOperation[], config?: RC) => Promise<any>
${interfaceContent}
}
`;
}
// TODO add the close method that closes the ws client
function renderSupportFunctionsTypes({ queryType, mutationType, subscriptionType }) {
let code = '';
if (queryType) {
code += `
export type QueryResult<fields extends ${requestTypeName(queryType)}> = GraphqlResponse<FieldsSelection<${
queryType.name
}, fields>>
export declare const generateQueryOp: (fields: ${requestTypeName(
queryType,
)} & { __name?: string }) => GraphqlOperation`;
}
if (mutationType) {
code += `
export type MutationResult<fields extends ${requestTypeName(mutationType)}> = GraphqlResponse<FieldsSelection<${
mutationType.name
}, fields>>
export declare const generateMutationOp: (fields: ${requestTypeName(
mutationType,
)} & { __name?: string }) => GraphqlOperation`;
}
if (subscriptionType) {
code += `
export type SubscriptionResult<fields extends ${requestTypeName(
subscriptionType,
)}> = GraphqlResponse<FieldsSelection<${subscriptionType.name}, fields>>
export declare const generateSubscriptionOp: (fields: ${requestTypeName(
subscriptionType,
)} & { __name?: string }) => GraphqlOperation`;
}
return code;
}