A simple, lightweight & framework agnostic JSON:API client using Axios
Migration guide for v10 & previous major releases
- JSON-API 1.0 compliant
- Automatically links relationships to data
- Works in Node & browsers
- Uses the Promise API
Package | Package Size* |
ESM Size† | Node | Chrome | Firefox | Safari | Edge |
---|---|---|---|---|---|---|---|
kitsu |
≤ 8.7 kb | ≤ 8.6 KB | 14+ | 83+ | 78+ | 13.1+ | 95+ |
* Including all dependencies & minified with brotli † EcmaScript Modules package size*
Object from a GET Response by a JSON:API Server
{
data: {
id: '1'
type: 'articles'
attributes: {
title: 'JSON API paints my bikeshed'
}
relationships: {
author: {
data: {
id: '42'
type: 'people'
}
}
}
}
included: [
{
id: '42'
type: 'people'
attributes: {
name: 'John'
}
}
]
}
Object from a GET Response with kitsu:
{
data: {
id: '1'
type: 'articles'
title: 'JSON API paints my bikeshed'
author: {
data: {
id: '42'
type: 'people'
name: 'John'
}
}
}
}
yarn add kitsu
npm install kitsu
import Kitsu from "kitsu"; // ES Modules & Babel
const Kitsu = require("kitsu"); // CommonJS & Browserify
// kitsu.app's API
const api = new Kitsu()
// Other JSON:API servers
const api = new Kitsu({
baseURL: 'https://api.example/2'
})
// Using with async/await
const res = await api.get('anime')
// Using with Promises
api.get('anime')
.then(res => { ... })
.catch(err => { ... })
// Fetching resources (get/fetch)
api.fetch('anime')
api.fetch('anime', { params: { filter: { id: 1 } } })
api.fetch('anime/1/episodes')
api.fetch('anime/1/relationships/episodes')
// Creating resources (post/create)
api.create('post', {
content: 'some content'
})
// Updating resources (patch/update)
api.update('post', {
id: '1',
content: 'new content'
})
// Deleting resources (delete/remove)
api.remove('post', 1)
// JSON:API parameters
api.get('users', {
params: {
include: 'followers,waifu.character',
fields: {
users: 'slug,followers,waifu'
},
filter: {
slug: 'wopian'
},
sort: '-id',
page: {
limit: 5,
offset: 0
}
}
})
If you're working with kitsu.app's API, their API docs lists all available resources with their attributes & relationships
See CONTRIBUTING
See CHANGELOG
All code released under MIT
packages/kitsu/src/index.js:31-567
Creates a new kitsu
instance
-
options
Object? Options (optional, default{}
)-
options.baseURL
string Set the API endpoint (optional, default'https://kitsu.app/api/edge'
) -
options.headers
Object? Additional headers to send with the requests -
options.query
("traditional"
|"modern"
| Function) Query serializer function to use. This will impact the way keys are serialized when passing arrays as query parameters. 'modern' is recommended for new projects. (optional, defaulttraditional
) -
options.camelCaseTypes
boolean If enabled,type
will be converted to camelCase from kebab-casae or snake_case (optional, defaulttrue
) -
options.resourceCase
("kebab"
|"snake"
|"none"
) Case to convert camelCase to.kebab
-/library-entries
;snake
- /library_entries;
none-
/libraryEntries` (optional, defaultkebab
) -
options.pluralize
boolean If enabled,/user
will become/users
in the URL request andtype
will be pluralized in POST, PATCH and DELETE requests (optional, defaulttrue
) -
options.timeout
number Set the request timeout in milliseconds (optional, default30000
) -
options.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Using with kitsu.app's API
const api = new Kitsu()
Using another API server
const api = new Kitsu({
baseURL: 'https://api.example.org/2'
})
Setting headers
const api = new Kitsu({
headers: {
'User-Agent': 'MyApp/1.0.0 (github.com/username/repo)',
Authorization: 'Bearer 1234567890'
}
})
packages/kitsu/src/index.js:58-59
- See: https://www.npmjs.com/package/pluralize for documentation
- See: Kitsu constructor options for disabling pluralization
If pluralization is enabled (default, see Kitsu constructor docs) then pluralization rules can be added
Adding an uncountable pluralization rule
api.plural.plural('paper') //=> 'papers'
api.plural.addUncountableRule('paper')
api.plural.plural('paper') //=> 'paper'
packages/kitsu/src/index.js:73-73
Get the current headers or add additional headers
Get all headers
api.headers
Get a single header's value
api.headers['User-Agent']
Add or update a header's value
api.headers['Authorization'] = 'Bearer 1234567890'
Returns Object All the current headers
packages/kitsu/src/index.js:120-120
- See: https://github.com/axios/axios#interceptors for documentation
Axios Interceptors (alias of axios.interceptors
)
You can intercept responses before they are handled by get
, post
, patch
and delete
and before requests are sent to the API server.
Request Interceptor
// Add a request interceptor
api.interceptors.request.use(config => {
// Do something before request is sent
return config
}, error => {
// Do something with the request error
return Promise.reject(error)
})
Response Interceptor
// Add a response interceptor
api.interceptors.response.use(response => {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response
}, error => {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error)
})
Removing Interceptors
const myInterceptor = api.interceptors.request.use(function () {...})
api.interceptors.request.eject(myInterceptor)
packages/kitsu/src/index.js:218-253
Fetch resources (alias fetch
)
-
model
string Resource to fetch data from. Expected formats are:resource
,:resource/:id
,:resource/:id/:relationship
or:resource/:id/relationships/:relationship
-
config
Object? Additional configuration (optional, default{}
)-
config.headers
Object? Additional headers to send with the request -
config.params
Object? JSON:API request queries. JSON:API query parameters not listed are supported-
config.params.fields
Object? Return a sparse fieldset with only the included attributes/relationships - JSON:API Sparse Fieldsets -
config.params.filter
Object? Filter dataset by attribute values - JSON:API Filtering -
config.params.include
string? Include relationship data - JSON:API Includes -
config.params.sort
string? Sort dataset by one or more comma separated attributes (prepend-
for descending order) - JSON:API Sorting -
config.params.page
Object? JSON:API Pagination. All pagination strategies are supported, even if they are not listed below.-
config.params.page.limit
number? Number of resources to return in request (Offset-based) - Note: For kitsu.app, max is20
except onlibraryEntries
which has a max of500
-
config.params.page.offset
number? Number of resources to offset the dataset by (Offset-based) -
config.params.page.number
number? Page of resources to return in request (Page-based) - Note: Not supported on kitsu.app -
config.params.page.size
number? Number of resources to return in request (Page-based and cursor-based) - Note: Not supported on kitsu.app -
config.params.page.before
string? Get the previous page of resources (Cursor-based) - Note: Not Supported on kitsu.app -
config.params.page.after
string? Get the next page of resources (Cursor-based) - Note: Not Supported on kitsu.app
-
-
-
config.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Getting a resource with JSON:API parameters
api.get('users', {
params: {
fields: {
users: 'name,birthday'
},
filter: {
name: 'wopian'
}
}
})
Getting a collection of resources with their relationships
api.get('anime', {
params: {
include: 'categories'
}
})
Getting a single resource by ID (method one)
api.get('anime/2', {
params: {
include: 'categories'
}
})
Getting a single resource by ID (method two)
api.get('anime', {
params: {
include: 'categories',
filter: { id: '2' }
}
})
Getting a resource's relationship data only
api.get('anime/2/categories')
Getting a resource with nested JSON:API filters (not supported by kitsu.app's API)
// resource?filter[x][y]=value
api.get('resource', {
params: {
filter: {
x: {
y: 'value'
}
}
}
})
Handling errors (async/await)
try {
const { data } = await api.get('anime')
} catch (err) {
// Array of JSON:API errors: http://jsonapi.org/format/#error-objects
if (err.errors) err.errors.forEach(error => { ... })
// Error type (Error, TypeError etc.)
err.name
// Error message
err.message
// Axios request parameters
err.config
// Axios response parameters
err.response
}
Handling errors (Promises)
api.get('anime')
.then(({ data }) => { ... })
.catch(err => {
// Array of JSON:API errors: http://jsonapi.org/format/#error-objects
if (err.errors) err.errors.forEach(error => { ... })
// Error type (Error, TypeError etc.)
err.name
// Error message
err.message
// Axios request parameters
err.config
// Axios response parameters
err.response
})
Returns Promise<Object> JSON-parsed response
packages/kitsu/src/index.js:289-323
Update a resource (alias update
)
-
model
string Resource to update data in. Expected formats are:resource
,:resource/:id
,:resource/:id/:relationship
or:resource/:id/relationships/:relationship
-
config
Object? Additional configuration (optional, default{}
)-
config.params
Object? JSON:API request queries. See #get for documentation -
config.headers
Object? Additional headers to send with the request -
config.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Update a resource
api.update('posts', {
id: '1',
content: 'Goodbye World'
})
Update a resource with relationships
api.update('posts', {
content: 'Hello World',
uploads: {
id: '167585',
type: 'uploads'
}
})
Clear to-one relationships from a resource
api.update('posts/1/relationships/uploads', null)
Clear to-many relationships from a resource
api.update('posts/1/relationships/uploads', [])
Update multiple resources (API must support the Bulk Extension)
api.update('posts', [
{ id: '1', content: 'Hello World' },
{ id: '2', content: 'Another post' }
])
Returns Promise<(Object | Array<Object>)> JSON-parsed response
packages/kitsu/src/index.js:358-390
Create a new resource (alias create
)
-
model
string Resource to create. Expected formats are:resource
,:resource/:id
,:resource/:id/:relationship
or:resource/:id/relationships/:relationship
-
config
Object? Additional configuration (optional, default{}
)-
config.params
Object? JSON:API request queries. See #get for documentation -
config.headers
Object? Additional headers to send with the request -
config.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Create a post on a user's profile feed
api.create('posts', {
content: 'Hello World',
targetUser: {
data: {
id: '42603',
type: 'users'
}
},
user: {
data: {
id: '42603',
type: 'users'
}
}
})
Create multiple resources (API must support the Bulk Extension)
api.create('posts', [
{ content: 'Hello World' },
{ content: 'Another post' }
])
Returns Promise<(Object | Array<Object>)> JSON-parsed response
packages/kitsu/src/index.js:410-450
Remove a resource (alias remove
)
-
model
string Resource to remove. Expected formats are:resource
,:resource/:id/:relationship
or:resource/:id/relationships/:relationship
-
id
(string | number | Array<number>) Resource ID to remove. Pass an array of IDs to delete multiple resources (Bulk Extension) -
config
Object? Additional configuration (optional, default{}
)-
config.params
Object? JSON:API request queries. See #get for documentation -
config.headers
Object? Additional headers to send with the request -
config.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Remove one or more relationships from a resource
api.delete('posts/1/relationships/uploads', [456, 789])
Remove a single resource
api.delete('posts', 123)
Remove multiple resources (API must support the Bulk Extension)
api.delete('posts', [ 1, 2 ])
Returns Promise<(Object | Array<Object>)> JSON-parsed response
packages/kitsu/src/index.js:474-483
Get the authenticated user's data
Note Requires the JSON:API server to support filter[self]=true
-
config
Object? Additional configuration (optional, default{}
)-
config.params
Object? JSON:API request queries. See #get for documentation -
config.headers
Object? Additional headers to send with the request -
config.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Get the authenticated user's resource
api.self()
Using JSON:API parameters
api.self({
params: {
fields: {
users: 'name,birthday'
}
}
})
Returns Promise<Object> JSON-parsed response
packages/kitsu/src/index.js:538-566
Send arbitrary requests
Note Planned changes to the get
, patch
, post
and delete
methods in a future major release may make this method redundent. See https://github.com/wopian/kitsu/issues/415 for details.
-
config
Object Request configuration-
config.body
(Object | Array<Object>)? Data to send in the request -
config.method
string? Request method -GET
,PATCH
,POST
orDELETE
(defaults toGET
, case-insensitive) -
config.params
Object? JSON:API request queries. See #get for documentation -
config.type
string The resource type -
config.url
string The URL path of the resource -
config.headers
Object? Additional headers to send with the request -
config.axiosOptions
Object? Additional options for the axios instance (see axios/axios#request-config for details)
-
Raw GET request
api.request({
url: 'anime/1/mappings',
type: 'mappings',
params: { filter: { externalSite: 'aozora' } }
})
Raw PATCH request
api.request({
method: 'PATCH',
url: 'anime',
type: 'anime',
body: { id: '1', subtype: 'tv' }
})
Raw POST request
api.request({
method: 'PATCH',
url: 'anime',
type: 'anime',
body: { subtype: 'tv' }
})
Raw DELETE request
api.request({
method: 'DELETE',
url: 'anime/1',
type: 'anime',
body: { id: '1' }
})
Bulk Extension support (PATCH
, POST
& DELETE
)
api.request({
method: 'PATCH',
url: 'anime',
type: 'anime',
body: [
{ id: '1', subtype: 'tv' }
{ id: '2', subtype: 'ona' }
]
})