feat(ssr): graduate SSR toward Stable — directive parity, production hydration, resumable boundaries (#127–#130) - #151
Merged
Merged
Conversation
…hydration, resumable boundaries (#127 #128 #129 #130) Collected work to move the `ssr` module out of Experimental. #128 — Interactive directive parity (`bq-model` / `bq-on`): - New `RenderOptions.directives: 'full' | 'static'` (default `'static'`, fully backwards compatible). `'full'` server-renders `bq-model` (value/checked/ selected option/textarea body) and emits a `data-bq-on` hydration marker for `bq-on:*` (handlers are never executed server-side). - New `RenderOptions.onUnsupportedDirective: 'warn' | 'throw' | 'ignore'` (default `'ignore'`) enforces an explicit, documented SSR directive boundary. - Shared `directive-support.ts` keeps the pure (DOM-free) and DOM backends in lock-step; options flow through async/stream/suspense/response paths too. #130 — Production hydration correctness: - `hydrate(selector, context, { onMismatch, onError })` with boundary-scoped `warn` | `repair` | `error` recovery. - `detectHydrationMismatches()` does a content-level diff (text/show/bind/model + structural signature) using the CSP-safe evaluator, skipping unresolved `bq-for` loop variables to avoid false positives. #129 — Resumable boundaries (resume, not replay): - `createResumableBoundary` / `createResumableGraph` (server) serialize signals, handler ids, and store slices; `resume()` (client) seeds existing signals, wires handlers by id (no eval), and rehydrates stores in place. - Opt-in, tree-shakeable, prototype-pollution-filtered, `<script>`-escaped. #127 — Stability docs: SSR guide gains a Stability section (exit criteria, frozen surface, per-runtime support matrix); introduction notes the 1.15.0 target. Tests: tests/ssr-stable.test.ts (both backends) + cross-runtime smoke coverage. All suites, tsc (src + tests), eslint, build, and cross-runtime (Node/Bun) pass. Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
JosunLP
added a commit
that referenced
this pull request
Jun 27, 2026
) ## Problem The **Greetings** workflow fails on every first-time issue/PR: ``` Error: Input required and not supplied: issue_message ##[warning]Unexpected input(s) 'repo-token', 'issue-message', 'pr-message', valid inputs are ['issue_message', 'pr_message', 'repo_token'] ``` `actions/first-interaction@v3` renamed its inputs to snake_case, but `.github/workflows/greetings.yml` still passes the old kebab-case names (`repo-token`, `issue-message`, `pr-message`). The action reads them as missing and aborts before posting the greeting. ## Fix Rename the three inputs to the v3 names: `repo_token`, `issue_message`, `pr_message`. Message content is unchanged. Surfaced by the Greetings run on #151. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <[email protected]>
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.
Collected implementation of all four open
ssrtickets, on one branch, targetingdev.Closes #128 · Closes #129 · Closes #130 · Advances #127 (tracking)
What & why
ssris the last foundational module marked Experimental. This PR resolves the three substantive prerequisites for promotion and publishes the stability contract.#128 — Interactive directive parity (
bq-model/bq-on)RenderOptions.directives: 'full' | 'static'(default'static'— byte-for-byte backwards compatible).'full'rendersbq-modelinitial state (value/checked/ selected<option>/<textarea>body) and emits adata-bq-onhydration marker forbq-on:*. Handlers are never executed on the server; inlineon*attrs /javascript:URLs are still stripped.RenderOptions.onUnsupportedDirective: 'warn' | 'throw' | 'ignore'(default'ignore') — formalizes the "static-render subset" into an explicit, enforced, documented boundary (option b of the ticket) while parity (option a) is delivered via'full'.src/ssr/directive-support.tskeeps the pure (DOM-free) and DOM backends in lock-step; options also flow throughrenderToStringAsync/renderToStream/renderToStreamSuspense/renderToResponse.#130 — Guaranteed hydration correctness
hydrate(selector, context, { onMismatch, onError })— boundary-scoped recovery:warn(dev default) ·repair(rewrite the boundary from client state) ·error(route toonError, else throw before mounting).detectHydrationMismatches(root, context)— content-level diff overbq-text/bq-show/bq-bind:*/bq-modelplus the structuraldata-bq-hsignature, using the CSP-safe evaluator. Skips expressions whose root identifier is absent from the context, sobq-forloop variables never false-positive.#129 — True resumability model (resume, not replay)
createResumableBoundary/createResumableGraph(server) serialize signals (values), handlers (ids only — no code), and store slices.resume()(client) seeds existing signals, wires handlers by id from a caller-supplied registry (noeval), and rehydrates store slices in place — pairs with island hydration. Opt-in, tree-shakeable, prototype-pollution-filtered,<script>-escaped.#127 — Stability (tracking)
introduction.mdnotes the 1.15.0 target. Public exports are now frozen for the cycle.New public API
Runtime:
hydrate,detectHydrationMismatches,createResumableBoundary,createResumableGraph,resume,SSR_ON_MARKER_ATTR,RESUMABLE_BOUNDARY_ATTR,RESUMABLE_HANDLER_ATTR,RESUMABLE_EVENT_ATTR— all re-exported fromsrc/full.tsand documented indocs/guide/ssr.md.Verification
bun test— 2743 pass / 0 fail (incl. newtests/ssr-stable.test.ts, both backends).bun run test:types+bun run lint:types(tsc src + tests) — clean.bunx eslint .— clean.bun run build— succeeds;check:full-bundlein sync;ssrdoc-export coverage 54/54 (100%).tests/cross-runtime/run.mjs) extended for'full'mode + resumable boundaries — 13/13 on Node 24 & Bun.Compatibility
Defaults preserve prior output exactly (no
value/checked/data-bq-on, no warnings). All additions are optional. No version bump (release handled separately).🤖 Generated with Claude Code