README
Commodo is a library of higher order functions (HOFs) that let you create and compose rich data models.
📹 Videos
Wanna get up to speed quickly? Check out the Commodo videos here!
Quick example
A simple model
The following example shows how to create a simple data model, which you can later use to validate data (e.g. data received as body of an HTTP request):
import { withFields, string, number, boolean } from "@commodo/fields";
const Animal = withFields({
name: string({
validation: value => {
if (!value) {
throw Error("A pet must have a name!");
}
}
}),
age: number(),
isAwesome: boolean(),
about: fields({
value: {},
instanceOf: withFields({
type: string({ value: "cat" }),
dangerous: boolean({ value: true })
})()
})
})();
const animal = new Animal();
animal.populate({ age: "7" }); // Throws data type error, cannot populate a string with number.
animal.populate({ age: 7 });
await animal.validate(); // Throws a validation error - name must be defined.
animal.name = "Garfield";
await animal.validate(); // All good.
More complex model
Using other HOFs, you can create more complex models, that have a name, attached hooks, and even storage layer, so that you can easily save the data to the database:
import { withFields, string, number, boolean, fields, onSet } from "@commodo/fields";
import { withName } from "@commodo/name";
import { withHooks } from "@commodo/hooks";
import { withStorage } from "@commodo/fields-storage";
import { MongoDbDriver, withId } from "@commodo/fields-storage-mongodb";
import { compose } from "ramda";
// Define User and Verification models.
const Verification = compose(
withFields({
verified: boolean(),
verifiedOn: string()
})
)();
const User = compose(
withFields({
firstName: string(),
lastName: string(),
email: compose(
onSet(value => value.toLowerCase())
)(string()),
age: number(),
scores: number({ list: true }),
enabled: boolean({ value: false }),
verification: fields({ instanceOf: Verification })
}),
withHooks({
async beforeCreate() {
if (await User.count({ query: { email: this.email } })) {
throw Error("User with same e-mail already exists.");
}
}
}),
withName("User"), // Utilized by storage layer, to determine collection / table name.
withId(),
withStorage({
driver: new MongoDbDriver({ database })
})
)();
const user = new User();
user.populate({
firstName: "Adrian",
lastName: "Smith",
email: "aDrIan@google.com",
enabled: true,
scores: [34, 66, 99],
verification: {
verified: true,
verifiedOn: "2019-01-01"
}
});
await user.save();
Is Commodo an ORM/ODM?
Fundamentally, Commodo is not an ORM/ODM, but can very quickly become one, by utilizing an additional HOF. You can use the already provided @commodo/fields-storage or even create your own if you don't like the existing one.
Using HOFs is a very flexible approach for defining your data models, because you can append only the functionality you actually need and will use.
Core packages:
The following section shows all of the useful higher order functions that you can use right now.
Package | Short Description | Version |
---|---|---|
@commodo/fields | The starting point of every model. Provides base string , number , boolean and model fields. |
|
@commodo/name | Assign a name to your models. | |
@commodo/hooks | Provides methods for defining and triggering hooks on your models. | |
@commodo/fields-storage | Enables saving models to a database (with an appropriate driver, e.g. MySQL). |
Additional packages:
Package | Short Description | Version |
---|---|---|
@commodo/fields-storage-ref | Provides ref field, for saving references to other models saved in database. |
|
@commodo/fields-storage-mongodb | A MongoDB driver for @commodo/fields-storage package. | |
@commodo/fields-storage-soft-delete | Introduces deleted boolean field to mark whether a model was deleted or not, instead of physically deleting the entry in the storage. |
Community packages:
Package | Short Description | Version |
---|---|---|
commodo-fields-date | Provides date field, for saving dates. |
|
commodo-fields-object | Provides object field, for saving plain objects. |
|
commodo-fields-int | Provides int field, for saving integer numbers. |
|
commodo-fields-float | Provides float field, for saving float numbers. |
|
commodo-fields-storage-crud-logs | Adds and automatically manages createdOn , updatedOn , savedOn fields. |
Contributing
Please see our Contributing Guideline which explains repo organization, linting, testing, and other steps.
License
This project is licensed under the terms of the MIT license.