src/components/operations/operation-details/ko/runtime/graphql-documentation/graphql-doc-service.ts (176 lines of code) (raw):

import * as GraphQL from "graphql"; import * as ko from "knockout"; import { GraphqlTypesForDocumentation, TypeOfApi, GraphqlTypes, GraphqlCustomFieldNames } from "../../../../../../constants"; import { Api } from "../../../../../../models/api"; import { ApiService } from "../../../../../../services/apiService"; import { RouteHelper } from "../../../../../../routing/routeHelper"; import { Router } from "@paperbits/common/routing"; import * as _ from "lodash"; export class GraphDocService { public currentSelected: ko.Observable<object>; public docGraphs: { query: ko.Observable<object>, mutation: ko.Observable<object>, subscription: ko.Observable<object>, objectType: ko.Observable<object>, inputObjectType: ko.Observable<object>, enumType: ko.Observable<object>, scalarType: ko.Observable<object>, unionType: ko.Observable<object>, interfaceType: ko.Observable<object> }; public content: ko.Observable<string>; public api: ko.Observable<Api>; public selectedApiName: ko.Observable<string>; public readonly availableTypes: ko.ObservableArray<string>; public readonly typeIndexer: ko.Observable<object>; constructor( private readonly apiService: ApiService, public readonly router: Router, public readonly routeHelper: RouteHelper ) { this.onRouteChangeGraph = this.onRouteChangeGraph.bind(this); this.currentSelected = ko.observable<object>(null); this.docGraphs = { query: ko.observable<object>(), mutation: ko.observable<object>(), subscription: ko.observable<object>(), objectType: ko.observable<object>(), inputObjectType: ko.observable<object>(), enumType: ko.observable<object>(), scalarType: ko.observable<object>(), unionType: ko.observable<object>(), interfaceType: ko.observable<object>() }; this.api = ko.observable<Api>(); this.selectedApiName = ko.observable<string>(); this.typeIndexer = ko.observable(); this.availableTypes = ko.observableArray<string>(); this.content = ko.observable<string>(); } public async initialize(): Promise<void> { this.selectedApiName(this.routeHelper.getApiName()); if (this.selectedApiName()) { await this.defaultValues(); this.router.addRouteChangeListener(this.onRouteChangeGraph); } } private async getApi(apiName: string): Promise<void> { const api = await this.apiService.getApi(`apis/${apiName}`); this.api(api); } private async defaultValues(): Promise<void> { await this.getApi(this.selectedApiName()); if (this.api().type === TypeOfApi.graphQL) { const graphQLSchema = await this.apiService.getGQLSchema(this.api().id); if (!graphQLSchema) { return; } this.content(graphQLSchema.graphQLSchema); const schema = GraphQL.buildSchema(this.content(), { commentDescriptions: true }); this.docGraphs.query(schema.getQueryType()?.getFields()); this.docGraphs.mutation(schema.getMutationType()?.getFields()); this.docGraphs.subscription(schema.getSubscriptionType()?.getFields()); const typeMap = schema.getTypeMap(); this.docGraphs.objectType(_.pickBy(typeMap, (t) => { return (t instanceof GraphQL.GraphQLObjectType); })); this.docGraphs.inputObjectType(_.pickBy(typeMap, (t) => { return (t instanceof GraphQL.GraphQLInputObjectType); })); this.docGraphs.enumType(_.pickBy(typeMap, (t) => { return (t instanceof GraphQL.GraphQLEnumType); })); this.docGraphs.scalarType(_.pickBy(typeMap, (t) => { return (t instanceof GraphQL.GraphQLScalarType); })); this.docGraphs.unionType(_.pickBy(typeMap, (t) => { return (t instanceof GraphQL.GraphQLUnionType); })); this.docGraphs.interfaceType(_.pickBy(typeMap, (t) => { return (t instanceof GraphQL.GraphQLInterfaceType); })); _.forEach(this.docGraphs, (value, key) => { const valueData = value(); this.addingNewFields(valueData, key); if (key == GraphqlTypes.query || key == GraphqlTypes.subscription || key == GraphqlTypes.mutation) { value(this.sortingAlphabetically(valueData)); } }); for (const type in GraphqlTypesForDocumentation) { if (_.size(this.docGraphs[type]()) > 0) { const selectedCollection = this.docGraphs[type](); const selectedGraph = selectedCollection[Object.keys(selectedCollection)[0]]; this.select(selectedGraph); break; } } this.getAvailableTypes(); } } public select(graph: object): void { const selected = this.currentSelected(); if (selected) { selected[GraphqlCustomFieldNames.selected](false); } graph[GraphqlCustomFieldNames.selected](true); this.currentSelected(graph); } public async onRouteChangeGraph(): Promise<void> { const apiName = this.routeHelper.getApiName(); const graphType = this.routeHelper.getGraphType(); const graphName = this.routeHelper.getGraphName(); if (!apiName) return; if (apiName !== this.selectedApiName()) { this.selectedApiName(apiName); await this.defaultValues(); } if (!(graphType && graphName)) return; const graph = this.docGraphs[graphType]()[graphName]; this.select(graph); } private sortingAlphabetically(collection) { return _(collection).toPairs().sortBy(0).fromPairs().value(); } private addingNewFields(collection: object, type: string) { _.forEach(collection, (value) => { if (type == GraphqlTypes.query || type == GraphqlTypes.subscription || type == GraphqlTypes.mutation) { value[GraphqlCustomFieldNames.selected] = ko.observable<boolean>(false); } value[GraphqlCustomFieldNames.type] = ko.observable<string>(type); }); } public indexCollectionFromType(type: GraphQL.GraphQLOutputType | GraphQL.GraphQLInputType): string { while ((type instanceof GraphQL.GraphQLList) || (type instanceof GraphQL.GraphQLNonNull)) { type = type.ofType; } if (type instanceof GraphQL.GraphQLObjectType) { return "objectType"; } if (type instanceof GraphQL.GraphQLInputObjectType) { return "inputObjectType"; } if (type instanceof GraphQL.GraphQLEnumType) { return "enumType"; } if (type instanceof GraphQL.GraphQLScalarType) { return "scalarType"; } if (type instanceof GraphQL.GraphQLUnionType) { return "unionType"; } return "interfaceType"; } private getAvailableTypes() { const indexer = {}; const availableTypes = []; _.each(GraphqlTypesForDocumentation, (v, k) => { if (_.size(this.docGraphs[k]()) > 0 && (k == GraphqlTypes.query || k == GraphqlTypes.subscription || k == GraphqlTypes.mutation)) { indexer[v] = k; availableTypes.push(v); } }); this.typeIndexer(indexer); this.availableTypes(availableTypes); } }