Skip to content
Open
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
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ VuexORM.use(VuexORMAxios, {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
},
// Include an HTTPConf for each entity
modelHttpConfigs: {
'todo': TodoHTTPConf
}
})
..
Expand All @@ -30,6 +34,46 @@ export default () => new Vuex.Store({

```

### HTTPConf (for each model)
``` js
export const TodoHTTPConf = {
http: {
url: '/batch'
},
methods: {
$fetch: {
name: 'fetch',
http: {
url: '',
method: 'get'
}
},
$get: {
name: 'get',
http: {
url: '/:id',
method: 'get',
},
},
$update: {
name: 'update',
http: {
url: '/:id/mark/',
method: 'put'
}
},
$delete: {
name: 'delete',
http: {
url: '/:id',
method: 'delete'
}
}
}
}
```


# Axios Request Config

``` js
Expand Down Expand Up @@ -203,7 +247,7 @@ User.$get({
params: {
id: 1
}
});
});

/**
* @uri `/users`
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@vuex-orm/core": "^0.26.2",
"deepmerge": "^3.2.0",
"lodash-es": "^4.17.11"
},
"devDependencies": {
Expand Down
32 changes: 22 additions & 10 deletions src/actions/Action.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import merge from 'lodash-es/merge'
// import merge from 'lodash-es/merge'
import * as deepmerge from 'deepmerge'
import Context from '../common/context'
import { ModuleConfig, ModelConfig } from '../support/interfaces'

Expand All @@ -8,7 +9,7 @@ export default class Action {
* @param {object} model
*/
static transformModule(module) {
return merge({}, ModuleConfig, module)
return deepmerge.all([{}, ModuleConfig, module])
}

/**
Expand All @@ -17,16 +18,16 @@ export default class Action {
*/
static transformModel(model) {
const context = Context.getInstance()
ModelConfig.http = merge({}, ModelConfig.http, context.options.http)
model.methodConf = merge({}, ModelConfig, model.methodConf)
ModelConfig.http = deepmerge.all([{}, ModelConfig.http, context.options.http])
model.methodConf = deepmerge.all([{}, ModelConfig, model.methodConf])
model.methodConf.http.url = model.methodConf.http.url === '/' ? `/${model.entity}` : model.methodConf.http.url

/**
* Add Model Interface to each model
*/
model.getFields = () => {
if (!model.cachedFields) {
model.cachedFields = merge(
model.cachedFields = deepmerge.all([
{},
{
$id: model.attr(undefined),
Expand All @@ -36,7 +37,7 @@ export default class Action {
$deleteErrors: model.attr([]),
},
model.fields()
)
])
}

return model.cachedFields
Expand All @@ -48,15 +49,21 @@ export default class Action {
/**
* Transform Params and Return Endpoint
* @param {string} type
* @param {object} model
* @param {object} config
* @param {object} HttpConf
* @param {object} config e.g. {params: {id:1}, query: {limit: 10, offset: 0}}
*/
static transformParams(type, model, config = {}) {
let endpoint = `${model.methodConf.http.url}${model.methodConf.methods[type].http.url}`
static transformParams(type, HttpConf, config = {}) {
// e.g. endpoint = `/batch/:id/mark`
let endpoint = `${HttpConf.http.url}${HttpConf.methods[type].http.url}`

// Create array of matching `/:id` params from endpoint, remove `/`.
// e.g. params = [":id"]
let params = (endpoint.match(/(\/?)(:)([A-z]*)/gm) || []).map(param => {
return param.replace('/', '')
})

// For each extracted param (e.g. `:id`) then try replace it with a value
// from config.params.
params.forEach(param => {
let paramName = param.replace(':', '')
const paramValue = paramName in config.params ? config.params[paramName] : ''
Expand All @@ -66,10 +73,15 @@ export default class Action {
const context = Context.getInstance()
let suffix = context.options.http.suffix
if (suffix) endpoint += suffix

// If any keys in the `config.query` dictionary then encode them correctly
// and attach to the end of the string.
if (config.query)
endpoint += `?${Object.keys(config.query)
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(config.query[k])}`)
.join('&')}`

console.log(`endpoint: ${endpoint}`)
return endpoint
}
}
24 changes: 18 additions & 6 deletions src/actions/Fetch.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as deepmerge from 'deepmerge'
import Axios from '../orm/axios'
import Context from '../common/context'
import Action from './Action'
import { ModelConfig } from '../support/interfaces'

export default class Fetch extends Action {
/**
Expand All @@ -11,12 +13,22 @@ export default class Fetch extends Action {
static async call({ state, commit }, params = {}) {
const context = Context.getInstance()
const model = context.getModelFromState(state)
const endpoint = Action.transformParams('$fetch', model, params)
const axios = new Axios(model.methodConf.http)
// Merge default http settings
ModelConfig.http = deepmerge.all([{}, ModelConfig.http, context.options.http])

// Get HTTPConf for this model
const HttpConf = context.getHttpConfigForModel(model.entity)
const endpoint = Action.transformParams('$fetch', HttpConf, params)

// New axios instance (with settings)
const axios = new Axios(ModelConfig.http)
const request = axios.get(endpoint)

this.onRequest(commit)
request.then(data => this.onSuccess(commit, model, data)).catch(error => this.onError(commit, error))

request
.then(data => this.onSuccess(commit, model, data))
.catch(error => this.onError(commit, error))

return request
}
Expand All @@ -31,15 +43,15 @@ export default class Fetch extends Action {

/**
* On Successful Request Method
* NOTE: At this point the `data` property is just the raw response from the
* server (other axios response properties have been stripped).
* @param {object} commit
* @param {object} model
* @param {object} data
*/
static onSuccess(commit, model, data) {
commit('onSuccess')
model.insertOrUpdate({
data,
})
model.insertOrUpdate({data})
}

/**
Expand Down
24 changes: 18 additions & 6 deletions src/actions/Get.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as deepmerge from 'deepmerge'
import Axios from '../orm/axios'
import Context from '../common/context'
import Action from './Action'
import { ModelConfig } from '../support/interfaces'

export default class Get extends Action {
/**
Expand All @@ -11,12 +13,22 @@ export default class Get extends Action {
static async call({ state, commit }, params = {}) {
const context = Context.getInstance()
const model = context.getModelFromState(state)
const endpoint = Action.transformParams('$get', model, params)
const axios = new Axios(model.methodConf.http)
// Merge default http settings
ModelConfig.http = deepmerge.all([{}, ModelConfig.http, context.options.http])

// Get HTTPConf for this model
const HttpConf = context.getHttpConfigForModel(model.entity)
const endpoint = Action.transformParams('$get', HttpConf, params)

// New axios instance (with settings)
const axios = new Axios(ModelConfig.http)
const request = axios.get(endpoint)

this.onRequest(commit)
request.then(data => this.onSuccess(commit, model, data)).catch(error => this.onError(commit, error))

request
.then(data => this.onSuccess(commit, model, data))
.catch(error => this.onError(commit, error))

return request
}
Expand All @@ -31,15 +43,15 @@ export default class Get extends Action {

/**
* On Successful Request Method
* NOTE: At this point the `data` property is just the raw response from the
* server (other axios response properties have been stripped).
* @param {object} commit
* @param {object} model
* @param {object} data
*/
static onSuccess(commit, model, data) {
commit('onSuccess')
model.insertOrUpdate({
data,
})
model.insertOrUpdate({data})
}

/**
Expand Down
22 changes: 20 additions & 2 deletions src/common/context.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import merge from 'lodash-es/merge'
// import merge from 'lodash-es/merge'
import * as deepmerge from 'deepmerge'
import { VuexOrmPluginConfig } from '../support/interfaces'

export default class Context {
Expand All @@ -11,9 +12,14 @@ export default class Context {
*/
constructor(components, options) {
this.components = components
this.options = merge({}, VuexOrmPluginConfig, options)
this.options = deepmerge.all([{}, VuexOrmPluginConfig, options])
this.database = options.database

if (!options.modelHttpConfigs) {
throw new Error('At least one modelHttpConf required')
}
this.modelHttpConfigs = options.modelHttpConfigs

if (!options.database) {
throw new Error('database option is required to initialise!')
}
Expand Down Expand Up @@ -45,4 +51,16 @@ export default class Context {
getModelFromState(state) {
return this.database.entities.find(({ name }) => name == state.$name).model
}

/**
* Returns an HTTPConf object for a given entity name
* @param {string} entityName
*/
getHttpConfigForModel(entityName) {
if (this.modelHttpConfigs.hasOwnProperty(entityName)) {
return this.modelHttpConfigs[entityName]
} else {
throw new Error(`No HTTPconfig found for entity: ${entityName}`)
}
}
}
13 changes: 6 additions & 7 deletions src/orm/axios.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ import axios from 'axios'

export default class Axios {
constructor(http) {
this.instance = axios.create(http);
this.setAuthentication(http.access_token);
this.instance = axios.create(http)
this.setAuthentication(http.access_token)

this.instance.interceptors.request.use(
config => http.onRequest(config),
error => http.onError(error),
);
)


this.instance.interceptors.request.use(
config => http.onRequest(config),
this.instance.interceptors.response.use(
config => http.onResponse(config),
error => http.onError(error),
);
)

return this.instance;
}
Expand Down
3 changes: 2 additions & 1 deletion src/vuex-orm-axios.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export default class VuexOrmAxios {
*/
context.database.entities.map(entity => {
entity.module = Action.transformModule(entity.module)
entity.model = Action.transformModel(entity.model)
// NOTE: This has been removed because it causes issues (IE11)
// entity.model = Action.transformModel(entity.model)
return entity
})

Expand Down