Files
pnpm/resolving/npm-resolver/test/utils/index.ts
Zoltan Kochan 2554264fdd perf: use NDJSON format for metadata cache (#11188)
The metadata cache files now use a two-line NDJSON format:
- Line 1: cache headers (etag, modified, cachedAt) ~100 bytes
- Line 2: raw registry metadata JSON (unchanged)

This allows loadMetaHeaders to read only the first 1 KB of the file
to extract conditional-request headers (etag, modified), avoiding
the cost of reading and parsing multi-MB metadata files when the
registry returns 200 and the old metadata would be discarded.

Also moves cache directories to v11/ namespace (v11/metadata,
v11/metadata-full, v11/metadata-full-filtered) since the format
is not backwards compatible.
2026-04-04 01:24:05 +02:00

38 lines
1.1 KiB
TypeScript

import fs from 'node:fs'
export { getMockAgent, setupMockAgent, teardownMockAgent } from '@pnpm/testing.mock-agent'
export async function retryLoadJsonFile<T> (filePath: string): Promise<T> {
let retry = 0
/* eslint-disable no-await-in-loop */
while (true) {
await delay(500)
try {
const data = await fs.promises.readFile(filePath, 'utf8')
return parseNdjsonMeta(data) as T
} catch (err: any) { // eslint-disable-line
if (retry > 2) throw err
retry++
}
}
/* eslint-enable no-await-in-loop */
}
/**
* Parses an NDJSON cache file: line 1 = headers, line 2 = metadata.
* The headers (etag, modified) are merged into the metadata object.
*/
export function parseNdjsonMeta<T> (data: string): T {
const newlineIdx = data.indexOf('\n')
if (newlineIdx === -1) return JSON.parse(data) as T
const headers = JSON.parse(data.slice(0, newlineIdx))
const meta = JSON.parse(data.slice(newlineIdx + 1))
return { ...meta, ...headers } as T
}
export async function delay (time: number): Promise<void> {
return new Promise<void>((resolve) => setTimeout(() => {
resolve()
}, time))
}