UNPKG

@pothos/core

Version:

Pothos (formerly GiraphQL) is a plugin based schema builder for creating code-first GraphQL schemas in typescript

119 lines (118 loc) 4.84 kB
import { PothosSchemaError } from '../errors.js'; import { unwrapInputFieldType } from './params.js'; export function resolveInputTypeConfig(type, buildCache) { if (type.kind === "List") { return resolveInputTypeConfig(type.type, buildCache); } const config = buildCache.getTypeConfig(type.ref); if (config.kind === "Enum" || config.kind === "Scalar" || config.kind === "InputObject") { return config; } throw new PothosSchemaError(`Unexpected config type ${config.kind} for input ref ${String(type.ref)}`); } export function mapInputFields(inputs, buildCache, mapper, cache = new Map()) { const filterMappings = new Map(); const hasMappings = new Map(); return filterMapped(internalMapInputFields(inputs, buildCache, mapper, cache)); function filterMapped(map) { if (filterMappings.has(map)) { return filterMappings.get(map); } const filtered = new Map(); filterMappings.set(map, filtered); map.forEach((mapping, fieldName) => { if (mapping.kind === "Enum" || mapping.kind === "Scalar") { filtered.set(fieldName, mapping); return; } const hasNestedMappings = checkForMappings(mapping.fields.map, hasMappings); if (mapping.value !== null || hasNestedMappings) { const filteredTypeFields = filterMapped(mapping.fields.map); const mappingForType = { ...mapping, fields: { configs: mapping.fields.configs, map: filteredTypeFields } }; filtered.set(fieldName, mappingForType); } }); return filtered.size > 0 ? filtered : null; } function checkForMappings(map, hasMappings) { if (hasMappings.has(map)) { return hasMappings.get(map); } hasMappings.set(map, false); let result = false; for (const mapping of map.values()) { if (mapping.value !== null) { result = true; } else if (mapping.kind === "InputObject" && mapping.fields.map && checkForMappings(mapping.fields.map, hasMappings)) { result = true; } } hasMappings.set(map, result); return result; } } function internalMapInputFields(inputs, buildCache, mapper, seenTypes) { const map = new Map(); for (const [fieldName, inputField] of Object.entries(inputs)) { const typeConfig = resolveInputTypeConfig(inputField.type, buildCache); const fieldMapping = mapper(inputField); if (typeConfig.kind === "Enum" || typeConfig.kind === "Scalar") { if (fieldMapping !== null) { map.set(fieldName, { kind: typeConfig.kind, isList: inputField.type.kind === "List", config: inputField, value: fieldMapping }); } continue; } const inputFieldConfigs = buildCache.getInputTypeFieldConfigs(unwrapInputFieldType(inputField.type)); if (!seenTypes.has(typeConfig.name)) { const typeEntry = { configs: inputFieldConfigs, map: new Map() }; seenTypes.set(typeConfig.name, typeEntry); typeEntry.map = internalMapInputFields(inputFieldConfigs, buildCache, mapper, seenTypes); } const typeFields = seenTypes.get(typeConfig.name); map.set(fieldName, { kind: typeConfig.kind, isList: inputField.type.kind === "List", config: inputField, value: fieldMapping, fields: typeFields }); } return map; } export function createInputValueMapper(argMap, mapValue) { return function mapObject(obj, map = argMap, ...args) { const mapped = { ...obj }; map.forEach((field, fieldName) => { let fieldVal = obj[fieldName]; if (fieldVal === null || fieldVal === undefined) { return; } if (field.kind === "InputObject" && field.fields.map) { fieldVal = field.isList ? fieldVal.map((val) => val && mapObject(val, field.fields.map, ...args)) : mapObject(fieldVal, field.fields.map, ...args); mapped[fieldName] = fieldVal; } if (field.kind !== "InputObject" || field.value !== null) { mapped[fieldName] = field.isList ? fieldVal.map((val) => val == null ? val : mapValue(val, field, ...args)) : mapValue(fieldVal, field, ...args); } }); return mapped; }; } //# sourceMappingURL=input.js.map