UNPKG

@graphql-tools/webpack-loader

Version:

A set of utils for faster development of GraphQL tools

82 lines (81 loc) 3.15 kB
import os from 'os'; import { isExecutableDefinitionNode, Kind } from 'graphql'; import { optimizeDocumentNode, removeDescriptions, removeEmptyNodes, } from '@graphql-tools/optimize'; import { uniqueCode } from '@graphql-tools/webpack-loader-runtime'; import { parseDocument } from './parser.js'; function isSDL(doc) { return !doc.definitions.some(def => isExecutableDefinitionNode(def)); } function expandImports(source, options) { const lines = source.split(/\r\n|\r|\n/); let outputCode = options.importHelpers ? ` var useUnique = require('@graphql-tools/webpack-loader-runtime').useUnique; var unique = useUnique(); ` : ` ${uniqueCode} `; lines.some(line => { if (line[0] === '#' && line.slice(1).split(' ')[0] === 'import') { const importFile = line.slice(1).split(' ')[1]; const parseDocument = `require(${importFile})`; const appendDef = `doc.definitions = doc.definitions.concat(unique(${parseDocument}.definitions));`; outputCode += appendDef + os.EOL; } return line.length !== 0 && line[0] !== '#'; }); return outputCode; } export default function graphqlLoader(source) { this.cacheable(); // TODO: This should probably use this.getOptions() const options = this.query || {}; let doc = parseDocument(source); const optimizers = []; if (options.noDescription) { optimizers.push(removeDescriptions); } if (options.noEmptyNodes) { optimizers.push(removeEmptyNodes); } if (optimizers.length > 0 && isSDL(doc)) { doc = optimizeDocumentNode(doc, optimizers); } let stringifiedDoc = JSON.stringify(doc); if (options.replaceKinds) { for (const identifier in Kind) { const value = Kind[identifier]; stringifiedDoc = stringifiedDoc.replace(new RegExp(`"kind":"${value}"`, 'g'), `"kind": Kind.${identifier}`); } } const headerCode = ` ${options.replaceKinds ? "var Kind = require('graphql/language/kinds');" : ''} var doc = ${stringifiedDoc}; `; let outputCode = ''; // Allow multiple query/mutation definitions in a file. This parses out dependencies // at compile time, and then uses those at load time to create minimal query documents // We cannot do the latter at compile time due to how the #import code works. const operationCount = doc.definitions.reduce((accum, op) => { if (op.kind === Kind.OPERATION_DEFINITION) { return accum + 1; } return accum; }, 0); function exportDefaultStatement(identifier) { if (options.esModule) { return `export default ${identifier}`; } return `module.exports = ${identifier}`; } if (operationCount > 1) { throw new Error('GraphQL Webpack Loader allows only for one GraphQL Operation per file'); } outputCode += ` ${exportDefaultStatement('doc')} `; const importOutputCode = expandImports(source, options); const allCode = [headerCode, importOutputCode, outputCode, ''].join(os.EOL); return allCode; }