@pedro.gilmora/http-call
TypeScript icon, indicating that this package has built-in type declarations

1.1.1 • Public • Published

🧙‍♂️ HTTP-Call: a dynamical + self-constructive + dot-syntax HTTP-client for REST

This packages relies on fetch API

Table of content:

💁‍♂️ Why?

I just love self-constructive objects. So, why not to create a dynamical self-constructive HTTP client?

https://user-images.githubusercontent.com/33942331/140660876-2eae5e31-2772-47c9-b3dd-d612a33014b5.mp4

👇Here we go...


🔨 Let's make it work easy

📝 In the beginning...

import { HttpCall } from "@pedro.gilmora\http-call";

const 
    $api = HttpCall.create({ baseUrl: `https://my-json-server.typicode.com` }),
    restPathParamProp = 'posts',
    $endpointBase = $api.typicode.demo[ restPathParamProp ];

...

console.log($endpointBase.$path);

And there was light...

https://my-json-server.typicode.com/typicode/demo/posts

🌈 Types...

export interface Post {
    id?: number;
    title: string;
}

export interface User {
  id: number;
  userName: string;
}

export interface UserPost extends Post{
  user: User
}

With Callback approach

While we do this...

$endpointBase.get<Post[]>().then(console.log);

We'll get this

Url

https://my-json-server.typicode.com/typicode/demo/posts

Response
[
  {
      "id": 1,
      "title": "Post 1"
  },
  {
      "id": 2,
      "title": "Post 2"
  },
  {
      "id": 3,
      "title": "Post 3"
  }
]

🍬 With async/await approach and query parameters...

Query parameters objects will be serialized as query string.

const queryParams = { a: 'b', b: 2, c: true, d: new Date(), e: null },
    id = 1;

const filtered = await $endpointBase[id].get<Post[]>(queryParams, { 
    // Tadaa: We have the ability to intercept the request before send it... 👏👏👏
    onSend({ url }) { 
        console.log(url);
    }
});

Url

https://my-json-server.typicode.com/typicode/demo/posts?a=b&b=2&c=true&d=2021-11-07T16%3A42%3A16.631Z&e=

Response

{
  "id": 1,
  "title": "Post 1"
}

💥 Error capture

You can easily handle errors like this (using the same creation context). FetchError might to the rescue in case you need it

try {
    await $api.another.missing.endpoint.post({id:1, title: 'test'});
} catch (error) {
    if(error instanceof FetchError && error.code === 404)
        await notifyError("We couldn't contact the server", /*timeout*/3500);
}

🔩 BTW... we can transform typed results

Consider to not specify generic-type for result in HTTP verb methods, transform hook will help infer types for you by specifying parameters and return types

const user = { id: -1, userName: 'admin' };
const posts: UserPost[] = await $endpointBase.get(undefined, 
  {
    transform(posts: Post[]){
      //returns (Post & {user: User})[] which is compatible with UserPost[] 
      return posts.map(post => Object.assign(post, {user}));
    }
  }
);

We'll get this

Url

GET: https://my-json-server.typicode.com/typicode/demo/posts

Response

[
  {
      "id": 1,
      "title": "Post 1",
      "user": { 
        "id": -1, 
        "name": "admin" 
      }
  },
  {
      "id": 2,
      "title": "Post 2",
      "user": { 
        "id": -1, 
        "name": "admin" 
      }
  },
  {
      "id": 3,
      "title": "Post 3",
      "user": { 
        "id": -1, 
        "name": "admin" 
      }
  }
]

🍬 With async/await approach and query parameters...

Query parameters objects will be serialized as query string.

const queryParams = { a: 'b', b: 2, c: true, d: new Date(), e: null },
    id = 1;

const filtered = await $endpointBase[id].get<Post[]>(queryParams, { 
    // Tadaa: We have the ability to intercept the request before send it... 👏👏👏
    onSend({ url }) { 
        console.log(url);
    }
});

Url

https://my-json-server.typicode.com/typicode/demo/posts?a=b&b=2&c=true&d=2021-11-07T16%3A42%3A16.631Z&e=

Response

{
  "id": 1,
  "title": "Post 1"
}

API

HttpCall Instance

//Caller instance
export type HttpCallerInstance = {  

  //Retrieve the built-in URL path
  $path: string;

  //Performs a GET request.
  get<T, TOut = T>(

    // Record object to be converted to query string
    query?: Record<string, any>, 

    //Custom request configuration
    init?: HttpCallInitOf<T,TOut>

  ): Promise<TOut>;

  
  //Performs a POST request.
  post<T, TOut = T>(

    //data to be sent
    data?: T, 

    //Custom request configuration
    init?: HttpCallInitOf<T, TOut>

  ): Promise<TOut>;

   
  //Performs a PUT request.
  put<T, TOut = T>(

    //data to be sent
    data?: T, 

    //Custom request configuration
    init?: HttpCallInitOf<T, TOut>

  ): Promise<TOut>;
 

  //Performs a DELETE request.
  delete<T, TOut = T>(

    // Record object to be converted to query string
    query?: Record<string, any>, 

    //Custom request configuration
    init?: HttpCallInitOf<T,TOut>

  ): Promise<TOut>;


  //configure the current request
  withOptions(opts: HttpCallInitOf<T,TOut>): HttpCallerInstance;
 
 
  //adds query parameters. Useful for POST and PUT requests
  withQuery(query: Record<string, any>): HttpCallerInstance;

} & {

  // any other specified property access will return the current instance with a new path segment (Proxy)
  [x: string|number]: HttpCallerInstance

};

Package Sidebar

Install

npm i @pedro.gilmora/http-call

Weekly Downloads

0

Version

1.1.1

License

ISC

Unpacked Size

28.1 kB

Total Files

11

Last publish

Collaborators

  • pedro.gilmora