@dossierhq/graphql
Version:
A library for creating GraphQL servers with Dossier.
115 lines • 4.18 kB
JavaScript
/// <reference types="./TypeRepository.d.ts" />
import { GraphQLEnumType, isEnumType, isInputType, isInterfaceType, isOutputType, } from 'graphql';
import { toAdminComponentInputTypeName, toAdminTypeName, toEnumName } from './NameGenerator.js';
export class TypeRepository {
#types = [];
getTypes() {
return this.#types;
}
addType(type) {
if (this.#types.find((it) => it.name === type.name)) {
throw new Error(`Type with name ${type.name} already exists`);
}
this.#types.push(type);
}
getType(name) {
const type = this.#types.find((x) => x.name === name);
if (!type) {
throw new Error(`Type with name ${name} doesn't exist`);
}
return type;
}
getOutputType(name) {
const type = this.getType(name);
if (isOutputType(type)) {
return type;
}
throw new Error(`Type ${name} is not an output type`);
}
getEnumType(name) {
const type = this.getType(name);
if (isEnumType(type)) {
return type;
}
throw new Error(`Type ${name} is not an enum type`);
}
getInputType(name) {
const type = this.getType(name);
if (isInputType(type)) {
return type;
}
throw new Error(`Type ${name} is not an input type`);
}
getInterface(name) {
const type = this.getType(name);
if (isInterfaceType(type)) {
return type;
}
throw new Error(`Type ${name} is not an interface`);
}
getInterfaces(...names) {
return names.map((name) => this.getInterface(name));
}
getOrCreateEntityUnion(isAdmin, names) {
if (names.length === 0) {
return this.getOutputType(toAdminTypeName('Entity', isAdmin));
}
// Remove duplicates, sort alphabetically
const filteredNames = [...new Set(names)];
filteredNames.sort();
if (filteredNames.length === 1) {
return this.getOutputType(toAdminTypeName(filteredNames[0], isAdmin));
}
const enumName = toEnumName(filteredNames, isAdmin);
const existingEnum = this.#types.find((x) => x.name === enumName);
if (existingEnum) {
if (isOutputType(existingEnum)) {
return existingEnum;
}
throw new Error(`Type ${enumName} is not an output type`);
}
const enumValues = {};
filteredNames.forEach((name) => (enumValues[toAdminTypeName(name, isAdmin)] = {}));
const enumType = new GraphQLEnumType({
name: enumName,
values: enumValues,
});
this.addType(enumType);
return enumType;
}
getOrCreateValueUnion(isAdmin, names) {
if (names.length === 0) {
return this.getOutputType(toAdminTypeName('Component', isAdmin));
}
// Remove duplicates, sort alphabetically
const filteredNames = [...new Set(names)];
filteredNames.sort();
if (filteredNames.length === 1) {
return this.getOutputType(toAdminTypeName(filteredNames[0], isAdmin));
}
const enumName = `_${toAdminTypeName(filteredNames.join('Or'), isAdmin)}`;
const existingEnum = this.#types.find((x) => x.name === enumName);
if (existingEnum) {
if (isOutputType(existingEnum)) {
return existingEnum;
}
throw new Error(`Type ${enumName} is not an output type`);
}
const enumValues = {};
filteredNames.forEach((name) => (enumValues[toAdminTypeName(name, isAdmin)] = {}));
const enumType = new GraphQLEnumType({
name: enumName,
values: enumValues,
});
this.addType(enumType);
return enumType;
}
getValueInputType(names) {
const uniqueNames = [...new Set(names)];
if (uniqueNames.length !== 1) {
return null; //There's no support for polymorphism on input types
}
return this.getInputType(toAdminComponentInputTypeName(uniqueNames[0]));
}
}
//# sourceMappingURL=TypeRepository.js.map