UNPKG

@vuex-orm/plugin-axios

Version:

Vuex ORM plugin for adding smooth integration with axios.

263 lines (257 loc) 7.86 kB
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 };