@graphql-tools/module-loader
Version:
A set of utils for faster development of GraphQL tools
148 lines (147 loc) • 5.16 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleLoader = void 0;
const fs_1 = require("fs");
const graphql_1 = require("graphql");
const { access } = fs_1.promises;
const InvalidError = new Error(`Imported object was not a string, DocumentNode or GraphQLSchema`);
const createLoadError = (error) => new Error('Unable to load schema from module: ' + `${error.message || /* istanbul ignore next */ error}`);
// module:node/module#export
function extractData(pointer) {
const parts = pointer.replace(/^module\:/i, '').split('#');
if (!parts || parts.length > 2) {
throw new Error('Schema pointer should match "module:path/to/module#export"');
}
return {
modulePath: parts[0],
exportName: parts[1],
};
}
/**
* * This loader loads documents and type definitions from a Node module
*
* ```js
* const schema = await loadSchema('module:someModuleName#someNamedExport', {
* loaders: [new ModuleLoader()],
* })
* ```
*/
class ModuleLoader {
isExpressionValid(pointer) {
return typeof pointer === 'string' && pointer.toLowerCase().startsWith('module:');
}
async canLoad(pointer) {
if (this.isExpressionValid(pointer)) {
const { modulePath } = extractData(pointer);
try {
const moduleAbsolutePath = require.resolve(modulePath);
await access(moduleAbsolutePath);
return true;
}
catch (e) {
return false;
}
}
return false;
}
canLoadSync(pointer) {
if (this.isExpressionValid(pointer)) {
const { modulePath } = extractData(pointer);
try {
const moduleAbsolutePath = require.resolve(modulePath);
return (0, fs_1.existsSync)(moduleAbsolutePath);
}
catch (e) {
return false;
}
}
return false;
}
async load(pointer) {
try {
const result = this.parse(pointer, await this.importModule(pointer));
if (result) {
return [result];
}
throw InvalidError;
}
catch (error) {
throw createLoadError(error);
}
}
loadSync(pointer) {
try {
const result = this.parse(pointer, this.importModuleSync(pointer));
if (result) {
return [result];
}
throw InvalidError;
}
catch (error) {
throw createLoadError(error);
}
}
parse(pointer, importedModule) {
if ((0, graphql_1.isSchema)(importedModule)) {
return {
schema: importedModule,
location: pointer,
};
}
else if (typeof importedModule === 'string') {
return {
location: pointer,
rawSDL: importedModule,
};
}
else if (typeof importedModule === 'object' && importedModule.kind === 'Document') {
return {
location: pointer,
document: importedModule,
};
}
}
extractFromModule(mod, modulePath, identifier) {
const thing = identifier ? mod[identifier] : mod;
if (!thing) {
throw new Error('Unable to import an object from module: ' + modulePath);
}
return thing;
}
// Sync and Async
async importModule(pointer) {
const { modulePath, exportName } = extractData(pointer);
const imported = await Promise.resolve(`${modulePath}`).then(s => __importStar(require(s)));
return this.extractFromModule(imported, modulePath, exportName || 'default');
}
importModuleSync(pointer) {
const { modulePath, exportName } = extractData(pointer);
// eslint-disable-next-line @typescript-eslint/no-require-imports
const imported = require(modulePath);
return this.extractFromModule(imported, modulePath, exportName);
}
}
exports.ModuleLoader = ModuleLoader;
;