UNPKG

@graphql-tools/load

Version:

A set of utils for faster development of GraphQL tools

105 lines (104 loc) • 4.24 kB
import { asArray, compareStrings } from '@graphql-tools/utils'; import { collectSources, collectSourcesSync } from './load-typedefs/collect-sources.js'; import { applyDefaultOptions } from './load-typedefs/options.js'; import { parseSource } from './load-typedefs/parse.js'; import { useLimit } from './utils/helpers.js'; import { normalizePointers } from './utils/pointers.js'; const CONCURRENCY_LIMIT = 100; /** * Asynchronously loads any GraphQL documents (i.e. executable documents like * operations and fragments as well as type system definitions) from the * provided pointers. * loadTypedefs does not merge the typeDefs when `#import` is used ( https://github.com/ardatan/graphql-tools/issues/2980#issuecomment-1003692728 ) * @param pointerOrPointers Pointers to the sources to load the documents from * @param options Additional options */ export async function loadTypedefs(pointerOrPointers, options) { const { ignore, pointerOptionMap } = normalizePointers(pointerOrPointers); options.ignore = asArray(options.ignore || []); options.ignore.push(...ignore); applyDefaultOptions(options); const sources = await collectSources({ pointerOptionMap, options, }); const parsedSources = []; // If we have few k of files it may be an issue const limit = useLimit(CONCURRENCY_LIMIT); await Promise.all(sources.map(partialSource => limit(() => parseSource({ partialSource, options, pointerOptionMap, addSource(source) { parsedSources.push(source); }, })))); return prepareResult({ options, pointerOptionMap, parsedSources }); } /** * Synchronously loads any GraphQL documents (i.e. executable documents like * operations and fragments as well as type system definitions) from the * provided pointers. * @param pointerOrPointers Pointers to the sources to load the documents from * @param options Additional options */ export function loadTypedefsSync(pointerOrPointers, options) { const { ignore, pointerOptionMap } = normalizePointers(pointerOrPointers); options.ignore = asArray(options.ignore || []).concat(ignore); applyDefaultOptions(options); const sources = collectSourcesSync({ pointerOptionMap, options, }); const parsedSources = []; for (const partialSource of sources) { parseSource({ partialSource, options, pointerOptionMap, addSource(source) { parsedSources.push(source); }, }); } return prepareResult({ options, pointerOptionMap, parsedSources }); } // function prepareResult({ options, pointerOptionMap, parsedSources, }) { const failedSources = parsedSources.filter(source => source.error != null); if (failedSources.length > 0) { if (options.errorHandling === 'aggregate') { const errors = failedSources.map(source => source.error); throw new AggregateError(errors, errors.map(error => error.message).join('\n')); } if (options.errorHandling === 'throw') { throw failedSources[0].error; } } const resultSources = options.errorHandling === 'return' ? parsedSources : parsedSources.filter(source => source.error == null); const pointerList = Object.keys(pointerOptionMap); const loadedDocuments = resultSources.filter(source => source.document?.definitions && source.document.definitions.length > 0); if (pointerList.length > 0 && loadedDocuments.length === 0 && options.errorHandling !== 'return') { throw new NoTypeDefinitionsFound(pointerList); } if (pointerList.length > 0 && resultSources.length === 0) { throw new NoTypeDefinitionsFound(pointerList); } return options.sort ? resultSources.sort((left, right) => compareStrings(left.location, right.location)) : resultSources; } export class NoTypeDefinitionsFound extends Error { constructor(pointerList) { super(` Unable to find any GraphQL type definitions for the following pointers: ${pointerList.map(p => ` - ${p} `)}`); this.name = 'NoTypeDefinitionsFound'; } }