Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mediamonks/jsonapi-client
TypeScript JSON:API client for the browser
https://github.com/mediamonks/jsonapi-client
json-api json-api-client json-api-consumer
Last synced: about 1 month ago
JSON representation
TypeScript JSON:API client for the browser
- Host: GitHub
- URL: https://github.com/mediamonks/jsonapi-client
- Owner: mediamonks
- License: mit
- Created: 2019-10-24T11:48:09.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2023-12-11T08:39:11.000Z (about 1 year ago)
- Last Synced: 2024-11-28T13:42:46.617Z (about 1 month ago)
- Topics: json-api, json-api-client, json-api-consumer
- Language: TypeScript
- Homepage:
- Size: 25.2 MB
- Stars: 12
- Watchers: 17
- Forks: 1
- Open Issues: 30
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# jsonapi-client
## Install
```sh
yarn add @mediamonks/jsonapi-client
npm i -S @mediamonks/jsonapi-client
```## Usage
```typescript
import JSONAPI, { Attribute, Relationship } from '@mediamonks/jsonapi-client'
import { isString } from 'isntnt'// set up a Resource, passing the `type` and the endpoint path
export class Post extends JSONAPI.resource('Post', 'posts') {
@Attribute.required(isString) public title!: string
@Attribute.optional(isString) public content!: string | null
@Relationship.toOne(() => Author) public author!: Author | null
@Relationship.toMany(() => Comment) public comments!: Comment[]
}// create a client
const url = new URL('http://www.example.com/api')
const client = JSONAPI.client(url)// create an endpoint
const endpoint = client.endpoint(Post)// get single item
endpoint.getOne(id, {
fields: { [Post.type]: ['title, author']},
includes: { author: null },
}).then(result => console.log('one', result))// get collection
endpoint.getMany({
offset: 10,
limit: 3,
sort: ['title', '-author'],
filter: { 'author.id': authorId }
}, {
fields: { [Post.type]: ['title, author']},
includes: { author: null },
}).then(results => console.log('many', results))// create a new resource
endpoint.create({
title: 'foo',
content: 'bar'
}).then(result => console.log('new', result))// patch an existing resource
endpoint.patch(id, {
title: 'foo',
content: 'bar'
})// delete an existing resource
endpoint.delete(id)
```## Types
Below is a quick reference on the types you'll encounter or use on a daily basis.
**Resource**
* `ResourceId` - a `string`, alias for the resource id
* `ResourceType` - a `string`, alias for the resource type
* `ResourceIdentifier` - type for a basic resource with id/type fields
* `AnyResource` - an alias for the above, to represent any resource
* `ResourceConstructor` - type for a resource constructor/class* `ResourceCreateValues` - to type data objects to create a specific resource
* `ResourcePatchValues` - to type data objects to patch a specific resource* `ResourceParameters` - a type that represents a resource filter with fields and includes
**Endpoint**
* `Endpoint` - to type an Endpoint, potentially for a specific resource
* `EndpointResource>` - a helper type to extract a Resource from an Endpoint* `FilteredResource>` - to type a resource that only contains specific fields (both attributes and nested relationships).
* `ClientSearchParameters` - to type the collection query parameters for pagination, sorting, filtering, etc## Examples
### Filters
Basic example for fetching filtered resources.
```typescript
// create a filter
const postFilter = {
// It's good practise to specify which fields to return for all resources in the response.
// It's an object with the resource type as key, and an array with the fields as values.
// The field array should contain both attributes and relationships.
// A relationship specified here would only return the ResourceIdentifier (id/type), unless
// you also include the relationship below .
fields: {
[Post.type]: ['name', 'content', 'comments', 'author'],
[Comment.type]: ['title', 'author'],
[Author.type]: ['name', 'homepage'],
},// Specify which relationship fields from the above defintion to include as additional resources.
// The nesting here should follow the one from the Resource field specification.
// Setting `null` means that resource won't include any others, while an object can be used
// to specify includes for that nested relationship, and can go many levels deep.
// As can be seen, author should be included on both the Post and the Comment.
// The includes object starts with the fields of the Resource to filter, which should
// also be placed as first Resource in the field list by convention
include: {
comments: {
author: null,
},
author: null,
},
} as const
// note the `as const` - that's needed for type checking// this type contains only the (nested) field specified in the filter above
type FilteredPost = FilteredResourcelet items: Array
// the filter itself can be passed to the getOne/getMany methods
endpoint.getMany({}, postFilter).then(result => {
items = result
})
```Basic example on how to specify function parameters
```typescript
const postFilter = {
fields: {
[Post.type]: ['title', 'author'],
[Author.type]: ['name'],
},
include: { author: null },
} as constfunction renderPost(post: FilteredResource) {
// in here, only a few specific fields of `post` are used
// so it's good practise to use a filter instead of requesting the full Post type
}// when not needing nested resources, a `Pick` can be used as well
function renderPost(post: Pick) {
// in here, only a few specific fields of `post` are used
// so it's good practise to use a filter instead of requesting the full Post type
}
```