Open pitcher-maarten opened 2 years ago
I'm facing similar problem updating to Nuxt 3 rc 11. My queries become unusable and had to revert back. Can we skip withQuery to resolve this issue or does anyone have any ideas?
Make wrapper function for fetch:
import { ofetch } from 'ofetch'
const myQuerySerializer = (params) => {
// Use your favorite serializer:
// https://www.npmjs.com/package/qs
// http://api.jquery.com/jquery.param/
return '?serialized=params'
}
/**
* Accept fetch instance and wrap it with custom function,
* which make some modifications before execute request
*
* Returns function, same signature as original fetch
*/
function wrapFetch (fetch) {
return (request, options) => {
// before
console.log('original request', {
request, // string
options, // { params: {...} }
})
// modify request if has params in options
let modifiedRequest, modifiedOptions
if (options && options.params) {
// append params string and delete params from options
modifiedRequest = request + myQuerySerializer(options.params)
modifiedOptions = _.omit(options, ['params'])
} else {
// use as is
modifiedRequest = request
modifiedOptions = options
}
// after
console.log('modified request', {
request: modifiedRequest,
options: modifiedOptions,
})
return fetch(modifiedRequest, modifiedOptions)
}
}
class Api {
constructor (fetch) {
this.fetch = wrapFetch(fetch)
}
getPosts (params = {}) {
return this.fetch('/post', { params })
}
}
const apiFetch = ofetch.create({
baseURL: '/api',
onRequest ({ options }) {
options.headers = {
Authorization: 'Bearer ...' // bonus 😃
}
},
})
// api usage
const api = new Api(apiFetch)
const posts = await api.getPosts({
// this params will be serialized by myQuerySerializer
param1: 'value1',
param2: 'value2',
})
console.log('posts:', posts)
@lukas-pierce That would work, but looks like a workaround, is there no proper support of custom query serializers?
@lukas-pierce That would work, but looks like a workaround, is there no proper support of custom query serializers?
No, I checked original library sources, need request to library author
qs.stringify(options.params, { arrayFormat: 'comma', encode: false })
Yeah, this works even you can simplify the wrapper function, but still this is not the real solution, it is workaround, unfortunately ofetch does not support this feature yet, hope it will soon
You can use a simple function to do this
Prerequisites:
Serializer
function serializeQuery(query: Record<string, any>) {
const queryString = qs.stringify(query, { encode: false })
return queryString.split('&').reduce<Record<string, any>>((acc, part) => {
const [key, value] = part.split('=')
acc[key] = value
return acc
}, {})
}
ofetch instance
ofetch.create({
baseURL: import.meta.env.VITE_APP_VOCABS_API,
async onRequest({ options }) {
if (options.query)
options.query = serializeQuery(options.query)
},
})
How to use
ofetchInstance('/api', {
query: {
where: {
key: { equals: 'foo' },
},
limit: 0,
},
})
As a result
{
where: {
key: { equals: 'foo' },
},
limit: 0,
}
serialized to ?where[key][equals]=foo&limit=0
As Axios does have the paramsSerializer I wanted to recreate this behaviour in combination with qs. To achieve this I've created an $fetch instance:
The request params:
After stringify
options.params
results in:The request by ohmyfetch:
As you can see the params are getting destructed by
withQuery
https://github.com/unjs/ohmyfetch/blob/main/src/fetch.ts#L109This issue is similar to: https://github.com/unjs/ohmyfetch/issues/117