Created
April 17, 2025 02:42
-
-
Save omavi/5527110cc6b664eefccd33fbb3f4aa20 to your computer and use it in GitHub Desktop.
NextJS 15 cache handler shim for transforming buffers appropriately
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This cache handler shim ensures compatibility with Redis, by converting | |
* buffers to strings on save and back to buffers on read, since the data | |
* is stored as JSON. | |
* | |
* This shim is a temporary workaround until Next 15 support is added to | |
* @neshca/cache-handler: | |
* https://github.com/caching-tools/next-shared-cache/pull/969 | |
* | |
* @param {import("@neshca/cache-handler").Handler} handler - The original cache handler to wrap. | |
* @returns {import("@neshca/cache-handler").Handler} - The transformed cache handler. | |
*/ | |
function bufferTransformCacheHandlerShim(handler) { | |
return { | |
name: handler.name, | |
async get(key, data) { | |
const result = await handler.get(key, data) | |
const value = result?.value | |
if (value?.kind === 'APP_PAGE') { | |
if (value.rscData) { | |
// Convert rscData string to Buffer | |
// See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L76 | |
value.rscData = Buffer.from(value.rscData, 'utf-8') | |
} | |
if (value.segmentData) { | |
// Convert segmentData Record<string, string> to Map<string, Buffer> | |
// See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L80 | |
value.segmentData = new Map( | |
Object.entries(value.segmentData).map(([key, value]) => [ | |
key, | |
Buffer.from(value, 'utf-8'), | |
]), | |
) | |
} | |
} | |
if (value?.kind === 'APP_ROUTE' && value?.body) { | |
// Convert body string to Buffer | |
// See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L97 | |
value.body = Buffer.from(value.body, 'utf-8') | |
} | |
return result | |
}, | |
async set(key, data) { | |
const value = data?.value | |
if (value?.kind === 'APP_PAGE') { | |
if (value.rscData) { | |
// Convert rscData Buffer to string | |
// See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L76 | |
value.rscData = value.rscData.toString() | |
} | |
if (value.segmentData) { | |
// Convert segmentData Map<string, Buffer> to Record<string, string> | |
// See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L80 | |
value.segmentData = Object.fromEntries( | |
Array.from(value.segmentData.entries()).map(([key, value]) => [key, value.toString()]), | |
) | |
} | |
} | |
if (value?.kind === 'APP_ROUTE' && value?.body) { | |
// Convert body Buffer to string | |
// See: https://github.com/vercel/next.js/blob/f5444a16ec2ef7b82d30048890b613aa3865c1f1/packages/next/src/server/response-cache/types.ts#L97 | |
value.body = value.body.toString() | |
} | |
await handler.set(key, data) | |
}, | |
async revalidateTag(tag) { | |
await handler.revalidateTag(tag) | |
}, | |
async delete(key) { | |
await handler.delete?.(key) | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment