@graphql-eslint/eslint-plugin
Version:
GraphQL plugin for ESLint
153 lines (152 loc) • 6.43 kB
JavaScript
;
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;