# Javascript Targetprocess API client

## Node.js compatibility
**Node.js 12 or higher is required.

JavaScript client for accessing Targetprocess API

## Features

- Allow to access `api/v2/` endpoint with type-checkings between entities and it's selectors
- Work with paginated results (**pagination based on ordering by entities ID**)
- Handful shortcuts for `where` conditions

##Prerequirements

1. `dotnet` 2.1 (for client-regeneration)

## Quick start

To install:

```bash
npm install  @targetprocess/tp-js-client
```
# Examples

## Client creation
You can use `httpClientFactory` from [tokiny](https://gitlab.tpondemand.net/sdk/tokiny/) library as a wrapper over you favorite `fetch` implementation. 
Also, it is strongly recommended to pass `X-Client-ID` and `X-Correlation-ID` headers to all request.

```typescript
import { createTokenFactory, httpClientFactory } from '@targetprocess/tokiny'
import { TpClient } from '@targetprocess/tp-js-client'
import { fetch } from 'got-fetch'

const tokenFactory = createTokenFactory({
  authUrl: env.AUTH_SERVICE_URI,
  clientId: env.CLIENT_ID,
  clientSecret: env.CLIENT_SECRET
})

const fetchWithHeaders = (input: RequestInfo, init?: RequestInit) =>
    fetch(input, {
      ...init,
      headers: {
        ...init?.headers,
        'X-Correlation-ID': 'sample-operation-0000-33300-0003-34443',
        'X-Client-ID': 'tp-client-sample-test',
      },
    })

const scopes = 'tp'

const tpClient = new TpClient(
    `https://inteam3.tpondemand.net/`,
    httpClientFactory(scopes, tokenFactory, fetchWithHeaders as any)
)

```

## `readAll` method
Can be used if you want to read all entities 

```typescript

type UserStory = {
    id: number
    name: string
    tasksCount: number
}

const users = await tpClient.readAll<UserStory>('userStories', {
    where: 'id==39528',
    select: {
        id: 'id',
        name: 'name',
        tasksCount: 'tasks.count',
    }
})
```
## `readPages` method
Can be used if you want to read data paged. Please note, entities skipping during pagination will be made using `where=(id > ...)`, not using `skip=...' parameter.

```typescript
type UserStory = {
    id: number
    name: string
    tasksCount: number
}

for await (const page of this.readPages<UserStory>("userStories", {
    where: 'id==39528',
    select: {
        id: 'id',
        name: 'name',
        tasksCount: 'tasks.count',
    })) {
      // page will have type UserStory[]
    }
```

## Selectors
Selectors will be checked during compile time. Following code:

```typescript
type UserStory = {
    id: number
    name: string
    tasksCount: number
    assignedUser: string
}

const selector:Selector<UserStory> = {
    id: 'id',
    name: 'name',
    tasksCount: 'tasks.count'
    // forget to specify selector for assignedUser property
}
```
will produce an error during compile time: `Property 'assignedUser' is missing in type '{ id: string; name: string; tasksCount: string; }' but required in type 'StructuredSelector<UserStory>'.`


## Other TP endpoints
Since client is mostly generated from `api/tp.yaml` swagger spec, all methods described in that spec could be also used:
```typescript
const loggedUser = await tpClient.getLoggedUser();
```

## Release notes

[here](docs/changelog.md)
