UNPKG

6.01 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 *
8 * @format
9 */
10'use strict';
11
12// Attempt to be as inclusive as possible of source text.
13var BABYLON_OPTIONS = {
14 allowImportExportEverywhere: true,
15 allowReturnOutsideFunction: true,
16 allowSuperOutsideMethod: true,
17 sourceType: 'module',
18 plugins: [// Previously "*"
19 'asyncGenerators', 'classProperties', ['decorators', {
20 decoratorsBeforeExport: true
21 }], 'doExpressions', 'dynamicImport', 'exportExtensions', 'flow', 'functionBind', 'functionSent', 'jsx', 'nullishCoalescingOperator', 'objectRestSpread', 'optionalChaining', 'optionalCatchBinding'],
22 strictMode: false
23};
24
25function find(text) {
26 var result = [];
27
28 var ast = require("@babel/parser").parse(text, BABYLON_OPTIONS);
29
30 var visitors = {
31 CallExpression: function CallExpression(node) {
32 var callee = node.callee;
33
34 if (!(callee.type === 'Identifier' && CREATE_CONTAINER_FUNCTIONS[callee.name] || callee.kind === 'MemberExpression' && callee.object.type === 'Identifier' && callee.object.value === 'Relay' && callee.property.type === 'Identifier' && CREATE_CONTAINER_FUNCTIONS[callee.property.name])) {
35 traverse(node, visitors);
36 return;
37 }
38
39 var fragments = node.arguments[1];
40
41 if (fragments.type === 'ObjectExpression') {
42 fragments.properties.forEach(function (property) {
43 !(property.type === 'ObjectProperty' && property.key.type === 'Identifier' && property.value.type === 'TaggedTemplateExpression') ? process.env.NODE_ENV !== "production" ? invariant(false, 'FindGraphQLTags: `%s` expects fragment definitions to be ' + '`key: graphql`.', node.callee.name) : invariant(false) : void 0;
44 !isGraphQLTag(property.value.tag) ? process.env.NODE_ENV !== "production" ? invariant(false, 'FindGraphQLTags: `%s` expects fragment definitions to be tagged ' + 'with `graphql`, got `%s`.', node.callee.name, getSourceTextForLocation(text, property.value.tag.loc)) : invariant(false) : void 0;
45 result.push({
46 keyName: property.key.name,
47 template: getGraphQLText(property.value.quasi),
48 sourceLocationOffset: getSourceLocationOffset(property.value.quasi)
49 });
50 });
51 } else {
52 !(fragments && fragments.type === 'TaggedTemplateExpression') ? process.env.NODE_ENV !== "production" ? invariant(false, 'FindGraphQLTags: `%s` expects a second argument of fragment ' + 'definitions.', node.callee.name) : invariant(false) : void 0;
53 !isGraphQLTag(fragments.tag) ? process.env.NODE_ENV !== "production" ? invariant(false, 'FindGraphQLTags: `%s` expects fragment definitions to be tagged ' + 'with `graphql`, got `%s`.', node.callee.name, getSourceTextForLocation(text, fragments.tag.loc)) : invariant(false) : void 0;
54 result.push({
55 keyName: null,
56 template: getGraphQLText(fragments.quasi),
57 sourceLocationOffset: getSourceLocationOffset(fragments.quasi)
58 });
59 } // Visit remaining arguments
60
61
62 for (var ii = 2; ii < node.arguments.length; ii++) {
63 visit(node.arguments[ii], visitors);
64 }
65 },
66 TaggedTemplateExpression: function TaggedTemplateExpression(node) {
67 if (isGraphQLTag(node.tag)) {
68 result.push({
69 keyName: null,
70 template: node.quasi.quasis[0].value.raw,
71 sourceLocationOffset: getSourceLocationOffset(node.quasi)
72 });
73 }
74 }
75 };
76 visit(ast, visitors);
77 return result;
78}
79
80var CREATE_CONTAINER_FUNCTIONS = Object.create(null, {
81 createFragmentContainer: {
82 value: true
83 },
84 createPaginationContainer: {
85 value: true
86 },
87 createRefetchContainer: {
88 value: true
89 }
90});
91var IGNORED_KEYS = {
92 comments: true,
93 end: true,
94 leadingComments: true,
95 loc: true,
96 name: true,
97 start: true,
98 trailingComments: true,
99 type: true
100};
101
102function isGraphQLTag(tag) {
103 return tag.type === 'Identifier' && tag.name === 'graphql';
104}
105
106function getTemplateNode(quasi) {
107 var quasis = quasi.quasis;
108 !(quasis && quasis.length === 1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'FindGraphQLTags: Substitutions are not allowed in graphql tags.') : invariant(false) : void 0;
109 return quasis[0];
110}
111
112function getGraphQLText(quasi) {
113 return getTemplateNode(quasi).value.raw;
114}
115
116function getSourceLocationOffset(quasi) {
117 var loc = getTemplateNode(quasi).loc.start;
118 return {
119 line: loc.line,
120 column: loc.column + 1 // babylon is 0-indexed, graphql expects 1-indexed
121
122 };
123}
124
125function getSourceTextForLocation(text, loc) {
126 if (loc == null) {
127 return '(source unavailable)';
128 }
129
130 var lines = text.split('\n').slice(loc.start.line - 1, loc.end.line);
131 lines[0] = lines[0].slice(loc.start.column);
132 lines[lines.length - 1] = lines[lines.length - 1].slice(0, loc.end.column);
133 return lines.join('\n');
134}
135
136function invariant(condition, msg) {
137 if (!condition) {
138 for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
139 args[_key - 2] = arguments[_key];
140 }
141
142 throw new Error(require("util").format.apply(require("util"), [msg].concat(args)));
143 }
144}
145
146function visit(node, visitors) {
147 var fn = visitors[node.type];
148
149 if (fn != null) {
150 fn(node);
151 return;
152 }
153
154 traverse(node, visitors);
155}
156
157function traverse(node, visitors) {
158 for (var key in node) {
159 if (IGNORED_KEYS[key]) {
160 continue;
161 }
162
163 var prop = node[key];
164
165 if (prop && typeof prop === 'object' && typeof prop.type === 'string') {
166 visit(prop, visitors);
167 } else if (Array.isArray(prop)) {
168 prop.forEach(function (item) {
169 if (item && typeof item === 'object' && typeof item.type === 'string') {
170 visit(item, visitors);
171 }
172 });
173 }
174 }
175}
176
177module.exports = {
178 find: require("./GraphQLCompilerProfiler").instrument(find, 'FindGraphQLTags.find')
179};
\No newline at end of file