UNPKG

@node-idempotency/fastify

Version:

fastify plugin that provides Race-Condition free idempotency for HTTP requests, preventing unintended duplicate operations.

88 lines 3.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.idempotencyAsPlugin = void 0; const shared_1 = require("@node-idempotency/shared"); const core_1 = require("@node-idempotency/core"); const setHeaders = (response, headers) => { Object.keys(headers).forEach((key) => { if (headers[key]) { void response.header(key, headers[key]); } }); }; const onResponse = async (request, reply, payload, nodeIdempotency) => { const idempotencyReq = { headers: request.headers, body: request.body, path: request.url, method: request.method, }; const { statusCode } = reply; const additional = { statusCode }; Object.values(shared_1.headers2Cache).forEach((header) => { const head = reply.getHeader(header); if (head) { additional[header] = head; } }); const res = { additional, ...(statusCode < 400 ? { body: payload } : { error: payload }), }; await nodeIdempotency.onResponse(idempotencyReq, res); }; const onRequest = async (request, reply, nodeIdempotency) => { const idempotencyReq = { headers: request.headers, body: request.body, path: request.url, method: request.method, }; try { const idempotencyResponse = await nodeIdempotency.onRequest(idempotencyReq); if (!idempotencyResponse) { return; } if (idempotencyResponse.additional?.statusCode) { const { statusCode } = idempotencyResponse.additional; void reply.status(statusCode); } const headers = Object.values(shared_1.headers2Cache).reduce((res, cur) => { if (idempotencyResponse?.additional?.[cur]) { res[cur] = idempotencyResponse.additional[cur]; } return res; }, {}); setHeaders(reply, { ...headers, [shared_1.HTTPHeaderEnum.idempotentReplayed]: "true", }); return await reply.send(idempotencyResponse.body || idempotencyResponse.error); } catch (err) { if (err instanceof core_1.IdempotencyError) { const status = shared_1.idempotency2HttpCodeMap[err.code] || 500; if (err.code === core_1.IdempotencyErrorCodes.REQUEST_IN_PROGRESS) { setHeaders(reply, { [shared_1.HTTPHeaderEnum.retryAfter]: "1" }); } return await reply.status(status).send(err); } } }; const idempotencyAsPlugin = async (fastify, options) => { const storageAdapter = await (0, shared_1.buildStorageAdapter)(options.storage); const idempotency = new core_1.Idempotency(storageAdapter, options); fastify.addHook("preHandler", async (request, reply) => { await onRequest(request, reply, idempotency); }); fastify.addHook("onSend", async (request, reply, payload) => { await onResponse(request, reply, payload, idempotency); }); fastify.addHook("onClose", async () => { if (typeof storageAdapter.disconnect === "function") { await storageAdapter.disconnect(); } }); }; exports.idempotencyAsPlugin = idempotencyAsPlugin; //# sourceMappingURL=idempotent-fastify.js.map