UNPKG

@envelop/graphql-jit

Version:

This plugins replaces the original `execute` of GraphQL with [`graphql-jit`](https://github.com/zalando-incubator/graphql-jit).

70 lines (69 loc) 2.93 kB
/* eslint-disable no-console */ import { makeExecute, makeSubscribe } from '@envelop/core'; import { Source } from 'graphql'; import { compileQuery, isCompiledQuery } from 'graphql-jit'; import LRU from 'lru-cache'; const DEFAULT_MAX = 1000; const DEFAULT_TTL = 3600000; export const useGraphQlJit = (compilerOptions = {}, pluginOptions = {}) => { const documentSourceMap = new WeakMap(); const jitCache = typeof pluginOptions.cache !== 'undefined' ? pluginOptions.cache : new LRU({ max: DEFAULT_MAX, maxAge: DEFAULT_TTL }); function getCacheEntry(args) { let cacheEntry; const documentSource = documentSourceMap.get(args.document); if (documentSource) { cacheEntry = jitCache.get(documentSource); } if (!cacheEntry) { const compilationResult = compileQuery(args.schema, args.document, args.operationName ?? undefined, compilerOptions); if (!isCompiledQuery(compilationResult)) { if (pluginOptions?.onError) { pluginOptions.onError(compilationResult); } else { console.error(compilationResult); } cacheEntry = { query: () => compilationResult, }; } else { cacheEntry = compilationResult; } if (documentSource) { jitCache.set(documentSource, cacheEntry); } } return cacheEntry; } return { onParse({ params: { source } }) { const key = source instanceof Source ? source.body : source; return ({ result }) => { if (!result || result instanceof Error) return; documentSourceMap.set(result, key); }; }, async onExecute({ args, setExecuteFn }) { if (!pluginOptions.enableIf || (pluginOptions.enableIf && (await pluginOptions.enableIf(args)))) { setExecuteFn(makeExecute(function jitExecutor(args) { const cacheEntry = getCacheEntry(args); return cacheEntry.query(args.rootValue, args.contextValue, args.variableValues); })); } }, async onSubscribe({ args, setSubscribeFn }) { if (!pluginOptions.enableIf || (pluginOptions.enableIf && (await pluginOptions.enableIf(args)))) { setSubscribeFn(makeSubscribe(async function jitSubscriber(args) { const cacheEntry = getCacheEntry(args); return cacheEntry.subscribe ? cacheEntry.subscribe(args.rootValue, args.contextValue, args.variableValues) : cacheEntry.query(args.rootValue, args.contextValue, args.variableValues); })); } }, }; };