@graphql-yoga/plugin-apq
Version:
APQ plugin for GraphQL Yoga.
77 lines (76 loc) • 2.82 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAPQ = exports.createInMemoryAPQStore = exports.hashSHA256 = void 0;
const graphql_yoga_1 = require("graphql-yoga");
const tiny_lru_1 = require("tiny-lru");
async function hashSHA256(str, api = globalThis) {
const { crypto, TextEncoder } = api;
const textEncoder = new TextEncoder();
const utf8 = textEncoder.encode(str);
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
let hashHex = '';
for (const bytes of new Uint8Array(hashBuffer)) {
hashHex += bytes.toString(16).padStart(2, '0');
}
return hashHex;
}
exports.hashSHA256 = hashSHA256;
function createInMemoryAPQStore(options = {}) {
return (0, tiny_lru_1.lru)(options.max ?? 1000, options.ttl ?? 36000);
}
exports.createInMemoryAPQStore = createInMemoryAPQStore;
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 } = options;
return {
async onParams({ params, setParams, fetchAPI }) {
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 (0, graphql_yoga_1.createGraphQLError)('PersistedQueryNotFound', {
extensions: {
http: {
status: 404,
},
},
});
}
setParams({
...params,
query: persistedQuery,
});
}
else {
const expectedHash = await hash(params.query, fetchAPI);
if (persistedQueryData.sha256Hash !== expectedHash) {
throw (0, graphql_yoga_1.createGraphQLError)('PersistedQueryMismatch', {
extensions: {
http: {
status: 400,
},
},
});
}
await store.set(persistedQueryData.sha256Hash, params.query);
}
},
};
}
exports.useAPQ = useAPQ;
;