@campxdev/server-shared 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/.prettierrc +0 -5
- package/.vscode/settings.json +0 -13
- package/src/common/config/mongo.config.ts +0 -13
- package/src/common/decorators/message-pattern.decorator.ts +0 -14
- package/src/common/decorators/request.decorators.ts +0 -32
- package/src/common/decorators/time-validation.decorator.ts +0 -22
- package/src/common/filters/unhandled-exception.filter.ts +0 -29
- package/src/common/guards/guard.ts +0 -19
- package/src/common/index.ts +0 -9
- package/src/common/interfaces/context.interface.ts +0 -68
- package/src/common/store/request-store.ts +0 -96
- package/src/common/store/store-config.ts +0 -25
- package/src/domain/db-connection.module.ts +0 -20
- package/src/domain/index.ts +0 -2
- package/src/domain/schemas/tenant.schema.ts +0 -112
- package/src/index.ts +0 -5
- package/src/permissions/index.ts +0 -1
- package/src/permissions/permissions.ts +0 -1943
- package/src/shared-module/index.ts +0 -2
- package/src/shared-module/shared.module.ts +0 -32
- package/src/shared-module/shared.service.ts +0 -101
- package/src/utils/constants.ts +0 -11
- package/src/utils/index.ts +0 -2
- package/src/utils/utils.ts +0 -191
- package/tsconfig.json +0 -19
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { getConnectionToken, MongooseModule } from '@nestjs/mongoose';
|
|
3
|
-
import { Connection } from 'mongoose';
|
|
4
|
-
import { DataSource } from 'typeorm';
|
|
5
|
-
import { MessagePatterProps } from '../common';
|
|
6
|
-
import { Tenant, TenantSchema, DBConnectionModule } from '../domain';
|
|
7
|
-
import { IDataBaseConfig, SharedService } from './shared.service';
|
|
8
|
-
|
|
9
|
-
export interface ISharedModuleOptions {
|
|
10
|
-
service: string;
|
|
11
|
-
dataBaseConfig?: IDataBaseConfig;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class SharedModule {
|
|
15
|
-
static forRoot(config: ISharedModuleOptions): DynamicModule {
|
|
16
|
-
MessagePatterProps.service = config.service;
|
|
17
|
-
return {
|
|
18
|
-
module: SharedModule,
|
|
19
|
-
imports: [MongooseModule.forFeature([{ name: Tenant.name, schema: TenantSchema }])],
|
|
20
|
-
providers: [
|
|
21
|
-
{
|
|
22
|
-
provide: SharedModule,
|
|
23
|
-
useFactory: (dbConnections: Map<string, DataSource>, connection: Connection) => {
|
|
24
|
-
return new SharedService(config.dataBaseConfig, dbConnections, connection);
|
|
25
|
-
},
|
|
26
|
-
inject: [DBConnectionModule, getConnectionToken()],
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
exports: [SharedService, MongooseModule],
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { Injectable, UnprocessableEntityException } from '@nestjs/common';
|
|
2
|
-
import { Connection, Model } from 'mongoose';
|
|
3
|
-
import { DataSource } from 'typeorm';
|
|
4
|
-
import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
|
|
5
|
-
import { IRequest, TenantDetails } from '../common/interfaces/context.interface';
|
|
6
|
-
import { Tenant } from '../domain';
|
|
7
|
-
import { TenantCollectionName, TenantSchema } from '../domain/schemas/tenant.schema';
|
|
8
|
-
|
|
9
|
-
export interface IDataBaseConfig {
|
|
10
|
-
entities?: any[];
|
|
11
|
-
migrations?: any[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@Injectable()
|
|
15
|
-
export class SharedService {
|
|
16
|
-
private readonly tenantModel: Model<Tenant>;
|
|
17
|
-
|
|
18
|
-
constructor(
|
|
19
|
-
private readonly dataBaseConfig: IDataBaseConfig,
|
|
20
|
-
private readonly dbConnections: Map<string, DataSource>,
|
|
21
|
-
private readonly connection: Connection,
|
|
22
|
-
) {
|
|
23
|
-
this.tenantModel = this.connection.model<Tenant>(TenantCollectionName, TenantSchema);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
createTenantDetails(tenant: Tenant): TenantDetails {
|
|
27
|
-
return {
|
|
28
|
-
...tenant.toObject(),
|
|
29
|
-
id: tenant.id,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async createTenantDetailsFromId(id: string) {
|
|
34
|
-
const tenant = await this.tenantModel.findById(id);
|
|
35
|
-
if (!tenant) {
|
|
36
|
-
throw new UnprocessableEntityException('Tenant not found with this details');
|
|
37
|
-
}
|
|
38
|
-
return this.createTenantDetails(tenant);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async getTenantRootConnection(tenantId: string) {
|
|
42
|
-
if (!tenantId) return;
|
|
43
|
-
|
|
44
|
-
const tenant = await this.tenantModel.findById(tenantId).exec();
|
|
45
|
-
if (!tenant) {
|
|
46
|
-
throw new UnprocessableEntityException('Tenant not found');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (this.dbConnections.has(tenant.id)) {
|
|
50
|
-
return this.dbConnections.get(tenant.id);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const dataSource = new DataSource({
|
|
54
|
-
type: 'mysql',
|
|
55
|
-
host: tenant.host,
|
|
56
|
-
port: tenant.port,
|
|
57
|
-
username: tenant.username,
|
|
58
|
-
password: tenant.password,
|
|
59
|
-
database: tenant.database,
|
|
60
|
-
namingStrategy: new SnakeNamingStrategy(),
|
|
61
|
-
synchronize: false,
|
|
62
|
-
logging: true,
|
|
63
|
-
entities: [
|
|
64
|
-
__dirname + '../domain/entities/*.entity{.ts,.js}',
|
|
65
|
-
...(this.dataBaseConfig.entities || []),
|
|
66
|
-
],
|
|
67
|
-
migrations: [...(this.dataBaseConfig.migrations || [])],
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
let res = await dataSource.initialize().catch((err) => {
|
|
71
|
-
console.log(err);
|
|
72
|
-
throw new UnprocessableEntityException('Unable to connect to database');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (!this.dbConnections.has(tenant.id)) {
|
|
76
|
-
this.dbConnections.set(tenant.id, res);
|
|
77
|
-
await res.runMigrations();
|
|
78
|
-
} else {
|
|
79
|
-
await res.destroy();
|
|
80
|
-
res = this.dbConnections.get(tenant.id);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return res;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async getTenantConnection(tenant: TenantDetails) {
|
|
87
|
-
const rootDataSource = await this.getTenantRootConnection(tenant.id);
|
|
88
|
-
return {
|
|
89
|
-
rootDataSource,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async getConnection(req: IRequest) {
|
|
94
|
-
if (req.cmd?.cmd === 'app' && req.cmd?.action === 'root') return {};
|
|
95
|
-
|
|
96
|
-
const connection = await this.getTenantConnection(req.tenantDetails);
|
|
97
|
-
return {
|
|
98
|
-
rootDataSource: connection.rootDataSource,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
package/src/utils/constants.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const userType = {
|
|
2
|
-
staff_user: 'staff_user',
|
|
3
|
-
student_user: 'student',
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export const TENANT_HEADER = 'x-tenant-id';
|
|
7
|
-
export const PAYMENTS_SERVICE = 'PAYMENTS_SERVICE';
|
|
8
|
-
export const EXAMS_SERVICE = 'EXAMS_SERVICE';
|
|
9
|
-
export const SQUARE_SERVICE = 'SQUARE_SERVICE';
|
|
10
|
-
export const HRMS_SERVICE = 'HRMS_SERVICE';
|
|
11
|
-
export const NOTIFICATION_SERVICE = 'NOTIFICATION_SERVICE';
|
package/src/utils/index.ts
DELETED
package/src/utils/utils.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { BadRequestException, UnprocessableEntityException } from '@nestjs/common';
|
|
2
|
-
import Joi from 'joi';
|
|
3
|
-
import { camelCase, uniq } from 'lodash';
|
|
4
|
-
import moment from 'moment';
|
|
5
|
-
import * as mongoose from 'mongoose';
|
|
6
|
-
import * as XLSX from 'xlsx';
|
|
7
|
-
|
|
8
|
-
export function getReceiptNo(letter: string): string {
|
|
9
|
-
const year = `${new Date().getFullYear()}`.slice(2);
|
|
10
|
-
const receiptNo = year + letter;
|
|
11
|
-
return receiptNo;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function xlsxToJson<T>(
|
|
15
|
-
file: Express.Multer.File,
|
|
16
|
-
schema?: Joi.ArraySchema<any[]>,
|
|
17
|
-
): Promise<T[]> {
|
|
18
|
-
if (!file) throw new UnprocessableEntityException('File not found');
|
|
19
|
-
const workbook = XLSX.read(Buffer.from(file.buffer));
|
|
20
|
-
const sheet_name_list = workbook.SheetNames;
|
|
21
|
-
let xlData = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
|
|
22
|
-
if (schema) {
|
|
23
|
-
try {
|
|
24
|
-
xlData = await schema.validateAsync(xlData);
|
|
25
|
-
} catch (err: any) {
|
|
26
|
-
console.log(err);
|
|
27
|
-
throw new UnprocessableEntityException(err.message);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return xlData as T[];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function joiDefault(val: any) {
|
|
34
|
-
return Joi.string()
|
|
35
|
-
.custom(() => val)
|
|
36
|
-
.default(val);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function validateBatches(batches: string[]) {
|
|
40
|
-
const invalidBatches = batches.filter((e) => {
|
|
41
|
-
const batch = e.split(' - ');
|
|
42
|
-
return batch.length !== 2 || isNaN(+batch[0]) || isNaN(+batch[1]);
|
|
43
|
-
});
|
|
44
|
-
if (invalidBatches.length) {
|
|
45
|
-
throw new BadRequestException(`Invalid batches: ${uniq(invalidBatches).join(', ')}`);
|
|
46
|
-
}
|
|
47
|
-
return uniq(batches);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function getBool(str: string, defaultValue: boolean) {
|
|
51
|
-
if (!str) return defaultValue;
|
|
52
|
-
return str.toLowerCase() == 'yes' ? true : false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function getGenderWithDefault(str: string, defaultValue: string) {
|
|
56
|
-
const value = !str ? defaultValue : str;
|
|
57
|
-
return getGender(value);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function getGender(str: string) {
|
|
61
|
-
switch (str.toUpperCase()) {
|
|
62
|
-
case 'M':
|
|
63
|
-
case 'MALE':
|
|
64
|
-
return 'male';
|
|
65
|
-
case 'F':
|
|
66
|
-
case 'FEMALE':
|
|
67
|
-
return 'female';
|
|
68
|
-
default:
|
|
69
|
-
return 'other';
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function getValue(val: any, defaultValue: any) {
|
|
74
|
-
if (!val) return defaultValue;
|
|
75
|
-
return `${val}`.trim();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function getDate(date: any, defaultValue: any) {
|
|
79
|
-
if (!date) return defaultValue;
|
|
80
|
-
return moment(new Date(date)).format('YYYY-MM-DD');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function romanize(num) {
|
|
84
|
-
if (!+num) return false;
|
|
85
|
-
const digits = String(+num).split('');
|
|
86
|
-
const key = [
|
|
87
|
-
'',
|
|
88
|
-
'C',
|
|
89
|
-
'CC',
|
|
90
|
-
'CCC',
|
|
91
|
-
'CD',
|
|
92
|
-
'D',
|
|
93
|
-
'DC',
|
|
94
|
-
'DCC',
|
|
95
|
-
'DCCC',
|
|
96
|
-
'CM',
|
|
97
|
-
'',
|
|
98
|
-
'X',
|
|
99
|
-
'XX',
|
|
100
|
-
'XXX',
|
|
101
|
-
'XL',
|
|
102
|
-
'L',
|
|
103
|
-
'LX',
|
|
104
|
-
'LXX',
|
|
105
|
-
'LXXX',
|
|
106
|
-
'XC',
|
|
107
|
-
'',
|
|
108
|
-
'I',
|
|
109
|
-
'II',
|
|
110
|
-
'III',
|
|
111
|
-
'IV',
|
|
112
|
-
'V',
|
|
113
|
-
'VI',
|
|
114
|
-
'VII',
|
|
115
|
-
'VIII',
|
|
116
|
-
'IX',
|
|
117
|
-
];
|
|
118
|
-
let roman = '',
|
|
119
|
-
i = 3;
|
|
120
|
-
while (i--) roman = (key[+digits.pop() + i * 10] || '') + roman;
|
|
121
|
-
return Array(+digits.join('') + 1).join('M') + roman;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function ordinalSuffixOf(i: number) {
|
|
125
|
-
const j = i % 10,
|
|
126
|
-
k = i % 100;
|
|
127
|
-
if (j == 1 && k != 11) {
|
|
128
|
-
return i + 'st';
|
|
129
|
-
}
|
|
130
|
-
if (j == 2 && k != 12) {
|
|
131
|
-
return i + 'nd';
|
|
132
|
-
}
|
|
133
|
-
if (j == 3 && k != 13) {
|
|
134
|
-
return i + 'rd';
|
|
135
|
-
}
|
|
136
|
-
return i + 'th';
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function getYearFromSem(sem: number) {
|
|
140
|
-
return Math.ceil(sem / 2);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function convertKeysToCamelCase(obj: any) {
|
|
144
|
-
const newObj: any = {};
|
|
145
|
-
for (const key in obj) {
|
|
146
|
-
newObj[camelCase(key)] = obj[key];
|
|
147
|
-
}
|
|
148
|
-
return newObj;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export const removeSpecialChars = (str: string) => str?.replace(/[^\w\s]/gi, '');
|
|
152
|
-
|
|
153
|
-
export function getObjectId(id: any) {
|
|
154
|
-
if (id instanceof mongoose.Types.ObjectId) {
|
|
155
|
-
return id;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
try {
|
|
159
|
-
return new mongoose.Types.ObjectId(id);
|
|
160
|
-
} catch (e) {
|
|
161
|
-
throw new UnprocessableEntityException('Invalid ID');
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function getTitle(val: string) {
|
|
166
|
-
return val
|
|
167
|
-
.toLowerCase()
|
|
168
|
-
.split('_')
|
|
169
|
-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
170
|
-
.join(' ');
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function generateObjectId() {
|
|
174
|
-
return new mongoose.Types.ObjectId();
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export function getTime(date: any) {
|
|
178
|
-
return new Date(date).getTime();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function getMonth(date: any) {
|
|
182
|
-
return new Date(date).getMonth();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export function timeLessThan(time1: string, time2: string) {
|
|
186
|
-
const [h1, m1, s1] = time1.split(':').map((e) => +e);
|
|
187
|
-
const [h2, m2, s2] = time2.split(':').map((e) => +e);
|
|
188
|
-
if (h1 !== h2) return h1 < h2;
|
|
189
|
-
if (m1 !== m2) return m1 < m2;
|
|
190
|
-
return s1 < s2;
|
|
191
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"experimentalDecorators": true,
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"module": "commonjs",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"declarationMap": true,
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"outDir": "./dist",
|
|
10
|
-
"rootDir": "./src",
|
|
11
|
-
"strict": true,
|
|
12
|
-
"noImplicitAny": false,
|
|
13
|
-
"strictNullChecks": false,
|
|
14
|
-
"allowSyntheticDefaultImports": true,
|
|
15
|
-
"esModuleInterop": true,
|
|
16
|
-
"emitDecoratorMetadata": true
|
|
17
|
-
},
|
|
18
|
-
"exclude": ["node_modules", "dist"]
|
|
19
|
-
}
|