@omnigraph/json-schema
Version:
This package generates GraphQL Schema from JSON Schema and sample JSON request and responses. You can define your root field endpoints like below in your GraphQL Config for example;
99 lines (98 loc) • 4.16 kB
JavaScript
import { createGraphQLError, getDirective } from '@graphql-tools/utils';
export function getTypeResolverFromOutputTCs({ possibleTypes, discriminatorField, discriminatorMapping, statusCodeTypeNameMap, }) {
return function resolveType(data, _ctx, info) {
if (data.__typename) {
return data.__typename;
}
else if (discriminatorField != null && data[discriminatorField]) {
const discriminatorValue = data[discriminatorField];
return discriminatorMapping?.[discriminatorValue] || discriminatorValue;
}
if (data.$statusCode && statusCodeTypeNameMap) {
const typeName = statusCodeTypeNameMap[data.$statusCode.toString()] || statusCodeTypeNameMap.default;
if (typeName) {
return typeName;
}
}
const dataTypeOf = typeof data;
if (dataTypeOf !== 'object') {
for (const possibleType of possibleTypes) {
const fieldMap = possibleType.getFields();
const fields = Object.values(fieldMap);
if (fields.length === 1) {
const field = fields[0];
const directiveObjs = getDirective(info.schema, field, 'resolveRoot');
if (directiveObjs?.length) {
const fieldType = field.type;
if ('parseValue' in fieldType) {
try {
fieldType.parseValue(data);
return possibleType.name;
}
catch (e) { }
}
}
}
}
}
// const validationErrors: Record<string, ErrorObject[]> = {};
const dataKeys = dataTypeOf
? Object.keys(data)
// Remove metadata fields used to pass data
.filter(property => !property.toString().startsWith('$'))
: null;
const scoreTypeNameMap = new Map();
for (const possibleType of possibleTypes) {
const typeName = possibleType.name;
if (dataKeys != null) {
const typeFields = Object.keys(possibleType.getFields());
if (dataKeys.length <= typeFields.length &&
dataKeys.every(property => typeFields.includes(property.toString()))) {
return typeName;
}
else {
const score = dataKeys.filter(property => typeFields.includes(property.toString())).length;
if (score || typeFields.includes('additionalProperties')) {
scoreTypeNameMap.set(score, typeName);
}
}
} /* else {
const validateFn = possibleType.extensions.validateWithJSONSchema as ValidateFunction;
if (validateFn) {
const isValid = validateFn(data);
if (isValid) {
return typeName;
}
validationErrors[typeName] = ajv.errors || validateFn.errors;
}
} */
}
const maxScore = Math.max(...scoreTypeNameMap.keys());
const typeName = scoreTypeNameMap.get(maxScore);
if (typeName) {
return typeName;
}
if (data.$response) {
const error = createGraphQLError(`HTTP Error: ${data.$statusCode}`, {
extensions: {
http: {
status: data.$statusCode,
headers: data.$response.header,
},
request: {
url: data.$url,
method: data.$method,
},
responseJson: data.$response,
},
});
return error;
}
/*
const error = new GraphQLError(`Received data doesn't met the union`, null, null, null, null, null, {
validationErrors,
});
return error;
*/
};
}