Skip to content

Commit 2110528

Browse files
authored
feat: add configurable persistBy option (#119)
1 parent 95e9db4 commit 2110528

File tree

14 files changed

+248
-50
lines changed

14 files changed

+248
-50
lines changed

docs/guide/configurations.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,22 @@ In addition to [axios request options](https://github.com/axios/axios#request-co
135135

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

138+
### `persistBy`
139+
140+
- **Type**: `string`
141+
- **Default**: `'insertOrUpdate'`
142+
143+
> Since 0.9.3+
144+
145+
This option determines which Vuex ORM persist method should be called when Vuex ORM Axios attempts to save the response data to the store.
146+
147+
You can set this option to any one of the following string values:
148+
149+
- `create`
150+
- `insert`
151+
- `update`
152+
- `insertOrUpdate` (default)
153+
138154
### `save`
139155

140156
- **Type**: `boolean`

docs/guide/usage.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,19 @@ Vuex ORM Axios will automatically save this data to the store, and the users ent
9494

9595
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.
9696

97+
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:
98+
99+
```js
100+
User.api().get('url', { persistBy: 'create' })
101+
```
102+
97103
If you do not want to persist response data automatically, you can defer persistence by configuring the request with the `{ save: false }` option.
98104

99105
**See also**:
100106

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

104111
### Delete Requests
105112

src/VuexORMAxios.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Model } from '@vuex-orm/core'
2-
import Components from './contracts/Components'
3-
import GlobalConfig from './contracts/GlobalConfig'
4-
import ModelMixin from './mixins/Model'
2+
import { Components } from './contracts/Components'
3+
import { GlobalConfig } from './contracts/Config'
4+
import { Model as ModelMixin } from './mixins/Model'
55

66
export default class VuexORMAxios {
77
/**
@@ -23,7 +23,7 @@ export default class VuexORMAxios {
2323
}
2424

2525
/**
26-
* Plug in features.
26+
* Plug-in features.
2727
*/
2828
plugin(): void {
2929
ModelMixin(this.model, this.config)

src/api/Request.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { AxiosInstance, AxiosResponse } from 'axios'
22
import { Model } from '@vuex-orm/core'
3-
import Config from '../contracts/Config'
4-
import Response from './Response'
3+
import { Config } from '../contracts/Config'
4+
import { Response } from './Response'
55

6-
export default class Request {
6+
export class Request {
77
/**
88
* The model class.
99
*/
@@ -13,7 +13,8 @@ export default class Request {
1313
* The default config.
1414
*/
1515
config: Config = {
16-
save: true
16+
save: true,
17+
persistBy: 'insertOrUpdate'
1718
}
1819

1920
/**

src/api/Response.ts

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { AxiosResponse } from 'axios'
22
import { Model, Record, Collections } from '@vuex-orm/core'
3-
import Config from '../contracts/Config'
3+
import { Config, PersistMethods } from '../contracts/Config'
44

5-
export default class Response {
5+
export class Response {
66
/**
77
* The model that called the request.
88
*/
@@ -45,19 +45,50 @@ export default class Response {
4545

4646
if (!this.validateData(data)) {
4747
console.warn(
48-
'[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.'
48+
'[Vuex ORM Axios] The response data could not be saved to the store ' +
49+
'because it is not an object or an array. You might want to use ' +
50+
'`dataTransformer` option to handle non-array/object response ' +
51+
'before saving it to the store.'
4952
)
5053

5154
return
5255
}
5356

54-
this.entities = await this.model.insertOrUpdate({ data })
57+
let method = this.config.persistBy as PersistMethods
58+
59+
if (!this.validatePersistMethod(method)) {
60+
console.warn(
61+
'[Vuex ORM Axios] The "persistBy" option configured is not a ' +
62+
'recognized value. Response data will be persisted by the ' +
63+
'default `insertOrUpdate` method.'
64+
)
65+
66+
method = 'insertOrUpdate'
67+
}
68+
69+
this.entities = await this.persist(method, { data })
5570

5671
this.isSaved = true
5772
}
5873

5974
/**
60-
* Delete store record depending on `delete` option.
75+
* Determine the method to be used to persist the payload to the store.
76+
*/
77+
persist(method: PersistMethods, payload: any): Promise<Collections> {
78+
switch (method) {
79+
case 'create':
80+
return this.model.create(payload)
81+
case 'insert':
82+
return this.model.insert(payload)
83+
case 'update':
84+
return this.model.update(payload)
85+
case 'insertOrUpdate':
86+
return this.model.insertOrUpdate(payload)
87+
}
88+
}
89+
90+
/**
91+
* Delete the entity record where the `delete` option is configured.
6192
*/
6293
async delete(): Promise<void> {
6394
if (this.config.delete === undefined) {
@@ -70,11 +101,12 @@ export default class Response {
70101
}
71102

72103
/**
73-
* Get data from the given response object. If the `dataTransformer` config is
74-
* provided, it tries to execute the method with the response as param. If the
75-
* `dataKey` config is provided, it tries to fetch the data at that key.
104+
* Get the response data from the axios response object. If a `dataTransformer`
105+
* option is configured, it will be applied to the response object. If the
106+
* `dataKey` option is configured, it will return the data from the given
107+
* property within the response body.
76108
*/
77-
private getDataFromResponse(): Record | Record[] {
109+
getDataFromResponse(): Record | Record[] {
78110
if (this.config.dataTransformer) {
79111
return this.config.dataTransformer(this.response)
80112
}
@@ -87,9 +119,17 @@ export default class Response {
87119
}
88120

89121
/**
90-
* Validate if Vuex ORM can insert the given data.
122+
* Validate the given data to ensure the Vuex ORM persist methods accept it.
91123
*/
92124
private validateData(data: any): data is Record | Record[] {
93125
return data !== null && typeof data === 'object'
94126
}
127+
128+
/**
129+
* Validate the given string as to ensure it correlates with the available
130+
* Vuex ORM persist methods.
131+
*/
132+
private validatePersistMethod(method: string): method is PersistMethods {
133+
return ['create', 'insert', 'update', 'insertOrUpdate'].includes(method)
134+
}
95135
}

src/contracts/Components.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,3 @@ import { Model } from '@vuex-orm/core'
33
export interface Components {
44
Model: typeof Model
55
}
6-
7-
export default Components

src/contracts/Config.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import { AxiosRequestConfig, AxiosResponse } from 'axios'
1+
import { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios'
22
import { Model, Record } from '@vuex-orm/core'
33

4+
export type PersistMethods = 'create' | 'insert' | 'update' | 'insertOrUpdate'
5+
46
export interface Config extends AxiosRequestConfig {
57
dataKey?: string
68
dataTransformer?: (response: AxiosResponse) => Record | Record[]
79
save?: boolean
10+
persistBy?: PersistMethods
811
delete?: string | number | ((model: Model) => boolean)
912
actions?: {
1013
[name: string]: any
1114
}
1215
}
1316

14-
export default Config
17+
export interface GlobalConfig extends Config {
18+
axios?: AxiosInstance
19+
}

src/contracts/GlobalConfig.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/index.cjs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import './types/vuex-orm'
22

3-
import Components from './contracts/Components'
4-
import GlobalConfig from './contracts/GlobalConfig'
3+
import { Components } from './contracts/Components'
4+
import { GlobalConfig } from './contracts/Config'
55
import VuexORMAxios from './VuexORMAxios'
66

77
export default {

src/index.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import './types/vuex-orm'
22

3-
import Components from './contracts/Components'
4-
import GlobalConfig from './contracts/GlobalConfig'
5-
import Config from './contracts/Config'
6-
import Request from './api/Request'
7-
import Response from './api/Response'
3+
import { Components } from './contracts/Components'
4+
import { Config, GlobalConfig } from './contracts/Config'
5+
import { Request } from './api/Request'
6+
import { Response } from './api/Response'
87
import VuexORMAxios from './VuexORMAxios'
98

109
export { GlobalConfig, Config, Request, Response }

0 commit comments

Comments
 (0)