Skip to main content
Version: 2.0.0

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());