@elite174/api-maker
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

@elite174/api-maker

version npm

Highly customizable small lib with 0 dependencies allows you to build API functions with mocks.

Features:

  • Provide mock handlers if your backend is not ready yet
  • Override mock handlers, request parameters and response handlers in 3 layers (api service creation, api function creation, api call)
  • Typed parameters
  • XHR support

Installation

pnpm i @elite174/api-maker

In browser

<script type="module">
  // specify correct version here
  import { APIMaker } from "https://cdn.jsdelivr.net/npm/@elite174/api-maker@1.0.0/dist/index.js";

  const api = new APIMaker({
    base: "https://jsonplaceholder.typicode.com",
  });

  const getData = api.create(() => ({
    path: "/todos",
  }));

  getData().then(console.log);
</script>

Examples

import { APIMaker } from "@elite174/api-maker";

// Create API controller instance
const api = new APIMaker({
  base: "https://jsonplaceholder.typicode.com",
  // You may specify custom response handler
  // by default for fetch requests it's response.json().
  // Later you may override it during api creation or api call.
  defaultResponseHandler: (response) => response.json(),
  // You may also pass extra options to fetch
  // sharedRequestOptions: { credentials: "include" },
});

// Create api route
// Specify result type (unknown) and params type (number)
const getUser = api.create<unknown, number>((id) => ({
  path: `/users/${id}`,
}));

// Call api route!
getUser(1).then(console.log);

//-----------------

// If your BE is not ready yet you can make a fetcher with mocked data
const getUserMocked = api.create<{ name: string }, number>((id) => ({
  path: `/users/${id}`,
  // Tree shaking will remove this code in production
  mockHandler: import.meta.env.PROD ? undefined : async (id) => ({ name: `User: ${id}: John Doe` }),
}));

// Call api route!
getUserMocked(1, {
  useMockedData: true,
  // You may override the mock handler provided in api creation
  // mockHandler: async () => ({ name: "This handler will be used" }),
}).then(console.log);

//-----------------

// You can override default response handler
const getUserCustomResponseHandler = api.create<unknown, number>((id) => ({
  path: `/users/${id}`,
  responseHandler: async (response) => response.text(),
}));

// Call api route!
getUserCustomResponseHandler(1, {
  // You may also override responseHandler during api call
  // responseHandler: (response) => response.blob(),
}).then(console.log);

//-----------------

// You may add some listeners to handle specific status codes
api.on(404, () => console.log("404 error!"));

//-----------------
// There's support for XHR requests!
const getUserXHR = api.createXHR<any, number>((id) => ({
  path: `/users/${id}`,
}));

getUserXHR(1).sendRequest().then(console.log);

See more examples in the test file.

Types

export declare type APIControllerConfig = {
  /** Base URL */
  base?: string;
  /**
   * Shared request options which are used for all the requests
   * @default { method: 'GET' }
   */
  sharedRequestOptions?: RequestInit;
  /**
   * Response handler which is used for all fetch requests
   * @default response => response.json()
   */
  defaultResponseHandler?: ResponseHandler;
};

/**
 * We have 3 layers:
 * 1. API service creation
 * 2. API route creation
 * 3. API call
 *
 * Things you can override at each layer:
 * 1. RequestInit params
 * 2. Mock handler (only on 2 and 3 layer)
 * 3. Response handler
 */
/**
 * The APIMaker class is responsible for creating and managing API requests.
 */
export declare class APIMaker {
  private logger?;
  private statusHandlers;
  private config;
  private getFullPath;
  constructor(config?: APIControllerConfig, logger?: Logger | undefined);
  /** When enabled mock handlers are used where possible */
  mockModeEnabled: boolean;
  /**
   * Sets the shared request options for all the requests.
   * If an object is passed, it will override the options defined in the constructor.
   * You may pass a function that receives the current shared request options and returns the new options.
   */
  setSharedRequestOptions(
    requestOptions: RequestInit | ((currentSharedRequestOptions: RequestInit) => RequestInit)
  ): void;
  on(statusCode: number, statusHandler: StatusHandler): void;
  off(statusCode: number, statusHandler: StatusHandler): void;
  createXHR<TResult, TParams = void>(requestCreator: XHRRequestCreator<TParams, TResult>): XHRFetcher<TParams, TResult>;
  create<TResult, TParams = void>(requestCreator: FetchRequestCreator<TParams, TResult>): Fetcher<TParams, TResult>;
}

export declare function deepMerge<T = any>(...objects: (Record<string, any> | undefined)[]): T;

export declare const DEFAULT_API_MAKER_CONFIG: {
  base: string;
  sharedRequestOptions: {
    method: string;
  };
  defaultResponseHandler: (response: Response) => Promise<any>;
};

/**
 * Represents a function that fetches data from an API.
 * @template TParams The type of the API parameters.
 * @template TResult The type of the API response.
 * @param apiParams The parameters to be passed to the API.
 * @param options Additional options for the fetcher.
 * @param options.customRequestOptions Custom request options to be passed to the fetch function.
 * @param options.useMockedData Specifies whether to use mocked data instead of making a real API request.
 * @param options.mockHandler A function that handles the mocked API request and returns the mocked response.
 * @param options.responseHandler A function that handles the API response and returns the processed result.
 * @returns A promise that resolves to the API response.
 */
export declare type Fetcher<TParams, TResult> = (
  apiParams: TParams,
  options?: {
    customRequestOptions?: RequestInit;
    useMockedData?: boolean;
    mockHandler?: MockHandler<TParams, TResult>;
    responseHandler?: ResponseHandler<TResult>;
  }
) => Promise<TResult>;

/**
 * Represents a function that creates a fetch request.
 * @template TParams The type of the request parameters.
 * @template TResult The type of the request result.
 * @param params The request parameters.
 * @returns An object containing the request path, optional request options, mock handler, and response handler.
 */
export declare type FetchRequestCreator<TParams, TResult> = (params: TParams) => {
  path: string;
  requestOptions?: RequestInit;
  mockHandler?: MockHandler<TParams, TResult>;
  responseHandler?: ResponseHandler<TResult>;
};

declare interface Logger {
  info(message: string): void;
}

export declare const makeLogMessage: (message: string) => string;

export declare type MockHandler<TParams, TResult> = (requestParams: TParams) => Promise<TResult>;

export declare type ResponseHandler<TResult = any> = (response: Response) => Promise<TResult>;

export declare type StatusHandler = (response: Response) => void;

/**
 * Represents a function that fetches data using XMLHttpRequest.
 * @template TParams - The type of the API parameters.
 * @template TResult - The type of the API result.
 * @param apiParams - The API parameters.
 * @param options - The options for the fetcher.
 * @param options.customRequestOptions - Custom request options for the XMLHttpRequest.
 * @param options.useMockedData - Indicates whether to use mocked data.
 * @param options.mockHandler - The mock handler for generating mocked data.
 * @returns An object containing the XMLHttpRequest and a function to send the request and get the result.
 */
export declare type XHRFetcher<TParams, TResult> = (
  apiParams: TParams,
  options?: {
    customRequestOptions?: RequestInit;
    useMockedData?: boolean;
    mockHandler?: MockHandler<TParams, TResult>;
  }
) => {
  xhr: XMLHttpRequest;
  sendRequest: () => Promise<TResult>;
};

/**
 * Represents a function that creates an XHR request.
 * @template TParams The type of the request parameters.
 * @template TResult The type of the request result.
 * @param params The request parameters.
 * @returns An object containing the request path, optional request options, and a mock handler.
 */
export declare type XHRRequestCreator<TParams, TResult> = (params: TParams) => {
  path: string;
  requestOptions?: RequestInit;
  mockHandler?: MockHandler<TParams, TResult>;
};

Lisence

MIT

Package Sidebar

Install

npm i @elite174/api-maker

Weekly Downloads

105

Version

1.1.0

License

none

Unpacked Size

24.3 kB

Total Files

7

Last publish

Collaborators

  • v-lipatov