-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathvalidate.ts
More file actions
94 lines (86 loc) · 2.55 KB
/
Copy pathvalidate.ts
File metadata and controls
94 lines (86 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// All of this is deprecated in favour of ./schema
// Will be kept around for a while.
import { type Address, getAddress } from "viem";
export type FieldParser<T> = Record<keyof T, FieldValidator<T[keyof T]>>;
export function validateInput<T>(
params: URLSearchParams,
validatorMapping: FieldParser<T>,
): T {
const fields = createFields<T>(validatorMapping);
return Object.fromEntries(
Object.entries(fields).map(([key, value]) => {
const { paramName, validator } = value as {
paramName: string;
validator: FieldValidator<T[keyof T]>;
};
return [key, validator(params.get(paramName), paramName)];
}),
) as T;
}
export function addressField(param: string | null, name: string): Address {
return parseField(param, name, getAddress, "Invalid Address field");
}
export function addressOrSymbolField(
param: string | null,
name: string,
): Address | string {
return parseField(
param,
name,
(value) => {
try {
return getAddress(value);
} catch {
return value;
}
},
"Invalid Address or Symbol field",
);
}
export function numberField(param: string | null, name: string): number {
const value = parseField(param, name, parseInt, "Invalid Float field");
if (isNaN(value)) {
throw new Error(`Invalid Integer field '${name}': Not a number`);
}
return value;
}
export function floatField(param: string | null, name: string): number {
const value = parseField(param, name, parseFloat, "Invalid Float parameter");
if (isNaN(value)) {
throw new Error(`Invalid Float parameter '${name}': Not a number`);
}
return value;
}
type FieldValidator<T> = (param: string | null, name: string) => T;
function createFields<T>(
validatorMapping: Record<keyof T, FieldValidator<unknown>>,
): Record<keyof T, { paramName: string; validator: FieldValidator<unknown> }> {
return Object.fromEntries(
(Object.keys(validatorMapping) as (keyof T)[]).map((key) => [
key,
{ paramName: key as string, validator: validatorMapping[key] },
]),
) as Record<
keyof T,
{ paramName: string; validator: FieldValidator<unknown> }
>;
}
function exists(param: string | null, name: string): string {
if (!param) {
throw new Error(`Missing required field: '${name}'`);
}
return param;
}
function parseField<T>(
param: string | null,
name: string,
parser: (value: string) => T,
errorMessage: string,
): T {
const value = exists(param, name);
try {
return parser(value);
} catch {
throw new Error(`${errorMessage} '${name}': ${value}`);
}
}