UNPKG

@graphql-eslint/eslint-plugin

Version:
153 lines (152 loc) • 6.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDocuments = void 0; const tslib_1 = require("tslib"); const path_1 = require("path"); const graphql_1 = require("graphql"); const debug_1 = tslib_1.__importDefault(require("debug")); const fast_glob_1 = tslib_1.__importDefault(require("fast-glob")); const utils_js_1 = require("./utils.js"); const cache_js_1 = require("./cache.js"); const debug = (0, debug_1.default)('graphql-eslint:operations'); const handleVirtualPath = (documents) => { const filepathMap = Object.create(null); return documents.map(source => { var _a; const location = source.location; if (['.gql', '.graphql'].some(extension => location.endsWith(extension))) { return source; } (_a = filepathMap[location]) !== null && _a !== void 0 ? _a : (filepathMap[location] = -1); const index = (filepathMap[location] += 1); return { ...source, location: (0, path_1.resolve)(location, `${index}_document.graphql`), }; }); }; const operationsCache = new cache_js_1.ModuleCache(); const siblingOperationsCache = new Map(); const getSiblings = (project) => { const documentsKey = project.documents; if (!documentsKey) { return []; } let siblings = operationsCache.get(documentsKey); if (!siblings) { debug('Loading operations from %o', project.documents); const documents = project.loadDocumentsSync(project.documents, { skipGraphQLImport: true, pluckConfig: project.extensions.pluckConfig, }); if (debug.enabled) { debug('Loaded %d operations', documents.length); const operationsPaths = fast_glob_1.default.sync(project.documents, { absolute: true }); debug('Operations pointers %O', operationsPaths); } siblings = handleVirtualPath(documents); operationsCache.set(documentsKey, siblings); } return siblings; }; function getDocuments(project) { const siblings = getSiblings(project); if (siblings.length === 0) { let printed = false; const noopWarn = () => { if (!printed) { utils_js_1.logger.warn('getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!'); printed = true; } return []; }; return { available: false, getFragment: noopWarn, getFragments: noopWarn, getFragmentByType: noopWarn, getFragmentsInUse: noopWarn, getOperation: noopWarn, getOperations: noopWarn, getOperationByType: noopWarn, }; } // Since the siblings array is cached, we can use it as cache key. // We should get the same array reference each time we get // to this point for the same graphql project const value = siblingOperationsCache.get(siblings); if (value) { return value; } let fragmentsCache = null; const getFragments = () => { var _a; if (fragmentsCache === null) { const result = []; for (const source of siblings) { for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) { if (definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION) { result.push({ filePath: source.location, document: definition, }); } } } fragmentsCache = result; } return fragmentsCache; }; let cachedOperations = null; const getOperations = () => { var _a; if (cachedOperations === null) { const result = []; for (const source of siblings) { for (const definition of ((_a = source.document) === null || _a === void 0 ? void 0 : _a.definitions) || []) { if (definition.kind === graphql_1.Kind.OPERATION_DEFINITION) { result.push({ filePath: source.location, document: definition, }); } } } cachedOperations = result; } return cachedOperations; }; const getFragment = (name) => getFragments().filter(f => { var _a; return ((_a = f.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; }); const collectFragments = (selectable, recursive, collected = new Map()) => { (0, graphql_1.visit)(selectable, { FragmentSpread(spread) { const fragmentName = spread.name.value; const [fragment] = getFragment(fragmentName); if (!fragment) { utils_js_1.logger.warn(`Unable to locate fragment named "${fragmentName}", please make sure it's loaded using "parserOptions.operations"`); return; } if (!collected.has(fragmentName)) { collected.set(fragmentName, fragment.document); if (recursive) { collectFragments(fragment.document, recursive, collected); } } }, }); return collected; }; const siblingOperations = { available: true, getFragment, getFragments, getFragmentByType: typeName => getFragments().filter(f => { var _a, _b; return ((_b = (_a = f.document.typeCondition) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) === typeName; }), getFragmentsInUse: (selectable, recursive = true) => Array.from(collectFragments(selectable, recursive).values()), getOperation: name => getOperations().filter(o => { var _a; return ((_a = o.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; }), getOperations, getOperationByType: type => getOperations().filter(o => o.document.operation === type), }; siblingOperationsCache.set(siblings, siblingOperations); return siblingOperations; } exports.getDocuments = getDocuments;