UNPKG

@gqlts/cli

Version:

Generate a client sdk from your GraphQl API

116 lines (107 loc) 3.75 kB
import { RenderContext } from '../common/RenderContext'; import { excludedTypes } from '../common/excludedTypes'; import { objectType } from './objectType'; import { unionType } from './unionType'; import { ArgMap, CompressedField, CompressedFieldMap, CompressedTypeMap, TypeMap } from '@gqlts/runtime/dist/types'; import { GraphQLSchema, isEnumType, isInputObjectType, isInterfaceType, isObjectType, isScalarType, isUnionType, } from 'graphql'; export function renderTypeMap(schema: GraphQLSchema, ctx: RenderContext) { // remove fields key, // remove the Type.type and Type.args, replace with [type, args] // reverse args.{name} // Args type is deduced and added only when the concrete type is different from type name, remove the scalar field and replace with a top level scalars array field. const result: TypeMap<string> = { scalars: [], types: {}, }; Object.keys(schema.getTypeMap()) .filter((t) => !excludedTypes.includes(t)) .map((t) => schema.getTypeMap()[t]) .map((t) => { if (isObjectType(t) || isInterfaceType(t) || isInputObjectType(t)) result.types[t.name] = objectType(t, ctx); else if (isUnionType(t)) result.types[t.name] = unionType(t, ctx); else if (isScalarType(t) || isEnumType(t)) { result.scalars.push(t.name); result.types[t.name] = {}; } }); // change names of query, mutation on schemas that chose different names (hasura) const q = schema.getQueryType(); if (q?.name && q?.name !== 'Query') { delete result.types[q.name]; result.types.Query = objectType(q, ctx); // result.Query.name = 'Query' } const m = schema.getMutationType(); if (m?.name && m.name !== 'Mutation') { delete result.types[m.name]; result.types.Mutation = objectType(m, ctx); // result.Mutation.name = 'Mutation' } const s = schema.getSubscriptionType(); if (s?.name && s.name !== 'Subscription') { delete result.types[s.name]; result.types.Subscription = objectType(s, ctx); // result.Subscription.name = 'Subscription' } ctx.addCodeBlock(JSON.stringify(replaceTypeNamesWithIndexes(result), null, 4)); } export function replaceTypeNamesWithIndexes(typeMap: TypeMap<string>): CompressedTypeMap<number> { const nameToIndex: Record<string, number> = Object.assign( {}, ...Object.keys(typeMap.types).map((k, i) => ({ [k]: i })), ); const scalars = typeMap.scalars.map((x) => nameToIndex[x]); const types = Object.assign( {}, ...Object.keys(typeMap.types || {}).map((k) => { const type = typeMap.types[k]; const fieldsMap = type || {}; // processFields(fields, indexToName) const fields = Object.assign( {}, ...Object.keys(fieldsMap).map((f): CompressedFieldMap<number> => { const content = fieldsMap[f] as any; if (!content) { throw new Error('no content in field ' + f); } const [typeName, args] = [content.type, content.args]; const res: CompressedField<number> = [typeName ? nameToIndex[typeName] : -1]; if (args) { res[1] = Object.assign( {}, ...Object.keys(args || {}).map((k) => { const arg = args?.[k]; if (!arg) { throw new Error('replaceTypeNamesWithIndexes: no arg for ' + k); } return { [k]: [nameToIndex[arg[0]], ...arg.slice(1)], } as ArgMap<number>; }), ); } return { [f]: res, }; }), ); return { [k]: { ...fields, }, }; }), ); return { scalars, types, }; }