Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
239 commits
Select commit Hold shift + click to select a range
5488e2c
feat: add tree shaking plugin mvp
radist2s May 2, 2026
9c071a3
chore: add package-lock.json to ignored list for the e2e
radist2s May 7, 2026
e384007
feat: update vitestFsMock.ts with `node:fs/promises` support
radist2s May 7, 2026
a6d3d58
feat: add precreated client transformer support
radist2s May 7, 2026
eedf560
chore: remove fs resolver
radist2s May 7, 2026
0620551
chore: remove fs resolver2
radist2s May 8, 2026
cb68b93
chore: remove fs resolver2
radist2s May 8, 2026
5c98738
fixup! chore: remove fs resolver2
radist2s May 8, 2026
d12f7b0
draft plan
radist2s May 8, 2026
1786bb6
docs: split qraft tree-shaking plans
radist2s May 8, 2026
28ca27e
docs: split qraft tree-shaking plans
radist2s May 8, 2026
d4b9b26
refactor: split tree-shaking pipeline
radist2s May 8, 2026
00994f9
fix: clean tree-shaking lint warnings
radist2s May 8, 2026
c464814
docs: add tsdoc
radist2s May 8, 2026
e61c8f2
docs: fix precreated transform example
radist2s May 8, 2026
debe81b
docs: close tree-shaking pipeline split plan
radist2s May 8, 2026
7503dcc
fixup! docs: split qraft tree-shaking plans
radist2s May 8, 2026
8469e66
fixup! docs: split qraft tree-shaking plans
radist2s May 8, 2026
e83d4b4
docs: finalize tree-shaking source maps plan
radist2s May 8, 2026
2e204cf
feat: compose tree-shaking source maps
radist2s May 8, 2026
8aefe47
Extract path rendering helpers
radist2s May 8, 2026
8c6d875
test: pin path-like precreated options imports
radist2s May 8, 2026
275541a
docs: note tree-shaking path rendering convention
radist2s May 8, 2026
a5c8969
docs: tighten path rendering wording
radist2s May 8, 2026
db72b83
docs: add e2e plans
radist2s May 8, 2026
b503f8e
Add sourcemap assertions to tree-shaking e2e
radist2s May 8, 2026
e69b972
docs: close tree-shaking source-map plan
radist2s May 8, 2026
f01c91f
refactor: playground App.tsx
radist2s May 8, 2026
c9905a6
chore: add tree shaking plugin in playground
radist2s May 8, 2026
03e8376
chore: add incorrect test
radist2s May 8, 2026
55541ee
fix: isolate tree-shaking callback scopes
radist2s May 8, 2026
6126966
docs: complete callback scope isolation plan
radist2s May 8, 2026
ce80e7c
chore: add broken optimizes precreated test
radist2s May 8, 2026
72e8f82
fix: naming collision for precreated
radist2s May 8, 2026
2a799ef
docs: add plans
radist2s May 8, 2026
8a60f49
fixup! docs: add plans
radist2s May 9, 2026
e2f4ee3
feat: No-Context Callback Support
radist2s May 9, 2026
6326eb9
docs: finish plans
radist2s May 9, 2026
b174e60
test(tree-shaking-plugin): add schema regressions
radist2s May 9, 2026
e219b66
Add schema rewrite support
radist2s May 9, 2026
7b45825
test(tree-shaking-plugin): reuse getPets for schema e2e
radist2s May 9, 2026
b5134b1
docs: add and finish schema tree-shaking plan
radist2s May 9, 2026
f1bfc22
docs: expand schema e2e plan
radist2s May 9, 2026
dfc4a9c
test(tree-shaking-plugin): cover all mixed schema accesses
radist2s May 9, 2026
3db823f
docs: update README.md
radist2s May 9, 2026
0041ccc
docs: add qraft tree-shaking helper selection plan
radist2s May 9, 2026
0264a88
docs: extend qraft tree-shaking helper selection plan
radist2s May 9, 2026
f301a8e
chore: unify tests with valid usage
radist2s May 9, 2026
6295664
docs: add tree-shaking imports ordering plan
radist2s May 9, 2026
1eaa1a8
Fix qraft import ordering
radist2s May 9, 2026
c9054cb
docs: mark tree-shaking import-order plan complete
radist2s May 9, 2026
7fb8b55
fix: unpublish-from-private-registry.sh
radist2s May 9, 2026
d703d18
chore: fix e2e project types
radist2s May 9, 2026
a40039d
fixup! docs: extend qraft tree-shaking helper selection plan
radist2s May 9, 2026
5958323
docs: rewrite qraft tree-shaking helper selection plan
radist2s May 9, 2026
e63143c
docs: refine qraft tree-shaking helper selection plan
radist2s May 9, 2026
ad986c3
fixup! docs: rewrite qraft tree-shaking helper selection plan
radist2s May 10, 2026
eec561f
fixup! fixup! docs: rewrite qraft tree-shaking helper selection plan
radist2s May 10, 2026
d3a4a97
feat: add Tree-Shaking Client Helper Selection Unit Tests
radist2s May 10, 2026
1b01884
docs: add createAPIClientFn scope split plan
radist2s May 10, 2026
611fb1a
feat: narrow sibling scope split regression (WIP)
radist2s May 10, 2026
3eedd09
fixup! docs: add createAPIClientFn scope split plan
radist2s May 10, 2026
afbae68
feat: use Babel UID for sibling scope client naming, drop manual index
radist2s May 10, 2026
19c7b9e
fixup! fixup! docs: add createAPIClientFn scope split plan
radist2s May 10, 2026
c06def6
test: cover qraft API client helper selection in e2e
radist2s May 10, 2026
7dddb7a
fix(tree-shaking): correct helper selection in e2e fixture and add un…
radist2s May 10, 2026
0f37d93
fixup! fix(tree-shaking): correct helper selection in e2e fixture and…
radist2s May 10, 2026
8e09d95
docs: Barrel Resolution & Zero-Arg No-Context Factory Fix
radist2s May 10, 2026
0444472
fix(tree-shaking): resolve factory through barrel re-exports in impor…
radist2s May 10, 2026
7b2f4fe
fix(tree-shaking): transform zero-arg no-options callbacks on no-cont…
radist2s May 10, 2026
d8238e4
fix(e2e): update node-api-helper-selection assertions after barrel an…
radist2s May 10, 2026
a054c93
refactor(tree-shaking): replace resolveBarrelReexportedFactory with r…
radist2s May 10, 2026
dfdc5d0
fixup! docs: Barrel Resolution & Zero-Arg No-Context Factory Fix
radist2s May 10, 2026
0dbe97b
docs(tree-shaking): plan module access refactor
radist2s May 10, 2026
6d11e51
refactor(tree-shaking): introduce module access boundary
radist2s May 10, 2026
67fa0c6
fix(tree-shaking): preserve module loader failures
radist2s May 10, 2026
614a163
docs(tree-shaking): mark module access boundary task done
radist2s May 10, 2026
a4aa045
refactor(tree-shaking): load generated modules through module access
radist2s May 10, 2026
9a6dd03
fix(tree-shaking): preserve module access compatibility
radist2s May 10, 2026
2e6e378
fix(tree-shaking): align module access resolver precedence
radist2s May 10, 2026
a06d3ab
test(tree-shaking): assert module access resolve precedence
radist2s May 10, 2026
7671948
docs(tree-shaking): mark module access core task done
radist2s May 10, 2026
7594e94
feat(tree-shaking): load module source through bundler adapters
radist2s May 10, 2026
08ac9b1
docs: add tree-shaking core test deduplication design
radist2s May 10, 2026
ceb1493
docs: add tree-shaking core test deduplication plan
radist2s May 10, 2026
f6962aa
test(tree-shaking): cover mixed createAPIClientFn variants
radist2s May 11, 2026
ad565eb
test(tree-shaking): cover mixed createAPIClientFn and apiClient modes
radist2s May 11, 2026
7b1821d
test(tree-shaking): cover mixed client mode edge cases
radist2s May 11, 2026
80f15b7
test(tree-shaking): merge multi-operation client snapshots
radist2s May 11, 2026
e6e9765
test(tree-shaking): merge prefix preservation snapshots
radist2s May 11, 2026
d9aefd1
test(tree-shaking): consolidate no-context factory snapshots
radist2s May 11, 2026
30d7e72
test(tree-shaking): remove duplicate explicit-options callback snapshot
radist2s May 11, 2026
fd582e1
test(tree-shaking): trim duplicate precreated options snapshot
radist2s May 11, 2026
82b93fe
docs: add mixed client identity tree-shaking design
radist2s May 11, 2026
049e863
docs: add mixed client identity implementation plan
radist2s May 11, 2026
e319127
fix(tree-shaking): track client source identity
radist2s May 11, 2026
21bd1a2
Use client source keys in planner
radist2s May 11, 2026
3f171a3
Use client source keys in mutator
radist2s May 11, 2026
10303d7
Document mixed-mode test skips
radist2s May 11, 2026
81646ee
fix(tree-shaking): align mixed client identity keys
radist2s May 11, 2026
ec6035e
fix(tree-shaking): infer context and separate operation imports & ali…
radist2s May 11, 2026
edaf6e5
docs: add tree-shaking core test refactor design
radist2s May 11, 2026
1eac4aa
docs: add tree-shaking core test refactor plan
radist2s May 11, 2026
db99eed
test(tree-shaking): add core transform test helpers
radist2s May 11, 2026
1e73ec8
test(tree-shaking): tighten core test helpers
radist2s May 11, 2026
cdbd840
test(tree-shaking): remove unused core assertion helper
radist2s May 11, 2026
f6e8a7f
docs: align core test helper plan
radist2s May 11, 2026
063d8f0
docs: sync core test harness plan
radist2s May 11, 2026
4938e47
test(tree-shaking): preserve explicit module load overrides
radist2s May 11, 2026
e3fe10a
test(tree-shaking): format core test helpers
radist2s May 11, 2026
ab98c55
test(tree-shaking): split createAPIClientFn core tests
radist2s May 11, 2026
af52a0f
test(tree-shaking): reuse core test helpers in legacy suite
radist2s May 11, 2026
8bd6b3f
test(tree-shaking): split explicit options core tests
radist2s May 11, 2026
1029113
test(tree-shaking): split precreated apiClient core tests
radist2s May 11, 2026
c2b0e8a
test(tree-shaking): split mixed client mode tests
radist2s May 11, 2026
f8c3b39
test(tree-shaking): make mixed partial case react-like
radist2s May 11, 2026
107c883
test(tree-shaking): avoid hook call inside mixed effect
radist2s May 11, 2026
622acd1
test(tree-shaking): split remaining core transform tests
radist2s May 11, 2026
00a7bea
test(tree-shaking): remove monolithic core test file
radist2s May 11, 2026
59c2be3
docs: update core test split references
radist2s May 11, 2026
3aff364
test(tree-shaking): cover representative callback classes
radist2s May 11, 2026
014a824
test(tree-shaking): cover unsupported member syntax
radist2s May 11, 2026
8a21618
test(tree-shaking): keep optional chaining safety active
radist2s May 12, 2026
459a8b1
test(tree-shaking): cover context detection and import identity
radist2s May 12, 2026
1e923fc
test(tree-shaking): reuse context fixture in schema identity case
radist2s May 12, 2026
e02b5f4
docs: mark core test refactor plan complete
radist2s May 12, 2026
acfabc3
docs: add test guide for core transform structure and maintenance
radist2s May 13, 2026
465b5c4
test(tree-shaking): cover skipping factories with service arguments
radist2s May 14, 2026
65f5a2d
docs: define tree-shaking transform boundaries
radist2s May 15, 2026
eb6bef3
docs: plan tree-shaking transform boundaries
radist2s May 15, 2026
fd4dc3a
test: pin create API client helper boundaries
radist2s May 15, 2026
2029761
test: pin precreated services ownership
radist2s May 15, 2026
c0cb2ad
test: pin mixed client helper isolation
radist2s May 15, 2026
020f6b5
test: pin schema services ownership
radist2s May 15, 2026
080d438
docs: mark tree-shaking boundary plan complete
radist2s May 15, 2026
dfca0f8
test: enable mixed schema alias coverage
radist2s May 15, 2026
3dd332b
docs: design tree-shaking plugin pipeline architecture
radist2s May 15, 2026
4a629b1
docs: plan tree-shaking plugin pipeline architecture
radist2s May 15, 2026
f22adfe
docs: clarify tree-shaking transform criteria
radist2s May 15, 2026
6a61c2e
docs: add tree-shaking e2e milestone gates
radist2s May 15, 2026
9384490
docs: split tree-shaking refactor into session plans
radist2s May 15, 2026
7e42ecc
feat: add tree-shaking diagnostics policy
radist2s May 16, 2026
54d5d81
refactor: normalize tree-shaking entrypoints
radist2s May 16, 2026
fa8525c
docs: mark tree-shaking session 1 complete
radist2s May 16, 2026
b8a8524
refactor: remove legacy config from normalized entrypoints
radist2s May 16, 2026
fd85e78
refactor: name generated react context explicitly
radist2s May 16, 2026
011e2fa
docs: plan tree-shaking public config alignment
radist2s May 16, 2026
8179023
Update tree-shaking entrypoint config types
radist2s May 16, 2026
63b094f
test(tree-shaking): use entrypoints in core transforms
radist2s May 16, 2026
6cf40d9
docs(tree-shaking): document entrypoints config
radist2s May 16, 2026
c15c5cd
docs: mark tree-shaking config alignment verified
radist2s May 16, 2026
4528eaa
docs: complete tree-shaking config alignment ledger
radist2s May 16, 2026
987463c
refactor: add tree-shaking source gate
radist2s May 16, 2026
30994f9
refactor: extract generated metadata inspection
radist2s May 16, 2026
f0bc573
fix: accept precreated factory barrels in metadata
radist2s May 16, 2026
bc14b74
fix: reuse generated metadata in planner
radist2s May 16, 2026
ecfa88f
chore: clean up task 2 lint blockers
radist2s May 16, 2026
dc7d5be
Fix precreated barrel metadata planning
radist2s May 16, 2026
c5ed59e
fix: add webpack source loading fallback
radist2s May 16, 2026
2395163
docs: complete tree-shaking session 2 ledger
radist2s May 16, 2026
56c9856
refactor: route tree-shaking through normalized runtime inputs
radist2s May 16, 2026
40a954f
test: assert normalized tree-shaking runtime inputs
radist2s May 16, 2026
50417ab
feat: enforce tree-shaking diagnostics policy
radist2s May 16, 2026
400036e
fix: report unresolved precreated diagnostics
radist2s May 16, 2026
86b9afe
fix: tighten diagnostics source signal matching
radist2s May 16, 2026
a8a8e1b
fix: keep diagnostics strict for debug and unsupported skips
radist2s May 16, 2026
21c7257
fix: narrow diagnostics source-signal candidates
radist2s May 16, 2026
f839a90
fix: make diagnostics source signals binding aware
radist2s May 16, 2026
cb73e2e
chore: format tree-shaking session 3 changes
radist2s May 16, 2026
75f25cc
docs: complete tree-shaking session 3 ledger
radist2s May 16, 2026
a1c77fb
fix: make diagnostics source signals order independent
radist2s May 16, 2026
8f8f555
refactor: remove legacy tree-shaking transform branches
radist2s May 16, 2026
1d60f77
docs: document tree-shaking diagnostics
radist2s May 16, 2026
58b20d7
docs: complete tree-shaking session 4 ledger
radist2s May 16, 2026
8968a87
refactor: simplify transform plan mutation API
radist2s May 16, 2026
9a68061
refactor: remove legacy tree-shaking debug option
radist2s May 16, 2026
1912e92
fix: resolve context handling inconsistencies in tree-shaking tests a…
radist2s May 16, 2026
19ab68e
docs: remove legacy tree-shaking debug option
radist2s May 16, 2026
0398093
refactor: extract `resolveDefaultExport` into a separate module and u…
radist2s May 16, 2026
bb0311c
refactor: extract reusable AST utility functions and `getGeneratedInf…
radist2s May 16, 2026
91c879c
refactor: replace `TransformPlan` with `TransformAnalysis` across cor…
radist2s May 16, 2026
e2f63f9
refactor: rename tree-shaking transform state
radist2s May 16, 2026
326349d
docs: specify tree-shaking module access resolving
radist2s May 16, 2026
dc171b4
docs: clarify module access source fallback
radist2s May 16, 2026
b69655f
refactor: standardize tree-shaking module access strategies
radist2s May 16, 2026
ff0daaa
docs: plan module access resolving refactor
radist2s May 16, 2026
9683252
fix: preserve exact module ids for source loading
radist2s May 16, 2026
01309f9
feat: trace module access diagnostics
radist2s May 16, 2026
52edd8b
docs: clarify module access fallback contract
radist2s May 17, 2026
37db66d
test: cover module access e2e edge cases
radist2s May 17, 2026
d6ae24a
docs: update module access resolving order and override semantics
radist2s May 18, 2026
28c1602
refactor: prioritize user override hooks in module access strategies
radist2s May 18, 2026
46b960b
docs: plan tree-shaking core test fixes
radist2s May 24, 2026
b5d43f3
test: clarify synthetic one-arg client snapshot
radist2s May 24, 2026
32303a2
test: align precreated direct invoke fixture
radist2s May 24, 2026
1c560bc
test: use React context value in explicit options fixture
radist2s May 24, 2026
f1d82a4
test: revise zero-arg client test to verify rewritten context-free ca…
radist2s May 27, 2026
879b4d5
test: remove unused context-capable factory test for explicit options…
radist2s May 27, 2026
6360170
test: add synthetic transform-shape coverage for named and inline cli…
radist2s May 27, 2026
d686a26
test: add transform-shape coverage for void/await prefixes in named a…
radist2s May 27, 2026
fc67a8f
docs: design tree-shaking import specifiers for client factories
radist2s May 27, 2026
511d97e
fixup! docs: design tree-shaking import specifiers for client factories
radist2s May 27, 2026
ba81cfb
docs: refine tree-shaking import specifier design
radist2s May 27, 2026
61c2fce
docs: plan tree-shaking public import bases
radist2s May 27, 2026
ede45fe
feat: normalize tree-shaking public import bases
radist2s May 27, 2026
161e3c0
fix: keep tree-shaking entrypoint keys type-safe
radist2s May 27, 2026
101f9fa
docs: align tree-shaking plan with staged migration
radist2s May 27, 2026
79c5b83
feat: compose public service operation imports
radist2s May 27, 2026
8e29f31
fix: normalize public service index imports
radist2s May 27, 2026
ab99a11
refactor: simplify generated tree-shaking metadata
radist2s May 27, 2026
4a08a39
fix: constrain generated metadata fallback
radist2s May 27, 2026
d4652cf
fix: constrain generated metadata fallback
radist2s May 27, 2026
20c5ea3
refactor: remove tree-shaking legacy config bridge
radist2s May 27, 2026
40cff3c
fix: complete normalized tree-shaking state
radist2s May 27, 2026
c46554d
test: cover public service import bases
radist2s May 27, 2026
592cb4a
test: configure tree-shaking e2e service bases
radist2s May 27, 2026
4308887
docs: document tree-shaking service import bases
radist2s May 27, 2026
65d47e8
fix: configure barrel precreated service base
radist2s May 27, 2026
6ca96eb
fix: configure virtual e2e service bases
radist2s May 27, 2026
ac31a11
fix: keep virtual e2e service metadata relative
radist2s May 27, 2026
f49a96f
feat: configure generated services directory
radist2s May 29, 2026
a7ecade
refactor: stop reading services index metadata
radist2s May 29, 2026
285bf38
refactor: derive services directory from entrypoint
radist2s May 29, 2026
707b706
refactor: keep react context module config-only
radist2s May 29, 2026
c8b5519
refactor: remove unused `importerId` parameter from `inspectFactoryFi…
radist2s May 29, 2026
901f3e6
refactor: remove options factory from generated metadata
radist2s May 29, 2026
0a05f78
refactor: derive factory export name from entrypoint
radist2s May 29, 2026
d8af8fe
refactor: share exported declaration reader
radist2s May 29, 2026
b36e4df
refactor: remove unused `clientFile` parameter from `validatePrecreat…
radist2s May 29, 2026
3919177
perf: cache generated metadata inspection
radist2s May 30, 2026
1b27035
refactor: move bundler lifecycle hooks to entrypoints
radist2s May 31, 2026
e20cd2e
fix: clear generated metadata cache on vite updates
radist2s May 31, 2026
dab7e41
refactor: route source gate node_modules skip through exclude
radist2s May 31, 2026
6e63304
refactor: centralize source filter defaults
radist2s May 31, 2026
6011717
refactor: move source filter defaults to plugin entrypoint
radist2s May 31, 2026
3451ac5
refactor: remove unused rollup-like resolver implementation and assoc…
radist2s Jun 12, 2026
b4f359a
refactor: remove unused resolver functions from `agnostic`, `webpack-…
radist2s Jun 12, 2026
10ae81e
refactor: remove unused resolver functions from `agnostic`, `webpack-…
radist2s Jun 12, 2026
a308456
refactor: make `sourceFilters` and `generatedMetadataCache` mandatory…
radist2s Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/qraft-tree-shaking-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openapi-qraft/tree-shaking-plugin": minor
---

Add a cross-bundler tree-shaking plugin for generated context API clients.
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
run: yarn install --immutable

- name: Build
run: yarn build:publishable
run: yarn build:publishable --force

- name: Remove Verdaccio Storage
run: rm -rf e2e/verdaccio-storage
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
run: yarn install --immutable

- name: Build
run: yarn build:publishable
run: yarn build:publishable --force

- name: Create dummy npmrc # Prevent creation of '.npmrc' by 'changesets-gitlab' with the 'NPM_TOKEN'
run: touch ".npmrc"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Qraft Tree-Shaking Explicit Options Coverage Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. When spawning workers, prefer a mini model and keep `reasoning_effort` at `high` or lower. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Cover the explicit `requestFn` and `queryClient` branches in the `tree-shaking-bundlers` fixture so the external e2e loop proves those overloads still tree-shake correctly.

**Architecture:** This plan stays relative-path only so it isolates branch coverage from resolver diversity. Two small entrypoints exercise the generated client in context-style and precreated-style form, each with explicit options calls that must survive bundling. `scenarios.mjs` owns the new matrix rows and `assert-dist.mjs` verifies both the constructor choice and the option-branch tokens.

**Tech Stack:** Node.js, Yarn 4, Vite, Rollup, Webpack, Rspack, esbuild, and the existing tree-shaking fixture scripts.

**File Structure:**
- `e2e/projects/tree-shaking-bundlers/src/context-explicit-options-relative.ts`: new context-style entrypoint that calls the generated client with explicit options.
- `e2e/projects/tree-shaking-bundlers/src/precreated-explicit-options-relative.ts`: new precreated-style entrypoint that calls the precreated client with explicit options.
- `e2e/projects/tree-shaking-bundlers/scripts/scenarios.mjs`: add the new scenarios and their expected tokens.
- `e2e/projects/tree-shaking-bundlers/scripts/assert-dist.mjs`: assert the explicit-option branches and the constructor token choices.

---

### Task 1: Add the new explicit-options entrypoints and make the assertions fail first

**Files:**
- Create: `e2e/projects/tree-shaking-bundlers/src/context-explicit-options-relative.ts`
- Create: `e2e/projects/tree-shaking-bundlers/src/precreated-explicit-options-relative.ts`
- Modify: `e2e/projects/tree-shaking-bundlers/scripts/scenarios.mjs`
- Modify: `e2e/projects/tree-shaking-bundlers/scripts/assert-dist.mjs`

- [ ] **Step 1: Add a context-style entrypoint that exercises both option branches**

Create `src/context-explicit-options-relative.ts` so it imports `createRelativeAPIClient` and exports both `createRelativeAPIClient({ requestFn: () => Promise.reject(new Error('stub')) })` and `createRelativeAPIClient({ queryClient: {} })`. Keep the file tiny and export the results so bundlers cannot drop either call.

- [ ] **Step 2: Add a precreated-style entrypoint that exercises both option branches**

Create `src/precreated-explicit-options-relative.ts` so it imports `createRelativePrecreatedAPIClient` and exports both `createRelativePrecreatedAPIClient({ requestFn: async () => ({}) })` and `createRelativePrecreatedAPIClient({ queryClient: {} })`.

- [ ] **Step 3: Add scenario rows for the two new entrypoints**

Add `context-explicit-options-relative` and `precreated-explicit-options-relative` to `scenarios.mjs`. Keep them relative-only; alias and extension diversity are already covered elsewhere in the matrix.

- [ ] **Step 4: Tighten the output assertions around constructor choice and explicit-option branches**

Update `assert-dist.mjs` so the context-style scenario must include `qraftReactAPIClient`, `requestFn`, and `queryClient`, while excluding `qraftAPIClient`. The precreated-style scenario must include `qraftAPIClient`, `requestFn`, and `queryClient`, while excluding `qraftReactAPIClient`. Keep the existing "unused context symbol must stay out" check for the precreated case.

- [ ] **Step 5: Run the local e2e workflow and confirm the new matrix is green**

Run:

```bash
cd e2e && yarn e2e:tree-shaking-bundlers-local
```

Expected: all bundlers pass for both new scenarios and the bundle text still reflects the intended branch selection.

- [ ] **Step 6: Commit the explicit-options coverage**

```bash
git add e2e/projects/tree-shaking-bundlers
git commit -m "test: cover explicit tree-shaking options branches"
```

### Task 2: Refresh the baseline after the new scenarios land

**Files:**
- Modify: `e2e/projects/tree-shaking-bundlers/dist/**`
- Modify: `e2e/projects/tree-shaking-bundlers/scripts/assert-dist.mjs`
- Modify: `e2e/projects/tree-shaking-bundlers/scripts/scenarios.mjs`

- [ ] **Step 1: Re-run the local e2e workflow from a clean state**

Run:

```bash
cd e2e && yarn e2e:tree-shaking-bundlers-local
```

Expected: the new explicit-options scenarios and the pre-existing matrix all pass together.

- [ ] **Step 2: Refresh only the checked-in outputs that changed**

If the new scenarios change bundle text, update the checked-in fixture outputs under `e2e/projects/tree-shaking-bundlers/dist`. Keep the one-file bundle contract intact.

- [ ] **Step 3: Commit the refreshed baseline**

```bash
git add e2e/projects/tree-shaking-bundlers
git commit -m "test: refresh explicit options e2e baseline"
```
130 changes: 130 additions & 0 deletions docs/superpowers/plans/2026-05-08-qraft-tree-shaking-path-rendering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Qraft Tree-Shaking Path Rendering Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. When spawning workers, prefer a mini model and keep `reasoning_effort` at `high` or lower. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Extract the import-path rendering rules out of `src/core.ts` so path normalization lives in one focused helper module, while keeping emitted import strings unchanged.

**Architecture:** This spec depends on the earlier pipeline split and source-map work. `src/lib/transform/path-rendering.ts` owns `composeImportPath`, `resolveRelativeImportPath`, `composeResolvedSourceImportPath`, `resolvePrecreatedOptionsImportPath`, `normalizeResolvedId`, `stripQueryAndHash`, `stripSourceExtension`, and `stripIndexSourceExtension`. `src/core.ts` imports those helpers instead of reimplementing path logic. `README.md` gets a short convention note so the output format stays documented.

**Tech Stack:** TypeScript, Node `path`, Vitest, Yarn 4.

---

### Task 1: Add helper-level tests that pin the rendering rules

**Files:**

- Create: `packages/tree-shaking-plugin/src/lib/transform/path-rendering.test.ts`
- Modify: `packages/tree-shaking-plugin/src/core.ts`

- [x] **Step 1: Write the helper test before the new module exists**

```ts
import {
composeImportPath,
composeResolvedSourceImportPath,
resolvePrecreatedOptionsImportPath,
} from './path-rendering.js';

it('renders relative source imports without source extensions or /index', () => {
expect(
composeResolvedSourceImportPath('/src/App.tsx', '/src/api/index.ts')
).toBe('./api');
expect(
composeResolvedSourceImportPath('/src/App.tsx', '/src/api/client.tsx')
).toBe('./api/client');
expect(
resolvePrecreatedOptionsImportPath(
'/src/App.tsx',
'./client-options',
'/src/client-options/index.ts'
)
).toBe('./client-options');
expect(composeImportPath('/src/App.tsx', '@openapi-qraft/react')).toBe(
'@openapi-qraft/react'
);
});
```

- [x] **Step 2: Run the helper test and confirm it fails because the module has not been extracted yet**

Run:

```bash
yarn workspace @openapi-qraft/tree-shaking-plugin test -- src/lib/transform/path-rendering.test.ts
```

Expected: FAIL because `path-rendering.ts` does not exist yet.

- [x] **Step 3: Add the helper module and move the path logic out of `core.ts`**

Move these functions unchanged except for imports and exports, and update `core.ts` to import them from the new module:

```ts
import {
composeImportPath,
composeResolvedSourceImportPath,
normalizeResolvedId,
resolvePrecreatedOptionsImportPath,
resolveRelativeImportPath,
stripIndexSourceExtension,
stripQueryAndHash,
stripSourceExtension,
} from './lib/transform/path-rendering.js';
```

- [x] **Step 4: Re-run the helper test and one representative core snapshot**

Run:

```bash
yarn workspace @openapi-qraft/tree-shaking-plugin test -- src/lib/transform/path-rendering.test.ts src/core.test.ts -t "renders relative source imports without source extensions or /index"
```

Expected: PASS, and the representative tree-shaking snapshot still emits the same bundler-friendly relative imports.

### Task 2: Document the convention and validate the external fixture

**Files:**

- Modify: `packages/tree-shaking-plugin/README.md`
- Modify: `packages/tree-shaking-plugin/src/core.ts`

- [x] **Step 1: Add a short README note for the rendering rule**

Add this note near the options or path-convention section:

```md
Relative generated imports are emitted without source extensions or `/index` so the output stays bundler-friendly.
Bare module specifiers are preserved as-is.
```

- [x] **Step 2: Run the package unit suite and typecheck**

Run:

```bash
yarn workspace @openapi-qraft/tree-shaking-plugin test
yarn workspace @openapi-qraft/tree-shaking-plugin typecheck
```

Expected: both commands pass after the helper extraction.

- [x] **Step 3: Run the external tree-shaking e2e checkpoint**

Run:

```bash
cd e2e && yarn e2e:tree-shaking-bundlers-local
```

Expected: the external multi-bundler fixture still produces the same output shape and the path strings remain bundler-friendly.

- [x] **Step 4: Commit the extraction**

```bash
git add packages/tree-shaking-plugin/src/lib/transform/path-rendering.ts packages/tree-shaking-plugin/src/lib/transform/path-rendering.test.ts packages/tree-shaking-plugin/src/core.ts packages/tree-shaking-plugin/README.md
git commit -m "refactor: centralize tree-shaking path rendering"
```

---
Loading
Loading