The central aspect here is that hello() is always executed on the server side, which enables hello() (and telefunctions in general) to use server-side utilities such as SQL and ORMs.
ORM & SQL
As we have seen in the previous section, telefunctions always run on the server-side and can therefore use server utilities such as SQL and ORMs.
.telefunc.js files are guaranteed to be loaded only on the server-side. You can therefore save secret information, such as the database passwords, in .telefunc.js files.
We collocate and name the TodoList.telefunc.js file after TodoList.jsx, which is a practice we recommend and explain at Guides > Event-based telefunctions.
While the examples here use JSX, Telefunc works with any UI framework (React, Vue, Svelte, Solid, ...).
Telefunctions can also be used to mutate data:
RPC enables your frontend to tap directly into the full power of the server such as SQL and ORMs. For most use cases it's simpler, more flexible, and more performant than REST and GraphQL.
GraphQL and RESTful can be better than RPC if:
you want to give third parties generic access to your data, or
you are a very large company with highly complex databases.
In other words,
the hello() function is always executed on the server-side
while the browser-side can remotely call it in a seamless fashion.
You can also call telefunctions from the server-side, in which case the telefunction is directly called (without making an HTTP request).
Telefunctions need protection
Your telefunctions can be remotely called not only by your frontend, but by anyone.
For example, anyone can call the hello() telefunction we've seen in the previous section by opening a Linux terminal and making this HTTP request:
Thus, such telefunction is problematic:
This run() telefunction essentially exposes the entire database to the world as
anyone can make this HTTP request:
Always keep in mind that your telefunctions are public and need protection.
throw Abort()
As we've seen in the previous section,
the following telefunction isn't safe.
But we can use throw Abort() to protect it:
Telefunctions can access contextual information by using getContext().
We can use throw Abort() to avoid any forbidden telefunction call.
We essentially use throw Abort() to implement permission: only a logged-in user is allowed to fetch its to-do items.
We talk more about permissions at Guides > Permissions.
In principle, we could also throw new Error() instead of throw Abort() as it also interupts the telefunction call. But we recommend throw Abort() as it comes with many conveniences.
If, upon aborting a telefunction call, you want to pass information to the frontend then use return someValue or throw Abort(someValue), see Guides > Permissions.
shield()
Since telefunctions are public and can be called by anyone, we cannot assuming anything about arguments. We can use throw Abort() to ensure the type of telefunction arguments:
For more convenience, we can use shield() instead:
Not only does shield() call throw Abort() on our behalf, but it also infers the type of the arguments for TypeScript and IntelliSense.
Any of your telefunctions can be called by anyone, at any time, and with any arguments. One way to think about it is that any random telefunction call can happen at any time.
You should always protect your telefunctions, even when your frontend calls a telefunction only in a certain way. For example:
Because the frontend shows the delete button only to admins, we can assume the user to be an admin whenever the frontend calls onDelete().
But we still need to use throw Abort() in order to protect the telefunction against calls that don't originate from the frontend.