[E00-S01-T03] Configure ESM package boundaries #370
No Reviewers
Labels
Clear labels
agent/analyst-drafted
agent/analyst-drafted
needs/human-decision
needs/human-decision
needs/security-review
needs/security-review
tier/t0
tier/t1
tier/t2
tier/t3
kind
bug
kind
bug
kind
epic
kind
epic
kind
initiative
EPPP programme initiative
kind
story
kind
story
kind
task
EPPP engineering card/task decomposed from a story
kind
toil
kind
toil
loop
1
loop
1
loop
2
loop
2
loop
3
loop
3
risk
agent-full
risk
agent-full
risk
human-gated
risk
human-gated
risk
human-only
risk
human-only
size
l
size
l
size
m
size
m
size
s
size
s
status
blocked
status
blocked
status
done
Workflow: Done
status
in-progress
status
in-progress
status
proposed
status
proposed
status
ready
status
ready
status
review
status
review
stream
checkout
stream
checkout
stream
onboarding
stream
onboarding
stream
platform
stream
platform
trivial — implementer only, auto-merge
standard — implementer + reviewer + tester
complex — security if triggered, human merge
critical — full chain + security, human merge
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Fabrika/PersonalBlog#370
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What changed
Configures ESM package boundaries for [E00-S01-T03] Configure ESM package boundaries (#156):
apps/server/package.json,packages/core/package.json,extensions/example/package.json— each workspace package now declares its ESM boundary in its manifest:"type": "module"— package source and emit are ESM"main": "./dist/index.js"+"types": "./dist/index.d.ts"— declared entry points matching therootDir src/outDir disttsconfig emit (T02)"exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } }— an export map that is the package boundary: only the package root is reachable, deep subpath imports (@personal-blog/core/src/...) are blocked, and thetypescondition is declared first for TS consumerspackage.json— adds"type": "module"so the whole workspace (apps, packages, extensions) is uniformly ESM, per Engineering-Standards "ESM-first"src/index.tsplaceholders stay as empty ESM modules (export {}); real exports land with later storiesExplicitly out of scope per the brief:
tsconfig.base.json(E00-S01-T02, merged), dependency-boundary rule/test (E00-S01-T04), root build/test scripts (E00-S01-T05). No tsconfig, no lockfile, no CI changes in this PR.Criterion → test table
apps/server,packages/core,extensions/exampleeach commit"type": "module","main": "./dist/index.js","types": "./dist/index.d.ts"and"exports"with.→{ types, import }; verified by parsing each manifest (3/3)type/main/types/exports); rootpackage.jsonalso declares"type": "module"so apps, packages and extensions are uniformly ESM; verified withpnpm -r list --depth -1→ all 4 workspace projects (root + 3 packages) install/listed with pnpm 11.23.0tsc -p <pkg>/tsconfig.json(TypeScript 6.0.3, NodeNext) succeeds for all 3 packages and emits ESMdist/index.js(export {};, no CJSexports./require) +dist/index.d.ts+ sourcemap; a consumer project that depends on the workspace packages by name (@personal-blog/server,@personal-blog/core,@personal-blog/example-extensionviafile:links) imports all three through theexportsmap as real ESM modules ([object Module]), and a deep import@personal-blog/core/src/index.jsis rejected withERR_PACKAGE_PATH_NOT_EXPORTEDTest plan executed
tsc -p apps/server/tsconfig.json,-p packages/core/tsconfig.json,-p extensions/example/tsconfig.json(TypeScript 6.0.3) → all compile, all emitdist/index.js+dist/index.d.ts+dist/index.js.map✓index.jsis ESM (top-levelexport {};, no CJS artifacts) ✓import('@personal-blog/<pkg>')by name resolves through theexportsmap for all 3 packages →[object Module]✓ERR_PACKAGE_PATH_NOT_EXPORTED✓pnpm install --frozen-lockfile(pnpm 11.23.0, same as CI) → "Already up to date", exit 0, lockfile unchanged (git statusclean apart from the 4 manifests) ✓pnpm -r list --depth -1→ all 4 workspace projects listed ✓Risks / notes
export {}— they compile as valid ESM under"type": "module"; meaningful exports arrive with the packages' real stories."type": "module"is a zero-behaviour change today (no root-level JS files) but keeps the workspace uniformly ESM;pnpm install/CI unaffected (verified above).Closes #156