NPM's "Unpacked Size" is innacurate because the package includes source maps and source files for easier debugging. So, the accurate size of this library for most users is this:
Value objects to the rescue: If you want an age, create an Age object.
class Age {
private _value: number;
constructor(raw: number) {
if (raw < 0) throw Error('Too small');
if (raw > 150) throw Error('Too big');
if (!Number.isInteger(raw)) throw Error('Not an integer');
this._value = raw;
}
valueOf(): number {
return this._value;
}
toMonths(): number {
return this.valueOf() * 12;
}
}
But that's ugly, so I made this library to ease your pain.
import { VOInteger } from '@lucaspaganini/value-objects';
class Age extends VOInteger({ min: 0, max: 150 }) {
toMonths(): number {
return this.valueOf() * 12;
}
}
import {
VOString,
VOInteger,
VOSet,
VOArray,
VOObject
} from '@lucaspaganini/value-objects';
const EMAIL_PATTERN = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
export class Email extends VOString({
trim: true,
maxLength: 256,
pattern: EMAIL_PATTERN
}) {
getHost(): string {
const arr = this.valueOf().split('@');
return arr[arr.length - 1];
}
}
const PASSWORD_PATTERN = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]*$/;
class Password extends VOString({
trim: false,
minLength: 8,
maxLength: 256,
pattern: PASSWORD_PATTERN
}) {}
class Age extends VOInteger({ min: 0, max: 150 }) {
toMonths(): number {
return this.valueOf() * 12;
}
}
class NetflixShow extends VOSet([
'You',
'House of Cards',
'Sense8',
'The Witcher'
]) {}
class NetflixShows extends VOArray(NetflixShow, { minLength: 1 }) {}
class User extends VOObject({
email: Email,
password: Password,
age: Age,
favoriteShows: NetflixShows
}) {}
const userError = new User({
email: '',
password: 123,
age: 21.5,
favoriteShows: ['Lost']
});
const userSuccess = new User({
email: 'test@example.com',
password: '123abcABC',
age: 150,
favoriteShows: ['You', 'House of Cards']
});
import { makeFromRawInit } from '@lucaspaganini/value-objects';
const userFromRaw = makeFromRawInit(User);
userFromRaw({});
app.post('/api/create-user', (req, res) => {
const userEither = userFromRaw(req.body as any);
if (userEither._tag === 'Left')
return res.status(400).json({ errors: userEither.left });
const user = userEither.right;
const createdUser = createUser(user);
res.status(200).json({ user: createdUser });
});