UNPKG

nexus

Version:

Scalable, strongly typed GraphQL schema development

232 lines 8.39 kB
import { GraphQLList, GraphQLNonNull, isWrappingType, isListType, isNonNullType, } from 'graphql'; import { Unreachable } from '../utils'; import { arg } from './args'; import { list } from './list'; import { nonNull } from './nonNull'; import { nullable } from './nullable'; import { isNexusMetaType, resolveNexusMetaType } from './nexusMeta'; import { NexusTypes, NexusWrappedSymbol } from './_types'; const NamedTypeDefs = new Set([ NexusTypes.Enum, NexusTypes.Object, NexusTypes.Scalar, NexusTypes.Union, NexusTypes.Interface, NexusTypes.InputObject, ]); export const isNexusTypeDef = (obj) => { console.warn(`isNexusTypeDef is deprecated, use isNexusStruct`); return isNexusStruct(obj); }; export function isNexusStruct(obj) { return obj && Boolean(obj[NexusWrappedSymbol]); } export function isNexusNamedTypeDef(obj) { return isNexusStruct(obj) && NamedTypeDefs.has(obj[NexusWrappedSymbol]) && 'name' in obj; } export function isNexusListTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.List; } export function isNexusNonNullTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.NonNull; } export function isNexusNullTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Null; } export function isNexusWrappingType(obj) { return isNexusListTypeDef(obj) || isNexusNullTypeDef(obj) || isNexusNonNullTypeDef(obj); } export function isNexusExtendInputTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.ExtendInputObject; } export function isNexusExtendTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.ExtendObject; } export function isNexusEnumTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Enum; } export function isNexusInputObjectTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.InputObject; } export function isNexusObjectTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Object; } export function isNexusScalarTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Scalar; } export function isNexusUnionTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Union; } export function isNexusInterfaceTypeDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Interface; } export function isNexusArgDef(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Arg; } export function isNexusNamedOuputTypeDef(obj) { return isNexusNamedTypeDef(obj) && !isNexusInputObjectTypeDef(obj); } export function isNexusNamedInputTypeDef(obj) { return isNexusNamedTypeDef(obj) && !isNexusObjectTypeDef(obj) && !isNexusInterfaceTypeDef(obj); } export function isNexusDynamicOutputProperty(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.DynamicOutputProperty; } export function isNexusDynamicOutputMethod(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.DynamicOutputMethod; } export function isNexusDynamicInputMethod(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.DynamicInput; } export function isNexusPrintedGenTyping(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.PrintedGenTyping; } export function isNexusPrintedGenTypingImport(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.PrintedGenTypingImport; } export function isNexusPlugin(obj) { return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Plugin; } export function unwrapGraphQLDef(typeDef) { const wrapping = []; let namedType = typeDef; while (isWrappingType(namedType)) { if (isListType(namedType)) { wrapping.unshift('List'); } else if (isNonNullType(namedType)) { wrapping.unshift('NonNull'); } else { throw new Unreachable(namedType); } namedType = namedType.ofType; } return { namedType, wrapping }; } /** Unwraps any wrapped Nexus or GraphQL types, turning into a list of wrapping */ export function unwrapNexusDef(typeDef) { const wrapping = []; let namedType = typeDef; while (isNexusWrappingType(namedType) || isWrappingType(namedType) || isNexusMetaType(namedType)) { if (isNexusMetaType(namedType)) { namedType = resolveNexusMetaType(namedType); } else if (isWrappingType(namedType)) { if (isListType(namedType)) { wrapping.unshift('List'); } else if (isNonNullType(namedType)) { wrapping.unshift('NonNull'); } else { throw new Unreachable(namedType); } namedType = namedType.ofType; } else { if (isNexusNonNullTypeDef(namedType)) { wrapping.unshift('NonNull'); } if (isNexusNullTypeDef(namedType)) { wrapping.unshift('Null'); } if (isNexusListTypeDef(namedType)) { wrapping.unshift('List'); } namedType = namedType.ofNexusType; } } return { namedType, wrapping }; } /** Takes the named type, and applies any of the NexusFinalWrapKind to create a properly wrapped GraphQL type. */ export function rewrapAsGraphQLType(baseType, wrapping) { let finalType = baseType; wrapping.forEach((wrap) => { if (wrap === 'List') { finalType = new GraphQLList(finalType); } else if (wrap === 'NonNull') { if (!isNonNullType(finalType)) { finalType = new GraphQLNonNull(finalType); } } else { throw new Unreachable(wrap); } }); return finalType; } /** * Apply the wrapping consistently to the arg `type` * * NonNull(list(stringArg())) -> arg({ type: nonNull(list('String')) }) */ export function normalizeArgWrapping(argVal) { if (isNexusArgDef(argVal)) { return argVal; } if (isNexusWrappingType(argVal)) { let { namedType, wrapping } = unwrapNexusDef(argVal); if (isNexusArgDef(namedType)) { const config = namedType.value; return arg(Object.assign(Object.assign({}, config), { type: applyNexusWrapping(config.type, wrapping) })); } return arg({ type: applyNexusWrapping(namedType, wrapping) }); } return arg({ type: argVal }); } /** * Applies the ['List', 'NonNull', 'Nullable'] * * @param toWrap * @param wrapping */ export function applyNexusWrapping(toWrap, wrapping) { let finalType = toWrap; wrapping.forEach((wrap) => { if (wrap === 'List') { finalType = list(finalType); } else if (wrap === 'NonNull') { finalType = nonNull(finalType); } else if (wrap === 'Null') { finalType = nullable(finalType); } else { throw new Unreachable(wrap); } }); return finalType; } /** * Takes the "nonNullDefault" value, the chained wrapping, and the field wrapping, to determine the proper * list of wrapping to apply to the field */ export function finalizeWrapping(nonNullDefault, typeWrapping, chainWrapping) { let finalChain = []; const allWrapping = typeWrapping.concat(chainWrapping !== null && chainWrapping !== void 0 ? chainWrapping : []); // Ensure the first item is wrapped, if we're not guarding if (nonNullDefault && (!allWrapping[0] || allWrapping[0] === 'List')) { allWrapping.unshift('NonNull'); } for (let i = 0; i < allWrapping.length; i++) { const current = allWrapping[i]; const next = allWrapping[i + 1]; if (current === 'Null') { continue; } else if (current === 'NonNull') { finalChain.push('NonNull'); } else if (current === 'List') { finalChain.push('List'); if (nonNullDefault && (next === 'List' || !next)) { finalChain.push('NonNull'); } } } return finalChain; } //# sourceMappingURL=wrapping.js.map