Skip to content

Getting started ​

Try It Live ​

You can try self-assert directly in your browser on CodeSandbox.

Installation ​

sh
npm install self-assert
sh
pnpm add self-assert
sh
yarn add self-assert

Validating Domain Objects with Assertion ​

The Assertion class lets you express rules declaratively. You can:

  • Define self-contained rules (no parameters)
  • Define reusable rules that apply to different values

A typical example:

ts
import { Assertion, Requirements, Ruleset } from "self-assert";

export class Person {
  static readonly nameNotBlank = Assertion.requiring(
    "name.notBlank",
    "Name must not be blank",
    Requirements.isNotBlank
  );

  static readonly agePositive = Assertion.requiring(
    "age.positive",
    "Age must be positive",
    Requirements.isPositive
  );

  static named(name: string, age: number) {
    Ruleset.ensureAll(
      this.nameNotBlank.evaluateFor(name),
      this.agePositive.evaluateFor(age)
    );
    return new this(name, age);
  }

  protected constructor(protected name: string, protected age: number) {}

  getName() {
    return this.name;
  }

  getAge() {
    return this.age;
  }
}

If any rule fails, a RulesBroken error is thrown with details.

Suggesting Completion with Draft Assistants ​

FieldDraftAssistant and SectionDraftAssistant help you manage incomplete or draft objects, especially useful in UI flows or external interfaces.

ts
function createPersonAssistant() {
  const nameAssistant = FieldDraftAssistant.handlingAll(
    ["name.notBlank"],
    (person: Person) => person.getName()
  );

  const ageAssistant = IntegerDraftAssistant.for(
    "age.positive",
    (person: Person) => person.getAge()
  );

  const personAssistant = SectionDraftAssistant.topLevelContainerWith(
    [nameAssistant, ageAssistant],
    (name, age) => Person.named(name, age),
    []
  );

  return Object.assign(personAssistant, { nameAssistant, ageAssistant });
}

TIP

Object.assign lets you expose the inner assistants of a composed one, so you can reuse them without creating a dedicated subclass.

The assistant lets you defer object creation until all validations pass:

ts
const personAssistant = createPersonAssistant();

personAssistant.nameAssistant.setModel("   ");
personAssistant.ageAssistant.setModel(30);

personAssistant.withCreatedModelDo(
  () => {
    throw new Error("this should not happen");
  },
  () => console.log("Person not created")
);

console.log(personAssistant.hasBrokenRules());

personAssistant.nameAssistant.setModel("John");
personAssistant.ageAssistant.setModel(50);

personAssistant.withCreatedModelDo(
  (person) => console.log(`Person created: ${person.getName()}`),
  () => {
    throw new Error("this should not happen");
  }
);

Extensions ​

self-assert provides a small React extension to help you integrate it with React. For more information, see the API reference.

You can install it with your favorite package manager:

sh
npm install @self-assert/react
sh
pnpm add @self-assert/react
sh
yarn add @self-assert/react