src/account-validation.tsTypeScript
@@ -0,0 +1,53 @@
1+
export type AccountField = "email" | "displayName";2+
3+
export class ValidationError extends Error {4+
constructor(5+
public readonly code: "INVALID_INPUT",6+
public readonly field: AccountField | "input",7+
) {8+
super(code);9+
}10+
}11+
12+
export interface AccountValidationInput {13+
email?: string | null;14+
displayName?: string | null;15+
}16+
17+
export interface NormalizedAccountInput {18+
email?: string;19+
displayName?: string;20+
}21+
22+
function normalize(23+
value: string | null | undefined,24+
maximumLength: number,25+
field: AccountField,26+
): string | undefined {27+
if (!value) {28+
return undefined;29+
}30+
31+
if (value.length > maximumLength) {32+
throw new ValidationError("INVALID_INPUT", field);33+
}34+
35+
return value.trim();36+
}37+
38+
export function validateAccountInput(39+
input: AccountValidationInput,40+
): NormalizedAccountInput {41+
const email = normalize(input.email, 254, "email");42+
const displayName = normalize(input.displayName, 40, "displayName");43+
44+
if (email !== undefined && !/^[^@\s]+@[^@\s]+$/.test(email)) {45+
throw new ValidationError("INVALID_INPUT", "email");46+
}47+
48+
if (displayName !== undefined && displayName.length === 0) {49+
throw new ValidationError("INVALID_INPUT", "displayName");50+
}51+
52+
return { email, displayName };53+
}