UNPKG

@graphql-yoga/plugin-apq

Version:
82 lines (81 loc) 3.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hashSHA256 = hashSHA256; exports.createInMemoryAPQStore = createInMemoryAPQStore; exports.useAPQ = useAPQ; const graphql_yoga_1 = require("graphql-yoga"); const promise_helpers_1 = require("@whatwg-node/promise-helpers"); function hashSHA256(text, api = globalThis) { const inputUint8Array = new api.TextEncoder().encode(text); return (0, promise_helpers_1.handleMaybePromise)(() => api.crypto.subtle.digest({ name: 'SHA-256' }, inputUint8Array), arrayBuf => { const outputUint8Array = new Uint8Array(arrayBuf); let hash = ''; for (const byte of outputUint8Array) { const hex = byte.toString(16); hash += '00'.slice(0, Math.max(0, 2 - hex.length)) + hex; } return hash; }); } function createInMemoryAPQStore(options = {}) { return (0, graphql_yoga_1.createLRUCache)({ max: options.max ?? 1000, ttl: options.ttl ?? 36_000, }); } function isAPQExtension(input) { return (input != null && typeof input === 'object' && 'version' in input && input?.version === 1 && 'sha256Hash' in input && typeof input?.sha256Hash === 'string'); } function decodeAPQExtension(input) { if (isAPQExtension(input)) { return input; } return null; } function useAPQ(options = {}) { const { store = createInMemoryAPQStore(), hash = hashSHA256, responseConfig = {} } = options; return { onParams({ params, setParams, fetchAPI }) { const persistedQueryData = decodeAPQExtension(params.extensions?.['persistedQuery']); if (persistedQueryData === null) { return; } if (params.query == null) { return (0, promise_helpers_1.handleMaybePromise)(() => store.get(persistedQueryData.sha256Hash), persistedQuery => { if (persistedQuery == null) { throw (0, graphql_yoga_1.createGraphQLError)('PersistedQueryNotFound', { extensions: { http: { status: responseConfig.forceStatusCodeOk ? 200 : 404, }, code: 'PERSISTED_QUERY_NOT_FOUND', }, }); } setParams({ ...params, query: persistedQuery, }); }); } return (0, promise_helpers_1.handleMaybePromise)(() => hash(params.query, fetchAPI), expectedHash => { if (persistedQueryData.sha256Hash !== expectedHash) { throw (0, graphql_yoga_1.createGraphQLError)('PersistedQueryMismatch', { extensions: { http: { status: responseConfig.forceStatusCodeOk ? 200 : 400, }, code: 'PERSISTED_QUERY_MISMATCH', }, }); } return store.set(persistedQueryData.sha256Hash, params.query); }); }, }; }