@flusys/nestjs-storage 5.1.2 → 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.
@@ -1,3 +1,4 @@
1
+ /// <reference types="multer" />
1
2
  "use strict";
2
3
  Object.defineProperty(exports, "__esModule", {
3
4
  value: true
@@ -103,13 +103,10 @@ const DEFAULT_SELECT_FIELDS = [
103
103
  'createdAt',
104
104
  'deletedAt'
105
105
  ];
106
- let FileManagerService = class FileManagerService extends _classes.RequestScopedApiService {
106
+ let FileManagerService = class FileManagerService extends _classes.ApiService {
107
107
  resolveEntity() {
108
108
  return this.storageConfig.isCompanyFeatureEnabled() ? _entities.FileManagerWithCompany : _entities.FileManager;
109
109
  }
110
- getDataSourceProvider() {
111
- return this.dataSourceProvider;
112
- }
113
110
  // ─── Override Methods ───────────────────────────────────────────────────────
114
111
  async convertSingleDtoToEntity(dto, user) {
115
112
  let entity = {};
@@ -196,7 +193,7 @@ let FileManagerService = class FileManagerService extends _classes.RequestScoped
196
193
  }
197
194
  // ─── Public Methods ─────────────────────────────────────────────────────────
198
195
  async getFiles(dtos, protocol, host, user) {
199
- await this.ensureRepositoryInitialized();
196
+ await this.ensureDataSourceRepository();
200
197
  const ids = dtos.map((d)=>d.id).filter(Boolean);
201
198
  if (!ids.length) throw new _common.BadRequestException({
202
199
  message: 'No valid file IDs provided',
@@ -364,7 +361,7 @@ let FileManagerService = class FileManagerService extends _classes.RequestScoped
364
361
  };
365
362
  }
366
363
  constructor(cacheManager, utilsService, uploadService, storageConfig, dataSourceProvider){
367
- super('file_manager', null, cacheManager, utilsService, FileManagerService.name, true, 'storage'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "uploadService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.uploadService = uploadService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
364
+ super('file_manager', cacheManager, utilsService, FileManagerService.name, true, 'storage', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "uploadService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.uploadService = uploadService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
368
365
  }
369
366
  };
370
367
  FileManagerService = _ts_decorate([
@@ -42,13 +42,10 @@ function _ts_param(paramIndex, decorator) {
42
42
  decorator(target, key, paramIndex);
43
43
  };
44
44
  }
45
- let FolderService = class FolderService extends _classes.RequestScopedApiService {
45
+ let FolderService = class FolderService extends _classes.ApiService {
46
46
  resolveEntity() {
47
47
  return this.storageConfig.isCompanyFeatureEnabled() ? _entities.FolderWithCompany : _entities.Folder;
48
48
  }
49
- getDataSourceProvider() {
50
- return this.dataSourceProvider;
51
- }
52
49
  // ─── Override Methods ───────────────────────────────────────────────────────
53
50
  async convertSingleDtoToEntity(dto, user) {
54
51
  const entity = await super.convertSingleDtoToEntity(dto, user);
@@ -85,7 +82,7 @@ let FolderService = class FolderService extends _classes.RequestScopedApiService
85
82
  return result;
86
83
  }
87
84
  constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
88
- super('folder', null, cacheManager, utilsService, FolderService.name, true, 'storage'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
85
+ super('folder', cacheManager, utilsService, FolderService.name, true, 'storage', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
89
86
  }
90
87
  };
91
88
  FolderService = _ts_decorate([
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "StorageDataSourceProvider", {
8
8
  return StorageDataSourceProvider;
9
9
  }
10
10
  });
11
- const _constants = require("@flusys/nestjs-shared/constants");
12
11
  const _modules = require("@flusys/nestjs-shared/modules");
13
12
  const _common = require("@nestjs/common");
14
13
  const _core = require("@nestjs/core");
@@ -83,8 +82,7 @@ function _ts_param(paramIndex, decorator) {
83
82
  };
84
83
  }
85
84
  let StorageDataSourceProvider = class StorageDataSourceProvider extends _modules.MultiTenantDataSourceService {
86
- // Factory Methods
87
- /** Build parent options from StorageModuleOptions */ static buildParentOptions(options) {
85
+ static buildParentOptions(options) {
88
86
  return {
89
87
  bootstrapAppConfig: options.bootstrapAppConfig,
90
88
  defaultDatabaseConfig: options.config?.defaultDatabaseConfig,
@@ -92,19 +90,10 @@ let StorageDataSourceProvider = class StorageDataSourceProvider extends _modules
92
90
  tenants: options.config?.tenants
93
91
  };
94
92
  }
95
- // Feature Flags
96
- /**
97
- * Get enable company feature for specific tenant
98
- * Falls back to global setting if not specified per-tenant
99
- */ getEnableCompanyFeatureForTenant(tenant) {
93
+ getEnableCompanyFeatureForTenant(tenant) {
100
94
  return tenant?.enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
101
95
  }
102
- // Entity Management
103
- /**
104
- * Get storage entities for migrations based on company feature flag.
105
- * For TypeORM repositories, we always use the base entities (FileManager, etc.)
106
- * but for migrations, we need the correct entity based on the feature flag.
107
- */ async getStorageEntities(enableCompanyFeature) {
96
+ async getStorageEntities(enableCompanyFeature) {
108
97
  const enable = enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
109
98
  const entities = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("../entities")));
110
99
  return enable ? [
@@ -117,72 +106,16 @@ let StorageDataSourceProvider = class StorageDataSourceProvider extends _modules
117
106
  entities.StorageConfig
118
107
  ];
119
108
  }
120
- // Overrides
121
- /** Override to dynamically set entities based on tenant config */ async createDataSourceFromConfig(config) {
109
+ async createDataSourceFromConfig(config) {
122
110
  const currentTenant = this.getCurrentTenant();
123
111
  const enableCompanyFeature = this.getEnableCompanyFeatureForTenant(currentTenant ?? undefined);
124
112
  const entities = await this.getStorageEntities(enableCompanyFeature);
125
113
  return super.createDataSourceFromConfig(config, entities);
126
114
  }
127
- /**
128
- * Override to use Storage-specific static cache
129
- */ async getSingleDataSource() {
130
- // Return existing initialized connection from Storage-specific cache
131
- if (StorageDataSourceProvider.singleDataSource?.isInitialized) {
132
- return StorageDataSourceProvider.singleDataSource;
133
- }
134
- // If another request is creating the connection, wait for it
135
- if (StorageDataSourceProvider.singleConnectionLock) {
136
- return StorageDataSourceProvider.singleConnectionLock;
137
- }
138
- const config = this.getDefaultDatabaseConfig();
139
- if (!config) {
140
- throw new _common.InternalServerErrorException({
141
- message: 'No database config available. Provide defaultDatabaseConfig or tenantDefaultDatabaseConfig.',
142
- messageKey: _constants.SYSTEM_MESSAGES.DATABASE_CONFIG_NOT_AVAILABLE
143
- });
144
- }
145
- // Create connection with lock to prevent race conditions
146
- const connectionPromise = this.createDataSourceFromConfig(config);
147
- StorageDataSourceProvider.singleConnectionLock = connectionPromise;
148
- try {
149
- const dataSource = await connectionPromise;
150
- StorageDataSourceProvider.singleDataSource = dataSource;
151
- return dataSource;
152
- } finally{
153
- StorageDataSourceProvider.singleConnectionLock = null;
154
- }
155
- }
156
- /**
157
- * Override to use Storage-specific static cache for tenant connections
158
- */ async getOrCreateTenantConnection(tenant) {
159
- // Return existing initialized connection from Storage-specific cache
160
- const existing = StorageDataSourceProvider.tenantConnections.get(tenant.id);
161
- if (existing?.isInitialized) {
162
- return existing;
163
- }
164
- // If another request is creating this tenant's connection, wait for it
165
- const pendingConnection = StorageDataSourceProvider.connectionLocks.get(tenant.id);
166
- if (pendingConnection) {
167
- return pendingConnection;
168
- }
169
- // Create connection with lock to prevent race conditions
170
- const config = this.buildTenantDatabaseConfig(tenant);
171
- const connectionPromise = this.createDataSourceFromConfig(config);
172
- StorageDataSourceProvider.connectionLocks.set(tenant.id, connectionPromise);
173
- try {
174
- const dataSource = await connectionPromise;
175
- StorageDataSourceProvider.tenantConnections.set(tenant.id, dataSource);
176
- return dataSource;
177
- } finally{
178
- StorageDataSourceProvider.connectionLocks.delete(tenant.id);
179
- }
180
- }
181
115
  constructor(configService, request){
182
116
  super(StorageDataSourceProvider.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), this.configService = configService;
183
117
  }
184
118
  };
185
- // Override parent's static properties to have Storage-specific cache
186
119
  _define_property(StorageDataSourceProvider, "tenantConnections", new Map());
187
120
  _define_property(StorageDataSourceProvider, "singleDataSource", null);
188
121
  _define_property(StorageDataSourceProvider, "tenantsRegistry", new Map());
@@ -42,13 +42,10 @@ function _ts_param(paramIndex, decorator) {
42
42
  decorator(target, key, paramIndex);
43
43
  };
44
44
  }
45
- let StorageProviderConfigService = class StorageProviderConfigService extends _classes.RequestScopedApiService {
45
+ let StorageProviderConfigService = class StorageProviderConfigService extends _classes.ApiService {
46
46
  resolveEntity() {
47
47
  return this.storageConfig.isCompanyFeatureEnabled() ? _entities.StorageConfigWithCompany : _entities.StorageConfig;
48
48
  }
49
- getDataSourceProvider() {
50
- return this.dataSourceProvider;
51
- }
52
49
  // ─── Override Methods ───────────────────────────────────────────────────────
53
50
  async convertSingleDtoToEntity(dto, user) {
54
51
  const entity = await super.convertSingleDtoToEntity(dto, user);
@@ -89,7 +86,7 @@ let StorageProviderConfigService = class StorageProviderConfigService extends _c
89
86
  return result;
90
87
  }
91
88
  async findByIdDirect(id) {
92
- await this.ensureRepositoryInitialized();
89
+ await this.ensureDataSourceRepository();
93
90
  return await this.repository.findOne({
94
91
  where: {
95
92
  id
@@ -97,7 +94,7 @@ let StorageProviderConfigService = class StorageProviderConfigService extends _c
97
94
  });
98
95
  }
99
96
  async getDefaultConfig(user) {
100
- await this.ensureRepositoryInitialized();
97
+ await this.ensureDataSourceRepository();
101
98
  const baseWhere = (0, _utils.buildCompanyWhereCondition)({
102
99
  isActive: true
103
100
  }, this.storageConfig.isCompanyFeatureEnabled(), user);
@@ -121,7 +118,7 @@ let StorageProviderConfigService = class StorageProviderConfigService extends _c
121
118
  });
122
119
  }
123
120
  async getConfigByType(storage, user) {
124
- await this.ensureRepositoryInitialized();
121
+ await this.ensureDataSourceRepository();
125
122
  const where = (0, _utils.buildCompanyWhereCondition)({
126
123
  storage,
127
124
  isActive: true
@@ -131,7 +128,7 @@ let StorageProviderConfigService = class StorageProviderConfigService extends _c
131
128
  });
132
129
  }
133
130
  constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
134
- super('storageConfig', null, cacheManager, utilsService, StorageProviderConfigService.name, true, 'storage'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
131
+ super('storageConfig', cacheManager, utilsService, StorageProviderConfigService.name, true, 'storage', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
135
132
  }
136
133
  };
137
134
  StorageProviderConfigService = _ts_decorate([
@@ -4,19 +4,19 @@ import { CreateFileManagerDto, FileManagerResponseDto, FilesResponseDto, GetFile
4
4
  import { Request } from 'express';
5
5
  import { FileManagerService } from '../services/file-manager.service';
6
6
  declare const FileManagerController_base: abstract new (service: FileManagerService) => {
7
- readonly enabledEndpoints: import("@flusys/nestjs-shared/classes").ApiEndpoint[] | "all";
7
+ readonly enabledEndpoints: import("@flusys/nestjs-shared").ApiEndpoint[] | "all";
8
8
  service: FileManagerService;
9
- isEnabled(endpoint: import("@flusys/nestjs-shared/classes").ApiEndpoint): boolean;
9
+ isEnabled(endpoint: import("@flusys/nestjs-shared").ApiEndpoint): boolean;
10
10
  insert(addDto: CreateFileManagerDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
11
- insertMany(addDto: CreateFileManagerDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FileManagerResponseDto>>;
12
- getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
13
- getByIds(body: import("@flusys/nestjs-shared/dtos").GetByIdsDto, user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<FileManagerResponseDto>>;
11
+ insertMany(addDto: CreateFileManagerDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<FileManagerResponseDto>>;
12
+ getById(id: string, body: import("@flusys/nestjs-shared").GetByIdBodyDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
13
+ getByIds(body: import("@flusys/nestjs-shared").GetByIdsDto, user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").ListResponseDto<FileManagerResponseDto>>;
14
14
  update(updateDto: UpdateFileManagerDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
15
- updateMany(updateDtos: UpdateFileManagerDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FileManagerResponseDto>>;
16
- bulkUpsert(dtos: (CreateFileManagerDto | UpdateFileManagerDto)[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FileManagerResponseDto>>;
15
+ updateMany(updateDtos: UpdateFileManagerDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<FileManagerResponseDto>>;
16
+ bulkUpsert(dtos: (CreateFileManagerDto | UpdateFileManagerDto)[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<FileManagerResponseDto>>;
17
17
  getByFilter(filter: Record<string, any>, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
18
- getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<FileManagerResponseDto>>;
19
- delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
18
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared").FilterAndPaginationDto, user: ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared").ListResponseDto<FileManagerResponseDto>>;
19
+ delete(deleteDto: import("@flusys/nestjs-shared").DeleteDto, user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").MessageResponseDto>;
20
20
  };
21
21
  export declare class FileManagerController extends FileManagerController_base {
22
22
  protected fileService: FileManagerService;
@@ -1,9 +1,9 @@
1
1
  import { CreateFolderDto, FolderResponseDto, UpdateFolderDto } from '../dtos';
2
2
  import { FolderService } from '../services/folder.service';
3
3
  declare const FolderController_base: abstract new (service: FolderService) => {
4
- readonly enabledEndpoints: import("@flusys/nestjs-shared/classes").ApiEndpoint[] | "all";
4
+ readonly enabledEndpoints: import("@flusys/nestjs-shared").ApiEndpoint[] | "all";
5
5
  service: FolderService;
6
- isEnabled(endpoint: import("@flusys/nestjs-shared/classes").ApiEndpoint): boolean;
6
+ isEnabled(endpoint: import("@flusys/nestjs-shared").ApiEndpoint): boolean;
7
7
  insert(addDto: CreateFolderDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<FolderResponseDto>>;
8
8
  insertMany(addDto: CreateFolderDto[], user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<FolderResponseDto>>;
9
9
  getById(id: string, body: import("@flusys/nestjs-shared").GetByIdBodyDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<FolderResponseDto>>;
@@ -1,9 +1,9 @@
1
1
  import { CreateStorageConfigDto, StorageConfigResponseDto, UpdateStorageConfigDto } from '../dtos';
2
2
  import { StorageProviderConfigService } from '../services/storage-provider-config.service';
3
3
  declare const StorageConfigController_base: abstract new (service: StorageProviderConfigService) => {
4
- readonly enabledEndpoints: import("@flusys/nestjs-shared/classes").ApiEndpoint[] | "all";
4
+ readonly enabledEndpoints: import("@flusys/nestjs-shared").ApiEndpoint[] | "all";
5
5
  service: StorageProviderConfigService;
6
- isEnabled(endpoint: import("@flusys/nestjs-shared/classes").ApiEndpoint): boolean;
6
+ isEnabled(endpoint: import("@flusys/nestjs-shared").ApiEndpoint): boolean;
7
7
  insert(addDto: CreateStorageConfigDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<StorageConfigResponseDto>>;
8
8
  insertMany(addDto: CreateStorageConfigDto[], user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<StorageConfigResponseDto>>;
9
9
  getById(id: string, body: import("@flusys/nestjs-shared").GetByIdBodyDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<StorageConfigResponseDto>>;
@@ -25,6 +25,7 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
+ /// <reference types="multer" />
28
29
  import { UPLOAD_CONFIG_PERMISSIONS } from '@flusys/nestjs-shared';
29
30
  import { ApiResponseDto, CurrentUser, RequirePermission } from '@flusys/nestjs-shared/decorators';
30
31
  import { JwtAuthGuard, PermissionGuard } from '@flusys/nestjs-shared/guards';
@@ -25,7 +25,7 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
28
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
29
29
  import { UtilsService } from '@flusys/nestjs-shared/modules';
30
30
  import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
31
31
  import { BadRequestException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
@@ -52,13 +52,10 @@ const DEFAULT_SELECT_FIELDS = [
52
52
  'createdAt',
53
53
  'deletedAt'
54
54
  ];
55
- export class FileManagerService extends RequestScopedApiService {
55
+ export class FileManagerService extends ApiService {
56
56
  resolveEntity() {
57
57
  return this.storageConfig.isCompanyFeatureEnabled() ? FileManagerWithCompany : FileManager;
58
58
  }
59
- getDataSourceProvider() {
60
- return this.dataSourceProvider;
61
- }
62
59
  // ─── Override Methods ───────────────────────────────────────────────────────
63
60
  async convertSingleDtoToEntity(dto, user) {
64
61
  let entity = {};
@@ -145,7 +142,7 @@ export class FileManagerService extends RequestScopedApiService {
145
142
  }
146
143
  // ─── Public Methods ─────────────────────────────────────────────────────────
147
144
  async getFiles(dtos, protocol, host, user) {
148
- await this.ensureRepositoryInitialized();
145
+ await this.ensureDataSourceRepository();
149
146
  const ids = dtos.map((d)=>d.id).filter(Boolean);
150
147
  if (!ids.length) throw new BadRequestException({
151
148
  message: 'No valid file IDs provided',
@@ -313,7 +310,7 @@ export class FileManagerService extends RequestScopedApiService {
313
310
  };
314
311
  }
315
312
  constructor(cacheManager, utilsService, uploadService, storageConfig, dataSourceProvider){
316
- super('file_manager', null, cacheManager, utilsService, FileManagerService.name, true, 'storage'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "uploadService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.uploadService = uploadService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
313
+ super('file_manager', cacheManager, utilsService, FileManagerService.name, true, 'storage', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "uploadService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.uploadService = uploadService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
317
314
  }
318
315
  }
319
316
  FileManagerService = _ts_decorate([
@@ -25,20 +25,17 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
28
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
29
29
  import { UtilsService } from '@flusys/nestjs-shared/modules';
30
30
  import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
31
31
  import { Inject, Injectable, Scope } from '@nestjs/common';
32
32
  import { Folder, FolderWithCompany } from '../entities';
33
33
  import { StorageConfigService } from './storage-config.service';
34
34
  import { StorageDataSourceProvider } from './storage-datasource.provider';
35
- export class FolderService extends RequestScopedApiService {
35
+ export class FolderService extends ApiService {
36
36
  resolveEntity() {
37
37
  return this.storageConfig.isCompanyFeatureEnabled() ? FolderWithCompany : Folder;
38
38
  }
39
- getDataSourceProvider() {
40
- return this.dataSourceProvider;
41
- }
42
39
  // ─── Override Methods ───────────────────────────────────────────────────────
43
40
  async convertSingleDtoToEntity(dto, user) {
44
41
  const entity = await super.convertSingleDtoToEntity(dto, user);
@@ -75,7 +72,7 @@ export class FolderService extends RequestScopedApiService {
75
72
  return result;
76
73
  }
77
74
  constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
78
- super('folder', null, cacheManager, utilsService, FolderService.name, true, 'storage'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
75
+ super('folder', cacheManager, utilsService, FolderService.name, true, 'storage', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
79
76
  }
80
77
  }
81
78
  FolderService = _ts_decorate([
@@ -25,15 +25,13 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { SYSTEM_MESSAGES } from '@flusys/nestjs-shared/constants';
29
28
  import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
30
- import { Inject, Injectable, InternalServerErrorException, Optional, Scope } from '@nestjs/common';
29
+ import { Inject, Injectable, Optional, Scope } from '@nestjs/common';
31
30
  import { REQUEST } from '@nestjs/core';
32
31
  import { Request } from 'express';
33
32
  import { StorageConfigService } from './storage-config.service';
34
33
  export class StorageDataSourceProvider extends MultiTenantDataSourceService {
35
- // Factory Methods
36
- /** Build parent options from StorageModuleOptions */ static buildParentOptions(options) {
34
+ static buildParentOptions(options) {
37
35
  return {
38
36
  bootstrapAppConfig: options.bootstrapAppConfig,
39
37
  defaultDatabaseConfig: options.config?.defaultDatabaseConfig,
@@ -41,19 +39,10 @@ export class StorageDataSourceProvider extends MultiTenantDataSourceService {
41
39
  tenants: options.config?.tenants
42
40
  };
43
41
  }
44
- // Feature Flags
45
- /**
46
- * Get enable company feature for specific tenant
47
- * Falls back to global setting if not specified per-tenant
48
- */ getEnableCompanyFeatureForTenant(tenant) {
42
+ getEnableCompanyFeatureForTenant(tenant) {
49
43
  return tenant?.enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
50
44
  }
51
- // Entity Management
52
- /**
53
- * Get storage entities for migrations based on company feature flag.
54
- * For TypeORM repositories, we always use the base entities (FileManager, etc.)
55
- * but for migrations, we need the correct entity based on the feature flag.
56
- */ async getStorageEntities(enableCompanyFeature) {
45
+ async getStorageEntities(enableCompanyFeature) {
57
46
  const enable = enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
58
47
  const entities = await import('../entities');
59
48
  return enable ? [
@@ -66,72 +55,16 @@ export class StorageDataSourceProvider extends MultiTenantDataSourceService {
66
55
  entities.StorageConfig
67
56
  ];
68
57
  }
69
- // Overrides
70
- /** Override to dynamically set entities based on tenant config */ async createDataSourceFromConfig(config) {
58
+ async createDataSourceFromConfig(config) {
71
59
  const currentTenant = this.getCurrentTenant();
72
60
  const enableCompanyFeature = this.getEnableCompanyFeatureForTenant(currentTenant ?? undefined);
73
61
  const entities = await this.getStorageEntities(enableCompanyFeature);
74
62
  return super.createDataSourceFromConfig(config, entities);
75
63
  }
76
- /**
77
- * Override to use Storage-specific static cache
78
- */ async getSingleDataSource() {
79
- // Return existing initialized connection from Storage-specific cache
80
- if (StorageDataSourceProvider.singleDataSource?.isInitialized) {
81
- return StorageDataSourceProvider.singleDataSource;
82
- }
83
- // If another request is creating the connection, wait for it
84
- if (StorageDataSourceProvider.singleConnectionLock) {
85
- return StorageDataSourceProvider.singleConnectionLock;
86
- }
87
- const config = this.getDefaultDatabaseConfig();
88
- if (!config) {
89
- throw new InternalServerErrorException({
90
- message: 'No database config available. Provide defaultDatabaseConfig or tenantDefaultDatabaseConfig.',
91
- messageKey: SYSTEM_MESSAGES.DATABASE_CONFIG_NOT_AVAILABLE
92
- });
93
- }
94
- // Create connection with lock to prevent race conditions
95
- const connectionPromise = this.createDataSourceFromConfig(config);
96
- StorageDataSourceProvider.singleConnectionLock = connectionPromise;
97
- try {
98
- const dataSource = await connectionPromise;
99
- StorageDataSourceProvider.singleDataSource = dataSource;
100
- return dataSource;
101
- } finally{
102
- StorageDataSourceProvider.singleConnectionLock = null;
103
- }
104
- }
105
- /**
106
- * Override to use Storage-specific static cache for tenant connections
107
- */ async getOrCreateTenantConnection(tenant) {
108
- // Return existing initialized connection from Storage-specific cache
109
- const existing = StorageDataSourceProvider.tenantConnections.get(tenant.id);
110
- if (existing?.isInitialized) {
111
- return existing;
112
- }
113
- // If another request is creating this tenant's connection, wait for it
114
- const pendingConnection = StorageDataSourceProvider.connectionLocks.get(tenant.id);
115
- if (pendingConnection) {
116
- return pendingConnection;
117
- }
118
- // Create connection with lock to prevent race conditions
119
- const config = this.buildTenantDatabaseConfig(tenant);
120
- const connectionPromise = this.createDataSourceFromConfig(config);
121
- StorageDataSourceProvider.connectionLocks.set(tenant.id, connectionPromise);
122
- try {
123
- const dataSource = await connectionPromise;
124
- StorageDataSourceProvider.tenantConnections.set(tenant.id, dataSource);
125
- return dataSource;
126
- } finally{
127
- StorageDataSourceProvider.connectionLocks.delete(tenant.id);
128
- }
129
- }
130
64
  constructor(configService, request){
131
65
  super(StorageDataSourceProvider.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), this.configService = configService;
132
66
  }
133
67
  }
134
- // Override parent's static properties to have Storage-specific cache
135
68
  _define_property(StorageDataSourceProvider, "tenantConnections", new Map());
136
69
  _define_property(StorageDataSourceProvider, "singleDataSource", null);
137
70
  _define_property(StorageDataSourceProvider, "tenantsRegistry", new Map());
@@ -25,20 +25,17 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
28
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
29
29
  import { UtilsService } from '@flusys/nestjs-shared/modules';
30
30
  import { applyCompanyFilter, buildCompanyWhereCondition } from '@flusys/nestjs-shared/utils';
31
31
  import { Inject, Injectable, Scope } from '@nestjs/common';
32
32
  import { StorageConfig, StorageConfigWithCompany } from '../entities';
33
33
  import { StorageConfigService } from './storage-config.service';
34
34
  import { StorageDataSourceProvider } from './storage-datasource.provider';
35
- export class StorageProviderConfigService extends RequestScopedApiService {
35
+ export class StorageProviderConfigService extends ApiService {
36
36
  resolveEntity() {
37
37
  return this.storageConfig.isCompanyFeatureEnabled() ? StorageConfigWithCompany : StorageConfig;
38
38
  }
39
- getDataSourceProvider() {
40
- return this.dataSourceProvider;
41
- }
42
39
  // ─── Override Methods ───────────────────────────────────────────────────────
43
40
  async convertSingleDtoToEntity(dto, user) {
44
41
  const entity = await super.convertSingleDtoToEntity(dto, user);
@@ -79,7 +76,7 @@ export class StorageProviderConfigService extends RequestScopedApiService {
79
76
  return result;
80
77
  }
81
78
  async findByIdDirect(id) {
82
- await this.ensureRepositoryInitialized();
79
+ await this.ensureDataSourceRepository();
83
80
  return await this.repository.findOne({
84
81
  where: {
85
82
  id
@@ -87,7 +84,7 @@ export class StorageProviderConfigService extends RequestScopedApiService {
87
84
  });
88
85
  }
89
86
  async getDefaultConfig(user) {
90
- await this.ensureRepositoryInitialized();
87
+ await this.ensureDataSourceRepository();
91
88
  const baseWhere = buildCompanyWhereCondition({
92
89
  isActive: true
93
90
  }, this.storageConfig.isCompanyFeatureEnabled(), user);
@@ -111,7 +108,7 @@ export class StorageProviderConfigService extends RequestScopedApiService {
111
108
  });
112
109
  }
113
110
  async getConfigByType(storage, user) {
114
- await this.ensureRepositoryInitialized();
111
+ await this.ensureDataSourceRepository();
115
112
  const where = buildCompanyWhereCondition({
116
113
  storage,
117
114
  isActive: true
@@ -121,7 +118,7 @@ export class StorageProviderConfigService extends RequestScopedApiService {
121
118
  });
122
119
  }
123
120
  constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
124
- super('storageConfig', null, cacheManager, utilsService, StorageProviderConfigService.name, true, 'storage'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
121
+ super('storageConfig', cacheManager, utilsService, StorageProviderConfigService.name, true, 'storage', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
125
122
  }
126
123
  }
127
124
  StorageProviderConfigService = _ts_decorate([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-storage",
3
- "version": "5.1.2",
3
+ "version": "5.1.3",
4
4
  "description": "Modular storage package with optional AWS S3, Azure Blob, and SFTP providers",
5
5
  "main": "cjs/index.js",
6
6
  "module": "fesm/index.js",
@@ -85,25 +85,25 @@
85
85
  }
86
86
  },
87
87
  "peerDependencies": {
88
- "@nestjs/common": "^10.0.0 || ^11.0.0",
89
- "@nestjs/config": "^3.0.0 || ^4.0.0",
90
- "@nestjs/core": "^10.0.0 || ^11.0.0",
91
- "@nestjs/platform-express": "^10.0.0 || ^11.0.0",
92
- "@nestjs/swagger": "^7.0.0 || ^11.0.0",
93
- "@nestjs/typeorm": "^10.0.0 || ^11.0.0",
94
- "class-transformer": "^0.5.0",
95
- "class-validator": "^0.14.0",
88
+ "@nestjs/common": "^11.0.0",
89
+ "@nestjs/config": "^4.0.0",
90
+ "@nestjs/core": "^11.0.0",
91
+ "@nestjs/platform-express": "^11.0.0",
92
+ "@nestjs/swagger": "^11.0.0",
93
+ "@nestjs/typeorm": "^11.0.0",
94
+ "class-transformer": "^0.5.1",
95
+ "class-validator": "^0.14.0 || ^0.15.0",
96
96
  "typeorm": "^0.3.0",
97
- "multer": "^2.0.0",
97
+ "multer": "^2.1.0",
98
98
  "sharp": "^0.34.0",
99
- "mime-types": "^2.1.0",
100
- "uuid": "^9.0.0 || ^11.0.0",
101
- "@aws-sdk/client-s3": "^3.400.0",
102
- "@aws-sdk/lib-storage": "^3.400.0",
103
- "@aws-sdk/s3-request-presigner": "^3.400.0",
104
- "@azure/storage-blob": "^12.15.0",
105
- "ssh2-sftp-client": "^12.0.0",
106
- "express": "^4.18.0"
99
+ "mime-types": "^2.1.0 || ^3.0.0",
100
+ "uuid": "^11.0.0",
101
+ "@aws-sdk/client-s3": "^3.900.0",
102
+ "@aws-sdk/lib-storage": "^3.900.0",
103
+ "@aws-sdk/s3-request-presigner": "^3.900.0",
104
+ "@azure/storage-blob": "^12.29.0",
105
+ "ssh2-sftp-client": "^12.1.0",
106
+ "express": "^4.18.0 || ^5.0.0"
107
107
  },
108
108
  "peerDependenciesMeta": {
109
109
  "sharp": {
@@ -129,7 +129,7 @@
129
129
  }
130
130
  },
131
131
  "dependencies": {
132
- "@flusys/nestjs-core": "5.1.2",
133
- "@flusys/nestjs-shared": "5.1.2"
132
+ "@flusys/nestjs-core": "5.1.3",
133
+ "@flusys/nestjs-shared": "5.1.3"
134
134
  }
135
135
  }
@@ -1,4 +1,4 @@
1
- import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
1
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
2
2
  import { DeleteDto, FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
3
3
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
4
4
  import { UtilsService } from '@flusys/nestjs-shared/modules';
@@ -9,7 +9,7 @@ import { IFileManager } from '../interfaces';
9
9
  import { StorageConfigService } from './storage-config.service';
10
10
  import { StorageDataSourceProvider } from './storage-datasource.provider';
11
11
  import { UploadService } from './upload.service';
12
- export declare class FileManagerService extends RequestScopedApiService<CreateFileManagerDto, UpdateFileManagerDto, IFileManager, FileManagerBase> {
12
+ export declare class FileManagerService extends ApiService<CreateFileManagerDto, UpdateFileManagerDto, IFileManager, FileManagerBase> {
13
13
  protected cacheManager: HybridCache;
14
14
  protected utilsService: UtilsService;
15
15
  protected uploadService: UploadService;
@@ -17,7 +17,6 @@ export declare class FileManagerService extends RequestScopedApiService<CreateFi
17
17
  private readonly dataSourceProvider;
18
18
  constructor(cacheManager: HybridCache, utilsService: UtilsService, uploadService: UploadService, storageConfig: StorageConfigService, dataSourceProvider: StorageDataSourceProvider);
19
19
  protected resolveEntity(): EntityTarget<FileManagerBase>;
20
- protected getDataSourceProvider(): StorageDataSourceProvider;
21
20
  convertSingleDtoToEntity(dto: CreateFileManagerDto | UpdateFileManagerDto, user: ILoggedUserInfo | null): Promise<FileManagerBase>;
22
21
  getSelectQuery(query: SelectQueryBuilder<FileManagerBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
23
22
  query: SelectQueryBuilder<FileManager>;
@@ -1,4 +1,4 @@
1
- import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
1
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
2
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { UtilsService } from '@flusys/nestjs-shared/modules';
4
4
  import { EntityTarget, SelectQueryBuilder } from 'typeorm';
@@ -7,14 +7,12 @@ import { Folder, FolderBase } from '../entities';
7
7
  import { IFolder } from '../interfaces';
8
8
  import { StorageConfigService } from './storage-config.service';
9
9
  import { StorageDataSourceProvider } from './storage-datasource.provider';
10
- export declare class FolderService extends RequestScopedApiService<CreateFolderDto, UpdateFolderDto, IFolder, FolderBase> {
10
+ export declare class FolderService extends ApiService<CreateFolderDto, UpdateFolderDto, IFolder, FolderBase> {
11
11
  protected cacheManager: HybridCache;
12
12
  protected utilsService: UtilsService;
13
13
  private readonly storageConfig;
14
- private readonly dataSourceProvider;
15
14
  constructor(cacheManager: HybridCache, utilsService: UtilsService, storageConfig: StorageConfigService, dataSourceProvider: StorageDataSourceProvider);
16
15
  protected resolveEntity(): EntityTarget<FolderBase>;
17
- protected getDataSourceProvider(): StorageDataSourceProvider;
18
16
  convertSingleDtoToEntity(dto: CreateFolderDto | UpdateFolderDto, user: ILoggedUserInfo | null): Promise<FolderBase>;
19
17
  getSelectQuery(query: SelectQueryBuilder<FolderBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
20
18
  query: SelectQueryBuilder<Folder>;
@@ -16,6 +16,4 @@ export declare class StorageDataSourceProvider extends MultiTenantDataSourceServ
16
16
  getEnableCompanyFeatureForTenant(tenant?: ITenantDatabaseConfig): boolean;
17
17
  getStorageEntities(enableCompanyFeature?: boolean): Promise<any[]>;
18
18
  protected createDataSourceFromConfig(config: IDatabaseConfig): Promise<DataSource>;
19
- protected getSingleDataSource(): Promise<DataSource>;
20
- protected getOrCreateTenantConnection(tenant: ITenantDatabaseConfig): Promise<DataSource>;
21
19
  }
@@ -1,4 +1,4 @@
1
- import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
1
+ import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
2
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { UtilsService } from '@flusys/nestjs-shared/modules';
4
4
  import { EntityTarget, SelectQueryBuilder } from 'typeorm';
@@ -7,14 +7,12 @@ import { StorageConfig, StorageConfigBase } from '../entities';
7
7
  import { IStorageConfig } from '../interfaces';
8
8
  import { StorageConfigService } from './storage-config.service';
9
9
  import { StorageDataSourceProvider } from './storage-datasource.provider';
10
- export declare class StorageProviderConfigService extends RequestScopedApiService<CreateStorageConfigDto, UpdateStorageConfigDto, IStorageConfig, StorageConfigBase> {
10
+ export declare class StorageProviderConfigService extends ApiService<CreateStorageConfigDto, UpdateStorageConfigDto, IStorageConfig, StorageConfigBase> {
11
11
  protected cacheManager: HybridCache;
12
12
  protected utilsService: UtilsService;
13
13
  private readonly storageConfig;
14
- private readonly dataSourceProvider;
15
14
  constructor(cacheManager: HybridCache, utilsService: UtilsService, storageConfig: StorageConfigService, dataSourceProvider: StorageDataSourceProvider);
16
15
  protected resolveEntity(): EntityTarget<StorageConfigBase>;
17
- protected getDataSourceProvider(): StorageDataSourceProvider;
18
16
  convertSingleDtoToEntity(dto: CreateStorageConfigDto | UpdateStorageConfigDto, user: ILoggedUserInfo | null): Promise<StorageConfigBase>;
19
17
  getSelectQuery(query: SelectQueryBuilder<StorageConfigBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
20
18
  query: SelectQueryBuilder<StorageConfig>;