Initial Sample.

This commit is contained in:
2024-06-03 20:23:50 +05:30
parent ef2b65f673
commit 5269ec3c66
2575 changed files with 282312 additions and 0 deletions

View File

@@ -0,0 +1,537 @@
import type { Kind } from './kinds';
import type { Source } from './source';
import type { TokenKind } from './tokenKind';
/**
* Contains a range of UTF-8 character offsets and token references that
* identify the region of the source from which the AST derived.
*/
export declare class Location {
/**
* The character offset at which this Node begins.
*/
readonly start: number;
/**
* The character offset at which this Node ends.
*/
readonly end: number;
/**
* The Token at which this Node begins.
*/
readonly startToken: Token;
/**
* The Token at which this Node ends.
*/
readonly endToken: Token;
/**
* The Source document the AST represents.
*/
readonly source: Source;
constructor(startToken: Token, endToken: Token, source: Source);
get [Symbol.toStringTag](): string;
toJSON(): {
start: number;
end: number;
};
}
/**
* Represents a range of characters represented by a lexical token
* within a Source.
*/
export declare class Token {
/**
* The kind of Token.
*/
readonly kind: TokenKind;
/**
* The character offset at which this Node begins.
*/
readonly start: number;
/**
* The character offset at which this Node ends.
*/
readonly end: number;
/**
* The 1-indexed line number on which this Token appears.
*/
readonly line: number;
/**
* The 1-indexed column number at which this Token begins.
*/
readonly column: number;
/**
* For non-punctuation tokens, represents the interpreted value of the token.
*
* Note: is undefined for punctuation tokens, but typed as string for
* convenience in the parser.
*/
readonly value: string;
/**
* Tokens exist as nodes in a double-linked-list amongst all tokens
* including ignored tokens. <SOF> is always the first node and <EOF>
* the last.
*/
readonly prev: Token | null;
readonly next: Token | null;
constructor(
kind: TokenKind,
start: number,
end: number,
line: number,
column: number,
value?: string,
);
get [Symbol.toStringTag](): string;
toJSON(): {
kind: TokenKind;
value?: string;
line: number;
column: number;
};
}
/**
* The list of all possible AST node types.
*/
export declare type ASTNode =
| NameNode
| DocumentNode
| OperationDefinitionNode
| VariableDefinitionNode
| VariableNode
| SelectionSetNode
| FieldNode
| ArgumentNode
| FragmentSpreadNode
| InlineFragmentNode
| FragmentDefinitionNode
| IntValueNode
| FloatValueNode
| StringValueNode
| BooleanValueNode
| NullValueNode
| EnumValueNode
| ListValueNode
| ObjectValueNode
| ObjectFieldNode
| DirectiveNode
| NamedTypeNode
| ListTypeNode
| NonNullTypeNode
| SchemaDefinitionNode
| OperationTypeDefinitionNode
| ScalarTypeDefinitionNode
| ObjectTypeDefinitionNode
| FieldDefinitionNode
| InputValueDefinitionNode
| InterfaceTypeDefinitionNode
| UnionTypeDefinitionNode
| EnumTypeDefinitionNode
| EnumValueDefinitionNode
| InputObjectTypeDefinitionNode
| DirectiveDefinitionNode
| SchemaExtensionNode
| ScalarTypeExtensionNode
| ObjectTypeExtensionNode
| InterfaceTypeExtensionNode
| UnionTypeExtensionNode
| EnumTypeExtensionNode
| InputObjectTypeExtensionNode;
/**
* Utility type listing all nodes indexed by their kind.
*/
export declare type ASTKindToNode = {
[NodeT in ASTNode as NodeT['kind']]: NodeT;
};
/**
* @internal
*/
export declare const QueryDocumentKeys: {
[NodeT in ASTNode as NodeT['kind']]: ReadonlyArray<keyof NodeT>;
};
/**
* @internal
*/
export declare function isNode(maybeNode: any): maybeNode is ASTNode;
/** Name */
export interface NameNode {
readonly kind: Kind.NAME;
readonly loc?: Location;
readonly value: string;
}
/** Document */
export interface DocumentNode {
readonly kind: Kind.DOCUMENT;
readonly loc?: Location;
readonly definitions: ReadonlyArray<DefinitionNode>;
}
export declare type DefinitionNode =
| ExecutableDefinitionNode
| TypeSystemDefinitionNode
| TypeSystemExtensionNode;
export declare type ExecutableDefinitionNode =
| OperationDefinitionNode
| FragmentDefinitionNode;
export interface OperationDefinitionNode {
readonly kind: Kind.OPERATION_DEFINITION;
readonly loc?: Location;
readonly operation: OperationTypeNode;
readonly name?: NameNode;
readonly variableDefinitions?: ReadonlyArray<VariableDefinitionNode>;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly selectionSet: SelectionSetNode;
}
declare enum OperationTypeNode {
QUERY = 'query',
MUTATION = 'mutation',
SUBSCRIPTION = 'subscription',
}
export { OperationTypeNode };
export interface VariableDefinitionNode {
readonly kind: Kind.VARIABLE_DEFINITION;
readonly loc?: Location;
readonly variable: VariableNode;
readonly type: TypeNode;
readonly defaultValue?: ConstValueNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
}
export interface VariableNode {
readonly kind: Kind.VARIABLE;
readonly loc?: Location;
readonly name: NameNode;
}
export interface SelectionSetNode {
kind: Kind.SELECTION_SET;
loc?: Location;
selections: ReadonlyArray<SelectionNode>;
}
export declare type SelectionNode =
| FieldNode
| FragmentSpreadNode
| InlineFragmentNode;
export interface FieldNode {
readonly kind: Kind.FIELD;
readonly loc?: Location;
readonly alias?: NameNode;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<ArgumentNode>;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly selectionSet?: SelectionSetNode;
}
export interface ArgumentNode {
readonly kind: Kind.ARGUMENT;
readonly loc?: Location;
readonly name: NameNode;
readonly value: ValueNode;
}
export interface ConstArgumentNode {
readonly kind: Kind.ARGUMENT;
readonly loc?: Location;
readonly name: NameNode;
readonly value: ConstValueNode;
}
/** Fragments */
export interface FragmentSpreadNode {
readonly kind: Kind.FRAGMENT_SPREAD;
readonly loc?: Location;
readonly name: NameNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
}
export interface InlineFragmentNode {
readonly kind: Kind.INLINE_FRAGMENT;
readonly loc?: Location;
readonly typeCondition?: NamedTypeNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly selectionSet: SelectionSetNode;
}
export interface FragmentDefinitionNode {
readonly kind: Kind.FRAGMENT_DEFINITION;
readonly loc?: Location;
readonly name: NameNode;
/** @deprecated variableDefinitions will be removed in v17.0.0 */
readonly variableDefinitions?: ReadonlyArray<VariableDefinitionNode>;
readonly typeCondition: NamedTypeNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly selectionSet: SelectionSetNode;
}
/** Values */
export declare type ValueNode =
| VariableNode
| IntValueNode
| FloatValueNode
| StringValueNode
| BooleanValueNode
| NullValueNode
| EnumValueNode
| ListValueNode
| ObjectValueNode;
export declare type ConstValueNode =
| IntValueNode
| FloatValueNode
| StringValueNode
| BooleanValueNode
| NullValueNode
| EnumValueNode
| ConstListValueNode
| ConstObjectValueNode;
export interface IntValueNode {
readonly kind: Kind.INT;
readonly loc?: Location;
readonly value: string;
}
export interface FloatValueNode {
readonly kind: Kind.FLOAT;
readonly loc?: Location;
readonly value: string;
}
export interface StringValueNode {
readonly kind: Kind.STRING;
readonly loc?: Location;
readonly value: string;
readonly block?: boolean;
}
export interface BooleanValueNode {
readonly kind: Kind.BOOLEAN;
readonly loc?: Location;
readonly value: boolean;
}
export interface NullValueNode {
readonly kind: Kind.NULL;
readonly loc?: Location;
}
export interface EnumValueNode {
readonly kind: Kind.ENUM;
readonly loc?: Location;
readonly value: string;
}
export interface ListValueNode {
readonly kind: Kind.LIST;
readonly loc?: Location;
readonly values: ReadonlyArray<ValueNode>;
}
export interface ConstListValueNode {
readonly kind: Kind.LIST;
readonly loc?: Location;
readonly values: ReadonlyArray<ConstValueNode>;
}
export interface ObjectValueNode {
readonly kind: Kind.OBJECT;
readonly loc?: Location;
readonly fields: ReadonlyArray<ObjectFieldNode>;
}
export interface ConstObjectValueNode {
readonly kind: Kind.OBJECT;
readonly loc?: Location;
readonly fields: ReadonlyArray<ConstObjectFieldNode>;
}
export interface ObjectFieldNode {
readonly kind: Kind.OBJECT_FIELD;
readonly loc?: Location;
readonly name: NameNode;
readonly value: ValueNode;
}
export interface ConstObjectFieldNode {
readonly kind: Kind.OBJECT_FIELD;
readonly loc?: Location;
readonly name: NameNode;
readonly value: ConstValueNode;
}
/** Directives */
export interface DirectiveNode {
readonly kind: Kind.DIRECTIVE;
readonly loc?: Location;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<ArgumentNode>;
}
export interface ConstDirectiveNode {
readonly kind: Kind.DIRECTIVE;
readonly loc?: Location;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<ConstArgumentNode>;
}
/** Type Reference */
export declare type TypeNode = NamedTypeNode | ListTypeNode | NonNullTypeNode;
export interface NamedTypeNode {
readonly kind: Kind.NAMED_TYPE;
readonly loc?: Location;
readonly name: NameNode;
}
export interface ListTypeNode {
readonly kind: Kind.LIST_TYPE;
readonly loc?: Location;
readonly type: TypeNode;
}
export interface NonNullTypeNode {
readonly kind: Kind.NON_NULL_TYPE;
readonly loc?: Location;
readonly type: NamedTypeNode | ListTypeNode;
}
/** Type System Definition */
export declare type TypeSystemDefinitionNode =
| SchemaDefinitionNode
| TypeDefinitionNode
| DirectiveDefinitionNode;
export interface SchemaDefinitionNode {
readonly kind: Kind.SCHEMA_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly operationTypes: ReadonlyArray<OperationTypeDefinitionNode>;
}
export interface OperationTypeDefinitionNode {
readonly kind: Kind.OPERATION_TYPE_DEFINITION;
readonly loc?: Location;
readonly operation: OperationTypeNode;
readonly type: NamedTypeNode;
}
/** Type Definition */
export declare type TypeDefinitionNode =
| ScalarTypeDefinitionNode
| ObjectTypeDefinitionNode
| InterfaceTypeDefinitionNode
| UnionTypeDefinitionNode
| EnumTypeDefinitionNode
| InputObjectTypeDefinitionNode;
export interface ScalarTypeDefinitionNode {
readonly kind: Kind.SCALAR_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
}
export interface ObjectTypeDefinitionNode {
readonly kind: Kind.OBJECT_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
}
export interface FieldDefinitionNode {
readonly kind: Kind.FIELD_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<InputValueDefinitionNode>;
readonly type: TypeNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
}
export interface InputValueDefinitionNode {
readonly kind: Kind.INPUT_VALUE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly type: TypeNode;
readonly defaultValue?: ConstValueNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
}
export interface InterfaceTypeDefinitionNode {
readonly kind: Kind.INTERFACE_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
}
export interface UnionTypeDefinitionNode {
readonly kind: Kind.UNION_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly types?: ReadonlyArray<NamedTypeNode>;
}
export interface EnumTypeDefinitionNode {
readonly kind: Kind.ENUM_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly values?: ReadonlyArray<EnumValueDefinitionNode>;
}
export interface EnumValueDefinitionNode {
readonly kind: Kind.ENUM_VALUE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
}
export interface InputObjectTypeDefinitionNode {
readonly kind: Kind.INPUT_OBJECT_TYPE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<InputValueDefinitionNode>;
}
/** Directive Definitions */
export interface DirectiveDefinitionNode {
readonly kind: Kind.DIRECTIVE_DEFINITION;
readonly loc?: Location;
readonly description?: StringValueNode;
readonly name: NameNode;
readonly arguments?: ReadonlyArray<InputValueDefinitionNode>;
readonly repeatable: boolean;
readonly locations: ReadonlyArray<NameNode>;
}
/** Type System Extensions */
export declare type TypeSystemExtensionNode =
| SchemaExtensionNode
| TypeExtensionNode;
export interface SchemaExtensionNode {
readonly kind: Kind.SCHEMA_EXTENSION;
readonly loc?: Location;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly operationTypes?: ReadonlyArray<OperationTypeDefinitionNode>;
}
/** Type Extensions */
export declare type TypeExtensionNode =
| ScalarTypeExtensionNode
| ObjectTypeExtensionNode
| InterfaceTypeExtensionNode
| UnionTypeExtensionNode
| EnumTypeExtensionNode
| InputObjectTypeExtensionNode;
export interface ScalarTypeExtensionNode {
readonly kind: Kind.SCALAR_TYPE_EXTENSION;
readonly loc?: Location;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
}
export interface ObjectTypeExtensionNode {
readonly kind: Kind.OBJECT_TYPE_EXTENSION;
readonly loc?: Location;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
}
export interface InterfaceTypeExtensionNode {
readonly kind: Kind.INTERFACE_TYPE_EXTENSION;
readonly loc?: Location;
readonly name: NameNode;
readonly interfaces?: ReadonlyArray<NamedTypeNode>;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<FieldDefinitionNode>;
}
export interface UnionTypeExtensionNode {
readonly kind: Kind.UNION_TYPE_EXTENSION;
readonly loc?: Location;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly types?: ReadonlyArray<NamedTypeNode>;
}
export interface EnumTypeExtensionNode {
readonly kind: Kind.ENUM_TYPE_EXTENSION;
readonly loc?: Location;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly values?: ReadonlyArray<EnumValueDefinitionNode>;
}
export interface InputObjectTypeExtensionNode {
readonly kind: Kind.INPUT_OBJECT_TYPE_EXTENSION;
readonly loc?: Location;
readonly name: NameNode;
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
readonly fields?: ReadonlyArray<InputValueDefinitionNode>;
}

View File

@@ -0,0 +1,224 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.Token =
exports.QueryDocumentKeys =
exports.OperationTypeNode =
exports.Location =
void 0;
exports.isNode = isNode;
/**
* Contains a range of UTF-8 character offsets and token references that
* identify the region of the source from which the AST derived.
*/
class Location {
/**
* The character offset at which this Node begins.
*/
/**
* The character offset at which this Node ends.
*/
/**
* The Token at which this Node begins.
*/
/**
* The Token at which this Node ends.
*/
/**
* The Source document the AST represents.
*/
constructor(startToken, endToken, source) {
this.start = startToken.start;
this.end = endToken.end;
this.startToken = startToken;
this.endToken = endToken;
this.source = source;
}
get [Symbol.toStringTag]() {
return 'Location';
}
toJSON() {
return {
start: this.start,
end: this.end,
};
}
}
/**
* Represents a range of characters represented by a lexical token
* within a Source.
*/
exports.Location = Location;
class Token {
/**
* The kind of Token.
*/
/**
* The character offset at which this Node begins.
*/
/**
* The character offset at which this Node ends.
*/
/**
* The 1-indexed line number on which this Token appears.
*/
/**
* The 1-indexed column number at which this Token begins.
*/
/**
* For non-punctuation tokens, represents the interpreted value of the token.
*
* Note: is undefined for punctuation tokens, but typed as string for
* convenience in the parser.
*/
/**
* Tokens exist as nodes in a double-linked-list amongst all tokens
* including ignored tokens. <SOF> is always the first node and <EOF>
* the last.
*/
constructor(kind, start, end, line, column, value) {
this.kind = kind;
this.start = start;
this.end = end;
this.line = line;
this.column = column; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.value = value;
this.prev = null;
this.next = null;
}
get [Symbol.toStringTag]() {
return 'Token';
}
toJSON() {
return {
kind: this.kind,
value: this.value,
line: this.line,
column: this.column,
};
}
}
/**
* The list of all possible AST node types.
*/
exports.Token = Token;
/**
* @internal
*/
const QueryDocumentKeys = {
Name: [],
Document: ['definitions'],
OperationDefinition: [
'name',
'variableDefinitions',
'directives',
'selectionSet',
],
VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'],
Variable: ['name'],
SelectionSet: ['selections'],
Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
Argument: ['name', 'value'],
FragmentSpread: ['name', 'directives'],
InlineFragment: ['typeCondition', 'directives', 'selectionSet'],
FragmentDefinition: [
'name', // Note: fragment variable definitions are deprecated and will removed in v17.0.0
'variableDefinitions',
'typeCondition',
'directives',
'selectionSet',
],
IntValue: [],
FloatValue: [],
StringValue: [],
BooleanValue: [],
NullValue: [],
EnumValue: [],
ListValue: ['values'],
ObjectValue: ['fields'],
ObjectField: ['name', 'value'],
Directive: ['name', 'arguments'],
NamedType: ['name'],
ListType: ['type'],
NonNullType: ['type'],
SchemaDefinition: ['description', 'directives', 'operationTypes'],
OperationTypeDefinition: ['type'],
ScalarTypeDefinition: ['description', 'name', 'directives'],
ObjectTypeDefinition: [
'description',
'name',
'interfaces',
'directives',
'fields',
],
FieldDefinition: ['description', 'name', 'arguments', 'type', 'directives'],
InputValueDefinition: [
'description',
'name',
'type',
'defaultValue',
'directives',
],
InterfaceTypeDefinition: [
'description',
'name',
'interfaces',
'directives',
'fields',
],
UnionTypeDefinition: ['description', 'name', 'directives', 'types'],
EnumTypeDefinition: ['description', 'name', 'directives', 'values'],
EnumValueDefinition: ['description', 'name', 'directives'],
InputObjectTypeDefinition: ['description', 'name', 'directives', 'fields'],
DirectiveDefinition: ['description', 'name', 'arguments', 'locations'],
SchemaExtension: ['directives', 'operationTypes'],
ScalarTypeExtension: ['name', 'directives'],
ObjectTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
InterfaceTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
UnionTypeExtension: ['name', 'directives', 'types'],
EnumTypeExtension: ['name', 'directives', 'values'],
InputObjectTypeExtension: ['name', 'directives', 'fields'],
};
exports.QueryDocumentKeys = QueryDocumentKeys;
const kindValues = new Set(Object.keys(QueryDocumentKeys));
/**
* @internal
*/
function isNode(maybeNode) {
const maybeKind =
maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.kind;
return typeof maybeKind === 'string' && kindValues.has(maybeKind);
}
/** Name */
var OperationTypeNode;
exports.OperationTypeNode = OperationTypeNode;
(function (OperationTypeNode) {
OperationTypeNode['QUERY'] = 'query';
OperationTypeNode['MUTATION'] = 'mutation';
OperationTypeNode['SUBSCRIPTION'] = 'subscription';
})(OperationTypeNode || (exports.OperationTypeNode = OperationTypeNode = {}));

View File

@@ -0,0 +1,208 @@
/**
* Contains a range of UTF-8 character offsets and token references that
* identify the region of the source from which the AST derived.
*/
export class Location {
/**
* The character offset at which this Node begins.
*/
/**
* The character offset at which this Node ends.
*/
/**
* The Token at which this Node begins.
*/
/**
* The Token at which this Node ends.
*/
/**
* The Source document the AST represents.
*/
constructor(startToken, endToken, source) {
this.start = startToken.start;
this.end = endToken.end;
this.startToken = startToken;
this.endToken = endToken;
this.source = source;
}
get [Symbol.toStringTag]() {
return 'Location';
}
toJSON() {
return {
start: this.start,
end: this.end,
};
}
}
/**
* Represents a range of characters represented by a lexical token
* within a Source.
*/
export class Token {
/**
* The kind of Token.
*/
/**
* The character offset at which this Node begins.
*/
/**
* The character offset at which this Node ends.
*/
/**
* The 1-indexed line number on which this Token appears.
*/
/**
* The 1-indexed column number at which this Token begins.
*/
/**
* For non-punctuation tokens, represents the interpreted value of the token.
*
* Note: is undefined for punctuation tokens, but typed as string for
* convenience in the parser.
*/
/**
* Tokens exist as nodes in a double-linked-list amongst all tokens
* including ignored tokens. <SOF> is always the first node and <EOF>
* the last.
*/
constructor(kind, start, end, line, column, value) {
this.kind = kind;
this.start = start;
this.end = end;
this.line = line;
this.column = column; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.value = value;
this.prev = null;
this.next = null;
}
get [Symbol.toStringTag]() {
return 'Token';
}
toJSON() {
return {
kind: this.kind,
value: this.value,
line: this.line,
column: this.column,
};
}
}
/**
* The list of all possible AST node types.
*/
/**
* @internal
*/
export const QueryDocumentKeys = {
Name: [],
Document: ['definitions'],
OperationDefinition: [
'name',
'variableDefinitions',
'directives',
'selectionSet',
],
VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'],
Variable: ['name'],
SelectionSet: ['selections'],
Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
Argument: ['name', 'value'],
FragmentSpread: ['name', 'directives'],
InlineFragment: ['typeCondition', 'directives', 'selectionSet'],
FragmentDefinition: [
'name', // Note: fragment variable definitions are deprecated and will removed in v17.0.0
'variableDefinitions',
'typeCondition',
'directives',
'selectionSet',
],
IntValue: [],
FloatValue: [],
StringValue: [],
BooleanValue: [],
NullValue: [],
EnumValue: [],
ListValue: ['values'],
ObjectValue: ['fields'],
ObjectField: ['name', 'value'],
Directive: ['name', 'arguments'],
NamedType: ['name'],
ListType: ['type'],
NonNullType: ['type'],
SchemaDefinition: ['description', 'directives', 'operationTypes'],
OperationTypeDefinition: ['type'],
ScalarTypeDefinition: ['description', 'name', 'directives'],
ObjectTypeDefinition: [
'description',
'name',
'interfaces',
'directives',
'fields',
],
FieldDefinition: ['description', 'name', 'arguments', 'type', 'directives'],
InputValueDefinition: [
'description',
'name',
'type',
'defaultValue',
'directives',
],
InterfaceTypeDefinition: [
'description',
'name',
'interfaces',
'directives',
'fields',
],
UnionTypeDefinition: ['description', 'name', 'directives', 'types'],
EnumTypeDefinition: ['description', 'name', 'directives', 'values'],
EnumValueDefinition: ['description', 'name', 'directives'],
InputObjectTypeDefinition: ['description', 'name', 'directives', 'fields'],
DirectiveDefinition: ['description', 'name', 'arguments', 'locations'],
SchemaExtension: ['directives', 'operationTypes'],
ScalarTypeExtension: ['name', 'directives'],
ObjectTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
InterfaceTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
UnionTypeExtension: ['name', 'directives', 'types'],
EnumTypeExtension: ['name', 'directives', 'values'],
InputObjectTypeExtension: ['name', 'directives', 'fields'],
};
const kindValues = new Set(Object.keys(QueryDocumentKeys));
/**
* @internal
*/
export function isNode(maybeNode) {
const maybeKind =
maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.kind;
return typeof maybeKind === 'string' && kindValues.has(maybeKind);
}
/** Name */
var OperationTypeNode;
(function (OperationTypeNode) {
OperationTypeNode['QUERY'] = 'query';
OperationTypeNode['MUTATION'] = 'mutation';
OperationTypeNode['SUBSCRIPTION'] = 'subscription';
})(OperationTypeNode || (OperationTypeNode = {}));
export { OperationTypeNode };

View File

@@ -0,0 +1,28 @@
/**
* Produces the value of a block string from its parsed raw value, similar to
* CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc.
*
* This implements the GraphQL spec's BlockStringValue() static algorithm.
*
* @internal
*/
export declare function dedentBlockStringLines(
lines: ReadonlyArray<string>,
): Array<string>;
/**
* @internal
*/
export declare function isPrintableAsBlockString(value: string): boolean;
/**
* Print a block string in the indented block form by adding a leading and
* trailing blank line. However, if a block string starts with whitespace and is
* a single-line, adding a leading blank line would strip that whitespace.
*
* @internal
*/
export declare function printBlockString(
value: string,
options?: {
minimize?: boolean;
},
): string;

View File

@@ -0,0 +1,195 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.dedentBlockStringLines = dedentBlockStringLines;
exports.isPrintableAsBlockString = isPrintableAsBlockString;
exports.printBlockString = printBlockString;
var _characterClasses = require('./characterClasses.js');
/**
* Produces the value of a block string from its parsed raw value, similar to
* CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc.
*
* This implements the GraphQL spec's BlockStringValue() static algorithm.
*
* @internal
*/
function dedentBlockStringLines(lines) {
var _firstNonEmptyLine2;
let commonIndent = Number.MAX_SAFE_INTEGER;
let firstNonEmptyLine = null;
let lastNonEmptyLine = -1;
for (let i = 0; i < lines.length; ++i) {
var _firstNonEmptyLine;
const line = lines[i];
const indent = leadingWhitespace(line);
if (indent === line.length) {
continue; // skip empty lines
}
firstNonEmptyLine =
(_firstNonEmptyLine = firstNonEmptyLine) !== null &&
_firstNonEmptyLine !== void 0
? _firstNonEmptyLine
: i;
lastNonEmptyLine = i;
if (i !== 0 && indent < commonIndent) {
commonIndent = indent;
}
}
return lines // Remove common indentation from all lines but first.
.map((line, i) => (i === 0 ? line : line.slice(commonIndent))) // Remove leading and trailing blank lines.
.slice(
(_firstNonEmptyLine2 = firstNonEmptyLine) !== null &&
_firstNonEmptyLine2 !== void 0
? _firstNonEmptyLine2
: 0,
lastNonEmptyLine + 1,
);
}
function leadingWhitespace(str) {
let i = 0;
while (
i < str.length &&
(0, _characterClasses.isWhiteSpace)(str.charCodeAt(i))
) {
++i;
}
return i;
}
/**
* @internal
*/
function isPrintableAsBlockString(value) {
if (value === '') {
return true; // empty string is printable
}
let isEmptyLine = true;
let hasIndent = false;
let hasCommonIndent = true;
let seenNonEmptyLine = false;
for (let i = 0; i < value.length; ++i) {
switch (value.codePointAt(i)) {
case 0x0000:
case 0x0001:
case 0x0002:
case 0x0003:
case 0x0004:
case 0x0005:
case 0x0006:
case 0x0007:
case 0x0008:
case 0x000b:
case 0x000c:
case 0x000e:
case 0x000f:
return false;
// Has non-printable characters
case 0x000d:
// \r
return false;
// Has \r or \r\n which will be replaced as \n
case 10:
// \n
if (isEmptyLine && !seenNonEmptyLine) {
return false; // Has leading new line
}
seenNonEmptyLine = true;
isEmptyLine = true;
hasIndent = false;
break;
case 9: // \t
case 32:
// <space>
hasIndent || (hasIndent = isEmptyLine);
break;
default:
hasCommonIndent && (hasCommonIndent = hasIndent);
isEmptyLine = false;
}
}
if (isEmptyLine) {
return false; // Has trailing empty lines
}
if (hasCommonIndent && seenNonEmptyLine) {
return false; // Has internal indent
}
return true;
}
/**
* Print a block string in the indented block form by adding a leading and
* trailing blank line. However, if a block string starts with whitespace and is
* a single-line, adding a leading blank line would strip that whitespace.
*
* @internal
*/
function printBlockString(value, options) {
const escapedValue = value.replace(/"""/g, '\\"""'); // Expand a block string's raw value into independent lines.
const lines = escapedValue.split(/\r\n|[\n\r]/g);
const isSingleLine = lines.length === 1; // If common indentation is found we can fix some of those cases by adding leading new line
const forceLeadingNewLine =
lines.length > 1 &&
lines
.slice(1)
.every(
(line) =>
line.length === 0 ||
(0, _characterClasses.isWhiteSpace)(line.charCodeAt(0)),
); // Trailing triple quotes just looks confusing but doesn't force trailing new line
const hasTrailingTripleQuotes = escapedValue.endsWith('\\"""'); // Trailing quote (single or double) or slash forces trailing new line
const hasTrailingQuote = value.endsWith('"') && !hasTrailingTripleQuotes;
const hasTrailingSlash = value.endsWith('\\');
const forceTrailingNewline = hasTrailingQuote || hasTrailingSlash;
const printAsMultipleLines =
!(options !== null && options !== void 0 && options.minimize) && // add leading and trailing new lines only if it improves readability
(!isSingleLine ||
value.length > 70 ||
forceTrailingNewline ||
forceLeadingNewLine ||
hasTrailingTripleQuotes);
let result = ''; // Format a multi-line block quote to account for leading space.
const skipLeadingNewLine =
isSingleLine && (0, _characterClasses.isWhiteSpace)(value.charCodeAt(0));
if ((printAsMultipleLines && !skipLeadingNewLine) || forceLeadingNewLine) {
result += '\n';
}
result += escapedValue;
if (printAsMultipleLines || forceTrailingNewline) {
result += '\n';
}
return '"""' + result + '"""';
}

View File

@@ -0,0 +1,178 @@
import { isWhiteSpace } from './characterClasses.mjs';
/**
* Produces the value of a block string from its parsed raw value, similar to
* CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc.
*
* This implements the GraphQL spec's BlockStringValue() static algorithm.
*
* @internal
*/
export function dedentBlockStringLines(lines) {
var _firstNonEmptyLine2;
let commonIndent = Number.MAX_SAFE_INTEGER;
let firstNonEmptyLine = null;
let lastNonEmptyLine = -1;
for (let i = 0; i < lines.length; ++i) {
var _firstNonEmptyLine;
const line = lines[i];
const indent = leadingWhitespace(line);
if (indent === line.length) {
continue; // skip empty lines
}
firstNonEmptyLine =
(_firstNonEmptyLine = firstNonEmptyLine) !== null &&
_firstNonEmptyLine !== void 0
? _firstNonEmptyLine
: i;
lastNonEmptyLine = i;
if (i !== 0 && indent < commonIndent) {
commonIndent = indent;
}
}
return lines // Remove common indentation from all lines but first.
.map((line, i) => (i === 0 ? line : line.slice(commonIndent))) // Remove leading and trailing blank lines.
.slice(
(_firstNonEmptyLine2 = firstNonEmptyLine) !== null &&
_firstNonEmptyLine2 !== void 0
? _firstNonEmptyLine2
: 0,
lastNonEmptyLine + 1,
);
}
function leadingWhitespace(str) {
let i = 0;
while (i < str.length && isWhiteSpace(str.charCodeAt(i))) {
++i;
}
return i;
}
/**
* @internal
*/
export function isPrintableAsBlockString(value) {
if (value === '') {
return true; // empty string is printable
}
let isEmptyLine = true;
let hasIndent = false;
let hasCommonIndent = true;
let seenNonEmptyLine = false;
for (let i = 0; i < value.length; ++i) {
switch (value.codePointAt(i)) {
case 0x0000:
case 0x0001:
case 0x0002:
case 0x0003:
case 0x0004:
case 0x0005:
case 0x0006:
case 0x0007:
case 0x0008:
case 0x000b:
case 0x000c:
case 0x000e:
case 0x000f:
return false;
// Has non-printable characters
case 0x000d:
// \r
return false;
// Has \r or \r\n which will be replaced as \n
case 10:
// \n
if (isEmptyLine && !seenNonEmptyLine) {
return false; // Has leading new line
}
seenNonEmptyLine = true;
isEmptyLine = true;
hasIndent = false;
break;
case 9: // \t
case 32:
// <space>
hasIndent || (hasIndent = isEmptyLine);
break;
default:
hasCommonIndent && (hasCommonIndent = hasIndent);
isEmptyLine = false;
}
}
if (isEmptyLine) {
return false; // Has trailing empty lines
}
if (hasCommonIndent && seenNonEmptyLine) {
return false; // Has internal indent
}
return true;
}
/**
* Print a block string in the indented block form by adding a leading and
* trailing blank line. However, if a block string starts with whitespace and is
* a single-line, adding a leading blank line would strip that whitespace.
*
* @internal
*/
export function printBlockString(value, options) {
const escapedValue = value.replace(/"""/g, '\\"""'); // Expand a block string's raw value into independent lines.
const lines = escapedValue.split(/\r\n|[\n\r]/g);
const isSingleLine = lines.length === 1; // If common indentation is found we can fix some of those cases by adding leading new line
const forceLeadingNewLine =
lines.length > 1 &&
lines
.slice(1)
.every((line) => line.length === 0 || isWhiteSpace(line.charCodeAt(0))); // Trailing triple quotes just looks confusing but doesn't force trailing new line
const hasTrailingTripleQuotes = escapedValue.endsWith('\\"""'); // Trailing quote (single or double) or slash forces trailing new line
const hasTrailingQuote = value.endsWith('"') && !hasTrailingTripleQuotes;
const hasTrailingSlash = value.endsWith('\\');
const forceTrailingNewline = hasTrailingQuote || hasTrailingSlash;
const printAsMultipleLines =
!(options !== null && options !== void 0 && options.minimize) && // add leading and trailing new lines only if it improves readability
(!isSingleLine ||
value.length > 70 ||
forceTrailingNewline ||
forceLeadingNewLine ||
hasTrailingTripleQuotes);
let result = ''; // Format a multi-line block quote to account for leading space.
const skipLeadingNewLine = isSingleLine && isWhiteSpace(value.charCodeAt(0));
if ((printAsMultipleLines && !skipLeadingNewLine) || forceLeadingNewLine) {
result += '\n';
}
result += escapedValue;
if (printAsMultipleLines || forceTrailingNewline) {
result += '\n';
}
return '"""' + result + '"""';
}

View File

@@ -0,0 +1,47 @@
/**
* ```
* WhiteSpace ::
* - "Horizontal Tab (U+0009)"
* - "Space (U+0020)"
* ```
* @internal
*/
export declare function isWhiteSpace(code: number): boolean;
/**
* ```
* Digit :: one of
* - `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`
* ```
* @internal
*/
export declare function isDigit(code: number): boolean;
/**
* ```
* Letter :: one of
* - `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M`
* - `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z`
* - `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m`
* - `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z`
* ```
* @internal
*/
export declare function isLetter(code: number): boolean;
/**
* ```
* NameStart ::
* - Letter
* - `_`
* ```
* @internal
*/
export declare function isNameStart(code: number): boolean;
/**
* ```
* NameContinue ::
* - Letter
* - Digit
* - `_`
* ```
* @internal
*/
export declare function isNameContinue(code: number): boolean;

View File

@@ -0,0 +1,75 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.isDigit = isDigit;
exports.isLetter = isLetter;
exports.isNameContinue = isNameContinue;
exports.isNameStart = isNameStart;
exports.isWhiteSpace = isWhiteSpace;
/**
* ```
* WhiteSpace ::
* - "Horizontal Tab (U+0009)"
* - "Space (U+0020)"
* ```
* @internal
*/
function isWhiteSpace(code) {
return code === 0x0009 || code === 0x0020;
}
/**
* ```
* Digit :: one of
* - `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`
* ```
* @internal
*/
function isDigit(code) {
return code >= 0x0030 && code <= 0x0039;
}
/**
* ```
* Letter :: one of
* - `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M`
* - `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z`
* - `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m`
* - `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z`
* ```
* @internal
*/
function isLetter(code) {
return (
(code >= 0x0061 && code <= 0x007a) || // A-Z
(code >= 0x0041 && code <= 0x005a) // a-z
);
}
/**
* ```
* NameStart ::
* - Letter
* - `_`
* ```
* @internal
*/
function isNameStart(code) {
return isLetter(code) || code === 0x005f;
}
/**
* ```
* NameContinue ::
* - Letter
* - Digit
* - `_`
* ```
* @internal
*/
function isNameContinue(code) {
return isLetter(code) || isDigit(code) || code === 0x005f;
}

View File

@@ -0,0 +1,64 @@
/**
* ```
* WhiteSpace ::
* - "Horizontal Tab (U+0009)"
* - "Space (U+0020)"
* ```
* @internal
*/
export function isWhiteSpace(code) {
return code === 0x0009 || code === 0x0020;
}
/**
* ```
* Digit :: one of
* - `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`
* ```
* @internal
*/
export function isDigit(code) {
return code >= 0x0030 && code <= 0x0039;
}
/**
* ```
* Letter :: one of
* - `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M`
* - `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z`
* - `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m`
* - `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z`
* ```
* @internal
*/
export function isLetter(code) {
return (
(code >= 0x0061 && code <= 0x007a) || // A-Z
(code >= 0x0041 && code <= 0x005a) // a-z
);
}
/**
* ```
* NameStart ::
* - Letter
* - `_`
* ```
* @internal
*/
export function isNameStart(code) {
return isLetter(code) || code === 0x005f;
}
/**
* ```
* NameContinue ::
* - Letter
* - Digit
* - `_`
* ```
* @internal
*/
export function isNameContinue(code) {
return isLetter(code) || isDigit(code) || code === 0x005f;
}

View File

@@ -0,0 +1,33 @@
/**
* The set of allowed directive location values.
*/
declare enum DirectiveLocation {
/** Request Definitions */
QUERY = 'QUERY',
MUTATION = 'MUTATION',
SUBSCRIPTION = 'SUBSCRIPTION',
FIELD = 'FIELD',
FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION',
FRAGMENT_SPREAD = 'FRAGMENT_SPREAD',
INLINE_FRAGMENT = 'INLINE_FRAGMENT',
VARIABLE_DEFINITION = 'VARIABLE_DEFINITION',
/** Type System Definitions */
SCHEMA = 'SCHEMA',
SCALAR = 'SCALAR',
OBJECT = 'OBJECT',
FIELD_DEFINITION = 'FIELD_DEFINITION',
ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION',
INTERFACE = 'INTERFACE',
UNION = 'UNION',
ENUM = 'ENUM',
ENUM_VALUE = 'ENUM_VALUE',
INPUT_OBJECT = 'INPUT_OBJECT',
INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION',
}
export { DirectiveLocation };
/**
* The enum type representing the directive location values.
*
* @deprecated Please use `DirectiveLocation`. Will be remove in v17.
*/
export declare type DirectiveLocationEnum = typeof DirectiveLocation;

View File

@@ -0,0 +1,39 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.DirectiveLocation = void 0;
/**
* The set of allowed directive location values.
*/
var DirectiveLocation;
exports.DirectiveLocation = DirectiveLocation;
(function (DirectiveLocation) {
DirectiveLocation['QUERY'] = 'QUERY';
DirectiveLocation['MUTATION'] = 'MUTATION';
DirectiveLocation['SUBSCRIPTION'] = 'SUBSCRIPTION';
DirectiveLocation['FIELD'] = 'FIELD';
DirectiveLocation['FRAGMENT_DEFINITION'] = 'FRAGMENT_DEFINITION';
DirectiveLocation['FRAGMENT_SPREAD'] = 'FRAGMENT_SPREAD';
DirectiveLocation['INLINE_FRAGMENT'] = 'INLINE_FRAGMENT';
DirectiveLocation['VARIABLE_DEFINITION'] = 'VARIABLE_DEFINITION';
DirectiveLocation['SCHEMA'] = 'SCHEMA';
DirectiveLocation['SCALAR'] = 'SCALAR';
DirectiveLocation['OBJECT'] = 'OBJECT';
DirectiveLocation['FIELD_DEFINITION'] = 'FIELD_DEFINITION';
DirectiveLocation['ARGUMENT_DEFINITION'] = 'ARGUMENT_DEFINITION';
DirectiveLocation['INTERFACE'] = 'INTERFACE';
DirectiveLocation['UNION'] = 'UNION';
DirectiveLocation['ENUM'] = 'ENUM';
DirectiveLocation['ENUM_VALUE'] = 'ENUM_VALUE';
DirectiveLocation['INPUT_OBJECT'] = 'INPUT_OBJECT';
DirectiveLocation['INPUT_FIELD_DEFINITION'] = 'INPUT_FIELD_DEFINITION';
})(DirectiveLocation || (exports.DirectiveLocation = DirectiveLocation = {}));
/**
* The enum type representing the directive location values.
*
* @deprecated Please use `DirectiveLocation`. Will be remove in v17.
*/

View File

@@ -0,0 +1,33 @@
/**
* The set of allowed directive location values.
*/
var DirectiveLocation;
(function (DirectiveLocation) {
DirectiveLocation['QUERY'] = 'QUERY';
DirectiveLocation['MUTATION'] = 'MUTATION';
DirectiveLocation['SUBSCRIPTION'] = 'SUBSCRIPTION';
DirectiveLocation['FIELD'] = 'FIELD';
DirectiveLocation['FRAGMENT_DEFINITION'] = 'FRAGMENT_DEFINITION';
DirectiveLocation['FRAGMENT_SPREAD'] = 'FRAGMENT_SPREAD';
DirectiveLocation['INLINE_FRAGMENT'] = 'INLINE_FRAGMENT';
DirectiveLocation['VARIABLE_DEFINITION'] = 'VARIABLE_DEFINITION';
DirectiveLocation['SCHEMA'] = 'SCHEMA';
DirectiveLocation['SCALAR'] = 'SCALAR';
DirectiveLocation['OBJECT'] = 'OBJECT';
DirectiveLocation['FIELD_DEFINITION'] = 'FIELD_DEFINITION';
DirectiveLocation['ARGUMENT_DEFINITION'] = 'ARGUMENT_DEFINITION';
DirectiveLocation['INTERFACE'] = 'INTERFACE';
DirectiveLocation['UNION'] = 'UNION';
DirectiveLocation['ENUM'] = 'ENUM';
DirectiveLocation['ENUM_VALUE'] = 'ENUM_VALUE';
DirectiveLocation['INPUT_OBJECT'] = 'INPUT_OBJECT';
DirectiveLocation['INPUT_FIELD_DEFINITION'] = 'INPUT_FIELD_DEFINITION';
})(DirectiveLocation || (DirectiveLocation = {}));
export { DirectiveLocation };
/**
* The enum type representing the directive location values.
*
* @deprecated Please use `DirectiveLocation`. Will be remove in v17.
*/

View File

@@ -0,0 +1,97 @@
export { Source } from './source';
export { getLocation } from './location';
export type { SourceLocation } from './location';
export { printLocation, printSourceLocation } from './printLocation';
export { Kind } from './kinds';
export type { KindEnum } from './kinds';
export { TokenKind } from './tokenKind';
export type { TokenKindEnum } from './tokenKind';
export { Lexer } from './lexer';
export { parse, parseValue, parseConstValue, parseType } from './parser';
export type { ParseOptions } from './parser';
export { print } from './printer';
export {
visit,
visitInParallel,
getVisitFn,
getEnterLeaveForKind,
BREAK,
} from './visitor';
export type { ASTVisitor, ASTVisitFn, ASTVisitorKeyMap } from './visitor';
export { Location, Token, OperationTypeNode } from './ast';
export type {
ASTNode,
ASTKindToNode,
NameNode,
DocumentNode,
DefinitionNode,
ExecutableDefinitionNode,
OperationDefinitionNode,
VariableDefinitionNode,
VariableNode,
SelectionSetNode,
SelectionNode,
FieldNode,
ArgumentNode,
ConstArgumentNode,
FragmentSpreadNode,
InlineFragmentNode,
FragmentDefinitionNode,
ValueNode,
ConstValueNode,
IntValueNode,
FloatValueNode,
StringValueNode,
BooleanValueNode,
NullValueNode,
EnumValueNode,
ListValueNode,
ConstListValueNode,
ObjectValueNode,
ConstObjectValueNode,
ObjectFieldNode,
ConstObjectFieldNode,
DirectiveNode,
ConstDirectiveNode,
TypeNode,
NamedTypeNode,
ListTypeNode,
NonNullTypeNode,
TypeSystemDefinitionNode,
SchemaDefinitionNode,
OperationTypeDefinitionNode,
TypeDefinitionNode,
ScalarTypeDefinitionNode,
ObjectTypeDefinitionNode,
FieldDefinitionNode,
InputValueDefinitionNode,
InterfaceTypeDefinitionNode,
UnionTypeDefinitionNode,
EnumTypeDefinitionNode,
EnumValueDefinitionNode,
InputObjectTypeDefinitionNode,
DirectiveDefinitionNode,
TypeSystemExtensionNode,
SchemaExtensionNode,
TypeExtensionNode,
ScalarTypeExtensionNode,
ObjectTypeExtensionNode,
InterfaceTypeExtensionNode,
UnionTypeExtensionNode,
EnumTypeExtensionNode,
InputObjectTypeExtensionNode,
} from './ast';
export {
isDefinitionNode,
isExecutableDefinitionNode,
isSelectionNode,
isValueNode,
isConstValueNode,
isTypeNode,
isTypeSystemDefinitionNode,
isTypeDefinitionNode,
isTypeSystemExtensionNode,
isTypeExtensionNode,
} from './predicates';
export { DirectiveLocation } from './directiveLocation';
export type { DirectiveLocationEnum } from './directiveLocation';

View File

@@ -0,0 +1,215 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
Object.defineProperty(exports, 'BREAK', {
enumerable: true,
get: function () {
return _visitor.BREAK;
},
});
Object.defineProperty(exports, 'DirectiveLocation', {
enumerable: true,
get: function () {
return _directiveLocation.DirectiveLocation;
},
});
Object.defineProperty(exports, 'Kind', {
enumerable: true,
get: function () {
return _kinds.Kind;
},
});
Object.defineProperty(exports, 'Lexer', {
enumerable: true,
get: function () {
return _lexer.Lexer;
},
});
Object.defineProperty(exports, 'Location', {
enumerable: true,
get: function () {
return _ast.Location;
},
});
Object.defineProperty(exports, 'OperationTypeNode', {
enumerable: true,
get: function () {
return _ast.OperationTypeNode;
},
});
Object.defineProperty(exports, 'Source', {
enumerable: true,
get: function () {
return _source.Source;
},
});
Object.defineProperty(exports, 'Token', {
enumerable: true,
get: function () {
return _ast.Token;
},
});
Object.defineProperty(exports, 'TokenKind', {
enumerable: true,
get: function () {
return _tokenKind.TokenKind;
},
});
Object.defineProperty(exports, 'getEnterLeaveForKind', {
enumerable: true,
get: function () {
return _visitor.getEnterLeaveForKind;
},
});
Object.defineProperty(exports, 'getLocation', {
enumerable: true,
get: function () {
return _location.getLocation;
},
});
Object.defineProperty(exports, 'getVisitFn', {
enumerable: true,
get: function () {
return _visitor.getVisitFn;
},
});
Object.defineProperty(exports, 'isConstValueNode', {
enumerable: true,
get: function () {
return _predicates.isConstValueNode;
},
});
Object.defineProperty(exports, 'isDefinitionNode', {
enumerable: true,
get: function () {
return _predicates.isDefinitionNode;
},
});
Object.defineProperty(exports, 'isExecutableDefinitionNode', {
enumerable: true,
get: function () {
return _predicates.isExecutableDefinitionNode;
},
});
Object.defineProperty(exports, 'isSelectionNode', {
enumerable: true,
get: function () {
return _predicates.isSelectionNode;
},
});
Object.defineProperty(exports, 'isTypeDefinitionNode', {
enumerable: true,
get: function () {
return _predicates.isTypeDefinitionNode;
},
});
Object.defineProperty(exports, 'isTypeExtensionNode', {
enumerable: true,
get: function () {
return _predicates.isTypeExtensionNode;
},
});
Object.defineProperty(exports, 'isTypeNode', {
enumerable: true,
get: function () {
return _predicates.isTypeNode;
},
});
Object.defineProperty(exports, 'isTypeSystemDefinitionNode', {
enumerable: true,
get: function () {
return _predicates.isTypeSystemDefinitionNode;
},
});
Object.defineProperty(exports, 'isTypeSystemExtensionNode', {
enumerable: true,
get: function () {
return _predicates.isTypeSystemExtensionNode;
},
});
Object.defineProperty(exports, 'isValueNode', {
enumerable: true,
get: function () {
return _predicates.isValueNode;
},
});
Object.defineProperty(exports, 'parse', {
enumerable: true,
get: function () {
return _parser.parse;
},
});
Object.defineProperty(exports, 'parseConstValue', {
enumerable: true,
get: function () {
return _parser.parseConstValue;
},
});
Object.defineProperty(exports, 'parseType', {
enumerable: true,
get: function () {
return _parser.parseType;
},
});
Object.defineProperty(exports, 'parseValue', {
enumerable: true,
get: function () {
return _parser.parseValue;
},
});
Object.defineProperty(exports, 'print', {
enumerable: true,
get: function () {
return _printer.print;
},
});
Object.defineProperty(exports, 'printLocation', {
enumerable: true,
get: function () {
return _printLocation.printLocation;
},
});
Object.defineProperty(exports, 'printSourceLocation', {
enumerable: true,
get: function () {
return _printLocation.printSourceLocation;
},
});
Object.defineProperty(exports, 'visit', {
enumerable: true,
get: function () {
return _visitor.visit;
},
});
Object.defineProperty(exports, 'visitInParallel', {
enumerable: true,
get: function () {
return _visitor.visitInParallel;
},
});
var _source = require('./source.js');
var _location = require('./location.js');
var _printLocation = require('./printLocation.js');
var _kinds = require('./kinds.js');
var _tokenKind = require('./tokenKind.js');
var _lexer = require('./lexer.js');
var _parser = require('./parser.js');
var _printer = require('./printer.js');
var _visitor = require('./visitor.js');
var _ast = require('./ast.js');
var _predicates = require('./predicates.js');
var _directiveLocation = require('./directiveLocation.js');

View File

@@ -0,0 +1,29 @@
export { Source } from './source.mjs';
export { getLocation } from './location.mjs';
export { printLocation, printSourceLocation } from './printLocation.mjs';
export { Kind } from './kinds.mjs';
export { TokenKind } from './tokenKind.mjs';
export { Lexer } from './lexer.mjs';
export { parse, parseValue, parseConstValue, parseType } from './parser.mjs';
export { print } from './printer.mjs';
export {
visit,
visitInParallel,
getVisitFn,
getEnterLeaveForKind,
BREAK,
} from './visitor.mjs';
export { Location, Token, OperationTypeNode } from './ast.mjs';
export {
isDefinitionNode,
isExecutableDefinitionNode,
isSelectionNode,
isValueNode,
isConstValueNode,
isTypeNode,
isTypeSystemDefinitionNode,
isTypeDefinitionNode,
isTypeSystemExtensionNode,
isTypeExtensionNode,
} from './predicates.mjs';
export { DirectiveLocation } from './directiveLocation.mjs';

View File

@@ -0,0 +1,66 @@
/**
* The set of allowed kind values for AST nodes.
*/
declare enum Kind {
/** Name */
NAME = 'Name',
/** Document */
DOCUMENT = 'Document',
OPERATION_DEFINITION = 'OperationDefinition',
VARIABLE_DEFINITION = 'VariableDefinition',
SELECTION_SET = 'SelectionSet',
FIELD = 'Field',
ARGUMENT = 'Argument',
/** Fragments */
FRAGMENT_SPREAD = 'FragmentSpread',
INLINE_FRAGMENT = 'InlineFragment',
FRAGMENT_DEFINITION = 'FragmentDefinition',
/** Values */
VARIABLE = 'Variable',
INT = 'IntValue',
FLOAT = 'FloatValue',
STRING = 'StringValue',
BOOLEAN = 'BooleanValue',
NULL = 'NullValue',
ENUM = 'EnumValue',
LIST = 'ListValue',
OBJECT = 'ObjectValue',
OBJECT_FIELD = 'ObjectField',
/** Directives */
DIRECTIVE = 'Directive',
/** Types */
NAMED_TYPE = 'NamedType',
LIST_TYPE = 'ListType',
NON_NULL_TYPE = 'NonNullType',
/** Type System Definitions */
SCHEMA_DEFINITION = 'SchemaDefinition',
OPERATION_TYPE_DEFINITION = 'OperationTypeDefinition',
/** Type Definitions */
SCALAR_TYPE_DEFINITION = 'ScalarTypeDefinition',
OBJECT_TYPE_DEFINITION = 'ObjectTypeDefinition',
FIELD_DEFINITION = 'FieldDefinition',
INPUT_VALUE_DEFINITION = 'InputValueDefinition',
INTERFACE_TYPE_DEFINITION = 'InterfaceTypeDefinition',
UNION_TYPE_DEFINITION = 'UnionTypeDefinition',
ENUM_TYPE_DEFINITION = 'EnumTypeDefinition',
ENUM_VALUE_DEFINITION = 'EnumValueDefinition',
INPUT_OBJECT_TYPE_DEFINITION = 'InputObjectTypeDefinition',
/** Directive Definitions */
DIRECTIVE_DEFINITION = 'DirectiveDefinition',
/** Type System Extensions */
SCHEMA_EXTENSION = 'SchemaExtension',
/** Type Extensions */
SCALAR_TYPE_EXTENSION = 'ScalarTypeExtension',
OBJECT_TYPE_EXTENSION = 'ObjectTypeExtension',
INTERFACE_TYPE_EXTENSION = 'InterfaceTypeExtension',
UNION_TYPE_EXTENSION = 'UnionTypeExtension',
ENUM_TYPE_EXTENSION = 'EnumTypeExtension',
INPUT_OBJECT_TYPE_EXTENSION = 'InputObjectTypeExtension',
}
export { Kind };
/**
* The enum type representing the possible kind values of AST nodes.
*
* @deprecated Please use `Kind`. Will be remove in v17.
*/
export declare type KindEnum = typeof Kind;

View File

@@ -0,0 +1,63 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.Kind = void 0;
/**
* The set of allowed kind values for AST nodes.
*/
var Kind;
exports.Kind = Kind;
(function (Kind) {
Kind['NAME'] = 'Name';
Kind['DOCUMENT'] = 'Document';
Kind['OPERATION_DEFINITION'] = 'OperationDefinition';
Kind['VARIABLE_DEFINITION'] = 'VariableDefinition';
Kind['SELECTION_SET'] = 'SelectionSet';
Kind['FIELD'] = 'Field';
Kind['ARGUMENT'] = 'Argument';
Kind['FRAGMENT_SPREAD'] = 'FragmentSpread';
Kind['INLINE_FRAGMENT'] = 'InlineFragment';
Kind['FRAGMENT_DEFINITION'] = 'FragmentDefinition';
Kind['VARIABLE'] = 'Variable';
Kind['INT'] = 'IntValue';
Kind['FLOAT'] = 'FloatValue';
Kind['STRING'] = 'StringValue';
Kind['BOOLEAN'] = 'BooleanValue';
Kind['NULL'] = 'NullValue';
Kind['ENUM'] = 'EnumValue';
Kind['LIST'] = 'ListValue';
Kind['OBJECT'] = 'ObjectValue';
Kind['OBJECT_FIELD'] = 'ObjectField';
Kind['DIRECTIVE'] = 'Directive';
Kind['NAMED_TYPE'] = 'NamedType';
Kind['LIST_TYPE'] = 'ListType';
Kind['NON_NULL_TYPE'] = 'NonNullType';
Kind['SCHEMA_DEFINITION'] = 'SchemaDefinition';
Kind['OPERATION_TYPE_DEFINITION'] = 'OperationTypeDefinition';
Kind['SCALAR_TYPE_DEFINITION'] = 'ScalarTypeDefinition';
Kind['OBJECT_TYPE_DEFINITION'] = 'ObjectTypeDefinition';
Kind['FIELD_DEFINITION'] = 'FieldDefinition';
Kind['INPUT_VALUE_DEFINITION'] = 'InputValueDefinition';
Kind['INTERFACE_TYPE_DEFINITION'] = 'InterfaceTypeDefinition';
Kind['UNION_TYPE_DEFINITION'] = 'UnionTypeDefinition';
Kind['ENUM_TYPE_DEFINITION'] = 'EnumTypeDefinition';
Kind['ENUM_VALUE_DEFINITION'] = 'EnumValueDefinition';
Kind['INPUT_OBJECT_TYPE_DEFINITION'] = 'InputObjectTypeDefinition';
Kind['DIRECTIVE_DEFINITION'] = 'DirectiveDefinition';
Kind['SCHEMA_EXTENSION'] = 'SchemaExtension';
Kind['SCALAR_TYPE_EXTENSION'] = 'ScalarTypeExtension';
Kind['OBJECT_TYPE_EXTENSION'] = 'ObjectTypeExtension';
Kind['INTERFACE_TYPE_EXTENSION'] = 'InterfaceTypeExtension';
Kind['UNION_TYPE_EXTENSION'] = 'UnionTypeExtension';
Kind['ENUM_TYPE_EXTENSION'] = 'EnumTypeExtension';
Kind['INPUT_OBJECT_TYPE_EXTENSION'] = 'InputObjectTypeExtension';
})(Kind || (exports.Kind = Kind = {}));
/**
* The enum type representing the possible kind values of AST nodes.
*
* @deprecated Please use `Kind`. Will be remove in v17.
*/

View File

@@ -0,0 +1,57 @@
/**
* The set of allowed kind values for AST nodes.
*/
var Kind;
(function (Kind) {
Kind['NAME'] = 'Name';
Kind['DOCUMENT'] = 'Document';
Kind['OPERATION_DEFINITION'] = 'OperationDefinition';
Kind['VARIABLE_DEFINITION'] = 'VariableDefinition';
Kind['SELECTION_SET'] = 'SelectionSet';
Kind['FIELD'] = 'Field';
Kind['ARGUMENT'] = 'Argument';
Kind['FRAGMENT_SPREAD'] = 'FragmentSpread';
Kind['INLINE_FRAGMENT'] = 'InlineFragment';
Kind['FRAGMENT_DEFINITION'] = 'FragmentDefinition';
Kind['VARIABLE'] = 'Variable';
Kind['INT'] = 'IntValue';
Kind['FLOAT'] = 'FloatValue';
Kind['STRING'] = 'StringValue';
Kind['BOOLEAN'] = 'BooleanValue';
Kind['NULL'] = 'NullValue';
Kind['ENUM'] = 'EnumValue';
Kind['LIST'] = 'ListValue';
Kind['OBJECT'] = 'ObjectValue';
Kind['OBJECT_FIELD'] = 'ObjectField';
Kind['DIRECTIVE'] = 'Directive';
Kind['NAMED_TYPE'] = 'NamedType';
Kind['LIST_TYPE'] = 'ListType';
Kind['NON_NULL_TYPE'] = 'NonNullType';
Kind['SCHEMA_DEFINITION'] = 'SchemaDefinition';
Kind['OPERATION_TYPE_DEFINITION'] = 'OperationTypeDefinition';
Kind['SCALAR_TYPE_DEFINITION'] = 'ScalarTypeDefinition';
Kind['OBJECT_TYPE_DEFINITION'] = 'ObjectTypeDefinition';
Kind['FIELD_DEFINITION'] = 'FieldDefinition';
Kind['INPUT_VALUE_DEFINITION'] = 'InputValueDefinition';
Kind['INTERFACE_TYPE_DEFINITION'] = 'InterfaceTypeDefinition';
Kind['UNION_TYPE_DEFINITION'] = 'UnionTypeDefinition';
Kind['ENUM_TYPE_DEFINITION'] = 'EnumTypeDefinition';
Kind['ENUM_VALUE_DEFINITION'] = 'EnumValueDefinition';
Kind['INPUT_OBJECT_TYPE_DEFINITION'] = 'InputObjectTypeDefinition';
Kind['DIRECTIVE_DEFINITION'] = 'DirectiveDefinition';
Kind['SCHEMA_EXTENSION'] = 'SchemaExtension';
Kind['SCALAR_TYPE_EXTENSION'] = 'ScalarTypeExtension';
Kind['OBJECT_TYPE_EXTENSION'] = 'ObjectTypeExtension';
Kind['INTERFACE_TYPE_EXTENSION'] = 'InterfaceTypeExtension';
Kind['UNION_TYPE_EXTENSION'] = 'UnionTypeExtension';
Kind['ENUM_TYPE_EXTENSION'] = 'EnumTypeExtension';
Kind['INPUT_OBJECT_TYPE_EXTENSION'] = 'InputObjectTypeExtension';
})(Kind || (Kind = {}));
export { Kind };
/**
* The enum type representing the possible kind values of AST nodes.
*
* @deprecated Please use `Kind`. Will be remove in v17.
*/

View File

@@ -0,0 +1,45 @@
import { Token } from './ast';
import type { Source } from './source';
import { TokenKind } from './tokenKind';
/**
* Given a Source object, creates a Lexer for that source.
* A Lexer is a stateful stream generator in that every time
* it is advanced, it returns the next token in the Source. Assuming the
* source lexes, the final Token emitted by the lexer will be of kind
* EOF, after which the lexer will repeatedly return the same EOF token
* whenever called.
*/
export declare class Lexer {
source: Source;
/**
* The previously focused non-ignored token.
*/
lastToken: Token;
/**
* The currently focused non-ignored token.
*/
token: Token;
/**
* The (1-indexed) line containing the current token.
*/
line: number;
/**
* The character offset at which the current line begins.
*/
lineStart: number;
constructor(source: Source);
get [Symbol.toStringTag](): string;
/**
* Advances the token stream to the next non-ignored token.
*/
advance(): Token;
/**
* Looks ahead and returns the next non-ignored token, but does not change
* the state of Lexer.
*/
lookahead(): Token;
}
/**
* @internal
*/
export declare function isPunctuatorTokenKind(kind: TokenKind): boolean;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,902 @@
import { syntaxError } from '../error/syntaxError.mjs';
import { Token } from './ast.mjs';
import { dedentBlockStringLines } from './blockString.mjs';
import { isDigit, isNameContinue, isNameStart } from './characterClasses.mjs';
import { TokenKind } from './tokenKind.mjs';
/**
* Given a Source object, creates a Lexer for that source.
* A Lexer is a stateful stream generator in that every time
* it is advanced, it returns the next token in the Source. Assuming the
* source lexes, the final Token emitted by the lexer will be of kind
* EOF, after which the lexer will repeatedly return the same EOF token
* whenever called.
*/
export class Lexer {
/**
* The previously focused non-ignored token.
*/
/**
* The currently focused non-ignored token.
*/
/**
* The (1-indexed) line containing the current token.
*/
/**
* The character offset at which the current line begins.
*/
constructor(source) {
const startOfFileToken = new Token(TokenKind.SOF, 0, 0, 0, 0);
this.source = source;
this.lastToken = startOfFileToken;
this.token = startOfFileToken;
this.line = 1;
this.lineStart = 0;
}
get [Symbol.toStringTag]() {
return 'Lexer';
}
/**
* Advances the token stream to the next non-ignored token.
*/
advance() {
this.lastToken = this.token;
const token = (this.token = this.lookahead());
return token;
}
/**
* Looks ahead and returns the next non-ignored token, but does not change
* the state of Lexer.
*/
lookahead() {
let token = this.token;
if (token.kind !== TokenKind.EOF) {
do {
if (token.next) {
token = token.next;
} else {
// Read the next token and form a link in the token linked-list.
const nextToken = readNextToken(this, token.end); // @ts-expect-error next is only mutable during parsing.
token.next = nextToken; // @ts-expect-error prev is only mutable during parsing.
nextToken.prev = token;
token = nextToken;
}
} while (token.kind === TokenKind.COMMENT);
}
return token;
}
}
/**
* @internal
*/
export function isPunctuatorTokenKind(kind) {
return (
kind === TokenKind.BANG ||
kind === TokenKind.DOLLAR ||
kind === TokenKind.AMP ||
kind === TokenKind.PAREN_L ||
kind === TokenKind.PAREN_R ||
kind === TokenKind.SPREAD ||
kind === TokenKind.COLON ||
kind === TokenKind.EQUALS ||
kind === TokenKind.AT ||
kind === TokenKind.BRACKET_L ||
kind === TokenKind.BRACKET_R ||
kind === TokenKind.BRACE_L ||
kind === TokenKind.PIPE ||
kind === TokenKind.BRACE_R
);
}
/**
* A Unicode scalar value is any Unicode code point except surrogate code
* points. In other words, the inclusive ranges of values 0x0000 to 0xD7FF and
* 0xE000 to 0x10FFFF.
*
* SourceCharacter ::
* - "Any Unicode scalar value"
*/
function isUnicodeScalarValue(code) {
return (
(code >= 0x0000 && code <= 0xd7ff) || (code >= 0xe000 && code <= 0x10ffff)
);
}
/**
* The GraphQL specification defines source text as a sequence of unicode scalar
* values (which Unicode defines to exclude surrogate code points). However
* JavaScript defines strings as a sequence of UTF-16 code units which may
* include surrogates. A surrogate pair is a valid source character as it
* encodes a supplementary code point (above U+FFFF), but unpaired surrogate
* code points are not valid source characters.
*/
function isSupplementaryCodePoint(body, location) {
return (
isLeadingSurrogate(body.charCodeAt(location)) &&
isTrailingSurrogate(body.charCodeAt(location + 1))
);
}
function isLeadingSurrogate(code) {
return code >= 0xd800 && code <= 0xdbff;
}
function isTrailingSurrogate(code) {
return code >= 0xdc00 && code <= 0xdfff;
}
/**
* Prints the code point (or end of file reference) at a given location in a
* source for use in error messages.
*
* Printable ASCII is printed quoted, while other points are printed in Unicode
* code point form (ie. U+1234).
*/
function printCodePointAt(lexer, location) {
const code = lexer.source.body.codePointAt(location);
if (code === undefined) {
return TokenKind.EOF;
} else if (code >= 0x0020 && code <= 0x007e) {
// Printable ASCII
const char = String.fromCodePoint(code);
return char === '"' ? "'\"'" : `"${char}"`;
} // Unicode code point
return 'U+' + code.toString(16).toUpperCase().padStart(4, '0');
}
/**
* Create a token with line and column location information.
*/
function createToken(lexer, kind, start, end, value) {
const line = lexer.line;
const col = 1 + start - lexer.lineStart;
return new Token(kind, start, end, line, col, value);
}
/**
* Gets the next token from the source starting at the given position.
*
* This skips over whitespace until it finds the next lexable token, then lexes
* punctuators immediately or calls the appropriate helper function for more
* complicated tokens.
*/
function readNextToken(lexer, start) {
const body = lexer.source.body;
const bodyLength = body.length;
let position = start;
while (position < bodyLength) {
const code = body.charCodeAt(position); // SourceCharacter
switch (code) {
// Ignored ::
// - UnicodeBOM
// - WhiteSpace
// - LineTerminator
// - Comment
// - Comma
//
// UnicodeBOM :: "Byte Order Mark (U+FEFF)"
//
// WhiteSpace ::
// - "Horizontal Tab (U+0009)"
// - "Space (U+0020)"
//
// Comma :: ,
case 0xfeff: // <BOM>
case 0x0009: // \t
case 0x0020: // <space>
case 0x002c:
// ,
++position;
continue;
// LineTerminator ::
// - "New Line (U+000A)"
// - "Carriage Return (U+000D)" [lookahead != "New Line (U+000A)"]
// - "Carriage Return (U+000D)" "New Line (U+000A)"
case 0x000a:
// \n
++position;
++lexer.line;
lexer.lineStart = position;
continue;
case 0x000d:
// \r
if (body.charCodeAt(position + 1) === 0x000a) {
position += 2;
} else {
++position;
}
++lexer.line;
lexer.lineStart = position;
continue;
// Comment
case 0x0023:
// #
return readComment(lexer, position);
// Token ::
// - Punctuator
// - Name
// - IntValue
// - FloatValue
// - StringValue
//
// Punctuator :: one of ! $ & ( ) ... : = @ [ ] { | }
case 0x0021:
// !
return createToken(lexer, TokenKind.BANG, position, position + 1);
case 0x0024:
// $
return createToken(lexer, TokenKind.DOLLAR, position, position + 1);
case 0x0026:
// &
return createToken(lexer, TokenKind.AMP, position, position + 1);
case 0x0028:
// (
return createToken(lexer, TokenKind.PAREN_L, position, position + 1);
case 0x0029:
// )
return createToken(lexer, TokenKind.PAREN_R, position, position + 1);
case 0x002e:
// .
if (
body.charCodeAt(position + 1) === 0x002e &&
body.charCodeAt(position + 2) === 0x002e
) {
return createToken(lexer, TokenKind.SPREAD, position, position + 3);
}
break;
case 0x003a:
// :
return createToken(lexer, TokenKind.COLON, position, position + 1);
case 0x003d:
// =
return createToken(lexer, TokenKind.EQUALS, position, position + 1);
case 0x0040:
// @
return createToken(lexer, TokenKind.AT, position, position + 1);
case 0x005b:
// [
return createToken(lexer, TokenKind.BRACKET_L, position, position + 1);
case 0x005d:
// ]
return createToken(lexer, TokenKind.BRACKET_R, position, position + 1);
case 0x007b:
// {
return createToken(lexer, TokenKind.BRACE_L, position, position + 1);
case 0x007c:
// |
return createToken(lexer, TokenKind.PIPE, position, position + 1);
case 0x007d:
// }
return createToken(lexer, TokenKind.BRACE_R, position, position + 1);
// StringValue
case 0x0022:
// "
if (
body.charCodeAt(position + 1) === 0x0022 &&
body.charCodeAt(position + 2) === 0x0022
) {
return readBlockString(lexer, position);
}
return readString(lexer, position);
} // IntValue | FloatValue (Digit | -)
if (isDigit(code) || code === 0x002d) {
return readNumber(lexer, position, code);
} // Name
if (isNameStart(code)) {
return readName(lexer, position);
}
throw syntaxError(
lexer.source,
position,
code === 0x0027
? 'Unexpected single quote character (\'), did you mean to use a double quote (")?'
: isUnicodeScalarValue(code) || isSupplementaryCodePoint(body, position)
? `Unexpected character: ${printCodePointAt(lexer, position)}.`
: `Invalid character: ${printCodePointAt(lexer, position)}.`,
);
}
return createToken(lexer, TokenKind.EOF, bodyLength, bodyLength);
}
/**
* Reads a comment token from the source file.
*
* ```
* Comment :: # CommentChar* [lookahead != CommentChar]
*
* CommentChar :: SourceCharacter but not LineTerminator
* ```
*/
function readComment(lexer, start) {
const body = lexer.source.body;
const bodyLength = body.length;
let position = start + 1;
while (position < bodyLength) {
const code = body.charCodeAt(position); // LineTerminator (\n | \r)
if (code === 0x000a || code === 0x000d) {
break;
} // SourceCharacter
if (isUnicodeScalarValue(code)) {
++position;
} else if (isSupplementaryCodePoint(body, position)) {
position += 2;
} else {
break;
}
}
return createToken(
lexer,
TokenKind.COMMENT,
start,
position,
body.slice(start + 1, position),
);
}
/**
* Reads a number token from the source file, either a FloatValue or an IntValue
* depending on whether a FractionalPart or ExponentPart is encountered.
*
* ```
* IntValue :: IntegerPart [lookahead != {Digit, `.`, NameStart}]
*
* IntegerPart ::
* - NegativeSign? 0
* - NegativeSign? NonZeroDigit Digit*
*
* NegativeSign :: -
*
* NonZeroDigit :: Digit but not `0`
*
* FloatValue ::
* - IntegerPart FractionalPart ExponentPart [lookahead != {Digit, `.`, NameStart}]
* - IntegerPart FractionalPart [lookahead != {Digit, `.`, NameStart}]
* - IntegerPart ExponentPart [lookahead != {Digit, `.`, NameStart}]
*
* FractionalPart :: . Digit+
*
* ExponentPart :: ExponentIndicator Sign? Digit+
*
* ExponentIndicator :: one of `e` `E`
*
* Sign :: one of + -
* ```
*/
function readNumber(lexer, start, firstCode) {
const body = lexer.source.body;
let position = start;
let code = firstCode;
let isFloat = false; // NegativeSign (-)
if (code === 0x002d) {
code = body.charCodeAt(++position);
} // Zero (0)
if (code === 0x0030) {
code = body.charCodeAt(++position);
if (isDigit(code)) {
throw syntaxError(
lexer.source,
position,
`Invalid number, unexpected digit after 0: ${printCodePointAt(
lexer,
position,
)}.`,
);
}
} else {
position = readDigits(lexer, position, code);
code = body.charCodeAt(position);
} // Full stop (.)
if (code === 0x002e) {
isFloat = true;
code = body.charCodeAt(++position);
position = readDigits(lexer, position, code);
code = body.charCodeAt(position);
} // E e
if (code === 0x0045 || code === 0x0065) {
isFloat = true;
code = body.charCodeAt(++position); // + -
if (code === 0x002b || code === 0x002d) {
code = body.charCodeAt(++position);
}
position = readDigits(lexer, position, code);
code = body.charCodeAt(position);
} // Numbers cannot be followed by . or NameStart
if (code === 0x002e || isNameStart(code)) {
throw syntaxError(
lexer.source,
position,
`Invalid number, expected digit but got: ${printCodePointAt(
lexer,
position,
)}.`,
);
}
return createToken(
lexer,
isFloat ? TokenKind.FLOAT : TokenKind.INT,
start,
position,
body.slice(start, position),
);
}
/**
* Returns the new position in the source after reading one or more digits.
*/
function readDigits(lexer, start, firstCode) {
if (!isDigit(firstCode)) {
throw syntaxError(
lexer.source,
start,
`Invalid number, expected digit but got: ${printCodePointAt(
lexer,
start,
)}.`,
);
}
const body = lexer.source.body;
let position = start + 1; // +1 to skip first firstCode
while (isDigit(body.charCodeAt(position))) {
++position;
}
return position;
}
/**
* Reads a single-quote string token from the source file.
*
* ```
* StringValue ::
* - `""` [lookahead != `"`]
* - `"` StringCharacter+ `"`
*
* StringCharacter ::
* - SourceCharacter but not `"` or `\` or LineTerminator
* - `\u` EscapedUnicode
* - `\` EscapedCharacter
*
* EscapedUnicode ::
* - `{` HexDigit+ `}`
* - HexDigit HexDigit HexDigit HexDigit
*
* EscapedCharacter :: one of `"` `\` `/` `b` `f` `n` `r` `t`
* ```
*/
function readString(lexer, start) {
const body = lexer.source.body;
const bodyLength = body.length;
let position = start + 1;
let chunkStart = position;
let value = '';
while (position < bodyLength) {
const code = body.charCodeAt(position); // Closing Quote (")
if (code === 0x0022) {
value += body.slice(chunkStart, position);
return createToken(lexer, TokenKind.STRING, start, position + 1, value);
} // Escape Sequence (\)
if (code === 0x005c) {
value += body.slice(chunkStart, position);
const escape =
body.charCodeAt(position + 1) === 0x0075 // u
? body.charCodeAt(position + 2) === 0x007b // {
? readEscapedUnicodeVariableWidth(lexer, position)
: readEscapedUnicodeFixedWidth(lexer, position)
: readEscapedCharacter(lexer, position);
value += escape.value;
position += escape.size;
chunkStart = position;
continue;
} // LineTerminator (\n | \r)
if (code === 0x000a || code === 0x000d) {
break;
} // SourceCharacter
if (isUnicodeScalarValue(code)) {
++position;
} else if (isSupplementaryCodePoint(body, position)) {
position += 2;
} else {
throw syntaxError(
lexer.source,
position,
`Invalid character within String: ${printCodePointAt(
lexer,
position,
)}.`,
);
}
}
throw syntaxError(lexer.source, position, 'Unterminated string.');
} // The string value and lexed size of an escape sequence.
function readEscapedUnicodeVariableWidth(lexer, position) {
const body = lexer.source.body;
let point = 0;
let size = 3; // Cannot be larger than 12 chars (\u{00000000}).
while (size < 12) {
const code = body.charCodeAt(position + size++); // Closing Brace (})
if (code === 0x007d) {
// Must be at least 5 chars (\u{0}) and encode a Unicode scalar value.
if (size < 5 || !isUnicodeScalarValue(point)) {
break;
}
return {
value: String.fromCodePoint(point),
size,
};
} // Append this hex digit to the code point.
point = (point << 4) | readHexDigit(code);
if (point < 0) {
break;
}
}
throw syntaxError(
lexer.source,
position,
`Invalid Unicode escape sequence: "${body.slice(
position,
position + size,
)}".`,
);
}
function readEscapedUnicodeFixedWidth(lexer, position) {
const body = lexer.source.body;
const code = read16BitHexCode(body, position + 2);
if (isUnicodeScalarValue(code)) {
return {
value: String.fromCodePoint(code),
size: 6,
};
} // GraphQL allows JSON-style surrogate pair escape sequences, but only when
// a valid pair is formed.
if (isLeadingSurrogate(code)) {
// \u
if (
body.charCodeAt(position + 6) === 0x005c &&
body.charCodeAt(position + 7) === 0x0075
) {
const trailingCode = read16BitHexCode(body, position + 8);
if (isTrailingSurrogate(trailingCode)) {
// JavaScript defines strings as a sequence of UTF-16 code units and
// encodes Unicode code points above U+FFFF using a surrogate pair of
// code units. Since this is a surrogate pair escape sequence, just
// include both codes into the JavaScript string value. Had JavaScript
// not been internally based on UTF-16, then this surrogate pair would
// be decoded to retrieve the supplementary code point.
return {
value: String.fromCodePoint(code, trailingCode),
size: 12,
};
}
}
}
throw syntaxError(
lexer.source,
position,
`Invalid Unicode escape sequence: "${body.slice(position, position + 6)}".`,
);
}
/**
* Reads four hexadecimal characters and returns the positive integer that 16bit
* hexadecimal string represents. For example, "000f" will return 15, and "dead"
* will return 57005.
*
* Returns a negative number if any char was not a valid hexadecimal digit.
*/
function read16BitHexCode(body, position) {
// readHexDigit() returns -1 on error. ORing a negative value with any other
// value always produces a negative value.
return (
(readHexDigit(body.charCodeAt(position)) << 12) |
(readHexDigit(body.charCodeAt(position + 1)) << 8) |
(readHexDigit(body.charCodeAt(position + 2)) << 4) |
readHexDigit(body.charCodeAt(position + 3))
);
}
/**
* Reads a hexadecimal character and returns its positive integer value (0-15).
*
* '0' becomes 0, '9' becomes 9
* 'A' becomes 10, 'F' becomes 15
* 'a' becomes 10, 'f' becomes 15
*
* Returns -1 if the provided character code was not a valid hexadecimal digit.
*
* HexDigit :: one of
* - `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`
* - `A` `B` `C` `D` `E` `F`
* - `a` `b` `c` `d` `e` `f`
*/
function readHexDigit(code) {
return code >= 0x0030 && code <= 0x0039 // 0-9
? code - 0x0030
: code >= 0x0041 && code <= 0x0046 // A-F
? code - 0x0037
: code >= 0x0061 && code <= 0x0066 // a-f
? code - 0x0057
: -1;
}
/**
* | Escaped Character | Code Point | Character Name |
* | ----------------- | ---------- | ---------------------------- |
* | `"` | U+0022 | double quote |
* | `\` | U+005C | reverse solidus (back slash) |
* | `/` | U+002F | solidus (forward slash) |
* | `b` | U+0008 | backspace |
* | `f` | U+000C | form feed |
* | `n` | U+000A | line feed (new line) |
* | `r` | U+000D | carriage return |
* | `t` | U+0009 | horizontal tab |
*/
function readEscapedCharacter(lexer, position) {
const body = lexer.source.body;
const code = body.charCodeAt(position + 1);
switch (code) {
case 0x0022:
// "
return {
value: '\u0022',
size: 2,
};
case 0x005c:
// \
return {
value: '\u005c',
size: 2,
};
case 0x002f:
// /
return {
value: '\u002f',
size: 2,
};
case 0x0062:
// b
return {
value: '\u0008',
size: 2,
};
case 0x0066:
// f
return {
value: '\u000c',
size: 2,
};
case 0x006e:
// n
return {
value: '\u000a',
size: 2,
};
case 0x0072:
// r
return {
value: '\u000d',
size: 2,
};
case 0x0074:
// t
return {
value: '\u0009',
size: 2,
};
}
throw syntaxError(
lexer.source,
position,
`Invalid character escape sequence: "${body.slice(
position,
position + 2,
)}".`,
);
}
/**
* Reads a block string token from the source file.
*
* ```
* StringValue ::
* - `"""` BlockStringCharacter* `"""`
*
* BlockStringCharacter ::
* - SourceCharacter but not `"""` or `\"""`
* - `\"""`
* ```
*/
function readBlockString(lexer, start) {
const body = lexer.source.body;
const bodyLength = body.length;
let lineStart = lexer.lineStart;
let position = start + 3;
let chunkStart = position;
let currentLine = '';
const blockLines = [];
while (position < bodyLength) {
const code = body.charCodeAt(position); // Closing Triple-Quote (""")
if (
code === 0x0022 &&
body.charCodeAt(position + 1) === 0x0022 &&
body.charCodeAt(position + 2) === 0x0022
) {
currentLine += body.slice(chunkStart, position);
blockLines.push(currentLine);
const token = createToken(
lexer,
TokenKind.BLOCK_STRING,
start,
position + 3, // Return a string of the lines joined with U+000A.
dedentBlockStringLines(blockLines).join('\n'),
);
lexer.line += blockLines.length - 1;
lexer.lineStart = lineStart;
return token;
} // Escaped Triple-Quote (\""")
if (
code === 0x005c &&
body.charCodeAt(position + 1) === 0x0022 &&
body.charCodeAt(position + 2) === 0x0022 &&
body.charCodeAt(position + 3) === 0x0022
) {
currentLine += body.slice(chunkStart, position);
chunkStart = position + 1; // skip only slash
position += 4;
continue;
} // LineTerminator
if (code === 0x000a || code === 0x000d) {
currentLine += body.slice(chunkStart, position);
blockLines.push(currentLine);
if (code === 0x000d && body.charCodeAt(position + 1) === 0x000a) {
position += 2;
} else {
++position;
}
currentLine = '';
chunkStart = position;
lineStart = position;
continue;
} // SourceCharacter
if (isUnicodeScalarValue(code)) {
++position;
} else if (isSupplementaryCodePoint(body, position)) {
position += 2;
} else {
throw syntaxError(
lexer.source,
position,
`Invalid character within String: ${printCodePointAt(
lexer,
position,
)}.`,
);
}
}
throw syntaxError(lexer.source, position, 'Unterminated string.');
}
/**
* Reads an alphanumeric + underscore name from the source.
*
* ```
* Name ::
* - NameStart NameContinue* [lookahead != NameContinue]
* ```
*/
function readName(lexer, start) {
const body = lexer.source.body;
const bodyLength = body.length;
let position = start + 1;
while (position < bodyLength) {
const code = body.charCodeAt(position);
if (isNameContinue(code)) {
++position;
} else {
break;
}
}
return createToken(
lexer,
TokenKind.NAME,
start,
position,
body.slice(start, position),
);
}

View File

@@ -0,0 +1,16 @@
import type { Source } from './source';
/**
* Represents a location in a Source.
*/
export interface SourceLocation {
readonly line: number;
readonly column: number;
}
/**
* Takes a Source and a UTF-8 character offset, and returns the corresponding
* line and column as a SourceLocation.
*/
export declare function getLocation(
source: Source,
position: number,
): SourceLocation;

View File

@@ -0,0 +1,38 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.getLocation = getLocation;
var _invariant = require('../jsutils/invariant.js');
const LineRegExp = /\r\n|[\n\r]/g;
/**
* Represents a location in a Source.
*/
/**
* Takes a Source and a UTF-8 character offset, and returns the corresponding
* line and column as a SourceLocation.
*/
function getLocation(source, position) {
let lastLineStart = 0;
let line = 1;
for (const match of source.body.matchAll(LineRegExp)) {
typeof match.index === 'number' || (0, _invariant.invariant)(false);
if (match.index >= position) {
break;
}
lastLineStart = match.index + match[0].length;
line += 1;
}
return {
line,
column: position + 1 - lastLineStart,
};
}

View File

@@ -0,0 +1,30 @@
import { invariant } from '../jsutils/invariant.mjs';
const LineRegExp = /\r\n|[\n\r]/g;
/**
* Represents a location in a Source.
*/
/**
* Takes a Source and a UTF-8 character offset, and returns the corresponding
* line and column as a SourceLocation.
*/
export function getLocation(source, position) {
let lastLineStart = 0;
let line = 1;
for (const match of source.body.matchAll(LineRegExp)) {
typeof match.index === 'number' || invariant(false);
if (match.index >= position) {
break;
}
lastLineStart = match.index + match[0].length;
line += 1;
}
return {
line,
column: position + 1 - lastLineStart,
};
}

View File

@@ -0,0 +1,564 @@
import type { Maybe } from '../jsutils/Maybe';
import type { GraphQLError } from '../error/GraphQLError';
import type {
ArgumentNode,
ConstArgumentNode,
ConstDirectiveNode,
ConstListValueNode,
ConstObjectFieldNode,
ConstObjectValueNode,
ConstValueNode,
DefinitionNode,
DirectiveDefinitionNode,
DirectiveNode,
DocumentNode,
EnumTypeDefinitionNode,
EnumTypeExtensionNode,
EnumValueDefinitionNode,
FieldDefinitionNode,
FieldNode,
FragmentDefinitionNode,
FragmentSpreadNode,
InlineFragmentNode,
InputObjectTypeDefinitionNode,
InputObjectTypeExtensionNode,
InputValueDefinitionNode,
InterfaceTypeDefinitionNode,
InterfaceTypeExtensionNode,
ListValueNode,
NamedTypeNode,
NameNode,
ObjectFieldNode,
ObjectTypeDefinitionNode,
ObjectTypeExtensionNode,
ObjectValueNode,
OperationDefinitionNode,
OperationTypeDefinitionNode,
ScalarTypeDefinitionNode,
ScalarTypeExtensionNode,
SchemaDefinitionNode,
SchemaExtensionNode,
SelectionNode,
SelectionSetNode,
StringValueNode,
Token,
TypeNode,
TypeSystemExtensionNode,
UnionTypeDefinitionNode,
UnionTypeExtensionNode,
ValueNode,
VariableDefinitionNode,
VariableNode,
} from './ast';
import { Location, OperationTypeNode } from './ast';
import { Lexer } from './lexer';
import { Source } from './source';
import { TokenKind } from './tokenKind';
/**
* 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;
/**
* 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;
/**
* @deprecated will be removed in the v17.0.0
*
* If enabled, the parser will understand and parse variable definitions
* contained in a fragment definition. They'll be represented in the
* `variableDefinitions` field of the FragmentDefinitionNode.
*
* The syntax is identical to normal, query-defined variables. For example:
*
* ```graphql
* fragment A($var: Boolean = false) on T {
* ...
* }
* ```
*/
allowLegacyFragmentVariables?: boolean;
}
/**
* Given a GraphQL source, parses it into a Document.
* Throws GraphQLError if a syntax error is encountered.
*/
export declare function parse(
source: string | Source,
options?: ParseOptions | undefined,
): 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().
*/
export declare function parseValue(
source: string | Source,
options?: ParseOptions | undefined,
): ValueNode;
/**
* Similar to parseValue(), but raises a parse error if it encounters a
* variable. The return type will be a constant value.
*/
export declare function parseConstValue(
source: string | Source,
options?: ParseOptions | undefined,
): 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().
*/
export declare function parseType(
source: string | Source,
options?: ParseOptions | undefined,
): TypeNode;
/**
* 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: ParseOptions;
protected _lexer: Lexer;
protected _tokenCounter: number;
constructor(source: string | Source, options?: ParseOptions);
/**
* Converts a name lex token into a name parse node.
*/
parseName(): NameNode;
/**
* Document : Definition+
*/
parseDocument(): DocumentNode;
/**
* Definition :
* - ExecutableDefinition
* - TypeSystemDefinition
* - TypeSystemExtension
*
* ExecutableDefinition :
* - OperationDefinition
* - FragmentDefinition
*
* TypeSystemDefinition :
* - SchemaDefinition
* - TypeDefinition
* - DirectiveDefinition
*
* TypeDefinition :
* - ScalarTypeDefinition
* - ObjectTypeDefinition
* - InterfaceTypeDefinition
* - UnionTypeDefinition
* - EnumTypeDefinition
* - InputObjectTypeDefinition
*/
parseDefinition(): DefinitionNode;
/**
* OperationDefinition :
* - SelectionSet
* - OperationType Name? VariableDefinitions? Directives? SelectionSet
*/
parseOperationDefinition(): OperationDefinitionNode;
/**
* OperationType : one of query mutation subscription
*/
parseOperationType(): OperationTypeNode;
/**
* VariableDefinitions : ( VariableDefinition+ )
*/
parseVariableDefinitions(): Array<VariableDefinitionNode>;
/**
* VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
*/
parseVariableDefinition(): VariableDefinitionNode;
/**
* Variable : $ Name
*/
parseVariable(): VariableNode;
/**
* ```
* SelectionSet : { Selection+ }
* ```
*/
parseSelectionSet(): SelectionSetNode;
/**
* Selection :
* - Field
* - FragmentSpread
* - InlineFragment
*/
parseSelection(): SelectionNode;
/**
* Field : Alias? Name Arguments? Directives? SelectionSet?
*
* Alias : Name :
*/
parseField(): FieldNode;
/**
* Arguments[Const] : ( Argument[?Const]+ )
*/
parseArguments(isConst: true): Array<ConstArgumentNode>;
parseArguments(isConst: boolean): Array<ArgumentNode>;
/**
* Argument[Const] : Name : Value[?Const]
*/
parseArgument(isConst: true): ConstArgumentNode;
parseArgument(isConst?: boolean): ArgumentNode;
parseConstArgument(): ConstArgumentNode;
/**
* Corresponds to both FragmentSpread and InlineFragment in the spec.
*
* FragmentSpread : ... FragmentName Directives?
*
* InlineFragment : ... TypeCondition? Directives? SelectionSet
*/
parseFragment(): FragmentSpreadNode | InlineFragmentNode;
/**
* FragmentDefinition :
* - fragment FragmentName on TypeCondition Directives? SelectionSet
*
* TypeCondition : NamedType
*/
parseFragmentDefinition(): FragmentDefinitionNode;
/**
* FragmentName : Name but not `on`
*/
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`
*/
parseValueLiteral(isConst: true): ConstValueNode;
parseValueLiteral(isConst: boolean): ValueNode;
parseConstValueLiteral(): ConstValueNode;
parseStringLiteral(): StringValueNode;
/**
* ListValue[Const] :
* - [ ]
* - [ Value[?Const]+ ]
*/
parseList(isConst: true): ConstListValueNode;
parseList(isConst: boolean): ListValueNode;
/**
* ```
* ObjectValue[Const] :
* - { }
* - { ObjectField[?Const]+ }
* ```
*/
parseObject(isConst: true): ConstObjectValueNode;
parseObject(isConst: boolean): ObjectValueNode;
/**
* ObjectField[Const] : Name : Value[?Const]
*/
parseObjectField(isConst: true): ConstObjectFieldNode;
parseObjectField(isConst: boolean): ObjectFieldNode;
/**
* Directives[Const] : Directive[?Const]+
*/
parseDirectives(isConst: true): Array<ConstDirectiveNode>;
parseDirectives(isConst: boolean): Array<DirectiveNode>;
parseConstDirectives(): Array<ConstDirectiveNode>;
/**
* ```
* Directive[Const] : @ Name Arguments[?Const]?
* ```
*/
parseDirective(isConst: true): ConstDirectiveNode;
parseDirective(isConst: boolean): DirectiveNode;
/**
* Type :
* - NamedType
* - ListType
* - NonNullType
*/
parseTypeReference(): TypeNode;
/**
* NamedType : Name
*/
parseNamedType(): NamedTypeNode;
peekDescription(): boolean;
/**
* Description : StringValue
*/
parseDescription(): undefined | StringValueNode;
/**
* ```
* SchemaDefinition : Description? schema Directives[Const]? { OperationTypeDefinition+ }
* ```
*/
parseSchemaDefinition(): SchemaDefinitionNode;
/**
* OperationTypeDefinition : OperationType : NamedType
*/
parseOperationTypeDefinition(): OperationTypeDefinitionNode;
/**
* ScalarTypeDefinition : Description? scalar Name Directives[Const]?
*/
parseScalarTypeDefinition(): ScalarTypeDefinitionNode;
/**
* ObjectTypeDefinition :
* Description?
* type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition?
*/
parseObjectTypeDefinition(): ObjectTypeDefinitionNode;
/**
* ImplementsInterfaces :
* - implements `&`? NamedType
* - ImplementsInterfaces & NamedType
*/
parseImplementsInterfaces(): Array<NamedTypeNode>;
/**
* ```
* FieldsDefinition : { FieldDefinition+ }
* ```
*/
parseFieldsDefinition(): Array<FieldDefinitionNode>;
/**
* FieldDefinition :
* - Description? Name ArgumentsDefinition? : Type Directives[Const]?
*/
parseFieldDefinition(): FieldDefinitionNode;
/**
* ArgumentsDefinition : ( InputValueDefinition+ )
*/
parseArgumentDefs(): Array<InputValueDefinitionNode>;
/**
* InputValueDefinition :
* - Description? Name : Type DefaultValue? Directives[Const]?
*/
parseInputValueDef(): InputValueDefinitionNode;
/**
* InterfaceTypeDefinition :
* - Description? interface Name Directives[Const]? FieldsDefinition?
*/
parseInterfaceTypeDefinition(): InterfaceTypeDefinitionNode;
/**
* UnionTypeDefinition :
* - Description? union Name Directives[Const]? UnionMemberTypes?
*/
parseUnionTypeDefinition(): UnionTypeDefinitionNode;
/**
* UnionMemberTypes :
* - = `|`? NamedType
* - UnionMemberTypes | NamedType
*/
parseUnionMemberTypes(): Array<NamedTypeNode>;
/**
* EnumTypeDefinition :
* - Description? enum Name Directives[Const]? EnumValuesDefinition?
*/
parseEnumTypeDefinition(): EnumTypeDefinitionNode;
/**
* ```
* EnumValuesDefinition : { EnumValueDefinition+ }
* ```
*/
parseEnumValuesDefinition(): Array<EnumValueDefinitionNode>;
/**
* EnumValueDefinition : Description? EnumValue Directives[Const]?
*/
parseEnumValueDefinition(): EnumValueDefinitionNode;
/**
* EnumValue : Name but not `true`, `false` or `null`
*/
parseEnumValueName(): NameNode;
/**
* InputObjectTypeDefinition :
* - Description? input Name Directives[Const]? InputFieldsDefinition?
*/
parseInputObjectTypeDefinition(): InputObjectTypeDefinitionNode;
/**
* ```
* InputFieldsDefinition : { InputValueDefinition+ }
* ```
*/
parseInputFieldsDefinition(): Array<InputValueDefinitionNode>;
/**
* TypeSystemExtension :
* - SchemaExtension
* - TypeExtension
*
* TypeExtension :
* - ScalarTypeExtension
* - ObjectTypeExtension
* - InterfaceTypeExtension
* - UnionTypeExtension
* - EnumTypeExtension
* - InputObjectTypeDefinition
*/
parseTypeSystemExtension(): TypeSystemExtensionNode;
/**
* ```
* SchemaExtension :
* - extend schema Directives[Const]? { OperationTypeDefinition+ }
* - extend schema Directives[Const]
* ```
*/
parseSchemaExtension(): SchemaExtensionNode;
/**
* ScalarTypeExtension :
* - extend scalar Name Directives[Const]
*/
parseScalarTypeExtension(): ScalarTypeExtensionNode;
/**
* ObjectTypeExtension :
* - extend type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition
* - extend type Name ImplementsInterfaces? Directives[Const]
* - extend type Name ImplementsInterfaces
*/
parseObjectTypeExtension(): ObjectTypeExtensionNode;
/**
* InterfaceTypeExtension :
* - extend interface Name ImplementsInterfaces? Directives[Const]? FieldsDefinition
* - extend interface Name ImplementsInterfaces? Directives[Const]
* - extend interface Name ImplementsInterfaces
*/
parseInterfaceTypeExtension(): InterfaceTypeExtensionNode;
/**
* UnionTypeExtension :
* - extend union Name Directives[Const]? UnionMemberTypes
* - extend union Name Directives[Const]
*/
parseUnionTypeExtension(): UnionTypeExtensionNode;
/**
* EnumTypeExtension :
* - extend enum Name Directives[Const]? EnumValuesDefinition
* - extend enum Name Directives[Const]
*/
parseEnumTypeExtension(): EnumTypeExtensionNode;
/**
* InputObjectTypeExtension :
* - extend input Name Directives[Const]? InputFieldsDefinition
* - extend input Name Directives[Const]
*/
parseInputObjectTypeExtension(): InputObjectTypeExtensionNode;
/**
* ```
* DirectiveDefinition :
* - Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations
* ```
*/
parseDirectiveDefinition(): DirectiveDefinitionNode;
/**
* DirectiveLocations :
* - `|`? DirectiveLocation
* - DirectiveLocations | DirectiveLocation
*/
parseDirectiveLocations(): Array<NameNode>;
parseDirectiveLocation(): NameNode;
/**
* 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.
*/
node<
T extends {
loc?: Location;
},
>(startToken: Token, node: T): T;
/**
* Determines if the next token is of a given kind
*/
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.
*/
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".
*/
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.
*/
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".
*/
expectOptionalKeyword(value: string): boolean;
/**
* Helper function for creating an error when an unexpected lexed token is encountered.
*/
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.
*/
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.
*/
optionalMany<T>(
openKind: TokenKind,
parseFn: () => T,
closeKind: TokenKind,
): Array<T>;
/**
* 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.
*/
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.
*/
delimitedMany<T>(delimiterKind: TokenKind, parseFn: () => T): Array<T>;
advanceLexer(): void;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
import type {
ASTNode,
ConstValueNode,
DefinitionNode,
ExecutableDefinitionNode,
SelectionNode,
TypeDefinitionNode,
TypeExtensionNode,
TypeNode,
TypeSystemDefinitionNode,
TypeSystemExtensionNode,
ValueNode,
} from './ast';
export declare function isDefinitionNode(node: ASTNode): node is DefinitionNode;
export declare function isExecutableDefinitionNode(
node: ASTNode,
): node is ExecutableDefinitionNode;
export declare function isSelectionNode(node: ASTNode): node is SelectionNode;
export declare function isValueNode(node: ASTNode): node is ValueNode;
export declare function isConstValueNode(node: ASTNode): node is ConstValueNode;
export declare function isTypeNode(node: ASTNode): node is TypeNode;
export declare function isTypeSystemDefinitionNode(
node: ASTNode,
): node is TypeSystemDefinitionNode;
export declare function isTypeDefinitionNode(
node: ASTNode,
): node is TypeDefinitionNode;
export declare function isTypeSystemExtensionNode(
node: ASTNode,
): node is TypeSystemExtensionNode;
export declare function isTypeExtensionNode(
node: ASTNode,
): node is TypeExtensionNode;

View File

@@ -0,0 +1,109 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.isConstValueNode = isConstValueNode;
exports.isDefinitionNode = isDefinitionNode;
exports.isExecutableDefinitionNode = isExecutableDefinitionNode;
exports.isSelectionNode = isSelectionNode;
exports.isTypeDefinitionNode = isTypeDefinitionNode;
exports.isTypeExtensionNode = isTypeExtensionNode;
exports.isTypeNode = isTypeNode;
exports.isTypeSystemDefinitionNode = isTypeSystemDefinitionNode;
exports.isTypeSystemExtensionNode = isTypeSystemExtensionNode;
exports.isValueNode = isValueNode;
var _kinds = require('./kinds.js');
function isDefinitionNode(node) {
return (
isExecutableDefinitionNode(node) ||
isTypeSystemDefinitionNode(node) ||
isTypeSystemExtensionNode(node)
);
}
function isExecutableDefinitionNode(node) {
return (
node.kind === _kinds.Kind.OPERATION_DEFINITION ||
node.kind === _kinds.Kind.FRAGMENT_DEFINITION
);
}
function isSelectionNode(node) {
return (
node.kind === _kinds.Kind.FIELD ||
node.kind === _kinds.Kind.FRAGMENT_SPREAD ||
node.kind === _kinds.Kind.INLINE_FRAGMENT
);
}
function isValueNode(node) {
return (
node.kind === _kinds.Kind.VARIABLE ||
node.kind === _kinds.Kind.INT ||
node.kind === _kinds.Kind.FLOAT ||
node.kind === _kinds.Kind.STRING ||
node.kind === _kinds.Kind.BOOLEAN ||
node.kind === _kinds.Kind.NULL ||
node.kind === _kinds.Kind.ENUM ||
node.kind === _kinds.Kind.LIST ||
node.kind === _kinds.Kind.OBJECT
);
}
function isConstValueNode(node) {
return (
isValueNode(node) &&
(node.kind === _kinds.Kind.LIST
? node.values.some(isConstValueNode)
: node.kind === _kinds.Kind.OBJECT
? node.fields.some((field) => isConstValueNode(field.value))
: node.kind !== _kinds.Kind.VARIABLE)
);
}
function isTypeNode(node) {
return (
node.kind === _kinds.Kind.NAMED_TYPE ||
node.kind === _kinds.Kind.LIST_TYPE ||
node.kind === _kinds.Kind.NON_NULL_TYPE
);
}
function isTypeSystemDefinitionNode(node) {
return (
node.kind === _kinds.Kind.SCHEMA_DEFINITION ||
isTypeDefinitionNode(node) ||
node.kind === _kinds.Kind.DIRECTIVE_DEFINITION
);
}
function isTypeDefinitionNode(node) {
return (
node.kind === _kinds.Kind.SCALAR_TYPE_DEFINITION ||
node.kind === _kinds.Kind.OBJECT_TYPE_DEFINITION ||
node.kind === _kinds.Kind.INTERFACE_TYPE_DEFINITION ||
node.kind === _kinds.Kind.UNION_TYPE_DEFINITION ||
node.kind === _kinds.Kind.ENUM_TYPE_DEFINITION ||
node.kind === _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION
);
}
function isTypeSystemExtensionNode(node) {
return (
node.kind === _kinds.Kind.SCHEMA_EXTENSION || isTypeExtensionNode(node)
);
}
function isTypeExtensionNode(node) {
return (
node.kind === _kinds.Kind.SCALAR_TYPE_EXTENSION ||
node.kind === _kinds.Kind.OBJECT_TYPE_EXTENSION ||
node.kind === _kinds.Kind.INTERFACE_TYPE_EXTENSION ||
node.kind === _kinds.Kind.UNION_TYPE_EXTENSION ||
node.kind === _kinds.Kind.ENUM_TYPE_EXTENSION ||
node.kind === _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION
);
}

View File

@@ -0,0 +1,81 @@
import { Kind } from './kinds.mjs';
export function isDefinitionNode(node) {
return (
isExecutableDefinitionNode(node) ||
isTypeSystemDefinitionNode(node) ||
isTypeSystemExtensionNode(node)
);
}
export function isExecutableDefinitionNode(node) {
return (
node.kind === Kind.OPERATION_DEFINITION ||
node.kind === Kind.FRAGMENT_DEFINITION
);
}
export function isSelectionNode(node) {
return (
node.kind === Kind.FIELD ||
node.kind === Kind.FRAGMENT_SPREAD ||
node.kind === Kind.INLINE_FRAGMENT
);
}
export function isValueNode(node) {
return (
node.kind === Kind.VARIABLE ||
node.kind === Kind.INT ||
node.kind === Kind.FLOAT ||
node.kind === Kind.STRING ||
node.kind === Kind.BOOLEAN ||
node.kind === Kind.NULL ||
node.kind === Kind.ENUM ||
node.kind === Kind.LIST ||
node.kind === Kind.OBJECT
);
}
export function isConstValueNode(node) {
return (
isValueNode(node) &&
(node.kind === Kind.LIST
? node.values.some(isConstValueNode)
: node.kind === Kind.OBJECT
? node.fields.some((field) => isConstValueNode(field.value))
: node.kind !== Kind.VARIABLE)
);
}
export function isTypeNode(node) {
return (
node.kind === Kind.NAMED_TYPE ||
node.kind === Kind.LIST_TYPE ||
node.kind === Kind.NON_NULL_TYPE
);
}
export function isTypeSystemDefinitionNode(node) {
return (
node.kind === Kind.SCHEMA_DEFINITION ||
isTypeDefinitionNode(node) ||
node.kind === Kind.DIRECTIVE_DEFINITION
);
}
export function isTypeDefinitionNode(node) {
return (
node.kind === Kind.SCALAR_TYPE_DEFINITION ||
node.kind === Kind.OBJECT_TYPE_DEFINITION ||
node.kind === Kind.INTERFACE_TYPE_DEFINITION ||
node.kind === Kind.UNION_TYPE_DEFINITION ||
node.kind === Kind.ENUM_TYPE_DEFINITION ||
node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION
);
}
export function isTypeSystemExtensionNode(node) {
return node.kind === Kind.SCHEMA_EXTENSION || isTypeExtensionNode(node);
}
export function isTypeExtensionNode(node) {
return (
node.kind === Kind.SCALAR_TYPE_EXTENSION ||
node.kind === Kind.OBJECT_TYPE_EXTENSION ||
node.kind === Kind.INTERFACE_TYPE_EXTENSION ||
node.kind === Kind.UNION_TYPE_EXTENSION ||
node.kind === Kind.ENUM_TYPE_EXTENSION ||
node.kind === Kind.INPUT_OBJECT_TYPE_EXTENSION
);
}

View File

@@ -0,0 +1,14 @@
import type { Location } from './ast';
import type { SourceLocation } from './location';
import type { Source } from './source';
/**
* Render a helpful description of the location in the GraphQL Source document.
*/
export declare function printLocation(location: Location): string;
/**
* Render a helpful description of the location in the GraphQL Source document.
*/
export declare function printSourceLocation(
source: Source,
sourceLocation: SourceLocation,
): string;

View File

@@ -0,0 +1,74 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.printLocation = printLocation;
exports.printSourceLocation = printSourceLocation;
var _location = require('./location.js');
/**
* Render a helpful description of the location in the GraphQL Source document.
*/
function printLocation(location) {
return printSourceLocation(
location.source,
(0, _location.getLocation)(location.source, location.start),
);
}
/**
* Render a helpful description of the location in the GraphQL Source document.
*/
function printSourceLocation(source, sourceLocation) {
const firstLineColumnOffset = source.locationOffset.column - 1;
const body = ''.padStart(firstLineColumnOffset) + source.body;
const lineIndex = sourceLocation.line - 1;
const lineOffset = source.locationOffset.line - 1;
const lineNum = sourceLocation.line + lineOffset;
const columnOffset = sourceLocation.line === 1 ? firstLineColumnOffset : 0;
const columnNum = sourceLocation.column + columnOffset;
const locationStr = `${source.name}:${lineNum}:${columnNum}\n`;
const lines = body.split(/\r\n|[\n\r]/g);
const locationLine = lines[lineIndex]; // Special case for minified documents
if (locationLine.length > 120) {
const subLineIndex = Math.floor(columnNum / 80);
const subLineColumnNum = columnNum % 80;
const subLines = [];
for (let i = 0; i < locationLine.length; i += 80) {
subLines.push(locationLine.slice(i, i + 80));
}
return (
locationStr +
printPrefixedLines([
[`${lineNum} |`, subLines[0]],
...subLines.slice(1, subLineIndex + 1).map((subLine) => ['|', subLine]),
['|', '^'.padStart(subLineColumnNum)],
['|', subLines[subLineIndex + 1]],
])
);
}
return (
locationStr +
printPrefixedLines([
// Lines specified like this: ["prefix", "string"],
[`${lineNum - 1} |`, lines[lineIndex - 1]],
[`${lineNum} |`, locationLine],
['|', '^'.padStart(columnNum)],
[`${lineNum + 1} |`, lines[lineIndex + 1]],
])
);
}
function printPrefixedLines(lines) {
const existingLines = lines.filter(([_, line]) => line !== undefined);
const padLen = Math.max(...existingLines.map(([prefix]) => prefix.length));
return existingLines
.map(([prefix, line]) => prefix.padStart(padLen) + (line ? ' ' + line : ''))
.join('\n');
}

View File

@@ -0,0 +1,66 @@
import { getLocation } from './location.mjs';
/**
* Render a helpful description of the location in the GraphQL Source document.
*/
export function printLocation(location) {
return printSourceLocation(
location.source,
getLocation(location.source, location.start),
);
}
/**
* Render a helpful description of the location in the GraphQL Source document.
*/
export function printSourceLocation(source, sourceLocation) {
const firstLineColumnOffset = source.locationOffset.column - 1;
const body = ''.padStart(firstLineColumnOffset) + source.body;
const lineIndex = sourceLocation.line - 1;
const lineOffset = source.locationOffset.line - 1;
const lineNum = sourceLocation.line + lineOffset;
const columnOffset = sourceLocation.line === 1 ? firstLineColumnOffset : 0;
const columnNum = sourceLocation.column + columnOffset;
const locationStr = `${source.name}:${lineNum}:${columnNum}\n`;
const lines = body.split(/\r\n|[\n\r]/g);
const locationLine = lines[lineIndex]; // Special case for minified documents
if (locationLine.length > 120) {
const subLineIndex = Math.floor(columnNum / 80);
const subLineColumnNum = columnNum % 80;
const subLines = [];
for (let i = 0; i < locationLine.length; i += 80) {
subLines.push(locationLine.slice(i, i + 80));
}
return (
locationStr +
printPrefixedLines([
[`${lineNum} |`, subLines[0]],
...subLines.slice(1, subLineIndex + 1).map((subLine) => ['|', subLine]),
['|', '^'.padStart(subLineColumnNum)],
['|', subLines[subLineIndex + 1]],
])
);
}
return (
locationStr +
printPrefixedLines([
// Lines specified like this: ["prefix", "string"],
[`${lineNum - 1} |`, lines[lineIndex - 1]],
[`${lineNum} |`, locationLine],
['|', '^'.padStart(columnNum)],
[`${lineNum + 1} |`, lines[lineIndex + 1]],
])
);
}
function printPrefixedLines(lines) {
const existingLines = lines.filter(([_, line]) => line !== undefined);
const padLen = Math.max(...existingLines.map(([prefix]) => prefix.length));
return existingLines
.map(([prefix, line]) => prefix.padStart(padLen) + (line ? ' ' + line : ''))
.join('\n');
}

View File

@@ -0,0 +1,5 @@
/**
* Prints a string as a GraphQL StringValue literal. Replaces control characters
* and excluded characters (" U+0022 and \\ U+005C) with escape sequences.
*/
export declare function printString(str: string): string;

View File

@@ -0,0 +1,183 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.printString = printString;
/**
* Prints a string as a GraphQL StringValue literal. Replaces control characters
* and excluded characters (" U+0022 and \\ U+005C) with escape sequences.
*/
function printString(str) {
return `"${str.replace(escapedRegExp, escapedReplacer)}"`;
} // eslint-disable-next-line no-control-regex
const escapedRegExp = /[\x00-\x1f\x22\x5c\x7f-\x9f]/g;
function escapedReplacer(str) {
return escapeSequences[str.charCodeAt(0)];
} // prettier-ignore
const escapeSequences = [
'\\u0000',
'\\u0001',
'\\u0002',
'\\u0003',
'\\u0004',
'\\u0005',
'\\u0006',
'\\u0007',
'\\b',
'\\t',
'\\n',
'\\u000B',
'\\f',
'\\r',
'\\u000E',
'\\u000F',
'\\u0010',
'\\u0011',
'\\u0012',
'\\u0013',
'\\u0014',
'\\u0015',
'\\u0016',
'\\u0017',
'\\u0018',
'\\u0019',
'\\u001A',
'\\u001B',
'\\u001C',
'\\u001D',
'\\u001E',
'\\u001F',
'',
'',
'\\"',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 2F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 3F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 4F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'\\\\',
'',
'',
'', // 5F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 6F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'\\u007F',
'\\u0080',
'\\u0081',
'\\u0082',
'\\u0083',
'\\u0084',
'\\u0085',
'\\u0086',
'\\u0087',
'\\u0088',
'\\u0089',
'\\u008A',
'\\u008B',
'\\u008C',
'\\u008D',
'\\u008E',
'\\u008F',
'\\u0090',
'\\u0091',
'\\u0092',
'\\u0093',
'\\u0094',
'\\u0095',
'\\u0096',
'\\u0097',
'\\u0098',
'\\u0099',
'\\u009A',
'\\u009B',
'\\u009C',
'\\u009D',
'\\u009E',
'\\u009F',
];

View File

@@ -0,0 +1,176 @@
/**
* Prints a string as a GraphQL StringValue literal. Replaces control characters
* and excluded characters (" U+0022 and \\ U+005C) with escape sequences.
*/
export function printString(str) {
return `"${str.replace(escapedRegExp, escapedReplacer)}"`;
} // eslint-disable-next-line no-control-regex
const escapedRegExp = /[\x00-\x1f\x22\x5c\x7f-\x9f]/g;
function escapedReplacer(str) {
return escapeSequences[str.charCodeAt(0)];
} // prettier-ignore
const escapeSequences = [
'\\u0000',
'\\u0001',
'\\u0002',
'\\u0003',
'\\u0004',
'\\u0005',
'\\u0006',
'\\u0007',
'\\b',
'\\t',
'\\n',
'\\u000B',
'\\f',
'\\r',
'\\u000E',
'\\u000F',
'\\u0010',
'\\u0011',
'\\u0012',
'\\u0013',
'\\u0014',
'\\u0015',
'\\u0016',
'\\u0017',
'\\u0018',
'\\u0019',
'\\u001A',
'\\u001B',
'\\u001C',
'\\u001D',
'\\u001E',
'\\u001F',
'',
'',
'\\"',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 2F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 3F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 4F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'\\\\',
'',
'',
'', // 5F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'', // 6F
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'\\u007F',
'\\u0080',
'\\u0081',
'\\u0082',
'\\u0083',
'\\u0084',
'\\u0085',
'\\u0086',
'\\u0087',
'\\u0088',
'\\u0089',
'\\u008A',
'\\u008B',
'\\u008C',
'\\u008D',
'\\u008E',
'\\u008F',
'\\u0090',
'\\u0091',
'\\u0092',
'\\u0093',
'\\u0094',
'\\u0095',
'\\u0096',
'\\u0097',
'\\u0098',
'\\u0099',
'\\u009A',
'\\u009B',
'\\u009C',
'\\u009D',
'\\u009E',
'\\u009F',
];

View File

@@ -0,0 +1,6 @@
import type { ASTNode } from './ast';
/**
* Converts an AST into a string, using one set of reasonable
* formatting rules.
*/
export declare function print(ast: ASTNode): string;

View File

@@ -0,0 +1,351 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.print = print;
var _blockString = require('./blockString.js');
var _printString = require('./printString.js');
var _visitor = require('./visitor.js');
/**
* Converts an AST into a string, using one set of reasonable
* formatting rules.
*/
function print(ast) {
return (0, _visitor.visit)(ast, printDocASTReducer);
}
const MAX_LINE_LENGTH = 80;
const printDocASTReducer = {
Name: {
leave: (node) => node.value,
},
Variable: {
leave: (node) => '$' + node.name,
},
// Document
Document: {
leave: (node) => join(node.definitions, '\n\n'),
},
OperationDefinition: {
leave(node) {
const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
const prefix = join(
[
node.operation,
join([node.name, varDefs]),
join(node.directives, ' '),
],
' ',
); // Anonymous queries with no directives or variable definitions can use
// the query short form.
return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet;
},
},
VariableDefinition: {
leave: ({ variable, type, defaultValue, directives }) =>
variable +
': ' +
type +
wrap(' = ', defaultValue) +
wrap(' ', join(directives, ' ')),
},
SelectionSet: {
leave: ({ selections }) => block(selections),
},
Field: {
leave({ alias, name, arguments: args, directives, selectionSet }) {
const prefix = wrap('', alias, ': ') + name;
let argsLine = prefix + wrap('(', join(args, ', '), ')');
if (argsLine.length > MAX_LINE_LENGTH) {
argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)');
}
return join([argsLine, join(directives, ' '), selectionSet], ' ');
},
},
Argument: {
leave: ({ name, value }) => name + ': ' + value,
},
// Fragments
FragmentSpread: {
leave: ({ name, directives }) =>
'...' + name + wrap(' ', join(directives, ' ')),
},
InlineFragment: {
leave: ({ typeCondition, directives, selectionSet }) =>
join(
[
'...',
wrap('on ', typeCondition),
join(directives, ' '),
selectionSet,
],
' ',
),
},
FragmentDefinition: {
leave: (
{ name, typeCondition, variableDefinitions, directives, selectionSet }, // Note: fragment variable definitions are experimental and may be changed
) =>
// or removed in the future.
`fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` +
`on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` +
selectionSet,
},
// Value
IntValue: {
leave: ({ value }) => value,
},
FloatValue: {
leave: ({ value }) => value,
},
StringValue: {
leave: ({ value, block: isBlockString }) =>
isBlockString
? (0, _blockString.printBlockString)(value)
: (0, _printString.printString)(value),
},
BooleanValue: {
leave: ({ value }) => (value ? 'true' : 'false'),
},
NullValue: {
leave: () => 'null',
},
EnumValue: {
leave: ({ value }) => value,
},
ListValue: {
leave: ({ values }) => '[' + join(values, ', ') + ']',
},
ObjectValue: {
leave: ({ fields }) => '{' + join(fields, ', ') + '}',
},
ObjectField: {
leave: ({ name, value }) => name + ': ' + value,
},
// Directive
Directive: {
leave: ({ name, arguments: args }) =>
'@' + name + wrap('(', join(args, ', '), ')'),
},
// Type
NamedType: {
leave: ({ name }) => name,
},
ListType: {
leave: ({ type }) => '[' + type + ']',
},
NonNullType: {
leave: ({ type }) => type + '!',
},
// Type System Definitions
SchemaDefinition: {
leave: ({ description, directives, operationTypes }) =>
wrap('', description, '\n') +
join(['schema', join(directives, ' '), block(operationTypes)], ' '),
},
OperationTypeDefinition: {
leave: ({ operation, type }) => operation + ': ' + type,
},
ScalarTypeDefinition: {
leave: ({ description, name, directives }) =>
wrap('', description, '\n') +
join(['scalar', name, join(directives, ' ')], ' '),
},
ObjectTypeDefinition: {
leave: ({ description, name, interfaces, directives, fields }) =>
wrap('', description, '\n') +
join(
[
'type',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
FieldDefinition: {
leave: ({ description, name, arguments: args, type, directives }) =>
wrap('', description, '\n') +
name +
(hasMultilineItems(args)
? wrap('(\n', indent(join(args, '\n')), '\n)')
: wrap('(', join(args, ', '), ')')) +
': ' +
type +
wrap(' ', join(directives, ' ')),
},
InputValueDefinition: {
leave: ({ description, name, type, defaultValue, directives }) =>
wrap('', description, '\n') +
join(
[name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')],
' ',
),
},
InterfaceTypeDefinition: {
leave: ({ description, name, interfaces, directives, fields }) =>
wrap('', description, '\n') +
join(
[
'interface',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
UnionTypeDefinition: {
leave: ({ description, name, directives, types }) =>
wrap('', description, '\n') +
join(
['union', name, join(directives, ' '), wrap('= ', join(types, ' | '))],
' ',
),
},
EnumTypeDefinition: {
leave: ({ description, name, directives, values }) =>
wrap('', description, '\n') +
join(['enum', name, join(directives, ' '), block(values)], ' '),
},
EnumValueDefinition: {
leave: ({ description, name, directives }) =>
wrap('', description, '\n') + join([name, join(directives, ' ')], ' '),
},
InputObjectTypeDefinition: {
leave: ({ description, name, directives, fields }) =>
wrap('', description, '\n') +
join(['input', name, join(directives, ' '), block(fields)], ' '),
},
DirectiveDefinition: {
leave: ({ description, name, arguments: args, repeatable, locations }) =>
wrap('', description, '\n') +
'directive @' +
name +
(hasMultilineItems(args)
? wrap('(\n', indent(join(args, '\n')), '\n)')
: wrap('(', join(args, ', '), ')')) +
(repeatable ? ' repeatable' : '') +
' on ' +
join(locations, ' | '),
},
SchemaExtension: {
leave: ({ directives, operationTypes }) =>
join(
['extend schema', join(directives, ' '), block(operationTypes)],
' ',
),
},
ScalarTypeExtension: {
leave: ({ name, directives }) =>
join(['extend scalar', name, join(directives, ' ')], ' '),
},
ObjectTypeExtension: {
leave: ({ name, interfaces, directives, fields }) =>
join(
[
'extend type',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
InterfaceTypeExtension: {
leave: ({ name, interfaces, directives, fields }) =>
join(
[
'extend interface',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
UnionTypeExtension: {
leave: ({ name, directives, types }) =>
join(
[
'extend union',
name,
join(directives, ' '),
wrap('= ', join(types, ' | ')),
],
' ',
),
},
EnumTypeExtension: {
leave: ({ name, directives, values }) =>
join(['extend enum', name, join(directives, ' '), block(values)], ' '),
},
InputObjectTypeExtension: {
leave: ({ name, directives, fields }) =>
join(['extend input', name, join(directives, ' '), block(fields)], ' '),
},
};
/**
* Given maybeArray, print an empty string if it is null or empty, otherwise
* print all items together separated by separator if provided
*/
function join(maybeArray, separator = '') {
var _maybeArray$filter$jo;
return (_maybeArray$filter$jo =
maybeArray === null || maybeArray === void 0
? void 0
: maybeArray.filter((x) => x).join(separator)) !== null &&
_maybeArray$filter$jo !== void 0
? _maybeArray$filter$jo
: '';
}
/**
* Given array, print each item on its own line, wrapped in an indented `{ }` block.
*/
function block(array) {
return wrap('{\n', indent(join(array, '\n')), '\n}');
}
/**
* If maybeString is not null or empty, then wrap with start and end, otherwise print an empty string.
*/
function wrap(start, maybeString, end = '') {
return maybeString != null && maybeString !== ''
? start + maybeString + end
: '';
}
function indent(str) {
return wrap(' ', str.replace(/\n/g, '\n '));
}
function hasMultilineItems(maybeArray) {
var _maybeArray$some;
// FIXME: https://github.com/graphql/graphql-js/issues/2203
/* c8 ignore next */
return (_maybeArray$some =
maybeArray === null || maybeArray === void 0
? void 0
: maybeArray.some((str) => str.includes('\n'))) !== null &&
_maybeArray$some !== void 0
? _maybeArray$some
: false;
}

View File

@@ -0,0 +1,339 @@
import { printBlockString } from './blockString.mjs';
import { printString } from './printString.mjs';
import { visit } from './visitor.mjs';
/**
* Converts an AST into a string, using one set of reasonable
* formatting rules.
*/
export function print(ast) {
return visit(ast, printDocASTReducer);
}
const MAX_LINE_LENGTH = 80;
const printDocASTReducer = {
Name: {
leave: (node) => node.value,
},
Variable: {
leave: (node) => '$' + node.name,
},
// Document
Document: {
leave: (node) => join(node.definitions, '\n\n'),
},
OperationDefinition: {
leave(node) {
const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
const prefix = join(
[
node.operation,
join([node.name, varDefs]),
join(node.directives, ' '),
],
' ',
); // Anonymous queries with no directives or variable definitions can use
// the query short form.
return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet;
},
},
VariableDefinition: {
leave: ({ variable, type, defaultValue, directives }) =>
variable +
': ' +
type +
wrap(' = ', defaultValue) +
wrap(' ', join(directives, ' ')),
},
SelectionSet: {
leave: ({ selections }) => block(selections),
},
Field: {
leave({ alias, name, arguments: args, directives, selectionSet }) {
const prefix = wrap('', alias, ': ') + name;
let argsLine = prefix + wrap('(', join(args, ', '), ')');
if (argsLine.length > MAX_LINE_LENGTH) {
argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)');
}
return join([argsLine, join(directives, ' '), selectionSet], ' ');
},
},
Argument: {
leave: ({ name, value }) => name + ': ' + value,
},
// Fragments
FragmentSpread: {
leave: ({ name, directives }) =>
'...' + name + wrap(' ', join(directives, ' ')),
},
InlineFragment: {
leave: ({ typeCondition, directives, selectionSet }) =>
join(
[
'...',
wrap('on ', typeCondition),
join(directives, ' '),
selectionSet,
],
' ',
),
},
FragmentDefinition: {
leave: (
{ name, typeCondition, variableDefinitions, directives, selectionSet }, // Note: fragment variable definitions are experimental and may be changed
) =>
// or removed in the future.
`fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` +
`on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` +
selectionSet,
},
// Value
IntValue: {
leave: ({ value }) => value,
},
FloatValue: {
leave: ({ value }) => value,
},
StringValue: {
leave: ({ value, block: isBlockString }) =>
isBlockString ? printBlockString(value) : printString(value),
},
BooleanValue: {
leave: ({ value }) => (value ? 'true' : 'false'),
},
NullValue: {
leave: () => 'null',
},
EnumValue: {
leave: ({ value }) => value,
},
ListValue: {
leave: ({ values }) => '[' + join(values, ', ') + ']',
},
ObjectValue: {
leave: ({ fields }) => '{' + join(fields, ', ') + '}',
},
ObjectField: {
leave: ({ name, value }) => name + ': ' + value,
},
// Directive
Directive: {
leave: ({ name, arguments: args }) =>
'@' + name + wrap('(', join(args, ', '), ')'),
},
// Type
NamedType: {
leave: ({ name }) => name,
},
ListType: {
leave: ({ type }) => '[' + type + ']',
},
NonNullType: {
leave: ({ type }) => type + '!',
},
// Type System Definitions
SchemaDefinition: {
leave: ({ description, directives, operationTypes }) =>
wrap('', description, '\n') +
join(['schema', join(directives, ' '), block(operationTypes)], ' '),
},
OperationTypeDefinition: {
leave: ({ operation, type }) => operation + ': ' + type,
},
ScalarTypeDefinition: {
leave: ({ description, name, directives }) =>
wrap('', description, '\n') +
join(['scalar', name, join(directives, ' ')], ' '),
},
ObjectTypeDefinition: {
leave: ({ description, name, interfaces, directives, fields }) =>
wrap('', description, '\n') +
join(
[
'type',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
FieldDefinition: {
leave: ({ description, name, arguments: args, type, directives }) =>
wrap('', description, '\n') +
name +
(hasMultilineItems(args)
? wrap('(\n', indent(join(args, '\n')), '\n)')
: wrap('(', join(args, ', '), ')')) +
': ' +
type +
wrap(' ', join(directives, ' ')),
},
InputValueDefinition: {
leave: ({ description, name, type, defaultValue, directives }) =>
wrap('', description, '\n') +
join(
[name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')],
' ',
),
},
InterfaceTypeDefinition: {
leave: ({ description, name, interfaces, directives, fields }) =>
wrap('', description, '\n') +
join(
[
'interface',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
UnionTypeDefinition: {
leave: ({ description, name, directives, types }) =>
wrap('', description, '\n') +
join(
['union', name, join(directives, ' '), wrap('= ', join(types, ' | '))],
' ',
),
},
EnumTypeDefinition: {
leave: ({ description, name, directives, values }) =>
wrap('', description, '\n') +
join(['enum', name, join(directives, ' '), block(values)], ' '),
},
EnumValueDefinition: {
leave: ({ description, name, directives }) =>
wrap('', description, '\n') + join([name, join(directives, ' ')], ' '),
},
InputObjectTypeDefinition: {
leave: ({ description, name, directives, fields }) =>
wrap('', description, '\n') +
join(['input', name, join(directives, ' '), block(fields)], ' '),
},
DirectiveDefinition: {
leave: ({ description, name, arguments: args, repeatable, locations }) =>
wrap('', description, '\n') +
'directive @' +
name +
(hasMultilineItems(args)
? wrap('(\n', indent(join(args, '\n')), '\n)')
: wrap('(', join(args, ', '), ')')) +
(repeatable ? ' repeatable' : '') +
' on ' +
join(locations, ' | '),
},
SchemaExtension: {
leave: ({ directives, operationTypes }) =>
join(
['extend schema', join(directives, ' '), block(operationTypes)],
' ',
),
},
ScalarTypeExtension: {
leave: ({ name, directives }) =>
join(['extend scalar', name, join(directives, ' ')], ' '),
},
ObjectTypeExtension: {
leave: ({ name, interfaces, directives, fields }) =>
join(
[
'extend type',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
InterfaceTypeExtension: {
leave: ({ name, interfaces, directives, fields }) =>
join(
[
'extend interface',
name,
wrap('implements ', join(interfaces, ' & ')),
join(directives, ' '),
block(fields),
],
' ',
),
},
UnionTypeExtension: {
leave: ({ name, directives, types }) =>
join(
[
'extend union',
name,
join(directives, ' '),
wrap('= ', join(types, ' | ')),
],
' ',
),
},
EnumTypeExtension: {
leave: ({ name, directives, values }) =>
join(['extend enum', name, join(directives, ' '), block(values)], ' '),
},
InputObjectTypeExtension: {
leave: ({ name, directives, fields }) =>
join(['extend input', name, join(directives, ' '), block(fields)], ' '),
},
};
/**
* Given maybeArray, print an empty string if it is null or empty, otherwise
* print all items together separated by separator if provided
*/
function join(maybeArray, separator = '') {
var _maybeArray$filter$jo;
return (_maybeArray$filter$jo =
maybeArray === null || maybeArray === void 0
? void 0
: maybeArray.filter((x) => x).join(separator)) !== null &&
_maybeArray$filter$jo !== void 0
? _maybeArray$filter$jo
: '';
}
/**
* Given array, print each item on its own line, wrapped in an indented `{ }` block.
*/
function block(array) {
return wrap('{\n', indent(join(array, '\n')), '\n}');
}
/**
* If maybeString is not null or empty, then wrap with start and end, otherwise print an empty string.
*/
function wrap(start, maybeString, end = '') {
return maybeString != null && maybeString !== ''
? start + maybeString + end
: '';
}
function indent(str) {
return wrap(' ', str.replace(/\n/g, '\n '));
}
function hasMultilineItems(maybeArray) {
var _maybeArray$some;
// FIXME: https://github.com/graphql/graphql-js/issues/2203
/* c8 ignore next */
return (_maybeArray$some =
maybeArray === null || maybeArray === void 0
? void 0
: maybeArray.some((str) => str.includes('\n'))) !== null &&
_maybeArray$some !== void 0
? _maybeArray$some
: false;
}

View File

@@ -0,0 +1,25 @@
interface Location {
line: number;
column: number;
}
/**
* A representation of source input to GraphQL. The `name` and `locationOffset` parameters are
* optional, but they are useful for clients who store GraphQL documents in source files.
* For example, if the GraphQL input starts at line 40 in a file named `Foo.graphql`, it might
* be useful for `name` to be `"Foo.graphql"` and location to be `{ line: 40, column: 1 }`.
* The `line` and `column` properties in `locationOffset` are 1-indexed.
*/
export declare class Source {
body: string;
name: string;
locationOffset: Location;
constructor(body: string, name?: string, locationOffset?: Location);
get [Symbol.toStringTag](): string;
}
/**
* Test if the given value is a Source object.
*
* @internal
*/
export declare function isSource(source: unknown): source is Source;
export {};

View File

@@ -0,0 +1,65 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.Source = void 0;
exports.isSource = isSource;
var _devAssert = require('../jsutils/devAssert.js');
var _inspect = require('../jsutils/inspect.js');
var _instanceOf = require('../jsutils/instanceOf.js');
/**
* A representation of source input to GraphQL. The `name` and `locationOffset` parameters are
* optional, but they are useful for clients who store GraphQL documents in source files.
* For example, if the GraphQL input starts at line 40 in a file named `Foo.graphql`, it might
* be useful for `name` to be `"Foo.graphql"` and location to be `{ line: 40, column: 1 }`.
* The `line` and `column` properties in `locationOffset` are 1-indexed.
*/
class Source {
constructor(
body,
name = 'GraphQL request',
locationOffset = {
line: 1,
column: 1,
},
) {
typeof body === 'string' ||
(0, _devAssert.devAssert)(
false,
`Body must be a string. Received: ${(0, _inspect.inspect)(body)}.`,
);
this.body = body;
this.name = name;
this.locationOffset = locationOffset;
this.locationOffset.line > 0 ||
(0, _devAssert.devAssert)(
false,
'line in locationOffset is 1-indexed and must be positive.',
);
this.locationOffset.column > 0 ||
(0, _devAssert.devAssert)(
false,
'column in locationOffset is 1-indexed and must be positive.',
);
}
get [Symbol.toStringTag]() {
return 'Source';
}
}
/**
* Test if the given value is a Source object.
*
* @internal
*/
exports.Source = Source;
function isSource(source) {
return (0, _instanceOf.instanceOf)(source, Source);
}

View File

@@ -0,0 +1,50 @@
import { devAssert } from '../jsutils/devAssert.mjs';
import { inspect } from '../jsutils/inspect.mjs';
import { instanceOf } from '../jsutils/instanceOf.mjs';
/**
* A representation of source input to GraphQL. The `name` and `locationOffset` parameters are
* optional, but they are useful for clients who store GraphQL documents in source files.
* For example, if the GraphQL input starts at line 40 in a file named `Foo.graphql`, it might
* be useful for `name` to be `"Foo.graphql"` and location to be `{ line: 40, column: 1 }`.
* The `line` and `column` properties in `locationOffset` are 1-indexed.
*/
export class Source {
constructor(
body,
name = 'GraphQL request',
locationOffset = {
line: 1,
column: 1,
},
) {
typeof body === 'string' ||
devAssert(false, `Body must be a string. Received: ${inspect(body)}.`);
this.body = body;
this.name = name;
this.locationOffset = locationOffset;
this.locationOffset.line > 0 ||
devAssert(
false,
'line in locationOffset is 1-indexed and must be positive.',
);
this.locationOffset.column > 0 ||
devAssert(
false,
'column in locationOffset is 1-indexed and must be positive.',
);
}
get [Symbol.toStringTag]() {
return 'Source';
}
}
/**
* Test if the given value is a Source object.
*
* @internal
*/
export function isSource(source) {
return instanceOf(source, Source);
}

View File

@@ -0,0 +1,35 @@
/**
* An exported enum describing the different kinds of tokens that the
* lexer emits.
*/
declare enum TokenKind {
SOF = '<SOF>',
EOF = '<EOF>',
BANG = '!',
DOLLAR = '$',
AMP = '&',
PAREN_L = '(',
PAREN_R = ')',
SPREAD = '...',
COLON = ':',
EQUALS = '=',
AT = '@',
BRACKET_L = '[',
BRACKET_R = ']',
BRACE_L = '{',
PIPE = '|',
BRACE_R = '}',
NAME = 'Name',
INT = 'Int',
FLOAT = 'Float',
STRING = 'String',
BLOCK_STRING = 'BlockString',
COMMENT = 'Comment',
}
export { TokenKind };
/**
* The enum type representing the token kinds values.
*
* @deprecated Please use `TokenKind`. Will be remove in v17.
*/
export declare type TokenKindEnum = typeof TokenKind;

View File

@@ -0,0 +1,43 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.TokenKind = void 0;
/**
* An exported enum describing the different kinds of tokens that the
* lexer emits.
*/
var TokenKind;
exports.TokenKind = TokenKind;
(function (TokenKind) {
TokenKind['SOF'] = '<SOF>';
TokenKind['EOF'] = '<EOF>';
TokenKind['BANG'] = '!';
TokenKind['DOLLAR'] = '$';
TokenKind['AMP'] = '&';
TokenKind['PAREN_L'] = '(';
TokenKind['PAREN_R'] = ')';
TokenKind['SPREAD'] = '...';
TokenKind['COLON'] = ':';
TokenKind['EQUALS'] = '=';
TokenKind['AT'] = '@';
TokenKind['BRACKET_L'] = '[';
TokenKind['BRACKET_R'] = ']';
TokenKind['BRACE_L'] = '{';
TokenKind['PIPE'] = '|';
TokenKind['BRACE_R'] = '}';
TokenKind['NAME'] = 'Name';
TokenKind['INT'] = 'Int';
TokenKind['FLOAT'] = 'Float';
TokenKind['STRING'] = 'String';
TokenKind['BLOCK_STRING'] = 'BlockString';
TokenKind['COMMENT'] = 'Comment';
})(TokenKind || (exports.TokenKind = TokenKind = {}));
/**
* The enum type representing the token kinds values.
*
* @deprecated Please use `TokenKind`. Will be remove in v17.
*/

View File

@@ -0,0 +1,37 @@
/**
* An exported enum describing the different kinds of tokens that the
* lexer emits.
*/
var TokenKind;
(function (TokenKind) {
TokenKind['SOF'] = '<SOF>';
TokenKind['EOF'] = '<EOF>';
TokenKind['BANG'] = '!';
TokenKind['DOLLAR'] = '$';
TokenKind['AMP'] = '&';
TokenKind['PAREN_L'] = '(';
TokenKind['PAREN_R'] = ')';
TokenKind['SPREAD'] = '...';
TokenKind['COLON'] = ':';
TokenKind['EQUALS'] = '=';
TokenKind['AT'] = '@';
TokenKind['BRACKET_L'] = '[';
TokenKind['BRACKET_R'] = ']';
TokenKind['BRACE_L'] = '{';
TokenKind['PIPE'] = '|';
TokenKind['BRACE_R'] = '}';
TokenKind['NAME'] = 'Name';
TokenKind['INT'] = 'Int';
TokenKind['FLOAT'] = 'Float';
TokenKind['STRING'] = 'String';
TokenKind['BLOCK_STRING'] = 'BlockString';
TokenKind['COMMENT'] = 'Comment';
})(TokenKind || (TokenKind = {}));
export { TokenKind };
/**
* The enum type representing the token kinds values.
*
* @deprecated Please use `TokenKind`. Will be remove in v17.
*/

View File

@@ -0,0 +1,194 @@
import type { ASTNode } from './ast';
import { Kind } from './kinds';
/**
* A visitor is provided to visit, it contains the collection of
* relevant functions to be called during the visitor's traversal.
*/
export declare type ASTVisitor = EnterLeaveVisitor<ASTNode> | KindVisitor;
declare type KindVisitor = {
readonly [NodeT in ASTNode as NodeT['kind']]?:
| ASTVisitFn<NodeT>
| EnterLeaveVisitor<NodeT>;
};
interface EnterLeaveVisitor<TVisitedNode extends ASTNode> {
readonly enter?: ASTVisitFn<TVisitedNode>;
readonly leave?: ASTVisitFn<TVisitedNode>;
}
/**
* A visitor is comprised of visit functions, which are called on each node
* during the visitor's traversal.
*/
export declare type ASTVisitFn<TVisitedNode extends ASTNode> = (
/** The current node being visiting. */
node: TVisitedNode,
/** The index or key to this node from the parent node or Array. */
key: string | number | undefined,
/** The parent immediately above this node, which may be an Array. */
parent: ASTNode | ReadonlyArray<ASTNode> | undefined,
/** The key path to get to this node from the root node. */
path: ReadonlyArray<string | number>,
/**
* All nodes and Arrays visited before reaching parent of this node.
* These correspond to array indices in `path`.
* Note: ancestors includes arrays which contain the parent of visited node.
*/
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>,
) => any;
/**
* A reducer is comprised of reducer functions which convert AST nodes into
* another form.
*/
export declare type ASTReducer<R> = {
readonly [NodeT in ASTNode as NodeT['kind']]?: {
readonly enter?: ASTVisitFn<NodeT>;
readonly leave: ASTReducerFn<NodeT, R>;
};
};
declare type ASTReducerFn<TReducedNode extends ASTNode, R> = (
/** The current node being visiting. */
node: {
[K in keyof TReducedNode]: ReducedField<TReducedNode[K], R>;
},
/** The index or key to this node from the parent node or Array. */
key: string | number | undefined,
/** The parent immediately above this node, which may be an Array. */
parent: ASTNode | ReadonlyArray<ASTNode> | undefined,
/** The key path to get to this node from the root node. */
path: ReadonlyArray<string | number>,
/**
* All nodes and Arrays visited before reaching parent of this node.
* These correspond to array indices in `path`.
* Note: ancestors includes arrays which contain the parent of visited node.
*/
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>,
) => R;
declare type ReducedField<T, R> = T extends null | undefined
? T
: T extends ReadonlyArray<any>
? ReadonlyArray<R>
: R;
/**
* A KeyMap describes each the traversable properties of each kind of node.
*
* @deprecated Please inline it. Will be removed in v17
*/
export declare type ASTVisitorKeyMap = {
[NodeT in ASTNode as NodeT['kind']]?: ReadonlyArray<keyof NodeT>;
};
export declare const BREAK: unknown;
/**
* visit() will walk through an AST using a depth-first traversal, calling
* the visitor's enter function at each node in the traversal, and calling the
* leave function after visiting that node and all of its child nodes.
*
* By returning different values from the enter and leave functions, the
* behavior of the visitor can be altered, including skipping over a sub-tree of
* the AST (by returning false), editing the AST by returning a value or null
* to remove the value, or to stop the whole traversal by returning BREAK.
*
* When using visit() to edit an AST, the original AST will not be modified, and
* a new version of the AST with the changes applied will be returned from the
* visit function.
*
* ```ts
* const editedAST = visit(ast, {
* enter(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: skip visiting this node
* // visitor.BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* },
* leave(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: no action
* // visitor.BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* }
* });
* ```
*
* Alternatively to providing enter() and leave() functions, a visitor can
* instead provide functions named the same as the kinds of AST nodes, or
* enter/leave visitors at a named key, leading to three permutations of the
* visitor API:
*
* 1) Named visitors triggered when entering a node of a specific kind.
*
* ```ts
* visit(ast, {
* Kind(node) {
* // enter the "Kind" node
* }
* })
* ```
*
* 2) Named visitors that trigger upon entering and leaving a node of a specific kind.
*
* ```ts
* visit(ast, {
* Kind: {
* enter(node) {
* // enter the "Kind" node
* }
* leave(node) {
* // leave the "Kind" node
* }
* }
* })
* ```
*
* 3) Generic visitors that trigger upon entering and leaving any node.
*
* ```ts
* visit(ast, {
* enter(node) {
* // enter any node
* },
* leave(node) {
* // leave any node
* }
* })
* ```
*/
export declare function visit<N extends ASTNode>(
root: N,
visitor: ASTVisitor,
visitorKeys?: ASTVisitorKeyMap,
): N;
export declare function visit<R>(
root: ASTNode,
visitor: ASTReducer<R>,
visitorKeys?: ASTVisitorKeyMap,
): R;
/**
* Creates a new visitor instance which delegates to many visitors to run in
* parallel. Each visitor will be visited for each node before moving on.
*
* If a prior visitor edits a node, no following visitors will see that node.
*/
export declare function visitInParallel(
visitors: ReadonlyArray<ASTVisitor>,
): ASTVisitor;
/**
* Given a visitor instance and a node kind, return EnterLeaveVisitor for that kind.
*/
export declare function getEnterLeaveForKind(
visitor: ASTVisitor,
kind: Kind,
): EnterLeaveVisitor<ASTNode>;
/**
* Given a visitor instance, if it is leaving or not, and a node kind, return
* the function the visitor runtime should call.
*
* @deprecated Please use `getEnterLeaveForKind` instead. Will be removed in v17
*/
export declare function getVisitFn(
visitor: ASTVisitor,
kind: Kind,
isLeaving: boolean,
): ASTVisitFn<ASTNode> | undefined;
export {};

View File

@@ -0,0 +1,377 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.BREAK = void 0;
exports.getEnterLeaveForKind = getEnterLeaveForKind;
exports.getVisitFn = getVisitFn;
exports.visit = visit;
exports.visitInParallel = visitInParallel;
var _devAssert = require('../jsutils/devAssert.js');
var _inspect = require('../jsutils/inspect.js');
var _ast = require('./ast.js');
var _kinds = require('./kinds.js');
const BREAK = Object.freeze({});
/**
* visit() will walk through an AST using a depth-first traversal, calling
* the visitor's enter function at each node in the traversal, and calling the
* leave function after visiting that node and all of its child nodes.
*
* By returning different values from the enter and leave functions, the
* behavior of the visitor can be altered, including skipping over a sub-tree of
* the AST (by returning false), editing the AST by returning a value or null
* to remove the value, or to stop the whole traversal by returning BREAK.
*
* When using visit() to edit an AST, the original AST will not be modified, and
* a new version of the AST with the changes applied will be returned from the
* visit function.
*
* ```ts
* const editedAST = visit(ast, {
* enter(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: skip visiting this node
* // visitor.BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* },
* leave(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: no action
* // visitor.BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* }
* });
* ```
*
* Alternatively to providing enter() and leave() functions, a visitor can
* instead provide functions named the same as the kinds of AST nodes, or
* enter/leave visitors at a named key, leading to three permutations of the
* visitor API:
*
* 1) Named visitors triggered when entering a node of a specific kind.
*
* ```ts
* visit(ast, {
* Kind(node) {
* // enter the "Kind" node
* }
* })
* ```
*
* 2) Named visitors that trigger upon entering and leaving a node of a specific kind.
*
* ```ts
* visit(ast, {
* Kind: {
* enter(node) {
* // enter the "Kind" node
* }
* leave(node) {
* // leave the "Kind" node
* }
* }
* })
* ```
*
* 3) Generic visitors that trigger upon entering and leaving any node.
*
* ```ts
* visit(ast, {
* enter(node) {
* // enter any node
* },
* leave(node) {
* // leave any node
* }
* })
* ```
*/
exports.BREAK = BREAK;
function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) {
const enterLeaveMap = new Map();
for (const kind of Object.values(_kinds.Kind)) {
enterLeaveMap.set(kind, getEnterLeaveForKind(visitor, kind));
}
/* eslint-disable no-undef-init */
let stack = undefined;
let inArray = Array.isArray(root);
let keys = [root];
let index = -1;
let edits = [];
let node = root;
let key = undefined;
let parent = undefined;
const path = [];
const ancestors = [];
/* eslint-enable no-undef-init */
do {
index++;
const isLeaving = index === keys.length;
const isEdited = isLeaving && edits.length !== 0;
if (isLeaving) {
key = ancestors.length === 0 ? undefined : path[path.length - 1];
node = parent;
parent = ancestors.pop();
if (isEdited) {
if (inArray) {
node = node.slice();
let editOffset = 0;
for (const [editKey, editValue] of edits) {
const arrayKey = editKey - editOffset;
if (editValue === null) {
node.splice(arrayKey, 1);
editOffset++;
} else {
node[arrayKey] = editValue;
}
}
} else {
node = Object.defineProperties(
{},
Object.getOwnPropertyDescriptors(node),
);
for (const [editKey, editValue] of edits) {
node[editKey] = editValue;
}
}
}
index = stack.index;
keys = stack.keys;
edits = stack.edits;
inArray = stack.inArray;
stack = stack.prev;
} else if (parent) {
key = inArray ? index : keys[index];
node = parent[key];
if (node === null || node === undefined) {
continue;
}
path.push(key);
}
let result;
if (!Array.isArray(node)) {
var _enterLeaveMap$get, _enterLeaveMap$get2;
(0, _ast.isNode)(node) ||
(0, _devAssert.devAssert)(
false,
`Invalid AST Node: ${(0, _inspect.inspect)(node)}.`,
);
const visitFn = isLeaving
? (_enterLeaveMap$get = enterLeaveMap.get(node.kind)) === null ||
_enterLeaveMap$get === void 0
? void 0
: _enterLeaveMap$get.leave
: (_enterLeaveMap$get2 = enterLeaveMap.get(node.kind)) === null ||
_enterLeaveMap$get2 === void 0
? void 0
: _enterLeaveMap$get2.enter;
result =
visitFn === null || visitFn === void 0
? void 0
: visitFn.call(visitor, node, key, parent, path, ancestors);
if (result === BREAK) {
break;
}
if (result === false) {
if (!isLeaving) {
path.pop();
continue;
}
} else if (result !== undefined) {
edits.push([key, result]);
if (!isLeaving) {
if ((0, _ast.isNode)(result)) {
node = result;
} else {
path.pop();
continue;
}
}
}
}
if (result === undefined && isEdited) {
edits.push([key, node]);
}
if (isLeaving) {
path.pop();
} else {
var _node$kind;
stack = {
inArray,
index,
keys,
edits,
prev: stack,
};
inArray = Array.isArray(node);
keys = inArray
? node
: (_node$kind = visitorKeys[node.kind]) !== null &&
_node$kind !== void 0
? _node$kind
: [];
index = -1;
edits = [];
if (parent) {
ancestors.push(parent);
}
parent = node;
}
} while (stack !== undefined);
if (edits.length !== 0) {
// New root
return edits[edits.length - 1][1];
}
return root;
}
/**
* Creates a new visitor instance which delegates to many visitors to run in
* parallel. Each visitor will be visited for each node before moving on.
*
* If a prior visitor edits a node, no following visitors will see that node.
*/
function visitInParallel(visitors) {
const skipping = new Array(visitors.length).fill(null);
const mergedVisitor = Object.create(null);
for (const kind of Object.values(_kinds.Kind)) {
let hasVisitor = false;
const enterList = new Array(visitors.length).fill(undefined);
const leaveList = new Array(visitors.length).fill(undefined);
for (let i = 0; i < visitors.length; ++i) {
const { enter, leave } = getEnterLeaveForKind(visitors[i], kind);
hasVisitor || (hasVisitor = enter != null || leave != null);
enterList[i] = enter;
leaveList[i] = leave;
}
if (!hasVisitor) {
continue;
}
const mergedEnterLeave = {
enter(...args) {
const node = args[0];
for (let i = 0; i < visitors.length; i++) {
if (skipping[i] === null) {
var _enterList$i;
const result =
(_enterList$i = enterList[i]) === null || _enterList$i === void 0
? void 0
: _enterList$i.apply(visitors[i], args);
if (result === false) {
skipping[i] = node;
} else if (result === BREAK) {
skipping[i] = BREAK;
} else if (result !== undefined) {
return result;
}
}
}
},
leave(...args) {
const node = args[0];
for (let i = 0; i < visitors.length; i++) {
if (skipping[i] === null) {
var _leaveList$i;
const result =
(_leaveList$i = leaveList[i]) === null || _leaveList$i === void 0
? void 0
: _leaveList$i.apply(visitors[i], args);
if (result === BREAK) {
skipping[i] = BREAK;
} else if (result !== undefined && result !== false) {
return result;
}
} else if (skipping[i] === node) {
skipping[i] = null;
}
}
},
};
mergedVisitor[kind] = mergedEnterLeave;
}
return mergedVisitor;
}
/**
* Given a visitor instance and a node kind, return EnterLeaveVisitor for that kind.
*/
function getEnterLeaveForKind(visitor, kind) {
const kindVisitor = visitor[kind];
if (typeof kindVisitor === 'object') {
// { Kind: { enter() {}, leave() {} } }
return kindVisitor;
} else if (typeof kindVisitor === 'function') {
// { Kind() {} }
return {
enter: kindVisitor,
leave: undefined,
};
} // { enter() {}, leave() {} }
return {
enter: visitor.enter,
leave: visitor.leave,
};
}
/**
* Given a visitor instance, if it is leaving or not, and a node kind, return
* the function the visitor runtime should call.
*
* @deprecated Please use `getEnterLeaveForKind` instead. Will be removed in v17
*/
/* c8 ignore next 8 */
function getVisitFn(visitor, kind, isLeaving) {
const { enter, leave } = getEnterLeaveForKind(visitor, kind);
return isLeaving ? leave : enter;
}

View File

@@ -0,0 +1,361 @@
import { devAssert } from '../jsutils/devAssert.mjs';
import { inspect } from '../jsutils/inspect.mjs';
import { isNode, QueryDocumentKeys } from './ast.mjs';
import { Kind } from './kinds.mjs';
/**
* A visitor is provided to visit, it contains the collection of
* relevant functions to be called during the visitor's traversal.
*/
export const BREAK = Object.freeze({});
/**
* visit() will walk through an AST using a depth-first traversal, calling
* the visitor's enter function at each node in the traversal, and calling the
* leave function after visiting that node and all of its child nodes.
*
* By returning different values from the enter and leave functions, the
* behavior of the visitor can be altered, including skipping over a sub-tree of
* the AST (by returning false), editing the AST by returning a value or null
* to remove the value, or to stop the whole traversal by returning BREAK.
*
* When using visit() to edit an AST, the original AST will not be modified, and
* a new version of the AST with the changes applied will be returned from the
* visit function.
*
* ```ts
* const editedAST = visit(ast, {
* enter(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: skip visiting this node
* // visitor.BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* },
* leave(node, key, parent, path, ancestors) {
* // @return
* // undefined: no action
* // false: no action
* // visitor.BREAK: stop visiting altogether
* // null: delete this node
* // any value: replace this node with the returned value
* }
* });
* ```
*
* Alternatively to providing enter() and leave() functions, a visitor can
* instead provide functions named the same as the kinds of AST nodes, or
* enter/leave visitors at a named key, leading to three permutations of the
* visitor API:
*
* 1) Named visitors triggered when entering a node of a specific kind.
*
* ```ts
* visit(ast, {
* Kind(node) {
* // enter the "Kind" node
* }
* })
* ```
*
* 2) Named visitors that trigger upon entering and leaving a node of a specific kind.
*
* ```ts
* visit(ast, {
* Kind: {
* enter(node) {
* // enter the "Kind" node
* }
* leave(node) {
* // leave the "Kind" node
* }
* }
* })
* ```
*
* 3) Generic visitors that trigger upon entering and leaving any node.
*
* ```ts
* visit(ast, {
* enter(node) {
* // enter any node
* },
* leave(node) {
* // leave any node
* }
* })
* ```
*/
export function visit(root, visitor, visitorKeys = QueryDocumentKeys) {
const enterLeaveMap = new Map();
for (const kind of Object.values(Kind)) {
enterLeaveMap.set(kind, getEnterLeaveForKind(visitor, kind));
}
/* eslint-disable no-undef-init */
let stack = undefined;
let inArray = Array.isArray(root);
let keys = [root];
let index = -1;
let edits = [];
let node = root;
let key = undefined;
let parent = undefined;
const path = [];
const ancestors = [];
/* eslint-enable no-undef-init */
do {
index++;
const isLeaving = index === keys.length;
const isEdited = isLeaving && edits.length !== 0;
if (isLeaving) {
key = ancestors.length === 0 ? undefined : path[path.length - 1];
node = parent;
parent = ancestors.pop();
if (isEdited) {
if (inArray) {
node = node.slice();
let editOffset = 0;
for (const [editKey, editValue] of edits) {
const arrayKey = editKey - editOffset;
if (editValue === null) {
node.splice(arrayKey, 1);
editOffset++;
} else {
node[arrayKey] = editValue;
}
}
} else {
node = Object.defineProperties(
{},
Object.getOwnPropertyDescriptors(node),
);
for (const [editKey, editValue] of edits) {
node[editKey] = editValue;
}
}
}
index = stack.index;
keys = stack.keys;
edits = stack.edits;
inArray = stack.inArray;
stack = stack.prev;
} else if (parent) {
key = inArray ? index : keys[index];
node = parent[key];
if (node === null || node === undefined) {
continue;
}
path.push(key);
}
let result;
if (!Array.isArray(node)) {
var _enterLeaveMap$get, _enterLeaveMap$get2;
isNode(node) || devAssert(false, `Invalid AST Node: ${inspect(node)}.`);
const visitFn = isLeaving
? (_enterLeaveMap$get = enterLeaveMap.get(node.kind)) === null ||
_enterLeaveMap$get === void 0
? void 0
: _enterLeaveMap$get.leave
: (_enterLeaveMap$get2 = enterLeaveMap.get(node.kind)) === null ||
_enterLeaveMap$get2 === void 0
? void 0
: _enterLeaveMap$get2.enter;
result =
visitFn === null || visitFn === void 0
? void 0
: visitFn.call(visitor, node, key, parent, path, ancestors);
if (result === BREAK) {
break;
}
if (result === false) {
if (!isLeaving) {
path.pop();
continue;
}
} else if (result !== undefined) {
edits.push([key, result]);
if (!isLeaving) {
if (isNode(result)) {
node = result;
} else {
path.pop();
continue;
}
}
}
}
if (result === undefined && isEdited) {
edits.push([key, node]);
}
if (isLeaving) {
path.pop();
} else {
var _node$kind;
stack = {
inArray,
index,
keys,
edits,
prev: stack,
};
inArray = Array.isArray(node);
keys = inArray
? node
: (_node$kind = visitorKeys[node.kind]) !== null &&
_node$kind !== void 0
? _node$kind
: [];
index = -1;
edits = [];
if (parent) {
ancestors.push(parent);
}
parent = node;
}
} while (stack !== undefined);
if (edits.length !== 0) {
// New root
return edits[edits.length - 1][1];
}
return root;
}
/**
* Creates a new visitor instance which delegates to many visitors to run in
* parallel. Each visitor will be visited for each node before moving on.
*
* If a prior visitor edits a node, no following visitors will see that node.
*/
export function visitInParallel(visitors) {
const skipping = new Array(visitors.length).fill(null);
const mergedVisitor = Object.create(null);
for (const kind of Object.values(Kind)) {
let hasVisitor = false;
const enterList = new Array(visitors.length).fill(undefined);
const leaveList = new Array(visitors.length).fill(undefined);
for (let i = 0; i < visitors.length; ++i) {
const { enter, leave } = getEnterLeaveForKind(visitors[i], kind);
hasVisitor || (hasVisitor = enter != null || leave != null);
enterList[i] = enter;
leaveList[i] = leave;
}
if (!hasVisitor) {
continue;
}
const mergedEnterLeave = {
enter(...args) {
const node = args[0];
for (let i = 0; i < visitors.length; i++) {
if (skipping[i] === null) {
var _enterList$i;
const result =
(_enterList$i = enterList[i]) === null || _enterList$i === void 0
? void 0
: _enterList$i.apply(visitors[i], args);
if (result === false) {
skipping[i] = node;
} else if (result === BREAK) {
skipping[i] = BREAK;
} else if (result !== undefined) {
return result;
}
}
}
},
leave(...args) {
const node = args[0];
for (let i = 0; i < visitors.length; i++) {
if (skipping[i] === null) {
var _leaveList$i;
const result =
(_leaveList$i = leaveList[i]) === null || _leaveList$i === void 0
? void 0
: _leaveList$i.apply(visitors[i], args);
if (result === BREAK) {
skipping[i] = BREAK;
} else if (result !== undefined && result !== false) {
return result;
}
} else if (skipping[i] === node) {
skipping[i] = null;
}
}
},
};
mergedVisitor[kind] = mergedEnterLeave;
}
return mergedVisitor;
}
/**
* Given a visitor instance and a node kind, return EnterLeaveVisitor for that kind.
*/
export function getEnterLeaveForKind(visitor, kind) {
const kindVisitor = visitor[kind];
if (typeof kindVisitor === 'object') {
// { Kind: { enter() {}, leave() {} } }
return kindVisitor;
} else if (typeof kindVisitor === 'function') {
// { Kind() {} }
return {
enter: kindVisitor,
leave: undefined,
};
} // { enter() {}, leave() {} }
return {
enter: visitor.enter,
leave: visitor.leave,
};
}
/**
* Given a visitor instance, if it is leaving or not, and a node kind, return
* the function the visitor runtime should call.
*
* @deprecated Please use `getEnterLeaveForKind` instead. Will be removed in v17
*/
/* c8 ignore next 8 */
export function getVisitFn(visitor, kind, isLeaving) {
const { enter, leave } = getEnterLeaveForKind(visitor, kind);
return isLeaving ? leave : enter;
}