Mirror: The spec-compliant minimum of client-side GraphQL.

fix linting ci (#2)

Changed files
+89 -143
benchmark
src
+2 -2
benchmark/suite.js
···
const document = graphql.parse(kitchenSink, { noLocation: true });
suite('parse kitchen sink query', () => {
-
benchmark('0no-co/graphql.web', () => {
+
benchmark('0no-co/graphql.web', () => {
graphqlWeb.parse(kitchenSink);
});
···
});
suite('print kitchen sink query', () => {
-
benchmark('0no-co/graphql.web', () => {
+
benchmark('0no-co/graphql.web', () => {
graphqlWeb.print(document);
});
+3 -1
src/__tests__/parser.test.ts
···
describe('print', () => {
it('prints the kitchen sink document like graphql.js does', () => {
-
const sink = readFileSync(__dirname + '/../../benchmark/kitchen_sink.graphql', { encoding: 'utf8' });
+
const sink = readFileSync(__dirname + '/../../benchmark/kitchen_sink.graphql', {
+
encoding: 'utf8',
+
});
const doc = parse(sink);
expect(doc).toMatchSnapshot();
expect(doc).toEqual(graphql_parse(sink, { noLocation: true }));
+3 -10
src/ast.ts
···
readonly loc?: Location;
}
-
export type DefinitionNode =
-
| OperationDefinitionNode
-
| FragmentDefinitionNode;
-
export type ExecutableDefinitionNode =
-
| OperationDefinitionNode
-
| FragmentDefinitionNode;
+
export type DefinitionNode = OperationDefinitionNode | FragmentDefinitionNode;
+
export type ExecutableDefinitionNode = OperationDefinitionNode | FragmentDefinitionNode;
export interface OperationDefinitionNode {
readonly kind: Kind.OPERATION_DEFINITION;
···
selections: ReadonlyArray<SelectionNode>;
}
-
export declare type SelectionNode =
-
| FieldNode
-
| FragmentSpreadNode
-
| InlineFragmentNode;
+
export declare type SelectionNode = FieldNode | FragmentSpreadNode | InlineFragmentNode;
export interface FieldNode {
readonly kind: Kind.FIELD;
+1 -1
src/error.ts
···
positions?: Maybe<ReadonlyArray<number>>,
path?: Maybe<ReadonlyArray<string | number>>,
originalError?: Maybe<Error>,
-
extensions?: Maybe<Extensions>,
+
extensions?: Maybe<Extensions>
) {
super(message);
+38 -63
src/parser.ts
···
function advance(pattern: RegExp) {
pattern.lastIndex = idx;
if (pattern.test(input)) {
-
const match = input.slice(idx, idx = pattern.lastIndex);
+
const match = input.slice(idx, (idx = pattern.lastIndex));
return match;
}
}
···
const nameRe = /[_\w][_\d\w]*/y;
function name(): ast.NameNode | undefined {
let match: string | undefined;
-
if (match = advance(nameRe)) {
+
if ((match = advance(nameRe))) {
return {
kind: Kind.NAME,
value: match,
···
let match: string | undefined;
if (advance(nullRe)) {
out = { kind: Kind.NULL };
-
} else if (match = advance(boolRe)) {
+
} else if ((match = advance(boolRe))) {
out = {
kind: Kind.BOOLEAN,
value: match === 'true',
···
value: match.slice(1),
},
};
-
} else if (match = advance(floatRe)) {
+
} else if ((match = advance(floatRe))) {
out = {
kind: Kind.FLOAT,
value: match,
};
-
} else if (match = advance(intRe)) {
+
} else if ((match = advance(intRe))) {
out = {
kind: Kind.INT,
value: match,
};
-
} else if (match = advance(nameRe)) {
+
} else if ((match = advance(nameRe))) {
out = {
kind: Kind.ENUM,
value: match,
};
-
} else if (match = advance(blockStringRe)) {
+
} else if ((match = advance(blockStringRe))) {
out = {
kind: Kind.STRING,
value: blockString(match.slice(3, -3)),
block: true,
};
-
} else if (match = advance(stringRe)) {
+
} else if ((match = advance(stringRe))) {
out = {
kind: Kind.STRING,
-
value: complexStringRe.test(match)
-
? JSON.parse(match) as string
-
: match.slice(1, -1),
+
value: complexStringRe.test(match) ? (JSON.parse(match) as string) : match.slice(1, -1),
block: false,
};
-
} else if (out = list(constant) || object(constant)) {
+
} else if ((out = list(constant) || object(constant))) {
return out;
}
···
idx++;
ignored();
const values: ast.ValueNode[] = [];
-
while (match = value(constant))
-
values.push(match);
-
if (input.charCodeAt(idx++) !== 93 /*']'*/)
-
throw error(Kind.LIST);
+
while ((match = value(constant))) values.push(match);
+
if (input.charCodeAt(idx++) !== 93 /*']'*/) throw error(Kind.LIST);
ignored();
return {
kind: Kind.LIST,
···
ignored();
const fields: ast.ObjectFieldNode[] = [];
let _name: ast.NameNode | undefined;
-
while (_name = name()) {
+
while ((_name = name())) {
ignored();
-
if (input.charCodeAt(idx++) !== 58 /*':'*/)
-
throw error(Kind.OBJECT_FIELD);
+
if (input.charCodeAt(idx++) !== 58 /*':'*/) throw error(Kind.OBJECT_FIELD);
ignored();
const _value = value(constant);
-
if (!_value)
-
throw error(Kind.OBJECT_FIELD);
+
if (!_value) throw error(Kind.OBJECT_FIELD);
fields.push({
kind: Kind.OBJECT_FIELD,
name: _name,
value: _value,
});
}
-
if (input.charCodeAt(idx++) !== 125 /*'}'*/)
-
throw error(Kind.OBJECT);
+
if (input.charCodeAt(idx++) !== 125 /*'}'*/) throw error(Kind.OBJECT);
ignored();
return {
kind: Kind.OBJECT,
···
idx++;
ignored();
let _name: ast.NameNode | undefined;
-
while (_name = name()) {
+
while ((_name = name())) {
ignored();
-
if (input.charCodeAt(idx++) !== 58 /*':'*/)
-
throw error(Kind.ARGUMENT);
+
if (input.charCodeAt(idx++) !== 58 /*':'*/) throw error(Kind.ARGUMENT);
ignored();
const _value = value(constant);
-
if (!_value)
-
throw error(Kind.ARGUMENT);
+
if (!_value) throw error(Kind.ARGUMENT);
args.push({
kind: Kind.ARGUMENT,
name: _name,
value: _value,
});
}
-
if (!args.length || input.charCodeAt(idx++) !== 41 /*')'*/)
-
throw error(Kind.ARGUMENT);
+
if (!args.length || input.charCodeAt(idx++) !== 41 /*')'*/) throw error(Kind.ARGUMENT);
ignored();
}
return args;
···
while (input.charCodeAt(idx) === 64 /*'@'*/) {
idx++;
const _name = name();
-
if (!_name)
-
throw error(Kind.DIRECTIVE);
+
if (!_name) throw error(Kind.DIRECTIVE);
ignored();
directives.push({
kind: Kind.DIRECTIVE,
···
ignored();
_alias = _name;
_name = name();
-
if (!_name)
-
throw error(Kind.FIELD);
+
if (!_name) throw error(Kind.FIELD);
ignored();
}
return {
···
idx++;
ignored();
const _type = type();
-
if (!_type || input.charCodeAt(idx++) !== 93 /*']'*/)
-
throw error(Kind.LIST_TYPE);
+
if (!_type || input.charCodeAt(idx++) !== 93 /*']'*/) throw error(Kind.LIST_TYPE);
match = {
kind: Kind.LIST_TYPE,
type: _type,
};
-
} else if (match = name()) {
+
} else if ((match = name())) {
match = {
kind: Kind.NAMED_TYPE,
name: match,
···
if (advance(typeConditionRe)) {
ignored();
const _name = name();
-
if (!_name)
-
throw error(Kind.NAMED_TYPE);
+
if (!_name) throw error(Kind.NAMED_TYPE);
ignored();
return {
kind: Kind.NAMED_TYPE,
···
const _typeCondition = typeCondition();
const _directives = directives(false);
const _selectionSet = selectionSet();
-
if (!_selectionSet)
-
throw error(Kind.INLINE_FRAGMENT);
+
if (!_selectionSet) throw error(Kind.INLINE_FRAGMENT);
return {
kind: Kind.INLINE_FRAGMENT,
typeCondition: _typeCondition,
···
idx++;
ignored();
const selections: ast.SelectionNode[] = [];
-
while (match = fragmentSpread() || field())
-
selections.push(match);
+
while ((match = fragmentSpread() || field())) selections.push(match);
if (!selections.length || input.charCodeAt(idx++) !== 125 /*'}'*/)
throw error(Kind.SELECTION_SET);
ignored();
···
if (input.charCodeAt(idx) === 40 /*'('*/) {
idx++;
ignored();
-
while (match = advance(variableRe)) {
+
while ((match = advance(variableRe))) {
ignored();
-
if (input.charCodeAt(idx++) !== 58 /*':'*/)
-
throw error(Kind.VARIABLE_DEFINITION);
+
if (input.charCodeAt(idx++) !== 58 /*':'*/) throw error(Kind.VARIABLE_DEFINITION);
const _type = type();
-
if (!_type)
-
throw error(Kind.VARIABLE_DEFINITION);
+
if (!_type) throw error(Kind.VARIABLE_DEFINITION);
let _defaultValue: ast.ValueNode | undefined;
if (input.charCodeAt(idx) === 61 /*'='*/) {
idx++;
ignored();
_defaultValue = value(true);
-
if (!_defaultValue)
-
throw error(Kind.VARIABLE_DEFINITION);
+
if (!_defaultValue) throw error(Kind.VARIABLE_DEFINITION);
}
ignored();
vars.push({
···
directives: directives(true),
});
}
-
if (input.charCodeAt(idx++) !== 41 /*')'*/)
-
throw error(Kind.VARIABLE_DEFINITION);
+
if (input.charCodeAt(idx++) !== 41 /*')'*/) throw error(Kind.VARIABLE_DEFINITION);
ignored();
}
return vars;
···
if (advance(fragmentDefinitionRe)) {
ignored();
const _name = name();
-
if (!_name)
-
throw error(Kind.FRAGMENT_DEFINITION);
+
if (!_name) throw error(Kind.FRAGMENT_DEFINITION);
ignored();
const _typeCondition = typeCondition();
-
if (!_typeCondition)
-
throw error(Kind.FRAGMENT_DEFINITION);
+
if (!_typeCondition) throw error(Kind.FRAGMENT_DEFINITION);
const _directives = directives(false);
const _selectionSet = selectionSet();
-
if (!_selectionSet)
-
throw error(Kind.FRAGMENT_DEFINITION);
+
if (!_selectionSet) throw error(Kind.FRAGMENT_DEFINITION);
return {
kind: Kind.FRAGMENT_DEFINITION,
name: _name,
···
let _name: ast.NameNode | undefined;
let _variableDefinitions: ast.VariableDefinitionNode[] = [];
let _directives: ast.DirectiveNode[] = [];
-
if (_operation = advance(operationDefinitionRe)) {
+
if ((_operation = advance(operationDefinitionRe))) {
ignored();
_name = name();
_variableDefinitions = variableDefinitions();
···
let match: ast.DefinitionNode | void;
ignored();
const definitions: ast.DefinitionNode[] = [];
-
while (match = fragmentDefinition() || operationDefinition())
-
definitions.push(match);
-
if (idx !== input.length)
-
throw error(Kind.DOCUMENT);
+
while ((match = fragmentDefinition() || operationDefinition())) definitions.push(match);
+
if (idx !== input.length) throw error(Kind.DOCUMENT);
return {
kind: Kind.DOCUMENT,
definitions,
+29 -44
src/printer.ts
···
return '"""\n' + string.replace(/"""/g, '\\"""') + '\n"""';
}
-
const hasItems = <T>(
-
array: ReadonlyArray<T> | undefined | null
-
): array is ReadonlyArray<T> => !!(array && array.length);
+
const hasItems = <T>(array: ReadonlyArray<T> | undefined | null): array is ReadonlyArray<T> =>
+
!!(array && array.length);
const MAX_LINE_LENGTH = 80;
···
let out: string;
switch (node.kind) {
case Kind.OPERATION_DEFINITION:
-
if (node.operation === 'query' && !node.name && !hasItems(node.variableDefinitions) && !hasItems(node.directives)) {
+
if (
+
node.operation === 'query' &&
+
!node.name &&
+
!hasItems(node.variableDefinitions) &&
+
!hasItems(node.directives)
+
) {
return print(node.selectionSet);
}
out = node.operation;
-
if (node.name)
-
out += ' ' + node.name.value;
+
if (node.name) out += ' ' + node.name.value;
if (hasItems(node.variableDefinitions)) {
if (!node.name) out += ' ';
out += '(' + node.variableDefinitions.map(print).join(', ') + ')';
}
-
if (hasItems(node.directives))
-
out += ' ' + node.directives.map(print).join(' ');
+
if (hasItems(node.directives)) out += ' ' + node.directives.map(print).join(' ');
return out + ' ' + print(node.selectionSet);
case Kind.VARIABLE_DEFINITION:
-
out = print(node.variable) +
-
': ' +
-
print(node.type);
-
if (node.defaultValue)
-
out += ' = ' + print(node.defaultValue);
-
if (hasItems(node.directives))
-
out += ' ' + node.directives.map(print).join(' ');
+
out = print(node.variable) + ': ' + print(node.type);
+
if (node.defaultValue) out += ' = ' + print(node.defaultValue);
+
if (hasItems(node.directives)) out += ' ' + node.directives.map(print).join(' ');
return out;
case Kind.FIELD:
-
out = (node.alias ? print(node.alias) + ': ' : '') + node.name.value
+
out = (node.alias ? print(node.alias) + ': ' : '') + node.name.value;
if (hasItems(node.arguments)) {
const args = node.arguments.map(print);
const argsLine = out + '(' + args.join(', ') + ')';
-
out = argsLine.length > MAX_LINE_LENGTH
-
? out + '(\n ' + args.join('\n').replace(/\n/g, '\n ') + '\n)'
-
: argsLine;
+
out =
+
argsLine.length > MAX_LINE_LENGTH
+
? out + '(\n ' + args.join('\n').replace(/\n/g, '\n ') + '\n)'
+
: argsLine;
}
-
if (hasItems(node.directives))
-
out += ' ' + node.directives.map(print).join(' ');
-
return node.selectionSet
-
? out + ' ' + print(node.selectionSet)
-
: out;
+
if (hasItems(node.directives)) out += ' ' + node.directives.map(print).join(' ');
+
return node.selectionSet ? out + ' ' + print(node.selectionSet) : out;
case Kind.STRING:
-
return node.block
-
? printBlockString(node.value)
-
: printString(node.value);
+
return node.block ? printBlockString(node.value) : printString(node.value);
case Kind.BOOLEAN:
return '' + node.value;
···
return '$' + node.name.value;
case Kind.DOCUMENT:
-
return hasItems(node.definitions)
-
? node.definitions.map(print).join('\n\n')
-
: '';
+
return hasItems(node.definitions) ? node.definitions.map(print).join('\n\n') : '';
case Kind.SELECTION_SET:
-
return '{\n ' +
-
node.selections.map(print).join('\n').replace(/\n/g, '\n ') +
-
'\n}';
+
return '{\n ' + node.selections.map(print).join('\n').replace(/\n/g, '\n ') + '\n}';
case Kind.ARGUMENT:
return node.name.value + ': ' + print(node.value);
case Kind.FRAGMENT_SPREAD:
out = '...' + node.name.value;
-
if (hasItems(node.directives))
-
out += ' ' + node.directives.map(print).join(' ');
+
if (hasItems(node.directives)) out += ' ' + node.directives.map(print).join(' ');
return out;
case Kind.INLINE_FRAGMENT:
out = '...';
-
if (node.typeCondition)
-
out += ' on ' + node.typeCondition.name.value;
-
if (hasItems(node.directives))
-
out += ' ' + node.directives.map(print).join(' ');
+
if (node.typeCondition) out += ' on ' + node.typeCondition.name.value;
+
if (hasItems(node.directives)) out += ' ' + node.directives.map(print).join(' ');
return out + ' ' + print(node.selectionSet);
case Kind.FRAGMENT_DEFINITION:
out = 'fragment ' + node.name.value;
out += ' on ' + node.typeCondition.name.value;
-
if (hasItems(node.directives))
-
out += ' ' + node.directives.map(print).join(' ');
+
if (hasItems(node.directives)) out += ' ' + node.directives.map(print).join(' ');
return out + ' ' + print(node.selectionSet);
-
+
case Kind.DIRECTIVE:
out = '@' + node.name.value;
-
if (hasItems(node.arguments))
-
out += '(' + node.arguments.map(print).join(', ') + ')';
+
if (hasItems(node.arguments)) out += '(' + node.arguments.map(print).join(', ') + ')';
return out;
case Kind.NAMED_TYPE:
+5 -10
src/values.ts
···
export function valueFromASTUntyped(
node: ValueNode,
-
variables?: Maybe<Record<string, any>>,
+
variables?: Maybe<Record<string, any>>
): unknown {
switch (node.kind) {
case Kind.NULL:
···
return node.value;
case Kind.LIST: {
const values: unknown[] = [];
-
for (const value of node.values)
-
values.push(valueFromASTUntyped(value, variables));
+
for (const value of node.values) values.push(valueFromASTUntyped(value, variables));
return values;
}
case Kind.OBJECT: {
···
export function valueFromTypeNode(
node: ValueNode,
type: TypeNode,
-
variables?: Maybe<Record<string, any>>,
+
variables?: Maybe<Record<string, any>>
): unknown {
if (node.kind === Kind.VARIABLE) {
const variableName = node.name.value;
-
return variables
-
? valueFromTypeNode(variables[variableName], type, variables)
-
: undefined;
+
return variables ? valueFromTypeNode(variables[variableName], type, variables) : undefined;
} else if (type.kind === Kind.NON_NULL_TYPE) {
-
return node.kind !== Kind.NULL
-
? valueFromTypeNode(node, type, variables)
-
: undefined
+
return node.kind !== Kind.NULL ? valueFromTypeNode(node, type, variables) : undefined;
} else if (node.kind === Kind.NULL) {
return null;
} else if (type.kind === Kind.LIST_TYPE) {
+8 -12
src/visitor.ts
···
export function visit<R>(root: ASTNode, visitor: ASTReducer<R>): R;
export function visit(node: ASTNode, visitor: ASTVisitor | ASTReducer<any>) {
-
const ancestors: Array<ASTNode | ReadonlyArray<ASTNode>>= [];
+
const ancestors: Array<ASTNode | ReadonlyArray<ASTNode>> = [];
const path: Array<string | number> = [];
function traverse(
node: ASTNode,
key?: string | number | undefined,
-
parent?: ASTNode | ReadonlyArray<ASTNode> | undefined,
+
parent?: ASTNode | ReadonlyArray<ASTNode> | undefined
) {
let hasEdited = false;
-
const enter = visitor[node.kind] && visitor[node.kind].enter || visitor[node.kind];
-
const resultEnter =
-
enter && enter.call(visitor, node, key, parent, path, ancestors);
+
const enter = (visitor[node.kind] && visitor[node.kind].enter) || visitor[node.kind];
+
const resultEnter = enter && enter.call(visitor, node, key, parent, path, ancestors);
if (resultEnter === false) {
return node;
} else if (resultEnter === null) {
···
if (parent) ancestors.pop();
const leave = visitor[node.kind] && visitor[node.kind].leave;
-
const resultLeave =
-
leave && leave.call(visitor, node, key, parent, path, ancestors);
+
const resultLeave = leave && leave.call(visitor, node, key, parent, path, ancestors);
if (resultLeave === BREAK) {
throw BREAK;
} else if (resultLeave !== undefined) {
···
export type ASTVisitor = EnterLeaveVisitor<ASTNode> | KindVisitor;
type KindVisitor = {
-
readonly [NodeT in ASTNode as NodeT['kind']]?:
-
| ASTVisitFn<NodeT>
-
| EnterLeaveVisitor<NodeT>;
+
readonly [NodeT in ASTNode as NodeT['kind']]?: ASTVisitFn<NodeT> | EnterLeaveVisitor<NodeT>;
};
interface EnterLeaveVisitor<TVisitedNode extends ASTNode> {
···
key: string | number | undefined,
parent: ASTNode | ReadonlyArray<ASTNode> | undefined,
path: ReadonlyArray<string | number>,
-
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>,
+
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>
) => any;
export type ASTReducer<R> = {
···
key: string | number | undefined,
parent: ASTNode | ReadonlyArray<ASTNode> | undefined,
path: ReadonlyArray<string | number>,
-
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>,
+
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>
) => R;
type ReducedField<T, R> = T extends null | undefined