Skip to content

Commit e0094fc

Browse files
committed
docs(playbook): map exports via '.' and add tsconfig symlink step
- Use explicit . export with types/import (+default) for compatibility - Replace tsconfig JSON example with symlink to .config/tsconfig.plugin.json - Update verify jq path and add symlink check - Clarify package.json files note and prefer .npmignore for maps
1 parent 60d4d79 commit e0094fc

File tree

1 file changed

+46
-20
lines changed

1 file changed

+46
-20
lines changed

.charlie/playbooks/upgrade-plugin-to-esm-only.md

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,43 @@ Upgrade a single plugin under `packages/<name>` to publish ESM-only output with
1111
## Steps
1212

1313
1. Identify the target package
14+
1415
- Set a shell variable for reuse: `PKG=packages/<name>`.
1516

1617
2. Package metadata: ESM-only and minimums
18+
1719
- Edit `$PKG/package.json`:
20+
1821
- Set `"type": "module"`.
19-
- Replace legacy `main/module/exports.require` with ESM-only exports:
22+
- Replace legacy `main/module/exports.require` with an ESM-only export mapped via the explicit `"."` entry for broad tooling compatibility:
2023
```json
21-
"exports": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
22-
"types": "./dist/index.d.ts"
24+
{
25+
"exports": {
26+
".": {
27+
"types": "./dist/index.d.ts",
28+
"import": "./dist/index.js",
29+
"default": "./dist/index.js"
30+
}
31+
},
32+
"types": "./dist/index.d.ts"
33+
}
2334
```
2435
- Set minimums: `"engines": { "node": ">=20.19.0" }` and `"peerDependencies": { "rollup": ">=4.0.0" }`.
2536
- Keep `rollup` as a devDependency only if tests use it. Otherwise remove it.
26-
- Ensure published files include dist but exclude maps:
37+
- Ensure published files include build output and standard docs:
2738
```json
28-
"files": ["dist", "!dist/**/*.map", "README.md", "LICENSE"]
39+
"files": ["dist", "README.md", "LICENSE"]
2940
```
41+
Note: `package.json` `files` does not support negation patterns. To exclude maps from the published package, add an `.npmignore` entry:
42+
43+
```
44+
dist/**/*.map
45+
```
46+
47+
If you must disable map emission, either update the shared `.config/tsconfig.plugin.json` (affects all packages) or create a package-local `tsconfig.build.json` that extends it with `"sourceMap": false` and `"declarationMap": false`, then change the build script to `tsc --project tsconfig.build.json`.
3048

3149
3. Build scripts: TypeScript emit to dist
50+
3251
- Prefer a tsc-only build for packages that do not need bundling:
3352
- In `$PKG/package.json`, set scripts:
3453
```json
@@ -40,30 +59,33 @@ Upgrade a single plugin under `packages/<name>` to publish ESM-only output with
4059
```
4160
- If this package still needs bundling for tests/examples, keep its Rollup config but point inputs at the TypeScript output in `dist/` instead of sources.
4261

43-
4. TypeScript config: emit ESM to `dist/`
44-
- Create or update `$PKG/tsconfig.json` to extend the shared plugin config and emit declarations:
45-
```json
46-
{
47-
"extends": "../../.config/tsconfig.base.json",
48-
"compilerOptions": {
49-
"noEmit": false,
50-
"outDir": "dist",
51-
"rootDir": "src",
52-
"declaration": true,
53-
"declarationMap": true
54-
},
55-
"include": ["src/**/*"]
56-
}
62+
4. TypeScript config: use the shared plugin config (symlink)
63+
64+
- Replace any existing `$PKG/tsconfig.json` with a symlink to the shared plugin config (`.config/tsconfig.plugin.json`), which already enables emit to `dist/` and declaration maps:
65+
```bash
66+
# from repo root
67+
ln -snf ../../.config/tsconfig.plugin.json "$PKG/tsconfig.json"
68+
git add "$PKG/tsconfig.json"
5769
```
70+
On Windows PowerShell, you can run:
71+
```powershell
72+
# from repo root
73+
$pkg = 'packages/<name>'
74+
New-Item -ItemType SymbolicLink -Path "$pkg/tsconfig.json" -Target (Resolve-Path ".config/tsconfig.plugin.json") -Force
75+
git add "$pkg/tsconfig.json"
76+
```
77+
The shared config content lives at `.config/tsconfig.plugin.json`.
5878
- Delete any package-local `rollup` build scripts that produced CJS, and remove any `types/` folder if declarations were hand-authored (they will now be generated).
5979

6080
5. Source: convert to pure ESM and modern Node APIs
81+
6182
- Replace `require`, `module.exports`, and `__dirname` patterns with ESM equivalents.
6283
- Use `node:` specifiers for built-ins (e.g., `import path from 'node:path'`).
6384
- Prefer URL utilities where needed (`fileURLToPath(new URL('.', import.meta.url))`).
6485
- Inline and export public types from `src/index.ts`; avoid separate `types/` unless unavoidable.
6586

6687
6. Tests: drop CJS branches; ESM everywhere
88+
6789
- Remove CJS-specific branches/assertions from tests.
6890
- Keep the existing runner (AVA) if it already handles ESM in Node 20. If the package already uses Vitest in this repo, keep that pattern.
6991
- Ensure Rollup bundles created in tests are `await bundle.close()`-d to avoid leaks.
@@ -80,9 +102,13 @@ Upgrade a single plugin under `packages/<name>` to publish ESM-only output with
80102
pnpm -C $PKG build
81103
tree $PKG/dist | sed -n '1,80p'
82104
```
105+
- Symlink exists and points at the shared config:
106+
```bash
107+
test -L "$PKG/tsconfig.json" && ls -l "$PKG/tsconfig.json" || (echo "tsconfig.json symlink missing" && exit 1)
108+
```
83109
- Type declarations resolve for consumers:
84110
```bash
85-
jq -r '.types, .exports.types, .exports.import' $PKG/package.json
111+
jq -r '.types, .exports["."].types, .exports["."].import' $PKG/package.json
86112
```
87113
- Runtime smoke (Node ESM import works):
88114
```bash

0 commit comments

Comments
 (0)