@flusys/nestjs-shared 5.1.1 → 5.1.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/cjs/classes/api-controller.class.js +16 -10
- package/cjs/classes/api-service.class.js +67 -35
- package/cjs/classes/index.js +0 -1
- package/cjs/dtos/identity-response.dto.js +4 -8
- package/cjs/entities/identity.js +8 -2
- package/cjs/modules/datasource/index.js +0 -1
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +24 -85
- package/classes/api-controller.class.d.ts +1 -0
- package/classes/api-service.class.d.ts +13 -6
- package/classes/index.d.ts +0 -1
- package/decorators/current-user.decorator.d.ts +1 -1
- package/fesm/classes/api-controller.class.js +16 -10
- package/fesm/classes/api-service.class.js +70 -38
- package/fesm/classes/index.js +0 -1
- package/fesm/dtos/identity-response.dto.js +4 -8
- package/fesm/entities/identity.js +8 -2
- package/fesm/interfaces/datasource.interface.js +1 -20
- package/fesm/modules/datasource/index.js +0 -1
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +24 -85
- package/guards/permission.guard.d.ts +1 -1
- package/interceptors/idempotency.interceptor.d.ts +1 -1
- package/interfaces/notification-adapter.interface.d.ts +13 -14
- package/modules/datasource/index.d.ts +0 -1
- package/modules/datasource/multi-tenant-datasource.service.d.ts +4 -13
- package/package.json +15 -15
- package/cjs/classes/request-scoped-api.service.js +0 -61
- package/cjs/modules/datasource/datasource.module.js +0 -117
- package/classes/request-scoped-api.service.d.ts +0 -14
- package/fesm/classes/request-scoped-api.service.js +0 -51
- package/fesm/modules/datasource/datasource.module.js +0 -107
- package/modules/datasource/datasource.module.d.ts +0 -19
|
@@ -33,21 +33,21 @@ import { Request } from 'express';
|
|
|
33
33
|
import { DataSource } from 'typeorm';
|
|
34
34
|
import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
|
|
35
35
|
export class MultiTenantDataSourceService {
|
|
36
|
+
get self() {
|
|
37
|
+
return this.constructor;
|
|
38
|
+
}
|
|
36
39
|
initializeFromOptions() {
|
|
37
40
|
if (!this.options) return;
|
|
38
|
-
if (!
|
|
41
|
+
if (!this.self.initialized) {
|
|
39
42
|
this.registerTenants();
|
|
40
|
-
|
|
43
|
+
this.self.initialized = true;
|
|
41
44
|
}
|
|
42
45
|
}
|
|
43
46
|
registerTenants() {
|
|
44
47
|
this.options?.tenants?.forEach((tenant)=>{
|
|
45
|
-
|
|
48
|
+
this.self.tenantsRegistry.set(tenant.id, tenant);
|
|
46
49
|
});
|
|
47
50
|
}
|
|
48
|
-
setTenantHeader(header) {
|
|
49
|
-
this.tenantHeader = header;
|
|
50
|
-
}
|
|
51
51
|
getDatabaseMode() {
|
|
52
52
|
return this.options?.bootstrapAppConfig?.databaseMode ?? 'single';
|
|
53
53
|
}
|
|
@@ -71,91 +71,33 @@ export class MultiTenantDataSourceService {
|
|
|
71
71
|
return tenantId ? this.getTenant(tenantId) : null;
|
|
72
72
|
}
|
|
73
73
|
getTenant(tenantId) {
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
getAllTenants() {
|
|
77
|
-
return Array.from(MultiTenantDataSourceService.tenantsRegistry.values());
|
|
78
|
-
}
|
|
79
|
-
getActiveTenants() {
|
|
80
|
-
return this.getAllTenants();
|
|
74
|
+
return this.self.tenantsRegistry.get(tenantId) ?? null;
|
|
81
75
|
}
|
|
82
76
|
async getDataSource() {
|
|
83
77
|
return this.isMultiTenant() ? this.getTenantDataSource() : this.getSingleDataSource();
|
|
84
78
|
}
|
|
85
|
-
async getDataSourceForTenant(tenantId) {
|
|
86
|
-
const tenant = this.getTenant(tenantId);
|
|
87
|
-
if (!tenant) {
|
|
88
|
-
throw new BadRequestException({
|
|
89
|
-
message: `Tenant '${tenantId}' not found`,
|
|
90
|
-
messageKey: SYSTEM_MESSAGES.TENANT_NOT_FOUND,
|
|
91
|
-
messageVariables: {
|
|
92
|
-
tenantId
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return this.getOrCreateTenantConnection(tenant);
|
|
97
|
-
}
|
|
98
|
-
setDataSource(dataSource) {
|
|
99
|
-
MultiTenantDataSourceService.singleDataSource = dataSource;
|
|
100
|
-
}
|
|
101
79
|
async getRepository(entity) {
|
|
102
80
|
const dataSource = await this.getDataSource();
|
|
103
81
|
return dataSource.getRepository(entity);
|
|
104
82
|
}
|
|
105
|
-
async withTenant(tenantId, callback) {
|
|
106
|
-
const dataSource = await this.getDataSourceForTenant(tenantId);
|
|
107
|
-
return callback(dataSource);
|
|
108
|
-
}
|
|
109
|
-
async forAllTenants(callback) {
|
|
110
|
-
const results = new Map();
|
|
111
|
-
for (const tenant of this.getActiveTenants()){
|
|
112
|
-
try {
|
|
113
|
-
const dataSource = await this.getOrCreateTenantConnection(tenant);
|
|
114
|
-
results.set(tenant.id, await callback(tenant, dataSource));
|
|
115
|
-
} catch {
|
|
116
|
-
// Silent failure for individual tenant
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return results;
|
|
120
|
-
}
|
|
121
|
-
registerTenant(tenant) {
|
|
122
|
-
MultiTenantDataSourceService.tenantsRegistry.set(tenant.id, tenant);
|
|
123
|
-
}
|
|
124
|
-
async removeTenant(tenantId) {
|
|
125
|
-
await this.closeTenantConnection(tenantId);
|
|
126
|
-
MultiTenantDataSourceService.tenantsRegistry.delete(tenantId);
|
|
127
|
-
}
|
|
128
83
|
async closeTenantConnection(tenantId) {
|
|
129
|
-
const connection =
|
|
84
|
+
const connection = this.self.tenantConnections.get(tenantId);
|
|
130
85
|
if (connection?.isInitialized) {
|
|
131
86
|
await connection.destroy();
|
|
132
|
-
|
|
87
|
+
this.self.tenantConnections.delete(tenantId);
|
|
133
88
|
}
|
|
134
89
|
}
|
|
135
90
|
async onModuleDestroy() {
|
|
136
|
-
for (const [tenantId] of
|
|
91
|
+
for (const [tenantId] of this.self.tenantConnections){
|
|
137
92
|
await this.closeTenantConnection(tenantId);
|
|
138
93
|
}
|
|
139
94
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
MultiTenantDataSourceService.singleConnectionLock = null;
|
|
144
|
-
MultiTenantDataSourceService.tenantConnections.clear();
|
|
145
|
-
MultiTenantDataSourceService.tenantsRegistry.clear();
|
|
146
|
-
MultiTenantDataSourceService.connectionLocks.clear();
|
|
147
|
-
}
|
|
148
|
-
// Protected Methods (for subclasses)
|
|
149
|
-
/**
|
|
150
|
-
* Get single database DataSource with connection locking to prevent race conditions
|
|
151
|
-
*/ async getSingleDataSource() {
|
|
152
|
-
// Return existing initialized connection
|
|
153
|
-
if (MultiTenantDataSourceService.singleDataSource?.isInitialized) {
|
|
154
|
-
return MultiTenantDataSourceService.singleDataSource;
|
|
95
|
+
async getSingleDataSource() {
|
|
96
|
+
if (this.self.singleDataSource?.isInitialized) {
|
|
97
|
+
return this.self.singleDataSource;
|
|
155
98
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return MultiTenantDataSourceService.singleConnectionLock;
|
|
99
|
+
if (this.self.singleConnectionLock) {
|
|
100
|
+
return this.self.singleConnectionLock;
|
|
159
101
|
}
|
|
160
102
|
const config = this.getDefaultDatabaseConfig();
|
|
161
103
|
if (!config) {
|
|
@@ -164,20 +106,17 @@ export class MultiTenantDataSourceService {
|
|
|
164
106
|
messageKey: SYSTEM_MESSAGES.DATABASE_CONFIG_NOT_AVAILABLE
|
|
165
107
|
});
|
|
166
108
|
}
|
|
167
|
-
// Create connection with lock to prevent race conditions
|
|
168
109
|
const connectionPromise = this.createDataSourceFromConfig(config);
|
|
169
|
-
|
|
110
|
+
this.self.singleConnectionLock = connectionPromise;
|
|
170
111
|
try {
|
|
171
112
|
const dataSource = await connectionPromise;
|
|
172
|
-
|
|
113
|
+
this.self.singleDataSource = dataSource;
|
|
173
114
|
return dataSource;
|
|
174
115
|
} finally{
|
|
175
|
-
|
|
116
|
+
this.self.singleConnectionLock = null;
|
|
176
117
|
}
|
|
177
118
|
}
|
|
178
|
-
|
|
179
|
-
* Get tenant-specific DataSource
|
|
180
|
-
*/ async getTenantDataSource() {
|
|
119
|
+
async getTenantDataSource() {
|
|
181
120
|
const tenant = this.getCurrentTenant();
|
|
182
121
|
if (!tenant) {
|
|
183
122
|
throw new BadRequestException({
|
|
@@ -191,19 +130,19 @@ export class MultiTenantDataSourceService {
|
|
|
191
130
|
return this.getOrCreateTenantConnection(tenant);
|
|
192
131
|
}
|
|
193
132
|
async getOrCreateTenantConnection(tenant) {
|
|
194
|
-
const existing =
|
|
133
|
+
const existing = this.self.tenantConnections.get(tenant.id);
|
|
195
134
|
if (existing?.isInitialized) return existing;
|
|
196
|
-
const pendingConnection =
|
|
135
|
+
const pendingConnection = this.self.connectionLocks.get(tenant.id);
|
|
197
136
|
if (pendingConnection) return pendingConnection;
|
|
198
137
|
const config = this.buildTenantDatabaseConfig(tenant);
|
|
199
138
|
const connectionPromise = this.createDataSourceFromConfig(config);
|
|
200
|
-
|
|
139
|
+
this.self.connectionLocks.set(tenant.id, connectionPromise);
|
|
201
140
|
try {
|
|
202
141
|
const dataSource = await connectionPromise;
|
|
203
|
-
|
|
142
|
+
this.self.tenantConnections.set(tenant.id, dataSource);
|
|
204
143
|
return dataSource;
|
|
205
144
|
} finally{
|
|
206
|
-
|
|
145
|
+
this.self.connectionLocks.delete(tenant.id);
|
|
207
146
|
}
|
|
208
147
|
}
|
|
209
148
|
getDefaultDatabaseConfig() {
|
|
@@ -6,7 +6,7 @@ export declare class PermissionGuard implements CanActivate {
|
|
|
6
6
|
private readonly reflector;
|
|
7
7
|
private readonly cache?;
|
|
8
8
|
private readonly config;
|
|
9
|
-
constructor(reflector: Reflector, cache?: HybridCache, config?: PermissionGuardConfig);
|
|
9
|
+
constructor(reflector: Reflector, cache?: HybridCache | undefined, config?: PermissionGuardConfig);
|
|
10
10
|
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
11
11
|
private normalizeToLogicNode;
|
|
12
12
|
private evaluateLogicNode;
|
|
@@ -5,6 +5,6 @@ export declare class IdempotencyInterceptor implements NestInterceptor {
|
|
|
5
5
|
private readonly cache?;
|
|
6
6
|
private readonly CACHE_TTL;
|
|
7
7
|
private readonly PROCESSING_MARKER;
|
|
8
|
-
constructor(cache?: HybridCache);
|
|
8
|
+
constructor(cache?: HybridCache | undefined);
|
|
9
9
|
intercept<T = any>(context: ExecutionContext, next: CallHandler<T>): Promise<Observable<T>>;
|
|
10
10
|
}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { NotificationType } from '../enums/notification-type.enum';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
sendToMany(options: NotificationBulkSendOptions): Promise<void>;
|
|
5
|
-
broadcastToCompany?(companyId: string, title: string, message?: string, type?: NotificationType, data?: Record<string, unknown>): Promise<void>;
|
|
6
|
-
isUserOnline?(userId: string): boolean;
|
|
7
|
-
}
|
|
8
|
-
interface NotificationBaseOptions {
|
|
2
|
+
export declare const NOTIFICATION_ADAPTER = "NOTIFICATION_ADAPTER";
|
|
3
|
+
export interface INotificationContent {
|
|
9
4
|
title: string;
|
|
10
|
-
message?: string;
|
|
5
|
+
message?: string | null;
|
|
11
6
|
type?: NotificationType;
|
|
12
|
-
data?: Record<string, unknown
|
|
13
|
-
companyId?: string;
|
|
7
|
+
data?: Record<string, unknown> | null;
|
|
8
|
+
companyId?: string | null;
|
|
9
|
+
realtime?: boolean;
|
|
14
10
|
}
|
|
15
|
-
export interface
|
|
11
|
+
export interface INotificationSendOptions extends INotificationContent {
|
|
16
12
|
userId: string;
|
|
17
13
|
}
|
|
18
|
-
export interface
|
|
14
|
+
export interface INotificationBulkSendOptions extends INotificationContent {
|
|
19
15
|
userIds: string[];
|
|
20
16
|
}
|
|
21
|
-
export
|
|
22
|
-
|
|
17
|
+
export interface INotificationAdapter {
|
|
18
|
+
send(options: INotificationSendOptions): Promise<void>;
|
|
19
|
+
sendToMany(options: INotificationBulkSendOptions): Promise<void>;
|
|
20
|
+
isUserOnline?(userId: string): boolean;
|
|
21
|
+
}
|
|
@@ -3,8 +3,8 @@ import { OnModuleDestroy } from '@nestjs/common';
|
|
|
3
3
|
import { Request } from 'express';
|
|
4
4
|
import { DataSource, EntityTarget, ObjectLiteral, Repository } from 'typeorm';
|
|
5
5
|
export declare class MultiTenantDataSourceService implements OnModuleDestroy {
|
|
6
|
-
protected readonly options?: IDataSourceServiceOptions;
|
|
7
|
-
protected readonly request?: Request;
|
|
6
|
+
protected readonly options?: IDataSourceServiceOptions | undefined;
|
|
7
|
+
protected readonly request?: Request | undefined;
|
|
8
8
|
protected static readonly tenantConnections: Map<string, DataSource>;
|
|
9
9
|
protected static singleDataSource: DataSource | null;
|
|
10
10
|
protected static readonly tenantsRegistry: Map<string, ITenantDatabaseConfig>;
|
|
@@ -12,28 +12,19 @@ export declare class MultiTenantDataSourceService implements OnModuleDestroy {
|
|
|
12
12
|
protected static readonly connectionLocks: Map<string, Promise<DataSource>>;
|
|
13
13
|
protected static singleConnectionLock: Promise<DataSource> | null;
|
|
14
14
|
protected tenantHeader: string;
|
|
15
|
-
constructor(options?: IDataSourceServiceOptions, request?: Request);
|
|
15
|
+
constructor(options?: IDataSourceServiceOptions | undefined, request?: Request | undefined);
|
|
16
|
+
private get self();
|
|
16
17
|
private initializeFromOptions;
|
|
17
18
|
private registerTenants;
|
|
18
|
-
setTenantHeader(header: string): void;
|
|
19
19
|
getDatabaseMode(): DatabaseMode;
|
|
20
20
|
isMultiTenant(): boolean;
|
|
21
21
|
getCurrentTenantId(): string | null;
|
|
22
22
|
getCurrentTenant(): ITenantDatabaseConfig | null;
|
|
23
23
|
getTenant(tenantId: string): ITenantDatabaseConfig | null;
|
|
24
|
-
getAllTenants(): ITenantDatabaseConfig[];
|
|
25
|
-
getActiveTenants(): ITenantDatabaseConfig[];
|
|
26
24
|
getDataSource(): Promise<DataSource>;
|
|
27
|
-
getDataSourceForTenant(tenantId: string): Promise<DataSource>;
|
|
28
|
-
setDataSource(dataSource: DataSource): void;
|
|
29
25
|
getRepository<T extends ObjectLiteral>(entity: EntityTarget<T>): Promise<Repository<T>>;
|
|
30
|
-
withTenant<T>(tenantId: string, callback: (ds: DataSource) => Promise<T>): Promise<T>;
|
|
31
|
-
forAllTenants<T>(callback: (tenant: ITenantDatabaseConfig, ds: DataSource) => Promise<T>): Promise<Map<string, T>>;
|
|
32
|
-
registerTenant(tenant: ITenantDatabaseConfig): void;
|
|
33
|
-
removeTenant(tenantId: string): Promise<void>;
|
|
34
26
|
closeTenantConnection(tenantId: string): Promise<void>;
|
|
35
27
|
onModuleDestroy(): Promise<void>;
|
|
36
|
-
static reset(): void;
|
|
37
28
|
protected getSingleDataSource(): Promise<DataSource>;
|
|
38
29
|
protected getTenantDataSource(): Promise<DataSource>;
|
|
39
30
|
protected getOrCreateTenantConnection(tenant: ITenantDatabaseConfig): Promise<DataSource>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-shared",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.3",
|
|
4
4
|
"description": "Common shared utilities for Flusys NestJS applications",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "fesm/index.js",
|
|
@@ -93,25 +93,25 @@
|
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
95
|
"peerDependencies": {
|
|
96
|
-
"@keyv/redis": "^5.0
|
|
97
|
-
"@nestjs/common": "^
|
|
98
|
-
"@nestjs/config": "^
|
|
99
|
-
"@nestjs/core": "^
|
|
100
|
-
"@nestjs/jwt": "^
|
|
101
|
-
"@nestjs/passport": "^
|
|
102
|
-
"@nestjs/swagger": "^
|
|
103
|
-
"@nestjs/typeorm": "^
|
|
104
|
-
"cacheable": "^2.
|
|
105
|
-
"class-transformer": "^0.5.
|
|
106
|
-
"class-validator": "^0.14.0",
|
|
107
|
-
"keyv": "^5.0.
|
|
96
|
+
"@keyv/redis": "^5.1.0",
|
|
97
|
+
"@nestjs/common": "^11.0.0",
|
|
98
|
+
"@nestjs/config": "^4.0.0",
|
|
99
|
+
"@nestjs/core": "^11.0.0",
|
|
100
|
+
"@nestjs/jwt": "^11.0.0",
|
|
101
|
+
"@nestjs/passport": "^11.0.0",
|
|
102
|
+
"@nestjs/swagger": "^11.0.0",
|
|
103
|
+
"@nestjs/typeorm": "^11.0.0",
|
|
104
|
+
"cacheable": "^2.1.0",
|
|
105
|
+
"class-transformer": "^0.5.1",
|
|
106
|
+
"class-validator": "^0.14.0 || ^0.15.0",
|
|
107
|
+
"keyv": "^5.0.0",
|
|
108
108
|
"typeorm": "^0.3.0",
|
|
109
109
|
"winston": "^3.0.0",
|
|
110
110
|
"winston-daily-rotate-file": "^5.0.0",
|
|
111
|
-
"express": "^4.18.0",
|
|
111
|
+
"express": "^4.18.0 || ^5.0.0",
|
|
112
112
|
"rxjs": "^7.8.0"
|
|
113
113
|
},
|
|
114
114
|
"dependencies": {
|
|
115
|
-
"@flusys/nestjs-core": "5.1.
|
|
115
|
+
"@flusys/nestjs-core": "5.1.3"
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "RequestScopedApiService", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return RequestScopedApiService;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _common = require("@nestjs/common");
|
|
12
|
-
const _apiserviceclass = require("./api-service.class");
|
|
13
|
-
function _define_property(obj, key, value) {
|
|
14
|
-
if (key in obj) {
|
|
15
|
-
Object.defineProperty(obj, key, {
|
|
16
|
-
value: value,
|
|
17
|
-
enumerable: true,
|
|
18
|
-
configurable: true,
|
|
19
|
-
writable: true
|
|
20
|
-
});
|
|
21
|
-
} else {
|
|
22
|
-
obj[key] = value;
|
|
23
|
-
}
|
|
24
|
-
return obj;
|
|
25
|
-
}
|
|
26
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
27
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
28
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
29
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
30
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
31
|
-
}
|
|
32
|
-
let RequestScopedApiService = class RequestScopedApiService extends _apiserviceclass.ApiService {
|
|
33
|
-
async ensureRepositoryInitialized() {
|
|
34
|
-
if (!this.repositoryInitialized) {
|
|
35
|
-
const entity = this.resolveEntity();
|
|
36
|
-
const provider = this.getDataSourceProvider();
|
|
37
|
-
this.repository = await provider.getRepository(entity);
|
|
38
|
-
this.repositoryInitialized = true;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/** Initialize additional repositories beyond the primary entity */ async initializeAdditionalRepositories(entities) {
|
|
42
|
-
const provider = this.getDataSourceProvider();
|
|
43
|
-
const repositories = [];
|
|
44
|
-
for (const entity of entities){
|
|
45
|
-
repositories.push(await provider.getRepository(entity));
|
|
46
|
-
}
|
|
47
|
-
return repositories;
|
|
48
|
-
}
|
|
49
|
-
/** Get DataSource for direct access (transactions, custom queries) */ async getDataSourceForService() {
|
|
50
|
-
const provider = this.getDataSourceProvider();
|
|
51
|
-
return await provider.getDataSource();
|
|
52
|
-
}
|
|
53
|
-
constructor(...args){
|
|
54
|
-
super(...args), _define_property(this, "repositoryInitialized", false);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
RequestScopedApiService = _ts_decorate([
|
|
58
|
-
(0, _common.Injectable)({
|
|
59
|
-
scope: _common.Scope.REQUEST
|
|
60
|
-
})
|
|
61
|
-
], RequestScopedApiService);
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "DataSourceModule", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return DataSourceModule;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nestjscore = require("@flusys/nestjs-core");
|
|
12
|
-
const _common = require("@nestjs/common");
|
|
13
|
-
const _multitenantdatasourceservice = require("./multi-tenant-datasource.service");
|
|
14
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
-
}
|
|
20
|
-
let DataSourceModule = class DataSourceModule {
|
|
21
|
-
/**
|
|
22
|
-
* Register with static options
|
|
23
|
-
*/ static forRoot(options) {
|
|
24
|
-
const { global = false, ...moduleOptions } = options;
|
|
25
|
-
return {
|
|
26
|
-
module: DataSourceModule,
|
|
27
|
-
global,
|
|
28
|
-
providers: [
|
|
29
|
-
{
|
|
30
|
-
provide: _nestjscore.MODULE_OPTIONS,
|
|
31
|
-
useValue: moduleOptions
|
|
32
|
-
},
|
|
33
|
-
_multitenantdatasourceservice.MultiTenantDataSourceService
|
|
34
|
-
],
|
|
35
|
-
exports: [
|
|
36
|
-
_nestjscore.MODULE_OPTIONS,
|
|
37
|
-
_multitenantdatasourceservice.MultiTenantDataSourceService
|
|
38
|
-
]
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Register with async options
|
|
43
|
-
*/ static forRootAsync(asyncOptions) {
|
|
44
|
-
const { global = false, imports = [] } = asyncOptions;
|
|
45
|
-
return {
|
|
46
|
-
module: DataSourceModule,
|
|
47
|
-
global,
|
|
48
|
-
imports,
|
|
49
|
-
providers: [
|
|
50
|
-
...this.createAsyncProviders(asyncOptions),
|
|
51
|
-
_multitenantdatasourceservice.MultiTenantDataSourceService
|
|
52
|
-
],
|
|
53
|
-
exports: [
|
|
54
|
-
_nestjscore.MODULE_OPTIONS,
|
|
55
|
-
_multitenantdatasourceservice.MultiTenantDataSourceService
|
|
56
|
-
]
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Import for child modules (uses existing MODULE_OPTIONS)
|
|
61
|
-
*/ static forFeature() {
|
|
62
|
-
return {
|
|
63
|
-
module: DataSourceModule,
|
|
64
|
-
providers: [
|
|
65
|
-
_multitenantdatasourceservice.MultiTenantDataSourceService
|
|
66
|
-
],
|
|
67
|
-
exports: [
|
|
68
|
-
_multitenantdatasourceservice.MultiTenantDataSourceService
|
|
69
|
-
]
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Create async providers based on options
|
|
74
|
-
*/ static createAsyncProviders(options) {
|
|
75
|
-
if (options.useFactory) {
|
|
76
|
-
return [
|
|
77
|
-
{
|
|
78
|
-
provide: _nestjscore.MODULE_OPTIONS,
|
|
79
|
-
useFactory: options.useFactory,
|
|
80
|
-
inject: options.inject || []
|
|
81
|
-
}
|
|
82
|
-
];
|
|
83
|
-
}
|
|
84
|
-
if (options.useClass) {
|
|
85
|
-
return [
|
|
86
|
-
{
|
|
87
|
-
provide: options.useClass,
|
|
88
|
-
useClass: options.useClass
|
|
89
|
-
},
|
|
90
|
-
this.createFactoryProvider(options.useClass)
|
|
91
|
-
];
|
|
92
|
-
}
|
|
93
|
-
if (options.useExisting) {
|
|
94
|
-
return [
|
|
95
|
-
this.createFactoryProvider(options.useExisting)
|
|
96
|
-
];
|
|
97
|
-
}
|
|
98
|
-
return [
|
|
99
|
-
{
|
|
100
|
-
provide: _nestjscore.MODULE_OPTIONS,
|
|
101
|
-
useValue: {}
|
|
102
|
-
}
|
|
103
|
-
];
|
|
104
|
-
}
|
|
105
|
-
static createFactoryProvider(factoryClass) {
|
|
106
|
-
return {
|
|
107
|
-
provide: _nestjscore.MODULE_OPTIONS,
|
|
108
|
-
useFactory: async (factory)=>factory.createOptions(),
|
|
109
|
-
inject: [
|
|
110
|
-
factoryClass
|
|
111
|
-
]
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
DataSourceModule = _ts_decorate([
|
|
116
|
-
(0, _common.Module)({})
|
|
117
|
-
], DataSourceModule);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { DataSource, EntityTarget, Repository } from 'typeorm';
|
|
2
|
-
import { Identity } from '../entities';
|
|
3
|
-
import { IDataSourceProvider } from '../interfaces';
|
|
4
|
-
import { ApiService } from './api-service.class';
|
|
5
|
-
export declare abstract class RequestScopedApiService<CreateDtoT extends object, UpdateDtoT extends {
|
|
6
|
-
id: string;
|
|
7
|
-
}, InterfaceT extends Identity, EntityT extends Identity> extends ApiService<CreateDtoT, UpdateDtoT, InterfaceT, EntityT> {
|
|
8
|
-
private repositoryInitialized;
|
|
9
|
-
protected abstract resolveEntity(): EntityTarget<EntityT>;
|
|
10
|
-
protected abstract getDataSourceProvider(): IDataSourceProvider;
|
|
11
|
-
protected ensureRepositoryInitialized(): Promise<void>;
|
|
12
|
-
protected initializeAdditionalRepositories(entities: EntityTarget<any>[]): Promise<Repository<any>[]>;
|
|
13
|
-
protected getDataSourceForService(): Promise<DataSource>;
|
|
14
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
function _define_property(obj, key, value) {
|
|
2
|
-
if (key in obj) {
|
|
3
|
-
Object.defineProperty(obj, key, {
|
|
4
|
-
value: value,
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true
|
|
8
|
-
});
|
|
9
|
-
} else {
|
|
10
|
-
obj[key] = value;
|
|
11
|
-
}
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
14
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
-
}
|
|
20
|
-
import { Injectable, Scope } from '@nestjs/common';
|
|
21
|
-
import { ApiService } from './api-service.class';
|
|
22
|
-
export class RequestScopedApiService extends ApiService {
|
|
23
|
-
async ensureRepositoryInitialized() {
|
|
24
|
-
if (!this.repositoryInitialized) {
|
|
25
|
-
const entity = this.resolveEntity();
|
|
26
|
-
const provider = this.getDataSourceProvider();
|
|
27
|
-
this.repository = await provider.getRepository(entity);
|
|
28
|
-
this.repositoryInitialized = true;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/** Initialize additional repositories beyond the primary entity */ async initializeAdditionalRepositories(entities) {
|
|
32
|
-
const provider = this.getDataSourceProvider();
|
|
33
|
-
const repositories = [];
|
|
34
|
-
for (const entity of entities){
|
|
35
|
-
repositories.push(await provider.getRepository(entity));
|
|
36
|
-
}
|
|
37
|
-
return repositories;
|
|
38
|
-
}
|
|
39
|
-
/** Get DataSource for direct access (transactions, custom queries) */ async getDataSourceForService() {
|
|
40
|
-
const provider = this.getDataSourceProvider();
|
|
41
|
-
return await provider.getDataSource();
|
|
42
|
-
}
|
|
43
|
-
constructor(...args){
|
|
44
|
-
super(...args), _define_property(this, "repositoryInitialized", false);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
RequestScopedApiService = _ts_decorate([
|
|
48
|
-
Injectable({
|
|
49
|
-
scope: Scope.REQUEST
|
|
50
|
-
})
|
|
51
|
-
], RequestScopedApiService);
|