Life Cycles
ivo exposes hooks at different stages of an operation.
Operation context
Handlers receive a context object with useful operation state:
{
input: Input; // sanitized input values
rawInput: Input; // original input values
values: Output; // current output values (including defaults and resolved dependents)
isUpdate: boolean;
summary: IvoSummary<Input, Output>;
}
Global listeners
Set them on schema options:
Loading playground…
Field listeners
Field builders support onSuccess, onFailure, and onDelete:
b.required("username")
.validate(validateUsername)
.onSuccess((summary) => console.log("username validated", summary))
.onFailure((summary) => console.log("username failed", summary));
Post-validation
Use postValidate to run cross-field validation after individual field validators:
new Schema((b) => ..., {
postValidate: {
fields: ['email', 'phoneNumber'],
validator: ({ input }) => [
!input.email && !input.phoneNumber,
'Provide email or phone number',
],
},
});
Custom context options
Pass extra data through every operation:
const UserSchema = new Schema<Input, Output, { db: Database }>((b) => ..., {
// schema definition
});
const UserModel = UserSchema.getModel();
const { data, error } = await UserModel.create(input, { db: usersDb });
Inside validators and resolvers, access the options via the context:
b.constant("id", ({ options }) => options.db.nextId());