What's the correct way to wrap server functions?
I have a bunch of duplicate authentication and validation logic in my server functions that I'd like to extract to a utility like
createAuthenticatedAction
that authenticates the user before running the server callback passed to it, but every time I create any wrapper around "use server" the compiler stats complaining. Where should I put a "use server" directive if I only want this helper to run on the server?4 Replies
from my understanding "use server" should only make a function an RPC, and it should only do it if you're not on the server already (otherwise it's just invoked) so my reasoning is I need a "use server" both inside my helper and inside the callback I pass to it, but that makes the compiler completely hang when I actually trying using it inside a form, the page will not load at all but no errors are logged to the console
A minimal example would be nice to figure out what's going on. I had some trouble figuring out where 'use server' belongs too and had similar experiences (weird error messages and things mysteriously just not working), but I resolved these by starting from the
with-auth
SolidStart template and adapting it for my needs.
Basically I found out that these forms are "safe":
I have all my loaders in loaders.ts and actions in actions.ts, and use them in route tsx files like this:
There's probably plenty of ways to structure your project but this works for me.
And route protection works with helpers like this:
which is then called from those loader and action functions that need to be protected.thanks for your help!
a practical example in this case is basically how to craft a function like
createAuthenticatedAction
that wraps action
from solid-router
so that i dont have to always do auth checks inside each action (which i've been doing for like 50 actions already)
i figured out a way which is defining the actual implementation of the action in a separate file with a top-level "use server" and using the single export inside action
, so that works. only annoying thing is that i need to split two files just to create an actionI see where the problems with
createAuthenticatedAction
could come from. I tried to just wrap action
in a function that just calls the callback and it breaks with "Error: callback is not defined". Probably because action
lives in the browser and function with use server
lives on the server, and you can't call callback
(which again lives in the browser) from the server. Not 100% sure what's going on but that's my theory.
So, I guess your top-level "use server" or some other solution is the way around this.
Adding "use server" to wrappedAction won't work either since the client can't just call server functions, it needs action
for that.
I'm starting to think that "use server" is maybe not the best abstraction to split client and server code, since there needs to be some bundler magic to facilitate communication between those two worlds, and your usual assumptions (such as "if I have a callback, I can simply call it") won't necessarily hold in that magic land