Skip to content

TypeScript REST client supports Axios and Fetch

License

Notifications You must be signed in to change notification settings

ETSOO/restclient

Repository files navigation

@etsoo/restclient

TypeScript promise based HTTP/REST API client. Unified axios and fetch usage.

ESLint + AirbnbBase + Prettier, Jest(ts-jest) applied, supports CommonJs and ESM. About how to build a NPM package and CI/CD with Github action: https://dev.to/garryxiao/build-a-react-components-npm-package-and-ci-cd-with-github-action-1jm6

Includes FetchLikeApi for extension quickly:

/**
 * Fetch API
 */
export class FetchApi extends FetchLikeApi<Response> {
  constructor() {
    super(fetch);
  }
}

// Under Node
// install node-fetch (https://github.com/node-fetch/node-fetch) first, and @types/node-fetch with TypeScript
const { FetchLikeApi } = require("@etsoo/restclient");
const fetch,
  { Response } = require("node-fetch");
class FetchApi extends FetchLikeApi<Response> {
  constructor() {
    super(fetch);
  }
}

Installing

Using npm:

$ npm install @etsoo/restclient

Using yarn:

$ yarn add @etsoo/restclient

Example

Initialization

  • Depending on the envioronment, fetch first, then use axios.
  • Under node, supports node-fetch.
import { createClient } from "@etsoo/restclient";
const client = createClient();

// Or
import { createClientAsync } from "@etsoo/restclient";
const client = await createClientAsync();
  • Depending on your decision.
import { FetchApi } from "@etsoo/restclient";
const client = new FetchApi();

// Or
import { AxiosApi } from "@etsoo/restclient";
const client = new AxiosApi();

Calls

// Customer data structure
interface Customer {
  id: string;
  name: string;
}

// API client
const client = createClient();

// Authorization, JWT
client.authorize(ApiAuthorizationScheme.Bearer, "*** JWT token ***");

// Read customer list with asyc/await ES6+ style
const customers = await client.get<Customer[]>("/api/customer");
// or with traditional callback way
client.get<Customer[]>("/api/customer").then((customers) => {});

// Read one customer
const customer = await client.get<Customer>("/api/customer/1");
if (customer == null) {
  // Error found
  return;
}
console.log(customer.name);

Error handling

// API client
const client = createClient();

// Global error handling
client.onError = (error) => {
  console.log(error);
};

// Read one customer
var payload: IApiPayload<Customer, any> = {
  // Current call's error handling
  onError = (error) => {
    console.log(error);
    // return false to prevent further error handling
    return false;
  },
  // Pass default value to distinguish return value with error or undefined
  defaultValue: {}
};

const customer = await client.get<Customer>(
  "/api/customer/1",
  undefined,
  payload
);
if (customer == null) {
  // Error found
  // client.lastError cache the last error
  // For accurate check, validate client.lastError.data.url
  return;
}

// Now call payload.response to access headers
// client.transformResponse(payload.response) to get a standard IApiResponse

Properties

Name Description
baseUrl API base URL, add to the API root of all calls
charset Charset for sending data, default is 'utf-8'
config See axios/Request Config or fetch/RequestInit
defaultResponseType Default type is JSON
jsonContentType JSON content type string, 'application/json'
lastError Last error for track
name The name of the API, default value is 'system'
onError Error occured callback
onRequest Before request callback
onComplete After request completed but before onResponse
onResponse After response callback

Methods

Provides delete, get, head, options, patch, post, put syntactic sugar for request method. Return with undefined means error found. If the API return nothing with success, a empty object {} will be returned to distingush the error case. Define a onError callback function at payload only for the call or client's property onError for global error handling.

    /**
     * Authorize the call
     * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
     * @param scheme Scheme
     * @param token Token, empty/null/undefined to remove it
     * @param writeHeaders Headers to write authtication, default to all calls
     */
    authorize(
        scheme: ApiAuthorizationScheme | string,
        token: string | undefined,
        writeHeaders?: HeadersInit
    ): void;

    /**
     * Detect IP data
     * @returns IP data
     */
    detectIP(): Promise<IPData | undefined>;

    /**
     * Get HTTP content dispostion
     * @param responseOrValue Response or header value
     * @returns Result
     */
    getContentDisposition(response: R): ContentDisposition | undefined;
    getContentDisposition(header: string): ContentDisposition | undefined;

    /**
     * Get content length
     * @param headers Headers
     * @returns
     */
    getContentLength(headers: HeadersAll): number | undefined;

    /**
     * Get content type and charset
     * @param headers Headers
     */
    getContentTypeAndCharset(headers: HeadersInit): [string, string?];

    /**
     * Get content type
     * @param headers Headers
     */
    getHeaderValue(headers: HeadersInit, key: string): string | null;

    /**
     * Get Json data directly
     * @param url URL
     * @returns Json data
     */
    getJson<T = DataTypes.ReadonlyData>(url: string): Promise<T>;

    /**
     * Request to API
     * @param method Method
     * @param url API URL
     * @param data Passed data
     * @param payload Payload
     */
    request<T>(
        method: ApiMethod,
        url: string,
        data?: ApiRequestData,
        payload?: IApiPayload<T, R>
    ): Promise<T | undefined>;

    /**
     * Set content language
     * @param language Content language
     * @param headers Headers, default is global headers
     */
    setContentLanguage(
        language: string | null | undefined,
        headers?: HeadersInit
    ): void;

    /**
     * Set header value
     * @param key Header name
     * @param value Header value
     * @param headers Headers to lookup
     */
    setHeaderValue(
        key: string,
        value: string | null | undefined,
        headers: HeadersInit
    ): void;

    /**
     * Transform the original response to a unified object
     * @param response Original response
     */
    transformResponse(response: R): IApiResponse;

Call Payload

When you call any API, pass additional properties with the payload parameter.

Name Description
contentType Specify data type to send, like 'application/json'
onError Current API call error callback
config Current API config. See axios/Request Config or fetch/RequestInit
defaultValue Default value, like [] for array return to distinguish undefined or error return
params URL parameters
parser Current API response data parser
response Request response object
responseType Specify response data type
showLoading Whether to show loading bar
local Local URL and ignore baseUrl

License

MIT