@vuex-orm/plugin-axios
Version:
Vuex ORM plugin for adding smooth integration with axios.
263 lines (257 loc) • 7.86 kB
JavaScript
class Response {
/**
* Create a new response instance.
*/
constructor(model, config, response) {
/**
* Entities created by Vuex ORM.
*/
this.entities = null;
/**
* Whether if response data is saved to the store or not.
*/
this.isSaved = false;
this.model = model;
this.config = config;
this.response = response;
}
/**
* Save response data to the store.
*/
async save() {
const data = this.getDataFromResponse();
if (!this.validateData(data)) {
console.warn('[Vuex ORM Axios] The response data could not be saved to the store ' +
'because it is not an object or an array. You might want to use ' +
'`dataTransformer` option to handle non-array/object response ' +
'before saving it to the store.');
return;
}
let method = this.config.persistBy || 'insertOrUpdate';
if (!this.validatePersistAction(method)) {
console.warn('[Vuex ORM Axios] The "persistBy" option configured is not a ' +
'recognized value. Response data will be persisted by the ' +
'default `insertOrUpdate` method.');
method = 'insertOrUpdate';
}
const options = this.getPersistOptions();
this.entities = await this.model[method]({ data, ...options });
this.isSaved = true;
}
/**
* Delete the entity record where the `delete` option is configured.
*/
async delete() {
if (this.config.delete === undefined) {
throw new Error('[Vuex ORM Axios] Could not delete records because the `delete` option is not set.');
}
await this.model.delete(this.config.delete);
}
/**
* Get the response data from the axios response object. If a `dataTransformer`
* option is configured, it will be applied to the response object. If the
* `dataKey` option is configured, it will return the data from the given
* property within the response body.
*/
getDataFromResponse() {
if (this.config.dataTransformer) {
return this.config.dataTransformer(this.response);
}
if (this.config.dataKey) {
return this.response.data[this.config.dataKey];
}
return this.response.data;
}
/**
* Get persist options if any set in config.
*/
getPersistOptions() {
const persistOptions = this.config.persistOptions;
if (!persistOptions || typeof persistOptions !== 'object') {
return;
}
return Object.keys(persistOptions)
.filter(this.validatePersistAction) // Filter to avoid polluting the payload.
.reduce((carry, key) => {
carry[key] = persistOptions[key];
return carry;
}, {});
}
/**
* Validate the given data to ensure the Vuex ORM persist methods accept it.
*/
validateData(data) {
return data !== null && typeof data === 'object';
}
/**
* Validate the given string as to ensure it correlates with the available
* Vuex ORM persist methods.
*/
validatePersistAction(action) {
return ['create', 'insert', 'update', 'insertOrUpdate'].includes(action);
}
}
class Request {
/**
* Create a new api instance.
*/
constructor(model) {
/**
* The default config.
*/
this.config = {
save: true
};
this.model = model;
this.registerActions();
}
/**
* Get the axios client.
*/
get axios() {
if (!this.model.axios) {
throw new Error('[Vuex ORM Axios] The axios instance is not registered. Please register the axios instance to the model.');
}
return this.model.axios;
}
/**
* Register actions from the model config.
*/
registerActions() {
const actions = this.model.apiConfig.actions;
if (!actions) {
return;
}
for (const name in actions) {
const action = actions[name];
typeof action === 'function'
? this.registerFunctionAction(name, action)
: this.registerObjectAction(name, action);
}
}
/**
* Register the given object action.
*/
registerObjectAction(name, action) {
this[name] = (config) => {
return this.request({ ...action, ...config });
};
}
/**
* Register the given function action.
*/
registerFunctionAction(name, action) {
this[name] = action.bind(this);
}
/**
* Perform a get request.
*/
get(url, config = {}) {
return this.request({ method: 'get', url, ...config });
}
/**
* Perform a post request.
*/
post(url, data = {}, config = {}) {
return this.request({ method: 'post', url, data, ...config });
}
/**
* Perform a put request.
*/
put(url, data = {}, config = {}) {
return this.request({ method: 'put', url, data, ...config });
}
/**
* Perform a patch request.
*/
patch(url, data = {}, config = {}) {
return this.request({ method: 'patch', url, data, ...config });
}
/**
* Perform a delete request.
*/
delete(url, config = {}) {
return this.request({ method: 'delete', url, ...config });
}
/**
* Perform an api request.
*/
async request(config) {
const requestConfig = this.createConfig(config);
const axiosResponse = await this.axios.request(requestConfig);
return this.createResponse(axiosResponse, requestConfig);
}
/**
* Create a new config by merging the global config, the model config,
* and the given config.
*/
createConfig(config) {
return {
...this.config,
...this.model.globalApiConfig,
...this.model.apiConfig,
...config
};
}
/**
* Create a new response instance by applying a few initialization processes.
* For example, it saves response data if `save` option id set to `true`.
*/
async createResponse(axiosResponse, config) {
const response = new Response(this.model, config, axiosResponse);
if (config.delete !== undefined) {
await response.delete();
return response;
}
config.save && (await response.save());
return response;
}
}
function Model(model, config) {
/**
* The api client.
*/
model.axios = config.axios || null;
/**
* The global api configuration for all models.
*/
model.globalApiConfig = config;
/**
* The api configuration for the model.
*/
model.apiConfig = {};
/**
* Set the given api client.
*/
model.setAxios = function (axios) {
this.axios = axios;
};
/**
* Get the api instance.
*/
model.api = function () {
return new Request(this);
};
}
class VuexORMAxios {
/**
* Create a new Vuex ORM Axios instance.
*/
constructor(components, config) {
this.model = components.Model;
this.config = config;
}
/**
* Plug-in features.
*/
plugin() {
Model(this.model, this.config);
}
}
var index = {
install(components, config) {
new VuexORMAxios(components, config).plugin();
}
};
export default index;
export { Request, Response };