chore: a2ui playground deps + extractor windows fix + rspeedy build o…#2562
Conversation
🦋 Changeset detectedLatest commit: a797591 The changes in this PR will be included in the next version bump. This PR includes changesets to release 9 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughRemoves the explicit chunk-scoped ChangesWeb-core Fetch Scope Refactoring
A2UI Catalog Extractor Robustness
A2UI Playground (Payload Store & Dev Middleware)
Build Infrastructure & Tooling Updates
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/web-platform/web-core/ts/client/background/background-apis/createChunkLoading.ts (1)
158-167:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
loadScriptAsyncsilently dropsreadScriptAsyncrejections.If
readScriptAsyncrejects (e.g.,fetchfails with a network error or a non-200 status), the.then()branch is never reached,callbackis never invoked, and the caller hangs indefinitely with no error signal. This is a pre-existing gap, but it is worth fixing while this function is under active modification.🛡️ Proposed fix
loadScriptAsync: async (sourceURL, callback, templateUrl: string) => { - readScriptAsync(sourceURL, templateUrl).then((jsContent) => { - callback( - null, - createBundleInitReturnObj( - jsContent, - ), - ); - }); + readScriptAsync(sourceURL, templateUrl).then( + (jsContent) => { + callback(null, createBundleInitReturnObj(jsContent)); + }, + (err) => { + callback(err instanceof Error ? err : new Error(String(err)), undefined); + }, + ); },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web-platform/web-core/ts/client/background/background-apis/createChunkLoading.ts` around lines 158 - 167, The loadScriptAsync implementation currently calls readScriptAsync(...).then(...) and thus swallows any rejection, leaving the callback never invoked; update loadScriptAsync (the loadScriptAsync function) to handle failures from readScriptAsync by catching rejections (either add a .catch or convert to async/await with try/catch) and invoke callback(error) on failure, and still call callback(null, createBundleInitReturnObj(jsContent)) on success so callers always receive either an error or the bundle object.
🧹 Nitpick comments (1)
packages/genui/a2ui-catalog-extractor/src/cli.ts (1)
146-160: ⚡ Quick winAvoid success-style logging before failing on zero catalogs.
At Line 146,
printGeneratedComponentsruns before the new failure guard, so the CLI can print a success-style summary and then return1. Move the zero-components check beforeprintGeneratedComponentsto keep output unambiguous.Proposed adjustment
- printGeneratedComponents(components); - - // Fail loudly if we matched source files but emitted no components — + // Fail loudly if we matched source files but emitted no components — // this used to silently succeed on Windows when TypeDoc rejected // backslash entry-point paths, and downstream packages then failed // to import the missing `catalog.json` files. if (components.length === 0) { console.error( `[a2ui-catalog-extractor] Found ${uniqueSourceFiles.length} ` + `source file(s) but emitted 0 component catalogs. Make sure ` + `each catalog props interface is annotated with ` + `\`@a2uiCatalog <Name>\`.`, ); return 1; } + + printGeneratedComponents(components);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/genui/a2ui-catalog-extractor/src/cli.ts` around lines 146 - 160, The CLI prints a success-style summary by calling printGeneratedComponents(components) before checking for zero emitted catalogs; move the zero-components guard (the if (components.length === 0) block that logs using uniqueSourceFiles and returns 1) to run before calling printGeneratedComponents so no success output is emitted when we intend to fail — keep the same error message and return 1 behavior, just relocate that block to precede the call to printGeneratedComponents.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/genui/a2ui-playground/rsbuild.config.ts`:
- Around line 33-47: The readJsonBody function currently buffers the entire
request with no size limit; update readJsonBody(IncomingMessage) to accept a
maxBodySize (e.g., default 1MB) and enforce it while collecting chunks: track
accumulated length on each 'data' event, and if it exceeds maxBodySize, remove
listeners, destroy the request (or call req.pause()/req.destroy()), and reject
the promise with a clear Payload Too Large error (HTTP 413) so the POST/payload
handler cannot exhaust server memory; ensure you also clean up 'end'/'error'
listeners on early termination. Reference: readJsonBody and the payload POST
handler that calls it.
---
Outside diff comments:
In
`@packages/web-platform/web-core/ts/client/background/background-apis/createChunkLoading.ts`:
- Around line 158-167: The loadScriptAsync implementation currently calls
readScriptAsync(...).then(...) and thus swallows any rejection, leaving the
callback never invoked; update loadScriptAsync (the loadScriptAsync function) to
handle failures from readScriptAsync by catching rejections (either add a .catch
or convert to async/await with try/catch) and invoke callback(error) on failure,
and still call callback(null, createBundleInitReturnObj(jsContent)) on success
so callers always receive either an error or the bundle object.
---
Nitpick comments:
In `@packages/genui/a2ui-catalog-extractor/src/cli.ts`:
- Around line 146-160: The CLI prints a success-style summary by calling
printGeneratedComponents(components) before checking for zero emitted catalogs;
move the zero-components guard (the if (components.length === 0) block that logs
using uniqueSourceFiles and returns 1) to run before calling
printGeneratedComponents so no success output is emitted when we intend to fail
— keep the same error message and return 1 behavior, just relocate that block to
precede the call to printGeneratedComponents.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f865394d-1b34-4e43-bbea-c7fa991d0ec9
📒 Files selected for processing (9)
.changeset/quirky-merkle-web-core-fetch.mdpackages/genui/a2ui-catalog-extractor/src/cli.tspackages/genui/a2ui-catalog-extractor/src/index.tspackages/genui/a2ui-playground/lynx.config.tspackages/genui/a2ui-playground/rsbuild.config.tspackages/genui/a2ui-playground/turbo.jsonpackages/rspeedy/core/turbo.jsonpackages/web-platform/web-core/ts/client/background/background-apis/createChunkLoading.tspackages/web-platform/web-core/ts/types/BTSChunk.ts
Merging this PR will not alter performance
Comparing Footnotes
|
React External#929 Bundle Size — 680.82KiB (0%).a797591(current) vs 5f3b6eb main#913(baseline) Bundle metrics
|
| Current #929 |
Baseline #913 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
3 |
3 |
|
17 |
17 |
|
5 |
5 |
|
8.59% |
8.59% |
|
0 |
0 |
|
0 |
0 |
Bundle analysis report Branch PupilTong:claude/quirky-merkle-n... Project dashboard
Generated by RelativeCI Documentation Report issue
React Example with Element Template#80 Bundle Size — 198.12KiB (0%).a797591(current) vs 5f3b6eb main#64(baseline) Bundle metrics
Bundle size by type
|
| Current #80 |
Baseline #64 |
|
|---|---|---|
145.76KiB |
145.76KiB |
|
52.36KiB |
52.36KiB |
Bundle analysis report Branch PupilTong:claude/quirky-merkle-n... Project dashboard
Generated by RelativeCI Documentation Report issue
React Example#7814 Bundle Size — 225.52KiB (0%).a797591(current) vs 5f3b6eb main#7798(baseline) Bundle metrics
|
| Current #7814 |
Baseline #7798 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
4 |
4 |
|
180 |
180 |
|
69 |
69 |
|
44.54% |
44.54% |
|
2 |
2 |
|
0 |
0 |
Bundle size by type no changes
| Current #7814 |
Baseline #7798 |
|
|---|---|---|
145.76KiB |
145.76KiB |
|
79.77KiB |
79.77KiB |
Bundle analysis report Branch PupilTong:claude/quirky-merkle-n... Project dashboard
Generated by RelativeCI Documentation Report issue
React MTF Example#946 Bundle Size — 196.68KiB (0%).a797591(current) vs 5f3b6eb main#930(baseline) Bundle metrics
|
| Current #946 |
Baseline #930 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
3 |
3 |
|
174 |
174 |
|
66 |
66 |
|
44.05% |
44.05% |
|
2 |
2 |
|
0 |
0 |
Bundle size by type no changes
| Current #946 |
Baseline #930 |
|
|---|---|---|
111.23KiB |
111.23KiB |
|
85.45KiB |
85.45KiB |
Bundle analysis report Branch PupilTong:claude/quirky-merkle-n... Project dashboard
Generated by RelativeCI Documentation Report issue
Web Explorer#9387 Bundle Size — 900.02KiB (~-0.01%).a797591(current) vs 5f3b6eb main#9371(baseline) Bundle metrics
Bundle size by type
Bundle analysis report Branch PupilTong:claude/quirky-merkle-n... Project dashboard Generated by RelativeCI Documentation Report issue |
…lumbing Independent slice of the broader a2ui refactor — these changes don't depend on the renderer/store reshape and can land on their own. - a2ui-catalog-extractor: force POSIX path separators on TypeDoc entry points so the extractor works on Windows; exit non-zero when source files match but 0 components are emitted; recognize the published bin shim as a valid entry script. - rspeedy/core/turbo.json: declare `//#build` as a dep of `build`. Without it, a fresh CI checkout can race rspeedy's `rslib build` d.ts generation against the root `tsc --build` that produces the webpack plugins' `lib/*.d.ts`, intermittently failing with TS2307 on `@lynx-js/cache-events-webpack-plugin` / `@lynx-js/chunk-loading-webpack-plugin`. - web-platform/web-core: stop redeclaring `fetch` as a chunk-scope binding so BTS chunks reuse `window.fetch`. - a2ui-playground: relocate the in-memory payload store from `lynx.config.ts` to `rsbuild.config.ts` (it belongs to the rsbuild dev server, not the rspeedy lynx config); run `gcPayloads()` on GET too so an idle dev server can't keep stale payloads past the 30-minute TTL; add per-package `turbo.json` declaring task ordering and outputs. - ci: ignore `packages/genui/a2ui-playground/www/**` in eslint and vitest coverage so the rspeedy/rsbuild build output isn't parsed as source.
76e85a2 to
a797591
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/genui/a2ui-playground/rsbuild.config.ts (1)
33-47:⚠️ Potential issue | 🟠 Major | ⚡ Quick winCap payload size before buffering the full request body.
readJsonBodycurrently accumulates the entire POST body with no byte limit, so one large request can exhaust memory before the error path runs. Reject oversized bodies early and return413from the POST handler.Suggested fix
interface StoredPayload { messages: unknown; actionMocks?: unknown; createdAt: number; } const payloadStore = new Map<string, StoredPayload>(); const PAYLOAD_TTL_MS = 30 * 60 * 1000; // 30 minutes +const MAX_PAYLOAD_BYTES = 1024 * 1024; // 1MB function readJsonBody(req: IncomingMessage): Promise<unknown> { return new Promise((resolve, reject) => { const chunks: Buffer[] = []; - req.on('data', (c: Buffer) => chunks.push(c)); - req.on('end', () => { + let total = 0; + + const cleanup = () => { + req.off('data', onData); + req.off('end', onEnd); + req.off('error', onError); + }; + + const onError = (error: Error) => { + cleanup(); + reject(error); + }; + + const onData = (chunk: Buffer) => { + total += chunk.length; + if (total > MAX_PAYLOAD_BYTES) { + cleanup(); + req.destroy(); + reject(new Error('payload too large')); + return; + } + chunks.push(chunk); + }; + + const onEnd = () => { + cleanup(); try { const raw = Buffer.concat(chunks).toString('utf8'); resolve(raw ? JSON.parse(raw) : {}); } catch (e) { reject(e instanceof Error ? e : new Error(String(e))); } - }); - req.on('error', reject); + }; + + req.on('data', onData); + req.on('end', onEnd); + req.on('error', onError); }); } @@ } catch (e) { - sendJson(res, 400, { - error: e instanceof Error ? e.message : 'bad request', - }); + const message = e instanceof Error ? e.message : 'bad request'; + sendJson(res, message === 'payload too large' ? 413 : 400, { + error: message, + }); }Also applies to: 99-102
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/genui/a2ui-playground/rsbuild.config.ts` around lines 33 - 47, readJsonBody currently buffers the entire request with no limit — add a maxBytes cap (either a constant or parameter) and track accumulated bytes while listening to 'data'; if the running total exceeds maxBytes immediately remove listeners, destroy the socket or call req.pause(), and reject with a distinct error (e.g., PayloadTooLargeError or an Error with a recognizable code). Update the POST handler that calls readJsonBody to catch that specific error and respond with status 413 and an appropriate message; also apply the same capped-buffer logic to the other equivalent JSON-body reader (the similar function at the other location referenced in the diff) so both endpoints guard against oversized bodies.
🧹 Nitpick comments (1)
packages/web-platform/web-core/ts/types/BTSChunk.ts (1)
35-35: 💤 Low valueLGTM — optional: remove the dead comment from the type definition.
The
// fetch: unknown,comment carries no structural meaning in a TypeScript function type and will silently mislead anyone counting positional parameters. The corresponding comments increateChunkLoading.ts(// 'fetch',and// tt.fetch,) already document the removal at the implementation level. Deleting the comment here keeps the type authoritative.♻️ Proposed cleanup
prompt: unknown, - // fetch: unknown, XMLHttpRequest: unknown,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web-platform/web-core/ts/types/BTSChunk.ts` at line 35, Remove the dead inline comment "// fetch: unknown," from the BTSChunk type definition in packages/web-platform/web-core/ts/types/BTSChunk.ts; locate the exported BTSChunk (or the function type declaration) and delete that commented parameter so the type signature remains authoritative and doesn't mislead about positional parameters.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@packages/genui/a2ui-playground/rsbuild.config.ts`:
- Around line 33-47: readJsonBody currently buffers the entire request with no
limit — add a maxBytes cap (either a constant or parameter) and track
accumulated bytes while listening to 'data'; if the running total exceeds
maxBytes immediately remove listeners, destroy the socket or call req.pause(),
and reject with a distinct error (e.g., PayloadTooLargeError or an Error with a
recognizable code). Update the POST handler that calls readJsonBody to catch
that specific error and respond with status 413 and an appropriate message; also
apply the same capped-buffer logic to the other equivalent JSON-body reader (the
similar function at the other location referenced in the diff) so both endpoints
guard against oversized bodies.
---
Nitpick comments:
In `@packages/web-platform/web-core/ts/types/BTSChunk.ts`:
- Line 35: Remove the dead inline comment "// fetch: unknown," from the BTSChunk
type definition in packages/web-platform/web-core/ts/types/BTSChunk.ts; locate
the exported BTSChunk (or the function type declaration) and delete that
commented parameter so the type signature remains authoritative and doesn't
mislead about positional parameters.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3452d448-9870-4828-8a06-771f84b730a7
📒 Files selected for processing (11)
.changeset/quirky-merkle-web-core-fetch.mdeslint.config.jspackages/genui/a2ui-catalog-extractor/src/cli.tspackages/genui/a2ui-catalog-extractor/src/index.tspackages/genui/a2ui-playground/lynx.config.tspackages/genui/a2ui-playground/rsbuild.config.tspackages/genui/a2ui-playground/turbo.jsonpackages/rspeedy/core/turbo.jsonpackages/web-platform/web-core/ts/client/background/background-apis/createChunkLoading.tspackages/web-platform/web-core/ts/types/BTSChunk.tsvitest.config.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/web-platform/web-core/ts/client/background/background-apis/createChunkLoading.ts
- packages/genui/a2ui-playground/turbo.json
…rder
Split out from the broader a2ui refactor — these are the non-
packages/genui/a2uichanges.build:lynxruns beforebuild; run payload-store GC on GET so the dev server can't keep stale payloads past TTL; drop@lynx-js/lynx-ui-inputto keep one React major across the workspace.//#buildas a dep ofbuildso the roottsc --buildfinishes before rspeedy'srslib buildd.ts generation needs the webpack plugins'lib/*.d.ts.fetchas a chunk-scope binding so BTS chunks reusewindow.fetch.Stacked on top of the broader a2ui refactor PR — the catalog.json subpath exports the playground imports here are introduced there.
Summary by CodeRabbit
Bug Fixes
New Features
Refactor
Chores
Checklist