Files
pnpm/pnpm11/cache/api/src/cacheView.ts
Zoltan Kochan fc2f33912e refactor: move the TypeScript pnpm CLI into a pnpm11/ directory (#12537)
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.

Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.

Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
  .gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
  pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
  climb one more level to reach the repo root

.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.

TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.
2026-06-20 14:36:25 +02:00

70 lines
2.4 KiB
TypeScript

import fs from 'node:fs'
import path from 'node:path'
import type { PackageMeta } from '@pnpm/resolving.npm-resolver'
import { StoreIndex, storeIndexKey } from '@pnpm/store.index'
import getRegistryName from 'encode-registry'
import { glob } from 'tinyglobby'
interface CachedVersions {
cachedVersions: string[]
nonCachedVersions: string[]
cachedAt?: string
distTags: Record<string, string>
}
export async function cacheView (opts: { cacheDir: string, storeDir: string, registry?: string }, packageName: string): Promise<string> {
const prefix = opts.registry ? `${getRegistryName(opts.registry)}` : '*'
const metaFilePaths = (await glob(`${prefix}/${packageName}.jsonl`, {
cwd: opts.cacheDir,
expandDirectories: false,
})).sort()
const metaFilesByPath: Record<string, CachedVersions> = {}
const storeIndex = new StoreIndex(opts.storeDir)
try {
for (const filePath of metaFilePaths) {
let metaObject: PackageMeta | null
const fullPath = path.join(opts.cacheDir, filePath)
let mtime: Date | undefined
try {
const raw = fs.readFileSync(fullPath, 'utf8')
mtime = fs.statSync(fullPath).mtime
const newlineIdx = raw.indexOf('\n')
if (newlineIdx !== -1) {
// NDJSON format: line 1 = headers, line 2 = metadata
metaObject = JSON.parse(raw.slice(newlineIdx + 1)) as PackageMeta
} else {
metaObject = JSON.parse(raw) as PackageMeta
}
} catch {
continue
}
if (!metaObject) continue
const cachedVersions: string[] = []
const nonCachedVersions: string[] = []
for (const [version, manifest] of Object.entries(metaObject.versions)) {
if (!manifest.dist.integrity) continue
const key = storeIndexKey(manifest.dist.integrity, `${manifest.name}@${manifest.version}`)
if (storeIndex.has(key)) {
cachedVersions.push(version)
} else {
nonCachedVersions.push(version)
}
}
let registryName = filePath
while (path.dirname(registryName) !== '.') {
registryName = path.dirname(registryName)
}
metaFilesByPath[registryName.replaceAll('+', ':')] = {
cachedVersions,
nonCachedVersions,
cachedAt: mtime?.toString(),
distTags: metaObject['dist-tags'],
}
}
} finally {
storeIndex.close()
}
return JSON.stringify(metaFilesByPath, null, 2)
}