@pedro.gilmora/http-call
v1.1.1
Published
A Typescript dynamical dot-syntax HTTP-client for REST
Downloads
18
Maintainers
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
};