@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;
1,019 lines • 65.2 kB
JavaScript
/* eslint-disable no-case-declarations */
import { ObjectTypeComposer, ScalarTypeComposer, SchemaComposer, ListComposer, UnionTypeComposer, isSomeInputTypeComposer, EnumTypeComposer, InterfaceTypeComposer, } from 'graphql-compose';
import { getNamedType, GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLString, isNonNullType, } from 'graphql';
import { GraphQLBigInt, GraphQLDateTime, GraphQLEmailAddress, GraphQLJSON, GraphQLUUID, GraphQLIPv4, GraphQLIPv6, GraphQLTime, GraphQLURL, GraphQLNonNegativeFloat, GraphQLPositiveFloat, GraphQLNonPositiveFloat, GraphQLNegativeFloat, GraphQLNonEmptyString, GraphQLNonNegativeInt, GraphQLPositiveInt, GraphQLNonPositiveInt, GraphQLNegativeInt, GraphQLByte, GraphQLTimestamp, } from 'graphql-scalars';
import { sanitizeNameForGraphQL } from '@graphql-mesh/utils';
import { visitJSONSchema } from 'json-machete';
import { getJSONSchemaStringFormatScalarMap } from './getJSONSchemaStringFormatScalarMap.js';
import { getUnionTypeComposers } from './getUnionTypeComposers.js';
import { getValidTypeName } from './getValidTypeName.js';
import { DictionaryDirective, DiscriminatorDirective, EnumDirective, ExampleDirective, LengthDirective, OneOfDirective, RegExpDirective, ResolveRootDirective, ResolveRootFieldDirective, TypeScriptDirective, } from './directives.js';
import { GraphQLFile, GraphQLVoid } from './scalars.js';
export function getComposerFromJSONSchema(schema, logger) {
const schemaComposer = new SchemaComposer();
const formatScalarMap = getJSONSchemaStringFormatScalarMap();
const rootInputTypeNameComposerMap = {
QueryInput: () => schemaComposer.Query,
MutationInput: () => schemaComposer.Mutation,
SubscriptionInput: () => schemaComposer.Subscription,
};
return visitJSONSchema(schema, {
enter(subSchema, { path, visitedSubschemaResultMap }) {
var _a, _b, _c, _d, _e, _f;
if (typeof subSchema === 'boolean' || subSchema.title === 'Any') {
const typeComposer = schemaComposer.getAnyTC(GraphQLJSON);
return subSchema
? {
input: typeComposer,
output: typeComposer,
}
: undefined;
}
if (!subSchema) {
throw new Error(`Something is wrong with ${path}`);
}
if (subSchema.type === 'array') {
if (typeof subSchema.items === 'object' && Object.keys(subSchema.items).length > 0) {
return {
// These are filled after enter
get input() {
const typeComposers = visitedSubschemaResultMap.get(subSchema.items);
return typeComposers.input.getTypePlural();
},
get output() {
const typeComposers = visitedSubschemaResultMap.get(subSchema.items);
return typeComposers.output.getTypePlural();
},
...subSchema,
};
}
if (subSchema.contains) {
// Scalars cannot be in union type
const typeComposer = schemaComposer.getAnyTC(GraphQLJSON).getTypePlural();
return {
input: typeComposer,
output: typeComposer,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
// If it doesn't have any clue
{
// const typeComposer = getGenericJSONScalar({
// schemaComposer,
// isInput: false,
// subSchema,
// validateWithJSONSchema,
// }).getTypePlural();
const typeComposer = schemaComposer.getAnyTC(GraphQLJSON).getTypePlural();
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
}
if (subSchema.pattern) {
let typeScriptType;
switch (subSchema.type) {
case 'number':
typeScriptType = 'number';
break;
case 'integer':
if (subSchema.format === 'int64') {
typeScriptType = 'bigint';
}
else {
typeScriptType = 'number';
}
break;
default:
typeScriptType = 'string';
break;
}
schemaComposer.addDirective(RegExpDirective);
schemaComposer.addDirective(TypeScriptDirective);
const typeComposer = schemaComposer.createScalarTC({
name: getValidTypeName({
schemaComposer,
isInput: false,
subSchema,
}),
directives: [
{
name: 'regexp',
args: {
pattern: subSchema.pattern,
},
},
{
name: 'typescript',
args: {
type: typeScriptType,
},
},
],
});
return {
input: typeComposer,
output: typeComposer,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
};
}
if (subSchema.const) {
const scalarTypeName = getValidTypeName({
schemaComposer,
isInput: false,
subSchema,
});
schemaComposer.addDirective(EnumDirective);
schemaComposer.addDirective(TypeScriptDirective);
schemaComposer.addDirective(ExampleDirective);
const typeComposer = schemaComposer.createEnumTC({
name: scalarTypeName,
values: {
[sanitizeNameForGraphQL(subSchema.const.toString())]: {
directives: [
{
name: 'enum',
args: {
value: JSON.stringify(subSchema.const),
},
},
],
},
},
directives: [
{
name: 'typescript',
args: {
type: JSON.stringify(subSchema.const),
},
},
{
name: 'example',
args: {
value: subSchema.const,
},
},
],
extensions: {
default: subSchema.const,
},
});
return {
input: typeComposer,
output: typeComposer,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
};
}
if (subSchema.enum && subSchema.type !== 'boolean') {
const values = {};
for (const value of subSchema.enum) {
let enumKey = sanitizeNameForGraphQL(value.toString());
if (enumKey === 'false' || enumKey === 'true' || enumKey === 'null') {
enumKey = enumKey.toUpperCase();
}
if (typeof enumKey === 'string' && enumKey.length === 0) {
enumKey = '_';
}
schemaComposer.addDirective(EnumDirective);
// Falsy values are ignored by GraphQL
// eslint-disable-next-line no-unneeded-ternary
const enumValue = value ? value : value === null || value === void 0 ? void 0 : value.toString();
const directives = [];
if (enumValue !== enumKey) {
directives.push({
name: 'enum',
args: {
value: JSON.stringify(enumValue),
},
});
}
values[enumKey] = {
directives,
value: enumValue,
};
}
const directives = [];
if ((_a = subSchema.examples) === null || _a === void 0 ? void 0 : _a.length) {
schemaComposer.addDirective(ExampleDirective);
for (const example of subSchema.examples) {
directives.push({
name: 'example',
args: {
value: example,
},
});
}
}
const typeComposer = schemaComposer.createEnumTC({
name: getValidTypeName({
schemaComposer,
isInput: false,
subSchema,
}),
values,
description: subSchema.description,
directives,
extensions: {
default: subSchema.default,
},
});
return {
input: typeComposer,
output: typeComposer,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
if (Array.isArray(subSchema.type)) {
const validTypes = subSchema.type.filter((typeName) => typeName !== 'null');
if (validTypes.length === 1) {
subSchema.type = validTypes[0];
// continue with the single type
}
else {
const typeComposer = schemaComposer.getAnyTC(GraphQLJSON);
return {
input: typeComposer,
output: typeComposer,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
}
if (subSchema.format) {
switch (subSchema.format) {
case 'byte': {
const typeComposer = schemaComposer.getAnyTC(GraphQLByte);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
default: subSchema.default,
};
}
case 'binary': {
const typeComposer = schemaComposer.getAnyTC(GraphQLFile);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
default: subSchema.default,
};
}
case 'date-time': {
const typeComposer = schemaComposer.getAnyTC(GraphQLDateTime);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'time': {
const typeComposer = schemaComposer.getAnyTC(GraphQLTime);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'email': {
const typeComposer = schemaComposer.getAnyTC(GraphQLEmailAddress);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'ipv4': {
const typeComposer = schemaComposer.getAnyTC(GraphQLIPv4);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'ipv6': {
const typeComposer = schemaComposer.getAnyTC(GraphQLIPv6);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'uri': {
const typeComposer = schemaComposer.getAnyTC(GraphQLURL);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'uuid': {
const typeComposer = schemaComposer.getAnyTC(GraphQLUUID);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'unix-time': {
const typeComposer = schemaComposer.createScalarTC(GraphQLTimestamp);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'int64': {
const typeComposer = schemaComposer.createScalarTC(GraphQLBigInt);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'int32': {
const typeComposer = schemaComposer.createScalarTC(GraphQLInt);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'decimal':
case 'float': {
const typeComposer = schemaComposer.createScalarTC(GraphQLFloat);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
default: {
const formatScalar = formatScalarMap.get(subSchema.format);
if (formatScalar) {
const typeComposer = schemaComposer.getAnyTC(formatScalar);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
}
}
}
if (subSchema.minimum === 0) {
const typeComposer = schemaComposer.getAnyTC(subSchema.type === 'integer' ? GraphQLNonNegativeInt : GraphQLNonNegativeFloat);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
else if (subSchema.minimum > 0) {
const typeComposer = schemaComposer.getAnyTC(subSchema.type === 'integer' ? GraphQLPositiveInt : GraphQLPositiveFloat);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
if (subSchema.maximum === 0) {
const typeComposer = schemaComposer.getAnyTC(subSchema.type === 'integer' ? GraphQLNonPositiveInt : GraphQLNonPositiveFloat);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
else if (subSchema.maximum < 0) {
const typeComposer = schemaComposer.getAnyTC(subSchema.type === 'integer' ? GraphQLNegativeInt : GraphQLNegativeFloat);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
if (subSchema.maximum > Number.MAX_SAFE_INTEGER ||
subSchema.minimum < Number.MIN_SAFE_INTEGER) {
const typeComposer = schemaComposer.getAnyTC(GraphQLBigInt);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
switch (subSchema.type) {
case 'boolean': {
const typeComposer = schemaComposer.getAnyTC(GraphQLBoolean);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'null': {
const typeComposer = schemaComposer.getAnyTC(GraphQLVoid);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'integer': {
const typeComposer = schemaComposer.getAnyTC(GraphQLInt);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'number': {
const typeComposer = schemaComposer.getAnyTC(GraphQLFloat);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'string': {
if (subSchema.minLength === 1 && subSchema.maxLength == null) {
const tc = schemaComposer.getAnyTC(GraphQLNonEmptyString);
return {
input: tc,
output: tc,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
if (subSchema.minLength || subSchema.maxLength) {
schemaComposer.addDirective(LengthDirective);
const typeComposer = schemaComposer.createScalarTC({
name: getValidTypeName({
schemaComposer,
isInput: false,
subSchema,
}),
description: subSchema.description,
directives: [
{
name: 'length',
args: {
min: subSchema.minLength,
max: subSchema.maxLength,
},
},
],
});
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
const typeComposer = schemaComposer.getAnyTC(GraphQLString);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
case 'object': {
switch (subSchema.title) {
case '_schema':
return {
output: schemaComposer,
...subSchema,
};
case 'Query':
return {
output: schemaComposer.Query,
...subSchema,
};
case 'Mutation':
return {
output: schemaComposer.Mutation,
...subSchema,
};
case 'Subscription':
if (path === '/properties/subscription') {
return {
output: schemaComposer.Subscription,
...subSchema,
};
}
subSchema.title = 'Subscription_';
break;
}
}
}
if (subSchema.oneOf && !subSchema.properties) {
schemaComposer.addDirective(OneOfDirective);
const input = schemaComposer.createInputTC({
name: getValidTypeName({
schemaComposer,
isInput: true,
subSchema,
}),
fields: {},
directives: [
{
name: 'oneOf',
},
],
});
const extensions = {};
const directives = [];
if ((_b = subSchema.$comment) === null || _b === void 0 ? void 0 : _b.startsWith('statusCodeOneOfIndexMap:')) {
const statusCodeOneOfIndexMapStr = subSchema.$comment.replace('statusCodeOneOfIndexMap:', '');
const statusCodeOneOfIndexMap = JSON.parse(statusCodeOneOfIndexMapStr);
if (statusCodeOneOfIndexMap) {
extensions.statusCodeOneOfIndexMap = statusCodeOneOfIndexMap;
}
}
if ((_c = subSchema.discriminator) === null || _c === void 0 ? void 0 : _c.propertyName) {
schemaComposer.addDirective(DiscriminatorDirective);
directives.push({
name: 'discriminator',
args: {
field: subSchema.discriminator.propertyName,
},
});
}
const output = schemaComposer.createUnionTC({
name: getValidTypeName({
schemaComposer,
isInput: false,
subSchema,
}),
description: subSchema.description,
types: [],
directives,
extensions,
});
return {
input,
output,
...subSchema,
};
}
if (subSchema.properties ||
subSchema.allOf ||
subSchema.anyOf ||
subSchema.additionalProperties) {
if (subSchema.title === 'Any') {
const typeComposer = schemaComposer.getAnyTC(GraphQLJSON);
return {
input: typeComposer,
output: typeComposer,
description: subSchema.description,
nullable: subSchema.nullable,
readOnly: subSchema.readOnly,
writeOnly: subSchema.writeOnly,
default: subSchema.default,
};
}
const config = {
name: getValidTypeName({
schemaComposer,
isInput: false,
subSchema,
}),
description: subSchema.description,
fields: {},
directives: [],
extensions: {
default: subSchema.default,
},
};
if ((_d = subSchema.examples) === null || _d === void 0 ? void 0 : _d.length) {
schemaComposer.addDirective(ExampleDirective);
for (const example of subSchema.examples) {
config.directives.push({
name: 'example',
args: {
value: example,
},
});
}
}
if ((_e = subSchema.discriminator) === null || _e === void 0 ? void 0 : _e.propertyName) {
schemaComposer.addDirective(DiscriminatorDirective);
}
const directives = [];
if ((_f = subSchema.examples) === null || _f === void 0 ? void 0 : _f.length) {
schemaComposer.addDirective(ExampleDirective);
for (const example of subSchema.examples) {
directives.push({
name: 'example',
args: {
value: example,
},
});
}
}
return {
input: schemaComposer.createInputTC({
name: getValidTypeName({
schemaComposer,
isInput: true,
subSchema,
}),
description: subSchema.description,
fields: {},
directives,
extensions: {
default: subSchema.default,
},
}),
output: subSchema.discriminator
? schemaComposer.createInterfaceTC({
...config,
resolveType(root) {
return root[subSchema.discriminator.propertyName];
},
directives: [
{
name: 'discriminator',
args: {
propertyName: subSchema.discriminator.propertyName,
},
},
],
})
: schemaComposer.createObjectTC(config),
...subSchema,
...(subSchema.properties ? { properties: { ...subSchema.properties } } : {}),
...(subSchema.allOf ? { allOf: [...subSchema.allOf] } : {}),
...(subSchema.additionalProperties
? {
additionalProperties: subSchema.additionalProperties === true
? true
: { ...subSchema.additionalProperties },
}
: {}),
};
}
return subSchema;
},
leave(subSchemaAndTypeComposers, { path }) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
// const validateWithJSONSchema = getValidateFnForSchemaPath(ajv, path, schema);
const subSchemaOnly = {
...subSchemaAndTypeComposers,
input: undefined,
output: undefined,
};
if (subSchemaAndTypeComposers.oneOf && !subSchemaAndTypeComposers.properties) {
const isPlural = subSchemaAndTypeComposers.oneOf.some(({ output }) => 'ofType' in output);
if (isPlural) {
const { input, output } = getUnionTypeComposers({
schemaComposer,
typeComposersList: subSchemaAndTypeComposers.oneOf.map(({ input, output }) => ({
input: input.ofType || input,
output: output.ofType || output,
})),
subSchemaAndTypeComposers,
logger,
});
return {
input: input.getTypePlural(),
output: output.getTypePlural(),
nullable: subSchemaAndTypeComposers.nullable,
default: subSchemaAndTypeComposers.default,
readOnly: subSchemaAndTypeComposers.readOnly,
writeOnly: subSchemaAndTypeComposers.writeOnly,
};
}
return getUnionTypeComposers({
schemaComposer,
typeComposersList: subSchemaAndTypeComposers.oneOf,
subSchemaAndTypeComposers,
logger,
});
}
const fieldMap = {};
const inputFieldMap = {};
let isList = false;
if (subSchemaAndTypeComposers.allOf) {
let ableToUseGraphQLInputObjectType = true;
for (const maybeTypeComposers of subSchemaAndTypeComposers.allOf) {
let { input: inputTypeComposer, output: outputTypeComposer } = maybeTypeComposers;
if (inputTypeComposer instanceof ListComposer) {
isList = true;
inputTypeComposer = inputTypeComposer.ofType;
}
if (outputTypeComposer instanceof ListComposer) {
isList = true;
outputTypeComposer = outputTypeComposer.ofType;
}
if (inputTypeComposer instanceof ScalarTypeComposer ||
inputTypeComposer instanceof EnumTypeComposer) {
ableToUseGraphQLInputObjectType = false;
}
else {
const inputTypeElemFieldMap = inputTypeComposer.getFields();
for (const fieldName in inputTypeElemFieldMap) {
const field = inputTypeElemFieldMap[fieldName];
inputFieldMap[fieldName] = field;
}
}
if (isSomeInputTypeComposer(outputTypeComposer)) {
schemaComposer.addDirective(ResolveRootDirective);
fieldMap[outputTypeComposer.getTypeName()] = {
type: outputTypeComposer,
directives: [
{
name: 'resolveRoot',
},
],
};
}
else if (outputTypeComposer instanceof UnionTypeComposer) {
const outputTCElems = outputTypeComposer.getTypes();
for (const outputTCElem of outputTCElems) {
const outputTypeElemFieldMap = outputTCElem.getFields();
for (const fieldName in outputTypeElemFieldMap) {
const field = outputTypeElemFieldMap[fieldName];
fieldMap[fieldName] = field;
}
}
}
else {
if (outputTypeComposer instanceof InterfaceTypeComposer) {
subSchemaAndTypeComposers.output.addInterface(outputTypeComposer);
}
const typeElemFieldMap = outputTypeComposer.getFields();
for (const fieldName in typeElemFieldMap) {
const field = typeElemFieldMap[fieldName];
fieldMap[fieldName] = field;
}
}
}
if ((_a = subSchemaAndTypeComposers.examples) === null || _a === void 0 ? void 0 : _a.length) {
schemaComposer.addDirective(ExampleDirective);
const directives = subSchemaAndTypeComposers.output.getDirectives() || [];
for (const example of subSchemaAndTypeComposers.examples) {
directives.push({
name: 'example',
args: {
value: example,
},
});
}
subSchemaAndTypeComposers.output.setDirectives(directives);
}
subSchemaAndTypeComposers.output.addFields(fieldMap);
subSchemaAndTypeComposers.output.setExtensions({
// validateWithJSONSchema,
default: subSchemaAndTypeComposers.default,
});
if (ableToUseGraphQLInputObjectType) {
subSchemaAndTypeComposers.input.addFields(inputFieldMap);
if ((_b = subSchemaAndTypeComposers.examples) === null || _b === void 0 ? void 0 : _b.length) {
schemaComposer.addDirective(ExampleDirective);
const directives = subSchemaAndTypeComposers.input.getDirectives() || [];
for (const example of subSchemaAndTypeComposers.examples) {
directives.push({
name: 'example',
args: {
value: example,
},
});
}
subSchemaAndTypeComposers.input.setDirectives(directives);
}
subSchemaAndTypeComposers.input.setExtensions({
default: subSchemaAndTypeComposers.default,
});
}
else {
subSchemaAndTypeComposers.input = schemaComposer.getAnyTC(GraphQLJSON);
}
}
if (subSchemaAndTypeComposers.anyOf) {
// It should not have `required` because it is `anyOf` not `allOf`
let ableToUseGraphQLInputObjectType = true;
for (const typeComposers of subSchemaAndTypeComposers.anyOf) {
let { input: inputTypeComposer, output: outputTypeComposer } = typeComposers;
if (inputTypeComposer instanceof ListComposer ||
outputTypeComposer instanceof ListComposer) {
isList = true;
inputTypeComposer = inputTypeComposer.ofType;
outputTypeComposer = outputTypeComposer.ofType;
}
if (inputTypeComposer instanceof ScalarTypeComposer ||
inputTypeComposer instanceof EnumTypeComposer) {
ableToUseGraphQLInputObjectType = false;
}
else {
const inputTypeElemFieldMap = inputTypeComposer.getFields();
for (const fieldName in inputTypeElemFieldMap) {
// In case of conflict set it to JSON
// TODO: But instead we can convert that field into a oneOf of all possible types
if (inputFieldMap[fieldName]) {
let existingType = inputFieldMap[fieldName].type;
if (typeof existingType === 'function') {
existingType = existingType();
}
let newType = inputTypeElemFieldMap[fieldName].type;
if (typeof newType === 'function') {
newType = newType();
}
const newTypeName = newType.getTypeName().replace('!', '');
const existingTypeName = existingType.getTypeName().replace('!', '');
if (existingTypeName !== newTypeName) {
if (newTypeName !== 'JSON') {
inputFieldMap[fieldName] = {
type: schemaComposer.getAnyTC(GraphQLJSON),
};
}
if (existingTypeName === 'JSON') {
const field = inputTypeElemFieldMap[fieldName];
inputFieldMap[fieldName] = isNonNullType(field.type.getType())
? {
...field,
type: () => field.type.ofType,
}
: field;
}
}
}
else {
const field = inputTypeElemFieldMap[fieldName];
inputFieldMap[fieldName] = isNonNullType(field.type.getType())
? {
...field,
type: () => field.type.ofType,
}
: field;
}
}
}
if (outputTypeComposer instanceof ScalarTypeComposer) {
const typeName = outputTypeComposer.getTypeName();
// In case of conflict set it to JSON
// TODO: But instead we can convert that field into a union of all possible types
if (fieldMap[typeName]) {
const existingTypeName = (_d = (_c = fieldMap[typeName]) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.getTypeName();
if (existingTypeName === 'JSON') {
schemaComposer.addDirective(ResolveRootDirective);
fieldMap[typeName] = {
type: outputTypeComposer,
directives: [
{
name: 'resolveRoot',
},
],
};
}
if (typeName !== 'JSON' && existingTypeName !== typeName) {
fieldMap[typeName] = {
type: schemaComposer.getAnyTC(GraphQLJSON),
};
}
}
else {
schemaComposer.addDirective(ResolveRootDirective);
fieldMap[typeName] = {
type: outputTypeComposer,
directives: [
{
name: 'resolveRoot',
},
],
};
}
}
else {
const typeElemFieldMap = outputTypeComposer.getFields();
for (const fieldName in typeElemFieldMap) {
// In case of conflict set it to JSON
// TODO: But instead we can convert that field into a union of all possible types
const field = typeElemFieldMap[fieldName];
const existingField = fieldMap[fieldName];
fieldMap[fieldName] = {
...field,
type: () => {
const fieldType = field.type.getType();
const namedType = getNamedType(fieldType);
if (existingField) {
const existingFieldType = existingField.type();
const existingNamedType = getNamedType(existingFieldType);
const existingTypeName = existingNamedType.name;
const newTypeName = namedType.name;
if (existingTypeName !== 'JSON' &