Create a plugin¶
Ilorm allows you to create plugin to add feature to the ORM.
Understand the internal¶
Ilorm use class, a plugin need to overload one or more class.
For example, a Model is always composed of at least two class; - BaseModel: The lowest representation of a Model, 100% internal, you could overload. - InternalModel: The final model which inherits from BaseModel (or plugin).
class InternalModel extends BaseModel {}
Adding a plugin, overload Base Model, and your plugin class is passed to InternalModel;
class YourPluginModel extends BaseModel {}
class InternalModel extends YourPluginModel {}
Using more than one plugin, overloading Base Model, make chainable inheritance;
class YourPluginModel1 extends BaseModel {}
class YourPluginModel2 extends YourPluginModel1 {}
class InternalModel extends YourPluginModel2 {}
To make this magic happen, your plugin need to be a class factory. The factory will take as parameter the "parent" Model;
const yourModelFactory = ({ ParentModel, }) => {
return class YourPluginModel extends ParentModel {
};
};
To make this factory usable by ilorm, you need to follow an interface; Ilorm will check if factory exists in the plugin and use the factory if it's declared;
ilorm.use({
core: {
modelFactory: yourModelFactory,
}
})
Interface¶
Ilorm let you overload everything, a plugin need to follow this interface;
{
core: {
modelFactory,
modelIdFactory,
queryFactory,
schemaFactory,
baseFieldFactory,
fieldFactories: {
booleanFieldFactory,
dateFieldFactory,
numberFieldFactory,
stringFieldFactory,
...
anyCustomFieldFactory,
},
transactionFactory,
}
}
Every factory take as parameter the parent class, and need to return the overloaded class a result.
fieldFactories is a bit different. It's allow you to create your own field. You could use it to overload existing field or create new one.
Example: Build a plugin to add soft delete¶
In this tutorial we will create a plugin to allow "soft" delete.
New field isDeleted in all schema¶
First we will create a isDeleted field into all schema, to do it, we will overload the default Schema;
function SchemaFactory(Schema) {
return class SoftDeleteSchema extends Schema {
constructor(schema) {
schema.isDeleted = this.constructor.boolean()
.required().default(false);
super(schema);
}
}
}
Change behavior of query to ignore deleted instance by default¶
We will add a constraint to ignore deleted instance when creating a query
function QueryFactory(Query) {
return class SoftDeleteQuery extends Query {
constructor(...params) {
const query = super(...params);
query.isDeleted.is(false);
return query;
}
}
}
Change behavior of delete¶
Soft delete means, updating the flag isDeleted to true.
function QueryFactory(Query) {
return class SoftDeleteQuery extends Query {
// ...
remove(...params) {
this.isDeleted.set(true);
return this.update(...params);
}
removeOne(...params) {
this.isDeleted.set(true);
return this.update(...params);
}
}
}
Had hard delete, if we want to delete instance¶
Let a way to the user to force the deletion of an instance.
function QueryFactory(Query) {
return class SoftDeleteQuery extends Query {
// ...
hardRemove(...params) {
return super.remove(...params);
}
hardRemoveOne(...params) {
return super.removeOne(...params);
}
}
}
Wrap up¶
function SchemaFactory(Schema) {
return class SoftDeleteSchema extends Schema {
constructor(schema) {
schema.isDeleted = this.constructor.boolean()
.required().default(false);
super(schema);
}
}
}
function QueryFactory(Query) {
return class SoftDeleteQuery extends Query {
constructor(...params) {
const query = super(...params);
query.isDeleted.is(false);
return query;
}
remove(...params) {
this.isDeleted.set(true);
return this.update(...params);
}
removeOne(...params) {
this.isDeleted.set(true);
return this.update(...params);
}
hardRemove(...params) {
return super.remove(...params);
}
hardRemoveOne(...params) {
return super.removeOne(...params);
}
}
}
module.exports = {
core: {
queryFactory: QueryFactory,
schemaFactory: SchemaFactory,
},
};