tcmts.cli.npm

Types

ModuleShape type
A module, as the analysis has it: its top-level declarations, what running it does, and what it exports.
NpmFacts type
What a package's export reaches, worked out from its code as tcm works out its own's: through every declaration it uses, in its module, the package's other modules and the packages they import. `effects`: what it reaches outside (the clock, randomness, the network, files, the environment, other processes, output), as `reaches` has them; `node`: Node's modules and globals it uses (it needs the server); `dom`: the browser's globals it uses (it needs the browser); `state`: a module it uses holds state something could change (a top-level `let`, or an object or array); `opaque`: what couldn't be followed (a computed `import()` or `require()`, `eval`, a module not found), so the rest can't be trusted to be all of it. `client`: why it's browser code, as React has it, if it is: a module it's in says `"use client"`, or it uses React's hooks, contexts or class components (which React's server components can't).
PackageJson type
A package's manifest, as far as resolving its modules goes.
Unit type
What a top-level declaration of a module (or its top-level code) uses itself: its own globals and imports.

Server

exportFacts (file: string, name: string, side: "browser" | "server", cacheDir: string) => NpmFacts
What `name` (an export; `*`, all of the module) of `file` reaches, on a side (its conditions resolve the packages it imports), following everything it uses (NpmFacts). Kept in `cacheDir/npm-facts`, by the package's installed directory (which is its version's, and never changes).
isPureExport (cacheDir: string, ext: ExtRef) => boolean
An npm package's export whose code, through everything it uses, renders the same for the same arguments on the server: it reaches nothing outside (NpmFacts), holds no state, uses no browser globals, and nothing of it couldn't be followed. (Node's modules it uses for that are fine: `node:path`.)
moduleFile (at: string) => string | undefined
The file a module path names, as Node and bundlers find it: as it is, with `.js`/`.mjs`/`.cjs`/`.json`, or its `index.js`.
moduleShape (file: string, text: string) => ModuleShape
A module's shape (`ModuleShape`), from its code.
npmFacts (cacheDir: string, ext: ExtRef, side: "browser" | "server") => NpmFacts | undefined
What an npm package's export (as code refers to it: `npm:<name>@<range>`, a subpath, an export) reaches on a side (exportFacts), from the package as the codebase has it installed; undefined if it isn't, or its export map names no file for it there. Kept for this process (factsKept) while the package's `package.json` is the same file: placing a codebase asks of each package many times over.
resolveSpecifier (from: string, spec: string, conditions: readonly string[]) => { builtin: string; } | { file: strin…
Where `spec`, imported from `from`, is: one of Node's modules, a file (in the same package, or another one found in `node_modules` above it, by its export map for `conditions`), or nothing found.

Shared

SIDE_CONDITIONS { readonly browser: readonly ["browser", "import", "module", "default"]; readonly server: readonly …
The conditions each side resolves packages with.
blockNames (statements: readonly StatementBase[], into: Set<string>) => void
The `let`, `const`, class and function declarations directly in a block's statements.
bound (name: BindingName) => string[]
The names a binding (a variable, a parameter, a destructuring pattern) declares.
emptyUnit () => Unit
factsKept Map<string, { stamp: number; facts: NpmFacts; }>
What npmFacts has worked out in this process, by package directory, export and side, with the time its `package.json` was written.
hoisted (body: Node | undefined, into: Set<string>) => void
`var`s and function declarations in a function's body, not in functions inside it: hoisted to its scope.
isFunctionLike (n: Node) => n is ArrowFunction | ConstructorDeclaration | FunctionDeclaration | FunctionExpression…
literalText (n: Node | undefined) => string | undefined
merge (into: Unit, u: Unit) => void
`into` and what `u` uses, together.
parseExtRef (ref: string) => ExtRef | undefined
An external reference as a definition's dependencies write it (`npm:x@1/sub#name`), read back.
resolvePackageSubpath (pkg: PackageJson, subpath: string, conditions: string[]) => string | undefined
The file a package's export map (`exports`) gives for a subpath (`.`, `./utils`), under the conditions a side resolves with (in order of what matters), as Node and bundlers read it: a string, conditions, arrays, `*` patterns. Without `exports`: `browser` (in the browser), `module`, `main`, `index.js`; a subpath is a path in it.
shapes Map<string, ModuleShape>
Modules' shapes, by file, for this process; and what's worked out of each package, kept beside it on disk.
unitOf (node: Node, top: Set<string>, imported: Map<string, { spec: string; name: string; }>) => Unit
What code in `node` uses, as one unit: the globals it refers to (an identifier no scope inside the module declares), `Global.member`s, the module's top-level names (`top`) and imported bindings (`imported`), `require()` and `import()` of modules (computed ones are opaque), and `eval`.

Tests

testNpmFactsAreKeptWhileInstalled () => void
An installed package's facts are read once a process, and a package that's gone isn't found any more.
testPackagesAreAnalyzedByExport () => void
Packages, as files under a directory's node_modules: what each export reaches is worked out from their code.