| name | koapp-model |
| description | Validate and serialize structured data with the @axiosleo/koapp Model class powered by validatorjs. Use when creating typed payload objects, running rules like required/integer/email/min/max, converting between JSON and plain objects, listing properties, or automatically raising HttpError(400) on validation failure inside a koapp handler. |
@axiosleo/koapp Model
Source: src/model.js.
Model is a lightweight data container around
validatorjs. It assigns
incoming fields onto itself, optionally validates them, and provides
utility methods for serialization.
Import
const { Model } = require('@axiosleo/koapp');
Constructor
new Model(obj?, rules?, messages?);
| Arg | Type | Purpose |
|---|
obj | object | Source data; each key is copied onto the instance via Object.assign |
rules | Rules | validatorjs rule set, e.g. `{ name: 'required |
messages | ErrorMessages | Custom error messages keyed by rule, e.g. { required: 'The :attribute is required.' } |
When rules are provided and validation fails, the constructor throws
HttpError(400, <first-error-message>). Inside a koapp handler that
translates to a standard 400 response without any extra plumbing.
Static helper
Model.create(obj, rules, messages);
Shortcut for new Model(obj, rules, messages) that benefits from subclass
context (same as new this(...)).
Instance methods
| Method | Returns | Notes |
|---|
toJson() | string | JSON.stringify(this) |
toObj() | object | JSON.parse(this.toJson()); strips class identity |
properties() | string[] | Enumerable own keys |
count() | number | properties().length |
validate(rules, messages?) | Validator | Runs validatorjs manually and returns the raw Validator object |
validate() does not throw - use it when you need the full error map:
const m = new Model({ email: 'not-an-email' });
const v = m.validate({ email: 'required|email' });
if (v.fails()) {
console.log(v.errors.all());
}
Extending Model
class UserModel extends Model {
constructor(data) {
super(data, {
name: 'required|string',
email: 'required|email',
age: 'integer|min:0'
}, {
required: 'The :attribute field is required.'
});
}
greet() {
return `Hi, ${this.name}`;
}
}
const user = new UserModel(context.body);
When user is created successfully, user.name, user.email, user.age
are all available, plus any custom methods.
Validation rules cheat sheet
Common rules from validatorjs:
required - present and non-empty
string - typeof === 'string'
integer - integer number (accepts strings that parse)
numeric - finite number (accepts strings)
boolean - true/false/0/1/'0'/'1'/'true'/'false'
email - RFC-style email
url - absolute URL
in:a,b,c - value in enumerated list
not_in:a,b,c - value not in list
min:N - string length / number value ≥ N
max:N - string length / number value ≤ N
between:a,b - inclusive range
size:N - exact length / value
regex:/pat/ - matches regex
array - is an array
alpha - letters only
alpha_num - letters or digits
alpha_dash - letters, digits, _, -
required_if:field,value
required_unless:field,value
confirmed - pairs with `<field>_confirmation`
date - parseable date
Combine with |: required|string|min:3|max:64.
Nesting Models
Model instances serialize via JSON, so nesting works naturally:
const address = new Model({
street: '1 Main St',
city: 'Springfield'
});
const user = new Model({
name: 'Alice',
address
});
console.log(user.toObj());
console.log(user.properties());
console.log(user.count());
Note that toObj() returns plain objects - class identity is stripped,
so user.toObj().address instanceof Model === false.
Validating without Model
If you only need to validate a payload once without persisting an
instance, Model.create(data, rules) and discard the return value:
router.post('/login', async (context) => {
Model.create(context.body, {
email: 'required|email',
password: 'required|min:8'
});
const { success } = require('@axiosleo/koapp');
success({ ok: true });
});
Comparison with router-level validators
| Router validators | Model validation |
|---|
| Declarative, lives next to the route | Imperative, lives in code |
Fields split into params / query / body | Arbitrary object shape |
| Runs automatically before the handler | Runs where you call it |
| Limited to the request payload | Can be reused for DB rows, intermediate data, etc. |
Use router validators for request shape enforcement, and Model when you
need to pass the validated data around or serialize it.
Common pitfalls
- Validators that look at missing fields (e.g.
integer) still pass when
the field is absent unless paired with required.
- The 400 message is the first failing rule's message; the others are
discarded. Use
model.validate(...) manually if you need all errors.
Object.assign (used in the constructor) copies own enumerable
properties; prototype getters/setters on obj are not preserved.
toObj() and toJson() include all own properties. If you want to
hide fields, delete them before serialization or implement a custom
toJSON().
See also
- Response helpers used after a successful
Model.create: koapp-response
- Validating fields declaratively on the route: koapp-router
- Concrete model recipes: examples.md