justmodel
Extendable immutable javascript models with validation and change tracking
Description
JustModel is a modern extendable model library written in typescript, that provides several features that every model library should have:
Static typed data types
Justmodel has fully typed models when working with typescript and flowtype, that provide type safety when working with models.
import { Model } from 'justmodel';
type User = {
username: string;
password: string;
};
class UserModel extends Model<User> {}
const user = new UserModel().create({username: 'username'}) // <-- property password is missing in type
Immutable and non-immutable operations
All operations are immutable by default, except is in place mutation methods are used
let mutatedUser = user.update({password: 'newpassword'});
user === mutatedUser // <-- false as immutable operation was used
muetatedUser = user.updateInPlace({password: 'newpassword'});
user === mutatedUser // <-- true as model was mutated in place
Data validation with create, update and load joi schemas
class UserModel extends Model<User> {
get schema() {
return Joi.object({
username: Joi.string(),
password: Joi.string().required(),
hashedPassword: Joi.string().hex()
}).xor('password', 'hashedPassword');
}
get createSchema() {
return this.schema.requiredKeys(['password']);
}
}
const user = new UserModel().create({
username: 'user'
}); // <-- validation error as password is missing
Change detection
Just model tracks changes on models and provides method that gets old value or tells if change was made compared to initial value. This is very usefull if doing update oprations on model and need to know if values have changed.
const model = new UserModel().load(data);
model.updateInPlace(req.data);
if (model.hasChanged('password')) {
// check old password for example
}
Insallation
npm install --save justmodel
Example
import { Model } from 'justmodel';
class UserModel extends Model<User> {
get schema() {
return Joi.object({
username: Joi.string().min(4).max(20).lowercase(),
password: Joi.string().required().min(8),
email: Joi.string().email().required(),
hashedPassword: Joi.string().hex()
});
}
get createSchema() {
return this.schema.requiredKeys(['password']);
}
value() {
return this._data.delete('password').toJS();
}
}
const user = new UserModel().create({
username: 'user',
password: 'mypassword',
email: 'email@example.com'
});
checkWeakPasswords(user);
user.updateInPlace({
hashedPassword: hashPassword(user.password)
});
if(user.hasChanged('email')) {
return sendChangeEmail(user);
}
save(user);
Development
npm t
: Run test suitenpm start
: Runsnpm run build
in watch modenpm run test:watch
: Run test suite in interactive watch modenpm run test:prod
: Run linting and generate coveragenpm run build
: Generage bundles and typings, create docsnpm run lint
: Lints codenpm run commit
: Commit using conventional commit style (husky will tell you to use it if you haven't 😉)
Credits
Made with ❤️ by @offlinehacker