{"id":21206979,"url":"https://github.com/paralect/node-mongo","last_synced_at":"2025-07-10T08:33:23.100Z","repository":{"id":25703092,"uuid":"105980995","full_name":"paralect/node-mongo","owner":"paralect","description":"Node Mongo — is reactive 🚀 extension to MongoDB API","archived":false,"fork":false,"pushed_at":"2022-04-18T08:31:32.000Z","size":929,"stargazers_count":20,"open_issues_count":10,"forks_count":7,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-04-13T22:13:34.094Z","etag":null,"topics":["api","mongodb","monk","nodejs","paralect-stack","reactive","schema-validation"],"latest_commit_sha":null,"homepage":"https://github.com/paralect/node-mongo","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paralect.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-06T08:05:36.000Z","updated_at":"2023-11-09T09:10:26.000Z","dependencies_parsed_at":"2022-07-27T05:16:36.577Z","dependency_job_id":null,"html_url":"https://github.com/paralect/node-mongo","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paralect%2Fnode-mongo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paralect%2Fnode-mongo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paralect%2Fnode-mongo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paralect%2Fnode-mongo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paralect","download_url":"https://codeload.github.com/paralect/node-mongo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225629838,"owners_count":17499295,"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":["api","mongodb","monk","nodejs","paralect-stack","reactive","schema-validation"],"created_at":"2024-11-20T20:57:23.443Z","updated_at":"2024-11-20T20:57:24.102Z","avatar_url":"https://github.com/paralect.png","language":"TypeScript","readme":"# This repository is no longer maintained. Check [Ship](https://github.com/paralect/ship).\n\n# Node Mongo\n\n[![npm version](https://badge.fury.io/js/%40paralect%2Fnode-mongo.svg)](https://badge.fury.io/js/%40paralect%2Fnode-mongo)\n\nNode Mongo is reactive extension to MongoDB API.\n\n## Features\n\n* ️️**Reactive**. Fires events as document stored, updated or deleted from database\n* **Paging**. Implements high level paging API\n* **Schema validation**. Validates your data before save\n\n## Installation\n\n```\nnpm i @paralect/node-mongo\n```\n\n## Documentation\n\n### Migrate from v2 to v3\n\n1. Methods `updateOne` and `updateMany` were removed. You should use `update` to perform update of single document, matched by a query. There is no replacement for `updateMany`, normally you should just perform multiple individual updates.\n2. `service.count()` renamed into `service.countDocuments` to match MongoDB driver.\n3. Use `service.atomic.updateMany` instead `service.atomic.update` to match MongoDB.\n4. `service.aggregate()` now returns cursor instead of list of documents. You can add `toArray()`\n5. Service accepts `schema` object instead of `validateSchema` method.\n\n### Connect\n\nUsually, you need to define a file called `database` is does two things:\n1. Creates database instance and connects to the database\n2. Exposed factory method `createService` to create different services to work with MongoDB. \n\n```typescript\nimport config from 'config';\nimport { Database, Service, ServiceOptions } from '@paralect/node-mongo';\n\nconst connectionString = 'mongodb://localhost:27017';\nconst dbName = 'home-db';\nconst database = new Database(connectionString, dbName);\ndatabase.connect();\n\n// Extended service can be used here.\nfunction createService\u003cT\u003e(collectionName: string, options: ServiceOptions = {}) {\n  return new Service\u003cT\u003e(collectionName, database, options);\n}\n\nexport default {\n  database,\n  createService,\n};\n```\n\nSee [how to add additional functionality to base serivce](#extend)\n\n\n### Schema validation\n```javascript\nconst Joi = require('Joi');\n\nconst userSchema = Joi.object({\n  _id: Joi.string(),\n  createdOn: Joi.date(),\n  updatedOn: Joi.date(),\n  deletedOn: Joi.date(),\n  name: Joi.string(),\n  status: Joi.string().valid('active', 'inactive'),\n});\n\n// Pass schema object to enable schema validation\nconst userService = db.createService('users', { schema: userSchema });\n```\n\n### Extend\n\nThe whole idea is to import service and extend it with custom methods:\n\n```typescript\nimport { Service } from '@paralect/node-mongo';\n\nclass CustomService\u003cT\u003e extends Service\u003cT\u003e {\n  createOrUpdate = async (query: any, updateCallback: (item?: T) =\u003e Partial\u003cT\u003e) =\u003e {\n    const docExists = await this.exists(query);\n    if (!docExists) {\n      const newDoc = updateCallback();\n      return this.create(newDoc);\n    }\n\n    return this.update(query, doc =\u003e {\n      return updateCallback(doc);\n    });\n  };\n}\n\nexport default CustomService;\n```\n\n### Query data\n\n```typescript\n// find one document\nconst user = await userService.findOne({ name: 'Bob' });\n\n// find many documents with pagination\nconst {results, pagesCount, count } = await userService.find(\n  { name: 'Bob' },\n  { page: 1, perPage: 30 },\n);\n```\n\n### Create or update data (and publish CUD events)\n\nThe key difference of the `@paralect/node-mongo` sdk is that every create, update or remove operation peforms \nan udpate and also publeshes CUD event. Events are used to easily update denormalized data and also to implement \ncomplex business logic without tight coupling of different entities.\n\n- Reactive updates (every update publishes event)\n  - [create](#create) — create one or many documents, publishes `document.created` event\n  - [update](#update) — update one document, publishes `document.updated` event\n  - [remove](#remove) — remove document, publishes `document.removed`\n  - [removeSoft](#removeSoft) — set `deleteOn` field and publish `document.removed` event \n\nAtomic udpates **do not publish events** and usually used to update denormalized data. Most the time you should be using reactive updates.\n\n- Atomic updates (events are not published)\n  - `atomic.deleteMany`\n  - `atomic.insertMany`\n  - `atomic.updateMany`\n  - `findOneAndUpdate`\n\n[API Reference V2](API.md).\n\n#### create \n\n```typescript\nconst users = await userService.create([\n  { name: 'Alex' },\n  { name: 'Bob' },\n]);\n```\n\n#### update \n\nUpdate using callback function:\n```typescript\nconst updatedUser = await userService.update({ _id: '1' }, (doc) =\u003e {\n  doc.name = 'Alex';\n});\n```\n\nUpdate by returning fields you need to update:\n```typescript\nconst updatedUser = await userService.update({ _id: '1' }, () =\u003e ({ name: 'Alex' }));\n```\n\n### remove\n```typescript\nconst removedUser = await userService.remove({ _id: '1' });\n```\n\n### removeSoft\n```typescript\nconst removedUser = await userService.removeSoft({ _id: '1' });\n```\n\n### Event handlers\n\nSDK support two kind of events:\n- `in memory events` (published by default), can be lost on service failure, work out of the box.\n- `transactional events` guarantee that every database write will also produce an event. Transactional events can be enabled by setting `{ outbox: true }` when creating service. Transactional events require additonal infrastructure components.\n\nTo subscribe to the in memory events you can just do following:\n\n```typescript\nimport { inMemoryEventBus, InMemoryEvent } from '@paralect/node-mongo';\n\ntype UserCreatedType = InMemoryEvent\u003cany\u003e;\ntype UserUpdatedType = InMemoryEvent\u003cany\u003e;\ntype UserRemovedType = InMemoryEvent\u003cany\u003e;\n\ninMemoryEventBus.on('user.created', (doc: UserCreatedType) =\u003e {});\n\ninMemoryEventBus.on('user.updated', (doc: UserUpdatedType) =\u003e {});\n\ninMemoryEventBus.on('user.removed', (doc: UserRemovedType) =\u003e {});\n```\n\n## Change Log\n\nThis project adheres to [Semantic Versioning](http://semver.org/).\n\nEvery release is documented on the Github [Releases](https://github.com/paralect/node-mongo/releases) page.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparalect%2Fnode-mongo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparalect%2Fnode-mongo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparalect%2Fnode-mongo/lists"}