Conversation
🦋 Changeset detectedLatest commit: fce37a8 The changes in this PR will be included in the next version bump. 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 |
✅ Deploy Preview for solid-start-landing-page ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
commit: |
packages/start/src/config/index.ts
Outdated
| middleware?: string; | ||
| serialization?: { | ||
| // This only matters for server function responses | ||
| mode?: 'js' | 'json'; |
There was a problem hiding this comment.
When possible, add a plugins option here that we can load into the serializer. The only problem is how do we bridge it from the config to the runtime (do we need a "runtime" config API?)
There was a problem hiding this comment.
The non-magical way I could think of is to add this as an option to createHandler in entry-server.tsx 🤔
There was a problem hiding this comment.
either that or an "entry" file for configs I suppose.
There was a problem hiding this comment.
Wouldn't we be able to set an environment variable, then use something like
const serialization = import.meta.env.VITE_SOLIDSTART_SERIALIZATION;
if (["js", "json"].includes(serialization ?? "js")) {
// initialize seroval mode
} else if (serialization) {
const [serializer, deserializer] = await import(serialization);
}There was a problem hiding this comment.
@atk Not exactly this API in mind. I'm not trying to override seroval, I'm more of trying to think of an idea to allow incorporating 3P seroval plugins
| URLSearchParamsPlugin, | ||
| URLPlugin, | ||
| ]; | ||
| const MAX_SERIALIZATION_DEPTH_LIMIT = 64; |
There was a problem hiding this comment.
Seroval has a default limit of 1000, but that's because of my poor judgment. Will probably port this default back.
| // TODO(Alexis): move to serializeToJSONStream | ||
| body: await serializeToJSONString(args), | ||
| // duplex: 'half', | ||
| // body: serializeToJSONStream(args), |
There was a problem hiding this comment.
bleeding edge. TypeScript doesn't have the duplex property defined yet so this one is invalid for now. On top of that, this doesn't actually "stream" as in the server responds immediately on request. What the browser does currently is buffer the entire stream then sends in bulk (technically speaking, duplex: half describes this behavior, duplex: full describes the desired behavior).
Once all browsers are ready for this (and also TypeScript), we can swap to duplex: full
| }); | ||
| } else if (contentType?.startsWith('application/json')) { | ||
| parsed = await event.request.json() as any[]; | ||
| } else if (request.headers.has('x-serialized')) { |
There was a problem hiding this comment.
- We no longer use the
application/jsonmime type for seroval - We wanted to distinguish seroval-based body from JSON body. Did I just add a new feature?
7932c2f to
25b3f44
Compare
| ...options, | ||
| // TODO(Alexis): move to serializeToJSONStream | ||
| body: await serializeToJSONString(args), | ||
| // duplex: 'half', |
There was a problem hiding this comment.
|
Testing this branch on my project and uploading files through The error is throwed at this line: https://github.com/hattipjs/hattip/blob/15aa5ae4dec4478aa07785c85b2c85d4a753d0af/packages/base/multipart/src/form-data.ts#L79 It looks like with the changes in this branch, the upload doesn't set proper multipart boundaries anymore 🤔. The condition leading to the throw is (Reference: https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html) |
|
Seemed like explicit definition of |
|
Whats the latest on this pr? |
|
@brenelz nothing much, but I haven't tested since the last commit lol |
820baec to
db436df
Compare
db436df to
0defa47
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Seroval serialization layer for server functions with an opt-in response mode (js vs json, defaulting to json) to improve CSP compatibility, and expands the server-function transport to support more body types.
Changes:
- Bumped
seroval/seroval-pluginsto^1.5.0. - Added a new serialization module plus shared body-format helpers to support JS-stream vs JSON-stream response deserialization and additional body types (FormData, File, Blob, ArrayBuffer, Uint8Array, etc.).
- Added new e2e/demo routes and tests for server-function round trips.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Updates lockfile for seroval/seroval-plugins upgrade. |
| packages/start/package.json | Bumps seroval and seroval-plugins dependency ranges. |
| packages/start/src/config/index.ts | Adds serialization.mode option and injects SEROVAL_MODE define. |
| packages/start/src/server/serialization.ts | Introduces streaming serializer/deserializer utilities for JS and JSON modes. |
| packages/start/src/server/server-functions-shared.ts | Adds body-format header constants + helpers for encoding/decoding request/response bodies. |
| packages/start/src/server/server-runtime.ts | Updates client runtime to use the new serialization/body extraction helpers. |
| packages/start/src/server/server-functions-handler.ts | Updates server handler to use the new serialization + body extraction helpers. |
| apps/tests/src/routes/server-function-ping.tsx | Adds a basic server-function route for testing. |
| apps/tests/src/routes/server-function-form-data.tsx | Adds a FormData/File server-function route for testing. |
| apps/tests/src/routes/server-function-blob.tsx | Adds a Blob server-function route for testing. |
| apps/tests/src/e2e/server-function.test.ts | Adds new e2e tests for ping and FormData server functions. |
| .changeset/plenty-geese-enter.md | Adds changeset entry for the feature. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| test("should build with a server function w/ form data", async ({ page }) => { | ||
| await page.goto("http://localhost:3000/server-function-form-data"); | ||
| await expect(page.locator("#server-fn-test")).toContainText('{"result":true}'); | ||
| }); |
There was a problem hiding this comment.
A new Blob server-function route was added (/server-function-blob), but there is no e2e coverage for it here. Consider adding an e2e test for the blob round-trip (or removing the route if it's not intended to be exercised) so the new body-format handling stays covered.
| }); | |
| }); | |
| test("should build with a server function w/ blob data", async ({ page }) => { | |
| await page.goto("http://localhost:3000/server-function-blob"); | |
| await expect(page.locator("#server-fn-test")).toContainText('{"result":true}'); | |
| }); |
| export const enum BodyFormat { | ||
| Seroval = "0", | ||
| String = "1", | ||
| FormData = "2", | ||
| URLSearchParams = "3", | ||
| Blob = "4", | ||
| File = "5", | ||
| ArrayBuffer = "6", | ||
| Uint8Array = "7", | ||
| } |
There was a problem hiding this comment.
BodyFormat is declared as a const enum, but this package is built with tsc + isolatedModules: true (and likely esbuild for TS transpilation). const enum will cause compilation/transpilation failures in isolated module builds. Use a regular enum, or replace it with a const object (as const) plus a string-literal union type.
| }); | ||
| } | ||
|
|
||
| class SerovalChunkReader { |
There was a problem hiding this comment.
Just to get a better understanding of the thinking here, why should this and getHeadersAndBody be part of SolidStart and not Seroval directly?
There was a problem hiding this comment.
The encoding is specific to Start. Seroval isn't tied to the Web APIs
Pretty straight forward. Adds an opt-in mode to use json mode (set by default) for seroval streaming, this is because the js stream is affected by CSP.
Also adds streaming support for client-to-server communication (except for url-encoded requests), assuming that the browser it comes from supports it.