9dd973a9506ebc7072bb29f64bea8773e56eae94
pubv resolves the default branch from the local refs/remotes/origin/HEAD, which git fetch never updates, so a clone or default-branch change left it stale and pubv warned that main was not the default. Refresh it from the remote before pubv runs, and assert releases are cut from main explicitly.
tiny-pattern-ts
Pattern matching for TypeScript/ESM environments (F#-style, not regex).
Development
- Build:
npm run build - Test:
npm run test,npm run test:ci - Watch:
npm run watch - Checks:
npm run check,npm run fix - Verify:
npm run verify— the definition of done - Maintenance:
npm run maintain— advisory only - Individual fixes:
npm run fix:oxfmt,npm run fix:oxlint
What each tier runs, when it fires and what it costs:
CONTRIBUTING.md § Feedback tiers. How the
prefix: in a script name is chosen:
§ Script prefix convention.
Tooling
- TypeScript 7 — type checker and build (
tsc). - node --test +
--strip-types— test runner. - c8 — code coverage for
test:ci. - oxlint — Rust-based linter, with type-aware rules powered by oxlint-tsgolint (typescript-go).
- oxfmt — Rust-based formatter (Prettier-compatible). Formats JS/TS, JSON/JSONC, YAML, Markdown, MDX, and more; built-in
package.jsonkey sorting replacessort-package-json. - cspell — spell checking.
- knip — finds unused dependencies, exports, and files.
- check-outdated — reports dependencies behind the registry; it exits non-zero whenever any dependency is outdated.
- publint — validates
package.jsonfor ESM publishing correctness. - @arethetypeswrong/cli (
attw) — validates.d.tsdeclarations against multiple module-resolution scenarios. - lefthook — git hooks.
- @spences10/pi-lsp — read-only LSP code intelligence for AI coding agents (project-local
.pi/settings.json). Talks to this repo's TypeScript 7 viatsc --lsp --stdio.
Each tool's configuration trade-off is recorded in Tooling decisions; when it runs is in CONTRIBUTING.md § Feedback tiers.
Tooling decisions
The choice and configuration of each tool above is the result of deliberate trade-offs, not defaults. The non-obvious ones:
tsconfig.jsonextends@tsconfig/strictest+@tsconfig/node26;tsconfig.build.jsonextends it to add the emit-only options (declaration,sourceMap,inlineSources,outDir,target: es2024,rewriteRelativeImportExtensions: true) and to exclude test files.inlineSourcesembeds the original TypeScript indist/*.js.map, so debuggers can map intosrc/without it being shipped;declarationMapis intentionally off because a.d.ts.mapcannot embed source and would dangle. This separation lets the editor and CI type-check from one config while the build emits from the other.npm run buildfirst runs aprebuildhook that emptiesdist/.tscdoes not prune orphaned emit output — droppingdeclarationMap, for example, left stale*.d.ts.mapfiles behind — so the build must start from an emptydist/to be reproducible.prebuildremoves onlydist; the manualcleanstill resetsdist+coverage, so a local coverage report survives a build.- Source imports use
.tsextensions sonode --strip-typesresolves them at test time.rewriteRelativeImportExtensions: trueintsconfig.build.jsonrewrites them to.jsin the emitted JavaScript; the emitted.d.tskeep the.tsspecifier, which TypeScript >= 5.0 resolves (see Requirements), so no post-processing step is needed. - Type-aware oxlint is enabled declaratively via
options.typeAware: truein.oxlintrc.json(powered byoxlint-tsgolint). The script commands stay clean — no CLI flag — and type-aware mode is a property of the config, not the invocation. - Source-level
oxlint-disabledirectives are used for known type-aware false positives (seesrc/pattern.ts,src/match.ts,src/index.test.ts). The disable lives next to the code it silences, not in.oxlintrc.json, so the trade-off is visible to anyone reading the source. knip --include dependencies,exports,filesintentionally omits thetypescategory, which produces systematic false positives for libraries whose exported types are part of the public API. The targeted scope keeps the signal high without config-file boilerplate.attw --profile esm-onlyis semantically correct: this package is intentionally ESM-only (no CommonJS shim), so CJS resolution scenarios are out of scope by design, not a bug.check:tscruns first in thenpm run checkchain so a type error short-circuits the rest (faster feedback than letting oxlint/oxfmt run and then failing on tsc at the end).- The pre-commit hook sets the
LEFTHOOK_FILESenv var to the staged-files list, and the affected scripts use${LEFTHOOK_FILES:-<default>}to default to the whole project when invoked manually. This keepspackage.json#scriptsas the single source of truth for the underlying commands —lefthook.ymlonly describes what to run on which files. tslibandtype-festare deliberately not used.tslibis a runtime helper for old ES3/ES5 targets (the project targets ES2024);type-festwas never imported. knip caught both.@spences10/pi-lspis pinned to0.0.46and is read-only by design. The package inspectsnode_modules/typescript, sees major ≥ 7 with nolib/tsserver.js(true of thetypescript-go/tsgoport), and spawns the repo's owntsc --lsp --stdiobinary — notypescript-language-serverdependency is required. Earlier releases (≤ 0.0.10) hard-wire totypescript-language-server --stdioand are TS6-only. The tool is intermediate agent feedback (hover, references, definition, symbols, diagnostics); it has no rename / code-action / apply-edit surface, and never a correctness gate —npm run check/verifyremain that..pi/settings.jsonis the shared, committed declaration;.pi/npm/is a gitignored install cache that pi recreates automatically on a trusted startup (it runsnpm installfor any missing project package), so the cache is deliberately not tracked.
Requirements
- Node.js >= 26 (engines field; pinned via
.node-version). - TypeScript >= 5.0 to consume the published declarations. The emitted
.d.tsuseconsttype parameters (TS 5.0) and keep their relative.tsspecifiers; both resolve on TS >= 5.0 innode10/node16/nodenext/bundler.
VSCode integration
- Recommended extensions: see
.vscode/extensions.json(oxc, cspell, TypeScript native-preview, EditorConfig, todo-tasks). - TypeScript 7 is used via the
typescriptteam.native-previewextension. - oxc extension provides oxlint squiggles and oxfmt format-on-save;
.vscode/settings.jsonpins it per language so a user's local[language]formatter settings cannot override the project's choice.
Contributing
For maintainer and contributor docs — the script prefix convention, the feedback-tier system, the rules the tools don't enforce, and the publishing workflow — see CONTRIBUTING.md. AI coding agents: your entry point is AGENTS.md, which points back to CONTRIBUTING.md.
- Commit signing (GPG).
- Type-only tests use
expect-type'sexpectTypeOf(...)insidenode --testcases.