@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
JavaScript
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