UNPKG

graphql

Version:

A Query Language and Runtime which can target any service.

741 lines (740 loc) 23.7 kB
/** @category Parsing */ import type { Maybe } from "../jsutils/Maybe.js"; import type { GraphQLError } from "../error/GraphQLError.js"; import type { ArgumentNode, ConstArgumentNode, ConstDirectiveNode, ConstListValueNode, ConstObjectFieldNode, ConstObjectValueNode, ConstValueNode, DefinitionNode, DirectiveDefinitionNode, DirectiveExtensionNode, DirectiveNode, DocumentNode, EnumTypeDefinitionNode, EnumTypeExtensionNode, EnumValueDefinitionNode, FieldDefinitionNode, FieldNode, FragmentArgumentNode, FragmentDefinitionNode, FragmentSpreadNode, InlineFragmentNode, InputObjectTypeDefinitionNode, InputObjectTypeExtensionNode, InputValueDefinitionNode, InterfaceTypeDefinitionNode, InterfaceTypeExtensionNode, ListValueNode, NamedTypeNode, NameNode, ObjectFieldNode, ObjectTypeDefinitionNode, ObjectTypeExtensionNode, ObjectValueNode, OperationDefinitionNode, OperationTypeDefinitionNode, ScalarTypeDefinitionNode, ScalarTypeExtensionNode, SchemaCoordinateNode, SchemaDefinitionNode, SchemaExtensionNode, SelectionNode, SelectionSetNode, StringValueNode, Token, TypeNode, TypeSystemExtensionNode, UnionTypeDefinitionNode, UnionTypeExtensionNode, ValueNode, VariableDefinitionNode, VariableNode } from "./ast.js"; import { Location, OperationTypeNode } from "./ast.js"; import type { LexerInterface } from "./lexer.js"; import { Source } from "./source.js"; import { TokenKind } from "./tokenKind.js"; /** Configuration options to control parser behavior */ export interface ParseOptions { /** * By default, the parser creates AST nodes that know the location * in the source that they correspond to. This configuration flag * disables that behavior for performance or testing. */ noLocation?: boolean | undefined; /** * Parser CPU and memory usage is linear to the number of tokens in a document * however in extreme cases it becomes quadratic due to memory exhaustion. * Parsing happens before validation so even invalid queries can burn lots of * CPU time and memory. * To prevent this you can set a maximum number of tokens allowed within a document. */ maxTokens?: number | undefined; /** * EXPERIMENTAL: * * If enabled, the parser will understand and parse fragment variable definitions * and arguments on fragment spreads. Fragment variable definitions will be represented * in the `variableDefinitions` field of the FragmentDefinitionNode. * Fragment spread arguments will be represented in the `arguments` field of FragmentSpreadNode. * @example * ```graphql prettier-ignore * { * t { ...A(var: true) } * } * fragment A($var: Boolean = false) on T { * ...B(x: $var) * } * ``` */ experimentalFragmentArguments?: boolean | undefined; /** * Internal parser hook for GraphQL.js entry points that need to parse a * restricted grammar with an alternate lexer. * @internal */ lexer?: LexerInterface | undefined; } /** * Given a GraphQL source, parses it into a Document. * Throws GraphQLError if a syntax error is encountered. * @param source - A GraphQL source string or source object. * @param options - Optional parser configuration. * @returns The parsed GraphQL document AST. * @example * ```ts * // Parse a GraphQL document with the default parser options. * import { parse } from 'graphql/language'; * * const document = parse('{ hero { name } }'); * * document.kind; // => 'Document' * ``` * @example * ```ts * // This variant enables parser options and provides an explicit lexer. * import { Lexer, Source, parse } from 'graphql/language'; * * const document = parse( * ` * { * t { ...A(var: true) } * } * fragment A($var: Boolean = false) on T { * name * } * `, * { * experimentalFragmentArguments: true, * maxTokens: 80, * noLocation: true, * }, * ); * const directiveDocument = parse('directive @foo @bar on FIELD'); * const source = new Source('{ hero }'); * const lexerDocument = parse(source, { lexer: new Lexer(source) }); * * document.definitions[0].kind; // => 'OperationDefinition' * document.definitions[1].kind; // => 'FragmentDefinition' * document.loc; // => undefined * directiveDocument.definitions[0].kind; // => 'DirectiveDefinition' * lexerDocument.definitions[0].kind; // => 'OperationDefinition' * ``` */ export declare function parse(source: string | Source, options?: ParseOptions): DocumentNode; /** * Given a string containing a GraphQL value (ex. `[42]`), parse the AST for * that value. * Throws GraphQLError if a syntax error is encountered. * * This is useful within tools that operate upon GraphQL Values directly and * in isolation of complete GraphQL documents. * * Consider providing the results to the utility function: valueFromAST(). * @param source - A GraphQL source string or source object containing a value. * @param options - Optional parser configuration. * @returns The parsed GraphQL value AST. * @example * ```ts * import { parseValue } from 'graphql/language'; * * const value = parseValue('[42]'); * * value.kind; // => 'ListValue' * ``` */ export declare function parseValue(source: string | Source, options?: ParseOptions): ValueNode; /** * Similar to parseValue(), but raises a parse error if it encounters a * variable. The return type will be a constant value. * @param source - A GraphQL source string or source object containing a constant value. * @param options - Optional parser configuration. * @returns The parsed GraphQL constant value AST. * @example * ```ts * import { parseConstValue } from 'graphql/language'; * * const value = parseConstValue('{ enabled: true }'); * * value.kind; // => 'ObjectValue' * parseConstValue('$variable'); // throws an error * ``` */ export declare function parseConstValue(source: string | Source, options?: ParseOptions): ConstValueNode; /** * Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for * that type. * Throws GraphQLError if a syntax error is encountered. * * This is useful within tools that operate upon GraphQL Types directly and * in isolation of complete GraphQL documents. * * Consider providing the results to the utility function: typeFromAST(). * @param source - A GraphQL source string or source object containing a type reference. * @param options - Optional parser configuration. * @returns The parsed GraphQL type AST. * @example * ```ts * import { parseType } from 'graphql/language'; * * const type = parseType('[String!]'); * * type.kind; // => 'ListType' * ``` */ export declare function parseType(source: string | Source, options?: ParseOptions): TypeNode; /** * Given a string containing a GraphQL Schema Coordinate (ex. `Type.field`), * parse the AST for that schema coordinate. * Throws GraphQLError if a syntax error is encountered. * * Consider providing the results to the utility function: * resolveASTSchemaCoordinate(). Or calling resolveSchemaCoordinate() directly * with an unparsed source. * @param source - A GraphQL source string or source object containing a schema coordinate. * @returns The parsed GraphQL schema coordinate AST. * @example * ```ts * import { parseSchemaCoordinate } from 'graphql/language'; * * const coordinate = parseSchemaCoordinate('Query.hero'); * * coordinate.kind; // => 'MemberCoordinate' * ``` */ export declare function parseSchemaCoordinate(source: string | Source): SchemaCoordinateNode; /** * This class is exported only to assist people in implementing their own parsers * without duplicating too much code and should be used only as last resort for cases * such as experimental syntax or if certain features could not be contributed upstream. * * It is still part of the internal API and is versioned, so any changes to it are never * considered breaking changes. If you still need to support multiple versions of the * library, please use the `versionInfo` variable for version detection. * * @internal */ export declare class Parser { protected _options: Omit<ParseOptions, 'lexer'>; protected _lexer: LexerInterface; protected _tokenCounter: number; constructor(source: string | Source, options?: ParseOptions); get tokenCount(): number; /** * Converts a name lex token into a name parse node. * * @internal */ parseName(): NameNode; /** * Document : Definition+ * * @internal */ parseDocument(): DocumentNode; /** * Definition : * - ExecutableDefinition * - TypeSystemDefinition * - TypeSystemExtension * * ExecutableDefinition : * - OperationDefinition * - FragmentDefinition * * TypeSystemDefinition : * - SchemaDefinition * - TypeDefinition * - DirectiveDefinition * * TypeDefinition : * - ScalarTypeDefinition * - ObjectTypeDefinition * - InterfaceTypeDefinition * - UnionTypeDefinition * - EnumTypeDefinition * - InputObjectTypeDefinition * * @internal */ parseDefinition(): DefinitionNode; /** * OperationDefinition : * - SelectionSet * - OperationType Name? VariableDefinitions? Directives? SelectionSet * * @internal */ parseOperationDefinition(): OperationDefinitionNode; /** * OperationType : one of query mutation subscription * * @internal */ parseOperationType(): OperationTypeNode; /** * VariableDefinitions : ( VariableDefinition+ ) * * @internal */ parseVariableDefinitions(): Array<VariableDefinitionNode> | undefined; /** * VariableDefinition : Variable : Type DefaultValue? Directives[Const]? * * @internal */ parseVariableDefinition(): VariableDefinitionNode; /** * Variable : $ Name * * @internal */ parseVariable(): VariableNode; /** * ``` * SelectionSet : { Selection+ } * ``` * * @internal */ parseSelectionSet(): SelectionSetNode; /** * Selection : * - Field * - FragmentSpread * - InlineFragment * * @internal */ parseSelection(): SelectionNode; /** * Field : Alias? Name Arguments? Directives? SelectionSet? * * Alias : Name : * * @internal */ parseField(): FieldNode; /** * Arguments[Const] : ( Argument[?Const]+ ) * * @internal */ parseArguments(isConst: true): Array<ConstArgumentNode> | undefined; parseArguments(isConst: boolean): Array<ArgumentNode> | undefined; parseFragmentArguments(): Array<FragmentArgumentNode> | undefined; /** * Argument[Const] : Name : Value[?Const] * * @internal */ parseArgument(isConst: true): ConstArgumentNode; parseArgument(isConst?: boolean): ArgumentNode; parseConstArgument(): ConstArgumentNode; parseFragmentArgument(): FragmentArgumentNode; /** * Corresponds to both FragmentSpread and InlineFragment in the spec. * * FragmentSpread : ... FragmentName Arguments? Directives? * * InlineFragment : ... TypeCondition? Directives? SelectionSet * * @internal */ parseFragment(): FragmentSpreadNode | InlineFragmentNode; /** * FragmentDefinition : * - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet * * TypeCondition : NamedType * * @internal */ parseFragmentDefinition(): FragmentDefinitionNode; /** * FragmentName : Name but not `on` * * @internal */ parseFragmentName(): NameNode; /** * Value[Const] : * - [~Const] Variable * - IntValue * - FloatValue * - StringValue * - BooleanValue * - NullValue * - EnumValue * - ListValue[?Const] * - ObjectValue[?Const] * * BooleanValue : one of `true` `false` * * NullValue : `null` * * EnumValue : Name but not `true`, `false` or `null` * * @internal */ parseValueLiteral(isConst: true): ConstValueNode; parseValueLiteral(isConst: boolean): ValueNode; parseConstValueLiteral(): ConstValueNode; parseStringLiteral(): StringValueNode; /** * ListValue[Const] : * - [ ] * - [ Value[?Const]+ ] * * @internal */ parseList(isConst: true): ConstListValueNode; parseList(isConst: boolean): ListValueNode; /** * ``` * ObjectValue[Const] : * - { } * - { ObjectField[?Const]+ } * ``` * * @internal */ parseObject(isConst: true): ConstObjectValueNode; parseObject(isConst: boolean): ObjectValueNode; /** * ObjectField[Const] : Name : Value[?Const] * * @internal */ parseObjectField(isConst: true): ConstObjectFieldNode; parseObjectField(isConst: boolean): ObjectFieldNode; /** * Directives[Const] : Directive[?Const]+ * * @internal */ parseDirectives(isConst: true): Array<ConstDirectiveNode> | undefined; parseDirectives(isConst: boolean): Array<DirectiveNode> | undefined; parseConstDirectives(): Array<ConstDirectiveNode> | undefined; /** * ``` * Directive[Const] : @ Name Arguments[?Const]? * ``` * * @internal */ parseDirective(isConst: true): ConstDirectiveNode; parseDirective(isConst: boolean): DirectiveNode; /** * Type : * - NamedType * - ListType * - NonNullType * * @internal */ parseTypeReference(): TypeNode; /** * NamedType : Name * * @internal */ parseNamedType(): NamedTypeNode; peekDescription(): boolean; /** * Description : StringValue * * @internal */ parseDescription(): undefined | StringValueNode; /** * ``` * SchemaDefinition : Description? schema Directives[Const]? { OperationTypeDefinition+ } * ``` * * @internal */ parseSchemaDefinition(): SchemaDefinitionNode; /** * OperationTypeDefinition : OperationType : NamedType * * @internal */ parseOperationTypeDefinition(): OperationTypeDefinitionNode; /** * ScalarTypeDefinition : Description? scalar Name Directives[Const]? * * @internal */ parseScalarTypeDefinition(): ScalarTypeDefinitionNode; /** * ObjectTypeDefinition : * Description? * type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition? * * @internal */ parseObjectTypeDefinition(): ObjectTypeDefinitionNode; /** * ImplementsInterfaces : * - implements `&`? NamedType * - ImplementsInterfaces & NamedType * * @internal */ parseImplementsInterfaces(): Array<NamedTypeNode> | undefined; /** * ``` * FieldsDefinition : { FieldDefinition+ } * ``` * * @internal */ parseFieldsDefinition(): Array<FieldDefinitionNode> | undefined; /** * FieldDefinition : * - Description? Name ArgumentsDefinition? : Type Directives[Const]? * * @internal */ parseFieldDefinition(): FieldDefinitionNode; /** * ArgumentsDefinition : ( InputValueDefinition+ ) * * @internal */ parseArgumentDefs(): Array<InputValueDefinitionNode> | undefined; /** * InputValueDefinition : * - Description? Name : Type DefaultValue? Directives[Const]? * * @internal */ parseInputValueDef(): InputValueDefinitionNode; /** * InterfaceTypeDefinition : * - Description? interface Name Directives[Const]? FieldsDefinition? * * @internal */ parseInterfaceTypeDefinition(): InterfaceTypeDefinitionNode; /** * UnionTypeDefinition : * - Description? union Name Directives[Const]? UnionMemberTypes? * * @internal */ parseUnionTypeDefinition(): UnionTypeDefinitionNode; /** * UnionMemberTypes : * - = `|`? NamedType * - UnionMemberTypes | NamedType * * @internal */ parseUnionMemberTypes(): Array<NamedTypeNode> | undefined; /** * EnumTypeDefinition : * - Description? enum Name Directives[Const]? EnumValuesDefinition? * * @internal */ parseEnumTypeDefinition(): EnumTypeDefinitionNode; /** * ``` * EnumValuesDefinition : { EnumValueDefinition+ } * ``` * * @internal */ parseEnumValuesDefinition(): Array<EnumValueDefinitionNode> | undefined; /** * EnumValueDefinition : Description? EnumValue Directives[Const]? * * @internal */ parseEnumValueDefinition(): EnumValueDefinitionNode; /** * EnumValue : Name but not `true`, `false` or `null` * * @internal */ parseEnumValueName(): NameNode; /** * InputObjectTypeDefinition : * - Description? input Name Directives[Const]? InputFieldsDefinition? * * @internal */ parseInputObjectTypeDefinition(): InputObjectTypeDefinitionNode; /** * ``` * InputFieldsDefinition : { InputValueDefinition+ } * ``` * * @internal */ parseInputFieldsDefinition(): Array<InputValueDefinitionNode> | undefined; /** * TypeSystemExtension : * - SchemaExtension * - TypeExtension * - DirectiveExtension * * TypeExtension : * - ScalarTypeExtension * - ObjectTypeExtension * - InterfaceTypeExtension * - UnionTypeExtension * - EnumTypeExtension * - InputObjectTypeExtension * * @internal */ parseTypeSystemExtension(): TypeSystemExtensionNode; /** * ``` * SchemaExtension : * - extend schema Directives[Const]? { OperationTypeDefinition+ } * - extend schema Directives[Const] * ``` * * @internal */ parseSchemaExtension(): SchemaExtensionNode; /** * ScalarTypeExtension : * - extend scalar Name Directives[Const] * * @internal */ parseScalarTypeExtension(): ScalarTypeExtensionNode; /** * ObjectTypeExtension : * - extend type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition * - extend type Name ImplementsInterfaces? Directives[Const] * - extend type Name ImplementsInterfaces * * @internal */ parseObjectTypeExtension(): ObjectTypeExtensionNode; /** * InterfaceTypeExtension : * - extend interface Name ImplementsInterfaces? Directives[Const]? FieldsDefinition * - extend interface Name ImplementsInterfaces? Directives[Const] * - extend interface Name ImplementsInterfaces * * @internal */ parseInterfaceTypeExtension(): InterfaceTypeExtensionNode; /** * UnionTypeExtension : * - extend union Name Directives[Const]? UnionMemberTypes * - extend union Name Directives[Const] * * @internal */ parseUnionTypeExtension(): UnionTypeExtensionNode; /** * EnumTypeExtension : * - extend enum Name Directives[Const]? EnumValuesDefinition * - extend enum Name Directives[Const] * * @internal */ parseEnumTypeExtension(): EnumTypeExtensionNode; /** * InputObjectTypeExtension : * - extend input Name Directives[Const]? InputFieldsDefinition * - extend input Name Directives[Const] * * @internal */ parseInputObjectTypeExtension(): InputObjectTypeExtensionNode; parseDirectiveExtension(): DirectiveExtensionNode; /** * ``` * DirectiveDefinition : * - Description? directive @ Name ArgumentsDefinition? Directives[Const]? `repeatable`? on DirectiveLocations * ``` * * @internal */ parseDirectiveDefinition(): DirectiveDefinitionNode; /** * DirectiveLocations : * - `|`? DirectiveLocation * - DirectiveLocations | DirectiveLocation * * @internal */ parseDirectiveLocations(): Array<NameNode>; parseDirectiveLocation(): NameNode; /** * SchemaCoordinate : * - Name * - Name . Name * - Name . Name ( Name : ) * - @ Name * - @ Name ( Name : ) * * @internal */ parseSchemaCoordinate(): SchemaCoordinateNode; /** * Returns a node that, if configured to do so, sets a "loc" field as a * location object, used to identify the place in the source that created a * given parsed object. * * @internal */ node<T extends { loc?: Location | undefined; }>(startToken: Token, node: T): T; /** * Determines if the next token is of a given kind * * @internal */ peek(kind: TokenKind): boolean; /** * If the next token is of the given kind, return that token after advancing the lexer. * Otherwise, do not change the parser state and throw an error. * * @internal */ expectToken(kind: TokenKind): Token; /** * If the next token is of the given kind, return "true" after advancing the lexer. * Otherwise, do not change the parser state and return "false". * * @internal */ expectOptionalToken(kind: TokenKind): boolean; /** * If the next token is a given keyword, advance the lexer. * Otherwise, do not change the parser state and throw an error. * * @internal */ expectKeyword(value: string): void; /** * If the next token is a given keyword, return "true" after advancing the lexer. * Otherwise, do not change the parser state and return "false". * * @internal */ expectOptionalKeyword(value: string): boolean; /** * Helper function for creating an error when an unexpected lexed token is encountered. * * @internal */ unexpected(atToken?: Maybe<Token>): GraphQLError; /** * Returns a possibly empty list of parse nodes, determined by the parseFn. * This list begins with a lex token of openKind and ends with a lex token of closeKind. * Advances the parser to the next lex token after the closing token. * * @internal */ any<T>(openKind: TokenKind, parseFn: () => T, closeKind: TokenKind): Array<T>; /** * Returns a list of parse nodes, determined by the parseFn. * It can be empty only if open token is missing otherwise it will always return non-empty list * that begins with a lex token of openKind and ends with a lex token of closeKind. * Advances the parser to the next lex token after the closing token. * * @internal */ optionalMany<T>(openKind: TokenKind, parseFn: () => T, closeKind: TokenKind): Array<T> | undefined; /** * Returns a non-empty list of parse nodes, determined by the parseFn. * This list begins with a lex token of openKind and ends with a lex token of closeKind. * Advances the parser to the next lex token after the closing token. * * @internal */ many<T>(openKind: TokenKind, parseFn: () => T, closeKind: TokenKind): Array<T>; /** * Returns a non-empty list of parse nodes, determined by the parseFn. * This list may begin with a lex token of delimiterKind followed by items separated by lex tokens of tokenKind. * Advances the parser to the next lex token after last item in the list. * * @internal */ delimitedMany<T>(delimiterKind: TokenKind, parseFn: () => T): Array<T>; advanceLexer(): void; }