Skip to content

Commit c9beb40

Browse files
committed
Open source some useful filters from Strontium
1 parent efc5c22 commit c9beb40

File tree

8 files changed

+134
-3
lines changed

8 files changed

+134
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "strontium",
3-
"version": "2.8.0",
3+
"version": "2.8.1",
44
"description": "Strontium is a TypeScript toolkit for High Performance API servers built for Production not Projects.",
55
"main": "lib/src/index.js",
66
"types": "lib/src/index.d.ts",

src/utils/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export type ConstructorOf<T> = {
22
new (...arg: any[]): T
33
}
4+
5+
export type UUID = string
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ValidationError } from "../../../errors"
2+
import { isBase64 } from "validator"
3+
4+
export const isBase64EncodedString = (i: string): string => {
5+
if (isBase64(i)) {
6+
return i
7+
}
8+
9+
throw new ValidationError(
10+
"IS_BASE_64",
11+
"Value is not a Base64 string",
12+
"This value is not a Base64 string"
13+
)
14+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { ValidationError } from "../../../errors"
2+
3+
import { ValidatorFunction } from "../.."
4+
5+
export const isDictionary = <V>(
6+
keyValidator: ValidatorFunction<any, string>,
7+
valueValidator: ValidatorFunction<any, V>
8+
) => async (
9+
i: unknown
10+
): Promise<{
11+
[index: string]: V
12+
}> => {
13+
if (typeof i !== "object" || i === null) {
14+
throw new ValidationError(
15+
"IS_OBJECT",
16+
"Object validation failed",
17+
"This value should be an object."
18+
)
19+
}
20+
21+
let response: {
22+
[index: string]: V
23+
} = {}
24+
for (let p in i) {
25+
if (i.hasOwnProperty(p)) {
26+
let validatedKey = await keyValidator(p)
27+
28+
// Sadly ts-ignore this as TS doesn't understand that we have strongly ensured
29+
// that this property is present.
30+
// @ts-ignore
31+
let rawValue = i[p]
32+
33+
let validatedOutput = await valueValidator(rawValue)
34+
35+
if (validatedOutput !== undefined) {
36+
response[validatedKey] = validatedOutput
37+
}
38+
}
39+
}
40+
41+
return response
42+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { isExactly } from "./isExactly"
2+
3+
export const isEnumValue = <T>(enumObject: any): ((i: unknown) => T) => {
4+
let values = Object.values(enumObject)
5+
6+
return isExactly(values) as any
7+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { either } from "../helpers/either"
2+
import { Filter } from "../../../query"
3+
4+
import {
5+
ObjectValidator,
6+
ValidatedObject,
7+
ValidatorFunction,
8+
isArray,
9+
isObject,
10+
isUndefined,
11+
} from "../.."
12+
13+
export const isFilter = <V extends ObjectValidator>(
14+
objectSchema: V,
15+
depth: number = 0
16+
): ((i: unknown) => Promise<Filter<ValidatedObject<V>>>) => {
17+
if (depth > 10) {
18+
// Stub this to any as it is a library operational detail and would pollute the type system
19+
return undefined as any
20+
}
21+
22+
let validatorObject: { [key: string]: ValidatorFunction<any, any> } = {
23+
$and: either(isUndefined, isArray(isFilter(objectSchema, depth + 1))),
24+
$or: either(isUndefined, isArray(isFilter(objectSchema, depth + 1))),
25+
}
26+
27+
for (let key of Object.keys(objectSchema)) {
28+
validatorObject[key] = isFieldSelector(objectSchema[key])
29+
}
30+
31+
// Flag as any so that TypeScript doesn't get scared about the use of a recursive builder function
32+
return isObject(validatorObject) as any
33+
}
34+
35+
const isFieldSelector = (keyValidator: ValidatorFunction<any, any>) =>
36+
either(
37+
isUndefined,
38+
keyValidator,
39+
isObject({
40+
$in: either(isUndefined, isArray(keyValidator)),
41+
$nin: either(isUndefined, isArray(keyValidator)),
42+
$eq: either(isUndefined, keyValidator),
43+
$neq: either(isUndefined, keyValidator),
44+
$gt: either(isUndefined, keyValidator),
45+
$gte: either(isUndefined, keyValidator),
46+
$lt: either(isUndefined, keyValidator),
47+
$lte: either(isUndefined, keyValidator),
48+
$contains: either(isUndefined, keyValidator),
49+
})
50+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ValidationError } from "../../../errors"
2+
import { UUID } from "../../../utils/types"
3+
4+
import { isUUID as uuidValidator } from "validator"
5+
6+
export const isUUID = (i: string): UUID => {
7+
if (uuidValidator(i)) {
8+
return i
9+
}
10+
11+
throw new ValidationError(
12+
"IS_UUID",
13+
"Value must be a UUID V4",
14+
"This value must be a UUID V4"
15+
)
16+
}

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
2525

2626
"lib": [
27-
"ES6",
28-
"dom"
27+
"es6",
28+
"es2017.object"
2929
],
3030

3131
"typeRoots": [

0 commit comments

Comments
 (0)