New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

typed-rest-api-client

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typed-rest-api-client

A javascript/typescript library to connect to RESTful APIs

latest
Source
npmnpm
Version
1.0.0
Version published
Maintainers
1
Created
Source

typed-rest-api-client

npm latest version NPM License Pipeline Badge

Flexible, Type-Safe REST Client Generator for JavaScript & TypeScript

typed-rest-api-client is a lightweight utility for defining and consuming RESTful APIs using declarative, namespaced syntax. It supports interceptors, argument substitution, and works in both Node.js and browser environments.

✨ Features

  • 🧠 Type-safe endpoint definitions with full TypeScript support
  • 🧩 Composable API structure with namespace support
  • 🔄 Request/response interceptors for parsing, logging, authentication, etc.
  • 🌐 Compatible with browser and Node.js environments
  • 🔄 Supports both CommonJS and ESM module formats
  • 🤝 Works with popular libraries like axios
  • 📦 Small bundle size (2.5k, gzipped: 1.2k)) for efficient builds

📦 Installation

npm install typed-rest-api-client

🚀 Getting Started

import { rest } from 'typed-rest-api-client';

const api = rest({
  baseUrl: 'https://api.no-domain/'
});

const users = api('users', ({ get, post, namespace }) => [
  get('about'),

  get('all', {
    path: '/',
    args: { limit: 100 } as {
      limit?: number;
      skip?: number;
      take?: number;
    },
    schema: null! as { name: string }[],
    config: { errorCodes: 500 } // normally >=400 will throw Error
  }),

  get('findOne', {
    path: '/:id'
  }),

  post('create', {
    path: '/:id'
  }),

  namespace('students', ({ get, post, put, del }) => [
    post('create', { path: '/' }),
    get('get', { path: '/:id', args: {} as { id: number } }),
    put('update', { path: '/:id' }),
    del('delete', { path: '/:id', args: {} as { id: number } })
  ])
]);

// calls: https://api.no-domain/users?skip=0&limit=100
// and `res` is object of type `{ name: string }[]`
const res = await users.all({ skip: 0 }); 

users.about();
users.findOne({ id: 42 });
users.students.get({ id: 5 });
users.students.update({ id: 5, name: 'Test' });
users.students.delete({ id: 5 });

⚙️ Http client

A simple build in http client with interceptors functionality.

import { http } from 'typed-rest-api-client';

const client = http();

// The same as:
const client = http((reqInfo, init) => fetch(reqInfo, init));

Built-in interceptors:

import { http, httpBodySerialize, httpErrorCode, httpJsonParser } from 'typed-rest-api-client';

const client = http.default();

// The same as:
const client = http()
  .wrap(httpBodySerialize)
  .wrap(httpErrorCode)
  .wrap(httpJsonParser);
  • httpBodySerialize - Serializes init.data to request.body using JSON.stringify (e.g. client(url, { data: { a: 1 } })).
  • httpErrorCode - When the request returns statusCode >= 400 throws and Error.
  • httpJsonParser - Parse response body as JSON object.

Custom interceptor:

import { interceptor } from 'typed-rest-api-client';

const logger = interceptor({
  init: (config) => ({ ..config, d: 10 }),
  preRequest: (req, config) => {
    console.log('configs:', config);
    return req;
  },
  postRequest: async (res, config) => {
    console.log('Response:', await res.text());
    return res;
  },
  defaultConfig: {
    a: -1,
    b: -1,
    c: -1,
    d: -1
  }
});

http().wrap(logger, { b: 1 })(
  'https://my.domain.com',
  { config: { c: 2 } }
);

// logs configs: { a: -1, b: 1, c: 2, d: 10 }

Work with other libraries

axios

import axios from 'axios';
import { http } from 'typed-rest-api-client';

const api = rest({
  baseUrl: 'https://api.no-domain/',
  http: (reqInfo, init) => axios({
    method: init?.method ?? 'get',
    url: reqInfo as string,
    data: init?.data
  })
});

// ... use api

Angular

@Injectable()
class RestClient {
  readonly #http = inject(HttpClient);
  readonly #api = rest<HttpHandler<Promise<object>>>({
    baseUrl: '/api',
    http: (reqInfo, init) =>
      firstValueFrom(
        this.#http.request(init.method as string, reqInfo as string, {
          body: init.body,
          headers: init.headers as Record<string, string>
        })
      )
  });

  readonly topics = this.#api('/topics', ({ get }) => [
    get('all', {
      path: '/'
    })
  ]);
}

// await inject(RestClient).topics.all();

Zod

import { z } from "zod";

const User = z.object({
  username: z.string(),
});

const users = rest()('users', ({ get  }) => [
  get('all', {
    schema: (res) => User.parse(res)
  })
]);


const allUsers = await users.all(); // zod parse is applied

🧱 REST Structure

rest(options)(rootPath, definition)

rest options:

  • baseUrl: string
  • http?: HttpHandler<object>
  • parseArgs?: (args: Record<string, string | number | boolean>) => string
  • substituteRootParams?: (path: string, args: Record<string, string | number | boolean>) => string

Creates a namespaced REST client:

  • rootPath – path of the api resource
  • definition(fn) – Declaratively define methods and nested namespaces

Endpoint Creators

  • get(name, config?)
  • post(name, config?)
  • put(name, config?)
  • patch(name, config?)
  • del(name, config?)
  • namespace(name, defineFn)

Each config object can include:

  • path – route path (e.g. /:id)
  • args – default argument types
  • config – custom config passed to interceptors
  • schema - validate the response body object

License

MIT © Rosen Kolev

Keywords

rest

FAQs

Package last updated on 05 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts