npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@pedro.gilmora/http-call

v1.1.1

Published

A Typescript dynamical dot-syntax HTTP-client for REST

Downloads

18

Readme

🧙‍♂️ 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

[
  {
      "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

};