query parsers

This commit is contained in:
2020-12-25 13:46:43 +03:00
parent 569e90b529
commit d803dc06cf
5 changed files with 67 additions and 5 deletions

5
package-lock.json generated
View File

@ -4772,6 +4772,11 @@
"whatwg-url": "^8.0.0" "whatwg-url": "^8.0.0"
} }
}, },
"date-fns": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz",
"integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ=="
},
"debug": { "debug": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",

View File

@ -12,6 +12,7 @@
"@most/types": "^1.1.0", "@most/types": "^1.1.0",
"@types/uuid": "^8.3.0", "@types/uuid": "^8.3.0",
"axios": "^0.21.0", "axios": "^0.21.0",
"date-fns": "^2.16.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"fp-ts": "^2.8.5", "fp-ts": "^2.8.5",
"lodash": "^4.17.20", "lodash": "^4.17.20",

View File

@ -1,10 +1,54 @@
import {head} from 'lodash';
import {parse, ParsedUrlQuery} from 'querystring'; import {parse, ParsedUrlQuery} from 'querystring';
import {useMemo} from 'react'; import {useMemo} from 'react';
import {useLocation} from 'react-router-dom'; import {useLocation} from 'react-router-dom';
import {toNumber} from '../../utils/parsers';
type QueryParser<T> = (value?: string | string[]) => Undefinable<T>; type QueryParser<T> = (value?: string | string[]) => T;
export type QueryParsers<T> = Partial<{[K in keyof T]: QueryParser<T[K]>}>; export type QueryParsers<T> = Partial<{[K in keyof T]: QueryParser<T[K]>}>;
export function stringParser<T extends string>(): QueryParser<Undefinable<T>>;
export function stringParser<T extends string>(defaultValue: T): QueryParser<T>;
export function stringParser<T extends string>(defaultValue?: T) {
return (val?: string | string[]) => {
const value = Array.isArray(val) ? head(val) : val;
return value ?? defaultValue;
};
}
export function numberParser(): QueryParser<Undefinable<number>>;
export function numberParser(defaultValue?: number): QueryParser<number>;
export function numberParser(defaultValue?: number) {
return (val?: string | string[]) => {
const value = Array.isArray(val) ? head(val) : val;
return toNumber(value) ?? defaultValue;
};
}
export function booleanParser(): QueryParser<Undefinable<boolean>>;
export function booleanParser(defaultValue: boolean): QueryParser<boolean>;
export function booleanParser(defaultValue?: boolean) {
return (val?: string | string[]) => {
const value = Array.isArray(val) ? head(val) : val;
if (value === 'true') {
return true;
}
if (value === 'false') {
return false;
}
return defaultValue;
};
}
// Date parser
// Array parser (должен уметь с enum)
export function useQuery(): ParsedUrlQuery; export function useQuery(): ParsedUrlQuery;
export function useQuery<T extends {[name: string]: unknown}>(queryParsers: QueryParsers<T>): Partial<T>; export function useQuery<T extends {[name: string]: unknown}>(queryParsers: QueryParsers<T>): Partial<T>;
export function useQuery<T extends {[name: string]: unknown}>( export function useQuery<T extends {[name: string]: unknown}>(

View File

@ -1,16 +1,24 @@
import {format} from 'date-fns';
import {parse} from 'querystring'; import {parse} from 'querystring';
import React, {memo} from 'react'; import React, {memo} from 'react';
import {QueryParsers, useQuery} from '../../../../common/hooks/useQuery'; import {numberParser, QueryParsers, stringParser, useQuery} from '../../../../common/hooks/useQuery';
import {QueryResponse, QueryResponseError} from '../../types'; import {QueryResponse, QueryResponseError} from '../../types';
const enum PersonType {
One = 'one',
Two = 'two'
}
type Person = { type Person = {
name: string; name: string;
age: number; age?: number;
type: PersonType;
}; };
const parsers: QueryParsers<Person> = { const parsers: QueryParsers<Person> = {
name: name => name ? name.toString() : '', name: stringParser(''),
age: age => age ? Number(age) : undefined, age: numberParser(),
type: stringParser(PersonType.One),
}; };
const AuthResponsePage: React.FC = () => { const AuthResponsePage: React.FC = () => {

4
src/utils/parsers.ts Normal file
View File

@ -0,0 +1,4 @@
export const toNumber = (val: unknown): Undefinable<number> => {
const prepareValue = Number(val);
return Number.isNaN(prepareValue) ? undefined : prepareValue;
};