| import { InvariantError } from '../../shared/lib/invariant-error' |
| import { |
| type UseCacheCacheStore, |
| type FetchCacheStore, |
| type EncryptedBoundArgsCacheStore, |
| serializeUseCacheCacheStore, |
| parseUseCacheCacheStore, |
| type DecryptedBoundArgsCacheStore, |
| type UseCacheCacheStoreSerialized, |
| } from './cache-store' |
|
|
| |
| |
| |
| |
| export interface RenderResumeDataCache { |
| |
| |
| |
| |
| readonly cache: Omit<UseCacheCacheStore, 'set'> |
|
|
| |
| |
| |
| |
| readonly fetch: Omit<FetchCacheStore, 'set'> |
|
|
| |
| |
| |
| |
| readonly encryptedBoundArgs: Omit<EncryptedBoundArgsCacheStore, 'set'> |
|
|
| |
| |
| |
| |
| |
| |
| readonly decryptedBoundArgs: Omit<DecryptedBoundArgsCacheStore, 'set'> |
| } |
|
|
| |
| |
| |
| |
| export interface PrerenderResumeDataCache { |
| |
| |
| |
| |
| |
| readonly cache: UseCacheCacheStore |
|
|
| |
| |
| |
| |
| |
| readonly fetch: FetchCacheStore |
|
|
| |
| |
| |
| |
| |
| readonly encryptedBoundArgs: EncryptedBoundArgsCacheStore |
|
|
| |
| |
| |
| |
| |
| |
| readonly decryptedBoundArgs: DecryptedBoundArgsCacheStore |
| } |
|
|
| type ResumeStoreSerialized = { |
| store: { |
| cache: { |
| [key: string]: any |
| } |
| fetch: { |
| [key: string]: any |
| } |
| encryptedBoundArgs: { |
| [key: string]: string |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export async function stringifyResumeDataCache( |
| resumeDataCache: RenderResumeDataCache | PrerenderResumeDataCache, |
| isCacheComponentsEnabled: boolean |
| ): Promise<string> { |
| if (process.env.NEXT_RUNTIME === 'edge') { |
| throw new InvariantError( |
| '`stringifyResumeDataCache` should not be called in edge runtime.' |
| ) |
| } else { |
| if (resumeDataCache.fetch.size === 0 && resumeDataCache.cache.size === 0) { |
| return 'null' |
| } |
|
|
| const json: ResumeStoreSerialized = { |
| store: { |
| fetch: Object.fromEntries(Array.from(resumeDataCache.fetch.entries())), |
| cache: Object.fromEntries( |
| ( |
| await serializeUseCacheCacheStore( |
| resumeDataCache.cache.entries(), |
| isCacheComponentsEnabled |
| ) |
| ).filter( |
| (entry): entry is [string, UseCacheCacheStoreSerialized] => |
| entry !== null |
| ) |
| ), |
| encryptedBoundArgs: Object.fromEntries( |
| Array.from(resumeDataCache.encryptedBoundArgs.entries()) |
| ), |
| }, |
| } |
|
|
| |
| |
| const { deflateSync } = require('node:zlib') as typeof import('node:zlib') |
|
|
| return deflateSync(JSON.stringify(json)).toString('base64') |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function createPrerenderResumeDataCache(): PrerenderResumeDataCache { |
| return { |
| cache: new Map(), |
| fetch: new Map(), |
| encryptedBoundArgs: new Map(), |
| decryptedBoundArgs: new Map(), |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export function createRenderResumeDataCache( |
| renderResumeDataCache: RenderResumeDataCache |
| ): RenderResumeDataCache |
| export function createRenderResumeDataCache( |
| prerenderResumeDataCache: PrerenderResumeDataCache |
| ): RenderResumeDataCache |
| export function createRenderResumeDataCache( |
| persistedCache: string, |
| maxPostponedStateSizeBytes: number | undefined |
| ): RenderResumeDataCache |
| export function createRenderResumeDataCache( |
| resumeDataCacheOrPersistedCache: |
| | RenderResumeDataCache |
| | PrerenderResumeDataCache |
| | string, |
| maxPostponedStateSizeBytes?: number | undefined |
| ): RenderResumeDataCache { |
| if (process.env.NEXT_RUNTIME === 'edge') { |
| throw new InvariantError( |
| '`createRenderResumeDataCache` should not be called in edge runtime.' |
| ) |
| } else { |
| if (typeof resumeDataCacheOrPersistedCache !== 'string') { |
| |
| |
| return resumeDataCacheOrPersistedCache |
| } |
|
|
| if (resumeDataCacheOrPersistedCache === 'null') { |
| return { |
| cache: new Map(), |
| fetch: new Map(), |
| encryptedBoundArgs: new Map(), |
| decryptedBoundArgs: new Map(), |
| } |
| } |
|
|
| |
| |
| |
| const { inflateSync } = require('node:zlib') as typeof import('node:zlib') |
|
|
| |
| |
| |
| |
| const maxDecompressedSize = maxPostponedStateSizeBytes |
| ? maxPostponedStateSizeBytes * 5 |
| : 500 * 1024 * 1024 |
|
|
| let json: ResumeStoreSerialized |
| try { |
| json = JSON.parse( |
| inflateSync(Buffer.from(resumeDataCacheOrPersistedCache, 'base64'), { |
| maxOutputLength: maxDecompressedSize, |
| }).toString('utf-8') |
| ) |
| } catch (err: unknown) { |
| if ( |
| err instanceof RangeError && |
| (err as NodeJS.ErrnoException).code === 'ERR_BUFFER_TOO_LARGE' |
| ) { |
| throw new Error( |
| `Decompressed resume data cache exceeded ${maxDecompressedSize} byte limit` |
| ) |
| } |
| throw err |
| } |
|
|
| return { |
| cache: parseUseCacheCacheStore(Object.entries(json.store.cache)), |
| fetch: new Map(Object.entries(json.store.fetch)), |
| encryptedBoundArgs: new Map( |
| Object.entries(json.store.encryptedBoundArgs) |
| ), |
| decryptedBoundArgs: new Map(), |
| } |
| } |
| } |
|
|