- `cache`: a component module in `.tcm/cache`, imports by hash, exported as `h_<hash>` - `internal`: like cache but without exports; used to re-typecheck definitions after an update - `scratch`: editable source for the project root, imports through `#codebase/...`
Where `writeShim` puts a type package for each augmentation (named by its path, importing its module), for checks to list in `types`: every check in the codebase sees each one, as TypeScript's whole program would.
Write the cache modules `hashes` need: their components and everything those import. `keepExisting` leaves a module that's already there as it is, rather than rendering it again: a component's code never changes, only the names and source maps it's rendered with, which is all an internal re-check needs. `trustExisting` goes further: an existing module's imports aren't followed either (they were written with it), so only what's new is visited; for the `#codebase` shim after a change, which needs modules to import, not their names up to date.
One module exporting a type and a value under one name. TypeScript won't merge two re-exports, but it merges a local declaration with a re-export, so the type is rendered here (under this name, with its type parameters intact) and the value is re-exported beside it. Returns the file name within the cache.
Regenerate `.tcm/codebase/**` so scratch files can `import { x } from "#codebase/ns"`: a file per namespace. With `only`, just those namespaces' files (the ones whose names changed), and only the modules they import that aren't there yet: the rest of the shim, and every module already written, are as they were.
A file's module: its content as the value of its export, as saved (its `{@link}`s as written, so the module is a function of its hash). Text is a string; bytes, a Uint8Array.
Imports as one statement per module (type-only names in one of their own): `import { a, b as c } from "x";`, wrapped when long. Default and namespace imports stay as they are. In order of module.
Order component members so module-init-time references are already initialized. A function called as a member is initialized (`const yieldNow = makePrimitive(…)`) runs its body then: what that uses is needed first too (`makePrimitiveProto`), and so on through the functions it calls. One only read (`const Reference = Service`) isn't run.
Whether a definition is an augmentation (`declare global { … }`): it declares no name of its own, so nothing imports it, and every check in the codebase includes it instead (see `writeShim`).
A component's module: `.tsx` when it uses JSX (TypeScript only parses JSX there), `.ts` otherwise. Its first JSX member's runtime is named in a pragma, so every compiler (tcm's module hook, Vite, the type checker) compiles the elements to the pinned version.
A value as code that makes it again (`new globalThis.Map([[1, "a"]])`), for a pure constant evaluated once: plain data (numbers, strings, bigints, arrays, plain objects, Maps, Sets, Dates, RegExps). Undefined if it can't be made again the same: a function, a class's instance, a frozen object, an object found twice in it or among `others` (what other definitions hold: a copy would be a different object), or more than `most` characters of code.
A member initialized by calling a function of its component comes after what that function uses, which may come after it in the component (Effect's `yieldNow = makePrimitive(…)`, whose body reads `makePrimitiveProto`).