Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature?]: Custom Seroval plugins #1474

Open
2 tasks done
wszerad opened this issue May 12, 2024 · 8 comments
Open
2 tasks done

[Feature?]: Custom Seroval plugins #1474

wszerad opened this issue May 12, 2024 · 8 comments
Labels
question Further information is requested

Comments

@wszerad
Copy link

wszerad commented May 12, 2024

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Summary 💡

It would be useful to be able to define a list of your own plugins used by Seroval, as far as I know, this is the only way to properly parse custom classes.

Examples 🌈

No response

Motivation 🔦

I'm struggling with trying to return the ObjectId (used in MongoDb) from a server function, instance cannot be parsed by Seroval.

@wszerad wszerad added the enhancement New feature or request label May 12, 2024
@leo1553
Copy link

leo1553 commented Jan 11, 2025

I took some time to find the code where the seroval plugins are specified and found that in the server-runtime.ts contains a plugin list as a module constant. Then tracked the function call chain until I reached some function or option that could receive the custom plugins, but as I don't really know the code base, I'm not sure if i tracked it right:

From runtime/server-runtime.ts

runtime/server-runtime.ts:

  • fetchServerFunction declares a response const that if provided with some args that are not FormData nor URLSearchParams, will use seroval to stringify the args as the response body.
  • createServerReference returns a Proxy to the fn argument that traps get operations at fn. When the called fn property name is withOptions, which looks to be a function, and the method for the request is GET, will use seroval to stringify the withOptions function args to be sent as a query param. This operation then calls fetchServerFunction.

createServerReference is also defined at server-fns-runtime, that does not use seroval.

config/server-component.js:

  • server returns an array of vinxi plugins, which one of them is a vinxi directive that contains two transforms that looks to contain two vinxi's "ExportsPlugin"s (shimExportsPlugin and decorateExportsPlugin) that refer back to server-runtime's fetchServerFunction with some kind of dynamic import.
  • server is then exported as the second element in the serverComponents const.

config/index.js

  • If using experimental islands, will use server when defining the plugins for the routers in ssr and server-fns.

From runtime/server-handler.ts

runtime/server-runtime.ts:

  • serializeToStream returns a ReadableStream, that when started calls seroval crossSerializeStream with the plugins.
  • handleServerFunction uses serializeToStream to send the response to the client if some conditions are met or if the somewhere the code breaks.
  • handleServerFunction is exported as a h3 eventHandler handler.

config/index.js

  • Seems to use the h3 event handler wrapping handleServerFunction as the handler for server-fns.

-

Both code flows seems to use seroval very deep in the call chain, but both of them starts at config/index.js which looks up app.config.[jt]s. Therefore my idea is to provide a start config field to point to a module default exporting an array of seroval plugins that could be dynamically loaded and used by each of the scenarios described above.

This seems to be the very start of the SolidStart runtime, and I'm not sure how dynamic module loading could interfere in code splitting. If some contributor could give me an idea of how to implement this without breaking the hole project, I could give it a try 😄.

@lxsmnsyc
Copy link
Member

I haven't really given a response here since the discussion for this remained with Ryan but user-based plugins is definitely in heavy consideration, it wasn't just considered back then because of potential security risks. No worries though, we will revisit this in the future.

@agoldstein03
Copy link

Hello! Checking back in on this thread now that v1.1.0 is out. I'm interested in adding a few server function/Seroval customization options, would a PR be considered at the point?

@atilafassina
Copy link
Member

Hello! Checking back in on this thread now that v1.1.0 is out. I'm interested in adding a few server function/Seroval customization options, would a PR be considered at the point?

Hey @agoldstein03 !!

About extending Seroval, I'll let @lxsmnsyc reply, but I imagine he'll need to know what kind of customization you're planning to add.

But I can say we'd be appreciative of any contribution that address a general use-case or improves the DX.
The best way to prevent wasting your time would be to create an issue with the proposed idea and we can iterate on that.

@atilafassina atilafassina added question Further information is requested and removed enhancement New feature or request labels Feb 12, 2025
@uerkw
Copy link

uerkw commented Feb 26, 2025

Figured I would bump this thread, as I'm reaching a similar need/use-case where I would like to define some schema/structure to the objects that I return (and serialize) from server functions.

For how I'd theoretically use this, I would probably see it being defined in the Solid config in the Vite plugin. I'm not sure of a better way to inject these, but I could see a config option for optional extensions to seroval being used there. I can foresee this being a little tricky to get passed to seroval, but I think it would be useful for devs to drop in some kind of common format into it and let seroval automatically pick up how to parse all your schemas.

Right now I have a lot of APIs I'm trying to use in solid, and end up having to structured clone the objects they return so that I can properly serialize them.

Does seroval expose these in a simple format? I'm interested in how we can get Solid to properly inject plugins like these so that there is a common path for class serialization

@lxsmnsyc
Copy link
Member

For how I'd theoretically use this, I would probably see it being defined in the Solid config in the Vite plugin.

Not an effective place since Vite is a bundler runtime, not the app runtime, where the serialization happens. We'll most likely introduce a place to set this up.

Does seroval expose these in a simple format? I'm interested in how we can get Solid to properly inject plugins like these so that there is a common path for class serialization

Not really, but it's going to be exposed in Solid. We are also planning to renovate the whole serialization stuff so it is in sync with Solid (currently it isn't)

@AlexErrant
Copy link
Contributor

Possible plugin feature request: can Seroval eventually support serverside validation (using Standard Schema)? Related.

@lxsmnsyc
Copy link
Member

lxsmnsyc commented Mar 6, 2025

@AlexErrant it's not seroval that handles server-side validation though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

7 participants