Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/guide/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,22 @@ In addition to [axios request options](https://github.com/axios/axios#request-co

**See also**: [Transforming Data](usage.md#transforming-data)

### `persistBy`

- **Type**: `string`
- **Default**: `'insertOrUpdate'`

> Since 0.9.3+

This option determines which Vuex ORM persist method should be called when Vuex ORM Axios attempts to save the response data to the store.

You can set this option to any one of the following string values:

- `create`
- `insert`
- `update`
- `insertOrUpdate` (default)

### `save`

- **Type**: `boolean`
Expand Down
9 changes: 8 additions & 1 deletion docs/guide/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,19 @@ Vuex ORM Axios will automatically save this data to the store, and the users ent

Under the hood, the plugin will persist data to the store by determining which records require inserting and which require updating. To accomplish this, the plugin passes data to the Vuex ORM `insertOrUpdate` model method. Therefore, only valid model attributes will be persisted to the store.

As of 0.9.3+ you may configure Vuex ORM Axios to persist data using an alternative Vuex ORM persist method other than the default `insertOrUpdate`. For example, you can refresh entities by passing the `persistBy` option as `'create'` which will persist data using the model's `create` method:

```js
User.api().get('url', { persistBy: 'create' })
```

If you do not want to persist response data automatically, you can defer persistence by configuring the request with the `{ save: false }` option.

**See also**:

- [Deferring Persistence](#deferring-persistence)
- [Vuex ORM - Insert or Update](https://vuex-orm.org/guide/data/inserting-and-updating.html#insert-or-update)
- [Configurations - persistBy](configurations.md#persistby)
- [Vuex ORM - Data - Inserting & Updating](https://vuex-orm.org/guide/data/inserting-and-updating.html#insert-or-update)

### Delete Requests

Expand Down
8 changes: 4 additions & 4 deletions src/VuexORMAxios.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Model } from '@vuex-orm/core'
import Components from './contracts/Components'
import GlobalConfig from './contracts/GlobalConfig'
import ModelMixin from './mixins/Model'
import { Components } from './contracts/Components'
import { GlobalConfig } from './contracts/Config'
import { Model as ModelMixin } from './mixins/Model'

export default class VuexORMAxios {
/**
Expand All @@ -23,7 +23,7 @@ export default class VuexORMAxios {
}

/**
* Plug in features.
* Plug-in features.
*/
plugin(): void {
ModelMixin(this.model, this.config)
Expand Down
9 changes: 5 additions & 4 deletions src/api/Request.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { AxiosInstance, AxiosResponse } from 'axios'
import { Model } from '@vuex-orm/core'
import Config from '../contracts/Config'
import Response from './Response'
import { Config } from '../contracts/Config'
import { Response } from './Response'

export default class Request {
export class Request {
/**
* The model class.
*/
Expand All @@ -13,7 +13,8 @@ export default class Request {
* The default config.
*/
config: Config = {
save: true
save: true,
persistBy: 'insertOrUpdate'
}

/**
Expand Down
60 changes: 50 additions & 10 deletions src/api/Response.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AxiosResponse } from 'axios'
import { Model, Record, Collections } from '@vuex-orm/core'
import Config from '../contracts/Config'
import { Config, PersistMethods } from '../contracts/Config'

export default class Response {
export class Response {
/**
* The model that called the request.
*/
Expand Down Expand Up @@ -45,19 +45,50 @@ export default class Response {

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.'
'[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
}

this.entities = await this.model.insertOrUpdate({ data })
let method = this.config.persistBy as PersistMethods

if (!this.validatePersistMethod(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'
}

this.entities = await this.persist(method, { data })

this.isSaved = true
}

/**
* Delete store record depending on `delete` option.
* Determine the method to be used to persist the payload to the store.
*/
persist(method: PersistMethods, payload: any): Promise<Collections> {
switch (method) {
case 'create':
return this.model.create(payload)
case 'insert':
return this.model.insert(payload)
case 'update':
return this.model.update(payload)
case 'insertOrUpdate':
return this.model.insertOrUpdate(payload)
}
}

/**
* Delete the entity record where the `delete` option is configured.
*/
async delete(): Promise<void> {
if (this.config.delete === undefined) {
Expand All @@ -70,11 +101,12 @@ export default class Response {
}

/**
* Get data from the given response object. If the `dataTransformer` config is
* provided, it tries to execute the method with the response as param. If the
* `dataKey` config is provided, it tries to fetch the data at that key.
* 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.
*/
private getDataFromResponse(): Record | Record[] {
getDataFromResponse(): Record | Record[] {
if (this.config.dataTransformer) {
return this.config.dataTransformer(this.response)
}
Expand All @@ -87,9 +119,17 @@ export default class Response {
}

/**
* Validate if Vuex ORM can insert the given data.
* Validate the given data to ensure the Vuex ORM persist methods accept it.
*/
private validateData(data: any): data is Record | Record[] {
return data !== null && typeof data === 'object'
}

/**
* Validate the given string as to ensure it correlates with the available
* Vuex ORM persist methods.
*/
private validatePersistMethod(method: string): method is PersistMethods {
return ['create', 'insert', 'update', 'insertOrUpdate'].includes(method)
}
}
2 changes: 0 additions & 2 deletions src/contracts/Components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@ import { Model } from '@vuex-orm/core'
export interface Components {
Model: typeof Model
}

export default Components
9 changes: 7 additions & 2 deletions src/contracts/Config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { AxiosRequestConfig, AxiosResponse } from 'axios'
import { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios'
import { Model, Record } from '@vuex-orm/core'

export type PersistMethods = 'create' | 'insert' | 'update' | 'insertOrUpdate'

export interface Config extends AxiosRequestConfig {
dataKey?: string
dataTransformer?: (response: AxiosResponse) => Record | Record[]
save?: boolean
persistBy?: PersistMethods
delete?: string | number | ((model: Model) => boolean)
actions?: {
[name: string]: any
}
}

export default Config
export interface GlobalConfig extends Config {
axios?: AxiosInstance
}
8 changes: 0 additions & 8 deletions src/contracts/GlobalConfig.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/index.cjs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './types/vuex-orm'

import Components from './contracts/Components'
import GlobalConfig from './contracts/GlobalConfig'
import { Components } from './contracts/Components'
import { GlobalConfig } from './contracts/Config'
import VuexORMAxios from './VuexORMAxios'

export default {
Expand Down
9 changes: 4 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import './types/vuex-orm'

import Components from './contracts/Components'
import GlobalConfig from './contracts/GlobalConfig'
import Config from './contracts/Config'
import Request from './api/Request'
import Response from './api/Response'
import { Components } from './contracts/Components'
import { Config, GlobalConfig } from './contracts/Config'
import { Request } from './api/Request'
import { Response } from './api/Response'
import VuexORMAxios from './VuexORMAxios'

export { GlobalConfig, Config, Request, Response }
Expand Down
9 changes: 3 additions & 6 deletions src/mixins/Model.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { AxiosInstance } from 'axios'
import { Model as BaseModel } from '@vuex-orm/core'
import GlobalConfig from '../contracts/GlobalConfig'
import Request from '../api/Request'
import { GlobalConfig } from '../contracts/Config'
import { Request } from '../api/Request'

export default function Model(
model: typeof BaseModel,
config: GlobalConfig
): void {
export function Model(model: typeof BaseModel, config: GlobalConfig): void {
/**
* The api client.
*/
Expand Down
5 changes: 2 additions & 3 deletions src/types/vuex-orm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AxiosInstance } from 'axios'
import GlobalConfig from '../contracts/GlobalConfig'
import Config from '../contracts/Config'
import Request from '../api/Request'
import { Config, GlobalConfig } from '../contracts/Config'
import { Request } from '../api/Request'

declare module '@vuex-orm/core' {
namespace Model {
Expand Down
Loading