UNPKG

@graphql-tools/module-loader

Version:

A set of utils for faster development of GraphQL tools

148 lines (147 loc) 5.16 kB
"use strict"; 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;