UNPKG

7.24 kBJavaScriptView Raw
1// @generated
2/**
3 * Copyright (c) 2013-present, Facebook, Inc.
4 * All rights reserved.
5 *
6 * This source code is licensed under the BSD-style license found in the
7 * LICENSE file in the root directory of this source tree. An additional grant
8 * of patent rights can be found in the PATENTS file in the same directory.
9 *
10 *
11 * @fullSyntaxTransform
12 */
13
14'use strict';
15
16var _require = require('./GraphQL');
17
18var buildClientSchema = _require.utilities_buildClientSchema.buildClientSchema;
19
20var RelayQLTransformer = require('./RelayQLTransformer');
21var babelAdapter = require('./babelAdapter');
22var generateHash = require('./generateHash');
23var invariant = require('./invariant');
24var util = require('util');
25
26var HASH_LENGTH = 12;
27var PROVIDES_MODULE = 'providesModule';
28
29/**
30 * Returns a new Babel Transformer that uses the supplied schema to transform
31 * template strings tagged with `Relay.QL` into an internal representation of
32 * GraphQL queries.
33 */
34function getBabelRelayPlugin(schemaProvider, pluginOptions) {
35 var options = pluginOptions || {};
36 var warning = options.suppressWarnings ? function () {} : console.warn.bind(console);
37
38 var schema = getSchema(schemaProvider);
39 var transformer = new RelayQLTransformer(schema, {
40 inputArgumentName: options.inputArgumentName,
41 snakeCase: !!options.snakeCase,
42 substituteVariables: !!options.substituteVariables,
43 validator: options.validator
44 });
45
46 return function (_ref) {
47 var Plugin = _ref.Plugin;
48 var types = _ref.types;
49
50 return babelAdapter(Plugin, types, 'relay-query', function (t) {
51 return {
52 visitor: {
53 /**
54 * Extract the module name from `@providesModule`.
55 */
56 Program: function Program(_ref2, state) {
57 var parent = _ref2.parent;
58
59 if (state.file.opts.documentName) {
60 return;
61 }
62 var documentName = undefined;
63 if (parent.comments && parent.comments.length) {
64 var docblock = parent.comments[0].value || '';
65 var propertyRegex = /@(\S+) *(\S*)/g;
66 var captures = undefined;
67 while (captures = propertyRegex.exec(docblock)) {
68 var property = captures[1];
69 var value = captures[2];
70 if (property === PROVIDES_MODULE) {
71 documentName = value.replace(/[\.-:]/g, '_');
72 break;
73 }
74 }
75 }
76 var basename = state.file.opts.basename;
77 if (basename && !documentName) {
78 var captures = basename.match(/^[_A-Za-z][_0-9A-Za-z]*/);
79 if (captures) {
80 documentName = captures[0];
81 }
82 }
83 state.file.opts.documentName = documentName || 'UnknownFile';
84 },
85
86 /**
87 * Transform Relay.QL`...`.
88 */
89 TaggedTemplateExpression: function TaggedTemplateExpression(path, state) {
90 var node = path.node;
91
92 var tag = path.get('tag');
93 var tagName = tag.matchesPattern('Relay.QL') ? 'Relay.QL' : tag.isIdentifier({ name: 'RelayQL' }) ? 'RelayQL' : null;
94 if (!tagName) {
95 return;
96 }
97
98 var documentName = state.file.opts.documentName;
99
100 invariant(documentName, 'Expected `documentName` to have been set.');
101
102 var _path$node$loc$start = path.node.loc.start;
103 var line = _path$node$loc$start.line;
104 var column = _path$node$loc$start.column;
105
106 var fragmentLocationID = generateHash(JSON.stringify({
107 filename: state.file.filename,
108 code: state.file.code,
109 line: line,
110 column: column
111 })).substring(0, HASH_LENGTH);
112
113 var p = path;
114 var propName = null;
115 while (!propName && (p = p.parentPath)) {
116 if (p.isProperty()) {
117 propName = p.node.key.name;
118 }
119 }
120
121 var result = undefined;
122 try {
123 result = transformer.transform(t, node.quasi, {
124 documentName: documentName,
125 fragmentLocationID: fragmentLocationID,
126 tagName: tagName,
127 propName: propName
128 });
129 } catch (error) {
130 // Print a console warning and replace the code with a function
131 // that will immediately throw an error in the browser.
132 var sourceText = error.sourceText;
133 var validationErrors = error.validationErrors;
134
135 var basename = state.file.opts.basename || 'UnknownFile';
136 var filename = state.file.opts.filename || 'UnknownFile';
137 var errorMessages = [];
138 if (validationErrors && sourceText) {
139 var sourceLines = sourceText.split('\n');
140 validationErrors.forEach(function (_ref3) {
141 var message = _ref3.message;
142 var locations = _ref3.locations;
143
144 errorMessages.push(message);
145 warning('\n-- GraphQL Validation Error -- %s --\n', basename);
146 warning(['File: ' + filename, 'Error: ' + message, 'Source:'].join('\n'));
147 locations.forEach(function (location) {
148 var preview = sourceLines[location.line - 1];
149 if (preview) {
150 warning(['> ', '> ' + preview, '> ' + ' '.repeat(location.column - 1) + '^^^'].join('\n'));
151 }
152 });
153 });
154 } else {
155 errorMessages.push(error.message);
156 warning('\n-- Relay Transform Error -- %s --\n', basename);
157 warning(['File: ' + filename, 'Error: ' + error.stack].join('\n'));
158 }
159 var runtimeMessage = util.format('GraphQL validation/transform error ``%s`` in file `%s`.', errorMessages.join(' '), filename);
160 result = t.callExpression(t.functionExpression(null, [], t.blockStatement([t.throwStatement(t.newExpression(t.identifier('Error'), [t.valueToNode(runtimeMessage)]))])), []);
161
162 if (options.debug) {
163 console.error(error.stack);
164 }
165 if (options.abortOnError) {
166 throw new Error('Aborting due to GraphQL validation/transform error(s).');
167 }
168 }
169 // For babel 5 compatibility
170 if (state.isLegacyState) {
171 return result; // eslint-disable-line consistent-return
172 } else {
173 path.replaceWith(result);
174 }
175 }
176 }
177 };
178 });
179 };
180}
181
182function getSchema(schemaProvider) {
183 var introspection = typeof schemaProvider === 'function' ? schemaProvider() : schemaProvider;
184 invariant(typeof introspection === 'object' && introspection && typeof introspection.__schema === 'object' && introspection.__schema, 'Invalid introspection data supplied to `getBabelRelayPlugin()`. The ' + 'resulting schema is not an object with a `__schema` property.');
185 return buildClientSchema(introspection);
186}
187
188module.exports = getBabelRelayPlugin;
\No newline at end of file