Skip to content

Commit 87c5637

Browse files
committed
docs: define v0.21.9 ESM consumer graph plan
1 parent eccf2a1 commit 87c5637

4 files changed

Lines changed: 387 additions & 26 deletions

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# ADR-0041: ESM Module Graph First for JSR Consumer Builds
2+
3+
> **Status**: ACCEPTED
4+
> **Date**: 2026-05-24
5+
> **Applies to**: v0.21.9
6+
> **Extends**: ADR-0033, ADR-0037, ADR-0038
7+
8+
## Context
9+
10+
LessJS v0.21.x is a Deno workspace published to JSR and consumed by generated
11+
applications through `deno run -A jsr:@lessjs/create`. The intended architecture
12+
is standards-first ESM:
13+
14+
1. LessJS packages expose TypeScript ESM entrypoints through JSR exports.
15+
2. Application source imports stable bare specifiers such as `@lessjs/core`,
16+
`@lessjs/ui/less-card`, and `@lessjs/signals/framework`.
17+
3. Vite/Rolldown performs the final production bundle, tree-shaking, and code
18+
splitting.
19+
20+
Recent JSR consumer smoke tests exposed a boundary leak. The adapter-vite SSG
21+
pipeline fetched JSR source files into virtual modules, then handed those
22+
modules to Vite. Source that was valid under Deno/JSR package resolution could
23+
still contain metadata-resolved specifiers such as:
24+
25+
```text
26+
jsr:@lessjs/signals@^0.21/framework
27+
```
28+
29+
Vite/Rolldown does not natively own Deno's `jsr:` package scheme. When the SSG
30+
pipeline bypasses Deno's resolver and fetches source manually, LessJS must not
31+
leave Deno/JSR resolution semantics half-applied inside the Vite module graph.
32+
33+
## Decision
34+
35+
**LessJS v0.21.9 will treat the ESM module graph as the primary contract for
36+
published package consumption. Vite/Rolldown remains the final bundler only.**
37+
38+
This means:
39+
40+
1. Userland and generated app code import LessJS through stable ESM bare
41+
specifiers.
42+
2. Package `exports` define the public entrypoint graph.
43+
3. Package `imports` may point at `jsr:` for Deno/JSR resolution, but `jsr:`
44+
specifiers must not leak into any Vite/Rolldown bundle graph.
45+
4. adapter-vite must provide a centralized LessJS package graph bridge for SSG
46+
when it consumes published JSR source outside Deno's native resolver.
47+
5. The bridge must be package-aware, export-aware, version-aware, and tested
48+
against a generated consumer project.
49+
50+
## Architecture Boundary
51+
52+
```
53+
Generated app source
54+
imports @lessjs/app, @lessjs/core, @lessjs/ui/*
55+
|
56+
v
57+
Deno / JSR package resolution
58+
resolves package exports and imports
59+
|
60+
v
61+
LessJS ESM module graph
62+
stable bare specifiers and virtual ids only
63+
|
64+
v
65+
adapter-vite SSG package graph bridge
66+
normalizes LessJS package entrypoints for Vite
67+
|
68+
v
69+
Vite / Rolldown
70+
bundle, tree-shake, split chunks
71+
```
72+
73+
Vite is not responsible for understanding Deno-specific package schemes.
74+
LessJS is responsible for ensuring the module graph handed to Vite is ordinary
75+
bundler-consumable ESM.
76+
77+
## Required Invariants
78+
79+
- Published LessJS package versions are unified for a release train.
80+
- Public package entrypoints are declared through `exports`.
81+
- Internal monorepo dependencies use stable LessJS bare specifiers in source.
82+
- `jsr:@lessjs/*` may appear in Deno package metadata, but not in generated
83+
Vite virtual entries or unresolved Vite/Rolldown logs.
84+
- adapter-vite SSG resolution must not be a list of one-off special cases.
85+
- Consumer smoke tests must exercise the JSR-published path, not only the local
86+
workspace path.
87+
88+
## Non-Goals
89+
90+
- Do not replace Vite/Rolldown.
91+
- Do not introduce a custom general-purpose bundler.
92+
- Do not force application authors to import `jsr:` specifiers in app source.
93+
- Do not add npm publishing as a workaround for the v0.21.x consumer path.
94+
- Do not widen v0.21.9 into Edge Full-Stack runtime work.
95+
96+
## Consequences
97+
98+
### Positive
99+
100+
- The generated app path matches the product story: ESM first, standards first,
101+
Vite final bundling.
102+
- JSR package consumption becomes a release gate instead of an after-publish
103+
surprise.
104+
- The SSG pipeline gets a single ownership boundary for package graph
105+
normalization.
106+
- Future packages such as content, i18n, UI, and adapters can be checked against
107+
the same graph rules.
108+
109+
### Negative
110+
111+
- adapter-vite must own more package-resolution logic than a purely local
112+
workspace build needs.
113+
- Release validation now needs an external-style consumer smoke test.
114+
- Version drift across packages becomes a blocking release issue.
115+
116+
## Acceptance Signals
117+
118+
v0.21.9 is accepted only when:
119+
120+
1. all `packages/*/deno.json` LessJS dependency imports are version-aligned;
121+
2. a generated JSR consumer app builds from outside the workspace;
122+
3. Vite/Rolldown receives no unresolved `jsr:@lessjs/*` specifier;
123+
4. the SSG package graph bridge is centralized and tested;
124+
5. release docs record the exact consumer validation command.
125+
126+
## Related
127+
128+
- ADR-0033: Architecture Positioning: SSG Islands
129+
- ADR-0037: DSD-First Strategic Boundary
130+
- ADR-0038: ISR + Edge KV Architecture
131+
- `docs/sop/v0.21.x/SOP-011-jsr-consumer-esm-graph.md`

docs/adr/README.md

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,33 @@ architectural decision, its context, and consequences.
2323

2424
## Active ADRs
2525

26-
| ADR | Title | Status |
27-
| ---- | ------------------------------------------ | ---------------------------------------- |
28-
| 0006 | Version Roadmap | Accepted |
29-
| 0007 | npm Publishing Strategy | Accepted |
30-
| 0010 | Eliminate .less/ temp files | Accepted, Implemented |
31-
| 0011 | Eliminate globalThis bridge | Accepted, Implemented |
32-
| 0016 | Dual-mode subpath resolution | Accepted, Implemented |
33-
| 0017 | Runtime/Build separation | Accepted, Implemented |
34-
| 0018 | Virtual Data Modules | Accepted, Implemented |
35-
| 0024 | Standards-first WC Renderer Roadmap | Accepted |
36-
| 0025 | Renderer Protocol | Accepted (v0.15 partial, v0.16 deferred) |
37-
| 0026 | Structured Render Pipeline (v0.16) | Proposed |
38-
| 0027 | Roadmap Reorder: Engine Before Hub | Accepted |
39-
| 0028 | Conservative Third-Party WC SSR Admission | Proposed |
40-
| 0029 | Happy DOM for v0.18.3 DOM Simulation | Superseded by ADR-0032 |
41-
| 0030 | Hub Architecture + Submission Pipeline | Proposed |
42-
| 0031 | Hub v2 Component Browser Workflow | Proposed |
43-
| 0032 | Real Browser Snapshot Rendering | Proposed |
44-
| 0033 | Architecture Positioning: SSG Islands | Accepted |
45-
| 0034 | Hermetic Hub Snapshots | Proposed |
46-
| 0035 | SSG Resilient Rendering + Visual Overhaul | Accepted |
47-
| 0036 | Ocean-Island Architecture | Accepted / Implemented |
48-
| 0037 | DSD-First Strategic Boundary | Accepted |
49-
| 0038 | ISR + Edge KV Architecture | Accepted |
50-
| 0039 | DsdElement + Signals Reactive Architecture | Accepted |
51-
| 0040 | Streaming DSD | Accepted |
26+
| ADR | Title | Status |
27+
| ---- | ---------------------------------------------- | ---------------------------------------- |
28+
| 0006 | Version Roadmap | Accepted |
29+
| 0007 | npm Publishing Strategy | Accepted |
30+
| 0010 | Eliminate .less/ temp files | Accepted, Implemented |
31+
| 0011 | Eliminate globalThis bridge | Accepted, Implemented |
32+
| 0016 | Dual-mode subpath resolution | Accepted, Implemented |
33+
| 0017 | Runtime/Build separation | Accepted, Implemented |
34+
| 0018 | Virtual Data Modules | Accepted, Implemented |
35+
| 0024 | Standards-first WC Renderer Roadmap | Accepted |
36+
| 0025 | Renderer Protocol | Accepted (v0.15 partial, v0.16 deferred) |
37+
| 0026 | Structured Render Pipeline (v0.16) | Proposed |
38+
| 0027 | Roadmap Reorder: Engine Before Hub | Accepted |
39+
| 0028 | Conservative Third-Party WC SSR Admission | Proposed |
40+
| 0029 | Happy DOM for v0.18.3 DOM Simulation | Superseded by ADR-0032 |
41+
| 0030 | Hub Architecture + Submission Pipeline | Proposed |
42+
| 0031 | Hub v2 Component Browser Workflow | Proposed |
43+
| 0032 | Real Browser Snapshot Rendering | Proposed |
44+
| 0033 | Architecture Positioning: SSG Islands | Accepted |
45+
| 0034 | Hermetic Hub Snapshots | Proposed |
46+
| 0035 | SSG Resilient Rendering + Visual Overhaul | Accepted |
47+
| 0036 | Ocean-Island Architecture | Accepted / Implemented |
48+
| 0037 | DSD-First Strategic Boundary | Accepted |
49+
| 0038 | ISR + Edge KV Architecture | Accepted |
50+
| 0039 | DsdElement + Signals Reactive Architecture | Accepted |
51+
| 0040 | Streaming DSD | Accepted |
52+
| 0041 | ESM Module Graph First for JSR Consumer Builds | Accepted |
5253

5354
## Superseded / Historical
5455

docs/sop/v0.21.x/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ The product stance for this line is:
2424
| v0.21.3 | SOP-007 to SOP-008 | Harden adapter-vite admission, SSG build reports, and the blog/docs product path. |
2525
| v0.21.4 | SOP-009 | Make Registry Hub evidence and package trust checks credible enough to support ecosystem growth. |
2626
| v0.21.5 | SOP-010 | Run the pre-v0.22 release gate and decide whether Edge Full-Stack can start. |
27+
| v0.21.9 | SOP-011 | Harden the JSR consumer ESM graph so Vite/Rolldown only owns final bundling optimization. |
2728

2829
## SOP List
2930

@@ -37,6 +38,7 @@ The product stance for this line is:
3738
8. [SOP-008 SSG Product Stack Hardening](./SOP-008-ssg-product-hardening.md)
3839
9. [SOP-009 Hub Evidence and Trust Pipeline](./SOP-009-hub-evidence-trust.md)
3940
10. [SOP-010 v0.22 Entry Gate](./SOP-010-v022-entry-gate.md)
41+
11. [SOP-011 JSR Consumer ESM Graph Hardening](./SOP-011-jsr-consumer-esm-graph.md)
4042

4143
## Public API Classification
4244

0 commit comments

Comments
 (0)