npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typing-qs

v12.1.2

Published

the purpose of this project is transforming search strings to types you need

Downloads

11

Readme

npm standard

type-qs ->中文文档

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 to parse your search to query first, then parse query with your template.

dependencies

  1. qs
  2. type-query-parser

differs with qs

the only differs with 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)

check and transform

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

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

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

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

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

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

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

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|undefined

if 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|undefined

if 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|undefined

if 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)=>string

the 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|undefined

if 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<any>) return a Parser
 
Parser:(value?:string)=>any|undefined

if 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<string>)=>Array<any>|Array<string>

if 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|undefined

if the value 'regExp.test(value)' is passed, it will return value, else it will undefined.

Parsers.date:

function Parsers.date(...dateLikeReduces: Array<DateLikeReduce>) return a Parser
 
Parser:(value?:string)=>DateLike|undefined

type 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<DateLikeReduce>) return a Parser
 
Parser:(value?:string)=>string|undefined

it 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<DateLikeReduce>) return a Parser
 
Parser:(value?:string)=>string|undefined

it 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.