From afb08f9a723e31526936a7fd3cc686d1a941dbec Mon Sep 17 00:00:00 2001 From: aymann90 Date: Tue, 29 Apr 2025 13:34:58 +0300 Subject: [PATCH 1/2] update typescript support --- CHANGELOG.md | 122 ++++++++++-------- README.md | 44 ++++++- package-lock.json | 32 +++-- package.json | 4 +- src/drivers/database/MongoDriver.js | 44 ++++++- src/drivers/database/SqlDriver.js | 43 +++++- src/drivers/queue/rabbitmq.js | 7 + src/drivers/queue/redis.js | 6 + .../InitializeCentralConnection.js | 10 ++ src/middlewares/InitializeTenancy.js | 10 ++ src/utils/db.js | 60 +++++++-- 11 files changed, 300 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea01d59..72e3845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ # Changelog -## v1.2.1 - 27 Apr, 2025 +## [1.2.2] - 2025-04-29 + +### Added + +- TypeScript support with type definitions (index.d.ts) +- Comprehensive JSDoc comments for better code documentation + +### Changed + +- Updated all dependencies to latest compatible versions +- Enhanced JSON response formatting for errors + +### Fixed + +- Connection cleanup on errors +- Schema registration to avoid duplicates +- Central domain validation logic + +## [1.2.1] - 2025-04-29 ### Features @@ -31,7 +49,7 @@ const connection = await queue.connect('redis://test:test@redis.test'); --- -## v1.2.0 - 16 Apr, 2025 +## [1.2.0] - 2025-04-16 ### Features @@ -44,7 +62,7 @@ const connection = await queue.connect('redis://test:test@redis.test'); --- -## v1.1.0 - 16 Mar, 2025 +## [1.1.0] - 2025-03-16 Adding jest tests and some code improvements to queue connection. @@ -66,46 +84,46 @@ queueClass.publishMessage('support_test', {'message': 'test'}, true); const {queue, config} = require('node-tenancy'); function setConnectionConfig(is_tenant_connection) { - if (is_tenant_connection) { - config.setConfig({ - 'connection': 'tenant', - }); - } else { - config.setConfig({ - 'connection': 'central', - }); - } + if (is_tenant_connection) { + config.setConfig({ + 'connection': 'tenant', + }); + } else { + config.setConfig({ + 'connection': 'central', + }); + } } async function getMessages(queue_name, is_tenant_connection = false) { - setConnectionConfig(is_tenant_connection); - - const conn = await queue.connect(queue.getConnectionUrl()); - const channel = await conn.createChannel(); - - await channel.assertQueue(queue_name); - - channel.consume(queue_name, async (msg) => { - if (msg !== null) { - console.log('Received:', msg.content.toString()); - channel.ack(msg); - } else { - console.log('Consumer cancelled by server'); - } - await channel.close(); - await conn.close(); - }); + setConnectionConfig(is_tenant_connection); + + const conn = await queue.connect(queue.getConnectionUrl()); + const channel = await conn.createChannel(); + + await channel.assertQueue(queue_name); + + channel.consume(queue_name, async (msg) => { + if (msg !== null) { + console.log('Received:', msg.content.toString()); + channel.ack(msg); + } else { + console.log('Consumer cancelled by server'); + } + await channel.close(); + await conn.close(); + }); } async function publishMessage(queue_name, message, is_tenant_connection = false) { - setConnectionConfig(is_tenant_connection); - - const conn = await queue.connect(queue.getConnectionUrl()); - const channel = await conn.createChannel(); - channel.sendToQueue(queue_name, Buffer.from(JSON.stringify(message))); - setTimeout(function () { - conn.close(); - }, 500); + setConnectionConfig(is_tenant_connection); + + const conn = await queue.connect(queue.getConnectionUrl()); + const channel = await conn.createChannel(); + channel.sendToQueue(queue_name, Buffer.from(JSON.stringify(message))); + setTimeout(function () { + conn.close(); + }, 500); } module.exports = {getMessages, publishMessage}; @@ -113,7 +131,7 @@ module.exports = {getMessages, publishMessage}; --- -## v1.0.4 - 7 Mar, 2025 +## [1.0.4] - 2025-03-07 ### File Structure @@ -129,23 +147,23 @@ errors you might get with v1.0.4*** const {queue} = require('node-tenancy'); queue.connect(queue.getConnectionUrl(), function (connectionErr, connection) { - if (connectionErr) { - console.log(connectionErr); - } - connection.createChannel(function (channelErr, channel) { - if (channelErr) { - console.log(channelErr); + if (connectionErr) { + console.log(connectionErr); } + connection.createChannel(function (channelErr, channel) { + if (channelErr) { + console.log(channelErr); + } - const queue = 'test'; + const queue = 'test'; - channel.assertQueue(queue, { - durable: true - }); + channel.assertQueue(queue, { + durable: true + }); - channel.consume(queue, function (msg) { - console.log(msg); - }); - }) + channel.consume(queue, function (msg) { + console.log(msg); + }); + }) }); ``` diff --git a/README.md b/README.md index 60644a1..3388b33 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Trying to make it like [Tenancy for Laravel](https://tenancyforlaravel.com) - [Queue](#2-queue-connection) - [Mongoose Usage](#3-using-mongoose) - [Sql Usage](#4-using-sql-with-sequelize) + - [TypeScript Support](#typescript-support) - [CHANGELOG](CHANGELOG.md) (for latest updates and changes) ## Support @@ -68,7 +69,7 @@ const tenancy = require('node-tenancy'); router.use(tenancy.initializeTenancyMiddleware); router.get('/get', function (Request, Response) { - return Response.status(200).json("Hello"); + return Response.status(200).json("Hello"); }); ``` @@ -82,9 +83,9 @@ const tenancy = require('node-tenancy'); router.use(tenancy.initializeCentralMiddleware); router.get('/get', function (Request, Response) { - return Response.status(200).json({ - 'tenant_id': tenancy.config.getConfig().tenant_id - }); + return Response.status(200).json({ + 'tenant_id': tenancy.config.getConfig().tenant_id + }); }); ``` @@ -119,3 +120,38 @@ Read more about it here [Sequelize guide](docs/SQL.md). **In case you are using mongodb we assume that domains is an array inside tenants collection** + +## TypeScript Support + +Tenancy now includes TypeScript type definitions. Example usage: + +```typescript +import {config, TenantSchema, db} from 'node-tenancy'; +import {Schema} from 'mongoose'; + +// Define schemas with TypeScript types +interface User { + username: string; + email: string; + active: boolean; + createdAt: Date; +} + +const userSchema = new Schema({ + username: String, + email: {type: String, required: true}, + active: {type: Boolean, default: true}, + createdAt: {type: Date, default: Date.now} +}); + +// Configure tenancy +config.setConfig({ + central_domains: ["admin.myapp.com"], + tenant_schemas: { + "User": userSchema + }, + central_schemas: { + "Tenant": TenantSchema + } +}); +``` diff --git a/package-lock.json b/package-lock.json index 7afcbfe..25c1b3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-tenancy", - "version": "1.2.1", + "version": "1.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-tenancy", - "version": "1.2.1", + "version": "1.2.2", "license": "ISC", "dependencies": { "amqplib": "^0.10.5", @@ -25,6 +25,8 @@ "@babel/core": "^7.26.9", "@babel/preset-env": "^7.26.9", "@shelf/jest-mongodb": "^5.1.0", + "@types/amqplib": "^0.10.5", + "@types/node": "^20.11.30", "babel-jest": "^29.7.0", "jest": "^29.7.0", "pg": "^8.14.1", @@ -2263,6 +2265,16 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@types/amqplib": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.7.tgz", + "integrity": "sha512-IVj3avf9AQd2nXCx0PGk/OYq7VmHiyNxWFSb5HhU9ATh+i+gHWvVcljFTcTWQ/dyHJCTrzCixde+r/asL2ErDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2351,11 +2363,12 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "node_modules/@types/node": { - "version": "22.13.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", - "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", + "version": "20.17.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.32.tgz", + "integrity": "sha512-zeMXFn8zQ+UkjK4ws0RiOC9EWByyW1CcVmLe+2rQocXRsGEDxUCwPEIVgpsGcLHS/P8JkT0oa3839BRABS0oPw==", + "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.19.2" } }, "node_modules/@types/stack-utils": { @@ -6211,9 +6224,10 @@ "dev": true }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", diff --git a/package.json b/package.json index f1987b0..11c9ad2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-tenancy", - "version": "1.2.1", + "version": "1.2.2", "description": "Automatic multi-tenancy for Node with support to Rabbitmq", "main": "index.js", "homepage": "https://github.com/johnabil/tenancy#readme", @@ -43,6 +43,8 @@ "@babel/core": "^7.26.9", "@babel/preset-env": "^7.26.9", "@shelf/jest-mongodb": "^5.1.0", + "@types/amqplib": "^0.10.5", + "@types/node": "^20.11.30", "babel-jest": "^29.7.0", "jest": "^29.7.0", "pg": "^8.14.1", diff --git a/src/drivers/database/MongoDriver.js b/src/drivers/database/MongoDriver.js index 340c18e..85939c4 100644 --- a/src/drivers/database/MongoDriver.js +++ b/src/drivers/database/MongoDriver.js @@ -2,6 +2,11 @@ const mongoose = require('mongoose'); const Config = require('../../utils/config'); const DatabaseDriver = require('../../utils/db'); +/** + * Find tenant by domain + * @param {string} domain - Domain to search for + * @returns {Promise} - Returns tenant document + */ function getTenantModel(domain) { let model = null; const connection = DatabaseDriver.resolveCentralConnection(); @@ -23,11 +28,18 @@ function getTenantModel(domain) { } } +/** + * Register schemas with Mongoose connection + * @param {Object} connection - Mongoose connection + * @param {Object} schemas - Object containing schemas to register + */ function registerSchemas(connection, schemas = {}) { if (Object.keys(schemas).length > 0) { try { for (const model_name in schemas) { - connection.model(model_name, schemas[model_name]); + if (!connection.models[model_name]) { + connection.model(model_name, schemas[model_name]); + } } } catch (error) { throw error; @@ -37,32 +49,58 @@ function registerSchemas(connection, schemas = {}) { } } +/** + * Create a MongoDB connection + * @param {string} connection - MongoDB connection string + * @param {string} db_name - Database name + * @param {Object} options - MongoDB connection options + * @returns {Object} - Mongoose connection + */ function connect(connection, db_name, options = {}) { const db_connection = mongoose.createConnection(connection, options); return db_connection.useDb(db_name, {useCache: true}); } +/** + * Disconnect from MongoDB + */ function disconnect() { mongoose.disconnect().catch((err) => { throw err }); } +/** + * Get a model by name from the current connection + * @param {string} model_name - Model name + * @returns {Object} - Mongoose model + */ function getModel(model_name) { let connection_name = Config.getConfig()?.connection; switch (connection_name) { case 'tenant': return Config.getConfig()?.tenant_connection.model(model_name); - case'central': + case 'central': return Config.getConfig()?.central_connection.model(model_name); default: throw new Error(`No database connections found.`); } } +/** + * Get the default tenant schema + * @returns {Object} - Mongoose schema for tenant + */ function getDefaultTenantSchema() { return require('../../schemas/mongodb/Tenant'); } -module.exports = {getTenantModel, connect, disconnect, registerSchemas, getModel, getDefaultTenantSchema}; +module.exports = { + getTenantModel, + connect, + disconnect, + registerSchemas, + getModel, + getDefaultTenantSchema +}; diff --git a/src/drivers/database/SqlDriver.js b/src/drivers/database/SqlDriver.js index 9fb8d54..dbd24c9 100644 --- a/src/drivers/database/SqlDriver.js +++ b/src/drivers/database/SqlDriver.js @@ -2,6 +2,11 @@ const Config = require('../../utils/config'); const DatabaseDriver = require('../../utils/db'); const {Sequelize} = require('sequelize'); +/** + * Find tenant by domain + * @param {string} domain - Domain to search for + * @returns {Promise} - Returns tenant document + */ function getTenantModel(domain) { let model = null; const connection = DatabaseDriver.resolveCentralConnection(); @@ -31,14 +36,19 @@ function getTenantModel(domain) { } } -function registerSchemas(connection, schemas = {}) { +/** + * Register schemas with Sequelize connection + * @param {Object} connection - Sequelize connection + * @param {Class} schemas - Array of schema definers + */ +function registerSchemas(connection, schemas= null) { try { - //defining models + // Defining models for (const modelDefiner of schemas) { modelDefiner(connection); } - //applying associations + // Applying associations for (const model_name in connection.models) { const model = connection.models[model_name]; if (model?.associate) { @@ -50,6 +60,13 @@ function registerSchemas(connection, schemas = {}) { } } +/** + * Create a SQL database connection + * @param {string} connection - SQL connection string + * @param {string} db_name - Database name + * @param {Object} options - SQL connection options + * @returns {Object} - Sequelize connection + */ function connect(connection, db_name, options = {}) { const dialect = process.env.DB_DRIVER; options.database = db_name; @@ -59,20 +76,36 @@ function connect(connection, db_name, options = {}) { return new Sequelize(connection, options); } +/** + * Get a model by name from the current connection + * @param {string} model_name - Model name + * @returns {Object} - Sequelize model + */ function getModel(model_name) { let connection_name = Config.getConfig()?.connection; + switch (connection_name) { case 'tenant': return Config.getConfig()?.tenant_connection?.models[model_name]; - case'central': + case 'central': return Config.getConfig()?.central_connection?.models[model_name]; default: throw new Error(`No database connections found.`); } } +/** + * Get the default tenant schema + * @returns {Function} - Schema definer for Tenant + */ function getDefaultTenantSchema() { return require('../../schemas/sql/Tenant'); } -module.exports = {getTenantModel, connect, registerSchemas, getModel, getDefaultTenantSchema}; +module.exports = { + getTenantModel, + connect, + registerSchemas, + getModel, + getDefaultTenantSchema +}; diff --git a/src/drivers/queue/rabbitmq.js b/src/drivers/queue/rabbitmq.js index 0e25a52..b099e1f 100644 --- a/src/drivers/queue/rabbitmq.js +++ b/src/drivers/queue/rabbitmq.js @@ -1,5 +1,12 @@ const RabbitMQ = require('amqplib'); + +/** + * Connect to RabbitMQ server with retry capability + * @param {string} url - RabbitMQ connection URL + * @param {Object} options - RabbitMQ connection options + * @returns {Promise} - Returns RabbitMQ connection + */ async function connect(url, options = {}) { try { return await RabbitMQ.connect(url, options); diff --git a/src/drivers/queue/redis.js b/src/drivers/queue/redis.js index 78ec31a..7d4de0a 100644 --- a/src/drivers/queue/redis.js +++ b/src/drivers/queue/redis.js @@ -1,5 +1,11 @@ const {createClient} = require('redis'); +/** + * Connect to Redis server + * @param {string} url - Redis connection URL + * @param {Object} options - Redis connection options + * @returns {Promise} - Returns Redis client instance + */ async function connect(url, options = {}) { try { const basic_config = { diff --git a/src/middlewares/InitializeCentralConnection.js b/src/middlewares/InitializeCentralConnection.js index 1ac70a1..819539b 100644 --- a/src/middlewares/InitializeCentralConnection.js +++ b/src/middlewares/InitializeCentralConnection.js @@ -2,6 +2,16 @@ const DatabaseDriver = require('../utils/db'); const QueueDriver = require('../utils/queue'); const Config = require('../utils/config'); + +/** + * Middleware to initialize central database connection + * Used for admin routes that manage multiple tenants + * + * @returns {Promise} + * @param Request + * @param Response + * @param Next + */ module.exports = function (Request, Response, Next) { const central_domains = Config.getConfig().central_domains; const domain = Request.hostname; diff --git a/src/middlewares/InitializeTenancy.js b/src/middlewares/InitializeTenancy.js index 57efbf7..32f7037 100644 --- a/src/middlewares/InitializeTenancy.js +++ b/src/middlewares/InitializeTenancy.js @@ -3,6 +3,16 @@ const DatabaseDriver = require('../utils/db'); const QueueDriver = require('../utils/queue'); const Config = require('../utils/config'); + +/** + * Middleware to initialize multi-tenancy based on domain + * Resolves the tenant connection and schemas for the current request + * + * @param {Object} Request + * @param Response + * @param Next + * @returns {Promise} + */ module.exports = function (Request, Response, Next) { const domain = Request.hostname; diff --git a/src/utils/db.js b/src/utils/db.js index 0a9d366..3fe7d6e 100644 --- a/src/utils/db.js +++ b/src/utils/db.js @@ -1,3 +1,8 @@ +/** + * Get the database driver class based on environment configuration + * @returns {Object} - Database driver module + * @throws {Error} - If DB_DRIVER is undefined or unknown + */ function getDriverClass() { const driver_name = process.env.DB_DRIVER; if (driver_name == null) { @@ -7,20 +12,27 @@ function getDriverClass() { switch (driver_name) { case 'mongodb': return require('../drivers/database/MongoDriver'); - case 'mysql' : - case 'postgres' : - case 'sqlite' : - case 'mariadb' : - case 'mssql' : - case 'db2' : - case 'snowflake' : + case 'mysql': + case 'postgres': + case 'sqlite': + case 'mariadb': + case 'mssql': + case 'db2': + case 'snowflake': case 'oracle': return require('../drivers/database/SqlDriver'); default: - throw new Error(`Unknown driver: ${driver_name}`); + throw new Error(`Unknown database driver: ${driver_name}`); } } +/** + * Resolve a tenant database connection + * @param {string} connection - Connection string + * @param {string} db_name - Database name + * @param {Object} options - Connection options + * @returns {Object} - Database connection + */ function resolveTenantConnection(connection, db_name, options = {}) { const Driver = getDriverClass(); @@ -31,28 +43,60 @@ function resolveTenantConnection(connection, db_name, options = {}) { } } +/** + * Resolve a central database connection + * @param {Object} options - Connection options + * @returns {Object} - Database connection + */ function resolveCentralConnection(options = {}) { const Driver = getDriverClass(); const connection = process.env.DB_CONNECTION || process.env.DB_HOST; const db_name = process.env.DB_NAME; + if (!connection || !db_name) { + throw new Error('Missing DB_CONNECTION/DB_HOST or DB_NAME environment variables'); + } + try { return Driver.connect(connection, db_name, options); } catch (err) { + console.error(`Failed to resolve central connection to ${db_name}:`, err); throw err; } } +/** + * Register schemas with a database connection + * @param {Object} connection - Database connection + * @param {Object|Array} schemas - Schemas to register + */ function registerSchemas(connection, schemas) { + if (!connection) { + throw new Error('Cannot register schemas - connection is null or undefined'); + } + + if (!schemas) { + throw new Error('Cannot register schemas - schemas parameter is null or undefined'); + } + const Driver = getDriverClass(); Driver.registerSchemas(connection, schemas); } +/** + * Get a model by name + * @param {string} model_name - Model name + * @returns {Object} - Model + */ function getModel(model_name) { return getDriverClass().getModel(model_name); } +/** + * Get the default tenant schema + * @returns {Object} - Default tenant schema + */ function getDefaultTenantSchema() { const Driver = getDriverClass(); return Driver.getDefaultTenantSchema(); From 562da0cbb47146f6a455dacde774a14454665b85 Mon Sep 17 00:00:00 2001 From: aymann90 Date: Tue, 29 Apr 2025 15:47:48 +0300 Subject: [PATCH 2/2] update typescript support --- .gitignore | 2 +- index.d.ts | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 index.d.ts diff --git a/.gitignore b/.gitignore index 6d0e6b0..0b21e17 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ .idea/**/usage.statistics.xml .idea/**/dictionaries .idea/**/shelf - +.idea* # AWS User-specific .idea/**/aws.xml diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..99558c8 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,74 @@ +// Type definitions for node-tenancy +// Project: https://github.com/johnabil/tenancy +// Definitions by: node-tenancy team + +import { Schema, Connection, Model } from 'mongoose'; +import { Sequelize, ModelOptions } from 'sequelize'; + +declare namespace NodeTenancy { + /** + * Configuration interface + */ + interface Config { + setConfig(config: ConfigOptions): void; + getConfig(): ConfigOptions; + } + + /** + * Configuration options + */ + interface ConfigOptions { + connection?: string; + central_domains?: string[]; + tenant_id?: string; + tenant_name?: string; + tenant_connection?: Connection | Sequelize; + central_connection?: Connection | Sequelize; + queue_connection?: string; + tenant_schemas?: Record | Array<(sequelize: Sequelize) => any>; + central_schemas?: Record | Array<(sequelize: Sequelize) => any>; + db_options?: Record; + } + + /** + * Database utility functions + */ + interface DatabaseUtils { + getDriverClass(): any; + resolveTenantConnection(connection: string, db_name: string, options?: object): Connection | Sequelize; + resolveCentralConnection(options?: object): Connection | Sequelize; + registerSchemas(connection: Connection | Sequelize, schemas: Record | Array<(sequelize: Sequelize) => any>): void; + getModel(model_name: string): Model | any; + getDefaultTenantSchema(): Schema | ((sequelize: Sequelize) => any); + } + + /** + * Queue utility functions + */ + interface QueueUtils { + getConnectionUrl(): string; + connect(url?: string, options?: object): Promise; + } + + /** + * Express middleware function + */ + type Middleware = (req: any, res: any, next: any) => void | Promise; + + /** + * Main module interface + */ + interface NodeTenancy { + config: Config; + db: DatabaseUtils; + queue: QueueUtils; + TenantSchema: Schema; + DomainSchema: (sequelize: Sequelize) => any; + initializeTenancyMiddleware: Middleware; + initializeCentralMiddleware: Middleware; + } +} + +declare const nodeTenancy: NodeTenancy.NodeTenancy; + +export = nodeTenancy; \ No newline at end of file diff --git a/package.json b/package.json index 11c9ad2..faf76ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-tenancy", - "version": "1.2.2", + "version": "1.2.1", "description": "Automatic multi-tenancy for Node with support to Rabbitmq", "main": "index.js", "homepage": "https://github.com/johnabil/tenancy#readme",