Add schema valiation

+ Using zod for validation
+ Add SchemaError
This commit is contained in:
Stephan
2022-05-01 17:18:55 +02:00
parent 2034faa448
commit 72ee918f00
3 changed files with 76 additions and 1 deletions
+2 -1
View File
@@ -31,7 +31,8 @@
"jsonwebtoken": "^8.5.1",
"nodemailer": "^6.7.0",
"redis": "^3.1.2",
"winston": "^3.7.2"
"winston": "^3.7.2",
"zod": "^3.14.4"
},
"devDependencies": {
"@types/chai": "^4.2.22",
+9
View File
@@ -0,0 +1,9 @@
import ForwardableError from "./ForwardableError";
export default class SchemaError extends ForwardableError {
protected __oid = "SCHEMA_ERROR";
constructor(message: string) {
super(400, message);
}
}
+65
View File
@@ -0,0 +1,65 @@
import { Schema, z, ZodError } from "zod";
import SchemaError from "../Middleware/error/SchemaError";
// -- Schema definitions --
const SchemaVersion = z.enum(["1.0"]);
const TimeUnit = z.enum(["days", "hours", "minutes", "seconds", "milliseconds"]);
const DurationSchema = z
.object({
type: z.literal("duration"),
min: z.number().int({ message: "min must be an integer (relative to smallestUnit)" }),
max: z.number().int({ message: "max must be an integer (relative to smallestUnit)" }),
smallestUnit: TimeUnit,
higherIsBetter: z.boolean(),
})
.refine(({ min, max }) => min < max, { message: "min must be smaller than max" });
const PointSchema = z
.object({
type: z.literal("points"),
min: z.number(),
max: z.number(),
step: z.number(),
start: z.number(),
unit: z.string(),
unitSign: z.string(),
higherIsBetter: z.boolean(),
})
.refine(({ min, max }) => min < max, { message: "min must be smaller than max" })
.refine(({ min, max, start }) => min <= start && max >= start, {
message: "start must be larger than or equal to min and smaller than or equal to max",
});
export type DurationSchemaT = z.infer<typeof DurationSchema>;
export type PointSchemaT = z.infer<typeof PointSchema>;
// -- Parser --
export function parseSchema(schema: any): DurationSchemaT | PointSchemaT {
try {
if (schema.type === "duration") {
return DurationSchema.parse(schema);
} else if (schema.type === "points") {
return PointSchema.parse(schema);
}
} catch (e) {
if (e instanceof ZodError) {
const issue = e.issues.at(0);
if (issue) {
throw new SchemaError(`${issue.path}: ${issue.message}`);
}
throw new SchemaError("Unknown error occured while validating the schema");
}
throw e;
}
throw new SchemaError("type must be either 'duration' or 'points'");
}