The presets
This guide shows you the shared configs a workspace extends for TypeScript, oxlint, oxfmt and TypeDoc, what each one sets, and where each goes.
Compile with the TypeScript configs
@wtf/project-typescript has four configs. Each is a JSON file that tsc reads as it is:
| Subpath | What it sets |
|---|---|
./base | ESNext on NodeNext, strict, with source maps, declarations and @wtf/source |
./strict | ./base plus noUncheckedIndexedAccess and exactOptionalPropertyTypes, with no ambient types: use it for a library |
./test | What tests add on top of the project’s own config: no emit, no references, Node’s types, and JSON |
./bundler | What code compiled by a bundler adds: Bundler resolution, React’s JSX and the DOM |
./base sets customConditions: ["@wtf/source"], so a package in the workspace resolves to the
other packages’ TypeScript source, not to a stale build. SOURCE_CONDITION of
@wtf/project-resolve/condition names the same condition for code, as the Vite and Vitest configs
use it. verbatimModuleSyntax and
erasableSyntaxOnly keep the source runnable by Node, which only strips the types. tsc keeps the
comments in what it emits, so a published .d.ts carries its JSDoc.
./test and ./bundler extend nothing, so list each one after the config it adds to:
{ "extends": ["./tsconfig.json", "@wtf/project-typescript/test"], "compilerOptions": { "rootDir": ".", "tsBuildInfoFile": "node_modules/.tmp/tsconfig.test.tsbuildinfo" }, "include": ["src", "test"]}A test config references no project and emits nothing. It reads each workspace package from its
source through @wtf/source, so pnpm run typecheck (tsc -b tsconfig.test.json) builds no
package and writes no dist. The build checks each package with that package’s own config. A test
config names its tsBuildInfoFile in node_modules/.tmp; otherwise the build info would land in
the dist folder that outDir names.
Lint and format with oxlint and oxfmt
@wtf/project-oxlint/config turns on the typescript, unicorn and import plugins. Correctness
rules are errors, suspicious and perf rules are warnings, and import/no-cycle, eqeqeq and
typescript/no-explicit-any are errors. Run oxlint with --deny-warnings, so a warning fails the
lint just as an error does.
@wtf/project-oxfmt/config formats at 100 columns, with single quotes, no semicolons and no
trailing commas. It leaves the build, the lockfile, the changelog and the generated reference
alone.
You can add rules of your own on top of the preset:
import preset from '@wtf/project-oxlint/config'import { defineConfig } from 'oxlint'
export default defineConfig({ extends: [preset], rules: { 'no-console': 'error' } })Build the reference with TypeDoc
typedocConfig() of @wtf/project-typedoc/config is the config for a docs package,
packages/docs. It writes the reference of the workspace’s packages as markdown in api/, with an
llms.txt built from the package’s llms-template.md. Each source links to its file in your
repository, and any warning fails the build.
import { typedocConfig } from '@wtf/project-typedoc/config'
export default typedocConfig({ docs: import.meta.url, repository: 'https://gitlab.com/wetryfun/project/project', entryPoints: ['../core', '../cli']})The revision each source links to is the first of these that applies:
--gitRevision <ref>, passed totypedoc;- the commit of HEAD;
- in a repo with no commit yet, its branch; outside git,
main.
./plugins holds the plugins the preset gives TypeDoc: cleanGeneratedMarkdown,
preventMediaFiles and linkTrackedSources. Add your own in plugins, each a function of
TypeDoc’s application or a module by its name: they run after the preset’s, and before
typedoc-plugin-llms-txt and typedoc-plugin-markdown. TypeDoc and its two plugins are peers.
import { typedocConfig } from '@wtf/project-typedoc/config'import type { TypedocPlugin } from '@wtf/project-typedoc/plugins'
/** A plugin of your own, which TypeDoc calls with its application, once. */const notice: TypedocPlugin = (app) => { app.renderer.on('endRender', () => console.log('The reference is written.'))}
export default typedocConfig({ docs: import.meta.url, repository: 'https://gitlab.com/wetryfun/project/project', entryPoints: ['../core'], plugins: [notice]})