kitsu
Version:
A simple, lightweight & framework agnostic JSON:API client using Axios
277 lines (273 loc) • 7.07 kB
JavaScript
'use strict';
var kitsuCore = require('kitsu-core');
var axios = require('axios');
var pluralise = require('pluralize');
class Kitsu {
constructor(options = {}) {
const traditional = typeof options.query === 'string' ? options.query === 'traditional' : true;
this.query = typeof options.query === 'function' ? options.query : obj => kitsuCore.query(obj, undefined, traditional);
if (options.camelCaseTypes === false) this.camel = s => s;else this.camel = kitsuCore.camel;
if (options.resourceCase === 'none') this.resCase = s => s;else if (options.resourceCase === 'snake') this.resCase = kitsuCore.snake;else this.resCase = kitsuCore.kebab;
if (options.pluralize === false) this.plural = s => s;else this.plural = pluralise;
this.headers = {
...{
Accept: 'application/vnd.api+json',
'Content-Type': 'application/vnd.api+json'
},
...options.headers
};
this.axios = axios.create({
...{
baseURL: options.baseURL || 'https://kitsu.app/api/edge',
timeout: options.timeout || 30000
},
paramsSerializer: {
serialize: p => this.query(p)
},
...options.axiosOptions
});
this.fetch = this.get;
this.update = this.patch;
this.create = this.post;
this.remove = this.delete;
this.interceptors = this.axios.interceptors;
}
async get(model, config = {}) {
try {
const headers = {
...this.headers,
...config.headers
};
const params = {
...{},
...config.params
};
const [res, id, relationship, subRelationship] = model.split('/');
let url = this.plural(this.resCase(res));
if (id) url += `/${this.resCase(id)}`;
if (relationship) url += `/${this.resCase(relationship)}`;
if (subRelationship) url += `/${this.resCase(subRelationship)}`;
const {
data,
headers: responseHeaders,
status
} = await this.axios.get(url, {
headers,
params,
...config.axiosOptions
});
return {
...kitsuCore.deserialise(data),
status,
...(responseHeaders && Object.keys(responseHeaders).length ? {
headers: responseHeaders
} : {})
};
} catch (E) {
throw kitsuCore.error(E);
}
}
async patch(model, body, config = {}) {
try {
const headers = {
...this.headers,
...config.headers
};
const params = {
...{},
...config.params
};
const [resourceModel, url] = kitsuCore.splitModel(model, {
resourceCase: this.resCase,
pluralModel: this.plural
});
const serialData = kitsuCore.serialise(resourceModel, body, 'PATCH', {
camelCaseTypes: this.camel,
pluralTypes: this.plural
});
const fullURL = body?.id ? `${url}/${body.id}` : url;
const {
data,
headers: responseHeaders,
status
} = await this.axios.patch(fullURL, serialData, {
headers,
params,
...config.axiosOptions
});
return {
...kitsuCore.deserialise(data),
status,
...(responseHeaders && Object.keys(responseHeaders).length ? {
headers: responseHeaders
} : {})
};
} catch (E) {
throw kitsuCore.error(E);
}
}
async post(model, body, config = {}) {
try {
const headers = {
...this.headers,
...config.headers
};
const params = {
...{},
...config.params
};
const [resourceModel, url] = kitsuCore.splitModel(model, {
resourceCase: this.resCase,
pluralModel: this.plural
});
const {
data,
headers: responseHeaders,
status
} = await this.axios.post(url, kitsuCore.serialise(resourceModel, body, 'POST', {
camelCaseTypes: this.camel,
pluralTypes: this.plural
}), {
headers,
params,
...config.axiosOptions
});
return {
...kitsuCore.deserialise(data),
status,
...(responseHeaders && Object.keys(responseHeaders).length ? {
headers: responseHeaders
} : {})
};
} catch (E) {
throw kitsuCore.error(E);
}
}
async delete(model, id, config = {}) {
try {
const headers = {
...this.headers,
...config.headers
};
const params = {
...{},
...config.params
};
const [resourceModel, url] = kitsuCore.splitModel(model, {
resourceCase: this.resCase,
pluralModel: this.plural
});
const isBulk = Array.isArray(id);
let path, payload;
if (isBulk) {
path = url;
payload = id.map(id => ({
id
}));
} else {
path = `${url}/${id}`;
payload = {
id
};
}
const {
data,
headers: responseHeaders,
status
} = await this.axios.delete(path, {
data: kitsuCore.serialise(resourceModel, payload, 'DELETE', {
camelCaseTypes: this.camel,
pluralTypes: this.plural
}),
headers,
params,
...config.axiosOptions
});
return {
...kitsuCore.deserialise(data),
status,
...(responseHeaders && Object.keys(responseHeaders).length ? {
headers: responseHeaders
} : {})
};
} catch (E) {
throw kitsuCore.error(E);
}
}
async self(config = {}) {
try {
const headers = {
...this.headers,
...config.headers
};
const params = {
...config.params,
...{
filter: {
self: true
}
}
};
const res = await this.get('users', {
...{
headers
},
...{
params
},
...config.axiosOptions
});
return {
...(res.headers && {
headers: res.headers
}),
...(res.data?.[0] && {
data: res.data[0]
})
};
} catch (E) {
throw kitsuCore.error(E);
}
}
async request({
body,
method,
params,
type,
url,
headers,
axiosOptions
}) {
try {
method = method?.toUpperCase() || 'GET';
const {
data,
headers: responseHeaders,
status
} = await this.axios.request({
method,
url,
data: ['GET', 'DELETE'].includes(method) ? undefined : kitsuCore.serialise(type, body, method, {
camelCaseTypes: this.camel,
pluralTypes: this.plural
}),
headers: {
...this.headers,
...headers
},
params,
...axiosOptions
});
return {
...kitsuCore.deserialise(data),
status,
...(responseHeaders && Object.keys(responseHeaders).length ? {
headers: responseHeaders
} : {})
};
} catch (E) {
throw kitsuCore.error(E);
}
}
}
module.exports = Kitsu;