Qowaiv is a (Single) Value Object library. It aims to model reusable (Single) Value Objects that can be used a wide variety of modeling scenarios, both inside and outside a Domain-driven context.
Supported scenarios include parsing, formatting, validation, (de)serialization, and domain specific logic.
As developement tool, we addopted TypeScript.
A Value Object that can be represented by a single scalar.
In Qowaiv.NET - for non continuous - SVO's there is a not-null state: The
default state of the struct
. Such concept does not exist in JavaScript. As a
result, for empty states, undefined
is used. So for example:
const svo = PostalCode.parse(''); // undefined.
To not to have to rely on try-catch every SVO has an tryParse
alternative.
This resturns an Unparsable
object, containing an error message and the
attempted value once a value can not be parsed, this allows clean code to
handle the unparsable state:
const svo = Guid.parse('not-a-guid'); // Unparsable object.
if (svo instanceof (Unparsable)) {
// handle the unparsable state
}
Represents a Globally Unique Identifier (GUID).
const next = Guid.newGuid(); // 123E4567-E89B-12D3-A456-426655440000
const str = next.format("B"); // {123E4567-E89B-12D3-A456-426655440000}
Represents an email address. It supports
- local part with quotes (
"Can contain anything"@qowaiv.org
) - comments (
in(some comment)[email protected]
) - Display Names
John Smith <[email protected]>
"John Smith" [email protected]
[email protected] (John Smith)
- Mailto prefix (
mailto:[email protected]
) - IP-based domins (
info@[127.0.0.1]
)
Comments, display names, and the mailto prefix are stripped.
const email = Email.parse('[email protected]');
const ip = Email.parse('info@[127.0.0.1]');
const isIP = ip.isIpBased; // true
Represnts a IBAN.
const iban = InternationBankAccountNumber.parse('NL20INGB0001234567');
const country = iban.country; // 'NL';
const formatted = iban.format(); // 'NL20 INGB 0001 2345 67' with nbsp.
const lower = iban.format('h'); // 'nl20 ingb 0001 2345 67' with nbsp.
Represents a postal code. It supports validation for all countries.
const dutch = PostalCode.parse('2624DP');
dutch.isValid('NL'); // true
dutch.isValid('BE'); // false
const argentina = PostalCode.Parse('Z1230ABC');
argentina.format('AR'); // Z 1230 ABC
argentina.format('NL'); // Z1230ABC
As JavaScript does not support method overloading, this interface makes explicit
by including toString()
and format(f?: string)
that the format
method
should be the overloaded version of toString
.
interface IFormattable {
toString(): string;
format(f?: string): string;
}
As JavaScript does not have a way to support equals overloading as a lot of other languages do, but it gives something.
interface IEquatable {
equals(other: any): boolean;
}
Compared with the follow snippet, you could work arround it, although using a
function eq(l, r)
over l === r
is obvious not trivial, or close to ideal.
function eq(l, r) {
if (arguments.length !== 2) { throw new Error('Invalid number of arguments.'); }
if (l !== null && l !== undefined && typeof (l.equals) === 'function') {
return l.equals(r);
}
if (r !== null && r !== undefined && typeof (r.equals) === 'function') {
return r.equals(l);
}
return l === r;
}
To support JSON.stringify()
this interface was introduced.
interface IJsonStringifyable {
toJSON(): any;
}