dot-http
v0.0.9
Published
A Typescript dynamical dot-syntax HTTP-client for REST
Downloads
7
Maintainers
Readme
🧙♂️ DotHTTP: 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?
👇Here we go...
🔨 Let's make it work easy
📝 In the beginning...
import DotHttp from "dot-http";
const
$api = DotHttp.create(`https://my-json-server.typicode.com`),
restPathParamProp = 'posts',
$endpointBase = $api.typicode.demo[ restPathParamProp ];
...
📝 Also it allows async configuration resolver...
import DottHttp from "dot-http";
const
$api = DotHttp.create(() => sleep(100).then(() => `https://my-json-server.typicode.com`)) // with async-resolver function,
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"
}
}
]
API
DotHttp
instance
$path: string | Promise<string>
get<T, TOut = T>(
query?: Record<string, any>,
init?: DotHttpInitOf<T,TOut>
)
query?: Record<string, any>
init?: DotHttpInitOf<T,TOut>
post<T, TOut = T>(
data?: T,
init?: DotHttpInitOf<T, TOut>
): Promise<TOut>;
data?: T
init?: DotHttpInitOf<T,TOut>
put<T, TOut = T>(
data?: T,
init?: DotHttpInitOf<T, TOut>
): Promise<TOut>;
data?: T
init?: DotHttpInitOf<T,TOut>
patch<T, TOut = T>(
data?: Partial<T>,
init?: DotHttpInitOf<T, TOut>
): Promise<TOut>;
data?: Partial<T>
init?: DotHttpInitOf<T,TOut>
delete<T, TOut = T>(
query?: Record<string, any>,
init?: DotHttpInitOf<T,TOut>
)
query?: Record<string, any>
init?: DotHttpInitOf<T,TOut>
Request extra-config
serialize?(e: DotHttpInit): void | Promise<void>
deserialize?(e: T): TOut | Promise<TOut>
throttle?: number
baseUrl?: string