@ooneex/validation component is a type-safe validation layer. You describe the shape of your data once with Assert({...}), and the same schema both narrows your TypeScript types and validates values at runtime. The package provides Assert, scope, union, and intersection, adds a set of ready-made constraints (email, URL, port, country code, and more), and exposes an abstract Validation class for building your own reusable validators. When a schema is attached to a route, the framework runs it for you before the controller is reached.
Why this component
- One schema, two jobs. An
Assert({...})definition is both a runtime validator and a static TypeScript type — no duplicate interfaces to keep in sync. - Concise schema syntax.
Assert,scope,union, andintersectiongive you a full string-based syntax (string.email,number >= 0,'a' | 'b', optional keys with?). - Automatic route validation. Schemas passed to
@Route.httpasparams,queries, orpayloadare validated before the controller runs; invalid requests produce an error response automatically. - Built-in constraints. Pre-built validators cover common shapes — email, URL, port, hostname, locale, currency, country code, hex color, names, IDs — so you do not re-write the same rules.
- Custom validators. Extend the abstract
Validationclass withgetConstraintandgetErrorMessageto package any rule (plus a friendly message) as a reusable class.
How it works
A schema is a function. Calling it with data returns either the validated value or anAssert.errors object. The Validation class wraps that flow into a { isValid, message } result, and the routing layer applies your schemas to incoming requests automatically.
| Stage | What happens |
|---|---|
| Define | Assert({...}) builds a schema that is both a runtime validator and a static type. |
| Validate | Calling the schema returns the parsed value, or an instance of Assert.errors with a .summary describing the failure. |
| Route input | Schemas on @Route.http (params, queries, payload) run before the controller; a failure yields an error response and the controller is skipped. |
| Custom rule | A Validation subclass turns a schema and an optional message into a validate(data) method returning { isValid, message? }. |
Defining schemas
UseAssert to describe an object. Each value is a schema expression — a primitive, a constrained primitive, a numeric range, a literal union, or an array. Mark a key optional by suffixing it with ?.
scope and export() the result; combine schemas with union and intersection.
Validation in routing
The most common place you use validation is on a route. Pass schemas to@Route.http and the framework validates the request before your controller’s index runs — so inside the controller the data is already guaranteed to match.
paramsvalidates path parameters (e.g.:idin the path).queriesvalidates the query string.payloadvalidates the request body.
Built-in constraints
Import these from@ooneex/validation/constraints. Each is a Validation subclass — construct it and call validate(data) to get a { isValid, message? } result.
| Constraint | Validates |
|---|---|
AssertEmail | A valid email address. |
AssertUrl | A URL (1–2083 chars, http/https, no .. or trailing dots); also offers validateStrict requiring a protocol. |
AssertYoutubeUrl | A YouTube watch URL (youtube.com/watch?v=… or youtu.be/…). |
AssertHostname | A hostname or IPv4 address (also accepts an empty string). |
AssertPort | An integer port between 1 and 65535. |
AssertHexaColor | A 3- or 6-digit hex color (e.g. #fff, #A1B2C3). |
AssertCountryCode | A 2-letter uppercase ISO 3166-1 alpha-2 code. |
AssertCurrency | A valid ISO 4217 currency code (3 uppercase letters). |
AssertLocale | A supported locale code from @ooneex/translation. |
AssertAppEnv | A valid application environment value. |
AssertName | A name (1–50 chars, letters/numbers/spaces/-'., trimmed). |
AssertFirstName | A first name (1–50 chars, letters, spaces, hyphens, apostrophes). |
AssertLastName | A last name (1–50 chars, letters, spaces, hyphens, apostrophes). |
AssertId | A 25-character lowercase hexadecimal ID. |
AssertDescription | Free text between 1 and 5000 characters. |
AssertChatQuery | Chat text (1–2000 chars) with no HTML, scripts, or unsafe protocols. |
Custom validators
To package a rule of your own, extend the abstractValidation class. It requires two methods and gives you validate for free.
validate(data, constraint?) calls the schema; on failure it returns your getErrorMessage() (falling back to the schema’s summary), otherwise { isValid: true }.
Inline assertions and utilities
Assert builds a schema you can call immediately to check a value — useful for one-off assertions without defining a named schema.
jsonSchemaToTypeString(schema) converts a JSON Schema object into a readable TypeScript-style type string — handling primitives, arrays, objects with required/optional keys, and anyOf/oneOf/allOf unions and intersections. Pair it with a schema’s toJsonSchema() for documentation or AI-output descriptions.
Types
AssertType— alias for the schemaType; the return type ofgetConstraintand the type of any schema.IAssert— the interface implemented by every validator:getConstraint,getErrorMessage, andvalidate.ValidationResultType— the result ofvalidate:{ isValid: boolean; message?: string }.
Best practices
- Validate at the edge. Attach schemas to
@Route.http(params,queries,payload) so bad input is rejected before any business logic runs. - Define schemas once. Export a schema and reuse it for routing, custom validators, and JSON Schema generation — never re-describe the same shape.
- Prefer built-in constraints. Use
AssertEmail,AssertPort, and friends instead of re-writing common rules; extendValidationonly for genuinely new ones. - Give helpful messages. Return a clear
getErrorMessage()so failures explain what was expected rather than leaning on the rawsummary. - Mark optionals explicitly. Use the
?key suffix for optional fields so the static type and runtime check agree.