# jsonapi-resolvers

> Resolve JSON-API entities

Latest version **2.0.0** (published 2023-07-20) · MIT license · 0 weekly downloads

## Install

```sh
npm install jsonapi-resolvers
pnpm add jsonapi-resolvers
yarn add jsonapi-resolvers
bun add jsonapi-resolvers
```

## 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 | 2.0.0 |
| Published | 2023-07-20 |
| First published | 2023-02-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 23.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | jdrydn |
| Maintainers | jdrydn |
| Keywords | JSON, JSON-API, resolvers |

## Links

- npm: https://www.npmjs.com/package/jsonapi-resolvers
- Repository: https://github.com/someimportantcompany/jsonapi-resolvers
- Homepage: https://github.com/someimportantcompany/jsonapi-resolvers#readme
- Issues: https://github.com/someimportantcompany/jsonapi-resolvers/issues
- npm.io page: https://npm.io/package/jsonapi-resolvers

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 2.0.0 (latest) — 2023-07-20
- 1.1.1 — 2023-05-08
- 1.0.0 — 2023-02-22

## README

# jsonapi-resolvers

[![NPM](https://badge.fury.io/js/jsonapi-resolvers.svg)](https://npm.im/jsonapi-resolvers)
[![CI](https://github.com/someimportantcompany/jsonapi-resolvers/workflows/CI/badge.svg?branch=master)](https://github.com/someimportantcompany/jsonapi-resolvers/actions?query=branch%3Amaster)
[![Typescript](https://img.shields.io/badge/TS-TypeScript-%230074c1.svg)](https://www.typescriptlang.org)

Build a resolving function to help you resolve JSON-API entities. With support for selecting specific `fields` & recursively `include`-ing related documents.

```js
const { createResolver } = require('jsonapi-resolvers');
// Or
import { createResolver } from 'jsonapi-resolvers';

const resolve = createResolver({
  posts(ids) {
    // Fetch posts by ID in the JSONAPI format
  },
  users(ids) {
    // Fetch users by ID in the JSONAPI format
  },
});

// Fetch a single post by ID
const { data } = await resolve('posts', '1234');
// { data: { type: 'posts', id: '1234', ... } }

// Fetch multiple posts by ID
const { data } = await resolve('posts', ['1234', '5678']);
// { data: [
//    { type: 'posts', id: '1234', ... },
//    { type: 'posts', id: '5678', ... } ] }

// Fetch a single post by ID, including users too
const { data } = await resolve('posts', '1234', {
  include: ['author'],
});
// { data: { type: 'posts', id: '1234', ... },
//   included: [ { type: 'users', id: 'abcd' } ]}

// Fetch multiple posts by ID, including users too
const { data } = await resolve('posts', ['1234', '5678']);
// { data: [
//    { type: 'posts', id: '1234', ... },
//    { type: 'posts', id: '5678', ... } ],
//   included: [ { type: 'users', id: 'abcd' } ]}
```

## Install

```sh
$ npm install jsonapi-resolvers
# or
$ yarn add jsonapi-resolvers
```

## API

### `createResolver(fetchers, opts?) => resolve`

Create a resolve function for a set of types.

Argument | Type | Description
---- | ---- | ----
`fetchers` | `Record<string, ResolveFunction>` | (**Required**) A dictionary of resolvers, where the name of each function should be the name of the type.
`opts?.links?.baseUrl` | `string` | If set, if `links` are included in the resolver responses they will be prepended by this `baseUrl` value. See [Rewriting `links`](#rewriting-links).

- Description of Resolve functions

### `resolve(type, id, opts?)`

Resolve one or more entries of a type by calling the fetcher with an ID / list of IDs.

Argument | Type | Description
---- | ---- | ----
`type` | `string` | (**Required**) The entry type you wish to resolve.
`id`/`ids` | `string`/`string[]` | (**Required**) The entry ID or IDs you wish to resolve.
`opts?.include` | `string[]` | An array of relationships you wish to expand
`opts?.fields` | `Record<string, string[]>` | A list of fields you'd like to return for each type, see [selecting fields](#selecting-fields).
`opts?.links?.baseUrl` | `string` | If set, if `links` are included in the resolver responses they will be prepended by this `baseUrl` value. See [Rewriting `links`](#rewriting-links).

- If you pass `opts.include`, [`resolve.included`](#resolveincludeddata-opts) will be called on your results automatically.
- If you pass `opts.links` to either [`createResolver`](#createresolverfetchers-opts--resolve) or this function, `resolve.links` will be called automatically.

### `resolve.included(data, opts)`

Given this entry or list of entries, fetch the requested included data.

Argument | Type | Description
---- | ---- | ----
`data` | `JsonApiResource`/`JsonApiResource[]` | (**Required**) The entry or list of entries to iterate over.
`opts.include` | `string[]` | (**Required**) An array of relationships you wish to expand
`opts.fields` | `Record<string, string[]>` | A list of fields you'd like to return for each type, see [selecting fields](#selecting-fields).
`opts.links?.baseUrl` | `string` | If set, if `links` are included in the included responses they will be prepended by this `baseUrl` value. See [Rewriting `links`](#rewriting-links).

### `resolve.links(links, opts)`

Given an object of links, rewrite them to fit the current request.

Argument | Type | Description
---- | ---- | ----
`links` | `Record<string, JsonApiLink | null>` | (**Required**) An object of links to iterate over.
`opts.baseUrl` | `string` | (**Required**) All links will be prepended by this `baseUrl` value. See [Rewriting `links`](#rewriting-links).

## Usage

### Inclusion of Related Resources

You can (recursively) resolve included entries by specifying the related resources in your `resolve` call.

```js
const resolve = createResolver({
  posts(ids) {
    // Fetch posts by ID in the JSONAPI format
    return [
      {
        type: 'posts',
        id: '1234',
        relationships: {
          // The author relationship is defined here
          // when you return the resolved posts
          author: { data: { type: 'users', id: 'abcd' } },
        },
      },
    ];
  },
  users(ids) {
    // Fetch users by ID in the JSONAPI format
    // Only when `author` is requested as an `include`d property
  },
});

const { data } = await resolve('posts', '1234', {
  include: ['author'],
});
// { data: { type: 'posts', id: '1234', ... },
//   included: [ { type: 'users', id: 'abcd', ... } ]}
```

You can also manually fetch a list of included entries, in cases where you have generated or built your primary data by hand & not with `resolve(...)`:

```js
const data = {
  type: 'custom.entry',
  id: 'FOO-BAR',
  relationships: {
    author: { data: { type: 'users', id: 'abcd' } },
  },
};

const included = await resolve.included(data, { include: ['author'] });
// [ { type: 'users', id: 'abcd', ... } ]
```

### Selecting fields

Pass a dict/list of fields to [`resolve`](#resolvetype-id-opts) for each entry type, which will be passed to each resolver function. You can then select/pick the exact fields you need to serve in your API response.

```js
const resolve = createResolver({
  posts(ids, { fields }) {
    // Fetch posts by ID in the JSONAPI format
    // Where fields is the array of fields for this type
  },
});

const { data } = await resolve('posts', '1234', {
  fields: {
    posts: ['title', 'excerpt'],
    users: ['name', 'email'],
  },
});

// And in your posts-by-id fetchers
// ids = ['1234']
// fields = ['title', 'excerpt']
```

### Rewriting `links`

To make working with different hostnames/paths during runtime easier, this library supports rewriting an entry's `links` property. For example, rather than passing core request logic all the way down to your `fetcher`, you can return relative URLs & rewrite the links to absolute URLs:

```js
const resolve = createResolver({
  posts(ids) {
    // Fetch posts by ID in the JSONAPI format
    return [
      {
        type: 'posts',
        id: '1234',
        links: {
          self: '/posts/1234',
          content: '/posts/1234/content',
          comments: '/comments?filter[post]=1234',
        },
      },
    ];
  },
});

const { data } = await resolve('posts', '1234', {
  links: {
    baseUrl: '/api/v1',
  },
});
// { data: {
//   type: 'posts',
//   id: '1234'
//   links: {
//     self: '/api/v1/posts/1234',
//     content: '/api/v1/posts/1234/content',
//     comments: '/api/v1/comments?filter[post]=1234' } }
```

## Notes

- For more information on the JSONAPI specification, [please see here](https://jsonapi.org/format/).
- Questions? Please [open an issue](https://github.com/someimportantcompany/jsonapi-resolvers/issues).

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