tcmts.cli.mirror

Types

Decl type
A top-level declaration in a file: where its code is, where its doc comment is, whether it's exported.
Edit type
Mirror type
MirrorFile type
Move type
A definition moved from one mirrored file's namespace to another's (as `as` there, if renamed too).
ReleaseRecord type
A release as the mirror keeps it.
Spelling typeof Spelling
How a file spells what its definitions refer to, learned from the definitions already in it: `ts.parse` through a namespace import, `parse` through a named one, `fs` for a default import. A target nothing there refers to yet is spelled like a sibling from the same module (`ts.` again), or gets an import.

Server

assetFiles (dir: string, exclude: Set<string>, marked?: { at: string; skip: string[]; } | undefined) => string…
The files under a mirrored directory that aren't code (Markdown, CSS, images, configuration, scripts): files of the codebase. In a git repository, only what git keeps (not what it ignores).
assetFormat (file: string) => string
A file's format as a file of the codebase: its extension (any, in a directory marked as holding files; none for `Dockerfile`), after a dot for a hidden file (`.gitignore` is ".", `.mcp.json` ".json").
assetName (root: string, into: string, file: string) => string
A file's name in a mirror's codebase: its directory's namespace (as for code), and its own name.
assetsUnder (dir: string, exclude: Set<string>, marked?: { at: string; skip: string[]; } | undefined) => string…
changedFiles (m: Mirror) => string[]
The mirror's files changed since tcm last wrote or read them (by hand, or by git: a pull, a checkout), or added or removed.
checkMirror (cb: CodebaseCore, m: Mirror, keepText?: boolean) => string[]
What doesn't match between the mirror's files and the codebase, re-analyzing the files as `import` does. With `keepText`, when they match, the codebase keeps each definition's code as the files spell it, so the next write spells references the way the files do (not as the scratch file it was edited in did).
codeFor (rec: DefRecord, leaf: string, spelling: Spelling, exported: boolean) => string
A definition's code as it reads in its mirror file.
declarations (file: string, text: string) => Map<string, Decl>
exportsFrom (entry: string, file: string, leaf: string, seen: Set<string>) => boolean
Whether module `entry` exports `leaf` from `file`, under that name: it is the file, or re-exports it (`export * from`, `export { leaf } from`).
fileFor (m: Mirror, ns: string, jsx: boolean) => string | undefined
Where a new namespace's file goes in a mirror: next to a sibling namespace's file, in a parent's directory (or an index.ts for a namespace with children), or by the namespace's path from the root. Only a path the mirror reads back as that namespace, and that doesn't exist yet.
followFileRename (files: string[], mirrored: Set<string>, from: string, to: string) => Map<string, string>
Imports and re-exports of the file `from`, renamed `to` (`site.ts` to `site.tsx`), pointed at its new name. Returns the text of the files outside `mirrored` it changed, as they were.
followMoves (files: string[], mirrored: Set<string>, moves: Move[], problems: string[]) => Map<string, string>
Imports and re-exports of moved definitions, pointed at the files they're in now: `{ x }` from the old file becomes an import from the new one (`{ y as x }` if renamed too, so the code using it reads the same), the new file stops importing it, and the old file imports it if its other code still uses it. A namespace import (`a.x`) can't follow: that's a problem. Returns the text of the files outside `mirrored` it changed, as they were.
git (dir: string, ...args: string[]) => string | undefined
gitKept (dir: string) => Set<string> | undefined
The files git keeps under `dir` (tracked, or new and not ignored), as absolute paths: undefined outside a repository.
importedNames (file: string, text: string) => string[]
The names a file's imports bind.
importsAt (file: string, text: string) => number
Where new imports go: after the file's last import, or at its top.
isAsset (file: string, root?: string) => boolean
Whether a mirror keeps a file as a file of the codebase: anything but code (TypeScript), configuration and scripts included.
linkMirror (cb: Codebase, dir: string, into: string, tests: boolean, exclude: string[], following?: { log: num…
Record that `into` mirrors `dir`: each file's namespace, content and definitions as they are now. Following the files, it records what they hold (`held`, by path) as of the log they were last written at, so what the codebase changed meanwhile is written to them at the next sync.
linkPackages (root: string, dir: string, top: string) => void
Let code taken from git (into `root`, a copy of the mirror `dir`) resolve its packages as it did: a workspace package (a directory with a package.json naming it) to its copy here, anything else to what's installed now. Each package gets a node_modules like its counterpart's in `dir` (pnpm installs dependencies per package), with the workspace's own packages pointing at the copies.
namespaceForFile (root: string, file: string) => string
`core/src/analyze.ts` → `core.analyze`, `store/src/index.ts` → `store`
nearbyFiles (m: Mirror, names: string[]) => string[]
TypeScript files near a mirror that aren't in it and mention any of `names`: the rest of its git repository (or its parent directory), leaving out installed packages, build output, hidden directories and codebases.
packageDirOf (file: string) => string | undefined
The directory of the package a file is in: the nearest with a package.json.
pruneImports (file: string, before: string, after: string) => string
Drop the imports an edit stopped using: names `after` binds and doesn't mention that `before` did. Imports that were already unused are left as they are (the file's author's business); an import with nothing left goes.
recordRelease (m: Mirror, r: Omit<ReleaseRecord, "dir">) => void
Add a release to the mirror's records (for git: commit them with the next change).
releaseCommit (m: Mirror) => string | undefined
The commit a release of a mirrored codebase is made from: the mirror's files must all be committed, so the release can be made again from git. Undefined when the mirror isn't in a git repository.
releaseRecords (dir: string) => ReleaseRecord[]
renameEverywhere (cb: CodebaseCore, m: Mirror, renames: { rel: string; from: string; to: string; }[]) => Map<string,…
Rename definitions at every reference in the mirror's files, as an editor's rename would.
replayReleases (cb: Codebase, dir: string, importAt: (root: string, label: string) => boolean, namespaceOf: (pkg: …
Make a mirror's recorded releases again, in a codebase that doesn't have them: for each, in order, its commit's files are imported (`importAt`) and the release is put at the history entry that makes. The files are taken from git into a directory inside the repository, so packages resolve as they did, and workspace packages (`@tcm/core`, say) are linked to their copies there rather than to today's.
sha (text: string) => string
sourceFiles (dir: string, exclude: Set<string>, tests: boolean) => string[]
specifierFor (from: string, to: string, leaf: string) => string
How a file imports `leaf` from the project's file `to`: by path, or from another package (the nearest package.json isn't the same, and it's a dependency) by that package's name, when an entry of its `exports` exports it (re-exporting it through barrels counts).
syncMirror (cb: CodebaseCore) => boolean
Bring the mirror's files up to date with the codebase, if this codebase has one and its names changed. Returns whether the files now match.
unusedImports (file: string, text: string) => Set<string>
The names a file's imports bind that nothing else in it mentions.
valueImports (file: string, text: string, names: Set<string>) => string
`text` with its type-only imports of `names` made value imports, for code that now uses them as values: `import type { Placement }` becomes `import { Placement }`, and one of several names moves to an import of its own.

Shared

FILES_MARK ".tcm-files"
A directory with this file in it holds files of the codebase, kept as written, not code (in a mirror).
KEY "mirror"
NEVER Set<string>
Files and directories that are never the codebase's: version control, codebases, Finder's, and the mirror's record of releases (a copy of what the codebase has, for git).
RECORDS "tcm-releases.json"
SKIP_DIRS Set<string>
TEST_DIRS Set<string>
With `--tests`: directories of tests written as definitions (`test…`), imported like the code they test.
applyEdits (text: string, edits: Edit[]) => string
docComment (doc: string) => string
extKey (e: ExtRef) => string
findDeclarationName (sf: SourceFile, name: string) => Identifier | undefined
joinName (...parts: string[]) => string
loadMirror (cb: CodebaseCore) => Mirror | undefined
mentions (sf: SourceFile, name: string) => boolean
Whether a file's code (not its imports) uses a name.
namesIn (cb: CodebaseCore, ns: string) => Record<string, string>
The definitions named directly in a namespace (not in namespaces under it): name → hash.
onMirrorBranch (cb: CodebaseCore, m: Mirror) => boolean
Whether this process works on the branch a mirror's files are (a session on another doesn't touch them).
saveMirror (cb: CodebaseCore, m: Mirror) => void
specifierOf (ext: ExtRef) => string
How a module is imported, for an import tcm adds: `node:fs`, `react/jsx-runtime`, `#tcm/host`.
terminated (code: string, semicolon: boolean) => string
Stored code leaves out a declaration's `;`: put it back where the file (or a variable declaration) has one.
unlinkMirror (cb: Codebase) => void
untextual (cb: CodebaseCore, log: number) => Set<string>
Changes to the name log since `log` that leave code's text as it was: dependents re-hashed, packages upgraded.

Tests

testValueImports () => void
A type-only import of what code now uses as a value becomes a value import: the whole of it, one specifier of several, or an inline `type`.