/**
* Copyright (c) 2021 GraphQL Contributors.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {
ExplorerFieldDef,
useExplorerContext,
useSchemaContext,
} from '@graphiql/react';
import {
GraphQLEnumValue,
GraphQLInterfaceType,
GraphQLNamedType,
GraphQLObjectType,
isEnumType,
isInterfaceType,
isNamedType,
isObjectType,
isUnionType,
} from 'graphql';
import React, { ReactNode, useState } from 'react';
import Argument from './Argument';
import DefaultValue from './DefaultValue';
import FieldLink from './FieldLink';
import MarkdownContent from './MarkdownContent';
import TypeLink from './TypeLink';
export default function TypeDoc() {
const { schema } = useSchemaContext({ nonNull: true });
const { explorerNavStack } = useExplorerContext({ nonNull: true });
const [showDeprecated, setShowDeprecated] = useState(false);
const navItem = explorerNavStack[explorerNavStack.length - 1];
const type = navItem.def;
if (!schema || !isNamedType(type)) {
return null;
}
let typesTitle: string | null = null;
let types: readonly (GraphQLObjectType | GraphQLInterfaceType)[] = [];
if (isUnionType(type)) {
typesTitle = 'possible types';
types = schema.getPossibleTypes(type);
} else if (isInterfaceType(type)) {
typesTitle = 'implementations';
types = schema.getPossibleTypes(type);
} else if (isObjectType(type)) {
typesTitle = 'implements';
types = type.getInterfaces();
}
let typesDef;
if (types && types.length > 0) {
typesDef = (
{typesTitle}
{types.map(subtype => (
))}
);
}
// InputObject and Object
let fieldsDef;
let deprecatedFieldsDef;
if (type && 'getFields' in type) {
const fieldMap = type.getFields();
const fields = Object.keys(fieldMap).map(name => fieldMap[name]);
fieldsDef = (
fields
{fields
.filter(field => !field.deprecationReason)
.map(field => (
))}
);
const deprecatedFields = fields.filter(field =>
Boolean(field.deprecationReason),
);
if (deprecatedFields.length > 0) {
deprecatedFieldsDef = (
deprecated fields
{!showDeprecated ? (
) : (
deprecatedFields.map(field => (
))
)}
);
}
}
let valuesDef: ReactNode;
let deprecatedValuesDef: ReactNode;
if (isEnumType(type)) {
const values = type.getValues();
valuesDef = (
values
{values
.filter(value => Boolean(!value.deprecationReason))
.map(value => (
))}
);
const deprecatedValues = values.filter(value =>
Boolean(value.deprecationReason),
);
if (deprecatedValues.length > 0) {
deprecatedValuesDef = (
deprecated values
{!showDeprecated ? (
) : (
deprecatedValues.map(value => (
))
)}
);
}
}
return (
{isObjectType(type) && typesDef}
{fieldsDef}
{deprecatedFieldsDef}
{valuesDef}
{deprecatedValuesDef}
{!isObjectType(type) && typesDef}
);
}
type FieldProps = {
type: GraphQLNamedType;
field: ExplorerFieldDef;
};
function Field({ field }: FieldProps) {
return (
{'args' in field &&
field.args &&
field.args.length > 0 && [
'(',
{field.args
.filter(arg => !arg.deprecationReason)
.map(arg => (
))}
,
')',
]}
{': '}
{field.description && (
)}
{'deprecationReason' in field && field.deprecationReason && (
)}
);
}
type EnumValueProps = {
value: GraphQLEnumValue;
};
function EnumValue({ value }: EnumValueProps) {
return (
{value.name}
{value.deprecationReason && (
)}
);
}