@faivform/yup
Version:
Adapter to use Yup with @tuentyfaiv/svelte-form
75 lines (74 loc) • 2.4 kB
JavaScript
import { Adapter } from "@tuentyfaiv/svelte-form";
import { ObjectSchema, ValidationError } from "yup";
class YupAdapter extends Adapter {
#schema;
#resolveDeep;
constructor(config) {
super();
this.#schema = config.schema;
this.#resolveDeep = config.resolveDeep;
Object.freeze(this);
}
// eslint-disable-next-line class-methods-use-this
#setError = async (field, errros, error) => {
let message = null;
if (error instanceof ValidationError) {
message = error.inner.reduce((_, issue) => issue.message, "");
}
await errros.update((prev) => ({ ...prev, [field]: message }));
};
initial = () => {
const start = Object.entries(this.#schema.fields).reduce((acc, [key, three]) => ({
fields: {
...acc.fields,
[key]: this.#resolveDeep(three),
},
errors: {
...acc.errors,
[key]: null,
},
}), {
fields: {},
errors: {},
});
return start;
};
validate = async (data) => {
await this.#schema.validate(data, { abortEarly: false, strict: true });
};
field = async (field, value, errors) => {
try {
await this.#schema.fields[field].validate(value, { abortEarly: false, strict: true });
await this.#setError(field, errors);
}
catch (error) {
await this.#setError(field, errors, error);
}
};
// eslint-disable-next-line class-methods-use-this
errors = async (error, errors, handle) => {
await handle?.(error);
if (error instanceof ValidationError) {
const messages = error.inner.reduce((acc, issue) => ({
...acc,
[String(issue.path)]: issue.message,
}), {});
errors.update((prev) => ({
...prev,
...messages,
}));
}
};
}
export function adapter(schema) {
const resolveDeep = (three) => {
if (three instanceof ObjectSchema) {
return Object.entries(three.fields).reduce((acc, [key, value]) => ({
...acc,
[key]: resolveDeep(value),
}), {});
}
return null;
};
return new YupAdapter({ schema, resolveDeep });
}