Skip to content

egon-orm-workspace / egon-orm / Changeset

Class: Changeset<S, New, E> ​

Defined in: core/src/changeset/changeset.ts:324

A change to one record: which values were accepted, what changed, what is wrong, and which database constraints to watch for. Immutable and synchronous; it never touches the database. Make one with cast or change: there is no public constructor.

S is the schema class (or, for a changeset without one, { data, types }). New is true for a new record, false for a changeset of a loaded row, and boolean when either is possible (a changeset function that takes User | typeof User). E collects the error keys that are not fields, as validations add them (validateConfirmation's passwordConfirmation, a key given to addError), so that errorMessages() is typed with them.

Example ​

ts
const cs = cast(User, params, ["email", "name", "age"])
  .validateRequired(["email"])
  .validateFormat("email", /^[^@\s]+@[^@\s]+$/)
  .validateLength("name", { min: 2, max: 80 })
  .validateNumber("age", { greaterThanOrEqualTo: 13 })
  .uniqueConstraint("email");

cs.valid; // boolean
cs.changes; // { email?: string; name?: string | null; age?: number | null }
cs.errorMessages(); // { email: ["can't be blank"] }

Type Parameters ​

S ​

S extends ChangesetSource = AnySchema

New ​

New extends boolean = boolean

E ​

E extends string = never

Implements ​

Properties ​

~errorKeys? ​

ts
readonly "~errorKeys"?: (keys) => void;

Defined in: core/src/changeset/changeset.ts:335

Type-only; never set at runtime. Records E, the error keys validations added. Typed as a method's parameter, which is compared both ways, so that a changeset with extra keys still fits wherever a changeset of its schema is expected.

Parameters ​

keys ​

E

Returns ​

void


action ​

ts
readonly action: Action | null;

Defined in: core/src/changeset/changeset.ts:353

What the changeset is used for; set by the repo or by applyAction.

Implementation of ​

ChangesetLike.action


changes ​

ts
readonly changes: Changes<S>;

Defined in: core/src/changeset/changeset.ts:347

The changed fields and their new values.

Implementation of ​

ChangesetLike.changes


constraints ​

ts
readonly constraints: readonly Constraint[];

Defined in: core/src/changeset/changeset.ts:355

The constraint declarations, in the order they were made.


data ​

ts
readonly data: DataMember<S, New>;

Defined in: core/src/changeset/changeset.ts:339

The loaded row (or, without a schema class, the data object); null for a new record.

Implementation of ​

ChangesetLike.data


errors ​

ts
readonly errors: Readonly<Record<string, readonly ChangesetError[]>>;

Defined in: core/src/changeset/changeset.ts:349

The errors, by field (or other key, such as passwordConfirmation).

Implementation of ​

ChangesetLike.errors


filters ​

ts
readonly filters: Readonly<Record<string, unknown>>;

Defined in: core/src/changeset/changeset.ts:357

Values the row must still have in the database for an update or delete to apply (optimisticLock).


model ​

ts
readonly model: ChangesetModel<S>;

Defined in: core/src/changeset/changeset.ts:337

The schema class; null for a changeset without one.


params ​

ts
readonly params: Readonly<Record<string, unknown>> | null;

Defined in: core/src/changeset/changeset.ts:345

The params given to cast, as given (merged when a changeset is cast again); null for a changeset made with change. They may hold values of redacted fields, and are never shown by inspect or toJSON.


prepare ​

ts
readonly prepare: readonly PrepareFunction<S, New>[];

Defined in: core/src/changeset/changeset.ts:359

The functions prepareChanges registered, in order. The repo runs them just before the write.


repo ​

ts
readonly repo: unknown;

Defined in: core/src/changeset/changeset.ts:361

The repo running the write, while prepare functions run; null otherwise.


valid ​

ts
readonly valid: boolean;

Defined in: core/src/changeset/changeset.ts:351

Whether there are no errors. Stored, not recomputed.

Implementation of ​

ChangesetLike.valid

Accessors ​

validations ​

Get Signature ​

ts
get validations(): readonly ValidationEntry[];

Defined in: core/src/changeset/changeset.ts:1866

The validations that ran, oldest first: [field, descriptor], where the descriptor names the validation and holds its options. For tools that generate forms.

Example ​
ts
cast(User, params, ["name"]).validateLength("name", { min: 2 }).validations;
// [["name", { validation: "length", min: 2 }]]
Returns ​

readonly ValidationEntry[]

Methods ​

[INSPECT]() ​

ts
[INSPECT](): string;

Defined in: core/src/changeset/changeset.ts:1893

What console.log(cs) shows, with redacted fields hidden.

Returns ​

string


addError() ​

ts
addError<K>(
   key, 
   message, 
   meta?
): Changeset<S, New>;

Defined in: core/src/changeset/changeset.ts:1462

Adds an error by hand. The key may be a field or any other name ($base for the changeset as a whole). meta fills the message's {placeholders}.

Type Parameters ​

K ​

K extends string = never

Parameters ​

key ​

FieldName<S> | K

message ​

string

meta? ​

Readonly<Record<string, unknown>>

Returns ​

Changeset<S, New>

Example ​

ts
cs.addError("email", "is not allowed", { domain: "example.com" });

Throws ​

QueryError when the key is empty or "__proto__".


applyChanges() ​

ts
applyChanges(this): AppliedData<S>;

Defined in: core/src/changeset/changeset.ts:831

The data with the changes applied, without validating: a new row of the same class (or, without a schema class, a new plain object). Associations loaded on the row are kept.

Not available on a new record: a row the database never returned cannot exist. It is a compile error there, and throws if reached anyway.

Parameters ​

this ​

Changeset<S, New, never> & NotNewRecord<New>

Returns ​

AppliedData<S>

Example ​

ts
change(user, { name: "Ada" }).applyChanges().name; // "Ada"

Throws ​

QueryError on a changeset of a new record.


assocConstraint() ​

ts
assocConstraint(assoc, options?): this;

Defined in: core/src/changeset/changeset.ts:1568

Declares the foreign-key constraint behind a belongsTo association: a write whose parent does not exist reports does not exist on the association's name.

Parameters ​

assoc ​

AssocName<S>

options? ​

ConstraintOptions

Returns ​

this

Example ​

ts
cast(Post, params, ["authorId"]).assocConstraint("author"); // posts_author_id_fkey, error on "author"

Throws ​

QueryError when assoc is not a belongsTo association.


castAssoc() ​

ts
castAssoc<K>(name, ...options): this;

Defined in: core/src/changeset/changeset.ts:1389

Casts an association from the params given to cast: each item becomes a child changeset made by with (by default the target's static changeset function), called as with(existingRow, item, index) for an item whose primary key matches a child the parent has (an update), and with(TargetClass, item, index) otherwise (an insert). Children the params leave out are handled by the association's onReplace.

A to-one association takes an object or null, a to-many one an array of objects. On a loaded parent the association must be preloaded as whole rows; a new parent has no children. A key missing from the params changes nothing. The parent is invalid when a child is; the children keep their own errors.

Type Parameters ​

K ​

K extends string

Parameters ​

name ​

K

options ​

...CastNestedArgs<AssocTarget<S, K>>

Returns ​

this

Example ​

ts
cast(post, params, ["title"]).castAssoc("comments", { with: Comment.changeset });

Throws ​

QueryError for an unknown or has-through association, wrong options, a changeset made by change, or a left-out child when onReplace is "error".

Throws ​

NotLoadedError when the association of a loaded parent is not preloaded.


castEmbed() ​

ts
castEmbed<K>(name, ...options): this;

Defined in: core/src/changeset/changeset.ts:1406

Casts an embed field from the params, as Changeset.castAssoc casts an association. Items of an embedded list are matched by the embedded schema's primary key; without one, the list is replaced as a whole.

Type Parameters ​

K ​

K extends string

Parameters ​

name ​

K

options ​

...CastNestedArgs<EmbedTarget<S, K>>

Returns ​

this

Example ​

ts
cast(user, params, ["email"]).castEmbed("address", { with: Address.changeset, required: true });

Throws ​

QueryError for a field that is not an embed, wrong options, a changeset made by change, or a left-out item when onReplace is "error".


checkConstraint() ​

ts
checkConstraint(field, options): this;

Defined in: core/src/changeset/changeset.ts:1631

Declares a check constraint, reported as is invalid on field. Its name is required.

Parameters ​

field ​

FieldName<S>

options ​

CheckConstraintOptions

Returns ​

this

Example ​

ts
cs.checkConstraint("age", { name: "users_age_check", message: "must be positive" });

Throws ​

QueryError when field is not a field or there is no name.


deleteChange() ​

ts
deleteChange(field): this;

Defined in: core/src/changeset/changeset.ts:592

Removes the change of a field, if it has one.

Parameters ​

field ​

FieldName<S>

Returns ​

this

Example ​

ts
cs.deleteChange("name").changes.name; // undefined

Throws ​

QueryError when field is not a field.


errorMessages() ​

ts
errorMessages<C>(this): ErrorMessages<C>;

Defined in: core/src/changeset/changeset.ts:1493

The errors as messages, with {placeholders} filled in from each error's metadata, including those of nested changesets. The tree is typed by the schema: its fields, associations and embeds (nested trees), the keys validations added (passwordConfirmation, carried in the changeset's type), and $base. Name its type with ErrorMessages: of the changeset's type, or of what the schema's changeset function returns.

Type Parameters ​

C ​

C extends ChangesetLike<unknown>

Parameters ​

this ​

C

Returns ​

ErrorMessages<C>

Example ​

ts
cast(User, {}, ["email"]).validateRequired(["email"]).errorMessages(); // { email: ["can't be blank"] }

// For a client: the errors of User.changeset, keys added by its validations included.
type SignUpErrors = ErrorMessages<ReturnType<typeof User.changeset>>;

exclusionConstraint() ​

ts
exclusionConstraint(field, options?): this;

Defined in: core/src/changeset/changeset.ts:1651

Declares an exclusion constraint, reported as violates an exclusion constraint. The default name is <table>_<column>_excl.

Parameters ​

field ​

FieldName<S>

options? ​

ConstraintOptions

Returns ​

this

Example ​

ts
cs.exclusionConstraint("during"); // bookings_during_excl

Throws ​

QueryError when field is not a field, or the default name cannot be made.


fetchChange() ​

ts
fetchChange<K>(field): 
  | {
  value: Exclude<Changes<S>[K], undefined>;
}
  | undefined;

Defined in: core/src/changeset/changeset.ts:768

{ value } when the field has a change, else undefined.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

Returns ​

| { value: Exclude<Changes<S>[K], undefined>; } | undefined

Example ​

ts
change(user, { name: null }).fetchChange("name"); // { value: null }

Throws ​

QueryError when field is not a field.


fetchField() ​

ts
fetchField<K>(field): 
  | {
  from: "data" | "changes";
  value: RowOf<SourceFields<S>>[K];
}
  | undefined;

Defined in: core/src/changeset/changeset.ts:745

Where the value of a field comes from, and the value: { from: "changes" } when it has a change, { from: "data" } otherwise (a new record's default counts as data). undefined when the field has no value at all.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

Returns ​

| { from: "data" | "changes"; value: RowOf<SourceFields<S>>[K]; } | undefined

Example ​

ts
change(user, { name: "Ada" }).fetchField("name"); // { from: "changes", value: "Ada" }

Throws ​

QueryError when field is not a field.


fieldMissing() ​

ts
fieldMissing(field): boolean;

Defined in: core/src/changeset/changeset.ts:812

Whether a field has no value, in the changes or the data: undefined, null, or a string of only whitespace.

Parameters ​

field ​

FieldName<S>

Returns ​

boolean

Example ​

ts
cast(User, { name: "  " }, ["name"]).fieldMissing("name"); // true

Throws ​

QueryError when field is not a field.


forceChange() ​

ts
forceChange<K>(field, value): this;

Defined in: core/src/changeset/changeset.ts:555

Sets a change even when the value equals the current one.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

value ​

RowOf<SourceFields<S>>[K]

Returns ​

this

Example ​

ts
change(user).forceChange("name", user.name).changes; // { name: … }

Throws ​

QueryError when field is not a field, or value is undefined.


foreignKeyConstraint() ​

ts
foreignKeyConstraint(field, options?): this;

Defined in: core/src/changeset/changeset.ts:1545

Declares a foreign-key constraint on a field of this record: a write that points at a row that does not exist reports does not exist. The default name is <table>_<column>_fkey.

Parameters ​

field ​

FieldName<S>

options? ​

ConstraintOptions

Returns ​

this

Example ​

ts
cast(Post, params, ["authorId"]).foreignKeyConstraint("authorId"); // posts_author_id_fkey

Throws ​

QueryError when field is not a field, or the default name cannot be made.


getChange() ​

Call Signature ​

ts
getChange<K>(field): Changes<S>[K] | undefined;

Defined in: core/src/changeset/changeset.ts:725

The change of a field, or fallback (default undefined) when it has none.

Type Parameters ​
K ​

K extends string

Parameters ​
field ​

K

Returns ​

Changes<S>[K] | undefined

Example ​
ts
cast(User, { name: "Ada" }, ["name"]).getChange("name"); // "Ada"
Throws ​

QueryError when field is not a field.

Call Signature ​

ts
getChange<K, D>(field, fallback): 
  | D
| Exclude<Changes<S>[K], undefined>;

Defined in: core/src/changeset/changeset.ts:726

The change of a field, or fallback (default undefined) when it has none.

Type Parameters ​
K ​

K extends string

D ​

D

Parameters ​
field ​

K

fallback ​

D

Returns ​

| D | Exclude<Changes<S>[K], undefined>

Example ​
ts
cast(User, { name: "Ada" }, ["name"]).getChange("name"); // "Ada"
Throws ​

QueryError when field is not a field.


getField() ​

Call Signature ​

ts
getField<K>(field): RowOf<SourceFields<S>>[K];

Defined in: core/src/changeset/changeset.ts:702

The value of a field: its change if it has one, else its value in the data; for a new record, its default. fallback is returned where that is undefined.

Type Parameters ​
K ​

K extends string

Parameters ​
field ​

K

Returns ​

RowOf<SourceFields<S>>[K]

Example ​
ts
cast(User, {}, ["role"]).getField("role"); // "member", the default
Throws ​

QueryError when field is not a field.

Call Signature ​

ts
getField<K, D>(field, fallback): D | RowOf<SourceFields<S>>[K];

Defined in: core/src/changeset/changeset.ts:703

The value of a field: its change if it has one, else its value in the data; for a new record, its default. fallback is returned where that is undefined.

Type Parameters ​
K ​

K extends string

D ​

D

Parameters ​
field ​

K

fallback ​

D

Returns ​

D | RowOf<SourceFields<S>>[K]

Example ​
ts
cast(User, {}, ["role"]).getField("role"); // "member", the default
Throws ​

QueryError when field is not a field.


isChanged() ​

ts
isChanged<K>(field, options?): boolean;

Defined in: core/src/changeset/changeset.ts:789

Whether a field has a change; with from and to, whether it changes from that value (in the data) and to that value. Values are compared by the field's type.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

options? ​
from? ​

RowOf<SourceFields<S>>[K]

to? ​

RowOf<SourceFields<S>>[K]

Returns ​

boolean

Example ​

ts
cs.isChanged("role", { from: "member", to: "admin" });

Throws ​

QueryError when field is not a field.


merge() ​

ts
merge(other): this;

Defined in: core/src/changeset/changeset.ts:630

Combines this changeset with another of the same record: the other's changes win, errors, validations, constraints, filters and prepare functions are joined, and the result is valid only if both are.

Parameters ​

other ​

Changeset<S, New>

Returns ​

this

Example ​

ts
const profile = cast(user, params, ["name"]);
const login = cast(user, params, ["email"]).validateRequired(["email"]);
profile.merge(login).changes; // { name: …, email: … }

Throws ​

QueryError when the changesets are not of the same record, or have different actions.


noAssocConstraint() ​

ts
noAssocConstraint(assoc, options?): this;

Defined in: core/src/changeset/changeset.ts:1600

Declares the foreign-key constraint of a hasOne or hasMany association, seen from this side: deleting this record while rows still point at it reports is still associated with this entry on the association's name. The default name is <child table>_<foreign key column>_fkey.

Parameters ​

assoc ​

AssocName<S>

options? ​

ConstraintOptions

Returns ​

this

Example ​

ts
change(user).noAssocConstraint("posts"); // posts_author_id_fkey

Throws ​

QueryError when assoc is not a hasOne or hasMany association.


optimisticLock() ​

ts
optimisticLock<K>(field, increment?): this;

Defined in: core/src/changeset/changeset.ts:1749

Makes an update or delete apply only if field still has the value it had when the row was read, and has the update increment it (by default n + 1, wrapping to 1 after 2147483647). A write that finds the row changed fails as stale. The increment on its own is not a change: an update with nothing else to write runs no query, so it is not checked either; with force it runs, increments the field and checks it.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

increment? ​

(current) => NonNullable<RowOf<SourceFields<S>>[K]>

Returns ​

this

Example ​

ts
repo.update(cast(user, params, ["name"]).optimisticLock("lockVersion"));

Throws ​

QueryError when field is not a field or has no value.


pipe() ​

ts
pipe<R>(fn): R;

Defined in: core/src/changeset/changeset.ts:683

Applies fn to this changeset and returns what it returns: for steps of your own that you reuse between changeset functions.

Type Parameters ​

R ​

R

Parameters ​

fn ​

(changeset) => R

Returns ​

R

Example ​

ts
const normalizeEmail = (cs: Changeset<typeof User>) =>
  cs.updateChange("email", (email) => email.trim().toLowerCase());

cast(User, params, ["email"]).pipe(normalizeEmail);

prepareChanges() ​

ts
prepareChanges(fn): this;

Defined in: core/src/changeset/changeset.ts:1796

Registers a function the repo runs just before the write, inside its transaction, with the changeset (its repo and action set). It returns the changeset to write.

Parameters ​

fn ​

PrepareFunction<S, New>

Returns ​

this

Example ​

ts
cs.prepareChanges((cs) => cs.putChange("slug", slugify(cs.getField("title"))));

Throws ​

QueryError when fn is not a function.


putAssoc() ​

ts
putAssoc<K>(name, value): this;

Defined in: core/src/changeset/changeset.ts:1427

Sets an association from values you trust: rows (kept as they are), changesets (a new record is inserted, one of a loaded row updated) or plain objects (a new record, or an update of the existing child with that primary key). A list for hasMany and manyToMany, one value or null for the others. Children left out follow onReplace; putting the rows that are already there changes nothing.

Type Parameters ​

K ​

K extends string

Parameters ​

name ​

K

value ​

PutAssocValue<S, K>

Returns ​

this

Example ​

ts
change(post).putAssoc("tags", [news, sport]);
change(comment).putAssoc("post", post);

Throws ​

QueryError for an unknown or has-through association, a value of the wrong kind, the same row twice, or a left-out child when onReplace is "error".

Throws ​

NotLoadedError when the association of a loaded parent is not preloaded.


putChange() ​

ts
putChange<K>(field, value): this;

Defined in: core/src/changeset/changeset.ts:541

Sets a change. A value equal to the current one is not a change, and putting the current value back removes the change. null on a field that is not nullable adds can't be blank instead.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

value ​

RowOf<SourceFields<S>>[K]

Returns ​

this

Example ​

ts
change(user).putChange("name", "Ada").changes; // { name: "Ada" }

Throws ​

QueryError when field is not a field, or value is undefined.


putEmbed() ​

ts
putEmbed<K>(name, value): this;

Defined in: core/src/changeset/changeset.ts:1443

Sets an embed field from values you trust, as Changeset.putAssoc sets an association: embedded rows, changesets of them, or plain objects of their fields.

Type Parameters ​

K ​

K extends string

Parameters ​

name ​

K

value ​

PutEmbedValue<S, K>

Returns ​

this

Example ​

ts
change(user).putEmbed("address", { street: "Storgata 1", city: "Oslo" });

Throws ​

QueryError for a field that is not an embed, a value of the wrong kind, or a left-out item when onReplace is "error".


toJSON() ​

ts
toJSON(): object;

Defined in: core/src/changeset/changeset.ts:1883

A JSON-ready plain object of the action, the changes, the errors and valid: what JSON.stringify writes. changes leaves out every field that is not in JSON (a redacted field, a virtual one not declared { json: true }), and maps the values as a row's toJSON does (a Date to its ISO string, a bigint to a decimal string, bytes to base64); nested changesets are written the same way.

Returns ​

object

action ​
ts
action: Action | null;
changes ​
ts
changes: Record<string, unknown>;
errors ​
ts
errors: Errors;
valid ​
ts
valid: boolean;

Example ​

ts
JSON.stringify(cs); // '{"action":null,"changes":{"email":"a@b.c"},"errors":{},"valid":true}'

uniqueConstraint() ​

ts
uniqueConstraint(fields, options?): this;

Defined in: core/src/changeset/changeset.ts:1514

Declares a unique constraint: if the database rejects the write because of it, the repo reports has already been taken on the (first) field instead of throwing. The default name is <table>_<column(s)>_key; a field listed twice is one column of it.

Parameters ​

fields ​

| FieldName<S> | readonly FieldName<S>[]

options? ​

ConstraintOptions

Returns ​

this

Example ​

ts
cs.uniqueConstraint("email"); // users_email_key
cs.uniqueConstraint(["orgId", "slug"]); // projects_org_id_slug_key

Throws ​

QueryError when a name is not a field, or the default name cannot be made.


updateChange() ​

ts
updateChange<K>(field, fn): this;

Defined in: core/src/changeset/changeset.ts:609

Replaces the change of a field with fn(change). Does nothing when the field has no change. The result is set as by Changeset.putChange.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

fn ​

(value) => RowOf<SourceFields<S>>[K]

Returns ​

this

Example ​

ts
cast(User, params, ["email"]).updateChange("email", (email) => email.trim().toLowerCase());

Throws ​

QueryError when field is not a field, or fn returns undefined.


validate() ​

ts
validate(validator, options?): this;

Defined in: core/src/changeset/changeset.ts:1298

Validates the record with a Standard Schema (Zod, Valibot, ArkType, recent Yup) or a function. The validator receives every field with the changes applied; each issue becomes an error on the field its path starts with (validation: "schema"), or on $base (exported as BASE) when the path is empty or does not start with a field.

Every issue is kept by default, except on a field that already has an error (from cast or an earlier validation): that field keeps its first message. { scope: "changed" } keeps only issues on changed fields. { apply: true } writes a schema's output back as changes when it finds no issue. { only: [...] } narrows the values and the issues to those fields.

Parameters ​

validator ​

Validator<RowOf<SourceFields<S>>>

options? ​

ValidateOptions<S>

Returns ​

this

Example ​

ts
const UserInput = z.object({ email: z.string().email(), age: z.number().int().min(13).nullish() });
cast(User, params, ["email", "age"]).validate(UserInput);

cs.validate((v, { isChanged }) =>
  isChanged("endsAt") && v.endsAt <= v.startsAt ? [{ path: "endsAt", message: "must be after start" }] : [],
);

Throws ​

TypeError when validator is neither a Standard Schema nor a function, or a validator function returns something other than an array of issues or nothing (undefined), such as null, a single issue without its array or a string.

Throws ​

QueryError when the validator answers with a promise (use validateAsync), or an option is wrong.


validateAcceptance() ​

ts
validateAcceptance<K>(key, options?): Changeset<S, New>;

Defined in: core/src/changeset/changeset.ts:1208

Adds must be accepted unless the params hold true (or "true", "1", 1) under key, such as a terms-of-service checkbox. The key need not be a field. Runs only on a changeset made by cast.

Type Parameters ​

K ​

K extends string = never

Parameters ​

key ​

FieldName<S> | K

options? ​

MessageOptions

Returns ​

Changeset<S, New>

Example ​

ts
cast(User, params, ["email"]).validateAcceptance("termsOfService");

validateAsync() ​

ts
validateAsync(validator, options?): Promise<Changeset<S, New, E>>;

Defined in: core/src/changeset/changeset.ts:1317

Like Changeset.validate, for validators that answer with a promise (a remote check, a schema with async refinements). Also accepts synchronous validators.

Parameters ​

validator ​

Validator<RowOf<SourceFields<S>>>

options? ​

ValidateOptions<S>

Returns ​

Promise<Changeset<S, New, E>>

Example ​

ts
const checked = await cs.validateAsync(async (v) =>
  (await isDisposable(v.email)) ? [{ path: "email", message: "is not allowed" }] : [],
);

Throws ​

TypeError (as a rejected promise) when validator is neither a Standard Schema nor a function, or a validator function's result resolves to something other than an array of issues or nothing (undefined), such as null, a single issue without its array or a string.


validateChange() ​

ts
validateChange<K>(field, fn): this;

Defined in: core/src/changeset/changeset.ts:1241

Runs fn on the change of a field (not on null, not when there is no change, and not when the field already has an error). fn returns a message, an error, a list of either, or nothing.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

fn ​

(value, field) => ChangeValidatorResult

Returns ​

this

Example ​

ts
cs.validateChange("email", (email) => (email.endsWith("@example.com") ? "is not allowed" : undefined));

Throws ​

QueryError when field is not a field or fn returns something else.


validateConfirmation() ​

ts
validateConfirmation<K>(field, options?): Changeset<S, New>;

Defined in: core/src/changeset/changeset.ts:1174

Checks that the params hold <field>Confirmation equal to the field's change (passwordConfirmation for password). The confirmation is cast with the field's type and compared with the change by that type, so the same input typed twice always matches; a confirmation the type rejects does not. The error, does not match confirmation, goes on the confirmation key. A missing confirmation is an error only with required: true (can't be blank). Like the other validations it runs only when the field has a change (not a change to null), and only on a changeset made by cast.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

options? ​

ConfirmationOptions

Returns ​

Changeset<S, New>

Example ​

ts
cast(User, params, ["email", "password"]).validateConfirmation("password");

Throws ​

QueryError when field is not a field.


validateExclusion() ​

ts
validateExclusion<K>(
   field, 
   values, 
   options?
): this;

Defined in: core/src/changeset/changeset.ts:953

Adds is reserved when the change of a field is one of values.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

values ​

readonly NonNullable<RowOf<SourceFields<S>>[K]>[]

options? ​

MessageOptions

Returns ​

this

Example ​

ts
cs.validateExclusion("name", ["admin", "root"]);

Throws ​

QueryError when field is not a field or values is not an array.


validateField() ​

ts
validateField<K>(field, validator): this;

Defined in: core/src/changeset/changeset.ts:1336

Validates the change of one field with a Standard Schema or a function. It runs only when the field has a change (not a change to null) and no error yet, and receives that value alone; every issue goes on the field, its path in meta.path.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

validator ​

FieldValidator<NonNullable<RowOf<SourceFields<S>>[K]>, RowOf<SourceFields<S>>>

Returns ​

this

Example ​

ts
cast(User, params, ["email"]).validateField("email", z.string().email());

Throws ​

TypeError when validator is neither a Standard Schema nor a function, or a validator function returns something other than an array of issues or nothing (undefined), such as null, a single issue without its array or a string.

Throws ​

QueryError when field is not a field, or the validator answers with a promise.


validateFieldAsync() ​

ts
validateFieldAsync<K>(field, validator): Promise<Changeset<S, New, E>>;

Defined in: core/src/changeset/changeset.ts:1357

Like Changeset.validateField, for validators that answer with a promise.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

validator ​

FieldValidator<NonNullable<RowOf<SourceFields<S>>[K]>, RowOf<SourceFields<S>>>

Returns ​

Promise<Changeset<S, New, E>>

Example ​

ts
const checked = await cs.validateFieldAsync("email", async (email) =>
  (await isDisposable(email)) ? [{ path: [], message: "is not allowed" }] : [],
);

Throws ​

TypeError (as a rejected promise) when validator is neither a Standard Schema nor a function, or a validator function's result resolves to something other than an array of issues or nothing (undefined), such as null, a single issue without its array or a string.


validateFormat() ​

ts
validateFormat(
   field, 
   pattern, 
   options?
): this;

Defined in: core/src/changeset/changeset.ts:905

Adds has invalid format when the change of a string field does not match pattern.

Parameters ​

field ​

FieldOfType<S, string>

pattern ​

RegExp

options? ​

MessageOptions

Returns ​

this

Example ​

ts
cs.validateFormat("email", /^[^@\s]+@[^@\s]+$/);

Throws ​

QueryError when field is not a field or pattern is not a regular expression.


validateInclusion() ​

ts
validateInclusion<K>(
   field, 
   values, 
   options?
): this;

Defined in: core/src/changeset/changeset.ts:935

Adds is invalid when the change of a field is not one of values (compared by the field's type).

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

values ​

readonly NonNullable<RowOf<SourceFields<S>>[K]>[]

options? ​

MessageOptions

Returns ​

this

Example ​

ts
cs.validateInclusion("role", ["admin", "member"]);

Throws ​

QueryError when field is not a field or values is not an array.


validateLength() ​

ts
validateLength(field, options): this;

Defined in: core/src/changeset/changeset.ts:1040

Checks the length of the change of a string or array field. A string is counted in grapheme clusters by default (count: "codepoints" or "bytes" for the others), an array in items. is is checked first, then min, then max; one error at most.

stringcount: "bytes"array
isshould be {count} character(s)should be {count} byte(s)should have {count} item(s)
minshould be at least {count} character(s)should be at least {count} byte(s)should have at least {count} item(s)
maxshould be at most {count} character(s)should be at most {count} byte(s)should have at most {count} item(s)

Parameters ​

field ​

FieldOfType<S, string | readonly unknown[]>

options ​

LengthOptions

Returns ​

this

Example ​

ts
cs.validateLength("name", { min: 2, max: 80 });

Throws ​

QueryError when field is not a field, or no limit is given.


validateNumber() ​

ts
validateNumber(field, options): this;

Defined in: core/src/changeset/changeset.ts:1111

Compares the change of a number field with limits, in the order the options are given; the first that fails is reported (must be greater than {number}, …).

Parameters ​

field ​

FieldOfType<S, number | bigint>

options ​

NumberOptions

Returns ​

this

Example ​

ts
cs.validateNumber("age", { greaterThanOrEqualTo: 13 });

Throws ​

QueryError when field is not a field, no limit is given, or an option is unknown or not a number.


validateRequired() ​

ts
validateRequired(fields?, options?): this;

Defined in: core/src/changeset/changeset.ts:856

Adds can't be blank to each field that has no value in the changes or the data: undefined, null, or a string of only whitespace (trim: false counts only ""). A field that already has an error is skipped, and the change of a field found missing is removed. A name listed twice is checked once.

With no list, it checks every stored field that is not nullable and has no default, no generator and no database-generated value.

Parameters ​

fields? ​

| FieldName<S> | readonly FieldName<S>[]

options? ​

RequiredOptions

Returns ​

this

Example ​

ts
cast(User, { email: " " }, ["email"]).validateRequired(["email"]).errors;
// { email: [{ message: "can't be blank", validation: "required", meta: {} }] }

Throws ​

QueryError when a name is not a field.


validateSubset() ​

ts
validateSubset<K>(
   field, 
   values, 
   options?
): this;

Defined in: core/src/changeset/changeset.ts:997

Adds has an invalid entry when the change of an array field has an element that is not one of values.

Type Parameters ​

K ​

K extends string

Parameters ​

field ​

K

values ​

readonly ElementOf<RowOf<SourceFields<S>>[K & keyof SourceFields<S> & string]>[]

options? ​

MessageOptions

Returns ​

this

Example ​

ts
cs.validateSubset("tagList", ["news", "howto", "release"]);

Throws ​

QueryError when field is not a field or values is not an array.


validateUniqueAsync() ​

ts
validateUniqueAsync(
   fields, 
   repo, 
   options?
): Promise<Changeset<S, New, E>>;

Defined in: core/src/changeset/changeset.ts:1829

Asks the database whether another row already has these values, and adds has already been taken if one does. It runs only when the fields have changes and no errors, and the error key (errorKey, by default the first field) has none. Another request can insert the same values between the check and the write, so it is for early feedback only: always declare uniqueConstraint as well.

Parameters ​

fields ​

| FieldName<S> | readonly FieldName<S>[]

repo ​

unknown

options? ​

UniqueAsyncOptions

Returns ​

Promise<Changeset<S, New, E>>

Example ​

ts
const checked = await cs.validateUniqueAsync("email", repo);

Throws ​

QueryError (as a rejected promise) when the repo does not provide the check.