{"_id":"@bitscheme/feathers-mongoose","name":"@bitscheme/feathers-mongoose","dist-tags":{"latest":"8.6.0"},"versions":{"8.6.0":{"name":"@bitscheme/feathers-mongoose","description":"A Feathers service adapter for the Mongoose ORM","version":"8.6.0","homepage":"https://github.com/feathersjs-ecosystem/feathers-mongoose","main":"lib/","types":"types","keywords":["feathers","feathers-plugin","REST","Socket.io","realtime","mongodb","mongo","mongoose","service"],"license":"MIT","repository":{"type":"git","url":"git://github.com/feathersjs-ecosystem/feathers-mongoose.git"},"author":{"name":"Feathers contributors","email":"hello@feathersjs.com","url":"https://feathersjs.com"},"contributors":[{"name":"Eric Kryski","email":"e.kryski@gmail.com","url":"http://erickryski.com"},{"name":"Glavin Wiechert","email":"glavin.wiechert@gmail.com","url":"https://github.com/Glavin001"},{"name":"Marshall Thompson","email":"marshall@creativeideal.net","url":"https://github.com/marshallswain"}],"bugs":{"url":"https://github.com/feathersjs-ecosystem/feathers-mongoose/issues"},"engines":{"node":">= 12"},"scripts":{"publish":"git push origin --tags && npm run changelog && git push origin","changelog":"github_changelog_generator --user feathersjs-ecosystem --project feathers-mongoose && git add CHANGELOG.md && git commit -am \"Updating changelog\"","release:patch":"npm version patch && npm publish --access public","release:minor":"npm version minor && npm publish --access public","release:major":"npm version major && npm publish --access public","mongodb":"run-rs -v 4.0.0","lint":"semistandard --fix","dtslint":"dtslint types","mocha":"mocha --timeout 5000 --recursive test/ --exit","update-dependencies":"ncu -u","coverage":"nyc npm run mocha","test":"npm run lint && npm run coverage"},"semistandard":{"env":["mocha"]},"directories":{"lib":"lib"},"peerDependencies":{"mongoose":">=6.0.14"},"dependencies":{"@feathersjs/adapter-commons":"^4.5.15","@feathersjs/commons":"^4.5.15","@feathersjs/errors":"^5.0.0"},"devDependencies":{"@feathersjs/adapter-tests":"^4.5.15","@feathersjs/express":"^4.5.15","@feathersjs/feathers":"^4.5.15","@feathersjs/socketio":"^4.5.15","chai":"^4.3.6","dtslint":"^4.2.1","mocha":"^10.0.0","mongoose":"^6.5.4","npm-check-updates":"^16.0.6","nyc":"^15.1.0","run-rs":"^0.7.7","semistandard":"^16.0.1","sinon":"^14.0.0","sinon-chai":"^3.7.0","typescript":"^4.8.2"},"gitHead":"41cd5e15b823c3a14df23f2e67a002ed02f26d37","_id":"@bitscheme/feathers-mongoose@8.6.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-FZ3j+eRz/bIl+/BjVF9pNik365qKVOND3z8Y1XhBqwHb45P7oMvSnz1w5up/rq57CiVRZ09LcrCOFA2kRVwlvw==","shasum":"f37fe9a977abacaec97b1f51891e162a74da3dc2","tarball":"https://registry.npmjs.org/@bitscheme/feathers-mongoose/-/feathers-mongoose-8.6.0.tgz","fileCount":13,"unpackedSize":106818,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHpdFD3P8MDC7xcBg4AemgpW6o80IPYCsq8P/CAgDLkGAiA46kB0qJfMTPaiF/qCxEqyUH/FAYPOsM+zs6QjG18yHA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkJdaLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqqnQ//Qgwdsya2VWaQgPl7prB2Hy+We0lSKwfVgs18Lh8LhC+tEgOf\r\nXnw2UQ+hvCHr/ZQcVC6q/DyhN83A6eMXu08+jNSq8gscFq2YKg0Vks0M5H4g\r\nmpiM3wSKRt/zjGIEboZEwpNYe8a8Ox8vyXuYINrVtvGoLvuiUTcqfew900uN\r\ncizLZ6GbXYLWT42My+HDp7t7OTcb+omsu8P2tVh4Ks6IDAhaerr3CGe/1iGH\r\nIEjhaA98UamLVqULKSxnzWLXmLVcq+CUEMnBr+yZvrOW5pdRAaLfyO+rdhZw\r\n9oIvlGPAFMNG9VsAb2XJ5lyw3G6AO9G506HcYamaqLztAUljf/tx+SiAb7KX\r\n5GeHN9d8rpyUKE6vBT1ySFuavnyuymXXujjUvTAOJD/HbSb3oxaLY1ffKSdt\r\nc5GBNDotcUKw0Gb5TESIFQiWUrOyj39qe1JNLMlDx5ORUygJkZhyOltJvrgX\r\n8Y+VCRugkhmaM4nDTDc2kDd0eoFetyDr57OfYMbJfvnz7LjDWPt1si4YBWyu\r\n3ksGqnLGsL2uMKk1iapCSjvXKXRPQU7GySfij9XXLb5q6J5B3onqTLbFe579\r\nf9Jy4xmc67OdTy755DB56t0FiXy+qPQxgzDirfBlilii+hSydwu+Plumz9r7\r\nNO6+SsAAB8sXaFOox57QKbVmNtJpS9a+QD8=\r\n=PEkG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"james918","email":"james.disposable+npm@gmail.com"},"maintainers":[{"name":"james918","email":"james.disposable+npm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/feathers-mongoose_8.6.0_1680201355219_0.307407612421116"},"_hasShrinkwrap":false}},"time":{"created":"2023-03-30T18:35:55.141Z","8.6.0":"2023-03-30T18:35:55.403Z","modified":"2023-03-30T18:35:55.678Z"},"maintainers":[{"name":"james918","email":"james.disposable+npm@gmail.com"}],"description":"A Feathers service adapter for the Mongoose ORM","homepage":"https://github.com/feathersjs-ecosystem/feathers-mongoose","keywords":["feathers","feathers-plugin","REST","Socket.io","realtime","mongodb","mongo","mongoose","service"],"repository":{"type":"git","url":"git://github.com/feathersjs-ecosystem/feathers-mongoose.git"},"contributors":[{"name":"Eric Kryski","email":"e.kryski@gmail.com","url":"http://erickryski.com"},{"name":"Glavin Wiechert","email":"glavin.wiechert@gmail.com","url":"https://github.com/Glavin001"},{"name":"Marshall Thompson","email":"marshall@creativeideal.net","url":"https://github.com/marshallswain"}],"author":{"name":"Feathers contributors","email":"hello@feathersjs.com","url":"https://feathersjs.com"},"bugs":{"url":"https://github.com/feathersjs-ecosystem/feathers-mongoose/issues"},"license":"MIT","readme":"# feathers-mongoose\n\n[![CI](https://github.com/feathersjs-ecosystem/feathers-mongoose/workflows/CI/badge.svg)](https://github.com/feathersjs-ecosystem/feathers-mongoose/actions?query=workflow%3ACI)\n[![Dependency Status](https://img.shields.io/david/feathersjs-ecosystem/feathers-mongoose.svg?style=flat-square)](https://david-dm.org/feathersjs-ecosystem/feathers-mongoose)\n[![Download Status](https://img.shields.io/npm/dm/feathers-mongoose.svg?style=flat-square)](https://www.npmjs.com/package/feathers-mongoose)\n\nA [Feathers](https://feathersjs.com) database adapter for [Mongoose](http://mongoosejs.com/), an object modeling tool for [MongoDB](https://www.mongodb.org/).\n\n```bash\n$ npm install --save mongoose feathers-mongoose\n```\n\n> __Important:__ `feathers-mongoose` implements the [Feathers Common database adapter API](https://docs.feathersjs.com/api/databases/common.html) and [querying syntax](https://docs.feathersjs.com/api/databases/querying.html).\n\n> This adapter also requires a [running MongoDB](https://docs.mongodb.com/getting-started/shell/#) database server.\n\n\n## API\n\n### `service(options)`\n\nReturns a new service instance initialized with the given options. `Model` has to be a Mongoose model. See the [Mongoose Guide](http://mongoosejs.com/docs/guide.html) for more information on defining your model.\n\n```js\nconst mongoose = require('mongoose');\nconst service = require('feathers-mongoose');\n\n// A module that exports your Mongoose model\nconst Model = require('./models/message');\n\n// Make Mongoose use the ES6 promise\nmongoose.Promise = global.Promise;\n\n// Connect to a local database called `feathers`\nmongoose.connect('mongodb://localhost:27017/feathers');\n\napp.use('/messages', service({ Model }));\napp.use('/messages', service({ Model, lean, id, events, paginate }));\n```\n\n__Options:__\n\n- `Model` (**required**) - The Mongoose model definition\n- `lean` (*optional*, default: `true`) - Runs queries faster by returning plain objects instead of Mongoose models.\n- `id` (*optional*, default: `'_id'`) - The name of the id field property.\n- `events` (*optional*) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service\n- `paginate` (*optional*) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size\n- `whitelist` (*optional*) - A list of additional query parameters to allow (e..g `[ '$regex', '$populate' ]`)\n- `multi` (*optional*) - Allow `create` with arrays and `update` and `remove` with `id` `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`)\n- `overwrite` (*optional*, default: `true`) - Overwrite the document when update, making mongoose detect is new document and trigger default value for unspecified properties in mongoose schema.\n- `discriminators` (*optional*) - A list of mongoose models that inherit from `Model`.\n- `useEstimatedDocumentCount` (*optional*, default: `false`) - Use `estimatedDocumentCount` instead (usually not necessary)\n- `queryModifier` (*optional*) - A function that takes in the raw mongoose Query object and params, which modifies all find and get requests unless overridden. (see Query Modifiers below)\n- `queryModifierKey` (*optional*, default: `'queryModifier'`) - The key to use to get the override query modifier function from the params. (see Query Modifiers below)\n\n> **Important:** To avoid odd error handling behaviour, always set `mongoose.Promise = global.Promise`. If not available already, Feathers comes with a polyfill for native Promises.\n\n<!-- -->\n\n> **Important:** When setting `lean` to `false`, Mongoose models will be returned which can not be modified unless they are converted to a regular JavaScript object via `toObject`.\n\n<!-- -->\n\n> **Note:** You can get access to the Mongoose model via `this.Model` inside a [hook](https://docs.feathersjs.com/api/hooks.html) and use it as usual. See the [Mongoose Guide](http://mongoosejs.com/docs/guide.html) for more information on defining your model.\n\n### params.mongoose\n\nWhen making a [service method](https://docs.feathersjs.com/api/services.html) call, `params` can contain a `mongoose` property which allows you to modify the options used to run the Mongoose query. Normally, this will be set in a before [hook](https://docs.feathersjs.com/api/hooks.html):\n\n```js\napp.service('messages').hooks({\n  before: {\n    patch(context) {\n      // Set some additional Mongoose options\n      // The adapter tries to use these settings by defaults\n      // but they can always be changed here\n      context.params.mongoose = {\n        runValidators: true,\n        setDefaultsOnInsert: true\n      }\n    }\n  }\n});\n```\n\nThe `mongoose` property is also useful for performing upserts on a `patch` request.  \"Upserts\" do an update if a matching record is found, or insert a record if there's no existing match.  The following example will create a document that matches the `data`, or if there's already a record that matches the `params.query`, that record will be updated.\n\nUsing the `writeResult` mongoose option will return the write result of a `patch` operation, including the _ids of all upserted or modified documents. This can be helpful alongside the `upsert` flag, for detecting whether the outcome was a find or insert operation. More on write results is available in the [Mongo documentation](https://docs.mongodb.com/manual/reference/method/db.collection.update/#writeresult)\n\n```js\nconst data = { address: '123', identifier: 'my-identifier' }\nconst params = {\n  query: { address: '123' },\n  mongoose: { upsert: true, writeResult: true }\n}\napp.service('address-meta').patch(null, data, params)\n```\n\n\n## Example\n\nHere's a complete example of a Feathers server with a `messages` Mongoose service.\n\n```\n$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio mongoose feathers-mongoose\n```\n\nIn `message-model.js`:\n\n```js\nconst mongoose = require('mongoose');\n\nconst Schema = mongoose.Schema;\nconst MessageSchema = new Schema({\n  text: {\n    type: String,\n    required: true\n  }\n});\nconst Model = mongoose.model('Message', MessageSchema);\n\nmodule.exports = Model;\n```\n\nThen in `app.js`:\n\n```js\nconst feathers = require('@feathersjs/feathers');\nconst express = require('@feathersjs/express');\nconst socketio = require('@feathersjs/socketio');\n\nconst mongoose = require('mongoose');\nconst service = require('feathers-mongoose');\n\nconst Model = require('./message-model');\n\nmongoose.Promise = global.Promise;\n\n// Connect to your MongoDB instance(s)\nmongoose.connect('mongodb://localhost:27017/feathers');\n\n// Create an Express compatible Feathers application instance.\nconst app = express(feathers());\n\n// Turn on JSON parser for REST services\napp.use(express.json());\n// Turn on URL-encoded parser for REST services\napp.use(express.urlencoded({extended: true}));\n// Enable REST services\napp.configure(express.rest());\n// Enable Socket.io services\napp.configure(socketio());\n// Connect to the db, create and register a Feathers service.\napp.use('/messages', service({\n  Model,\n  lean: true, // set to false if you want Mongoose documents returned\n  paginate: {\n    default: 2,\n    max: 4\n  }\n}));\napp.use(express.errorHandler());\n\n// Create a dummy Message\napp.service('messages').create({\n  text: 'Message created on server'\n}).then(function(message) {\n  console.log('Created message', message);\n});\n\n// Start the server.\nconst port = 3030;\napp.listen(port, () => {\n    console.log(`Feathers server listening on port ${port}`);\n});\n```\n\nYou can run this example by using `node app` and go to [localhost:3030/messages](http://localhost:3030/messages).\n\n## Querying, Validation\n\nMongoose by default gives you the ability to add [validations at the model level](http://mongoosejs.com/docs/validation.html). Using an error handler like the one that [comes with Feathers](https://github.com/feathersjs/feathers-errors/blob/master/src/error-handler.js) your validation errors will be formatted nicely right out of the box!\n\nFor more information on querying and validation refer to the [Mongoose documentation](http://mongoosejs.com/docs/guide.html).\n\n## $populate\n\nFor Mongoose, the special `$populate` query parameter can be used to allow [Mongoose query population](http://mongoosejs.com/docs/populate.html).\n\n> **Important:** `$populate` has to be whitelisted explicitly since it can expose protected fields in sub-documents (like the user password) which have to be removed manually.\n\n```js\nconst mongoose = require('feathers-mongoose');\n\napp.use('/posts', mongoose({\n  Model,\n  whitelist: [ '$populate' ]\n});\n\napp.service('posts').find({\n  query: { $populate: 'user' }\n});\n```\n\n## Error handling\n\nAs of v7.3.0, the original Mongoose error can be retrieved on the server via:\n\n```js\nconst { ERROR } = require('feathers-mongoose');\n\ntry {\n  await app.service('posts').create({ value: 'invalid' });\n} catch(error) {\n  // error is a FeathersError\n  // Safely retrieve the original Mongoose error\n  const mongooseError = error[ERROR];\n}\n```\n\n\n## Discriminators (Inheritance)\n\nInstead of strict inheritance, Mongoose uses [discriminators](http://mongoosejs.com/docs/discriminators.html) as their schema inheritance model.\nTo use them, pass in a `discriminatorKey` option to your schema object and use `Model.discriminator('modelName', schema)` instead of `mongoose.model()`\n\nFeathers comes with full support for mongoose discriminators, allowing for automatic fetching of inherited types. A typical use case might look like:\n\n```js\nvar mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar Post = require('./post');\nvar feathers = require('@feathersjs/feathers');\nvar app = feathers();\nvar service = require('feathers-mongoose');\n\n// Discriminator key, we'll use this later to refer to all text posts\nvar options = {\n  discriminatorKey: '_type'\n};\n\nvar TextPostSchema = new Schema({\n  text: { type: String, default: null }\n}, options);\n\n// Note the use of `Post.discriminator` rather than `mongoose.discriminator`.\nvar TextPost = Post.discriminator('text', TextPostSchema);\n\n// Using the discriminators option, let feathers know about any inherited models you may have\n// for that service\napp.use('/posts', service({\n  Model: Post,\n  discriminators: [TextPost]\n}))\n\n```\n\nWithout support for discriminators, when you perform a `.get` on the posts service, you'd only get back `Post` models, not `TextPost` models.\nNow in your query, you can specify a value for your discriminatorKey:\n\n```js\n{\n  _type: 'text'\n}\n```\n\nand Feathers will automatically swap in the correct model and execute the query it instead of its parent model.\n\n## Collation Support\n\nThis adapter includes support for [collation and case insensitive indexes available in MongoDB v3.4](https://docs.mongodb.com/manual/release-notes/3.4/#collation-and-case-insensitive-indexes). Collation parameters may be passed using the special `collation` parameter to the `find()`, `remove()` and `patch()` methods.\n\n### Example: Patch records with case-insensitive alphabetical ordering\n\nThe example below would patch all student records with grades of `'c'` or `'C'` and above (a natural language ordering). Without collations this would not be as simple, since the comparison `{ $gt: 'c' }` would not include uppercase grades of `'C'` because the code point of `'C'` is less than that of `'c'`.\n\n```js\nconst patch = { shouldStudyMore: true };\nconst query = { grade: { $gte: 'c' } };\nconst collation = { locale: 'en', strength: 1 };\nstudents.patch(null, patch, { query, collation }).then( ... );\n```\n\n### Example: Find records with a case-insensitive search\n\nSimilar to the above example, this would find students with a grade of `'c'` or greater, in a case-insensitive manner.\n\n```js\nconst query = { grade: { $gte: 'c' } };\nconst collation = { locale: 'en', strength: 1 };\nstudents.find({ query, collation }).then( ... );\n```\n\nFor more information on MongoDB's collation feature, visit the [collation reference page](https://docs.mongodb.com/manual/reference/collation/).\n\n\n## Mongo-DB Transaction\n\nThis adapter includes support to enable database transaction to rollback the persisted records for any error occured for a api call. This requires  [Mongo-DB v4.x](https://docs.mongodb.com/manual/) installed and [replica-set](https://linode.com/docs/databases/mongodb/create-a-mongodb-replica-set/#start-replication-and-add-members) enabled.\n\nStart working with transaction enabled by adding the following lines in `app.hooks.js` or `<any-service>.hooks.js`.\n\n```js\nconst TransactionManager = require('feathers-mongoose').TransactionManager;\nconst isTransactionEnable = process.env.TRANSACTION_ENABLE || false;\nconst skipPath = ['login'];\n\nlet moduleExports = {\n  before: {\n    all: [],\n    find: [],\n    get: [],\n    create: [\n      when(isTransactionEnable, async hook =>\n        TransactionManager.beginTransaction(hook, skipPath)\n      )\n    ],\n    update: [\n      when(isTransactionEnable, async hook =>\n        TransactionManager.beginTransaction(hook, skipPath)\n      )\n    ],\n    patch: [],\n    remove: []\n  },\n\n  after: {\n    all: [],\n    find: [],\n    get: [],\n    create: [when(isTransactionEnable, TransactionManager.commitTransaction)],\n    update: [when(isTransactionEnable, TransactionManager.commitTransaction)],\n    patch: [],\n    remove: []\n  },\n\n  error: {\n    all: [],\n    find: [],\n    get: [],\n    create: [when(isTransactionEnable, TransactionManager.rollbackTransaction)],\n    update: [when(isTransactionEnable, TransactionManager.rollbackTransaction)],\n    patch: [],\n    remove: []\n  }\n};\n\nmodule.exports = moduleExports;\n```\n\n## Query Modifiers\n\nSometimes it's important to use an unusual Mongoose Query method, like [specifying whether to read from a primary or secondary node,](https://mongoosejs.com/docs/api.html#query_Query-read) but maybe only for certain requests.\n\nYou can access the internal Mongoose Query object used for a find/get request by specifying the queryModifier function. It is also possible to override that global function by specifying the function in a requests params.\n\n```js\n// Specify a global query modifier when creating the service\napp.use('/messages', service({\n  Model,\n  queryModifier: (query, params) => {\n    query.read('secondaryPreferred');\n  }\n}));\n\napp.service('messages').find({\n  query: { ... },\n}).then((result) => {\n  console.log('Result from secondary:', result)\n});\n\n// Override the modifier on a per-request basis\napp.service('messages').find({\n  query: { ... },\n  queryModifier: (query, params) => {\n    query.read('primaryPreferred');\n  }\n}).then((result) => {\n  console.log('Result from primary:', result)\n});\n\n// Disable the global modifier on a per-request basis\napp.service('messages').find({\n  query: { ... },\n  queryModifier: false\n}).then((result) => {\n  console.log('Result from default option:', result)\n});\n```\n\n> **Note:** Due to replication lag, a secondary node can have \"stale\" data. You should ensure that this \"staleness\" will not be an issue for your application before reading from the secondary set.\n\n## Contributing\n\nThis module is community maintained and open for pull requests. Features and bug fixes should contain\n\n- The bug fix / feature code\n- Tests to reproduce the bug or test the feature\n- Documentation updates (if necessary)\n\nTo contribute, fork and clone the repository. To run the tests, a MongoDB v4.0.0 server is required. If you do not have a MongoDB server running you can start one with:\n\n```\nnpm run mongodb\n```\n\nThe command needs to stay open while running the tests with\n\n\n```\nnpm test\n```\n\n## License\n\n[MIT](LICENSE)\n\n## Authors\n\n- [Feathers contributors](https://github.com/feathersjs-ecosystem/feathers-mongoose/graphs/contributors)\n","readmeFilename":"README.md"}