GraphQL

graphql/language

graphql/language 模块负责对 GraphQL 查询语言进行解析和操作。你既可以从 graphql/language 模块引入,也可以从根模块 graphql 引入。示例如下:

import { Source } from 'graphql'; // ES6
var { Source } = require('graphql'); // CommonJS

概览#

Source

词法分析器(Lexer)

解析器(Parser)

Visitor

Printer

Source#

Source#

export class Source {
constructor(body: string, name?: string)
}

对 GraphQL 源输入的表示。name 参数是可选的,但对于将 GraphQL 文档存储在源文件里的客户端来说,这个参数是非常有用的;举个例子,如果 GraphQL 的输入是在一个名为 Foo.graphql 的文件里,那么将 name 设置为 "Foo.graphql" 在之后就会很有用了。

getLocation#

function getLocation(source: Source, position: number): SourceLocation
type SourceLocation = {
line: number;
column: number;
}

接收一个 Source 对象和一个 UTF-8 编码的字符偏移量作为参数,返回一个 SourceLocation 对象,包含相关的行列位置信息。

词法分析器(Lexer)#

lex#

function lex(source: Source): Lexer;
type Lexer = (resetPosition?: number) => Token;
export type Token = {
kind: number;
start: number;
end: number;
value: ?string;
};

给定一个 Source 对象,为这个对象返回一个词法分析器。词法分析器每次被调用的时候会表现得像一个生成器,返回 Source 里的下一个 token。假设对某个 source 进行词法分析,最后返回的 token 就将是某种类型的文件结尾符,而在这之后,词法分析器不管何时被调用都会重复返回文件结尾符的 token。

词法分析器函数的参数是可选的,而且可被用于在 Source 里将词法分析器回退或者前进到某个新位置。

解析器(Parser)#

parse#

export function parse(
source: Source | string,
options?: ParseOptions
): Document

给定一个 GraphQL 源,将其解析并放入文档里。

如果遇到语法错误则抛出 GraphQLError。

parseValue#

export function parseValue(
source: Source | string,
options?: ParseOptions
): Value

给定一个包含 GraphQL 值的字符串,将这个值解析为 AST。

如果遇到语法错误则抛出 GraphQLError。

这在某些工具中会很有用,比如直接在 GraphQL 值上进行操作,并且与 GraphQL 文档完全分离开来。

Kind#

这是一个枚举类型,用于描述不同类型的 AST 节点。

Visitor#

visit#

function visit(root, visitor, keyMap)

visit() 将使用深度优先遍历一个 AST,在遍历当中对每个节点调用 visitor 的 enter 函数,并在访问完当前节点及其子节点后调用 leave 函数。

通过从 enterleave 函数里返回不同的值,visitor 的行为可以进行更改,包括跳过 AST 的一个子树(返回 false)、编辑这个 AST(返回一个值或者返回 null 来删除这个节点)、或者返回 BREAK 停止整个遍历。

当使用 visit() 编辑一个 AST 的时候,原始的 AST 不会被修改,visit 函数会返回一个经过修改的新版本 AST。

var editedAST = visit(ast, {
enter(node, key, parent, path, ancestors) {
// @return
// undefined: 无操作
// false: 跳过访问该节点
// visitor.BREAK: 停止访问
// null: 删除该节点
// any value: 使用返回的这个值替代原本的节点
},
leave(node, key, parent, path, ancestors) {
// @return
// undefined: 无操作
// false: 无操作
// visitor.BREAK: 停止访问
// null: 删除该节点
// any value: 使用返回的这个值替代原本的节点
}
});

Visitor 可以通过提供和节点类型同名的函数来替代 enter()leave() 函数,或者通过名称的关键字来使用 visitor 中的 enterleave,这就造成 visitor 的 API 有四种形式:

1) 当进入特定类型的节点时,触发同名的 visitor。

visit(ast, {
Kind(node) {
// enter the "Kind" node
}
})

2) 在进入或离开特定类型的节点时,触发同名的 visitor。

visit(ast, {
Kind: {
enter(node) {
// enter the "Kind" node
}
leave(node) {
// leave the "Kind" node
}
}
})

3) 在进入或离开任意节点时,触发通用的 visitor。

visit(ast, {
enter(node) {
// enter any node
},
leave(node) {
// leave any node
}
})

4) 为进入或离开特定类型的节点创建平行的 visitor。

visit(ast, {
enter: {
Kind(node) {
// enter the "Kind" node
}
},
leave: {
Kind(node) {
// leave the "Kind" node
}
}
})

BREAK#

BREAK 标记在 visitor 的文档中有描述。

Printer#

print#

function print(ast): string

使用一组合理的格式化规则,将一个 AST 转化成一个字符串。

继续阅读 →graphql/type