forked from water-fountains/datablue
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
water-fountains#150 support forceRefresh byId
moreover: - fix getSingleBooleanQueryParam: looks like it is not always automatically parsed as boolean - cleanup eslint, no-unused-vars was duplicated resulting in undesired compile error
- Loading branch information
Showing
5 changed files
with
130 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,131 @@ | ||
import { Request } from 'express'; | ||
import { isArray, isObject } from 'lodash'; | ||
|
||
export function getSingleStringQueryParam(req: Request, paramName: string): string; | ||
export function getSingleStringQueryParam(req: Request, paramName: string, isOptional: true): string | undefined; | ||
export function getSingleStringQueryParam(req: Request, paramName: string, isOptional = false): string | undefined { | ||
return getSingleQueryParam(req, paramName, isOptional, 'string'); | ||
return getSingleQueryParamTypeOfCheck(req, paramName, isOptional, 'string'); | ||
} | ||
|
||
export function getSingleNumberQueryParam(req: Request, paramName: string): number; | ||
export function getSingleNumberQueryParam(req: Request, paramName: string, isOptional: true): number | undefined; | ||
export function getSingleNumberQueryParam(req: Request, paramName: string, isOptional = false): number | undefined { | ||
return getSingleQueryParam(req, paramName, isOptional, 'number'); | ||
export function getSingleNumericQueryParam(req: Request, paramName: string): number; | ||
export function getSingleNumericQueryParam(req: Request, paramName: string, isOptional: true): number | undefined; | ||
export function getSingleNumericQueryParam(req: Request, paramName: string, isOptional = false): number | undefined { | ||
return getSingleQueryParam( | ||
req, | ||
paramName, | ||
isOptional, | ||
'numeric', | ||
v => isNumeric(v), | ||
v => Number(v) | ||
); | ||
} | ||
|
||
export function isNumeric(v: string | undefined): boolean { | ||
if (typeof v === 'number') return true; | ||
if (typeof v !== 'string') return false; | ||
return ( | ||
// we also use parseFloat next to Number because Number returns 0 for a blank string and we don't want to accept a blank string | ||
// on the other hand parseFloat accepts things like `10 bananas` which we also don't want, thus the combination | ||
!isNaN(Number(v)) && !isNaN(parseFloat(v)) | ||
); | ||
} | ||
|
||
export function getSingleBooleanQueryParam(req: Request, paramName: string): boolean; | ||
export function getSingleBooleanQueryParam(req: Request, paramName: string, isOptional: true): boolean | undefined; | ||
export function getSingleBooleanQueryParam(req: Request, paramName: string, isOptional = false): boolean | undefined { | ||
return getSingleQueryParam(req, paramName, isOptional, 'boolean'); | ||
return getSingleQueryParam( | ||
req, | ||
paramName, | ||
isOptional, | ||
'boolean', | ||
v => typeof v === 'boolean' || v === 'true' || v === 'false', | ||
v => (typeof v === 'boolean' ? v : v === 'true') | ||
); | ||
} | ||
|
||
function getSingleQueryParamTypeOfCheck<T>( | ||
req: Request, | ||
paramName: string, | ||
isOptional: boolean, | ||
type: string | ||
): T | undefined { | ||
return getSingleQueryParam( | ||
req, | ||
paramName, | ||
isOptional, | ||
type, | ||
v => typeof v === type, | ||
v => v as unknown as T | ||
); | ||
} | ||
|
||
interface ParsedQs { | ||
[key: string]: undefined | string | string[] | ParsedQs | ParsedQs[]; | ||
} | ||
|
||
function getSingleQueryParam<T>( | ||
req: Request, | ||
paramName: string, | ||
isOptional: boolean, | ||
type: string, | ||
typeCheck: (v: string | undefined) => boolean, | ||
typeConversion: (v: string | undefined) => T | ||
): T | undefined { | ||
const param: undefined | string | string[] | ParsedQs[] = throwIfParsedQs(req.query[paramName], paramName); | ||
if (isArray(param)) { | ||
return getSingleQueryParamFromArray(param, paramName, isOptional, type, typeCheck, typeConversion); | ||
} else { | ||
return typeCheckAndConvertParam(param, paramName, isOptional, type, typeCheck, typeConversion); | ||
} | ||
} | ||
|
||
function getSingleQueryParamFromArray<T>( | ||
arr: string[] | ParsedQs[], | ||
paramName: string, | ||
isOptional: boolean, | ||
type: string, | ||
typeCheck: (v: string | undefined) => boolean, | ||
typeConversion: (v: string | undefined) => T | ||
): T | undefined { | ||
if (arr.length === 0 && isOptional) { | ||
return undefined; | ||
} else if (arr.length > 1) { | ||
throw Error(`${paramName} is not a single parameter, was ${JSON.stringify(arr)} with type ${typeof arr}`); | ||
} else { | ||
return typeCheckAndConvertParam( | ||
throwIfParsedQs(arr[0], paramName), | ||
paramName, | ||
isOptional, | ||
type, | ||
typeCheck, | ||
typeConversion | ||
); | ||
} | ||
} | ||
|
||
function typeCheckAndConvertParam<T>( | ||
param: string | undefined, | ||
paramName: string, | ||
isOptional: boolean, | ||
type: string, | ||
typeCheck: (v: string | undefined) => boolean, | ||
typeConversion: (v: string | undefined) => T | ||
): T | undefined { | ||
if (param === undefined && isOptional) { | ||
return undefined; | ||
} else if (typeCheck(param)) { | ||
return typeConversion(param); | ||
} else { | ||
throw Error(`${paramName} was of a wrong type, expected ${type} was ${JSON.stringify(param)} ${typeof param}`); | ||
} | ||
} | ||
|
||
function getSingleQueryParam<T>(req: Request, paramName: string, isOptional: boolean, type: string): T | undefined { | ||
const v = req.query[paramName]; | ||
// looks like we sometimes get numbers or booleans and not string even though query[x] does not include it in its type signature | ||
if (typeof v === type) return v as unknown as T; | ||
else if (v === undefined && isOptional) return undefined; | ||
else throw Error(`${paramName} is not a single parameter, was ${JSON.stringify(v)} with type ${typeof v}`); | ||
function throwIfParsedQs<T>(param: T | ParsedQs, paramName: string): T { | ||
if (isObject(param)) { | ||
throw Error( | ||
`${paramName} is not a single parameter, was an object ${JSON.stringify(param)} with type ${typeof param}` | ||
); | ||
} else { | ||
return param; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
// this file is automatically generated by git.version.js script | ||
const buildInfo = { | ||
version: '', | ||
revision: 'de728a0', | ||
branch: '#147-remove-deprecated-byCoords', | ||
commit_time: '2021-12-17 23:49:37 +0100', | ||
build_time: 'Mon Dec 20 2021 08:44:55 GMT+0100 (Central European Standard Time)', | ||
revision: '88376dc', | ||
branch: '#150-forceRefresh-id', | ||
commit_time: '2021-12-20 09:34:27 +0100', | ||
build_time: 'Mon Dec 20 2021 10:30:17 GMT+0100 (Central European Standard Time)', | ||
}; | ||
export default buildInfo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters