# 07 — Tooling & build ## Scripts | `npm run …` | Does | | --------------------- | -------------------------------------------------------- | | `build` | `rm -rf dist && tsc --outDir dist` | | `typecheck` | `tsc --noEmit`, then `tsc -p tsconfig.test.json` | | `lint` | `oxlint src test` | | `format` | `oxfmt '*.md' 'src/**/*.{ts,js,json,md}' 'test/**/*.ts'` | | `test` / `test:watch` | `vitest run` / `vitest` | ## TypeScript 7 `package.json` pins `typescript@^7.0.2`. This choice constrains the lint setup below. `tsconfig.json` highlights: - `module: ESNext`, `moduleResolution: bundler`, `target: ESNext` - `allowImportingTsExtensions` + `rewriteRelativeImportExtensions` — source imports each other with explicit `.ts` extensions, and `tsc` rewrites them to `.js` in the emitted output - `declaration` + `declarationMap` — every module ships `.d.ts` + `.d.ts.map` - `strict`, `isolatedModules`, `skipLibCheck` - `include: ["src/**/*"]` only — `test/**` never reaches `dist/`. The root-level `oxfmt.config.ts` is outside this glob too, so it's never compiled. ## Linting: oxlint (not ESLint) `oxlint.config.ts` — `oxlint@^1`, configured with `defineConfig`: `plugins: ['typescript', 'unicorn', 'oxc']`, `categories` correctness→error / suspicious+pedantic→warn, `max-lines*` and (in `test/`) `max-classes-per-file` turned off. **Why not `@typescript-eslint`:** it has no released version supporting TypeScript 7 — its peer range caps at `<6.1.0`, and even loading `@typescript-eslint/parser` crashes against TS 7's package shape. `oxlint` has its own parser and never touches the `typescript` package, so it works regardless of TS version. **The tradeoff:** no type-aware rules — no `no-floating-promises`, no `no-unnecessary-condition`, etc. Worth revisiting once `@typescript-eslint` supports TS 7. ## Formatting: oxfmt `oxfmt.config.ts` — `oxfmt` (the oxc project's formatter), configured with its `defineConfig` default export: ```ts export default defineConfig({ semi: true, singleQuote: true, trailingComma: 'all', printWidth: 100, tabWidth: 2, }); ``` - Same toolchain family as `oxlint`; single native binary, no plugin ecosystem to pin against TS 7. - Prettier-compatible options; the values above are Prettier's popular defaults, so running `oxfmt` over the existing tree is a near no-op. - oxfmt auto-discovers `oxfmt.config.ts` (search order: `.oxfmtrc.json` → `.oxfmtrc.jsonc` → `oxfmt.config.ts` → `oxfmt.config.mts`); no `--config` flag needed. It reads `.gitignore` automatically. - One behavioural difference from Prettier: oxfmt formats fenced code blocks _inside_ Markdown. - Pre-1.0 — expect its output to shift between releases. ## Testing: Vitest + jsdom `vitest.config.ts` — `environment: 'jsdom'`, `include: test/**/*.test.ts`, `setupFiles: ['./test/setup.ts']`. - **`test/setup.ts`** stubs `ResizeObserver` — jsdom doesn't implement it and `leaflet-map.ts` constructs one unconditionally, so without the stub even _importing_ the component throws. Nothing here depends on it firing. - **Real Leaflet objects work under jsdom** for everything this library verifies: option/attribute wiring, event forwarding, child binding. No browser needed. - **`onAdd()`-only state:** the ``/`