Skip to content

Dependencies ​

Policy ​

  • Zero runtime dependency: dependencies stays empty; the published library has no import of any package (import-x/no-extraneous-dependencies in src/).
  • Every development package is pinned to an exact version (npm install -D --save-exact).
  • Every package has one row below stating why it is needed and why this one rather than an alternative. The test tests/package.test.ts fails when a package of package.json has no row here, or when a row names a package that is not installed.
  • Adding a package: search alternatives (official docs, maintenance date, weekly use, license), check npm audit, add the row in the same change, mention it in the commit (build(deps): …). A package bringing a structural choice also gets an ADR.
  • Removing a package: remove its row.

Packages ​

Language and build ​

PackageWhyAlternatives rejected
typescriptcompiler and type checker; pinned to 6.0 because typescript-eslint requires <6.1 (ADR-0009)TypeScript 7: no typed lint yet
@types/nodeNode.js types for the tooling (ESLint plugin, configuration files)—
vitedevelopment server of the playground and library build (Product Owner requirement, ADR-0009)—
vitesttests, sharing Vite's configuration and transformsJest: separate transform pipeline
@vitest/coverage-v8test coverage of src/, with 100 % thresholds (lines, branches, functions, statements): every behavior of the library is tested@vitest/coverage-istanbul: slower, instruments the code
happy-domDOM implementation for the tests of src/render/ (per-file // @vitest-environment happy-dom), so the shell keeps 100 % coveragejsdom: heavier and slower
fast-checkproperty-based tests of math and geometry (ADR-0022): random inputs, shrunk counterexamples, seeded replay; MIT, one dependency (pure-rand)hand-written random loops: no shrinking, no replay; jsverify: unmaintained
@fast-check/vitesttest.prop for Vitest: properties reported as tests, with the failing seed in the test name (ADR-0022)calling fc.assert inside it: more boilerplate per property

Lint ​

PackageWhyAlternatives rejected
eslintthe linter; every rule decided explicitly (ADR-0010)—
@eslint/jslists the live core rules for the completeness audit (eslint/config.test.ts)deprecated builtinRules API
typescript-eslintTypeScript parser and type-aware rules—
@typescript-eslint/utilstyped helpers to write the custom local/* rulesuntyped Rule.RuleModule
@typescript-eslint/rule-testertests of the custom rules with VitestESLint's untyped RuleTester
jitiloads eslint.config.ts, the method documented by ESLint (REF-ESLINT-TS-CONFIG)experimental native flag
eslint-plugin-jsdocmandatory, well-formed TSDoc—
eslint-plugin-import-xcycles, layer boundaries, import order and resolutioneslint-plugin-import: slower, less maintained; a home-made cycle checker: re-inventing a maintained tool
eslint-plugin-unused-importsremoves unused imports on save (core and typescript-eslint only report)—
eslint-plugin-functionalimmutability and no classes: "a function never modifies its arguments" (ADR-0014)—
eslint-plugin-unicorn~370 modern best-practice ruleseslint-plugin-sonarjs: overlaps unicorn and complexity rules
@stylistic/eslint-pluginblank lines between statements and comment style, which Prettier does not decide—
eslint-config-prettierturns off the ESLint rules that conflict with Prettier (ADR-0013)eslint-plugin-prettier: discouraged by Prettier (REF-PRETTIER-LINTERS)
@eslint/markdownlints the structure of every Markdown page (headings, links, code languages, tables) inside ESLint, with the same "every rule decided" auditmarkdownlint-cli2: depends on braces, vulnerable without fix (GHSA-vfj7-8cjw-p6xm)
prettiercode formatting—

Documentation site ​

PackageWhyAlternatives rejected
vitepressMarkdown documentation site built on Vite (REF-VITEPRESS); 2.0 alpha because 1.6 bundles a vulnerable Vite 5 (ADR-0009)Docusaurus: React and webpack/rspack toolchain, no native PDF either
typedocgenerates the API reference from the TSDoc; supports TypeScript 6.0—
typedoc-plugin-markdownTypeDoc output as Markdown pages (REF-TYPEDOC-MARKDOWN)TypeDoc's HTML site: separate from the docs
typedoc-vitepress-themeVitePress-flavored Markdown and sidebar for the API pages—
mermaiddiagrams written as text in mermaid code blocks (flowcharts, Git graphs, sequences), drawn by the site's theme in the browser and natively by GitHub (REF-MERMAID, REF-GH-DIAGRAMS)vitepress-plugin-mermaid: last release 2024, VitePress 1 only; hand-drawn SVG: hard to keep up to date

Git workflow ​

PackageWhyAlternatives rejected
huskyinstalls the Git hooks (.husky/) on npm installlefthook: equally good, less widespread
lint-stagedruns Prettier, ESLint and secretlint on staged files only, before each commit (.lintstagedrc.json)—
@commitlint/clichecks commit messages—
@commitlint/config-conventionalConventional Commits rule set (REF-CONVENTIONAL-COMMITS)—
@commitlint/typestypes of commitlint.config.ts—
validate-branch-namechecks the branch name before pushinga home-made script

Security ​

PackageWhyAlternatives rejected
secretlintdetects keys, tokens and passwords in any file: before each commit, before each push (check:all) and in the CI into maingitleaks: a Go binary outside npm; GitHub secret scanning also runs, server side
@secretlint/secretlint-rule-preset-recommendsecretlint's recommended rule set (cloud keys, GitHub, Slack, npm tokens, private keys…)—

Maintenance ​

PackageWhyAlternatives rejected
npm-check-updatesnpm run deps:outdated: fails when a dependency is not on its latest versionnpm outdated: no per-package target (TypeScript limited to patches)
knipnpm run deps:unused: unused files, exports and dependencies (knip.json), which lint cannot see across modulests-prune: unused exports only; ESLint no-unused-vars: one module at a time

Overrides ​

Checked at each retrospective: an override goes once the package that pulls the vulnerable version asks for a fixed one. Still needed on 2026-10-13: eslint-plugin-functional 10.0.1 asks for deepmerge-ts ^7.1.5, and micromark-extension-math 3.1.0 (through @eslint/markdown) for katex ^0.16.0.

OverrideWhy
deepmerge-ts → ^8.0.0eslint-plugin-functional pulls a version affected by GHSA-ggr8-5vv4-36mx; 8.x fixes it
katex → ^0.19.0@eslint/markdown pulls a version affected by GHSA-238p-pmpm-9mq7 (math rendering, unused here); 0.19 fixes it

Considered for later ​

Not installed yet; to reconsider when the library grows (Product Owner, 2026-10-08).

PackageWould bringWhen
size-limitsize budget of the published bundlebefore the first npm publication
@microsoft/api-extractorreport of the public API, to detect breaking changes in pull requestsonce the public API stabilizes
@stryker-mutator/coremutation testing: proves the tests catch real changes, not only cover lineswhen stryker-js issue 6210 (Vitest 5 runs no test against mutants) is fixed and released — tried 2026-10-08, ADR-0022