api-registry
v1.2.0
Published
Centralized HTTP API client for the browser and Node.js based on Fetch API
Downloads
306
Maintainers
Readme
api-registry
Centralized HTTP API client for the browser and Node.js based on Fetch API. Supports request caching with Cache API.
Getting started
import { JsonApiRegistry } from 'api-registry';
// Register an API
const api = JsonApiRegistry.api('user-api', 'https://reqres.in/api');
// Define an endpoint
const getUser = api
.endpoint('users/{id}') // See https://github.com/teil-one/rfc6570-uri-template for supported templates
.receives<{ id: number }>()
.returns<{ id: number; email: string }>()
.build();
// GET https://reqres.in/api/users/1
const response = await getUser({ id: 1 });
// Parse the JSON data from the response (see https://developer.mozilla.org/en-US/docs/Web/API/Response)
const user = await response.json();
console.log(user);
Send POST requests
const createUser = api
.endpoint('users', 'POST')
.returns<CreatedUser>()
.receives<NewUser>()
.buildWithParse(); // Builds a method that parses the returned JSON
const user = await createUser({ email: '[email protected]' });
Track progress
Track progress with fetch-api-progress
import { trackRequestProgress, trackResponseProgress } from 'fetch-api-progress';
const api = JsonApiRegistry.api('httpbin.org', 'https://httpbin.org');
const upload = api.endpoint('put', 'PUT').build();
const blob = new Blob([new Uint8Array(5 * 1024 * 1024)]);
const request = {
headers: {
'Content-Type': 'application/octet-stream'
},
body: blob
};
const trackedRequest = trackRequestProgress(
request,
(progress) => {
console.log(`Uploaded ${progress.loaded} bytes out of ${progress.total ?? 'unknown'}`)
}
);
const response = await upload(trackedRequest);
const trackedResponse = trackResponseProgress(
response,
(progress) => {
console.log(`Downloaded ${progress.loaded} bytes out of ${progress.total ?? 'unknown'}`)
}
);
// Read the response. E.G. with a function from https://github.com/teil-one/api-registry/blob/main/test/progress/download.spec.ts
await readResponse(trackedResponse);
Share an API across micro frontends
The library registers API objects globally. It allows to register an API in one application and reuse it in another.
Frontend 1
const api = JsonApiRegistry.api('user-api', 'https://reqres.in/api');
Frontend 2
const api = JsonApiRegistry.api('user-api'); // The base URL will be picked up from the already registered API
Cache responses
const getUser = api
.endpoint('users/{id}')
.receives<{ id: number }>()
.returns<{ id: number; email: string }>()
.withCache(1000) // Cache requests for 1000 ms
.buildWithParse();
const user1 = await getUser({ id: 1 }); // The response will be cached for 1 second
const user1_ = await getUser({ id: 1 }); // There will be no additional HTTP request. The data will be read from the cache
const user2 = await getUser({ id: 2 }); // The request is different and the HTTP response will be cached for 1 second
Send custom headers and other request options
On the endpoint level
const getUser = api
.endpoint('users/{id}')
.withOptions({ headers: { Authorization: 'Basic ZXhhbXBsZQ==' }, referrer: 'http://foo.bar/' }) // See all options at https://developer.mozilla.org/en-US/docs/Web/API/Request
.receives<{ id: number }>()
.returns<{ id: number; email: string }>()
.build();
On the request level
const response = await getUser({ id: 1 }, { headers: { 'uber-trace-id': '00000000000000009c54cc5904914703:cf0f9dbcc295b86c:0:1' }});
Request options from different levels and different frontends are combined.
Use factory methods
For the base URL
const api = JsonApiRegistry.api('user-api', () => Promise.resolve('https://reqres.in/api'));
For the request options
const getUser = api
.endpoint('users/{id}')
.withOptions(() => Promise.resolve({ headers: { Authorization: 'Basic ZXhhbXBsZQ==' }}))
.receives<{ id: number }>()
.returns<{ id: number; email: string }>()
.build();
const response = await getUser({ id: 1 }, () => Promise.resolve({ headers: { 'uber-trace-id': '00000000000000009c54cc5904914703:cf0f9dbcc295b86c:0:1' }}));
Intercept requests
On the API level
All requests to the API will be handled by the passed interception function.
JsonApiRegistry.api('rest-api', 'http://foo.bar/api')
.intercept(
async (request: Request, next: () => Promise<Response>): Promise<Response> => {
let response = await next();
if (response.status === 401) {
// ... Authenticate
// Repeat the request
response = await next();
}
return response;
}
);
On the endpoint level
All requests to the endpoint will be handled by the passed interception function.
const getUser = api.endpoint('user/{id}')
.receives<{ id: number }>()
.intercept(
async (request: Request, next: () => Promise<Response>): Promise<Response> => {
let response = await next();
// ...
return response;
}
)
.build();
Usage options
The library is built as an ES module and as a CommonJS module. It can be used in Javascript, Typescript, and Node.js applications.
The ES module can be used in a web browser directly from a CDN. See the examples folder.