@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;
110 lines (109 loc) • 4.64 kB
JavaScript
import { isSomeInputTypeComposer, ListComposer, } from 'graphql-compose';
import { ResolveRootDirective, StatusCodeTypeNameDirective } from './directives.js';
export function getContainerTC(subgraphName, schemaComposer, output) {
const containerTypeName = `${output.getTypeName()}_container`;
schemaComposer.addDirective(ResolveRootDirective);
return schemaComposer.getOrCreateOTC(containerTypeName, otc => otc.addFields({
[output.getTypeName()]: {
type: output,
directives: [
{
name: 'resolveRoot',
args: {
subgraph: subgraphName,
},
},
],
},
}));
}
export function getUnionTypeComposers({ subgraphName, schemaComposer, typeComposersList, subSchemaAndTypeComposers, logger, }) {
if (new Set(typeComposersList).size === 1) {
return typeComposersList[0];
}
const unionInputFields = {};
const outputTypeComposers = [];
let isOutputPlural = false;
typeComposersList.forEach(typeComposers => {
let { input, output } = typeComposers;
if (output instanceof ListComposer) {
output = output.getUnwrappedTC();
isOutputPlural = true;
}
if (isSomeInputTypeComposer(output)) {
outputTypeComposers.push(getContainerTC(subgraphName, schemaComposer, output));
}
else {
outputTypeComposers.push(output);
}
if (input) {
const inputTypeName = input instanceof ListComposer
? input.getUnwrappedTC().getTypeName() + '_list'
: input.getTypeName();
unionInputFields[inputTypeName] = {
type: input,
};
}
if (!input) {
logger.debug(`No input type composer found for ${output.getTypeName()}, skipping...`);
}
});
if (Object.keys(unionInputFields).length === 1) {
subSchemaAndTypeComposers.input = Object.values(unionInputFields)[0].type;
}
else {
subSchemaAndTypeComposers.input.addFields(unionInputFields);
}
if (new Set(outputTypeComposers).size === 1) {
subSchemaAndTypeComposers.output = outputTypeComposers[0];
}
else {
const directives = subSchemaAndTypeComposers.output.getDirectives() || [];
const statusCodeOneOfIndexMap = subSchemaAndTypeComposers.output.getExtension('statusCodeOneOfIndexMap');
const statusCodeOneOfIndexMapEntries = Object.entries(statusCodeOneOfIndexMap || {});
for (const outputTypeComposerIndex in outputTypeComposers) {
const outputTypeComposer = outputTypeComposers[outputTypeComposerIndex];
const statusCode = statusCodeOneOfIndexMapEntries.find(([statusCode, index]) => index.toString() === outputTypeComposerIndex.toString())?.[0];
if ('getFields' in outputTypeComposer) {
if (statusCode != null) {
schemaComposer.addDirective(StatusCodeTypeNameDirective);
directives.push({
name: 'statusCodeTypeName',
args: {
subgraph: subgraphName,
statusCode,
typeName: outputTypeComposer.getTypeName(),
},
});
}
subSchemaAndTypeComposers.output.addType(outputTypeComposer);
}
else {
for (const possibleType of outputTypeComposer.getTypes()) {
subSchemaAndTypeComposers.output.addType(possibleType);
}
}
}
subSchemaAndTypeComposers.output.setDirectives(directives);
}
let flatten = false;
// TODO: container suffix might not be coming from us
if (subSchemaAndTypeComposers.output.getTypeName().endsWith('_container')) {
const fields = subSchemaAndTypeComposers.output.getFields();
const fieldKeys = Object.keys(fields);
if (fieldKeys.length === 1) {
subSchemaAndTypeComposers.output = fields[fieldKeys[0]].type;
flatten = isOutputPlural;
}
}
return {
input: subSchemaAndTypeComposers.input,
output: isOutputPlural
? subSchemaAndTypeComposers.output.List
: subSchemaAndTypeComposers.output,
nullable: subSchemaAndTypeComposers.nullable,
readOnly: subSchemaAndTypeComposers.readOnly,
writeOnly: subSchemaAndTypeComposers.writeOnly,
flatten,
};
}