SkillAgentSearch skills...

4rest

REST Client built on top of axios and zod packages

Install / Use

/learn @LiorVainer/4rest
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

</br> <img src="https://raw.github.com/LiorVainer/4rest/main/assets/4rest.svg"> </br> </br>

4REST

test coverage npm version install size minizipped size License

<strong>4rest (Forest)</strong> is a promise based, HTTP REST Client built on top of axios and zod packages suggesting easy to use and extensively customizable, extendable and configurable services with built in CRUD methods and type safe request functions to API.

<br />

Installation

Using npm

  npm install 4rest

Using yarn

  yarn add 4rest
<br /> <h2>Table of Contents</h2> <ul> <li><a href="#motivation">Motivation</a></li> <li><a href="#features">Features</a></li> <li><a href="#usage">Usage / Examples</a> <ul><li><a href="#usage/basic">Basic Service</a></li></ul> <ul><li><a href="#usage/extended">Extended Service</a></li></ul> <li><a href="#config">Configuration</a> <ul><li><a href="#config/instance">Instance</a><ul><li><a href="#config/instance/instance-creation">Instance Creation</a></li><li><a href="#config/instance/axios-instance-access">Axios Instance Access</a></li></ul></li></ul> <ul><li><a href="#config/service">Service</a></li><ul><li><a href="#config/service/routes">Methods Routes</a></li></ul> <ul><li><a href="#config/service/request-config">Request Config</a></li> <li><a href="#config/service/payload-key">Payload Data Key</a></li><li><a href="#config/service/handlingFunctions">On Success / On Error Handling</a></li><li><a href="#config/service/validation">Zod Validation</a></li></ul></li></ul> <ul><li><a href="#config/methods-creator">Methods Creator Helper</a></li></ul> <li><a href="#types">Types</a> <ul><li><a href="#types/service-generics">Service Generics</a></li><li><a href="#types/service-method-metadata">Service Method Metadata</a></li><li><a href="#types/on-success">OnSuccess Function</a></li><li><a href="#types/on-error">OnError Function</a></li><li><a href="#types/validation">Validation</a></li></ul></li> <ul></ul></ul> <br />

<a id="motivation"> <h2>Motivation</h2></a>

The package was created to help developers to get their requests functions from client to API up and runing quickly and comfortably, as well as making configuration for requests all centeralized in one spot at the code base of the app. Using the package, you can divide your requests functions to API to different services based on the models (data structures) of the API. When you have initiallized your service, you can make request to API at every place in your app with type safety based on the service configuration.

Note: The package was meant to be used with <strong>rest</strong> API only and it <strong>does not support graphql.</strong>

<br />

<a id="features"> <h2>Features</h2></a>

💎 <strong> Service with built in CRUD Methods: </strong>

  • getAll
  • getById
  • deleteAll
  • deleteById
  • post
  • patch
  • patchById
  • put
  • putById
<br />

🎨 <strong>Extended Services</strong> with option to add additional methods extending out CRUD methods that comes built in with the base service you create

🧱 <strong>Services Built</strong> on fully configurable axios Instance

⚙️ <strong>Convenient Configuration</strong> with custom routes, request configuration, and payload data (body property of request) key custom define. all of that configuration is per service or can be set globally on fetching instance as well

🛡️ <strong>Data Type Validation</strong> - API fetching requests, payloads and responses data validation with zod schemas

🧪 <strong>Test Proof</strong> - 4rest has 100% test coverage

<br />

<a id="usage"> <h2>Usage / Examples</h2></a>

<a id="usage/basic"> <h3>🧱<u>Basic</u></h3></a>

1) Create Instance

import forest from "4rest";

const instance = forest.create({ baseURL: "http://localhost:5000" });

2) Create Service

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

const userService = instance.createService<UserWithId, User>("user");

3) Use Service

  • GET

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

// GET http://localhost:5000/user/:id
async function getUserById(id: string) {
  const user: User = await (await userService.getById(id)).data;
}
  • DELETE

// DELETE http://localhost:5000/user
async function deleteAllUsers() {
  const usersDeleted: User[] = await (await userService.deleteAll()).data;
}

// DELETE http://localhost:5000/user/:id
async function deleteUserById(id: ObjectId) {
  const userDeleted: User = await (await userService.deleteById(id)).data;
}
  • POST

// POST http://localhost:5000/user
async function createUser(newUser: User) {
  const userCreated: User = await (await userService.post(newUser)).data;
}
  • PATCH

// PATCH http://localhost:5000/user
async function updateUser(partialUser: Partial<User>) {
  const updatedUser: User = await (await userService.patch(partialUser)).data;
}

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

// PUT http://localhost:5000/user
async function updateUser(partialUser: Partial<User>) {
  const updatedUser: User = await (await userService.put(partialUser)).data;
}

// PUT http://localhost:5000/user/:id
async function updateUserById(id: ObjectId, partialUser: Partial<User>) {
  const updatedUser: User = await (await userService.putById(id, partialUser)).data;
}

<a id="usage/extended"> <h3>🎨 <u>Extended</u></h3></a>

1) Create Extended Service

import { ForestService } from "4rest";

import { instance } from "./forestInstance";

export class UserService extends ForestService<UserWithId, User> {
  constructor() {
    super("user", instance, {
      /* service config will go here */
    });
    /* prefix for request url will be "user" */
  }

  public getByName = (name: string) => this.methodsCreator.getByParam<UserWithId, string>({ suffix: "name" })(name);
  public getByNameWithQuery = (name: string) =>
    this.methodsCreator.get<UserWithId>({ route: "name", config: { params: { name } } })();
  public isEmailTaken = (email: string) =>
    this.methodsCreator.getByParam<boolean, string>({ route: ["email", "taken"] })(email);
}

<strong>Notes:</strong>

  1. You <strong>must</strong> include constructor in the structure that is shown above in your extended service in order for it to work properly

  2. Extended Service will include all the base service methods as well as the additional ones you have added

  3. Read about <a href='#config/methods-creator'>Methods Creator</a> to add new methods to extended service easily

2) Use Extended Service

const userService = new UserService();

async function getUserName(name: string) {
  const user: User = await (await userService.getByName(name)).data;
}

async function getUserNameByQuery(name: string) {
  const user: User = await (await userService.getByNameWithQuery(name)).data;
}

async function isEmailTaken(email: string) {
  const isEmailTaken: boolean = await (await userService.isEmailTaken(email)).data;
}
</br>

<a id="config"> <h2>Configuration</h2></a>

<a id="config/instance"> <h3>📀 <strong>Forest Instance</strong></h3></a>

<a id="config/instance/instance-creation"><h4><strong><u>Instance Creation</u></strong></h4></a> <strong>Create Forest Instance based</strong> axios Instance with forest.create() Function

import forest from "4rest";

/* Customised Forest Instance can be based on
   AxiosInstance, AxiosRequestConfig */

const forestInstance = forest.create({
    axiosSettings: /* Here goes instance or config*/,
    globalServiceConfig: /* Here goes service configuration that will be applied by default to
                            all created service from these ForestInstance*/
  });

See What <a href="#config/service">Service Config</a> includes down below.

<strong>Note:</strong> if a created service will have a config of it's own, it's config properties will be overriding the global service config properties, which means the more specific property is the one that will be in use eventually

<br/>

<strong>Options to configure</strong> forest.create()

interface InstanceConfig {
  axiosSettings?: AxiosSettings;
  globalServiceConfig?: ServiceConfig;
}

<strong>Note:</strong> Configuration is completly optional, and if axiosSettings are empty the forest instance will be based on the base AxiosInstance

</br>

<a id="config/instance/axios-instance-access"><h4><strong><u>Axios Instance Access</u></strong></h4></a>

You can access the totally regular AxiosInstance that the ForestInstance is based on which contains all of axios methods on it: </br> </br> Access it using the axiosInstance property on created ForestInstance

import { forestInstance } from "./instance";

const response = forestInstance.axiosInstance.get("localhost:5000/users" /* Here goes axios config*/);
</br>

<a id="config/service"> <h3>📀 <strong>Forest Service</stron

View on GitHub
GitHub Stars18
CategoryDevelopment
Updated2y ago
Forks0

Languages

TypeScript

Security Score

80/100

Audited on Feb 28, 2024

No findings