npm package: @null-bug/easy-json-api
Description: Ferramenta para ler dados retornados por endpoints JSON:API
Latest version: 1.1.4

# easy-json-api

Ferramenta para ler dados retornados pelos endpoints JSON:API. Serve tanto para
respostas em formato array quanto em formato objeto.

## Visão geral

A função `parseResponse` lê todos os dados retornados pelo endpoint e cria um
objeto (ou um array de objetos, de acordo com o tipo de resposta) com esses
dados, sem necessidade de um schema pré-definido.

O retorno dessa função é um array onde o primeiro item é o objeto (ou array de
objetos) gerado e o segundo item é uma string que identifica o tipo da
resposta (`array`
ou `object`).

## Instalação

```shell
yarn add @null-bug/easy-json-api
```

## Utilização

### Javascript puro:

```js
import { parseResponse } from '@null-bug/easy-json-api'
import http from '@/services/http/http'

// ...

// esse endpoint retorna um único usuário
const { data } = await http.get('/users/123?include=roles')

const [user, responseType] = parseResponse(data)

/**
 * {
 *   __type: 'users',
 *   age: 23,
 *   document: '11111111100',
 *   id: '123',
 *   name: 'Josefino Mariano',
 *   roles: [
 *     {
 *       __type: 'roles',
 *       id: '1',
 *       name: 'admin',
 *     }
 *   ],
 * }
 */
console.log(user)

console.log(responseType) // 'object'

// ...

// esse outro endpoint retorna vários usuários
const { data } = await axios.get('/users?include=roles?per_page=2')

const [users, responseType] = parseResponse(data)

/**
 * [
 *   {
 *     __type: 'users',
 *     age: 23,
 *     id: '123',
 *     document: '11111111100',
 *     name: 'Josefino Mariano',
 *     roles: [
 *       {
 *         __type: 'roles',
 *         id: '1',
 *         name: 'admin',
 *       }
 *     ],
 *   },
 *   {
 *     __type: 'users',
 *     age: 54,
 *     id: '51',
 *     document: '11111111100',
 *     name: 'Etelvina do Prado',
 *     roles: [
 *       {
 *         __type: 'roles',
 *         id: '1',
 *         name: 'admin',
 *       }
 *     ],
 *   },
 * ]
 */
console.log(users)

console.log(responseType) // 'array'
```

### Typescript

Usando Typescript, também é possível atribuir um tipo ao objeto retornado:
```ts
import { parseResponse } from '@null-bug/easy-json-api'
import http from '@/services/http/http'

// ...

interface IRole {
  id: string
  name: string
}

interface IUser {
  age: number
  document: string
  id: string
  name: string
  roles: IRole[]
}

const { data } = await http.get('/users/123?include=roles')


// o tipo de `user` é `User | User[]` e
// o tipo de `responseType` é `'object' | 'array'`
const [user, responseType] = parseResponse<IUser>(data)
```

A biblioteca também exporta
os [tipos genéricos](https://www.typescriptlang.org/pt/play#example/generic-functions) `ResponseAsObject`
e `ResponseAsArray`, que podem ser usados quando você já conhece o tipo que o
endpoint vai retornar:

```ts
import {
  parseResponse,
  ResponseAsObject,
  ResponseAsArray
} from '@null-bug/easy-json-api'

// ...

// esse endpoint retorna sempre um único usuário
const { data } = await http.get('/users/123?include=roles')

// o tipo de `user` é `User` e o tipo de `responseType` é `'object'`
const [user, responseType] = parseResponse(data) as ResponseAsObject<IUser>

// ...

// o tipo de `users` é `User[]` e o tipo de `responseType` é `'array'`
const [users, responseType] = parseResponse(data) as ResponseAsArray<IUser>
```

Para os casos onde a chamada pode retornar tanto um item único quanto um array
de itens (quando a URL é montada condicionalmente, por exemplo), é possível
atribuir o tipo verificando o valor do segundo item do array retornado pela
função `parseResponse`:

```ts
const { data } = await http.get(`/users${type === 'show' ? `/${userId}` : ''}?include=roles`)

// ao invés de desestruturar o resultado diretamente,
// melhor salvar ele em uma variável e pegar o primeiro
// item na hora em que formos usá-lo
const result = parseResponse<IUser>(data)

// isso pega apenas o segundo item do result
const [, responseType] = result

// com essa verificação, o Typescript identifica o tipo adequado
// e não mostra nenhum erro ao usar o valor
if(responseType === 'array') {
  // o tipo de `users` é User[]
  const users = result[0]

  users.forEach(user => console.log(user.id))
}
else {
  // o tipo de `user` é User
  const user = result[0]

  console.log(user.id)
}
```