babel-plugin-import-graphql
Version:
Babel plugin to make .gql/.graphql files importable
192 lines (151 loc) • 7.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _path = require("path");
var _fs = require("fs");
var _language = require("graphql/language");
var _requireGql = require("./requireGql");
var _errorMessages = require("./errorMessages");
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
var resolve;
var seenJSFiles = new Set();
var _default = function _default(_ref) {
var t = _ref.types,
template = _ref.template;
return {
manipulateOptions(_ref2) {
var resolveModuleSource = _ref2.resolveModuleSource,
plugins = _ref2.plugins;
resolve = resolveModuleSource || _requireGql.defaultResolve;
},
visitor: {
ImportDeclaration: {
exit(curPath, _ref3) {
var opts = _ref3.opts,
file = _ref3.file;
var importPath = curPath.node.source.value;
var jsFilename = file.opts.filename;
var _opts$extensions = opts.extensions,
extensions = _opts$extensions === void 0 ? [] : _opts$extensions,
_opts$emitDeclaration = opts.emitDeclarations,
emitDeclarations = _opts$emitDeclaration === void 0 ? false : _opts$emitDeclaration;
extensions = _toConsumableArray(extensions).concat(['.graphql', '.gql']);
if (extensions.some(function (extension) {
return importPath.endsWith(extension);
})) {
if (opts.runtime) {
try {
require('graphql-tag');
} catch (e) {
throw new Error(_errorMessages.missingOptionalDep);
}
} // Find the file, using node resolution/NODE_PATH if necessary.
var fallbackPaths = opts.nodePath ? opts.nodePath.split(_path.delimiter) : [process.env.NODE_PATH];
var absPath = resolve(importPath, jsFilename);
if (!(0, _fs.existsSync)(absPath)) {
absPath = fallbackPaths.map(function (fallbackPath) {
return (0, _path.join)(fallbackPath, importPath);
}).find(function (altPath) {
return (0, _fs.existsSync)(altPath);
});
} // Analyze the file, returning one of the following...
// For schema-like files: string - the GraphQL source code
// For op/frag files: object - map of names to GraphQL Documents
var result = (0, _requireGql.requireGql)(absPath, {
resolve,
nowrap: false,
emitDeclarations
});
var importNames = curPath.node.specifiers;
if (typeof result === 'string') {
curPath.replaceWith(buildSrcVarNode(result, importNames[0].local.name));
} else {
var replacements = buildReplacements(result, importNames, opts, seenJSFiles);
replacements.length > 1 ? curPath.replaceWithMultiple(replacements) : curPath.replaceWith(replacements[0]);
}
}
function buildReplacements(docs, specifiers, opts, seenJSFiles) {
var replacements = [];
var buildVarNode = opts.runtime ? buildRuntimeVarNode : buildASTVarNode; // Add the graphql-tag import to the first non-schema .graphql import in each .js file.
if (opts.runtime && !seenJSFiles.has(jsFilename)) {
replacements = _toConsumableArray(replacements).concat([template(`import gql from 'graphql-tag'`, {
sourceType: 'module'
})()]);
}
seenJSFiles.add(jsFilename);
var varNodes = specifiers.map(function (_ref4) {
var type = _ref4.type,
imported = _ref4.imported,
local = _ref4.local;
switch (type) {
case 'ImportDefaultSpecifier':
return buildVarNode(docs.default, local.name);
case 'ImportSpecifier':
return buildVarNode(docs[imported.name] || docs.default, local.name);
case 'ImportNamespaceSpecifier':
return buildVarNode(docs, local.name);
default:
throw new Error(`Unexpected import specifier type: ${type}`);
}
});
return _toConsumableArray(replacements).concat(_toConsumableArray(varNodes));
} // Use to inline raw source when a schema-like file is detected.
function buildSrcVarNode(graphqlSrc, importName) {
var buildNode = template('var IMPORT_NAME = SOURCE;', {
sourceType: 'module'
});
return buildNode({
IMPORT_NAME: t.identifier(importName),
SOURCE: t.stringLiteral(graphqlSrc)
});
} // Use to inline the raw GraphQL source text to be processed by 'graphql-tag' at runtime.
function buildRuntimeVarNode(graphqlAST, importName) {
if (graphqlAST.default) {
var properties = Object.entries(graphqlAST).map(function (_ref5) {
var _ref6 = _slicedToArray(_ref5, 2),
key = _ref6[0],
value = _ref6[1];
var expr = t.callExpression(t.identifier('gql'), [t.stringLiteral((0, _language.print)(value))]);
return t.objectProperty(t.stringLiteral(key), expr);
});
return template('var IMPORT_NAME = SOURCE', {
sourceType: 'module'
})({
IMPORT_NAME: t.identifier(importName),
SOURCE: t.objectExpression(properties)
});
}
var buildNode = template('var IMPORT_NAME = gql(SOURCE);', {
sourceType: 'module'
});
return buildNode({
IMPORT_NAME: t.identifier(importName),
SOURCE: t.stringLiteral((0, _language.print)(graphqlAST))
});
} // Use to inline the preprocessed AST object when the 'runtime' option is off.
function buildASTVarNode(graphqlAST, importName) {
var buildNode = template('var IMPORT_NAME = AST;', {
sourceType: 'module'
});
var astNode = t.valueToNode(JSON.parse(JSON.stringify(graphqlAST)));
astNode._compact = true;
return buildNode({
IMPORT_NAME: t.identifier(importName),
AST: astNode
});
}
}
}
}
};
};
exports.default = _default;