UNPKG

@graphql-tools/load

Version:

A set of utils for faster development of GraphQL tools

188 lines (187 loc) • 6.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveLoaderModuleUrl = resolveLoaderModuleUrl; exports.getCustomLoaderByPath = getCustomLoaderByPath; exports.useCustomLoader = useCustomLoader; exports.useCustomLoaderSync = useCustomLoaderSync; const tslib_1 = require("tslib"); const fs_1 = require("fs"); const module_1 = require("module"); const path_1 = require("path"); const url_1 = require("url"); function extractLoaderFromModule(loaderModule) { if (loaderModule == null) { return undefined; } if (typeof loaderModule.default === 'function') { return loaderModule.default; } if (typeof loaderModule === 'function') { return loaderModule; } } function createLoaderRequire(cwd) { return (0, module_1.createRequire)((0, path_1.join)(cwd, 'noop.js')); } function isBarePackageSpecifier(specifier) { return !(0, path_1.isAbsolute)(specifier) && !specifier.startsWith('.') && !specifier.startsWith('file:'); } function findPackageDir(packageName, cwd) { let dir = cwd; while (true) { const candidate = (0, path_1.join)(dir, 'node_modules', ...packageName.split('/')); if ((0, fs_1.existsSync)((0, path_1.join)(candidate, 'package.json'))) { return candidate; } const parent = (0, path_1.dirname)(dir); if (parent === dir) { return undefined; } dir = parent; } } function stringFromConditionalExport(entry) { if (typeof entry === 'string') { return entry; } if (entry == null || typeof entry !== 'object') { return undefined; } const record = entry; const importEntry = record['import']; if (typeof importEntry === 'string') { return importEntry; } if (importEntry != null && typeof importEntry === 'object') { const nested = importEntry['default']; if (typeof nested === 'string') { return nested; } } const defaultEntry = record['default']; if (typeof defaultEntry === 'string') { return defaultEntry; } return undefined; } function packageImportEntry(exportsField) { if (typeof exportsField === 'string') { return exportsField; } if (exportsField == null || typeof exportsField !== 'object') { return undefined; } const record = exportsField; if (Object.prototype.hasOwnProperty.call(record, '.')) { return stringFromConditionalExport(record['.']); } return stringFromConditionalExport(record); } function resolvePackageImportPath(packageDir) { const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(packageDir, 'package.json'), 'utf8')); const entry = packageImportEntry(pkg.exports) ?? pkg.module ?? pkg.main; if (entry == null) { return undefined; } return (0, path_1.join)(packageDir, entry); } function resolveLoaderModuleUrl(path, cwd, requireFn) { try { return (0, url_1.pathToFileURL)(requireFn.resolve(path)).href; } catch { if (isBarePackageSpecifier(path)) { const packageDir = findPackageDir(path, cwd); const entry = packageDir != null ? resolvePackageImportPath(packageDir) : undefined; if (entry != null) { return (0, url_1.pathToFileURL)(entry).href; } } const absolutePath = (0, path_1.isAbsolute)(path) ? path : (0, path_1.join)(cwd, path); return (0, url_1.pathToFileURL)(absolutePath).href; } } function toError(error) { return error instanceof Error ? error : new Error(String(error)); } function missingFunctionExportError(path) { return new Error(`custom loader module did not export a function: ${path}`); } function combineLoadErrors(first, second) { if (first != null && first.message !== second.message) { return new Error(`${first}\n${second}`); } return first ?? second; } function failedToLoadCustomLoader(loaderPointer, error) { return new Error(`Failed to load custom loader: ${loaderPointer}\n${error}`); } async function loadCustomLoaderByPath(path, cwd) { const requireFn = createLoaderRequire(cwd); let requireError; try { const loader = extractLoaderFromModule(requireFn(path)); if (typeof loader === 'function') { return loader; } } catch (error) { // createRequire cannot load ESM; fall through to import(). requireError = toError(error); } try { const href = resolveLoaderModuleUrl(path, cwd, requireFn); const importedModule = await Promise.resolve(`${href}`).then(s => tslib_1.__importStar(require(s))); const loader = extractLoaderFromModule(importedModule); if (typeof loader === 'function') { return loader; } throw missingFunctionExportError(path); } catch (error) { throw combineLoadErrors(requireError, toError(error)); } } function loadCustomLoaderByPathSync(path, cwd) { const loader = extractLoaderFromModule(createLoaderRequire(cwd)(path)); if (typeof loader === 'function') { return loader; } throw missingFunctionExportError(path); } async function getCustomLoaderByPath(path, cwd) { try { return await loadCustomLoaderByPath(path, cwd); } catch { return null; } } async function useCustomLoader(loaderPointer, cwd) { if (typeof loaderPointer === 'function') { return loaderPointer; } if (typeof loaderPointer === 'string') { try { return await loadCustomLoaderByPath(loaderPointer, cwd); } catch (error) { throw failedToLoadCustomLoader(loaderPointer, toError(error)); } } throw new Error(`Failed to load custom loader: ${loaderPointer}`); } function useCustomLoaderSync(loaderPointer, cwd) { if (typeof loaderPointer === 'function') { return loaderPointer; } if (typeof loaderPointer === 'string') { try { return loadCustomLoaderByPathSync(loaderPointer, cwd); } catch (error) { throw failedToLoadCustomLoader(loaderPointer, toError(error)); } } throw new Error(`Failed to load custom loader: ${loaderPointer}`); }