chore: fix packaging anti-patterns before 0.1.0 publish

- leaflet moves from `dependencies` to `peerDependencies` (^1.9.4), kept in
  `devDependencies` for local dev/tests. The nesting protocol dispatches on
  `instanceof` against Leaflet's own Layer/Popup/Tooltip, so a second copy
  pulled in transitively would silently break child registration.
- `@types/leaflet` (and its `@types/geojson` dep, imported directly by
  leaflet-geojson's emitted .d.ts) move to `dependencies` — the published
  declarations reference them and `leaflet` ships no types of its own, so a
  TS consumer had a broken type surface with nothing signalling why.
- Drop the `exports["./dist/*"]` wildcard: it exposed the whole internal
  tree (`core/*`, explicitly "not a stable contract") as importable,
  semver-relevant surface. Root + `./elements` + `./components/*.js` cover
  every intended entry.
- `prepublishOnly` now runs `typecheck` + `test` + `build`, not just `build`.

Verified against a packed tarball: a fresh consumer with only the declared
deps present typechecks clean under `moduleResolution` bundler and nodenext.
CLAUDE.md / docs / README updated to match.
main
Buddy 2 weeks ago
parent b7f7a43113
commit c03eb77d5b

@ -119,7 +119,7 @@ Two registries, different entry files (both pinned to the same version — keep
| Registry | Package name | Entry | Ships | | Registry | Package name | Entry | Ships |
| -------- | --------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | -------- | --------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| npm | `leaflet-web-components` | `package.json` `.`/`main`/`module`/`types` → `dist/index.npm.*` | compiled `dist/` + `README.md` + `LICENSE` (`files` field); `prepublishOnly` runs `build` | | npm | `leaflet-web-components` | `package.json` `.`/`main`/`module`/`types` → `dist/index.npm.*` | compiled `dist/` + `README.md` + `LICENSE` (`files` field); `prepublishOnly` runs `typecheck` + `test` + `build` |
| JSR | `@buddy/leaflet-components` | `jsr.json` `exports``./src/index.ts` (+ `./elements`) | TypeScript source directly, minus `jsr.json`'s `publish.exclude` (which drops `src/index.npm.ts`, `src/core/globals.ts`, `test/`, `docs/`, `dist/`, configs) | | JSR | `@buddy/leaflet-components` | `jsr.json` `exports``./src/index.ts` (+ `./elements`) | TypeScript source directly, minus `jsr.json`'s `publish.exclude` (which drops `src/index.npm.ts`, `src/core/globals.ts`, `test/`, `docs/`, `dist/`, configs) |
The npm entry (`src/index.npm.ts`) adds the `declare global` augmentations via `src/core/globals.ts`; the JSR entry (`src/index.ts`) can't, because JSR's "no slow types" check forbids `declare global` in its published graph. That constraint is also why every element file uses the explicitly-typed `const PROPS` / `const Base` shape (see the `WithProps` section). `npx jsr publish --dry-run` is the authoritative check; it must print "Success" with no slow-type errors. The npm entry (`src/index.npm.ts`) adds the `declare global` augmentations via `src/core/globals.ts`; the JSR entry (`src/index.ts`) can't, because JSR's "no slow types" check forbids `declare global` in its published graph. That constraint is also why every element file uses the explicitly-typed `const PROPS` / `const Base` shape (see the `WithProps` section). `npx jsr publish --dry-run` is the authoritative check; it must print "Success" with no slow-type errors.

@ -8,7 +8,12 @@
npm install leaflet-web-components leaflet npm install leaflet-web-components leaflet
``` ```
Also published to JSR as [`@buddy/leaflet-components`](https://jsr.io/@buddy/leaflet-components) (`deno add jsr:@buddy/leaflet-components`). `leaflet` is always a peer dependency you install yourself; there is no CommonJS or UMD build. The examples below use the npm name — substitute `@buddy/leaflet-components` if you pull from JSR. `leaflet` is a **peer dependency** — you install it, and only one copy must be
present (the nesting protocol relies on `instanceof` against Leaflet's own
classes). The Leaflet type definitions (`@types/leaflet`, `@types/geojson`)
ship as regular dependencies, so TypeScript consumers need nothing extra.
Also published to JSR as [`@buddy/leaflet-components`](https://jsr.io/@buddy/leaflet-components) (`deno add jsr:@buddy/leaflet-components`). There is no CommonJS or UMD build. The examples below use the npm name — substitute `@buddy/leaflet-components` if you pull from JSR.
## Import options ## Import options

@ -109,13 +109,20 @@ export default defineConfig({
`src/index.ts` on JSR — see "Publishing" below) or any single module `src/index.ts` on JSR — see "Publishing" below) or any single module
directly. directly.
- **No CJS, no UMD** build. - **No CJS, no UMD** build.
- **Leaflet is always external** — never bundled. It's a `dependencies` entry - **Leaflet is always external** — never bundled, a bare `import` in the
and a bare `import` in the output. output. It's a **`peerDependency`** (`^1.9.4`), not a regular dependency:
the nesting protocol keys off `instanceof` against Leaflet's own `Layer` /
`Popup` / `Tooltip`, so a second copy under our own `node_modules` would
silently break it. Kept in `devDependencies` too, for local dev and tests.
The Leaflet **type** packages (`@types/leaflet`, `@types/geojson`) are
regular `dependencies` — the emitted `.d.ts` reference them directly, and
`leaflet` ships no types of its own.
- `package.json` `exports`: `.``dist/index.npm.js` (+ types — this is the - `package.json` `exports`: `.``dist/index.npm.js` (+ types — this is the
npm entry, `src/index.npm.ts` compiled; see below); npm entry, `src/index.npm.ts` compiled; see below);
`./elements``dist/elements/index.js` (the class barrel, no `define`); `./elements``dist/elements/index.js` (the class barrel, no `define`);
`./elements/*.js` and `./components/*.js` → the matching `dist/` module; `./elements/*.js` and `./components/*.js` → the matching `dist/` module.
`./dist/*` still there for deep imports. There is deliberately **no `./dist/*`** wildcard — `core/*` is not a stable
contract, and the root export already surfaces the toolkit.
- `sideEffects: true` — the `components/*` modules (and both `index*.js` - `sideEffects: true` — the `components/*` modules (and both `index*.js`
entries) call `customElements.define()` at import time, so a bundler must entries) call `customElements.define()` at import time, so a bundler must
not tree-shake them away. The `elements/*` modules have no side effect. not tree-shake them away. The `elements/*` modules have no side effect.
@ -123,8 +130,8 @@ export default defineConfig({
## Publishing to two registries ## Publishing to two registries
| Registry | Package name | Entry | Ships | | Registry | Package name | Entry | Ships |
| -------- | --------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | -------- | --------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| npm | `leaflet-web-components` | `package.json` `.`/`main`/`module`/`types` → `dist/index.npm.*` | compiled `dist/` + `README.md` + `LICENSE` (`files` field); `prepublishOnly` runs `build` | | npm | `leaflet-web-components` | `package.json` `.`/`main`/`module`/`types` → `dist/index.npm.*` | compiled `dist/` + `README.md` + `LICENSE` (`files` field); `prepublishOnly` runs `typecheck` + `test` + `build` |
| JSR | `@buddy/leaflet-components` | `jsr.json` `exports``./src/index.ts` (+ `./elements`) | TypeScript source directly (JSR compiles per-consumer), minus `jsr.json`'s `publish.exclude` | | JSR | `@buddy/leaflet-components` | `jsr.json` `exports``./src/index.ts` (+ `./elements`) | TypeScript source directly (JSR compiles per-consumer), minus `jsr.json`'s `publish.exclude` |
Both are pinned to the same version; keep them in step. JSR publishes `src/` Both are pinned to the same version; keep them in step. JSR publishes `src/`

15
package-lock.json generated

@ -1,23 +1,27 @@
{ {
"name": "leaflet-components", "name": "leaflet-web-components",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "leaflet-components", "name": "leaflet-web-components",
"version": "0.1.0", "version": "0.1.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"leaflet": "^1.9.4" "@types/geojson": "^7946.0.16",
"@types/leaflet": "^1.9.21"
}, },
"devDependencies": { "devDependencies": {
"@types/leaflet": "^1.9.21",
"jsdom": "^30.0.1", "jsdom": "^30.0.1",
"leaflet": "^1.9.4",
"oxfmt": "^0.66.0", "oxfmt": "^0.66.0",
"oxlint": "^1.79.0", "oxlint": "^1.79.0",
"typescript": "^7.0.2", "typescript": "^7.0.2",
"vitest": "^4.1.11" "vitest": "^4.1.11"
},
"peerDependencies": {
"leaflet": "^1.9.4"
} }
}, },
"node_modules/@asamuzakjp/css-color": { "node_modules/@asamuzakjp/css-color": {
@ -1251,14 +1255,12 @@
"version": "7946.0.16", "version": "7946.0.16",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/leaflet": { "node_modules/@types/leaflet": {
"version": "1.9.22", "version": "1.9.22",
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.22.tgz", "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.22.tgz",
"integrity": "sha512-h3lhECYEKDasG7LFHu+GiHqAvsgLuQvlJvVZzJDGONo3sEL+wUOqSFLnwkZlK0qVxnxbuGFW8iBlJNYs5wgndA==", "integrity": "sha512-h3lhECYEKDasG7LFHu+GiHqAvsgLuQvlJvVZzJDGONo3sEL+wUOqSFLnwkZlK0qVxnxbuGFW8iBlJNYs5wgndA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/geojson": "*" "@types/geojson": "*"
@ -1952,6 +1954,7 @@
"version": "1.9.4", "version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
"dev": true,
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/lightningcss": { "node_modules/lightningcss": {

@ -22,7 +22,6 @@
"types": "./dist/components/*.d.ts", "types": "./dist/components/*.d.ts",
"import": "./dist/components/*.js" "import": "./dist/components/*.js"
}, },
"./dist/*": "./dist/*",
"./package.json": "./package.json" "./package.json": "./package.json"
}, },
"sideEffects": true, "sideEffects": true,
@ -38,7 +37,7 @@
"format": "oxfmt '*.md' 'docs/**/*.md' 'src/**/*.{ts,js,json,md}' 'test/**/*.ts'", "format": "oxfmt '*.md' 'docs/**/*.md' 'src/**/*.{ts,js,json,md}' 'test/**/*.ts'",
"test": "vitest run", "test": "vitest run",
"test:watch": "vitest", "test:watch": "vitest",
"prepublishOnly": "npm run build" "prepublishOnly": "npm run typecheck && npm run test && npm run build"
}, },
"keywords": [ "keywords": [
"leaflet", "leaflet",
@ -49,11 +48,15 @@
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@types/geojson": "^7946.0.16",
"@types/leaflet": "^1.9.21"
},
"peerDependencies": {
"leaflet": "^1.9.4" "leaflet": "^1.9.4"
}, },
"devDependencies": { "devDependencies": {
"@types/leaflet": "^1.9.21",
"jsdom": "^30.0.1", "jsdom": "^30.0.1",
"leaflet": "^1.9.4",
"oxfmt": "^0.66.0", "oxfmt": "^0.66.0",
"oxlint": "^1.79.0", "oxlint": "^1.79.0",
"typescript": "^7.0.2", "typescript": "^7.0.2",

Loading…
Cancel
Save