npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ts-rest-client

v1.2.5

Published

Simple way to create REST API clients

Downloads

12

Readme

npm version Build status Coverage Status

ts-rest-client

Generic service for consuming RESTful API using Typescript decorators. Though the idea comes from the angular2-rest package, I abstracted it a bit more so that it is not dependent on Angular and so that it supports easier unit testing.

Backends

To decouple the REST client from a concrete XHR engine, the client just collects the data needed for creating an HTTP request and then passes those to an interface called HttpService which is then responsible for executing the actual request, parsing the response and returning the data back. Actually there are the following backends implemented:

Besides that the base ts-rest-client package contains a mocked MockHttpService that can help you with writing your unit tests.

If you need to implement a different backend, all you need to do is to implement the HttpService interface and pass that implementation to the RestClient constructor.

Installation

npm install ts-rest-client

Example

Using Typescript decorators you define a proxy to your API. Using the RestClient constructor you pass the concrete backend as an argument.

import {
  BaseUrl,
  Body,
  DefaultHeaders,
  DELETE,
  GET,
  HEAD,
  Headers,
  Path,
  POST,
  PUT,
  Query,
  RestClient,
} from './rest-client';

import { CreateUserData, User } from 'src/models/user';

@BaseUrl('https://reqres.in/api')
@DefaultHeaders({
  Accepts: 'application/json'
})
class UsersApiClient extends RestClient {
  constructor() {
    super(new MockHttpService());
  }

  @GET('/users')
  listUsers(@Query('page') _page: number): Observable<User[]> { return null; }

  @POST('/users')
  createUser(@Body _userData: CreateUserData): Observable<User> { return null; }

  @PUT('/users/{id}')
  updateUser(@Path('id') _id: number, @Body _userData: CreateUserData): Observable<User> { return null; }

  @DELETE('/users/{id}')
  deleteUser(@Path('id') _id: number): Observable<void> { return null; }

  @HEAD('/test-head')
  @Headers({
    MyHeader: 215
  })
  testHead(): Observable<void> { return null; }
}

Then having the instance of the proxy, you just simply call its methods. Under the hood the call is transformed to an HTTP request and you get an observable that returns the parsed response body once the request completes. If an error occurs, you get an instance of HttpErrorResponse with details about what happened:

function callApi(usersApi: UsersApiClient) {
  usersApi.createUser({ name: 'morpheus', job: 'leader' }).subscribe(
    user => console.log('User has been created: ', user),
    err => err.error instanceof Event ?
      console.error('Client-side error', err.error) :
      console.error('Request processing failed on server', err.status, err.error)
  );
}

API

As shown in the example you define your API proxy by inheriting from the

RestClient class

Methods:

  • getBaseUrl(): string: returns the base url of RestClient
  • getDefaultHeaders(): StringMap: returns the default headers of RestClient in a key-value pair

Class decorators

  • @BaseUrl(url: string): Defines the base URL of your API, this will be prepended to the path of every method
  • @DefaultHeaders(headers: StringMap): Defines default headers that will be added to each request; you can override or append individual headers on the method level

Method decorators:

  • @GET(url: string): Indicates that the method is a GET request to a given URL
  • @POST(url: string): Indicates that the method is a POST request to a given URL
  • @PUT(url: string): Indicates that the method is a PUT request to a given URL
  • @DELETE(url: string): Indicates that the method is a DELETE request to a given URL
  • @HEAD(url: string): Indicates that the method is a HEAD request to a given URL
  • @Headers(headers: Object): Additional headers to be added to the request (or override the default)

Parameter decorators:

  • @Path(key: string): Value of the parameter will be inserted into the URL of the method replacing the corresponding {key} placeholder
  • @Query(key: string): Value of the parameter will be inserted into the query string of the request under the given key
  • @Header(key: string): Value of the parameter will be inserted into the request headers under the given key
  • @Body: Value of the parameter will be sent as the body of the request

HttpErrorResponse

When something goes wrong, either the server fails to process your request or there is e.g. a network failure, the observable throws an HttpErrorResponse instance filled with the details about the problem.

It implements the Error interface and extends it with the following fields

  • headers: StringMap any eventual response headers
  • status: number eventual HTTP status code
  • statusText: string eventual HTTP status text
  • url: string URL of the original request
  • error: Event | any | null in case of a server error, it contains the parsed response body (if any), in case of a client-side error it contains an error Event returned by the backend.

MockHttpService

This is a mocked backend that can be passed to the RestClient to simplify writing unit tests for the frontend. It basically allows you to define the response for the subsequent request(s) so that you can simulate different situations that your code has to deal with.

Properties

  • requestOptions: HttpRequestOptions: returns the data of the last request

Methods

  • callback(handler: (request: HttpRequestOptions) => any): Specifies a callback that will be called on each subsequent request. MockService will return whatever the callback returns or throw whatever it throws.
  • response(body: any = {}, status: number = 200, statusText?: string, headers?: StringMap): Defines an HTTP response that will be sent for subsequent request(s).
  • clientError(error: Event): Defines a client-side error that will be returned for subsequent request(s)
  • offline(): Simulates a network-offline condition

Utility classes

  • StringMap: an interface for an object containing key-value pairs where both the key and the value are strings
  • HttpService: an interface for the backend
  • HttpRequestOptions: data collected by the RestClient for creating the actual HTTP request, includes methods for basic request formatting