@orveth/validation

Discriminated validation results and a Validator interface that adapters can implement without pulling in a specific schema library. Orveth standardizes the outcome shape; your team chooses the backing implementation.

Result types

TypeShape
ValidationSuccess<T>{ ok: true, value: T }
ValidationFailure{ ok: false, issues: ValidationIssue[] }
ValidationResult<T>Union of success and failure variants.

ValidationIssue

  • path — dotted location (for example user.email).
  • message — human-readable explanation.
  • code? — optional stable machine identifier for the issue.

Validator<TInput, TOutput>

Implementations expose validate(input: TInput): ValidationResult<TOutput>. The method must be pure with respect to Orveth: no global mutation, no implicit I/O unless your adapter documents it.

Factory helpers

validationSuccess(value) and validationFailure(issues) keep discriminant fields consistent and reduce boilerplate inside adapters.

Example adapter

validation/positive-int.ts
import { validationFailure, validationSuccess } from "@orveth/validation";
import type { Validator } from "@orveth/validation";

export const positiveInteger: Validator<string, number> = {
  validate(input) {
    const trimmed = input.trim();
    if (trimmed.length === 0) {
      return validationFailure([
        { path: "input", message: "Value is required", code: "REQUIRED" },
      ]);
    }

    const parsed = Number.parseInt(trimmed, 10);
    if (!Number.isFinite(parsed) || parsed <= 0) {
      return validationFailure([
        { path: "input", message: "Must be a positive integer", code: "FORMAT" },
      ]);
    }

    return validationSuccess(parsed);
  },
};

Consuming results

handlers/signup.ts
import type { ValidationResult } from "@orveth/validation";
import { HttpError } from "@orveth/errors";

export function ensureSuccess<T>(result: ValidationResult<T>): T {
  if (result.ok) {
    return result.value;
  }
  throw new HttpError(422, "ORVETH_VALIDATION_FAILED", "Invalid input", {
    details: { issues: result.issues },
  });
}