Protect your database from data loss by soft deleting your rows.
I don't use this package anymore so it's un-maintained. I still spend a little time managing small fixes but do so at a fairly slow pace. If you're interested in maintaining this project, please reach out to me.
npm i --save bookshelf-paranoia,
all you need to do is add it as a bookshelf plugin and enable it on your models.
The default field used to soft delete your models is
deleted_at but you can override that.
let knex = developmentlet bookshelf = knex// Add the pluginbookshelf// Enable it on your modelslet User = bookshelfModel
You can call every method as usual and
bookshelf-paranoia will handle soft
deletes transparently for you.
// This user is indestructibleUser// Now try to find it againlet user = User // null// It won't exist, even through eager loadingslet user = User // undefinedlet blog = Blogblog // also undefined// But we didn't delete it from the databaselet user =console // Fri Apr 15 2016 00:40:40 GMT-0300 (BRT)
bookshelf-paranoia provides a set of overrides so you can customize your
experience while using it.
// Override the field name that holds the deletion datebookshelf// Override the null value if you're using a database that defaults values to// something other than nullbookshelf// If you want to delete something for good, even if the model has soft deleting onUser// Retrieve a soft deleted row even with the plugin enabled. Works for// eager loaded relations toolet user = User// By default soft deletes also emit "destroying" and "destroyed" events. You// can easily disable this behavior when setting the pluginbookshelf// Disable only one eventbookshelf// Enable saving, updating, saved, and updated. This will turn on all events// since destroying and destroyed are already on by defaultbookshelf
Due to limitations with some DBMSes, constraining a soft-delete-enabled model to "only one active instance" is difficult: any unique index will capture both undeleted and deleted rows. There are ways around this, e.g., scoped indexes (WHERE deleted_at IS NULL), but the most portable method involves adding a so-called sentinel column: a field that is true/1 when the row is active and NULL when it has been deleted. Since unique indexes do not consider null fields, this allows a compound unique index to fulfill our needs: indexing ['email', 'active'] will ensure only one unique active email at a time, for example.
To maintain backward compatibility, sentinel functionality is disabled
by default. It can be enabled globally by setting the
value to the name of the sentinel column, nominally "active". The
sentinel column should be added to all soft-deletable tables via
migration as a nullable boolean field.
// Enable sentinel values stored under "active"bookshelflet user = Useruser // will be trueuseruser // will be false
Detecting soft deletes
By listening to the default events emitted by bookshelf when destroying a model you're able to detect if that model is being soft deleted.
let model = id: 1000// Watch for deletes as usualmodelmodelmodel// User 1000 is being soft deleted!// User 1000 has been soft deleted!
git clone email@example.com:bsiddiqui/bookshelf-paranoia.gitcd bookshelf-paranoia && npm install && npm test