mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-11 10:40:53 -04:00
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.
38 lines
1.1 KiB
TypeScript
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))
|
|
}
|