tcmts.loader.packages

Types

CachePackageJson type
Candidate type
PackageLock type
The codebase's package lock: the exact version of each package used within each compatible range.
Progress type
How installs are shown: a line each by default; the CLI shows spinners on a terminal.
Viewed type
What `<package manager> view` said.

Server

candidates (name: string, range: string) => Candidate[]
checkIntegrity (lay: Layout, lock: PackageLock) => void
A locked version means exactly one tarball: the first install records its integrity (the registry's sha512), and an install that got different bytes for the same version is refused.
ensureExternals (lay: Layout, exts: Iterable<ExtRef>) => void
Install what `exts` import: each package at its locked version (picking one for ranges not locked yet), under its range's alias, with DefinitelyTyped types (`@types/react`) beside packages that ship none.
hasTypes (lay: Layout, alias: string) => boolean
Whether an installed package carries its own types.
install (lay: Layout, what: string[]) => void
installDir (lay: Layout, name: string, range: string) => string
Where a locked package range is installed: its alias, `@types/<alias>` for DefinitelyTyped packages.
installedIntegrity (lay: Layout) => Map<string, string>
What the cache's install got, by `name@version`: the integrity its package manager recorded for each tarball.
installedPeers (lay: Layout, module: string) => Record<string, string>
The peer dependencies of the installed copy of a pinned module.
installedVersion (lay: Layout, alias: string) => string | undefined
linkPeers (lay: Layout, lock: PackageLock) => void
Point each installed package's peers at the locked range its peer range accepts. Package managers resolve a peer by name across the whole install, so with two ranges of React in the cache, React DOM 18 could get React 19 (pnpm), or a second copy at the same version (npm). Two copies of one React break it, and the wrong one breaks it worse. A link inside the package wins: Node resolution looks there first.
newestVersion (name: string) => string | undefined
The newest version of `name` (its `latest` tag), from the registry; undefined if there's no such package.
oneCopyEach (lay: Layout, locked: { name: string; range: string; version: string; }[]) => void
One copy of each package version in the cache. npm installs a package a peer asks for (React, for React Aria's own packages) at its name, beside the alias tcm installed it under: two copies of one version, which React can't be (two Reacts break hooks). A package at its name that's a locked version becomes a link to that version's alias. Run after each install (npm puts its copy back).
packageManager () => "npm" | "pnpm"
pnpm when it's installed, else npm.
pickVersions (wanted: { name: string; range: string; }[], lock: PackageLock) => void
Pick versions for packages the lock doesn't have yet: the newest in each range whose peers accept what's locked. Peers among the packages being picked are picked first, so React comes before React DOM.
progress Progress
registryView (args: string[], view?: (args: string[]) => Viewed, pause?: (ms: number) => void) => Viewed
`<package manager> view <args>`, asked again (twice, a moment apart, then longer) when it fails other than by the package or version not being there: a registry that didn't answer once (a timeout, a dropped connection) isn't a package that doesn't exist. `view` and `pause` are for tests.
resolvesTo (name: string, dir: string) => string | undefined
Where Node (and Vite, and TypeScript) would find package `name` from inside directory `dir`.
setProgress (p: Progress) => void
shippedPackage (name: string) => { dir: string; version: string; } | undefined
A package tcm ships, installed with it: its directory and version. Undefined for others, and where tcm has none beside it. The directory is the package's own, links followed. Run from its codebase, tcm ships what the codebase installed for it (its package's `with`), in the cache it runs from: at its name (Vitest, through the cache's link to it), or else under its alias, as its browser test runner is (all of it, so they're one install: a codebase given Vitest linked and its browser side installed gets two that don't fit).
versionsIn (name: string, range: string) => { version: string; peers: Record<string, string>; }[]
Versions of `name` in npm range `range` with their peer dependencies, newest first (no prereleases, unless asked).
writeIfChanged (file: string, text: string) => boolean

Shared

SHIPPED Set<string>
The packages tcm ships (dependencies of the tcm-ts package, at the versions its tests ran): the tools it runs (oxlint, oxfmt, the React Compiler) and its test runner (Vitest, which tests import, and its browser side).
lockAtLeast (lay: Layout, name: string, range: string, version: string) => string | undefined
Raise the lock for `name` within `range` to at least `version`: code was checked against it, and within a compatible range a newer version only adds (semver). Returns the version before, if it changed.
lockOf (lay: Layout) => PackageLock
locks Map<string, PackageLock>
manager "npm" | "pnpm" | undefined
memoryLock () => PackageLock
npmAlias (module: string) => string
The cache alias for a pinned module: `npm:@scope/name@19` (or `@19.3.1`) → `npm__scope__name__19`.
parseModule (module: string) => { name: string; version: string; }
`npm:@scope/name@19` → `{ name: "@scope/name", version: "19" }`
shippedPins Map<string, (name: string) => string | undefined>
By cache: the range a codebase chose for a package tcm ships (`tcm upgrade vitest@<range>`), if any
usePackageLock (lay: Layout, lock: PackageLock) => void
The lock installs in this layout follow (the codebase registers its own).
viewed Map<string, Candidate[]>

Tests

testOneCopyOfEachVersion () => void
testRegistryViewAsksAgain () => void
The registry is asked again when it didn't answer, not when the package isn't there.