# pretend

> A decorator based http webservice client written in typescript

Latest version **4.0.0** (published 2023-03-28) · MIT license · 0 weekly downloads

## Install

```sh
npm install pretend
pnpm add pretend
yarn add pretend
bun add pretend
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 4.0.0 |
| Published | 2023-03-28 |
| First published | 2016-03-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 2 |
| Unpacked size | 34.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Markus Wolf |
| Maintainers | knisterpeter |

## Links

- npm: https://www.npmjs.com/package/pretend
- Repository: https://github.com/KnisterPeter/pretend
- Homepage: https://github.com/KnisterPeter/pretend#readme
- Issues: https://github.com/KnisterPeter/pretend/issues
- npm.io page: https://npm.io/package/pretend

## Dependencies (2)

- [isomorphic-fetch](https://npm.io/package/isomorphic-fetch.md) 3.0.0
- [isomorphic-form-data](https://npm.io/package/isomorphic-form-data.md) 2.0.0

## Recent versions

- 4.0.0 (latest) — 2023-03-28
- 3.1.1 — 2021-10-22
- 3.1.0 — 2020-06-22
- 3.0.2 — 2020-06-15
- 3.0.1 — 2020-06-15
- 3.0.0 — 2019-09-19
- 2.0.0 — 2018-11-19
- 1.5.1 — 2018-05-24
- 1.5.0 — 2018-05-07
- 1.4.2 — 2018-03-19
- 1.4.1 — 2018-03-02
- 1.4.0 — 2018-02-12
- 1.3.0 — 2018-02-08
- 1.2.1 — 2017-12-28
- 1.2.0 — 2017-12-15
- … 16 more at https://npm.io/package/pretend/versions

## README

# pretend

[![npm](https://img.shields.io/npm/v/pretend.svg)](https://www.npmjs.com/package/pretend)
[![GitHub license](https://img.shields.io/github/license/KnisterPeter/pretend.svg)](https://github.com/KnisterPeter/pretend)
![build](https://github.com/KnisterPeter/pretend/workflows/build/badge.svg?branch=master)
[![codecov](https://codecov.io/gh/KnisterPeter/pretend/branch/master/graph/badge.svg)](https://codecov.io/gh/KnisterPeter/pretend)
[![renovate badge](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovateapp.com/)

A decorator based http webservice client build with typescript (inspired bei [feign](https://github.com/OpenFeign/feign)).

## Features

- Handle REST based webservices
- Configure a decoder (defaults to JSON)
- Generic request/response interceptor chain
- Basic authentication
- Request parameters (currently on GET requests)
- Custom headers per method

## Usage

### Installation

Install as npm package:

```sh
npm install pretend --save
```

**Note:** To work on node.js (server-side) the `fetch` must be polyfilled. This could easy be done importing `isomorphic-fetch`.

### API

```js
class Test {

  @Headers('Accept: application/json')
  @Get('/path/{id}', true)
  public async get(id: string, parameters: any) {}

  @Post('/path')
  public async post(body: any) {}

  @Post('/path')
  public async post(@FormData('name') blob: any) {}

  @Put('/path')
  public async put() {}

  @Delete('/path/:id')
  public async delete(id: string) {}

}

async function call() {
  const client = Pretend
                  .builder()
                  .target(Test, 'http://host:port/');
  const result = await client.get('some-id', {'name': 'value'});
}

// Executes a GET request to 'http://host:port/path/some-id?name=value'
call();

```

Decoders, basicAuthentication and requestInterceptors are all special forms
of the more generic interceptors which could be chained per request/response.

```js
// Configure a text based decoder
const client = Pretend.builder()
  .decoder(Pretend.TextDecoder)
  .target(Test, 'http://host:port/');
```

```js
// Configure basic authentication
const client = Pretend.builder()
  .basicAuthentication('user', 'pass')
  .target(Test, 'http://host:port/');
```

```js
// Configure a request interceptor
const client = Pretend.builder()
  .requestInterceptor((request) => {
    request.options.headers['X-Custom-Header'] = 'value';
    return request;
  })
  .target(Test, 'http://host:port/');
```

#### Interceptors

Multiple interceptors could be added to each builder. The order of interceptor
calls will result in a chain of calls like illistrated below:

```js
// Configure a request interceptor
const client = Pretend.builder()
  .interceptor(async (chain, request) => {
    console.log('interceptor 1: request');
    const response = await chain(request);
    console.log('interceptor 1: response');
    return response;
  })
  .interceptor(async (chain, request) => {
    console.log('interceptor 2: request');
    const response = await chain(request);
    console.log('interceptor 2: response');
    return response;
  })
  .target(Test, 'http://host:port/');
```

```text
             +---------------+    +---------------+
Request ---> |               | -> |               |
             | Interceptor 1 |    | Interceptor 2 | -> HTTP REST call
Response <-- |               | <- |               |
             +---------------+    +---------------+
```

This leads to the following console output:

```text
interceptor 1: request
interceptor 2: request
interceptor 2: response
interceptor 1: response
```

### Data Mappers

DataMappers could be used to map response structures to TypeScript classes.
This is done using the `@ResponseType` decorator.

```ts
class User {
  public name: string;

  constuctor(data: { name: string }) {
    this.name = data.name;
  }
}

class API {
  @Get('/path/{id}')
  @ResponseType(User)
  public async loadUser(id: string): Promise<User> {
    /*
     * `/path/{id}` returns a JSON like this from the server:
     *
     *  {
     *    name: 'some string'
     *  }
     */
  }
}

const client = Pretend.builder().target(API, 'http://host:port/');
const result: User = await client.loadUser(1);
```

There is a second parameter to the `@ResponseType` decorator which is a transform function.
The input is the server response, the output need to match the class constructor parameters.

**Note**: The constructor parameters are always an array!

```ts
class User {
  public get name(): string {
    return this.data.name;
  }

  constuctor(private data: { name: string }) {}
}

class API {
  @Get('/path/{id}')
  @ResponseType(User, (data) => [
    { name: `${data.firstname} ${data.lastname}` }
  ])
  public async loadUser(id: string): Promise<User> {
    /*
     * `/path/{id}` returns a JSON like this from the server:
     *
     *  {
     *    firstname: 'John',
     *    lastname: 'Doe'
     *  }
     */
  }
}

const client = Pretend.builder().target(API, 'http://host:port/');
const result: User = await client.loadUser(1);
```

## Future ideas / Roadmap

- Named parameters

---
_Source: https://npm.io/package/pretend · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
