rozwiązanie kolejnych todo i pozbycie się zbędnych paczek npm.
This commit is contained in:
@@ -62,25 +62,31 @@ export function stringifyContent(collections: CollectionModel[], opts: GenerateO
|
||||
break;
|
||||
|
||||
case "email":
|
||||
const onlyDomainsConstraint = createEmailDomainConstraint(field.onlyDomains, true);
|
||||
const exceptDomainsConstraint = createEmailDomainConstraint(field.exceptDomains, false);
|
||||
const onlyDomainsConstraint = createDomainConstraint(field.onlyDomains, true, "email");
|
||||
const exceptDomainsConstraint = createDomainConstraint(field.exceptDomains, false, "email");
|
||||
|
||||
schema = `z.string().email()${onlyDomainsConstraint}${exceptDomainsConstraint}`;
|
||||
break;
|
||||
|
||||
case "file":
|
||||
// TODO: implement maxSize, mimeTypes, protected, thumbs
|
||||
// NOTE: PocketBase API returns only filenames in responses, limiting validation capabilities.
|
||||
// Full file validation (size, MIME types, etc.) should be implemented at the create record endpoint.
|
||||
// const mimeTypesArray: string[] = field.mimeTypes || [];
|
||||
const maxSelectFile: number = field.maxSelect;
|
||||
const maxSizeFile: number = field.maxSize;
|
||||
const mimeTypesArray: string[] = field.mimeTypes || [];
|
||||
// const protectedFile: boolean = field.protected;
|
||||
// const thumbsFileArray: string[] = field.thumbs || [];
|
||||
// const maxSizeFile: number = field.maxSize;
|
||||
const maxSelectFile: number = field.maxSelect;
|
||||
|
||||
const fileFieldMaxSelect = maxSelectFile ? `.max(${maxSelectFile})` : "";
|
||||
const fileFieldTypeArray = maxSelectFile === 1 ? "" : `.array()${fileFieldMaxSelect}`;
|
||||
|
||||
schema = `z.string()${fileFieldTypeArray}`;
|
||||
let fileValidation = "z.instanceof(File)";
|
||||
|
||||
if (maxSizeFile) fileValidation += `.refine((file) => file.size <= ${maxSizeFile}, { message: "File size too large" })`;
|
||||
|
||||
if (mimeTypesArray.length > 0)
|
||||
fileValidation += `.refine((file) => ${JSON.stringify(mimeTypesArray)}.includes(file.type), { message: "Invalid file type" })`;
|
||||
|
||||
const baseFileSchema = `z.union([z.string(), ${fileValidation}])`;
|
||||
schema = `${baseFileSchema}${fileFieldTypeArray}`;
|
||||
break;
|
||||
|
||||
case "json":
|
||||
@@ -88,42 +94,43 @@ export function stringifyContent(collections: CollectionModel[], opts: GenerateO
|
||||
break;
|
||||
|
||||
case "number":
|
||||
// if (collectionName === "testFiles") console.log(`${collectionName}:`, field);
|
||||
const maxNumber = field.maxNumber;
|
||||
const minNumber = field.minNumber;
|
||||
const noDecimal = field.noDecimal;
|
||||
schema = `z.number()${noDecimal ? ".int()" : ""}${minNumber ? `.min(${minNumber})` : ""}${maxNumber ? `.max(${maxNumber})` : ""}`;
|
||||
const maxNumber = field.maxNumber ? `.max(${field.maxNumber})` : "";
|
||||
const minNumber = field.minNumber ? `.min(${field.minNumber})` : "";
|
||||
const noDecimal = field.noDecimal ? ".int()" : "";
|
||||
|
||||
schema = `z.number()${noDecimal}${minNumber}${maxNumber}`;
|
||||
break;
|
||||
|
||||
case "relation":
|
||||
// TODO: implement cascadeDelete, displayFields, multiple records
|
||||
const required = field.required;
|
||||
const maxSelectRelation = field.maxSelect;
|
||||
const minSelectRelation = field.minSelect;
|
||||
const min = `.min(${minSelectRelation})`;
|
||||
const max = `.max(${maxSelectRelation})`;
|
||||
const multiple = maxSelectRelation === 1 ? "" : `.array()${min}${max}`;
|
||||
const isOptional = required || maxSelectRelation !== 1 ? `` : `.transform((id) => id === "" ? undefined : id)`;
|
||||
// TODO: implement cascadeDelete, displayFields, multiple records query
|
||||
const multiple = field.maxSelect === 1 ? "" : `.array().min(${field.minSelect}).max(${field.maxSelect})`;
|
||||
const isOptional = field.required || field.maxSelect !== 1 ? `` : `.transform((id: string) => id === "" ? undefined : id)`;
|
||||
|
||||
schema = `z.string()${isOptional}${multiple}`;
|
||||
break;
|
||||
|
||||
case "select":
|
||||
const maxSelect = field.maxSelect;
|
||||
// if (collectionName === "testFiles") console.log(`${collectionName}:`, field);
|
||||
// TODO: implement values
|
||||
const maxSelect = field.maxSelect;
|
||||
|
||||
schema = `${opts.nameEnumSchema(opts.nameEnumField(collectionName, field.name))}${maxSelect === 1 ? "" : `.array().max(${maxSelect})`}`;
|
||||
break;
|
||||
|
||||
case "text":
|
||||
const maxText = field.max;
|
||||
const minText = field.min;
|
||||
// TODO: implement pattern
|
||||
schema = `z.string()${minText ? `.min(${minText})` : ""}${maxText ? `.max(${maxText})` : ""}`;
|
||||
const patternText =
|
||||
field.pattern && field.pattern.trim() !== "" ? `.regex(new RegExp("${field.pattern.replace(/"/g, '\\"')}"))` : "";
|
||||
const maxText = field.max ? `.max(${field.max})` : "";
|
||||
const minText = field.min ? `.min(${field.min})` : "";
|
||||
|
||||
schema = `z.string()${minText}${maxText}${patternText}`;
|
||||
break;
|
||||
|
||||
case "url":
|
||||
// TODO: implement exceptDomains and onlyDomains
|
||||
schema = "z.string().url()";
|
||||
const onlyDomainsUrlConstraint = createDomainConstraint(field.onlyDomains, true, "url");
|
||||
const exceptDomainsUrlConstraint = createDomainConstraint(field.exceptDomains, false, "url");
|
||||
|
||||
schema = `z.string().url()${onlyDomainsUrlConstraint}${exceptDomainsUrlConstraint}`;
|
||||
break;
|
||||
|
||||
case "geoPoint":
|
||||
@@ -140,11 +147,19 @@ export function stringifyContent(collections: CollectionModel[], opts: GenerateO
|
||||
|
||||
/* Helpers */
|
||||
|
||||
const createEmailDomainConstraint = (domains: string[], isWhitelist: boolean) => {
|
||||
const createDomainConstraint = (domains: string[], isWhitelist: boolean, type: "email" | "url") => {
|
||||
if (!domains?.length) return "";
|
||||
|
||||
const domainsList = domains.map((domain) => `"${domain}"`).join(", ");
|
||||
const messageType = isWhitelist ? "isn't one of the allowed ones" : "is one of the disallowed ones";
|
||||
return `.refine((email) => { const domain = email.split("@")[1]; const domainsArray = [${domainsList}]; return domain && ${isWhitelist ? "" : "!"}domainsArray.includes(domain); }, { message: "Invalid email, email domain ${messageType}" })`;
|
||||
const negation = isWhitelist ? "" : "!";
|
||||
|
||||
const domainExtraction = type === "email" ? 'const domain = value.split("@")[1];' : "const domain = new URL(value).hostname;";
|
||||
|
||||
const errorHandling = type === "url" ? "try { " : "";
|
||||
const errorCatch = type === "url" ? " } catch { return false; }" : "";
|
||||
|
||||
return `.refine((value: string) => { ${errorHandling}${domainExtraction} const domainsArray = [${domainsList}]; return domain && ${negation}domainsArray.includes(domain);${errorCatch} }, { message: "Invalid ${type}, domain ${messageType}" })`;
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user