DEV Community

loading...
Cover image for No more rest πŸš€

No more rest πŸš€

epavanello profile image Emanuele Pavanello ・1 min read

Hello guys!

Here the GitHub Repo and here the NPM package πŸ“¦

If you, like me, don't like to pass all day defining new rest API and calling them from the frontend in a verbose way, you can start to use my new NPM package no-more-rest that allows you to expose your API directly from your server to be called transparently from your client with the IntelliSense support.

If you like the idea star the project and collaborate with me πŸ’—

A small example of the potential

// server/myApi.js

export function doLogin(username, password) {
  return username == "admin" && password == "admin";
}

export function getLoggedUsers() {
  return ["Elon Musk", "admin"];
}

Enter fullscreen mode Exit fullscreen mode
// server/server.js

import express from "express";
import { expose } from "no-more-rest";

import * as myApi from "./myApi";

const app = express();
expose(app, myApi);

app.listen(8000);
Enter fullscreen mode Exit fullscreen mode
  • Add this npm script to your package to generate the proxy script for the client from the exposed module
"scripts": {
   "sync-api": "no-more-rest --input myApi.js --output-dir ../your-client-path/ --watch"
}
Enter fullscreen mode Exit fullscreen mode
  • Import in the client your generated proxy and use it as if it were on your backend.
// client/index.js

import { doLogin, getLoggedUsers } from "./generatedProxy";

doLogin("admin", "admin")
  .then((result) => {
    if (result) {
      alert("Login success");

      getLoggedUsers().then((users) => {
        alert("The logged users are: " + users.join(", "));
      });
    } else {
      alert("Login failed");
    }
  })
  .catch(() => {
    alert("Network error");
  });

Enter fullscreen mode Exit fullscreen mode

Discussion (7)

pic
Editor guide
Collapse
oguimbal profile image
Olivier Guimbal • Edited

Hi !

Just to sound a bit pedantic, the name for such a pattern is called RPC (Remote Procedure Call)...
It's seducing, and actually older than the web itself, but its not without its drawbacks.

Collapse
jackmellis profile image
Jack

We actually went from rest to rpc and back to rest again. But I do like the potential here to generate and strongly type your endpoints between client and server. Interesting idea

Collapse
epavanello profile image
Emanuele Pavanello Author

The roadmap about this library consider exactly this point.
Soon I need to integrate another ast parser for typescript to handle e mirror the parameters and the return type to be strongly typed on server and client πŸ’ͺ🏻

Thread Thread
oguimbal profile image
Olivier Guimbal • Edited

I dont want to spoil you the surprise, but here is a catch, with hidden RPC calls/proxies.
You'll soon enough want some kind of shared state between client and server (session authentication, ...). This is often carried by headers of your http requests. But by abstracting away the http calls, you have removed the possibility to your users to tweak those headers. If you dont want your users to be foreced to pass an extra argument to all their methods, you surely could devise some kind of static method get/setState() that allows to carry the information you need accross calls, but this does not play well with async/await, nor with unit testing, and it hides things to your user, tending to bloat your code.

Speaking of hiding, another problem you will face is that the lines between server & client will be a bit more blurred, meaning that it (arguably) leads some less experienced developpers to adopt confusing development habits. Sharing methods is fine, but you've put your finger in a mechanism that will probably will make you want to add support for shared object instances. And that's a rabbit hole you dont want to go down into.

It also leads to problems with API versioning, N+1 problems, and much more.

Being a seducing pattern, RPC is being reinvented every now and then. Like you, and like many of us, I've been there a couple of years ago, and everyone seems to be convinced at one point that it is a silver bullet... Trust me, I've dealt with too many RPC frameworks, and faced too many failures with this pattern (I'm watching at you, Dotnet Remoting) not to emphasis that RPC is neat, but has its drawbacks.

Now, I dont want to sound paternalistic by telling some kind of absolute truth: There is none to be told. That's just my harshly acquired opinion, which is worth what it is worth: Nothing more than the one of any of us😊 I strongly encourage you to push this experiment, and even make a production ready library out of it... it might be useful to plenty of people not thinking like me ! ...worst case scenario: you'll learn from it.

Collapse
oguimbal profile image
Olivier Guimbal • Edited

You might also want to try GraphQL with graphql code generator for that 😊

Thread Thread
epavanello profile image
Emanuele Pavanello Author

The idea came exactly from this utility, whiteout the overhead of graphql πŸ˜…

Collapse
epavanello profile image
Emanuele Pavanello Author

Thanks for your feedback,
I know, the pattern is RPC, but here all the things are hidden by the generator and the user can use these apis transparently like the others functions.

Also graphql generator has this similar pattern, but you can’t use only one technology because the graphql schema and query language.