5.5 KiB
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: ESNextallowImportingTsExtensions+rewriteRelativeImportExtensions— source imports each other with explicit.tsextensions, andtscrewrites them to.jsin the emitted outputdeclaration+declarationMap— every module ships.d.ts+.d.ts.mapstrict,isolatedModules,skipLibCheckinclude: ["src/**/*"]only —test/**never reachesdist/. The root-leveloxfmt.config.tsis 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:
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
oxfmtover 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--configflag needed. It reads.gitignoreautomatically. - 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.tsstubsResizeObserver— jsdom doesn't implement it andleaflet-map.tsconstructs 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<img>/<video>behind an overlay, a marker'sdragginghandler,marker.getElement()— these exist only once the layer is added to a real map. Tests touching them append through a<leaflet-map>rather than standalone.test/core/with-props.test.tstests the mixin against a fake Leaflet-like class; the exception is child registration, which needs realPopup/Tooltip/Layerbecause#onChildRegisterbranches oninstanceof.test/load-order.test.ts— see 06; it's the only test reproducing real page load order.test/**is typechecked separately viatsconfig.test.json(extendsthe main config,rootDir: '.',noEmit, addstest/**/*toinclude).
Build output
tsc compiles src/ → dist/ as individual ESM modules — .js +
.d.ts + .d.ts.map per source file, no bundling step.
- Consumers import
dist/index.js(or any single module) directly. - No CJS, no UMD build.
- Leaflet is always external — never bundled. It's a
dependenciesentry and a bareimportin the output. package.jsonexports:.→dist/index.js(+ types), plus./dist/*for deep imports.sideEffects: true— the component modules callcustomElements.define()at import time, so a bundler must not tree-shake them away.
Publishing to two registries
| Registry | Entry | Ships |
|---|---|---|
| npm | package.json main/module/types → dist/… |
compiled dist/ + README.md (files field); prepublishOnly runs build |
| JSR | jsr.json exports → ./src/index.ts |
TypeScript source directly (JSR compiles per-consumer) |
Both are version 0.1.0; keep them in step. JSR publishes src/ with its
.ts import extensions intact, which JSR supports natively.