This is a mongoose plugin for tracking history and differences of your docs.
yarn add mongoose-history-diff
npm i mongoose-history-diff
import DiffPlugin from 'mongoose-history-diff';
PostSchema.plugin(DiffPlugin, {
orderIndependent: true,
diffCollectionName: 'my_diffs',
});
orderIndependent
option define whether the order of array elements is important or not. If true
then it won't create a new diff. By default false.
diffCollectionName
option define the name of collection with diffs. If not provided ${parent_collection_name}_diffs
will be used.
You can exclude document fields from tracking by adding { track_diff: false }
property to your field definition inside the schema:
export const PostSchema: MongooseSchema<PostDoc> = new mongoose.Schema(
{
title: {
type: String,
},
text: {
type: String,
track_diff: false,
},
authors: [
{
name: { type: String }
lname: { type: String }, track_diff: false },
},
],
{
timestamps: true,
collection: 'post',
}
);
The _id field is excluded from the tracking by default.
After adding, the plugin will create a diff document with the following shape in a separate collection on every changing of your documents.
{
_id: '5c33240bd7cce8cba92030aa',
dId: '5c25abc9c9a367742cd5341b',
c : [
{
p : [
'lastname'
],
k : 'E',
l : 'borodaev',
r : 'Borodayev'
}
],
v: 4,
createdAt: '2019-01-07T10:03:55.933Z',
updatedAt: '2019-01-07T10:03:55.933Z',
}
Important! Plugin creates diffs on a preSave
mongoose hook. That's why all methods which directly operates with MongoDB won't call creating diff.
Diffs are represented as one or more change records. Change records have the following structure:
k
- indicates the kind of change; will be one of the following:N
- indicates a newly added property/elementD
- indicates a property/element was deletedE
- indicates a property/element was editedA
- indicates a change occurred within an array
p
- the property pathl
- the value that was (undefined ifk === 'N'
)r
- the value that become (undefined ifk === 'D'
)i
- whenk === 'A'
, indicates the array index where the change occurredit
- whenk === 'A'
, contains a nested change record indicating the change that occurred at the array index
Under the hood, the plugin uses refactored and simplified algorithm of deep-diff
package, that is why this plugin has similar structure of changes. You can explore that repo too if you are interested in.
Also, the plugin will add a static diffModel
method that returns the model of diff collection.
const Diff = Post.diffModel();
This model contains several static methods as well:
findByDocId(_id: ObjectId)
- finds all diffs by parent doc_id
findAfterVersion(_id: ObjectId, v: number)
- finds all diffs by parent doc_id
after specific versionfindBeforeVersion(_id: ObjectId, v: number)
- finds all diffs docs by parent doc_id
before specific versionrevertToVersion(doc: Object, v: number)
- reverts changes of specific doc to a specific version.mergeDiffs(doc: MongooseDocument)
- return all diffs between current doc state and initial doc state.
Feel free to submit a pull request. Also, be sure all tests have passed otherwise pull request won't be merged.