This guide covers the optional result-code layer.
Use it when you want validators to emit stable codes and only resolve the final text when you build the result output. If you only need inline err, warn, or hint messages, you can skip this page.
Codes are useful when:
hint and an errThe coded-result API uses:
ResultCatalogResultCatalog.globalIResultCatalogResultCodeResultCodeDefinitiontype ResultCode = string | number;
interface ResultCodeDefinition {
hint?: string | Record<string, string>;
warn?: string | Record<string, string>;
err?: string | Record<string, string>;
}
Each level is optional. A single code can define one level or several levels.
If a level is declared as a single string, the catalog stores it as the English translation. These two registrations are equivalent:
catalog.register('person.name.missing', {
err: 'Name is required'
});
catalog.register('person.name.missing', {
err: {
en: 'Name is required'
}
});
Language maps are plain key-value objects. The package looks up the requested language first and then falls back to default when present. If no translation matches, the validator falls back to the original generated validator message.
Use the shared catalog when one process-wide registry is sufficient.
import { FieldCheck, ResultCatalog } from '@samatawy/checks';
ResultCatalog.global.register('person.name.missing', {
hint: {
en: 'Add the legal full name when available',
de: 'Ergaenze den vollstaendigen Namen, wenn verfuegbar'
},
err: {
en: 'Name is required',
de: 'Name ist erforderlich'
}
});
const result = new FieldCheck('name', {}).required({
code: 'person.name.missing'
}).result({ language: 'de' });
console.log(result.code);
console.log(result.hint);
console.log(result.err);
Expected result shape:
{
"field": "name",
"valid": false,
"code": "person.name.missing",
"hint": "Ergaenze den vollstaendigen Namen, wenn verfuegbar",
"err": "Name ist erforderlich"
}
Use a separate ResultCatalog instance when different modules or tenants should not share the same registry.
import { FieldCheck, ResultCatalog } from '@samatawy/checks';
const catalog = new ResultCatalog();
catalog.register('person.name.missing', {
warn: {
en: 'Name is missing',
de: 'Name fehlt'
}
});
const result = new FieldCheck('name', {}).required({
code: 'person.name.missing',
catalog
}).result({
language: 'de',
catalog
});
Checks keep the code while rules are being composed. Translation is applied when you call result(...).
If final result formatting runs without an explicit language, the catalog resolves coded messages using English by default.
That matters because the same check output can be formatted in more than one language:
const check = new FieldCheck('name', {}).required({
code: 'person.name.missing'
});
const german = check.result({ language: 'de' });
const english = check.result({ language: 'en' });
If a code exists in the catalog but the requested language does not, the package falls back to the original generated validator text for that level.
import { FieldCheck, ResultCatalog } from '@samatawy/checks';
ResultCatalog.global.register('person.name.missing', {
err: {
en: 'Name is required'
}
});
const check = new FieldCheck('name', {}).required({
code: 'person.name.missing'
});
const english = check.result({ language: 'en' });
const french = check.result({ language: 'fr' });
Here:
english.err is Name is requiredfrench.err falls back to Field name is requiredcode: 'person.name.missing'Codes also survive inside nested object and array results.
import { ObjectCheck, ResultCatalog } from '@samatawy/checks';
ResultCatalog.global.register('children.minor', {
err: {
en: 'All children must be minors'
}
});
const check = await ObjectCheck.for({
children: [{ age: 26 }]
}).check(person => [
person.optional('children').array().isTrueEach(child => {
if (child.age !== undefined && child.age >= 18) {
return false;
}
return true;
}, { code: 'children.minor' })
]);
const result = check.result({
raw: true,
flattened: true,
language: 'en'
}) as any;
console.log(result.raw.results[0].results[0].code);
console.log(result.errors);
Available ResultCatalog methods:
register(code, definition) adds or replaces one coderegisterAll(source) copies codes from another cataloggetDefinition(code) returns a cloned definitiongetResult(code, language?) returns a resolved SingleResultlistCodes() returns the configured codesclear() empties the catalogconfigure(source) replaces the current catalog contents from another catalogDo not add codes just because the feature exists.
Inline messages are usually enough when: