{"id":14975508,"url":"https://github.com/daton89-topperblues/mongoose-transactions","last_synced_at":"2025-09-18T13:36:39.579Z","repository":{"id":22756451,"uuid":"97004088","full_name":"daton89-topperblues/mongoose-transactions","owner":"daton89-topperblues","description":"Atomicity and Transactions for mongoose.","archived":false,"fork":false,"pushed_at":"2024-07-22T10:48:19.000Z","size":1371,"stargazers_count":53,"open_issues_count":19,"forks_count":17,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-10T23:51:54.316Z","etag":null,"topics":["mongoose","mongoose-transactions","mongoosejs","nodejs","transactions"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/daton89-topperblues.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2017-07-12T12:18:36.000Z","updated_at":"2024-07-22T10:48:23.000Z","dependencies_parsed_at":"2024-11-13T06:09:20.220Z","dependency_job_id":"c2d82109-576a-4fb8-b7c8-64ef026c6422","html_url":"https://github.com/daton89-topperblues/mongoose-transactions","commit_stats":{"total_commits":151,"total_committers":5,"mean_commits":30.2,"dds":"0.29801324503311255","last_synced_commit":"27e5253f618ac5b836f64f5823f5f8743a2e40a2"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daton89-topperblues%2Fmongoose-transactions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daton89-topperblues%2Fmongoose-transactions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daton89-topperblues%2Fmongoose-transactions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daton89-topperblues%2Fmongoose-transactions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daton89-topperblues","download_url":"https://codeload.github.com/daton89-topperblues/mongoose-transactions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248317706,"owners_count":21083528,"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":["mongoose","mongoose-transactions","mongoosejs","nodejs","transactions"],"created_at":"2024-09-24T13:52:08.452Z","updated_at":"2025-09-18T13:36:34.521Z","avatar_url":"https://github.com/daton89-topperblues.png","language":"TypeScript","funding_links":[],"categories":["Packages"],"sub_categories":["Mongoose"],"readme":"[![dm](https://img.shields.io/npm/dm/mongoose-transactions.svg)](https://www.npmjs.com/package/mongoose-transactions)\n[![version](https://img.shields.io/npm/v/mongoose-transactions.svg)](https://www.npmjs.com/package/mongoose-transactions)\n[![GitHub stars](https://img.shields.io/github/stars/daton89-topperblues/mongoose-transactions.svg?style=social\u0026label=Star)](https://www.github.com/daton89-topperblues/mongoose-transactions)\n[![GitHub forks](https://img.shields.io/github/forks/daton89-topperblues/mongoose-transactions.svg?style=social\u0026label=Fork)](https://github.com/daton89-topperblues/mongoose-transactions)\n[![mongoose-transactions](https://raw.githubusercontent.com/daton89-topperblues/mongoose-transactions/master/docs/img/mongoose-transactions.png)](https://www.npmjs.com/package/mongoose-transactions)\n\n# Introduction\n\n###### Atomicity and Transactions for mongoose\n\nA transaction is a sequential group of database manipulation operations, which is performed as if it were one single work unit. In other words, a transaction will never be complete unless each individual operation within the group is successful. If any operation within the transaction fails, the entire transaction will fail.\n\nWith this module, you can :\n\nPractically, you will club many MongoDB queries into a group and you will execute all of them together as a part of a transaction.\n\n### Getting started\n\nInstall module:\n\n```sh\n$ npm i mongoose-transactions\n```\n\nInstall and save module in your project:\n\n```sh\n$ npm i -S mongoose-transactions\n```\n\n#### API\n\nCreate new instance:\n\n```js\nconst Transaction = require('mongoose-transactions')\n\nconst transaction = new Transaction()\n```\n\nAdd an operation:\n\n```js\n/**\n * Create the insert transaction and rollback states.\n * @param modelName - The string containing the mongoose model name.\n * @param data - The object containing data to insert into mongoose model.\n * @returns id - The id of the object to insert.\n */\nconst id = transaction.insert('modelName', object)\n/**\n * Create the findOneAndUpdate transaction and rollback states.\n * @param modelName - The string containing the mongoose model name.\n * @param findId - The id of the object to update.\n * @param dataObj - The object containing data to update into mongoose model.\n * @param options - The update operation options object as { new: true }\n */\ntransaction.update('modelName', id, object, options)\n/**\n * Create the remove transaction and rollback states.\n * @param modelName - The string containing the mongoose model name.\n * @param findObj - The object containing data to find mongoose collection.\n */\ntransaction.remove('modelName', id)\n```\n\nRun operations:\n\n```js\n/**\n * Run the operations and check errors.\n * @returns Array of objects - The objects returned by operations\n *          Error - The error object containing:\n *                  data - the input data of operation\n *                  error - the error returned by the operation\n *                  executedTransactions - the number of executed operations\n *                  remainingTransactions - the number of the not executed operations\n */\ntransaction.run() // return Promise\n```\n\nRollback operations:\n\n```js\n/**\n * Rollback the executed operations if any error occurred.\n * @param   stepNumber - (optional) the number of the operation to rollback - default to length of\n *                            operation successfully runned\n * @returns Array of objects - The objects returned by rollback operations\n *          Error - The error object containing:\n *                  data - the input data of operation\n *                  error - the error returned by the operation\n *                  executedTransactions - the number of rollbacked operations\n *                  remainingTransactions - the number of the not rollbacked operations\n */\ntransaction.rollback() // return Promise\n```\n\nClean operations:\n\n```js\n/**\n * Clean the transactions object to begin a new transaction on the same instance.\n */\ntransaction.clean() // clean the previous operation\n```\n\nFull example:\n\n```js\nconst Transaction = require('mongoose-transactions')\nconst transaction = new Transaction()\n\nconst person = 'Person' // the name of the registered schema\n\nconst jonathanObject = {\n    age: 18,\n    name: 'Jonathan',\n}\nconst aliceObject = {\n    age: 23,\n    name: 'Alice',\n}\n\nasync function start() {\n    try {\n        const jonathanId = transaction.insert(person, jonathanObject)\n        transaction.update(person, jonathanId, aliceObject)\n        transaction.remove(person, 'fakeId') // this operation fail\n        const final = await transaction.run()\n        // expect(final[0].name).toBe('Jonathan')\n    } catch (error) {\n        console.error(error)\n        const rollbackObj = await transaction.rollback().catch(console.error)\n        transaction.clean()\n        //  expect(rollbacks[0].name).toBe('Alice')\n        //  expect(rollbacks[0].age).toBe(aliceObject.age)\n        //  expect(rollbacks[1].name).toBe('Jonathan')\n        //  expect(rollbacks[1].age).toBe(bobObject.age)\n    }\n}\n\nstart()\n```\n\n### Operation Object\n\nYou can get the operations object by calling getOperations method.\n\n```js\n/**\n * Get transaction operations array from transaction object or collection on db.\n * @param transactionId - Optional. If the transaction id is passed return the elements of the transaction id\n *                                  else return the elements of current transaction (default null).\n */\nconst operations = transaction.getOperations()\n```\n\nFor debug purposes you can inspect the array of transaction operation object that is designed like this:\n\n```js\n// console.log(operations)\n;[\n    {\n        /** The transaction type to run */\n        type: string, // 'insert', 'update', 'remove'\n        /** The transaction type to execute for rollback */\n        rollbackType: string, // 'remove', 'update', 'insert'\n        /** The mongoose model instance */\n        model: any, // compiled mongoose model\n        /** The mongoose model name */\n        modelName: string, // 'Person'\n        /** The mongoose model instance before transaction if exists */\n        oldModel: any, // model used for rollback\n        /** The id of the object */\n        findId: any,\n        /** The data */\n        data: any,\n        /** options configuration query */\n        options: any,\n        /** The current status of the operation */\n        status: Status,\n    },\n]\n\n/** The operations possible states are: */\nStatus = ['Pending', 'Success', 'Error', 'Rollback', 'ErrorRollback']\n```\n\nThe status is automatically updated, so you can check the current status of your transaction operations every time you need\n\n### Using database to save transactions\n\nCreate new transaction instance with the ability to store and load transaction object to/form database.\n\n```js\nconst useDB = true\nconst transaction = new Transaction(useDB)\n```\n\nFirst of all you need to get the actual transaction id, you can use the id to load the transaction object from database.\n\n```js\n/**\n * If the instance is db true, return the actual or new transaction id.\n * @throws Error - Throws error if the instance is not a db instance.\n */\nconst transId = await transaction.getTransactionId()\n```\n\nYou can load a transaction object from database with the loadDbTransaction fuction.\n\n```js\n/**\n * Load transaction from transaction collection on db.\n * @param transactionId - The id of the transaction to load.\n * @trows Error - Throws error if the transaction is not found\n */\nawait transaction.loadDbTransaction(transId)\n```\n\nYou can save the operations object on database by calling saveOperations method.\n\n```js\n/**\n * Save transaction operations array on db.\n * @throws Error - Throws error if the instance is not a db instance.\n * @return transactionId - The transaction id on database\n */\nconst transId = await transaction.saveOperations()\n```\n\nFull example:\n\n```js\nconst Transaction = require('mongoose-transactions')\nconst useDB = true\nconst transaction = new Transaction(useDB)\n\nconst person: string = 'Person'\n\nconst tonyObject: any = {\n    age: 28,\n    name: 'Tony',\n}\n\nconst nicolaObject: any = {\n    age: 32,\n    name: 'Nicola',\n}\n\nasync function start() {\n    // create operation on transaction instance\n    const id = transaction.insert(person, tonyObject)\n    transaction.update(person, id, nicolaObject, { new: true })\n\n    // get and save created operation, saveOperations method  return the transaction id saved on database\n    const operations = transaction.getOperations()\n    const transId = await transaction.saveOperations()\n\n    // create a new transaction instance\n    const newTransaction = new Transaction(true)\n\n    // load the saved operations in the new transaction instance using the transId\n    await newTransaction.loadDbTransaction(transId)\n\n    // if you need you can get the operations object\n    const newOperations = newTransaction.getOperations()\n\n    // finally run and rollback\n    try {\n        const final = await newTransaction.run()\n    } catch (err) {\n        const rolled = await newTransaction.rollback()\n    }\n}\n\nstart()\n```\n\n## More examples\n\nSee tests folder for more examples\n\nFeel free to open issues, fork project, and collaborate with us!\n\n## Contribute\n\nClone repository locally and install dependencies:\n\n```sh\n$ git clone https://github.com/daton89-topperblues/mongoose-transactions.git\n$ cd mongoose-transactions\n$ npm i\n```\n\nFork project and open pull request\n\nCurrently development runs with:\n\nNode.js v12.13.0\n\nMongoose v5.9.2\n\nTypescript v2.9.2\n\nJest v25.1.0\n\n## Changelog\n\n1.1.0 add transaction persistence\n\n1.0.4 fix exports default error\n\n### Contributors\n\n[@topperblues](https://github.com/topperblues) Nicola Bonavita\n\n[@daton89](https://github.com/daton89) Toni D'Angelo\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaton89-topperblues%2Fmongoose-transactions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaton89-topperblues%2Fmongoose-transactions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaton89-topperblues%2Fmongoose-transactions/lists"}