UNPKG

@graphql-yoga/plugin-apq

Version:
60 lines (59 loc) 2.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useAPQ = exports.createInMemoryAPQStore = exports.hashSHA256 = void 0; const graphql_1 = require("graphql"); const tiny_lru_1 = require("tiny-lru"); const fetch_1 = require("@whatwg-node/fetch"); const textEncoder = new fetch_1.TextEncoder(); async function hashSHA256(str) { const utf8 = textEncoder.encode(str); const hashBuffer = await fetch_1.crypto.subtle.digest('SHA-256', utf8); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray .map((bytes) => bytes.toString(16).padStart(2, '0')) .join(''); return hashHex; } exports.hashSHA256 = hashSHA256; function createInMemoryAPQStore(options = {}) { return (0, tiny_lru_1.lru)(options.max ?? 1000, options.ttl ?? 36000); } exports.createInMemoryAPQStore = createInMemoryAPQStore; function decodeAPQExtension(input) { if (input != null && typeof input === 'object' && input?.version === 1 && typeof input?.sha256Hash === 'string') { return input; } return null; } function useAPQ(options = {}) { const { store = createInMemoryAPQStore(), hash = hashSHA256 } = options; return { async onParams({ params, setParams }) { const persistedQueryData = decodeAPQExtension(params.extensions?.persistedQuery); if (persistedQueryData === null) { return; } if (params.query == null) { const persistedQuery = await store.get(persistedQueryData.sha256Hash); if (persistedQuery == null) { throw new graphql_1.GraphQLError('PersistedQueryNotFound'); } setParams({ ...params, query: persistedQuery, }); } else { const expectedHash = await hash(params.query); if (persistedQueryData.sha256Hash !== expectedHash) { throw new graphql_1.GraphQLError('PersistedQueryMismatch'); } await store.set(persistedQueryData.sha256Hash, params.query); } }, }; } exports.useAPQ = useAPQ;