78 lines
1.9 KiB
Plaintext
78 lines
1.9 KiB
Plaintext
import { decode, encode } from './qss'
|
|
import type { AnySchema } from './validators'
|
|
|
|
export const defaultParseSearch = parseSearchWith(JSON.parse)
|
|
export const defaultStringifySearch = stringifySearchWith(
|
|
JSON.stringify,
|
|
JSON.parse,
|
|
)
|
|
|
|
export function parseSearchWith(parser: (str: string) => any) {
|
|
return (searchStr: string): AnySchema => {
|
|
if (searchStr.substring(0, 1) === '?') {
|
|
searchStr = searchStr.substring(1)
|
|
}
|
|
|
|
const query: Record<string, unknown> = decode(searchStr)
|
|
|
|
// Try to parse any query params that might be json
|
|
for (const key in query) {
|
|
const value = query[key]
|
|
if (typeof value === 'string') {
|
|
try {
|
|
query[key] = parser(value)
|
|
} catch (err) {
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
return query
|
|
}
|
|
}
|
|
|
|
export function stringifySearchWith(
|
|
stringify: (search: any) => string,
|
|
parser?: (str: string) => any,
|
|
) {
|
|
function stringifyValue(val: any) {
|
|
if (typeof val === 'object' && val !== null) {
|
|
try {
|
|
return stringify(val)
|
|
} catch (err) {
|
|
// silent
|
|
}
|
|
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
try {
|
|
// Check if it's a valid parseable string.
|
|
// If it is, then stringify it again.
|
|
parser(val)
|
|
return stringify(val)
|
|
} catch (err) {
|
|
// silent
|
|
}
|
|
}
|
|
return val
|
|
}
|
|
|
|
return (search: Record<string, any>) => {
|
|
search = { ...search }
|
|
|
|
Object.keys(search).forEach((key) => {
|
|
const val = search[key]
|
|
if (typeof val === 'undefined' || val === undefined) {
|
|
delete search[key]
|
|
} else {
|
|
search[key] = stringifyValue(val)
|
|
}
|
|
})
|
|
|
|
const searchStr = encode(search as Record<string, string>).toString()
|
|
|
|
return searchStr ? `?${searchStr}` : ''
|
|
}
|
|
}
|
|
|
|
export type SearchSerializer = (searchObj: Record<string, any>) => string
|
|
export type SearchParser = (searchStr: string) => Record<string, any>
|