1 | /* eslint-disable no-redeclare */
|
2 | /**
|
3 | * Copyright (c) 2021 GraphQL Contributors.
|
4 | *
|
5 | * This source code is licensed under the MIT license found in the
|
6 | * LICENSE file in the root directory of this source tree.
|
7 | */
|
8 | import { parse, visit } from 'graphql';
|
9 | import { collectVariables } from './collectVariables';
|
10 |
|
11 | import type { VariableToType } from './collectVariables';
|
12 | import type {
|
13 | GraphQLSchema,
|
14 | DocumentNode,
|
15 | OperationDefinitionNode,
|
16 | } from 'graphql';
|
17 |
|
18 | export type OperationASTFacts = {
|
19 | variableToType?: VariableToType;
|
20 | operations: OperationDefinitionNode[];
|
21 | };
|
22 |
|
23 | /**
|
24 | * extract all operation nodes, and if schema is present, variable definitions, in a map
|
25 | *
|
26 | * @param documentAST {DocumentNode} a graphql-js compatible AST node
|
27 | * @param schema {GraphQLSchema} optional schema
|
28 | * @returns {OperationASTFacts}
|
29 | * @example
|
30 | *
|
31 | * ```ts
|
32 | * const { variablesToType, operations } = getOperationASTFacts(
|
33 | * parse('documentString'),
|
34 | * );
|
35 | * operations.forEach(op => {
|
36 | * console.log(op.name, op.operation, op.loc);
|
37 | * });
|
38 | * Object.entries(variablesToType).forEach(([variableName, type]) => {
|
39 | * console.log(variableName, type);
|
40 | * });
|
41 | * ```
|
42 | */
|
43 |
|
44 | export function getOperationASTFacts(
|
45 | documentAST: DocumentNode,
|
46 | schema?: GraphQLSchema | null,
|
47 | ): OperationASTFacts {
|
48 | const variableToType = schema
|
49 | ? collectVariables(schema, documentAST)
|
50 | : undefined;
|
51 |
|
52 | // Collect operations by their names.
|
53 | const operations: OperationDefinitionNode[] = [];
|
54 |
|
55 | visit(documentAST, {
|
56 | OperationDefinition(node) {
|
57 | operations.push(node);
|
58 | },
|
59 | });
|
60 |
|
61 | return { variableToType, operations };
|
62 | }
|
63 |
|
64 | export type OperationFacts = {
|
65 | documentAST: DocumentNode;
|
66 | } & OperationASTFacts;
|
67 |
|
68 | export type QueryFacts = OperationFacts;
|
69 |
|
70 | /**
|
71 | * Provided previous "queryFacts", a GraphQL schema, and a query document
|
72 | * string, return a set of facts about that query useful for GraphiQL features.
|
73 | *
|
74 | * If the query cannot be parsed, returns undefined.
|
75 | * @param schema {GraphQLSchema} (optional)
|
76 | * @param documentString {string} the document you want to parse for operations (optional)
|
77 | *
|
78 | * @returns {OperationFacts | undefined}
|
79 | */
|
80 | export default function getOperationFacts(
|
81 | schema?: GraphQLSchema | null,
|
82 | documentString?: string | null,
|
83 | ): OperationFacts | undefined {
|
84 | if (!documentString) {
|
85 | return;
|
86 | }
|
87 |
|
88 | try {
|
89 | const documentAST = parse(documentString);
|
90 | return {
|
91 | ...getOperationASTFacts(documentAST, schema),
|
92 | documentAST,
|
93 | };
|
94 | } catch {
|
95 | return;
|
96 | }
|
97 | }
|
98 |
|
99 | /**
|
100 | * for backwards compatibility
|
101 | */
|
102 | export const getQueryFacts = getOperationFacts;
|