Repository navigation
refactor(ranvi): extract the builder into its own published package - #408
Merged
Merged
Conversation
The builder had grown into a general-purpose library wearing a component
library's clothes: 1,831 lines, a 434-line manual, 345 tests, and exactly one
external import. Anyone who wanted framework-free reactive DOM had to install
ranui — and with it dash.js, hls.js, mpegts.js, mermaid and temml: 242 MB of
transitive dependencies for a file that depends on one function. ranpress could
not use it at all for that reason.
It is `ranvi` now, depending only on ranuts.
**ranui's behaviour is unchanged, and that was the acceptance test.** All 1,641
of its remaining tests pass without a single edit. The count moved from
1,732 + 254 to 1,565 + 76 because 344 builder tests moved to the new package;
1,986 before, 1,986 after, none lost. The one further difference —
1,566 → 1,565 — is `docs.references`, which generates a case per doc file in
ranui, and ranui now has one fewer doc.
How the surface was kept identical:
- 84 of the 90 internal imports go through `@/utils/builder`, so that path
stays and re-exports `ranvi`. Not one of those files changed.
- The six that reached past it (`./builder/core`, `./builder/signal`,
`./builder/env`) now name `ranvi` directly.
- `builder.ts`, the published `ranui/builder` entry, keeps enumerating every
export by name rather than forwarding wholesale — a star would also carry
whatever ranvi adds next, quietly widening ranui's public API.
Build output was checked in both shapes, because they differ: the ES build
externalises `ranvi` (it is a runtime dependency, so consumers get it through
npm), while the IIFE bundles inline it, as they must — verified that no
standalone bundle contains a bare import of it.
`ranvi` exports TypeScript source to workspace consumers and swaps in `dist`
through `publishConfig` at pack time, so `pnpm -F ranui build` needs no
build-order dependency on it. That does mean consumers type-check this source,
which immediately found a bare `import.meta.env.DEV` that only compiles where
Vite's ambient types are declared; it is a local helper now.
Two other things surfaced on the way. `ShadowBuilder` kept a private `options`
field that nothing ever read — taken in the constructor, assigned, never used.
And the error strings still said "ranui": a cyclic-dependency message and a
duplicate-key warning that now name the package they come from.
`test/readme.test.ts` is new: the manual's import lines were rewritten from
`ranui/builder` to `ranvi` mechanically, and nothing was checking that the
*names* in them exist. A manual that tells a reader to import something that
does not exist is worse than no manual — they assume they are holding it wrong.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019pjSL6jGCw2wmBLhCAW35d
Deploying ran with
|
| Latest commit: |
e09f322
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a95ba4f7.ran-4ty.pages.dev |
| Branch Preview URL: | https://refactor-extract-ranview.ran-4ty.pages.dev |
Moving a file breaks whatever pointed at it, and the repo's dead-link check
found thirteen — which is the check doing exactly its job.
- `docs/BUILDER.md` was linked from all eight ranui READMEs and both
`utils/README*.md`. They now point at ranvi's README, which is where the
manual went.
- `SSR_DESIGN.md` cited `utils/builder/mocks.ts#L227` for the serialisation
contract; that file is `ranvi/src/mocks.ts` now.
- ranvi's own README carried two relative links to `COMPONENTS.md` and
`DESIGN.md`. They resolved while it lived in `ranui/docs/` and stopped the
moment it did not — both name ranui's copies explicitly now.
Also removes a `readFileSync` import left unused in `design-bundle.ts` by an
earlier commit of mine. It was a lint warning rather than the failure, but it
was mine and it was noise in the same log.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019pjSL6jGCw2wmBLhCAW35d
The previous run sat queued for 51 minutes without a runner being allocated — GitHub reported all systems operational, the repository is public so standard runners are unmetered, nothing else was consuming concurrency, and no workflow declares a concurrency group. Cancelled and re-triggered; no source change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019pjSL6jGCw2wmBLhCAW35d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The builder had grown into a general-purpose library wearing a component library's clothes: 1,831 lines, a 434-line manual, 345 tests, and exactly one external import. Anyone who wanted framework-free reactive DOM had to install ranui — and with it dash.js, hls.js, mpegts.js, mermaid and temml: 242 MB of transitive dependencies for a file that depends on one function. ranpress could not use it at all for that reason.
It is
ranvinow, depending only onranuts.ranui's behaviour is unchanged — that was the acceptance test
All 1,641 remaining ranui tests pass without a single edit.
None lost. The one further difference — 1,566 → 1,565 — is
docs.references, which generates a case per doc file in ranui, and ranui now has one fewer doc.How the surface was kept identical
@/utils/builder, so that path stays and re-exportsranvi. Not one of those files changed../builder/core,./builder/signal,./builder/env) now nameranvidirectly.builder.ts, the publishedranui/builderentry, keeps enumerating every export by name rather than forwarding wholesale — a star would also carry whatever ranvi adds next, quietly widening ranui's public API. (package-exports.sourceenforces this, and caught it when the word appeared in a comment.)Build output, checked in both shapes
They differ, and both had to be right:
ranvi— it is a runtime dependency, so consumers get it through npm.dist/builder.jsis now a 1.4 kB re-export.Packaging
ranviexports TypeScript source to workspace consumers and swaps indistthroughpublishConfigat pack time, sopnpm -F ranui buildneeds no build-order dependency on it.That does mean consumers type-check this source — which immediately found a bare
import.meta.env.DEVthat only compiles where Vite's ambient types are declared. It is a local helper now. This is the kind of thing that would otherwise have been discovered by the first person to install the package.Found on the way
ShadowBuilderkept a privateoptionsfield that nothing ever read — taken in the constructor, assigned, never used.test/readme.test.tsis new. The manual's import lines were rewritten fromranui/buildertoranvimechanically, and nothing was checking that the names in them exist. A manual that tells a reader to import something that does not exist is worse than no manual — they assume they are holding it wrong. 21 names checked.Verification
tscacross 8 packages, 3,145 tests,verify:designacross 3 packages,verify-packages(14 declared), prettier, and bothranuiandranvibuilds.🤖 Generated with Claude Code
https://claude.ai/code/session_019pjSL6jGCw2wmBLhCAW35d