From 4162783136d8379d924d0e591a60507b298fa229 Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Thu, 5 Mar 2026 13:05:45 +0100 Subject: [PATCH] review --- README.md | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 596284a..55871d3 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,21 @@ Remote functions, callable in the browser. - Telefunc is an RPC framework you can attach to your server. - It enables full-stack teams to adopt development patterns that - - Improve application security and performance, - And allow for rapid and flexible iteration. - - Telefunc makes it easy to add RPC to your server, but it's up to you to take advantage of the benefits RPC has to offer. + - Improve performance. + - Improve application security. + - Telefunc is easy to add RPC to your server — you can use Telefunc in parallel to your server. It's up to you how much RPC you want to use (you can progressively migrate back and forth between your server API endpoints and Telefunc). It's up to you to take advantage of the benefits RPC has to offer. > A [remote procedure call](https://en.wikipedia.org/wiki/Remote_procedure_call) (RPC) is when a \[...] computer programmer writes essentially the same code whether the subroutine is local to the executing program, or remote. -- RPC is a pattern for calling a remote function as if it were colocated with the client. No adapters or injection needed. - 1. Create named Telefunctions to call the database or do other backend work. +- RPC is a pattern for calling a remote function as if it were define in the client. Zero boilerplate. + 1. Create telefunctions (on the server) to call the database or do other backend work. 2. Import and call the function from your frontend, passing any required arguments (e.g., `await onNewTodo(text)`). 3. Telefunc creates a lightweight HTTP client to call your Telefunction, which returns only what the caller needs. ::: info - The term RPC is often used loosely to denote RPC-like approaches, like creating JSON endpoints. - - RPC-like describes an API that is schemaless — in contrast to RESTful and GraphQL APIs that always have a schema. + - RPC-like describes an API that is schemaless — in contrast to RESTful and GraphQL APIs which have a schema. ::: @@ -75,8 +76,8 @@ async function TodoList() { - You can think of RPC as a type-safe `fetch` call to a registered server-side function. ## Securing resources -- Always keep in mind that your **telefuncs are public**. - - A simple HTTP request could be used to extract, modify, or destroy user secrets or business-critical data from an unprotected function. +- Always keep in mind that your **telefunctions are public**. + - A simple HTTP request could be used to extract, modify, or destroy user secrets or business-critical data from an unprotected telefunction. - Add guards to Telefunctions to prevent illegitimate access. - Use `throw Abort()` to exit early if the client is unauthenticated or doesn't have permission to access the requested resource @@ -85,7 +86,7 @@ async function TodoList() { - Use `shield()` to validate incoming requests. - Don't forget to sanitize SQL arguments - Allows argument types to be inferred. - - Telefunc generates a `shield` automatically from TypeScript types, if available. + - Telefunc generates a `shield` automatically from TypeScript types. ```js // When using TypeScript, Telefunc automatically generates @@ -144,14 +145,14 @@ export async function MarkAllComplete() { } ``` -- To the consumer, these are all just functions, that do some async work. +- To the client, these are all just functions, that do some async work. - RPC abstracts away the request management. - This is nice, but the real value comes from the (framework-agnostic) colocation of browser and server code it enables. - You can write a Telefunction for each view and interaction, just as if you were loading data from local storage, but with all the power of a remote server. ### Design patterns - RPC is a full-stack pattern, and projects that use a monorepo will get the most out of the acceleration it has to offer. - - It allows you to colocate (and codevelop) highly-tailored server functions with client code. + - It allows you to colocate (and co-develop) highly-tailored server functions with client code. ```jsx // /Todos.jsx @@ -164,8 +165,9 @@ import { } from './Todos.telefunc.js' async function TodoList() { - // No need for an adapter, or "server only" flag - const todoItems = await onLoad() + // @ambergristle We'll implement useData() after we merged Dani's streaming PR + // No need for an adapter, or "server only" flag, works for both Client and Server components + const todoItems = await useData(() => onLoad()) async function onClick(form) { const text = form.input.value @@ -196,9 +198,12 @@ async function TodoList() { } ``` -- The naming convention enforces coupling, which is a cornerstone of keeping RPC calls lithe (i.e., avoiding function scope creep). +- The naming convention enforces coupling, which is a cornerstone of keeping RPC calls slim (i.e., avoiding function scope creep). - Opting out of the naming convention is perfectly fine, though we recommend having a clear reason for doing so. +> @ambergristle I didn't know the word "lithe" — I guess many non-native English speakers won't know it either + - Accordingly, RPC versioning is typically equivalent to project versioning. You will need a custom solution if you choose to use RPC with a monorepo. +> @ambergristle The best pattern here is to always deploy the frontend and JS server at the same time. Versioning telefunctions are a pain (even more than versionin RESTFul/GraphQL APIs because telefunctions change a *lot* more change generic RESTful/GraphQL APIs) — it's a core Telefunc philosophy: you develop frontend hand-in-hand with telefunctions. The backend can be decoupled using a three party setup: static files (frontend) + JS server for SSR + telefunctions (frontend) + backend (Java/Ruby/...) — this setup is commonly called "BFF" (backend-for-frontend). ## Schema-less vs schema-full - Comparing RPC to GraphQL or REST is a bit like comparing apples to oranges. They each make trade-offs to achieve different goals. @@ -215,12 +220,12 @@ async function TodoList() { ### Should I use it? > Premature optimization is the root of all evil. -> - *Turing Award winner, Donal Knuth* +> - *Donal Knuth, Turing Award winner* - In most cases you can start with RPC, and switch to REST or GraphQL as needed. - RPC enables you to stay lean, iterating faster and pivoting more flexibly. - Many apps will never need a public (or schema-full) API. - - RPC functions are just functions; migrating to REST or GraphQL is fairly straightforward. + - RPC functions are just functions; migrating to REST or GraphQL is straightforward. - There's a simple litmus test for whether RPC is the right solution: - If your goal is to enable third party developers to access your data, then you need a generic API and you'll have to use REST or GraphQL - - If your goal is to seamlessly add data and interactivity to a front-end, then RPC can improve DX and enable security and performance optimizations. + - If your goal is to seamlessly add data and interactivity to a front-end, then RPC improves DX and enable security and performance optimizations.