-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d4cb975
Showing
42 changed files
with
1,221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module.exports = { | ||
parser: '@typescript-eslint/parser', | ||
parserOptions: { | ||
project: 'tsconfig.json', | ||
sourceType: 'module', | ||
}, | ||
plugins: ['@typescript-eslint/eslint-plugin'], | ||
extends: [ | ||
'plugin:@typescript-eslint/eslint-recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
'prettier', | ||
'prettier/@typescript-eslint', | ||
], | ||
root: true, | ||
env: { | ||
node: true, | ||
jest: true, | ||
}, | ||
rules: { | ||
'@typescript-eslint/interface-name-prefix': 'off', | ||
'@typescript-eslint/explicit-function-return-type': 'off', | ||
'@typescript-eslint/no-explicit-any': 'off', | ||
'@typescript-eslint/no-use-before-define': 'off', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# compiled output | ||
/dist | ||
/node_modules | ||
|
||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
|
||
# OS | ||
.DS_Store | ||
|
||
# Tests | ||
/coverage | ||
/.nyc_output | ||
|
||
# IDEs and editors | ||
/.idea | ||
.project | ||
.classpath | ||
.c9/ | ||
*.launch | ||
.settings/ | ||
*.sublime-workspace | ||
|
||
# IDE - VSCode | ||
.vscode/* | ||
!.vscode/settings.json | ||
!.vscode/tasks.json | ||
!.vscode/launch.json | ||
!.vscode/extensions.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"singleQuote": true, | ||
"trailingComma": "all" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"git": { | ||
"commitMessage": "chore(): release v${version}" | ||
}, | ||
"github": { | ||
"release": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
# nestjs-tenancy | ||
|
||
## Description | ||
|
||
[Mongoose](http://mongoosejs.com/) multitenancy module for [Nest](https://github.com/nestjs/nest). | ||
|
||
## Installation | ||
|
||
```bash | ||
$ npm i --save @needle-innovision/nestjs-tenancy | ||
``` | ||
|
||
## Basic usage | ||
|
||
**app.module.ts** | ||
|
||
```typescript | ||
import { Module } from "@nestjs/common"; | ||
import { TenancyModule } from "@needle-innovision/nestjs-tenancy"; | ||
import { CatsModule } from "./cat.module.ts"; | ||
|
||
@Module({ | ||
imports: [ | ||
TenancyModule.forRoot({ | ||
tenantIdentifier: 'X-TenantId', | ||
options: {}, | ||
uri: (tenantId: string) => `mongodb://localhost/test-tenant-${tenantId}`, | ||
}), | ||
CatsModule, | ||
], | ||
}) | ||
export class AppModule {} | ||
``` | ||
|
||
Create class that describes your schema | ||
|
||
**cat.model.ts** | ||
|
||
```typescript | ||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | ||
import { Document } from 'mongoose'; | ||
|
||
@Schema() | ||
export class Cat extends Document { | ||
@Prop() | ||
name: string; | ||
|
||
@Prop() | ||
age: number; | ||
|
||
@Prop() | ||
breed: string; | ||
} | ||
|
||
export const CatSchema = SchemaFactory.createForClass(Cat); | ||
``` | ||
|
||
Inject Cat for `CatsModule` | ||
|
||
**cat.module.ts** | ||
|
||
```typescript | ||
import { Module } from '@nestjs/common'; | ||
import { TenancyModule } from '../../../lib'; | ||
import { CatsController } from './cats.controller'; | ||
import { CatsService } from './cats.service'; | ||
import { Cat, CatSchema } from './schemas/cat.schema'; | ||
|
||
@Module({ | ||
imports: [ | ||
TenancyModule.forFeature([{ name: Cat.name, schema: CatSchema }]) | ||
], | ||
controllers: [CatsController], | ||
providers: [CatsService], | ||
}) | ||
export class CatsModule { } | ||
``` | ||
|
||
Get the cat model in a service | ||
|
||
**cats.service.ts** | ||
|
||
```typescript | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectModel } from '@nestjs/mongoose'; | ||
import { Model } from 'mongoose'; | ||
import { CreateCatDto } from './dto/create-cat.dto'; | ||
import { Cat } from './schemas/cat.schema'; | ||
|
||
@Injectable() | ||
export class CatsService { | ||
constructor( | ||
@InjectModel(Cat.name) private readonly catModel: Model<Cat> | ||
) { } | ||
|
||
async create(createCatDto: CreateCatDto): Promise<Cat> { | ||
const createdCat = new this.catModel(createCatDto); | ||
return createdCat.save(); | ||
} | ||
|
||
async findAll(): Promise<Cat[]> { | ||
return this.catModel.find().exec(); | ||
} | ||
} | ||
``` | ||
|
||
Finally, use the service in a controller! | ||
|
||
**cats.controller.ts** | ||
|
||
```typescript | ||
|
||
import { Body, Controller, Get, Post } from '@nestjs/common'; | ||
import { CatsService } from './cats.service'; | ||
import { CreateCatDto } from './dto/create-cat.dto'; | ||
import { Cat } from './schemas/cat.schema'; | ||
|
||
@Controller('cats') | ||
export class CatsController { | ||
constructor(private readonly catsService: CatsService) { } | ||
|
||
@Post() | ||
async create(@Body() createCatDto: CreateCatDto) { | ||
return this.catsService.create(createCatDto); | ||
} | ||
|
||
@Get() | ||
async findAll(): Promise<Cat[]> { | ||
return this.catsService.findAll(); | ||
} | ||
} | ||
``` | ||
|
||
## Requirements | ||
|
||
1. @nest/mongoose +6.4.0 | ||
2. @nestjs/common +6.10.1 | ||
3. @nestjs/core +6.10.1 | ||
4. mongoose (with typings `@types/mongoose`) +5.7.12 | ||
|
||
## Test | ||
|
||
```bash | ||
# e2e tests | ||
$ npm run test:e2e | ||
``` | ||
|
||
## Stay in touch | ||
|
||
- Author - [Sandeep K](https://github.com/sandeepsuvit) | ||
|
||
## License | ||
|
||
Nest is [MIT licensed](LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
export * from './dist'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './dist'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './tenancy.decorator'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Inject } from '@nestjs/common'; | ||
import { getTeanantConnectionToken, getTenantModelToken } from '../utils'; | ||
|
||
/** | ||
* Get the instance of the tenant model object | ||
* | ||
* @param model any | ||
*/ | ||
export const InjectTenancyModel = (model: string) => Inject(getTenantModelToken(model)); | ||
|
||
/** | ||
* Get the instance of the tenant connection | ||
* | ||
* @param name any | ||
*/ | ||
export const InjectTenancyConnection = (name?: string) => Inject(getTeanantConnectionToken(name)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './tenancy.factory'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Provider } from '@nestjs/common'; | ||
import { Connection } from 'mongoose'; | ||
import { ModelDefinition } from '../interfaces'; | ||
import { CONNECTION_MAP, MODEL_DEFINITION_MAP, TENANT_CONNECTION } from '../tenancy.constants'; | ||
import { ConnectionMap, ModelDefinitionMap } from '../types'; | ||
import { getTenantModelDefinitionToken, getTenantModelToken } from '../utils'; | ||
|
||
export const createTeanancyProviders = (definitions: ModelDefinition[]): Provider[] => { | ||
const providers: Provider[] = []; | ||
|
||
for (const definition of definitions) { | ||
// Extract the definition data | ||
const { name, schema, collection } = definition; | ||
|
||
providers.push({ | ||
provide: getTenantModelDefinitionToken(name), | ||
useFactory: ( | ||
modelDefinitionMap: ModelDefinitionMap, | ||
connectionMap: ConnectionMap, | ||
) => { | ||
const exists = modelDefinitionMap.has(name); | ||
if (!exists) { | ||
modelDefinitionMap.set(name, { ...definition }); | ||
|
||
connectionMap.forEach((connection: Connection) => { | ||
connection.model(name, schema, collection); | ||
}); | ||
} | ||
}, | ||
inject: [ | ||
MODEL_DEFINITION_MAP, | ||
CONNECTION_MAP, | ||
], | ||
}); | ||
|
||
// Creating Models with connections attached | ||
providers.push({ | ||
provide: getTenantModelToken(name), | ||
useFactory(tenantConnection: Connection) { | ||
return tenantConnection.model(name, schema, collection); | ||
}, | ||
inject: [TENANT_CONNECTION], | ||
}); | ||
} | ||
|
||
// Return the list of providers mapping | ||
return providers; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export * from './types'; | ||
export * from './interfaces'; | ||
export * from './decorators'; | ||
export * from './utils'; | ||
export * from './factories'; | ||
export * from './tenancy.module'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './model-definition.interface'; | ||
export * from './tenancy-options.interface'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Schema } from 'mongoose'; | ||
|
||
export interface ModelDefinition { | ||
name: string; | ||
schema: Schema; | ||
collection?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { ModuleMetadata, Type } from '@nestjs/common/interfaces'; | ||
|
||
/** | ||
* Options for synchronous setup | ||
* | ||
* @export | ||
* @interface TenancyModuleOptions | ||
*/ | ||
export interface TenancyModuleOptions extends Record<string, any> { | ||
/** | ||
* If `true`, tenant id will be extracted from the subdomain | ||
*/ | ||
isTenantFromSubdomain?: boolean; | ||
|
||
/** | ||
* Tenant id will be extracted using the keyword from the request header | ||
*/ | ||
tenantIdentifier?: string; | ||
|
||
/** | ||
* URI for the tenant database | ||
*/ | ||
uri: (uri: string) => string; | ||
|
||
/** | ||
* Options for the database | ||
*/ | ||
options?: any; | ||
|
||
/** | ||
* Whitelist following subdomains | ||
*/ | ||
whitelist?: any; | ||
} | ||
|
||
/** | ||
* For creating options dynamically | ||
* | ||
* To use this the class implementing `TenancyOptionsFactory` should | ||
* implement the method `createTenancyOptions` under it. | ||
* | ||
* @export | ||
* @interface TenancyOptionsFactory | ||
*/ | ||
export interface TenancyOptionsFactory { | ||
createTenancyOptions():Promise<TenancyModuleOptions> | TenancyModuleOptions; | ||
} | ||
|
||
/** | ||
* Options for asynchronous setup | ||
* | ||
* @export | ||
* @interface TenancyModuleAsyncOptions | ||
*/ | ||
export interface TenancyModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> { | ||
useExisting?: Type<TenancyOptionsFactory>; | ||
useClass?: Type<TenancyOptionsFactory>; | ||
useFactory?: (...args: any[]) => Promise<TenancyModuleOptions> | TenancyModuleOptions; | ||
inject?: any[]; | ||
} |
Oops, something went wrong.