DEV Community

Cover image for I've made a RESTful HTTP client which will make your life much easier
LiorVainer
LiorVainer

Posted on

I've made a RESTful HTTP client which will make your life much easier

Most of you reading this are probably already familiar and using axios for making HTTP requests from your application to an API, whether it is your own API or an external one.

Today I want to introduce you to 4rest, the new npm package I built, on top of axios, which is designed to help you set up all of your app's functions for making HTTP requests to API, easily, quickly, and make them as organized as possible by splitting them to services based on API's data models.



Let's see a basic usage example:

1) First of all you create a Forest Instance with your API base URL and other relevant configuration.

import forest from "4rest";

export const instance = forest.create({ axiosSettings: { baseURL: "http://localhost:5000" } });
Enter fullscreen mode Exit fullscreen mode

2) Then we create a Forest Service using the instance we just made.

import { instance } from "./forestInstance";
import { UserWithId, User } from "./types";

export const userService = instance.createService<UserWithId, User>("user");
Enter fullscreen mode Exit fullscreen mode

That's It!
Just by doing these 2 simple steps we got our self a total of 9 different functions for making calls to an API with types for request payload and response data on them, including:

  • getAll
  • getById
  • deleteAll
  • deleteById
  • post
  • patch
  • patchById
  • put
  • putById



Let's see a few examples of using the service methods in our app:

  • GET
// GET http://localhost:5000/user
async function getUsers() {
  const users: User[] = (await userService.getAll()).data;
}

// GET http://localhost:5000/user/:id
async function getUserById(id: string) {
  const user: User = (await userService.getById(id)).data;
}
Enter fullscreen mode Exit fullscreen mode
  • POST
// POST http://localhost:5000/user
async function createUser(newUser: User) {
  const userCreated: User = (await userService.post(newUser)).data;
}
Enter fullscreen mode Exit fullscreen mode
  • PATCH
// PATCH http://localhost:5000/user
async function updateUser(partialUser: Partial<User>) {
  const updatedUser: User = (await userService.patch(partialUser)).data;
}

// PATCH http://localhost:5000/user/:id
async function updateUserById(id: ObjectId, partialUser: Partial<User>) {
  const updatedUser: User = (await userService.patchById(id, partialUser)).data;
}
Enter fullscreen mode Exit fullscreen mode

This is only the most basic example of how you use 4rest but there are a lot more options to configure service and instance, which let you do much more than shown in this article like zod payload and response data type validations, methods routes configuration, custom service with custom methods, requests onSuccess and onError handling and more.

See more:

4rest Full docs and source code on Github

4rest NPM Page

Hope you will find this package useful.
I would like to hear your feedback on the package and suggestions for future improvement 😀

Discussion (8)

Collapse
ecyrbe profile image
ecyrbe

I like the CRUD generation feature.
Nice work.
I also made one, but completely typescript oriented , that does not hide the routes behind functions : it's named zodios.
I might steal your idea for CRUD auto generation.

Collapse
liorvainer profile image
LiorVainer Author

Hey, thank you for the nice feedback, I checked out your package as well and really liked it's dx and features. My plan was to do a react-query based plugin for 4rest as well. You really inspired me with zodios. Maybe we can even collaborate on some features :)

Collapse
ecyrbe profile image
ecyrbe

Hello, quick update.

I like both your features of named enpoints and crud generattion.
so i added them both to zodios.

You can check it in these tests and documentation

Thread Thread
liorvainer profile image
LiorVainer Author • Edited on

Hi, I have seen those features you have added and you really did a very good job. Few things I would like to recommand you to do as well are changing the names of the getUser, deleteUser and maybe even updateUser to getUserById and etc or at least give the user the option to choose its own default alias extensions which will be used for every asCrudApi function.
Second of all, let the user an option to valdiate the id he sends out to the API as param, for example to validate it represents ObjectId string or such.
Also, think about maybe splitting the api instance to services based on the DataModel of the api similirally to how you have done with the asCrudApi function but to make it actually diffrrent services in order for the user to get diffrenet autocomplete when calling api based on the service he wants and not just by url. Lastly, give the user to make his own scheme validation decisions based on the method he is calling to, for example: change only the getUsers validation to be of interface including the following keys: result of type User array scheme and amount of type number.

Thread Thread
ecyrbe profile image
ecyrbe • Edited on

Thank you for the feedback,

  • naming is a matter of taste, and i would prefer evoid taking decisions in the place of the end user. But i also would like to evoid making zodios asCrudApi a helper monster that tries to fit everyone needs. So maybe, i'll instead add guidance in the documentation on how to write your own helpers like asCrudApi.
  • As of today, i did not add runtime validation for parameters. I would prefer enforcing typescript string validation for this use case (see typescript template type literals that can typecheck for you your strings at compile time). But if you have a use case where we can't check parameters at compile time, i might change my mind.
  • For splitting the API, take a look at dev.to directory in examples. it's called asApi and can be used to code split your deplarations by models.
  • validation customization is already possible per endpoint. Just not for asCrudApi. i would also suggest the user to create is own helper if his use cases are too complex or even not use one and use zodios already generic api declaration for this use case.
Collapse
liadaltiff profile image
Liad Altif

Super cool, very useful and unbelievably easy 👌 😀 👍

Collapse
itaylisaey profile image
ItayLisaey

Nice 👍🏼, looks very useful!

Collapse
nitzanhen profile image
Nitzan Hen

Seems like a really handy tool!

Great job, keep it up 🙌