https://github.com/filefoxper/type-qs
parse a location.search with type descriptions, and get a more useful query data
https://github.com/filefoxper/type-qs
browser location-search parsers qs-api query-parser querystring template type url-parser
Last synced: 4 months ago
JSON representation
parse a location.search with type descriptions, and get a more useful query data
- Host: GitHub
- URL: https://github.com/filefoxper/type-qs
- Owner: filefoxper
- License: mit
- Created: 2020-05-28T10:05:27.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-08-13T08:49:13.000Z (over 3 years ago)
- Last Synced: 2024-12-11T23:11:39.704Z (5 months ago)
- Topics: browser, location-search, parsers, qs-api, query-parser, querystring, template, type, url-parser
- Language: TypeScript
- Homepage:
- Size: 115 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE.md
Awesome Lists containing this project
README
[![npm][npm-image]][npm-url]
[![standard][standard-image]][standard-url][npm-image]: https://img.shields.io/npm/v/type-qs.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/type-qs
[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
[standard-url]: http://npm.im/standard# type-qs [->中文文档](https://github.com/filefoxper/type-qs/blob/master/readme_zh-cn.md)
# problem
When we parse a search from location, we often get an object like ```{[key: string]: string|string[]|undefined}```,
but we really want an object like ```{[key:string]:number|boolean|Date|string|string[]...} ``` which can describe more
types about the values. Also we want to validate these values, if they are invalid we can replace them from an default.# resolve
Here is a tool ```type-qs``` which can do something like transforming value type and replacing value which is invalid.
It use [qs](https://www.npmjs.com/package/qs) to parse your `search` to `query` first,
then parse query with your template.
# dependencies
1. [qs](https://www.npmjs.com/package/qs)
2. [type-query-parser](https://www.npmjs.com/package/type-query-parser)
# differs with qs
the only differs with [qs](https://www.npmjs.com/package/qs) is the parse function.parse(search: string, opt?: IParseOptions & { defaults?: any, template?: Template })
we add the template and defaults into options. So you can work with template to recompute your query and use defaults to replace the invalid query params.
if you set nothing about template, it works what qs.parse works.
# example (more in [test](https://github.com/filefoxper/type-qs/blob/master/test/index.test.ts))
check and transform
```js
import {parse} from 'type-qs';
import {Parsers} from 'type-qs/libs';...
const template={
id:Parsers.natural(), //get a natural number 0,1,2,3, ......
name:Parsers.string(true), //get a string data with trim option: boolean, if true then the name will be trimmed
active:Parsers.boolean(), //get a boolean data
role:Parsers.enum(['GUEST','USER','MASTER','ADMIN']),
//get a data which only can be one of 'GUEST'|'USER'|'MASTER'|'ADMIN'
page:Parsers.natural() //get a natural number, check out the source page is not a natural number, but 'abc', then get an undefined
};
const query=parse('id=123456&name= jimmy &active=true&role=MASTER&page=abc',{template});
...
console.log(query);/*** result ***/
{
id:123456,
name:'jimmy',
active:true,
role:'MASTER',
page:undefined
}
```
check and transform with default values
```js
import {parse} from 'type-qs';
import {Parsers} from 'type-qs/libs';...
const template={
id:Parsers.natural(), //get a natural number 0,1,2,3, ......
name:Parsers.string(true), //get a string data with trim option: boolean, if true then the name will be trimmed
active:Parsers.boolean(), //get a boolean data
role:Parsers.enum(['GUEST','USER','MASTER','ADMIN']),
//get a data which only can be one of 'GUEST'|'USER'|'MASTER'|'ADMIN'
page:Parsers.natural() //get a natural number, check out the source page is not a natural number, then get an undefined
};
const defaults={
role:'GUEST', //notice now we change role=MASTERR in search, and it should be undefined,
//but we give an defaults which contains a 'role' key
page:1
};
const query=parse('id=123456&name= jimmy &active=true&role=MASTERR&page=abc',{template,defaults});
...
console.log(query);/*** result ***/
{
id:123456,
name:'jimmy',
active:true,
role:'GUEST',
page:1
}
```
omit entries which we do not care
```js
import {parse} from 'type-qs';
import {Parsers} from 'type-qs/libs';...
const template={
ids:Parsers.array(),
}const query=parse('ids=1%2C2%2C3&useless=123',{template,defaults:{useless:'123'}}); //the url like ids=1,2,3&useless=123
...
console.log(query);/*** result ***/
{
ids:['1','2','3']
} //the 'useless' in url is omited, because the template has no key 'useless'
```
make array data type by numbers
```js
import {parse} from 'type-qs';
import {Parsers} from 'type-qs/libs';...
const template={
ids:Parsers.array(Parsers.natural()), //the param to Parses.array can be another Parser which use map array data to you want
}const query=parse('ids=1%2C2%2C3',{template}); //the url like ids=1,2,3
...
console.log(query);/*** result ***/
{
ids:[1,2,3]
}
```
make a custom Parser function
```js
import {parse} from 'type-qs';const numberToBoolean=(value:string='')=>{
if(value.trim()==='1'){
return true;
}
if(value.trim()==='0'){
return false
}
}const template={
active:numberToBoolean
}const query=parse('active=1',{template});
...
console.log(query);/*** result ***/
{
active:true
}
```
use qs abilities
```js
import {parse,stringify} from 'type-qs';
import {Parsers} from 'type-qs/libs';const source={
id:1,
more:{
active:true,
name:'Jimmy',
size:'ab'
}
};const template={
id:Parsers.natural(),
more:{
active:Parsers.boolean(),
name:Parsers.string(),
size:Parsers.natural()
}
};const defaults={
more:{
size:10
}
};const search = stringify(source); //id=1&more%5Bactive%5D=true&more%5Bname%5D=Jimmy&more%5Bsize%5D=ab
const result = parse(search,{template,defaults});
...
console.log(result);/*** result ***/
{
id:1,
more:{
active:true,
name:'Jimmy',
size:10 //from defaults
}
}
```
# api
parse `search` to an object you want by `template` and `defaults` in `opt`.types:
type Parser = (value?: string|string[]) => any|void;
`any function matches Parser is used to transform value to you want`type Template = {
[key: string]: Template | Parser
} | Parser[];
`any object matches Template is used to structure result you want`type IParseOption is from qs, you can learn it with [qs api](https://www.npmjs.com/package/qs)
type {defaults?:any}
`the default value you provide, when the value is undefined, the value in defaults with same key will replace the undefined one.`
```
function parse(search:string,opt?: IParseOptions & { defaults?: any,template?:Template })
```
stringify is from qs, you can earn it with [qs api](https://www.npmjs.com/package/qs)```
function stringify(obj: any, opt?: IStringifyOptions): string
```
Parsers provide some `Parser`, which is helpful, also you can write yourself Parsers.Parsers.number:
```
function Parsers.number() return a Parser
Parser:(value?:string)=>number|undefinedif the value isNaN (can not be a number), it will return an undefined value,
else it will provide a number value (typeof returnValue==='number').
```Parsers.natural:
```
function Parsers.natural() return a Parser
Parser:(value?:string)=>number|undefinedif the value can not be a natural number, it will return an undefined value,
else it will provide a natural number value (typeof returnValue==='number').
```Parsers.integer:
```
function Parsers.natural() return a Parser
Parser:(value?:string)=>number|undefinedif the value can not be a integer, it will return an undefined value,
else it will provide a integer value (typeof returnValue==='number').
```Parsers.string:
```
function Parsers.string(trim:boolean) return a Parser
Parser:(value?:string)=>stringthe value will be a string, if you set trim:true the string value will be trimmed.
```Parsers.boolean:
```
function Parsers.boolean() return a Parser
Parser:(value?:string)=>boolean|undefinedif the value trimmed is not 'true' or 'false', it will return an undefined value,
else it will provide a boolean value (typeof returnValue==='boolean').
```Parsers.enum:
```
function Parsers.enum(array:Array) return a Parser
Parser:(value?:string)=>any|undefinedif the value trimmed is not included in array, it will return an undefined value,
else it will return the one in array which matches value by '==' not '==='.
```Parsers.array:
```
function Parsers.array(mapper?: (data: string) => any) return a Parser
Parser: (value?: string | Array)=>Array|Arrayif the value is string, it will transform to array by string.split, then the array will map with mapper,
at last the mapped array will filter out the datas to a new array which data is not undefined.
```Parsers.regExp:
```
function Parsers.regExp(regExp: RegExp) return a Parser
Parser:(value?:string)=>string|undefinedif the value 'regExp.test(value)' is passed, it will return value, else it will undefined.
```Parsers.date:
```
function Parsers.date(...dateLikeReduces: Array) return a Parser
Parser:(value?:string)=>DateLike|undefinedtype DateLike = string | number | Date;
type DateLikeReduce = (dateLike: DateLike) => DateLike
if the value trimmed can be a Date value, it will return a DateLike value,
which might be produced by dateLikeReduces, else it will return undefined.here is some dateLikeReduces provided, they can help you use it more quickly:
startOfDay(dateLike: DateLike)=>Date // DateLike[2020-05-23 12:11:34] => new Date(2020-05-23 00:00:00:000)
endOfDay(dateLike: DateLike)=>Date // DateLike[2020-05-23 12:11:34] => new Date(2020-05-23 23:59:59:999)
toDateString(date: DateLike)=>string // DateLike[2020-05-23 12:11:34] => '2020-05-23'
toDatetimeString(date: DateLike)=>string // DateLike[2020-05-23 12:11:34] => '2020-05-23 12:11:34'
pattern(pat: string)=>formatDateLike(dateLike: DateLike)=>string
// pattern('YYYY-MM-DD HH:mm')=>formatter
// formatter(DateLike[2020-05-23 12:11:34])
// =>'2020-05-23 12:11'
we can use like this:
import {parse,Parsers} from 'type-qs';
import {startOfDay,pattern,endOfDay,toDatetimeString} from 'type-qs/libs';const template={
start:Parsers.date(startOfDay,pattern('YYYY-MM-DD HH:mm:ss')),
end:Parsers.date(endOfDay,toDatetimeString)
};const data=parse('start=2020-01-01%2011%3A11%3A11&end=2020-12-13%2010%3A01%3A18',{template});
/*** result ***/
{
start:'2020-01-01 00:00:00',
end:'2020-12-13 23:59:59'
}
```Parsers.datePattern:
```
function Parsers.datePattern(...dateLikeReduces: Array) return a Parser
Parser:(value?:string)=>string|undefinedit is just a wrap on Parsers.date, and returns a 'YYYY-MM-DD' formatted string value or undefined.
```Parsers.datetimePattern:
```
function Parsers.datetimePattern(...dateLikeReduces: Array) return a Parser
Parser:(value?:string)=>string|undefinedit is just a wrap on Parsers.date, and returns a 'YYYY-MM-DD HH:mm:ss' formatted string value or undefined.
```# summary
if you like this tool, give me a little start, thank you.