Skip to content

Commit

Permalink
feat(model): add method stringifyOptions (#254)
Browse files Browse the repository at this point in the history
* chore(deps): add `@types/qs`

* feat(model): add method `stringifyOptions`

* docs(configurations): add method `stringifyOptions`
  • Loading branch information
JoaoPedroAS51 authored Nov 21, 2022
1 parent 808d8c3 commit 03cbd69
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 3 deletions.
17 changes: 17 additions & 0 deletions docs/content/en/api/model-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ formData() {
}
```

### `stringifyOptions`
- Default: `{ encode: false, arrayFormat: 'comma' }`
- Returns: `object`

This method can be overridden in the model to configure `qs`.

See [qs](https://github.com/ljharb/qs#stringifying)

```js
stringifyOptions() {
return {
encode: false,
arrayFormat: 'comma',
}
}
```

## Model Options

These are model-related options.
Expand Down
53 changes: 53 additions & 0 deletions docs/content/en/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,52 @@ export default class Model extends BaseModel {
}
```

## Configuring Query Parameters Parser

See the [API reference](/api/model-options#stringifyOptions) and [qs](https://github.com/ljharb/qs#stringifying)

We may also need to configure the parser to match our needs. By default, it is configured to match
`spatie/laravel-query-builder`, which uses `comma` array format.

If we want, for example, to change this behaviour to `indices`, we can configure the stringify options of `qs`
by overriding the `stringifyOptions` method.

We can globally configure this in the [Base Model](/configuration#creating-a-base-model):

```js{}[~/models/Model.js]
import { Model as BaseModel } from 'vue-api-query'
export default class Model extends BaseModel {
// Define a base url for a REST API
baseURL() {
return 'http://my-api.com'
}
// Implement a default request method
request(config) {
return this.$http.request(config)
}
// Override default query parameter names
parameterNames() {
const defaultParams = super.parameterNames()
const customParams = {
include: 'include_custom'
}
return { ...defaultParams, ...customParams }
}
// Configure qs
stringifyOptions() {
return {
arrayFormat: 'indices'
}
}
}
```

## Configuring FormData

See the [API reference](/api/model-options#formdata) and [object-to-formdata](https://github.com/therealparmesh/object-to-formdata#usage)
Expand Down Expand Up @@ -331,6 +377,13 @@ export default class Model extends BaseModel {
return { ...defaultParams, ...customParams }
}
// Configure qs
stringifyOptions() {
return {
arrayFormat: 'indices'
}
}
// Configure object-to-formadata
formData() {
return {
Expand Down
10 changes: 10 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { IStringifyOptions } from 'qs'

type Method =
| 'get'
| 'GET'
Expand Down Expand Up @@ -443,6 +445,14 @@ export class Model extends StaticModel {
limit: string
}

/**
* This method can be overridden in the model to configure `qs`.
*
* @see {@link https://robsontenorio.github.io/vue-api-query/api/model-options#stringifyOptions|API Reference}
* @see {@link https://github.com/ljharb/qs#stringifying|qs}
*/
protected stringifyOptions(): IStringifyOptions

/**
* Query
*/
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"semantic-release": "^19.0.3"
},
"dependencies": {
"@types/qs": "^6.9.7",
"defu": "^6.0.0",
"dotprop": "^1.2.0",
"dset": "^3.1.2",
Expand Down
6 changes: 6 additions & 0 deletions src/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ export default class Model extends StaticModel {
}
}

stringifyOptions() {
return {
arrayFormat: 'comma'
}
}

/**
* Query
*/
Expand Down
12 changes: 9 additions & 3 deletions src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ export default class Parser {
let fields = { [this.parameterNames().fields]: this.builder.fields }
this.uri +=
this.prepend() +
qs.stringify(fields, { encode: false, arrayFormat: 'comma' })
qs.stringify(fields, {
encode: false,
...this.builder.model.stringifyOptions()
})
}

filters() {
Expand All @@ -117,7 +120,10 @@ export default class Parser {
let filters = { [this.parameterNames().filter]: this.builder.filters }
this.uri +=
this.prepend() +
qs.stringify(filters, { encode: false, arrayFormat: 'comma' })
qs.stringify(filters, {
encode: false,
...this.builder.model.stringifyOptions()
})
}

sorts() {
Expand Down Expand Up @@ -159,7 +165,7 @@ export default class Parser {
this.prepend() +
qs.stringify(this.builder.payload, {
encode: false,
arrayFormat: 'comma'
...this.builder.model.stringifyOptions()
})
}
}
31 changes: 31 additions & 0 deletions tests/builder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter'
import { Model } from '../src'
import ModelWithParamNames from './dummy/models/ModelWithParamNames'
import Post from './dummy/models/Post'
import PostWithOptions from './dummy/models/PostWithOptions'

describe('Query builder', () => {
let errorModel = {}
Expand Down Expand Up @@ -56,6 +57,36 @@ describe('Query builder', () => {
expect(post._builder.query()).toEqual(query)
})

test('it can change default array format option', () => {
let post = PostWithOptions.include('user').whereIn('status', [
'published',
'archived'
])

expect(post._builder.query()).toEqual(
'?include=user&filter[status][0]=published&filter[status][1]=archived'
)

expect(post._builder.filters).toEqual({
status: ['published', 'archived']
})

post = PostWithOptions.include('user').whereIn(
['user', 'status'],
['active', 'inactive']
)

expect(post._builder.query()).toEqual(
'?include=user&filter[user][status][0]=active&filter[user][status][1]=inactive'
)

expect(post._builder.filters).toEqual({
user: {
status: ['active', 'inactive']
}
})
})

test('include() sets properly the builder', () => {
let post = Post.include('user')

Expand Down
23 changes: 23 additions & 0 deletions tests/dummy/models/PostWithOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import BaseModel from './BaseModel'
import Comment from './Comment'
import Tag from './Tag'
import User from './User'

export default class PostWithOptions extends BaseModel {
comments() {
return this.hasMany(Comment)
}

relations() {
return {
user: User,
'relationships.tags': Tag
}
}

stringifyOptions() {
return {
arrayFormat: 'indices'
}
}
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,11 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==

"@types/qs@^6.9.7":
version "6.9.7"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==

"@types/retry@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
Expand Down

0 comments on commit 03cbd69

Please sign in to comment.