import { DocumentNode , OperationDefinitionNode , FragmentDefinitionNode , SchemaDefinitionNode , DirectiveDefinitionNode , SchemaExtensionNode , ScalarTypeDefinitionNode , ObjectTypeDefinitionNode , InterfaceTypeDefinitionNode , UnionTypeDefinitionNode , EnumTypeDefinitionNode , InputObjectTypeDefinitionNode , ScalarTypeExtensionNode , ObjectTypeExtensionNode , InterfaceTypeExtensionNode , UnionTypeExtensionNode , EnumTypeExtensionNode , EnumValueDefinitionNode , InputObjectTypeExtensionNode , DefinitionNode , FieldDefinitionNode , NamedTypeNode , ListTypeNode , NonNullTypeNode , DirectiveNode , ArgumentNode , VariableNode , IntValueNode , FloatValueNode , StringValueNode , BooleanValueNode , NullValueNode , EnumValueNode , ListValueNode , ObjectValueNode , } from "graphql/language/ast" ; import * as gql from "graphql/language/parser" ; export function parse ( p1 ) { const doc = gql . parse ( p1 ) ; return new Schema ( doc ) ; } export class Schema { constructor ( private readonly doc ) { } get definitions ( ) : Definition [ ] { return this . doc . definitions . map ( ( def ) => { switch ( def . kind ) { case "SchemaDefinition" : return new SchemaDefinition ( def ) ; case "ScalarTypeDefinition" : return new ScalarTypeDefinition ( def ) ; case "ObjectTypeDefinition" : return new ObjectTypeDefinition ( def ) ; case "InterfaceTypeDefinition" : return new InterfaceTypeDefinition ( def ) ; case "UnionTypeDefinition" : return new UnionTypeDefinition ( def ) ; case "EnumTypeDefinition" : return new EnumTypeDefinition ( def ) ; case "InputObjectTypeDefinition" : return new InputObjectTypeDefinition ( def ) ; case "DirectiveDefinition" : return new DirectiveDefinition ( def ) ; case "SchemaExtension" : return new SchemaExtension ( def ) ; case "ScalarTypeExtension" : return new ScalarTypeExtension ( def ) ; case "ObjectTypeExtension" : return new ObjectTypeExtension ( def ) ; case "InterfaceTypeExtension" : return new InterfaceTypeExtension ( def ) ; case "UnionTypeExtension" : return new UnionTypeExtension ( def ) ; case "EnumTypeExtension" : return new EnumTypeExtension ( def ) ; case "InputObjectTypeExtension" : return new InputObjectTypeExtension ( def ) ; case "OperationDefinition" : return new OperationDefinition ( def ) ; case "FragmentDefinition" : return new FragmentDefinition ( def ) ; } } ) ; } get objects ( ) : ObjectTypeDefinition [ ] { let arr = [ ] ; for ( let def of this . definitions ) { if ( def instanceof ObjectTypeDefinition ) { arr . push ( def ) ; } } return arr ; } findObject ( fn ) { for ( let object of this . objects ) { if ( fn ( object ) ) { return object ; } } } get enums ( ) : EnumTypeDefinition [ ] { let arr = [ ] ; for ( let def of this . definitions ) { if ( def instanceof EnumTypeDefinition ) { arr . push ( def ) ; } } return arr ; } version ( ) { for ( let obj of this . objects ) { for ( let field of obj . fields ) { if ( field . type . named ( ) !== "ID" ) { continue ; } for ( let directive of field . directives ) { if ( directive . name === "id" ) { return "1.1" ; } } return "1.0" ; } } return "1.1" ; } } interface Definition { kind : DefinitionNode [ "kind" ] ; } export class SchemaDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class ScalarTypeDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class ObjectTypeDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } get name ( ) : string { return this . def . name . value ; } get dbname ( ) : string { if ( ! this . def . directives ) { return this . name ; } const db = this . def . directives . find ( ( d ) => d . name . value === "db" ) ; if ( ! db || ! db . arguments ) { return this . name ; } const arg = db . arguments . find ( ( arg ) => arg . name . value === "name" ) ; if ( ! arg || ! arg . value || arg . value . kind !== "StringValue" ) { return this . name ; } return arg . value . value ; } get fields ( ) : FieldDefinition [ ] { if ( ! this . def . fields ) return [ ] ; return this . def . fields . map ( ( field ) => new FieldDefinition ( this , field ) ) ; } } export class InterfaceTypeDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class UnionTypeDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class EnumTypeDefinition { constructor ( private readonly def ) { } get name ( ) { return this . def . name . value ; } get dbname ( ) : string { if ( ! this . def . directives ) { return this . name ; } const db = this . def . directives . find ( ( d ) => d . name . value === "db" ) ; if ( ! db || ! db . arguments ) { return this . name ; } const arg = db . arguments . find ( ( arg ) => arg . name . value === "name" ) ; if ( ! arg || ! arg . value || arg . value . kind !== "StringValue" ) { return this . name ; } return arg . value . value ; } get kind ( ) { return this . def . kind ; } get values ( ) : EnumValueDefinition [ ] { let arr = [ ] ; if ( ! this . def . values ) { return arr ; } for ( let value of this . def . values ) { arr . push ( new EnumValueDefinition ( value ) ) ; } return arr ; } } export class EnumValueDefinition { constructor ( private readonly def ) { } get name ( ) { return this . def . name . value ; } } export class InputObjectTypeDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class DirectiveDefinition { constructor ( private readonly def ) { } get name ( ) : string { return this . def . name . value ; } get kind ( ) { return this . def . kind ; } } export class SchemaExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class ScalarTypeExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class ObjectTypeExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class InterfaceTypeExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class UnionTypeExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class EnumTypeExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class InputObjectTypeExtension { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class OperationDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class FragmentDefinition { constructor ( private readonly def ) { } get kind ( ) { return this . def . kind ; } } export class FieldDefinition { constructor ( private readonly modelDef , private readonly def ) { } get parent ( ) { return this . modelDef ; } get name ( ) { return this . def . name . value ; } get dbname ( ) : string { if ( ! this . def . directives ) { return this . name ; } const db = this . def . directives . find ( ( d ) => d . name . value === "db" ) ; if ( ! db || ! db . arguments ) { return this . name ; } const arg = db . arguments . find ( ( arg ) => arg . name . value === "name" ) ; if ( ! arg || ! arg . value || arg . value . kind !== "StringValue" ) { return this . name ; } return arg . value . value ; } get type ( ) : Type { switch ( this . def . type . kind ) { case "ListType" : return new ListType ( this . def . type ) ; case "NamedType" : return new NamedType ( this . def . type ) ; case "NonNullType" : return new NonNullType ( this . def . type ) ; } } get directives ( ) : Directive [ ] { if ( ! this . def . directives ) return [ ] ; return this . def . directives . map ( ( dir ) => new Directive ( dir ) ) ; } optional ( ) { return this . type . optional ( ) ; } findDirective ( fn ) { for ( let d of this . directives ) { if ( fn ( d ) ) { return d ; } } } } export type Type = NamedType | ListType | NonNullType ; function isReference ( name ) { switch ( name ) { case "ID" : case "UUID" : case "String" : case "Int" : case "Float" : case "Boolean" : case "DateTime" : case "Json" : return false ; default : return true ; } } export class NamedType { constructor ( private readonly def ) { } get name ( ) : string { return this . def . name . value ; } get kind ( ) : "NamedType" { return this . def . kind ; } list ( ) { return false ; } optional ( ) { return true ; } named ( ) { return this . name ; } toString ( ) { return this . def . name . value ; } isReference ( ) { return isReference ( this . named ( ) ) ; } } export class ListType { constructor ( private readonly def ) { } get kind ( ) : "ListType" { return this . def . kind ; } inner ( ) { switch ( this . def . type . kind ) { case "ListType" : return new ListType ( this . def . type ) ; case "NamedType" : return new NamedType ( this . def . type ) ; case "NonNullType" : return new NonNullType ( this . def . type ) ; } } optional ( ) { return true ; } list ( ) { return true ; } named ( ) { return this . inner ( ) . named ( ) ; } toString ( ) { return "[" + this . inner ( ) . toString ( ) + "]" ; } isReference ( ) { return isReference ( this . named ( ) ) ; } } export class NonNullType { constructor ( private readonly def ) { } get kind ( ) : "NonNullType" { return this . def . kind ; } inner ( ) { switch ( this . def . type . kind ) { case "ListType" : return new ListType ( this . def . type ) ; case "NamedType" : return new NamedType ( this . def . type ) ; } } optional ( ) { return false ; } list ( ) { return this . inner ( ) . list ( ) ; } named ( ) { return this . inner ( ) . named ( ) ; } toString ( ) { return this . inner ( ) . toString ( ) + "!" ; } isReference ( ) { return isReference ( this . named ( ) ) ; } } export class Directive { constructor ( private readonly def ) { } get name ( ) { return this . def . name . value ; } get arguments ( ) { if ( ! this . def . arguments ) return [ ] ; return this . def . arguments . map ( ( arg ) => new Argument ( arg ) ) ; } findArgument ( fn ) { for ( let arg of this . arguments ) { if ( fn ( arg ) ) { return arg ; } } } } export class Argument { constructor ( private readonly def ) { } get name ( ) { return this . def . name . value ; } get value ( ) : Value { switch ( this . def . value . kind ) { case "Variable" : return new Variable ( this . def . value ) ; case "IntValue" : return new IntValue ( this . def . value ) ; case "FloatValue" : return new FloatValue ( this . def . value ) ; case "StringValue" : return new StringValue ( this . def . value ) ; case "BooleanValue" : return new BooleanValue ( this . def . value ) ; case "NullValue" : return new NullValue ( this . def . value ) ; case "EnumValue" : return new EnumValue ( this . def . value ) ; case "ListValue" : return new ListValue ( this . def . value ) ; case "ObjectValue" : return new ObjectValue ( this . def . value ) ; } } } export type Value = Variable | IntValue | FloatValue | StringValue | BooleanValue | NullValue | EnumValue | ListValue | ObjectValue ; export class Variable { constructor ( private readonly def ) { } get kind ( ) : "Variable" { return this . def . kind ; } get name ( ) : string { return this . def . name . value ; } } export class IntValue { constructor ( private readonly def ) { } get kind ( ) : "IntValue" { return this . def . kind ; } get value ( ) : number { return parseInt ( this . def . value , 10 ) ; } } export class FloatValue { constructor ( private readonly def ) { } get kind ( ) : "FloatValue" { return this . def . kind ; } get value ( ) : number { return parseFloat ( this . def . value ) ; } } export class StringValue { constructor ( private readonly def ) { } get kind ( ) : "StringValue" { return this . def . kind ; } get value ( ) : string { return this . def . value ; } } export class BooleanValue { constructor ( private readonly def ) { } get kind ( ) : "BooleanValue" { return this . def . kind ; } get value ( ) : boolean { return this . def . value ; } } export class NullValue { constructor ( private readonly def ) { } get kind ( ) : "NullValue" { return this . def . kind ; } get value ( ) : null { return null ; } } export class EnumValue { constructor ( private readonly def ) { } get kind ( ) : "EnumValue" { return this . def . kind ; } get value ( ) : string { return this . def . value ; } } export class ListValue { constructor ( private readonly def ) { } get kind ( ) : "ListValue" { return this . def . kind ; } get value ( ) : Readonly < Value [ ] > { return [ ] ; } } type ObjectMap = { [ name ] : Value ; } ; export class ObjectValue { constructor ( private readonly def ) { } get kind ( ) : "ObjectValue" { return this . def . kind ; } get value ( ) : ObjectMap { const map = { } ; return map ; } }