api-registry
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

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: 'new.user@reqres.in' });

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.

GitHub · NPM package

Package Sidebar

Install

npm i api-registry

Weekly Downloads

4

Version

1.0.0

License

Apache-2.0

Unpacked Size

33.7 kB

Total Files

6

Last publish

Collaborators

  • teil-one