Commit Graph
372 Commits
Author SHA1 Message Date
ClintchizandClaude Opus 5 02fdfa3aee feat(react): remount islands on hot module replacement
Disposes and re-creates island roots after a source change. Island state
resets by design; Fast Refresh needs a Babel/SWC transform plus a
runtime and is out of scope for v1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:34:36 +05:30
ClintchizandClaude Opus 5 5f66c8129c docs(react-islands): drop the write-during-render guard
Implemented and removed. A render-phase flag cleared on a microtask is
still set when React runs effects, so islands writing from an effect —
the documented correct pattern — would throw. The flag also cannot be
set for an island's own re-renders, so real violations pass silently.

Detecting React's render phase reliably needs React internals, which is
not acceptable in a shipped framework. React already reports the real
hazard, and the getSnapshot caching requirement covers the loop case.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:33:48 +05:30
ClintchizandClaude Opus 5 01a3b3b4e9 feat(compiler): classify island routes as static-interactive
A route mounting an island ships JavaScript, so reporting it as zero-JS
static would make the framework's performance accounting wrong.

Adds a separate needsIslandRuntime flag rather than reusing
needsClientRuntime: an island needs the island runtime, not WRNexus's
reactive runtime, and conflating them would ship the wrong bundle.

analyzeRuntimeRequirements takes island presence as an optional second
argument, so existing callers are unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:30:19 +05:30
ClintchizandClaude Opus 5 a184f1a3be feat(islands): serve the island runtime in dev, prod, and static builds
Adds /__wrnexus/islands.js (the bootstrap) and the /__wrnexus/island/
prefix (mount runtime, island bundles, shared chunks) to all three
serving paths.

Dev reuses the browserArtifactPaths registry pattern from pipeline.ts.
Prod mirrors the clientModulesDir handler, including its filename
allowlist, so island names cannot escape the output directory.

The bootstrap is inert without a data-wrn-island marker, so island-free
pages still download nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:28:10 +05:30
ClintchizandClaude Opus 5 06df9d66ae feat(compiler): bundle islands with a shared React chunk
splitting:true keeps React in one shared chunk so a page with several
islands does not ship react-dom repeatedly.

Island .tsx is compiled against React's JSX runtime via a Bun onLoad
plugin. The repo's root tsconfig sets jsxImportSource to @wrnexus/core,
so islands would otherwise compile to the HTML-string renderer and never
mount. A @jsxImportSource pragma only affects the file carrying it, so
injecting one into the generated entry is not enough — the injection has
to happen per source file. App-authored islands stay plain .tsx.

The JSX test asserts built output rather than generated entry text,
because the entry-text assertion passed while the mechanism did not work.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:22:58 +05:30
ClintchizandClaude Opus 5 d269772a79 feat(react): add island mount strategies and navigation-safe unmount
Mounts markers with client:only/load/visible/idle, and disposes roots on
route change so React roots, detached DOM, and store subscriptions do
not leak across client-side navigation.

Bundle load failures and malformed props JSON degrade to a warning and
leave the server markup intact rather than taking down the page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:20:05 +05:30
ClintchizandClaude Opus 5 df2ee036eb feat(react): add per-island error boundary
A crashed island renders its error in dev and nothing in prod, leaving
the surrounding server-rendered page intact.

Island .tsx sources carry an explicit @jsxImportSource react pragma: the
repo's root tsconfig points jsxImportSource at @wrnexus/core, so without
it island JSX compiles to WRNexus's string renderer instead of React
elements.

Tests render on the client via createRoot rather than a server renderer,
because React error boundaries do not engage during SSR — and islands
are client-only regardless.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:16:42 +05:30
ClintchizandClaude Opus 5 b405025f37 feat(compiler): resolve .tsx imports and tag them as islands
.wrn keeps resolution priority so existing components are unaffected
when a .tsx file shares their name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:15:08 +05:30
ClintchizandClaude Opus 5 cd07f0f8e2 feat(compiler): add island marker codegen and props contract
Emits the data-wrn-island placeholder, parses client:* strategies, and
rejects non-serializable props at compile time via WRN-ISLAND-PROPS so
the serialization boundary fails where it is cheapest to fix.

Island names become URL path segments when the browser fetches the
island bundle, so they are validated with core's existing
isSafeIslandName rather than relying on escaping alone. This adds
@wrnexus/core to the compiler's dependencies; core has no dependencies
of its own, so no cycle is introduced.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:13:56 +05:30
ClintchizandClaude Opus 5 ce67d0d1d2 feat(react): add useWrnStore bridge over useSyncExternalStore
Resolves WRNexus stores from inside islands, reading through the cached
snapshot so React sees a stable reference. Unknown store names throw
with the list of registered stores rather than failing opaquely.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:12:33 +05:30
ClintchizandClaude Opus 5 468f63f378 feat(react): add referentially-stable snapshot and selector caches
useSyncExternalStore requires getSnapshot to return an identical
reference when unchanged; @wrnexus/store's readonlySnapshot returns a
fresh clone per call. The cache lives here rather than in the store
package so existing consumers are untouched.

createSelectorCache takes an optional equality function: the Object.is
default can never stabilize a selector that allocates, which is the
usual source of infinite re-renders.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:11:22 +05:30
ClintchizandClaude Opus 5 a6570d7f68 docs(react-islands): add implementation plan
Twelve TDD tasks covering the approved spec: snapshot cache, store
bridge, marker codegen, .tsx resolution, error boundary, island runtime,
bundling with a shared React chunk, asset serving, route classification,
integration guards, the write-during-render guard, and HMR remount.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:07:32 +05:30
ClintchizandClaude Opus 5 4ef2ef14ff docs(react-islands): add design spec for opt-in React islands
Adds the approved design for consuming npm React components as
client-only islands inside WRNexus, without changing the SSR-first
rendering model.

Key decisions:
- New isolated @wrnexus/react package; react/react-dom as optional peers
- Client-only by default, SSR deferred to v2
- Islands declared via .tsx imports in .wrn frontmatter
- Store access via useSyncExternalStore, with the snapshot cache in the
  adapter so @wrnexus/store stays untouched
- Bundling extends the existing Bun pipeline; React as a shared chunk
- Routes with no islands must still ship zero framework JavaScript

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:01:58 +05:30
Clintchiz d78707be9f fix(forms): surface validation and recover schema drift
Quality / quality (ubuntu-latest) (push) Failing after 10m23s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-15 13:01:10 +05:30
Clintchiz 1d16ef1e82 chore(release): refresh ui consumers
Quality / quality (ubuntu-latest) (push) Failing after 9m50s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-15 12:33:40 +05:30
Clintchiz 12a1014db2 fix(ui): bind textarea values without markup
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-15 12:30:46 +05:30
Clintchiz 52b3e6d378 fix(csr): preserve translations across navigation
Quality / quality (ubuntu-latest) (push) Failing after 9m51s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-15 12:26:01 +05:30
Clintchiz f88dd47408 fix(runtime): stabilize navigation and custom errors
Quality / quality (ubuntu-latest) (push) Failing after 23s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-15 10:44:06 +05:30
Clintchiz f0447fddb0 fix(db): share registry across bundled copies
Quality / quality (ubuntu-latest) (push) Failing after 9m51s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-13 19:10:51 +05:30
Clintchiz 5106256401 fix(production): preserve emitted plugin runtimes 2026-08-13 18:00:30 +05:30
ClintchizandClaude Opus 5 94a6b436f5 test(examples): give each run its own sqlite database
The test profile pointed at ./test.db in the app directory, so a run inherited
whatever schema an earlier run left behind. On a machine with a stale file,
0003_add_password re-applied ALTER TABLE ADD COLUMN over a column that already
existed; fail-on-test-warnings turned the warning into a failure, and
check:production failed for environment reasons rather than code.

Each run now uses a fresh database under the OS temp directory. Verified by
restoring the stale dev.db and test.db that reproduced the failure: the suite
passes with them present.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 17:38:28 +05:30
ClintchizandClaude Opus 5 2425a5146f chore: untrack the .publish staging directory
.publish/ is already listed in .gitignore, but 119 files were committed before
that rule existed, so they stayed tracked. The release prepare step clears and
restages the directory, which meant a routine `git add -A` during a release
would stage the deletion of every package it had not just staged.

Nothing reads the committed contents: publish-packages.ts writes the directory,
test-staged-consumers.mjs reads it after staging, and check-component-imports
skips it. Untracking leaves the release flow unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 17:37:04 +05:30
ClintchizandClaude Opus 5 fc2c526d70 chore(release): patch-bump csr, db and ui
@wrnexus/csr 0.8.18 -> 0.8.19   output handler errors are now reported
  @wrnexus/db  0.8.10 -> 0.8.11   dead quote tracking removed
  @wrnexus/ui  0.8.15 -> 0.8.16   Typography scoping, Pagination href template

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 17:10:24 +05:30
ClintchizandClaude Opus 5 fcd552969f chore: drop a stray launch entry and format migrate.ts
An over-broad `git add -A` in the previous commit swept a local dev-server
entry for an unrelated application into .claude/launch.json. It pointed at a
path outside this repository and was not Prettier-formatted, so it failed
format:check. Restored to the version on main.

Also runs Prettier over migrate.ts, which the dead-code removal left unformatted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 17:03:17 +05:30
ClintchizandClaude Opus 5 5deac48131 chore: refresh the Typography entry in the UI visual contract
The contract tracks a content hash per component source. Rewording the comment
in Typography.wrn changed its hash, so the check failed on an edit that alters
no rendered output. Regenerated intentionally; only that one entry moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 16:59:52 +05:30
ClintchizandClaude Opus 5 2e1b667285 fix(ui): avoid component-tag syntax in a Typography comment
check-component-imports scans sources for <Component> tags and requires each to
be imported. The explanatory comment added with the prose-scoping fix wrote
<Blockquote> literally, so the checker demanded an import for a component the
file never renders. Naming it without angle brackets keeps the explanation and
clears the gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 16:58:52 +05:30
ClintchizandClaude Opus 5 8393a953b7 fix(db): drop dead quote tracking in hasExecutableSql, clear lint
hasExecutableSql returns as soon as it meets a quote character, so the quote
variable was assigned and never read: the `if (quote)` branch could never run.
eslint reported it as a useless assignment and the error blocks the release
gate on main. Removing the variable and the unreachable branch keeps behaviour
identical, since encountering a quote already means the SQL is executable.

Also drops an eslint-disable directive in csr's output error reporter that
suppressed nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 16:57:34 +05:30
ClintchizandClaude Opus 5 2459a0b5a7 chore: sync bun.lock with the @wrnexus/ui package version
The lockfile recorded @wrnexus/ui at 0.8.13 while its manifest is 0.8.15, so
validate:0.8 failed its workspace version check. The drift predates this branch
and is present on main; bun install does not rewrite workspace metadata that is
already satisfied, so this applies the same targeted rewrite the release
tooling performs in syncWorkspaceLock. No version is bumped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 16:54:34 +05:30
ClintchizandClaude Opus 5 4e5949aedc chore: refresh the public API snapshot
The committed snapshot had drifted from source on main: dev-server exports
validateRpcCsrf, and styles exports the browser-cookie configuration types and
resolveBrowserCookieOptions. All six are additions, so the surface stays
backward compatible.

This unblocks check:production, which fails on main for the same reason.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 16:51:22 +05:30
ClintchizandClaude Opus 5 60e38b983c build(editor): rebuild the bundled compiler and language server
The checked-in bundles predated the typecheck fix that resolves @wrnexus/ui
imports as component contracts, so VS Code reported "has no exported member"
for components such as Grid while the CLI typechecker passed. The package
exports nothing by design — components resolve by directory scan — so the
stale bundle was the whole defect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 15:47:08 +05:30
ClintchizandClaude Opus 5 5afb2d1875 fix(ui): make Pagination usable server-rendered, surface output errors
Pagination reported the requested page only through its change output, so on a
server-rendered page the controls did nothing: the parent had to own client
state to react, and the emitted page never became a URL. An optional
hrefTemplate now renders the steps and page numbers as anchors, which work
before hydration and without JavaScript and give each page a crawlable URL.
Buttons remain the default for client-owned lists. End steps are clamped and
marked disabled rather than linking past the first or last page.

Output handler errors are no longer swallowed. Nothing awaits invokeOutput, so
a handler that threw became an unhandled rejection that never reached the
console and presented as a control that silently does nothing. Handler errors
are now reported as WRN-DEV-OUTPUT-HANDLER-ERROR.

Regenerates the component reference and the UI visual contract.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 15:46:00 +05:30
ClintchizandClaude Opus 5 2e42be7b31 fix(ui): stop Typography prose styles leaking into nested components
Typography styled every descendant element, including those inside nested UI
components. A <Blockquote variant="bordered"> placed inside <Typography> drew
two left borders: its own, plus the one these prose rules apply to any
<blockquote>. The same leak applied to headings, links, lists and code.

Prose rules now exclude the subtree of any nested `.wrn-component`, so they
style raw markup only. The exclusion sits inside :where() so specificity stays
at zero and applications can still override these rules with a plain class.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 15:09:46 +05:30
Clintchiz b508b49058 fix(dev): consolidate generated cache directories
Quality / quality (ubuntu-latest) (push) Failing after 9m50s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 22:25:12 +05:30
Clintchiz e638c6be6a fix(cli): bundle current WRN typechecker
Quality / quality (ubuntu-latest) (push) Failing after 9m50s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 22:11:32 +05:30
Clintchiz 082da38f67 fix(typecheck): resolve UI imports as component contracts
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 22:07:37 +05:30
Clintchiz 5de792f359 feat(config): add shared browser cookie policy
Quality / quality (ubuntu-latest) (push) Failing after 9m46s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 21:53:07 +05:30
Clintchiz a0dab308f0 fix(styles): persist accent cookies on localhost
Quality / quality (ubuntu-latest) (push) Failing after 10m41s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 21:28:18 +05:30
Clintchiz dd9b7a289a fix(theme): persist switcher accent for SSR
Quality / quality (ubuntu-latest) (push) Failing after 9m48s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 21:17:20 +05:30
Clintchiz effed1c3cf fix(styles): synchronize accent across open apps
Quality / quality (ubuntu-latest) (push) Failing after 9m48s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 21:11:22 +05:30
Clintchiz 6133d33b8c feat(styles): share accent cookies across app domains
Quality / quality (ubuntu-latest) (push) Failing after 9m48s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 20:40:35 +05:30
Clintchiz 32187a425c fix: refresh UI compiler dependency
Quality / quality (ubuntu-latest) (push) Failing after 9m50s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 20:25:06 +05:30
Clintchiz 531bf7b2da fix(ui): align footer legal bar
Quality / quality (ubuntu-latest) (push) Failing after 10m14s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 20:16:49 +05:30
Clintchiz afe1c413cc fix: reject RPC requests without CSRF tokens
Quality / quality (ubuntu-latest) (push) Failing after 11m28s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:49:58 +05:30
Clintchiz f68f79786f fix: compile typed catches and reject event loop syntax
Quality / quality (ubuntu-latest) (push) Failing after 9m46s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:36:18 +05:30
Clintchiz d47c57a953 fix: skip comment-only migration SQL
Quality / quality (ubuntu-latest) (push) Failing after 9m47s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:30:30 +05:30
Clintchiz 7a968977f6 fix: preserve parent RPC scope identity
Quality / quality (ubuntu-latest) (push) Failing after 9m50s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:23:27 +05:30
Clintchiz fe9bb9ede0 fix: resolve RPC component from hydration boundary
Quality / quality (ubuntu-latest) (push) Failing after 9m44s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:17:58 +05:30
Clintchiz 7ba7c8a73f fix: ignore WRN component examples in import validation
Quality / quality (ubuntu-latest) (push) Failing after 10m54s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:13:28 +05:30
Clintchiz 8e6dca0751 fix: require corrected UI dependency chain
Quality / quality (ubuntu-latest) (push) Failing after 9m50s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:10:19 +05:30
Clintchiz b76053ae93 fix: require complete UI package in dev server
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s
2026-08-12 19:08:15 +05:30