@graphql-tools/git-loader
Version:
A set of utils for faster development of GraphQL tools
225 lines (224 loc) • 8.32 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitLoader = void 0;
const tslib_1 = require("tslib");
const process_1 = require("process");
const graphql_1 = require("graphql");
const is_glob_1 = tslib_1.__importDefault(require("is-glob"));
const micromatch_1 = tslib_1.__importDefault(require("micromatch"));
const unixify_1 = tslib_1.__importDefault(require("unixify"));
const graphql_tag_pluck_1 = require("@graphql-tools/graphql-tag-pluck");
const utils_1 = require("@graphql-tools/utils");
const load_git_js_1 = require("./load-git.js");
const parse_js_1 = require("./parse.js");
// git:branch:path/to/file
function extractData(pointer) {
const parts = pointer.replace(/^git\:/i, '').split(':');
if (!parts || parts.length !== 2) {
return null;
}
return {
ref: parts[0],
path: parts[1],
};
}
/**
* This loader loads a file from git.
*
* ```js
* const typeDefs = await loadTypedefs('git:someBranch:some/path/to/file.js', {
* loaders: [new GitLoader()],
* })
* ```
*/
class GitLoader {
async canLoad(pointer) {
return this.canLoadSync(pointer);
}
canLoadSync(pointer) {
return typeof pointer === 'string' && pointer.toLowerCase().startsWith('git:');
}
async resolveGlobs(glob, ignores) {
const data = extractData(glob);
if (data === null) {
return [];
}
const refsForPaths = new Map();
const { ref, path } = data;
if (!refsForPaths.has(ref)) {
refsForPaths.set(ref, []);
}
refsForPaths.get(ref).push((0, unixify_1.default)(path));
for (const ignore of ignores) {
const data = extractData(ignore);
if (data === null) {
continue;
}
const { ref, path } = data;
if (!refsForPaths.has(ref)) {
refsForPaths.set(ref, []);
}
refsForPaths.get(ref).push(`!${(0, unixify_1.default)(path)}`);
}
const maybeLeadingDotSlash = path.startsWith('./') ? './' : '';
const resolved = [];
await Promise.all([...refsForPaths.entries()].map(async ([ref, paths]) => {
resolved.push(...(0, micromatch_1.default)(await (0, load_git_js_1.readTreeAtRef)(ref), paths).map(filePath => `git:${ref}:${maybeLeadingDotSlash}${filePath}`));
}));
return resolved;
}
resolveGlobsSync(glob, ignores) {
const data = extractData(glob);
if (data === null) {
return [];
}
const { ref, path } = data;
const refsForPaths = new Map();
if (!refsForPaths.has(ref)) {
refsForPaths.set(ref, []);
}
refsForPaths.get(ref).push((0, unixify_1.default)(path));
for (const ignore of ignores) {
const data = extractData(ignore);
if (data === null) {
continue;
}
const { ref, path } = data;
if (!refsForPaths.has(ref)) {
refsForPaths.set(ref, []);
}
refsForPaths.get(ref).push(`!${(0, unixify_1.default)(path)}`);
}
const maybeLeadingDotSlash = path.startsWith('./') ? './' : '';
const resolved = [];
for (const [ref, paths] of refsForPaths.entries()) {
resolved.push(...(0, micromatch_1.default)((0, load_git_js_1.readTreeAtRefSync)(ref), paths).map(filePath => `git:${ref}:${maybeLeadingDotSlash}${filePath}`));
}
return resolved;
}
async handleSingularPointerAsync(pointer, options) {
const result = extractData(pointer);
if (result === null) {
return [];
}
const { ref, path } = result;
const content = await (0, load_git_js_1.loadFromGit)({ ref, path });
const parsed = (0, parse_js_1.parse)({ path, options, pointer, content });
if (parsed) {
return [parsed];
}
const sources = await (0, graphql_tag_pluck_1.gqlPluckFromCodeString)(pointer, content, options.pluckConfig);
return sources.map(source => ({
location: pointer,
document: (0, graphql_1.parse)(source, options),
}));
}
async load(pointer, options) {
const result = extractData(pointer);
if (result === null) {
return [];
}
const { path } = result;
const finalResult = [];
const errors = [];
try {
if ((0, is_glob_1.default)(path)) {
const resolvedPaths = await this.resolveGlobs(pointer, (0, utils_1.asArray)(options.ignore || []));
await Promise.all(resolvedPaths.map(async (path) => {
const results = await this.load(path, options);
results?.forEach(result => finalResult.push(result));
}));
}
else if (await this.canLoad(pointer)) {
const results = await this.handleSingularPointerAsync(pointer, options);
results?.forEach(result => finalResult.push(result));
}
}
catch (error) {
if (process_1.env['DEBUG']) {
console.error(error);
}
if (error instanceof AggregateError) {
for (const errorElement of error.errors) {
errors.push(errorElement);
}
}
else {
errors.push(error);
}
}
if (finalResult.length === 0 && errors.length > 0) {
if (errors.length === 1) {
throw errors[0];
}
throw new AggregateError(errors, `Reading from ${pointer} failed ; \n ` + errors.map((e) => e.message).join('\n'));
}
return finalResult;
}
handleSingularPointerSync(pointer, options) {
const result = extractData(pointer);
if (result === null) {
return [];
}
const { ref, path } = result;
const content = (0, load_git_js_1.loadFromGitSync)({ ref, path });
const parsed = (0, parse_js_1.parse)({ path, options, pointer, content });
if (parsed) {
return [parsed];
}
const sources = (0, graphql_tag_pluck_1.gqlPluckFromCodeStringSync)(pointer, content, options.pluckConfig);
return sources.map(source => ({
location: pointer,
document: (0, graphql_1.parse)(source, options),
}));
}
loadSync(pointer, options) {
const result = extractData(pointer);
if (result === null) {
return [];
}
const { path } = result;
const finalResult = [];
const errors = [];
try {
if ((0, is_glob_1.default)(path)) {
const resolvedPaths = this.resolveGlobsSync(pointer, (0, utils_1.asArray)(options.ignore || []));
for (const path of resolvedPaths) {
if (this.canLoadSync(path)) {
const results = this.loadSync(path, options);
for (const result of results) {
finalResult.push(result);
}
}
}
}
else if (this.canLoadSync(pointer)) {
const results = this.handleSingularPointerSync(pointer, options);
for (const result of results) {
finalResult.push(result);
}
}
}
catch (error) {
if (process_1.env['DEBUG']) {
console.error(error);
}
if (error instanceof AggregateError) {
for (const errorElement of error.errors) {
errors.push(errorElement);
}
}
else {
errors.push(error);
}
}
if (finalResult.length === 0 && errors.length > 0) {
if (errors.length === 1) {
throw errors[0];
}
throw new AggregateError(errors, `Reading from ${pointer} failed ; \n ` + errors.map((e) => e.message).join('\n'));
}
return finalResult;
}
}
exports.GitLoader = GitLoader;
;