{"id":21418447,"url":"https://github.com/bsovs/mongoose-time-machine","last_synced_at":"2025-07-14T05:31:06.414Z","repository":{"id":38425982,"uuid":"356363994","full_name":"bsovs/mongoose-time-machine","owner":"bsovs","description":"Mongoose history plugin allowing for many/few history collections depending on your needs. Built in hooks and methods with the option to manually add more.","archived":false,"fork":false,"pushed_at":"2023-03-05T23:51:55.000Z","size":988,"stargazers_count":4,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-27T23:49:51.172Z","etag":null,"topics":["audit","diff","history","microservices","mongodb","mongoose","nodejs","rollback","versioning"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bsovs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-09T18:26:21.000Z","updated_at":"2023-10-20T12:00:02.000Z","dependencies_parsed_at":"2025-03-13T09:02:31.540Z","dependency_job_id":"6aa304c9-9c69-45cc-b564-3a73fa6271d5","html_url":"https://github.com/bsovs/mongoose-time-machine","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bsovs/mongoose-time-machine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsovs%2Fmongoose-time-machine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsovs%2Fmongoose-time-machine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsovs%2Fmongoose-time-machine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsovs%2Fmongoose-time-machine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bsovs","download_url":"https://codeload.github.com/bsovs/mongoose-time-machine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsovs%2Fmongoose-time-machine/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265245950,"owners_count":23734108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit","diff","history","microservices","mongodb","mongoose","nodejs","rollback","versioning"],"created_at":"2024-11-22T19:21:30.549Z","updated_at":"2025-07-14T05:31:06.045Z","avatar_url":"https://github.com/bsovs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/bsovs/mongoose-time-machine.svg?branch=main)](https://travis-ci.com/bsovs/mongoose-time-machine)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/3c4a540fdfd74b6f8f016d6644a313b2)](https://www.codacy.com/gh/bsovs/mongoose-time-machine/dashboard?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=bsovs/mongoose-time-machine\u0026utm_campaign=Badge_Grade)\n[![Maintainability](https://api.codeclimate.com/v1/badges/d5933d4166719ff11775/maintainability)](https://codeclimate.com/github/bsovs/mongoose-time-machine/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/d5933d4166719ff11775/test_coverage)](https://codeclimate.com/github/bsovs/mongoose-time-machine/test_coverage)\n\n# mongoose-time-machine\n\nStores and Manages all the differences and versions, any Mongo collection goes through it's lifecycle.\n\n-   Based on the popular project [mongoose-diff-history](https://github.com/mimani/mongoose-diff-history)\n\n## Installation\n\n---\n\n### npm\n\n```sh\nnpm install mongoose-time-machine\n```\n\n## Operation\n\n---\n\nEach update will create a history record with [jsonDiff](https://github.com/benjamine/jsondiffpatch) of the change. This helps in tracking all the changes happened to an object from the beginning.\n\nFollowing will be the structure of the diff history being saved:\n\ndiff Collection schema:\n\n```\n_id : mongo id of the diff object\ncollectionId : Mongo Id of the collection being modified\ndiff: diff object\nuser: User who modified\nreason: Why the collection is modified\ncreatedAt: When the collection is modified\n_v: version\n```\n\n## Usage\n\n---\n\nUse as you would any Mongoose plugin:\n\n```js\nconst mongoose = require('mongoose'),\n      timeMachine = require('mongoose-time-machine'),\n      schema = new mongoose.Schema({ ... });\n      schema.plugin(timeMachine.plugin, { name: 'SchemaHistory' });\n```\n\nThe plugin also has an omit option which accepts either a string or array. This will omit the given\nkeys from history. Follows dot syntax for deeply nested values.\n\n```js\nconst mongoose = require('mongoose');\nconst timeMachine = require('mongoose-time-machine');\n\nconst schema = new mongoose.Schema({\n    someField: String,\n    ignoredField: String,\n    some: {\n        deepField: String\n    }\n});\n\nschema.plugin(timeMachine.plugin, {\n    name: 'MyModelHistory',\n    omit: ['ignoredField', 'some.deepField']\n});\nconst mongooseModel = mongoose.model('MyModel', schema);\n```\n\nYou can pass in a mongoose adapter to use for your history models as well. This allows for models to be connected to different clusters/collections.\n\n```js\nconst myAdapter = await mongoose.createConnection(\n    `${uri}/${databaseName}?retryWrites=true`,\n    {}\n);\n\nschema.plugin(timeMachine.plugin, {\n    name: 'MyModelHistory',\n    adapter: myAdapter\n});\nconst mongooseModel = myAdapter.model('MyModel', schema);\n\n// MyModelHistory model now lives at the same uri/databaseName as the mongooseModel created\n```\n\n## Helper Methods\n\n---\n\nYou can get all the histories created for an object using following method:\n\n```js\nconst expandableFields = ['abc', 'def'];\n\nmongooseModel.getHistories(\n    ObjectId,\n    expandableFields,\n    function (err, histories) {}\n);\n\n// or, as a promise\nmongooseModel\n    .getHistories(ObjectId, expandableFields)\n    .then(histories =\u003e {})\n    .catch(console.error);\n```\n\nIf you just want the raw histories return with json diff patches:\n\n```js\nmongooseModel.getDiffs(ObjectId, function (err, histories) {});\n\n// or, as a promise\nmongooseModel\n    .getDiffs(ObjectId)\n    .then(histories =\u003e {})\n    .catch(console.error);\n\n// with optional query parameters:\nmongooseModel\n    .getDiffs(ObjectId, { select: 'diff user' })\n    .then(histories =\u003e {})\n    .catch(console.error);\n```\n\nYou can get an older version of the object using following method:\n\n```js\nmongooseModel.getVersion(ObjectId, version, function (err, oldObject) {});\n\n// or, as a promise\nmongooseModel\n    .getVersion(ObjectId, version)\n    .then(oldObject =\u003e {})\n    .catch(console.error);\n```\n\nYou can also use Mongoose query options with getVersion like so:\n\n```js\nmongooseModel.getVersion(\n    ObjectId,\n    version,\n    { lean: true },\n    function (err, oldObject) {}\n);\n\n// or, as a promise\nmongooseModel\n    .getVersion(ObjectId, version, { lean: true })\n    .then(oldObject =\u003e {})\n    .catch(console.error);\n```\n\n## Access History Model\n\nYou can access the model's history-model by calling: `mongooseModel.history` on your attached model\n\nFrom there you can call custom mongoose queries on the history model:\n\n```js\nmongooseModel.history\n    .find({ diff: { name: 'foo' } })\n    .limit(10)\n    .then(oldObject =\u003e {})\n    .catch(console.error);\n```\n\n## Example\n\n---\n\nThe example found [here](https://github.com/bsovs/mongoose-time-machine/tree/master/example) is an express service (documentation [here](https://github.com/bsovs/mongoose-time-machine/blob/master/example/README.md)), demonstrating this plugin via an simple employee schema, checkout `example` directory in this repo.\n\n## Contributing\n\n---\n\nThis project is now using [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) syntax for commit messages, to allow for easier updates in change logs \u0026 release notes. Please follow these conventions in your commits.\n\n### Test Locally\n\n-   Install [Docker Desktop](https://www.docker.com/products/docker-desktop)\n-   Run `npm run dc:db-up` to start local mongoDB on port 27017\n-   In the console type:\n    -   `mongo`\n    -   then copy paste\n        ```sh\n        rs.initiate(\n          {\n            _id : 'rs0',\n            members: [\n              { _id : 0, host : \"mongo1:27017\" },\n              { _id : 1, host : \"mongo2:27017\" },\n              { _id : 2, host : \"mongo3:27017\" }\n            ]\n          }\n        )\n        ```\n-   You can view the database by connecting to `mongodb://localhost:27017,localhost:27018,localhost:27019/tekpub_test?replicaSet=rs0` through [mongo compass](https://www.mongodb.com/try/download/compass)\n-   Run test suite with `npm run test`\n\n### Available Commands\n\n-   `dc:db-up` start local db\n-   `dc:db-down` stop local db\n-   `dc:db-destroy` delete local db\n-   `test` run test suite\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsovs%2Fmongoose-time-machine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbsovs%2Fmongoose-time-machine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsovs%2Fmongoose-time-machine/lists"}