1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | 'use strict';
|
15 |
|
16 | var _require = require('./GraphQL');
|
17 |
|
18 | var buildClientSchema = _require.utilities_buildClientSchema.buildClientSchema;
|
19 |
|
20 | var RelayQLTransformer = require('./RelayQLTransformer');
|
21 | var babelAdapter = require('./babelAdapter');
|
22 | var generateHash = require('./generateHash');
|
23 | var invariant = require('./invariant');
|
24 | var util = require('util');
|
25 |
|
26 | var HASH_LENGTH = 12;
|
27 | var PROVIDES_MODULE = 'providesModule';
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | function 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 |
|
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 |
|
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 |
|
131 |
|
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 |
|
170 | if (state.isLegacyState) {
|
171 | return result;
|
172 | } else {
|
173 | path.replaceWith(result);
|
174 | }
|
175 | }
|
176 | }
|
177 | };
|
178 | });
|
179 | };
|
180 | }
|
181 |
|
182 | function 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 |
|
188 | module.exports = getBabelRelayPlugin; |
\ | No newline at end of file |