Cool! Y’all, this is obviously an RPC interface, but the point is that `import { onNewTodo } from './CreateTodo.telefunc.js'` is not, as written, an RPC. That transform, with seamless type support et cetera, is what makes this interesting. (If you think it’s interesting.)<p>I think it’s interesting; I experimented with a higher-magic version of this a couple of years ago. (It had continuations to support returning callbacks, could preserve object identity, and could lift inline anonymous functions to the server with some amount of intelligence.) My goal was to make the RPCs as close as possible to local async functions, which was really fun when it was working.<p>My experience was that for the simplest use cases, the ergonomics were unbeatable. Just drop a `@remote` tag into your TodoMVC frontend, and there’s your TodoMVC backend. But as soon as I had to look under the hood (for something as simple as caching behavior), the “just a function” interface was a distraction and I found myself wishing for a more conventional RPC interface.<p>(I think that might be why you tend to see this sort of magic more in the context of a full framework (such as Meteor), where all the typical use cases can be answered robustly. If you’re building your thing out of modules, cleverer abstractions usually mean more work overall to integrate everything and boring is better.)
Don't wanna break it for you - but calling even a remote function exactly is "using an API" (application programming interface).<p>I like the logo (or icon) they have, that masquerades it as some serious haskell (or some other functional PL) related project.<p>If it was this easy eveyone would be using RPC all over the place for many years already, and we'd have no HTTP and no train-load of other protocols.
I think this is neat having looked at the examples but isn't the title really just a game of semantics?<p>Non rigorously a web API is just the boundary across some service which you communicate with over (commonly) HTTP at the endpoints specified at that boundary by developers. I could write my own library that wraps those endpoints with functions that make the calls to them, in fact many libraries do just that.<p>What this takes care of, again kind of nicely, is dynamically and automatically generating that boiler plate as you write your API so you don't have to put in the work, but I think saying this isn't just a style of building an API is a little much.<p>Whether you're doing RPC, REST or whatever the boundary between your service and another service is it's API.
Our latest projects are built with RPC-style APIs and a BFF approach. We generate the TS client with Swagger and you effectively get strongly typed remote method calls.<p>So basically, we're at SOAP again. A few more years and maybe we'll come back to Remoting?
That's exactly how I program my APIs. The urls even look like '/rpc/FuncName'<p>The backend language I work with is Go, so there are "two" problems that need to be solved for this to work:<p>- Resolving function name and encoding/decoding arguments from a url to a real function call<p>- Representing Go structs as Typescript interfaces for the client side code to look like regular function calls with regular types and all that.<p>For the second part, I have a writeup about how I'm doing it: <a href="https://hasen.surge.sh/go-ts-type-bridge.html" rel="nofollow">https://hasen.surge.sh/go-ts-type-bridge.html</a><p>It's worth noting that the title of the OP website is wrong.<p>"Remote Functions Instad of API"<p>What do you think an API is? API does not stand for "HTTP Requests with JSON". It stands for "Application Programming Interface".
Google has a system called plaque in which you can express DAGs of operators (functions) and it handles all the scheduling and data flow between nodes running on a distributed cluster. This achieves much better performance efficiency at large distributed scale while also providing an easy to reason and debug program logic. I would expect more such distributed computer programming models with dedicated language/compiler toolchains in the future.
"Rock-solid<p>The source code of Telefunc has no known bug"<p>No known bugs does not "rock-solid" make. This claim alone makes this project very hard to take seriously.
We should revisit this before RMI<p><a href="https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing" rel="nofollow">https://en.wikipedia.org/wiki/Fallacies_of_distributed_compu...</a>
This is pretty neat. You write a function and then a library automatically creates wrapper libs to be called in a browser as if it’s a function call. A variety of frameworks have done similar - SOAP auto-generated Java libs come to mind - but this looks very clean and minimal.
Author of Telefunc here. I'm glad folks are finally taking RPC seriously.<p>RPC is back. Smarter, leaner, and stronger. (Sorry for the marketing jargon, but I really do believe that.)<p>Telefunc is still fairly young, you can expect a lot of polishing in the coming weeks/months. The high-level design is solid and I expect no breaking change on that end.<p>If you encounter any bug (or DX paper cut), please create a GitHub Issue and I'll fix it. I'm also the author of <a href="https://vite-plugin-ssr.com" rel="nofollow">https://vite-plugin-ssr.com</a> which also has no known bug, so I do take that claim seriously.<p>Let me know if you have any questions!
How does this compare to <a href="https://trpc.io/" rel="nofollow">https://trpc.io/</a> ?<p>Edit: so far, I'm preferring trpc, because it has support for zod and a few other libraries <a href="https://trpc.io/docs/v9/router" rel="nofollow">https://trpc.io/docs/v9/router</a><p>It seems like this library has its own bespoke syntax for types <a href="https://telefunc.com/typescript" rel="nofollow">https://telefunc.com/typescript</a>
Nice, I do something similar in a web framework I've been working on. All rendering happen on the server so the callbacks has to run there too. The onclick-handler in the DOM will trigger a POST to the server with an unique callback id.<p><pre><code> def self.get_initial_state(initial_count: 0, **)
{ count: initial_count }
end
def handle_decrement(_)
update do |state|
{ count: [0, state[:count] - 1].max }
end
end
def handle_increment(_)
update do |state|
{ count: state[:count] + 1 }
end
end
def render
<div class={styles.counter}>
<button on-click={handler(:handle_decrement)} disabled={state[:count].zero?}>
-
</button>
<span>{state[:count]}</span>
<button on-click={handler(:handle_increment)}>
+
</button>
</div>
end</code></pre>
Really odd how there is a dozen comments on RPC but no one mentioned gRPC for the web browser. Google goes in the reverse, where from both protobuf you autogenerate API boilerplate, client stubs and even REST-over-HTTP apis.<p><a href="https://github.com/grpc/grpc-web" rel="nofollow">https://github.com/grpc/grpc-web</a>
Whoa, that’s so similar to our project [1] it’s almost scary :)<p>How are errors handled though? What happens when you “throw Abort()”.<p><a href="https://github.com/samen-io/samen" rel="nofollow">https://github.com/samen-io/samen</a>
This reminds me of the ScriptMethod thing that asp.net has in the early days of AJAX. Was fun to use it, but didn’t stand the test of time. <a href="https://learn.microsoft.com/en-us/aspnet/web-forms/overview/older-versions-getting-started/aspnet-ajax/understanding-asp-net-ajax-web-services?source=recommendations" rel="nofollow">https://learn.microsoft.com/en-us/aspnet/web-forms/overview/...</a><p>Maybe there has been enough changes in the ecosystem now to be able to abstract network and write code that’s not too brittle.
We have a hand-rolled solution that does this and it's easily my favourite part of our codebase. Ours is with a Java backend so a bit more complicated but not much.<p>If you have a tightly coupled frontend and backend and no need for third party consumers of your API, I highly recommend it. Makes moving between frontend and backend such a pleasant experience with a well typed and defined interface.
The thing about people with experience, we love to tell you about the past. The cycles are all the same, technology A is created, it has some level of success, then something else (B) is adopted. A new generation of developers have only experienced B and due to its shortcomings reinvent A as C. And the cycle repeats over and over.
The DX is really cool, but I remembered protobuf exists <a href="https://buf.build/blog/connect-web-protobuf-grpc-in-the-browser" rel="nofollow">https://buf.build/blog/connect-web-protobuf-grpc-in-the-brow...</a><p>The marketing rhetoric of telefunc activates my skepticism, but I hope it's just me
This seems like a very nicely done implementation.<p>One negative: I don't think people realize how easy it will be to inadvertently include server side files in client side bundles.<p>The technical approach mitigates this and is well designed. But simply by blurring the lines it might result in sever side config bundled to the client.<p>(Easy to mitigate, just add a line to server side stuff which and destructs if it detects wrong environment)