Skip to content

Replace superjson with vendored Flight protocol encoder#45

Open
remorses wants to merge 1 commit into
mainfrom
replace-superjson-with-flight-encoder
Open

Replace superjson with vendored Flight protocol encoder#45
remorses wants to merge 1 commit into
mainfrom
replace-superjson-with-flight-encoder

Conversation

@remorses

Copy link
Copy Markdown
Owner

Summary

  • Removes superjson dependency entirely
  • Adds spiceflow/src/flight-data.ts — a ~230-line Flight-protocol data encoder/decoder written from scratch based on the wire format spec
  • Typed clients now receive text/x-flight responses (same wire format as React's renderToReadableStream) instead of superjson-wrapped JSON
  • Regular HTTP consumers still get plain application/json
  • Vary: x-spiceflow-agent header prevents CDN cache mixing between the two formats

Supported types: Date, Map, Set, BigInt, undefined, NaN, ±Infinity, -0, RegExp, Symbol.for(), Error, URL

Verification: pnpm tsc ✅, pnpm check-entry ✅ (263KB), 554 tests pass

Removes the `superjson` dependency and replaces it with a ~230-line
Flight-protocol data encoder/decoder (`flight-data.ts`) that produces
the same wire format as React's `renderToReadableStream`.

The typed client (`createSpiceflowClient` / `createSpiceflowFetch`) now
receives `text/x-flight` responses instead of superjson-wrapped JSON
when the `x-spiceflow-agent: spiceflow-client` header is present.
Regular HTTP consumers still get plain `application/json`.

Wire format prefixes:
  $D<iso>     Date
  $Q<id>      Map (entries at chunk id)
  $W<id>      Set (items at chunk id)
  $n<digits>  BigInt
  $undefined  undefined
  $NaN, $Infinity, $-Infinity, $-0  special numbers
  $R<regex>   RegExp
  $S<key>     Symbol.for()
  $Z<json>    Error
  $l<href>    URL

Changes:
- new `spiceflow/src/flight-data.ts` — encoder + decoder, zero deps
- new `spiceflow/src/flight-data.test.ts` — 18 tests covering all types
- `spiceflow.tsx` — `superjsonSerialize` → `serializeResponse`, uses
  `flightEncode` for RPC requests, `JSON.stringify` for plain requests.
  Renamed `disableSuperJsonUnlessRpc` → `useFlightEncoding` (deprecated
  alias kept for backward compat)
- `client/shared.ts` — `superjsonDeserialize` → `flightDecode`, added
  `text/x-flight` content-type handling in `parseResponseData`
- `client/index.ts` — same content-type switch
- `vite.tsx` — removed `spiceflow > superjson` from optimizeDeps
- `package.json` — removed superjson dependency
- Added `Vary: x-spiceflow-agent` header to prevent CDN cache mixing
- check-entry passes (263KB bundle, no superjson)
- All 554 tests pass

Session: ses_2562f1c11ffeDC9ypyA2F116GL
@vercel

vercel Bot commented Apr 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
integration-tests Error Error Apr 20, 2026 8:42am

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20cf4dab26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 2902 to 2904
'event: message\ndata: ' +
self.superjsonSerialize(chunk, false, request) +
self.serializeResponse(chunk, false, request) +
'\n\n',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prefix every Flight row as SSE data lines

When serializeResponse returns Flight payloads with multiple rows (for example values containing Map/Set), this concatenation writes only the first row after data: and leaves subsequent rows as bare SSE lines. EventSource parsers ignore non-data fields, so streamed chunks are truncated/corrupted before flightDecode runs. This breaks streamed server action/subscribe payloads that include chunked Flight types.

Useful? React with 👍 / 👎.

Comment on lines 370 to 374
case 'text/event-stream':
data = streamSSEResponse({
response,
map: (x) => tryParsingSSEJson(x.data),
map: (x) => tryParsingSSEJson(x.data, true),
executeRequest,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve JSON fallback for non-Flight SSE events

This path now forces SSE message parsing to Flight mode, but many custom text/event-stream handlers emit plain JSON strings. In that case flightDecode fails and the client returns the raw string instead of parsed JSON, which is a behavioral regression from the previous parser. Please keep a JSON fallback when Flight decoding fails (or gate Flight mode explicitly) so existing JSON SSE endpoints still work.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant