src/components/operations/operation-details/ko/runtime/graphql-utilities/graphql-node-models.ts (167 lines of code) (raw):

import { Utils } from "../../../../../../utils"; import * as GraphQL from "graphql"; import * as ko from "knockout"; import * as _ from "lodash"; export function getType(type: GraphQL.GraphQLOutputType | GraphQL.GraphQLInputType) { while ((type instanceof GraphQL.GraphQLList) || (type instanceof GraphQL.GraphQLNonNull)) { type = type.ofType; } return type; } function isNonNull(type: GraphQL.GraphQLOutputType | GraphQL.GraphQLInputType) { while (type instanceof GraphQL.GraphQLList) { type = type.ofType; } return GraphQL.isNonNullType(type); } export abstract class GraphQLTreeNode { public id: string = Utils.getBsonObjectId(); public label: ko.Observable<string>; public selected: ko.Observable<boolean>; public data: GraphQL.GraphQLField<any, any> | GraphQL.GraphQLInputField; public children: ko.ObservableArray<GraphQLTreeNode> = ko.observableArray([]); public isRequired: ko.Observable<boolean>; public generateDocument: () => void; public parent: ko.Observable<GraphQLTreeNode>; constructor(label: string, generateDocument: () => void, parent: GraphQLTreeNode) { this.label = ko.observable(label); this.selected = ko.observable(false); this.generateDocument = generateDocument; this.parent = ko.observable(parent); } public isInputNode(): boolean { return this instanceof GraphQLInputTreeNode; } public isScalarType(): boolean { return getType(this.data.type) instanceof GraphQL.GraphQLScalarType; } public isEnumType(): boolean { return getType(this.data.type) instanceof GraphQL.GraphQLEnumType; } public toggle(value?: boolean, regenerateDoc = true): void { let preCondition: boolean; if (value === true || value === false) { preCondition = !value; } else { preCondition = this.selected(); } if (!preCondition) { this.selected(true); this.generateNodes(); } else { this.selected(false); } if (regenerateDoc) { this.generateDocument(); } } public clear(): void { this.toggle(false, false); for (const child of this.children()) { child.clear(); } } public hasActiveChild(): boolean { return !!this.children().find(c => c.selected()); } public abstract generateNodes(): void; } export class GraphQLOutputTreeNode extends GraphQLTreeNode { public data: GraphQL.GraphQLField<any, any>; public level: number; public variables: { name: string, type: string }[] = []; constructor(label: string, data: GraphQL.GraphQLField<any, any>, generateDocument: () => void, parent: GraphQLTreeNode) { super(label, generateDocument, parent); this.children([]); this.data = data; this.isRequired = ko.observable(isNonNull(this.data.type)); } public generateNodes() { const args = this.data?.args || []; const type = getType(this.data?.type) || this.data; const argsNodes: GraphQLInputTreeNode[] = []; const fieldNodes: GraphQLOutputTreeNode[] = []; if (this.children().length === 0) { for (const arg of args) { const inputTreeeNode = new GraphQLInputTreeNode(arg.name, arg, this.generateDocument, this); argsNodes.push(inputTreeeNode); } if (type instanceof GraphQL.GraphQLObjectType || type instanceof GraphQL.GraphQLInterfaceType) { const fields = type.getFields(); for (const name in fields) { fieldNodes.push(new GraphQLOutputTreeNode(name, fields[name], this.generateDocument, this)); } } if (type instanceof GraphQL.GraphQLUnionType) { const subtypes = type.getTypes(); _.forEach(subtypes, (subtype) => { fieldNodes.push(new GraphQLOutputTreeNode(subtype["name"], subtype, this.generateDocument, this)); }); } this.children([...argsNodes.sort((a, b) => a.label().localeCompare(b.label())), ...fieldNodes.sort((a, b) => a.label().localeCompare(b.label()))]); } return this; } } export class GraphQLInputTreeNode extends GraphQLTreeNode { public children: ko.ObservableArray<GraphQLInputTreeNode>; public data: GraphQL.GraphQLInputField; public inputValue?: ko.Observable<string>; public options?: ko.ObservableArray<string>; constructor(label: string, data: GraphQL.GraphQLInputField, generateDocument: () => void, parent: GraphQLTreeNode) { super(label, generateDocument, parent); this.children = ko.observableArray([]); this.data = data; this.isRequired = ko.observable(isNonNull(data.type)); if (this.isRequired()) { this.toggle(true, false); } this.inputValue = ko.observable(""); const type = getType(data.type); if (type instanceof GraphQL.GraphQLEnumType) { this.options = ko.observableArray(type.getValues().map(v => v.name)); if (this.options().length > 0) { this.inputValue(this.options()[0]); } } else if (type instanceof GraphQL.GraphQLScalarType) { switch (type.name) { case "String": this.inputValue(`"string"`); break; case "Int": this.inputValue("10"); break; case "Float": this.inputValue("0.0"); break; case "Boolean": this.inputValue("false"); break; case "ID": this.inputValue(`"id"`); break; default: this.inputValue(`""`); break; } } } public changeInput(): void { this.generateDocument(); } public generateNodes(): void { const data = this.data; const type = getType(data.type); if (type instanceof GraphQL.GraphQLInputObjectType && this.children().length === 0) { const fields = type.getFields(); for (const name in fields) { const inputTreeNode = new GraphQLInputTreeNode(name, fields[name], this.generateDocument, this); this.children.push(inputTreeNode); } } } }