@flusys/nestjs-storage 7.1.0 → 8.0.0-beta.1

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.
Files changed (202) hide show
  1. package/config/index.d.ts +3 -3
  2. package/controllers/file-manager.controller.d.ts +4 -4
  3. package/controllers/folder.controller.d.ts +2 -2
  4. package/controllers/index.d.ts +4 -4
  5. package/controllers/storage-config.controller.d.ts +2 -2
  6. package/controllers/upload.controller.d.ts +3 -3
  7. package/docs/index.d.ts +1 -1
  8. package/docs/storage-swagger.config.d.ts +2 -2
  9. package/dtos/index.d.ts +4 -4
  10. package/entities/file-manager-with-company.entity.d.ts +2 -2
  11. package/entities/file-manager.entity.d.ts +1 -1
  12. package/entities/folder-with-company.entity.d.ts +1 -1
  13. package/entities/index.d.ts +15 -15
  14. package/entities/storage-config-with-company.entity.d.ts +1 -1
  15. package/enums/index.d.ts +1 -1
  16. package/fesm/493.js +2768 -0
  17. package/fesm/537.js +1157 -0
  18. package/fesm/562.js +786 -0
  19. package/fesm/{providers/azure-provider.optional.js → chunks/190.js} +33 -30
  20. package/fesm/chunks/252.js +12 -0
  21. package/fesm/chunks/327.js +12 -0
  22. package/fesm/chunks/385.js +12 -0
  23. package/fesm/{providers/s3-provider.optional.js → chunks/591.js} +37 -34
  24. package/fesm/chunks/746.js +12 -0
  25. package/fesm/chunks/798.js +12 -0
  26. package/fesm/{providers/sftp-provider.optional.js → chunks/918.js} +35 -31
  27. package/fesm/config/index.js +119 -3
  28. package/fesm/controllers/index.js +16 -4
  29. package/fesm/docs/index.js +206 -1
  30. package/fesm/dtos/index.js +879 -4
  31. package/fesm/entities/index.js +463 -18
  32. package/fesm/enums/index.js +36 -1
  33. package/fesm/index.js +398 -12
  34. package/fesm/interfaces/index.js +19 -5
  35. package/fesm/modules/index.js +16 -1
  36. package/fesm/providers/index.js +364 -3
  37. package/fesm/runtime.js +252 -0
  38. package/fesm/services/index.js +16 -6
  39. package/fesm/utils/index.js +149 -1
  40. package/index.d.ts +11 -11
  41. package/interfaces/file-manager.interface.d.ts +1 -1
  42. package/interfaces/folder.interface.d.ts +1 -1
  43. package/interfaces/index.d.ts +5 -5
  44. package/interfaces/storage-config.interface.d.ts +1 -1
  45. package/interfaces/storage-module-options.interface.d.ts +3 -3
  46. package/interfaces/storage-provider.interface.d.ts +1 -1
  47. package/middlewares/file-serve.middleware.d.ts +4 -3
  48. package/middlewares/index.d.ts +1 -1
  49. package/modules/index.d.ts +1 -1
  50. package/modules/storage.module.d.ts +2 -2
  51. package/package.json +30 -41
  52. package/providers/azure-provider.optional.d.ts +2 -2
  53. package/providers/index.d.ts +3 -3
  54. package/providers/local-provider.d.ts +2 -2
  55. package/providers/s3-provider.optional.d.ts +2 -2
  56. package/providers/sftp-provider.optional.d.ts +2 -2
  57. package/providers/storage-factory.service.d.ts +3 -3
  58. package/providers/storage-provider.registry.d.ts +2 -2
  59. package/services/file-manager.service.d.ts +9 -8
  60. package/services/folder.service.d.ts +6 -6
  61. package/services/index.d.ts +6 -6
  62. package/services/storage-config.service.d.ts +3 -3
  63. package/services/storage-datasource.provider.d.ts +3 -3
  64. package/services/storage-provider-config.service.d.ts +7 -7
  65. package/services/upload.service.d.ts +6 -6
  66. package/utils/image-compressor.util.d.ts +1 -1
  67. package/utils/index.d.ts +1 -1
  68. package/cjs/config/event-actions.js +0 -34
  69. package/cjs/config/index.js +0 -20
  70. package/cjs/config/message-keys.js +0 -46
  71. package/cjs/config/storage.constants.js +0 -28
  72. package/cjs/controllers/file-manager.controller.js +0 -152
  73. package/cjs/controllers/file-manager.controller.spec.js +0 -135
  74. package/cjs/controllers/folder.controller.js +0 -102
  75. package/cjs/controllers/folder.controller.spec.js +0 -86
  76. package/cjs/controllers/index.js +0 -21
  77. package/cjs/controllers/storage-config.controller.js +0 -102
  78. package/cjs/controllers/storage-config.controller.spec.js +0 -85
  79. package/cjs/controllers/upload.controller.js +0 -234
  80. package/cjs/controllers/upload.controller.spec.js +0 -132
  81. package/cjs/docs/index.js +0 -11
  82. package/cjs/docs/storage-swagger.config.js +0 -188
  83. package/cjs/docs/storage-swagger.config.spec.js +0 -72
  84. package/cjs/dtos/file-manager.dto.js +0 -327
  85. package/cjs/dtos/folder.dto.js +0 -105
  86. package/cjs/dtos/index.js +0 -21
  87. package/cjs/dtos/storage-config.dto.js +0 -170
  88. package/cjs/dtos/upload.dto.js +0 -272
  89. package/cjs/entities/file-manager-with-company.entity.js +0 -61
  90. package/cjs/entities/file-manager.entity.js +0 -122
  91. package/cjs/entities/folder-with-company.entity.js +0 -55
  92. package/cjs/entities/folder.entity.js +0 -64
  93. package/cjs/entities/index.js +0 -63
  94. package/cjs/entities/index.spec.js +0 -18
  95. package/cjs/entities/storage-config-with-company.entity.js +0 -51
  96. package/cjs/entities/storage-config.entity.js +0 -96
  97. package/cjs/enums/file-location.enum.js +0 -17
  98. package/cjs/enums/index.js +0 -18
  99. package/cjs/index.js +0 -29
  100. package/cjs/interfaces/file-manager.interface.js +0 -4
  101. package/cjs/interfaces/folder.interface.js +0 -4
  102. package/cjs/interfaces/index.js +0 -22
  103. package/cjs/interfaces/storage-config.interface.js +0 -4
  104. package/cjs/interfaces/storage-module-options.interface.js +0 -4
  105. package/cjs/interfaces/storage-provider.interface.js +0 -4
  106. package/cjs/middlewares/file-serve.middleware.js +0 -241
  107. package/cjs/middlewares/file-serve.middleware.spec.js +0 -211
  108. package/cjs/middlewares/index.js +0 -18
  109. package/cjs/modules/index.js +0 -18
  110. package/cjs/modules/storage.module.js +0 -165
  111. package/cjs/modules/storage.module.spec.js +0 -184
  112. package/cjs/providers/azure-provider.optional.js +0 -155
  113. package/cjs/providers/azure-provider.optional.spec.js +0 -228
  114. package/cjs/providers/index.js +0 -26
  115. package/cjs/providers/local-provider.js +0 -230
  116. package/cjs/providers/local-provider.spec.js +0 -239
  117. package/cjs/providers/s3-provider.optional.js +0 -175
  118. package/cjs/providers/s3-provider.optional.spec.js +0 -243
  119. package/cjs/providers/sftp-provider.optional.js +0 -203
  120. package/cjs/providers/sftp-provider.optional.spec.js +0 -217
  121. package/cjs/providers/storage-factory.service.js +0 -175
  122. package/cjs/providers/storage-factory.service.spec.js +0 -253
  123. package/cjs/providers/storage-provider.registry.js +0 -41
  124. package/cjs/providers/storage-provider.registry.spec.js +0 -67
  125. package/cjs/services/file-manager.service.js +0 -387
  126. package/cjs/services/file-manager.service.spec.js +0 -580
  127. package/cjs/services/folder.service.js +0 -101
  128. package/cjs/services/folder.service.spec.js +0 -167
  129. package/cjs/services/index.js +0 -23
  130. package/cjs/services/storage-config.service.js +0 -129
  131. package/cjs/services/storage-config.service.spec.js +0 -257
  132. package/cjs/services/storage-datasource.provider.js +0 -137
  133. package/cjs/services/storage-datasource.provider.spec.js +0 -217
  134. package/cjs/services/storage-provider-config.service.js +0 -171
  135. package/cjs/services/storage-provider-config.service.spec.js +0 -265
  136. package/cjs/services/upload.service.js +0 -376
  137. package/cjs/services/upload.service.spec.js +0 -426
  138. package/cjs/utils/file-validator.util.js +0 -440
  139. package/cjs/utils/file-validator.util.spec.js +0 -259
  140. package/cjs/utils/image-compressor.util.js +0 -162
  141. package/cjs/utils/image-compressor.util.spec.js +0 -166
  142. package/cjs/utils/index.js +0 -18
  143. package/fesm/config/event-actions.js +0 -13
  144. package/fesm/config/message-keys.js +0 -22
  145. package/fesm/config/storage.constants.js +0 -7
  146. package/fesm/controllers/file-manager.controller.js +0 -142
  147. package/fesm/controllers/file-manager.controller.spec.js +0 -131
  148. package/fesm/controllers/folder.controller.js +0 -92
  149. package/fesm/controllers/folder.controller.spec.js +0 -82
  150. package/fesm/controllers/storage-config.controller.js +0 -92
  151. package/fesm/controllers/storage-config.controller.spec.js +0 -81
  152. package/fesm/controllers/upload.controller.js +0 -224
  153. package/fesm/controllers/upload.controller.spec.js +0 -128
  154. package/fesm/docs/storage-swagger.config.js +0 -181
  155. package/fesm/docs/storage-swagger.config.spec.js +0 -68
  156. package/fesm/dtos/file-manager.dto.js +0 -300
  157. package/fesm/dtos/folder.dto.js +0 -84
  158. package/fesm/dtos/storage-config.dto.js +0 -149
  159. package/fesm/dtos/upload.dto.js +0 -245
  160. package/fesm/entities/file-manager-with-company.entity.js +0 -51
  161. package/fesm/entities/file-manager.entity.js +0 -112
  162. package/fesm/entities/folder-with-company.entity.js +0 -45
  163. package/fesm/entities/folder.entity.js +0 -54
  164. package/fesm/entities/index.spec.js +0 -14
  165. package/fesm/entities/storage-config-with-company.entity.js +0 -41
  166. package/fesm/entities/storage-config.entity.js +0 -86
  167. package/fesm/enums/file-location.enum.js +0 -7
  168. package/fesm/interfaces/file-manager.interface.js +0 -1
  169. package/fesm/interfaces/folder.interface.js +0 -1
  170. package/fesm/interfaces/storage-config.interface.js +0 -1
  171. package/fesm/interfaces/storage-module-options.interface.js +0 -3
  172. package/fesm/interfaces/storage-provider.interface.js +0 -4
  173. package/fesm/middlewares/file-serve.middleware.js +0 -190
  174. package/fesm/middlewares/file-serve.middleware.spec.js +0 -207
  175. package/fesm/middlewares/index.js +0 -1
  176. package/fesm/modules/storage.module.js +0 -156
  177. package/fesm/modules/storage.module.spec.js +0 -180
  178. package/fesm/providers/azure-provider.optional.spec.js +0 -224
  179. package/fesm/providers/local-provider.js +0 -182
  180. package/fesm/providers/local-provider.spec.js +0 -194
  181. package/fesm/providers/s3-provider.optional.spec.js +0 -239
  182. package/fesm/providers/sftp-provider.optional.spec.js +0 -213
  183. package/fesm/providers/storage-factory.service.js +0 -124
  184. package/fesm/providers/storage-factory.service.spec.js +0 -249
  185. package/fesm/providers/storage-provider.registry.js +0 -34
  186. package/fesm/providers/storage-provider.registry.spec.js +0 -63
  187. package/fesm/services/file-manager.service.js +0 -336
  188. package/fesm/services/file-manager.service.spec.js +0 -576
  189. package/fesm/services/folder.service.js +0 -91
  190. package/fesm/services/folder.service.spec.js +0 -163
  191. package/fesm/services/storage-config.service.js +0 -119
  192. package/fesm/services/storage-config.service.spec.js +0 -253
  193. package/fesm/services/storage-datasource.provider.js +0 -86
  194. package/fesm/services/storage-datasource.provider.spec.js +0 -172
  195. package/fesm/services/storage-provider-config.service.js +0 -161
  196. package/fesm/services/storage-provider-config.service.spec.js +0 -261
  197. package/fesm/services/upload.service.js +0 -366
  198. package/fesm/services/upload.service.spec.js +0 -422
  199. package/fesm/utils/file-validator.util.js +0 -433
  200. package/fesm/utils/file-validator.util.spec.js +0 -255
  201. package/fesm/utils/image-compressor.util.js +0 -114
  202. package/fesm/utils/image-compressor.util.spec.js +0 -162
@@ -1,172 +0,0 @@
1
- import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
2
- import { StorageDataSourceProvider } from './storage-datasource.provider';
3
- import * as entities from '../entities';
4
- function buildMockConfigService(overrides = {}) {
5
- const options = {
6
- bootstrapAppConfig: {
7
- databaseMode: 'single',
8
- enableCompanyFeature: false
9
- },
10
- config: {},
11
- ...overrides
12
- };
13
- return {
14
- isCompanyFeatureEnabled: jest.fn().mockReturnValue(options.bootstrapAppConfig?.enableCompanyFeature ?? false),
15
- getOptions: jest.fn().mockReturnValue(options)
16
- };
17
- }
18
- describe('StorageDataSourceProvider', ()=>{
19
- afterEach(()=>{
20
- jest.restoreAllMocks();
21
- });
22
- describe('construction', ()=>{
23
- it('propagates bootstrap options from StorageConfigService into the parent data-source service', ()=>{
24
- const configService = buildMockConfigService({
25
- bootstrapAppConfig: {
26
- databaseMode: 'multi-tenant',
27
- enableCompanyFeature: true
28
- }
29
- });
30
- const provider = new StorageDataSourceProvider(configService);
31
- expect(provider.getDatabaseMode()).toBe('multi-tenant');
32
- expect(provider.isMultiTenant()).toBe(true);
33
- });
34
- it('defaults to single database mode when bootstrap config is absent', ()=>{
35
- const configService = buildMockConfigService({
36
- bootstrapAppConfig: undefined
37
- });
38
- const provider = new StorageDataSourceProvider(configService);
39
- expect(provider.getDatabaseMode()).toBe('single');
40
- expect(provider.isMultiTenant()).toBe(false);
41
- });
42
- });
43
- describe('getEnableCompanyFeatureForTenant', ()=>{
44
- it('uses the tenant-level override when provided', ()=>{
45
- const configService = buildMockConfigService();
46
- const provider = new StorageDataSourceProvider(configService);
47
- const result = provider.getEnableCompanyFeatureForTenant({
48
- id: 'tenant-1',
49
- enableCompanyFeature: true
50
- });
51
- expect(result).toBe(true);
52
- });
53
- it('falls back to global config when tenant has no override', ()=>{
54
- const configService = buildMockConfigService({
55
- bootstrapAppConfig: {
56
- databaseMode: 'single',
57
- enableCompanyFeature: true
58
- }
59
- });
60
- const provider = new StorageDataSourceProvider(configService);
61
- const result = provider.getEnableCompanyFeatureForTenant({
62
- id: 'tenant-1'
63
- });
64
- expect(result).toBe(true);
65
- });
66
- it('falls back to global config when no tenant is provided', ()=>{
67
- const configService = buildMockConfigService({
68
- bootstrapAppConfig: {
69
- databaseMode: 'single',
70
- enableCompanyFeature: false
71
- }
72
- });
73
- const provider = new StorageDataSourceProvider(configService);
74
- expect(provider.getEnableCompanyFeatureForTenant(undefined)).toBe(false);
75
- });
76
- });
77
- describe('getStorageEntities', ()=>{
78
- it('returns company-scoped entities when company feature is enabled', async ()=>{
79
- const configService = buildMockConfigService();
80
- const provider = new StorageDataSourceProvider(configService);
81
- const result = await provider.getStorageEntities(true);
82
- expect(result).toEqual([
83
- entities.FileManagerWithCompany,
84
- entities.FolderWithCompany,
85
- entities.StorageConfigWithCompany
86
- ]);
87
- });
88
- it('returns core entities when company feature is disabled', async ()=>{
89
- const configService = buildMockConfigService();
90
- const provider = new StorageDataSourceProvider(configService);
91
- const result = await provider.getStorageEntities(false);
92
- expect(result).toEqual([
93
- entities.FileManager,
94
- entities.Folder,
95
- entities.StorageConfig
96
- ]);
97
- });
98
- it('falls back to the config service value when no explicit flag is passed', async ()=>{
99
- const configService = buildMockConfigService({
100
- bootstrapAppConfig: {
101
- databaseMode: 'single',
102
- enableCompanyFeature: true
103
- }
104
- });
105
- const provider = new StorageDataSourceProvider(configService);
106
- const result = await provider.getStorageEntities();
107
- expect(result).toEqual([
108
- entities.FileManagerWithCompany,
109
- entities.FolderWithCompany,
110
- entities.StorageConfigWithCompany
111
- ]);
112
- });
113
- });
114
- describe('createDataSourceFromConfig', ()=>{
115
- it('resolves storage entities for the current tenant/config and delegates to the parent implementation', async ()=>{
116
- const configService = buildMockConfigService({
117
- bootstrapAppConfig: {
118
- databaseMode: 'single',
119
- enableCompanyFeature: false
120
- }
121
- });
122
- const provider = new StorageDataSourceProvider(configService);
123
- jest.spyOn(provider, 'getCurrentTenant').mockReturnValue(null);
124
- const superCreateSpy = jest.spyOn(MultiTenantDataSourceService.prototype, 'createDataSourceFromConfig').mockResolvedValue({
125
- isInitialized: true
126
- });
127
- const config = {
128
- type: 'mysql',
129
- host: 'localhost',
130
- port: 3306,
131
- username: 'root',
132
- password: '',
133
- database: 'test'
134
- };
135
- const result = await provider.createDataSourceFromConfig(config);
136
- expect(superCreateSpy).toHaveBeenCalledWith(config, [
137
- entities.FileManager,
138
- entities.Folder,
139
- entities.StorageConfig
140
- ]);
141
- expect(result).toEqual({
142
- isInitialized: true
143
- });
144
- });
145
- it('uses the tenant enableCompanyFeature override to pick company-scoped entities', async ()=>{
146
- const configService = buildMockConfigService({
147
- bootstrapAppConfig: {
148
- databaseMode: 'multi-tenant',
149
- enableCompanyFeature: false
150
- }
151
- });
152
- const provider = new StorageDataSourceProvider(configService);
153
- jest.spyOn(provider, 'getCurrentTenant').mockReturnValue({
154
- id: 'tenant-1',
155
- enableCompanyFeature: true
156
- });
157
- const superCreateSpy = jest.spyOn(MultiTenantDataSourceService.prototype, 'createDataSourceFromConfig').mockResolvedValue({
158
- isInitialized: true
159
- });
160
- const config = {
161
- type: 'mysql',
162
- database: 'tenant_db'
163
- };
164
- await provider.createDataSourceFromConfig(config);
165
- expect(superCreateSpy).toHaveBeenCalledWith(config, [
166
- entities.FileManagerWithCompany,
167
- entities.FolderWithCompany,
168
- entities.StorageConfigWithCompany
169
- ]);
170
- });
171
- });
172
- });
@@ -1,161 +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
- function _ts_metadata(k, v) {
21
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
- }
23
- function _ts_param(paramIndex, decorator) {
24
- return function(target, key) {
25
- decorator(target, key, paramIndex);
26
- };
27
- }
28
- import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
29
- import { UtilsService } from '@flusys/nestjs-shared/modules';
30
- import { applyCompanyFilter, buildCompanyWhereCondition } from '@flusys/nestjs-shared/utils';
31
- import { ForbiddenException, Inject, Injectable, Scope } from '@nestjs/common';
32
- import { In, IsNull } from 'typeorm';
33
- import { STORAGE_CONFIG_MESSAGES, STORAGE_EVENT_ENTITIES, STORAGE_EVENT_MODULE } from '../config';
34
- import { StorageConfig, StorageConfigWithCompany } from '../entities';
35
- import { StorageConfigService } from './storage-config.service';
36
- import { StorageDataSourceProvider } from './storage-datasource.provider';
37
- export class StorageProviderConfigService extends ApiService {
38
- async beforeDeleteOperation(dto, _user, _queryRunner) {
39
- const ids = Array.isArray(dto.id) ? dto.id : [
40
- dto.id
41
- ];
42
- await this.ensureDataSourceRepository();
43
- const defaultConfigs = await this.repository.find({
44
- where: {
45
- id: In(ids),
46
- isDefault: true,
47
- deletedAt: IsNull()
48
- }
49
- });
50
- if (defaultConfigs.length > 0) {
51
- const names = defaultConfigs.map((c)=>c.name).join(', ');
52
- throw new ForbiddenException({
53
- message: `Cannot delete the default storage config(s): ${names}. Set another config as default first.`,
54
- messageKey: STORAGE_CONFIG_MESSAGES.DEFAULT_DELETE_FORBIDDEN,
55
- messageVariables: {
56
- names
57
- }
58
- });
59
- }
60
- }
61
- // ─── Override Methods ───────────────────────────────────────────────────────
62
- async convertSingleDtoToEntity(dto, user) {
63
- const entity = await super.convertSingleDtoToEntity(dto, user);
64
- if (this.storageConfig.isCompanyFeatureEnabled()) {
65
- entity.companyId = user?.companyId ?? null;
66
- }
67
- return entity;
68
- }
69
- async getSelectQuery(query, _user, select) {
70
- if (!select?.length) {
71
- select = [
72
- 'id',
73
- 'name',
74
- 'storage',
75
- 'config',
76
- 'isActive',
77
- 'isDefault',
78
- 'createdAt',
79
- 'updatedAt'
80
- ];
81
- if (this.storageConfig.isCompanyFeatureEnabled()) {
82
- select.push('companyId');
83
- }
84
- }
85
- query.select(select.map((f)=>`${this.entityName}.${f}`));
86
- return {
87
- query,
88
- isRaw: false
89
- };
90
- }
91
- async getExtraManipulateQuery(query, filterDto, user) {
92
- const result = await super.getExtraManipulateQuery(query, filterDto, user);
93
- applyCompanyFilter(query, {
94
- isCompanyFeatureEnabled: this.storageConfig.isCompanyFeatureEnabled(),
95
- entityAlias: 'storageConfig'
96
- }, user);
97
- query.orderBy(`${this.entityName}.createdAt`, 'DESC');
98
- return result;
99
- }
100
- async findByIdDirect(id) {
101
- await this.ensureDataSourceRepository();
102
- return await this.repository.findOne({
103
- where: {
104
- id
105
- }
106
- });
107
- }
108
- async getDefaultConfig(user) {
109
- await this.ensureDataSourceRepository();
110
- const baseWhere = buildCompanyWhereCondition({
111
- isActive: true
112
- }, this.storageConfig.isCompanyFeatureEnabled(), user);
113
- const defaultConfig = await this.repository.findOne({
114
- where: {
115
- ...baseWhere,
116
- isDefault: true
117
- },
118
- order: {
119
- createdAt: 'ASC'
120
- }
121
- });
122
- if (defaultConfig) {
123
- return defaultConfig;
124
- }
125
- return await this.repository.findOne({
126
- where: baseWhere,
127
- order: {
128
- createdAt: 'ASC'
129
- }
130
- });
131
- }
132
- async getConfigByType(storage, user) {
133
- await this.ensureDataSourceRepository();
134
- const where = buildCompanyWhereCondition({
135
- storage,
136
- isActive: true
137
- }, this.storageConfig.isCompanyFeatureEnabled(), user);
138
- return await this.repository.find({
139
- where
140
- });
141
- }
142
- constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
143
- super(STORAGE_EVENT_ENTITIES.STORAGE_CONFIG, cacheManager, utilsService, StorageProviderConfigService.name, true, STORAGE_EVENT_MODULE, dataSourceProvider, storageConfig.isCompanyFeatureEnabled() ? StorageConfigWithCompany : StorageConfig), _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;
144
- }
145
- }
146
- StorageProviderConfigService = _ts_decorate([
147
- Injectable({
148
- scope: Scope.REQUEST
149
- }),
150
- _ts_param(0, Inject('CACHE_INSTANCE')),
151
- _ts_param(1, Inject(UtilsService)),
152
- _ts_param(2, Inject(StorageConfigService)),
153
- _ts_param(3, Inject(StorageDataSourceProvider)),
154
- _ts_metadata("design:type", Function),
155
- _ts_metadata("design:paramtypes", [
156
- typeof HybridCache === "undefined" ? Object : HybridCache,
157
- typeof UtilsService === "undefined" ? Object : UtilsService,
158
- typeof StorageConfigService === "undefined" ? Object : StorageConfigService,
159
- typeof StorageDataSourceProvider === "undefined" ? Object : StorageDataSourceProvider
160
- ])
161
- ], StorageProviderConfigService);
@@ -1,261 +0,0 @@
1
- import { Test } from '@nestjs/testing';
2
- import { UtilsService } from '@flusys/nestjs-shared/modules';
3
- import { createMockDataSourceProvider, createMockRepository } from '@test-utils/mocks/repository.mock';
4
- import { buildMockUser } from '@test-utils/mocks/logged-user.mock';
5
- import { StorageProviderConfigService } from './storage-provider-config.service';
6
- import { StorageConfigService } from './storage-config.service';
7
- import { StorageDataSourceProvider } from './storage-datasource.provider';
8
- import { StorageConfig, StorageConfigWithCompany } from '../entities';
9
- function buildStorageConfig(overrides = {}) {
10
- return {
11
- id: 'config-uuid-1',
12
- name: 'Default Local',
13
- storage: 'local',
14
- config: {
15
- basePath: './uploads'
16
- },
17
- isActive: true,
18
- isDefault: false,
19
- createdAt: new Date(),
20
- updatedAt: new Date(),
21
- deletedAt: null,
22
- createdById: null,
23
- updatedById: null,
24
- deletedById: null,
25
- ...overrides
26
- };
27
- }
28
- describe('StorageProviderConfigService', ()=>{
29
- let service;
30
- let module;
31
- let mockRepo;
32
- let mockStorageConfig;
33
- beforeEach(async ()=>{
34
- mockRepo = createMockRepository();
35
- const mockDataSourceProvider = createMockDataSourceProvider(mockRepo);
36
- mockStorageConfig = {
37
- isCompanyFeatureEnabled: jest.fn().mockReturnValue(false),
38
- getAppUrl: jest.fn().mockReturnValue('http://localhost:2002')
39
- };
40
- module = await Test.createTestingModule({
41
- providers: [
42
- StorageProviderConfigService,
43
- {
44
- provide: 'CACHE_INSTANCE',
45
- useValue: {}
46
- },
47
- {
48
- provide: UtilsService,
49
- useValue: {}
50
- },
51
- {
52
- provide: StorageConfigService,
53
- useValue: mockStorageConfig
54
- },
55
- {
56
- provide: StorageDataSourceProvider,
57
- useValue: mockDataSourceProvider
58
- }
59
- ]
60
- }).compile();
61
- service = await module.resolve(StorageProviderConfigService);
62
- });
63
- describe('entity selection', ()=>{
64
- it('uses StorageConfig when the company feature is disabled', async ()=>{
65
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(false);
66
- const built = await module.resolve(StorageProviderConfigService);
67
- expect(built['_entity']).toBe(StorageConfig);
68
- });
69
- it('uses StorageConfigWithCompany when the company feature is enabled', async ()=>{
70
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
71
- const built = await module.resolve(StorageProviderConfigService);
72
- expect(built['_entity']).toBe(StorageConfigWithCompany);
73
- });
74
- });
75
- describe('convertSingleDtoToEntity', ()=>{
76
- beforeEach(async ()=>{
77
- mockRepo.create.mockReturnValue({});
78
- await service.ensureDataSourceRepository();
79
- });
80
- it('does not attach companyId when the company feature is disabled', async ()=>{
81
- const entity = await service.convertSingleDtoToEntity({
82
- name: 'AWS S3',
83
- storage: 'aws',
84
- config: {}
85
- }, buildMockUser());
86
- expect(entity.companyId).toBeUndefined();
87
- });
88
- it('attaches the current user companyId when the company feature is enabled', async ()=>{
89
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
90
- const entity = await service.convertSingleDtoToEntity({
91
- name: 'AWS S3',
92
- storage: 'aws',
93
- config: {}
94
- }, buildMockUser({
95
- companyId: 'company-42'
96
- }));
97
- expect(entity.companyId).toBe('company-42');
98
- });
99
- it('defaults companyId to null when company feature is enabled but user has none', async ()=>{
100
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
101
- const entity = await service.convertSingleDtoToEntity({
102
- name: 'AWS S3',
103
- storage: 'aws',
104
- config: {}
105
- }, null);
106
- expect(entity.companyId).toBeNull();
107
- });
108
- });
109
- describe('getSelectQuery', ()=>{
110
- it('selects the default field set when none is provided', async ()=>{
111
- const query = {
112
- select: jest.fn().mockReturnThis()
113
- };
114
- await service.getSelectQuery(query, buildMockUser());
115
- expect(query.select).toHaveBeenCalledWith([
116
- 'storageConfig.id',
117
- 'storageConfig.name',
118
- 'storageConfig.storage',
119
- 'storageConfig.config',
120
- 'storageConfig.isActive',
121
- 'storageConfig.isDefault',
122
- 'storageConfig.createdAt',
123
- 'storageConfig.updatedAt'
124
- ]);
125
- });
126
- it('adds companyId to the default select list when company feature is enabled', async ()=>{
127
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
128
- const query = {
129
- select: jest.fn().mockReturnThis()
130
- };
131
- await service.getSelectQuery(query, buildMockUser());
132
- const selected = query.select.mock.calls[0][0];
133
- expect(selected).toContain('storageConfig.companyId');
134
- });
135
- it('respects an explicitly provided select list', async ()=>{
136
- const query = {
137
- select: jest.fn().mockReturnThis()
138
- };
139
- await service.getSelectQuery(query, buildMockUser(), [
140
- 'id',
141
- 'name'
142
- ]);
143
- expect(query.select).toHaveBeenCalledWith([
144
- 'storageConfig.id',
145
- 'storageConfig.name'
146
- ]);
147
- });
148
- });
149
- describe('findByIdDirect', ()=>{
150
- it('bypasses company filtering and returns the raw entity by id', async ()=>{
151
- const config = buildStorageConfig();
152
- mockRepo.findOne.mockResolvedValue(config);
153
- const result = await service.findByIdDirect('config-uuid-1');
154
- expect(mockRepo.findOne).toHaveBeenCalledWith({
155
- where: {
156
- id: 'config-uuid-1'
157
- }
158
- });
159
- expect(result).toEqual(config);
160
- });
161
- it('returns null when no config exists for the given id', async ()=>{
162
- mockRepo.findOne.mockResolvedValue(null);
163
- const result = await service.findByIdDirect('missing-id');
164
- expect(result).toBeNull();
165
- });
166
- });
167
- describe('getDefaultConfig', ()=>{
168
- it('returns the config explicitly flagged isDefault when one exists', async ()=>{
169
- const defaultConfig = buildStorageConfig({
170
- id: 'default-1',
171
- isDefault: true
172
- });
173
- mockRepo.findOne.mockResolvedValueOnce(defaultConfig);
174
- const result = await service.getDefaultConfig(buildMockUser());
175
- expect(result).toEqual(defaultConfig);
176
- expect(mockRepo.findOne).toHaveBeenCalledTimes(1);
177
- });
178
- it('falls back to the oldest active config when no default is flagged', async ()=>{
179
- const fallbackConfig = buildStorageConfig({
180
- id: 'fallback-1'
181
- });
182
- mockRepo.findOne.mockResolvedValueOnce(null).mockResolvedValueOnce(fallbackConfig);
183
- const result = await service.getDefaultConfig(buildMockUser());
184
- expect(result).toEqual(fallbackConfig);
185
- expect(mockRepo.findOne).toHaveBeenCalledTimes(2);
186
- });
187
- it('returns null when there is no default and no active config at all', async ()=>{
188
- mockRepo.findOne.mockResolvedValue(null);
189
- const result = await service.getDefaultConfig(buildMockUser());
190
- expect(result).toBeNull();
191
- });
192
- it('scopes the query to the user company when company feature is enabled', async ()=>{
193
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
194
- mockRepo.findOne.mockResolvedValue(null);
195
- await service.getDefaultConfig(buildMockUser({
196
- companyId: 'company-9'
197
- }));
198
- expect(mockRepo.findOne).toHaveBeenCalledWith(expect.objectContaining({
199
- where: expect.objectContaining({
200
- companyId: 'company-9',
201
- isActive: true
202
- })
203
- }));
204
- });
205
- });
206
- describe('getConfigByType', ()=>{
207
- it('returns active configs matching the requested storage type', async ()=>{
208
- const localConfigs = [
209
- buildStorageConfig({
210
- storage: 'local'
211
- })
212
- ];
213
- mockRepo.find.mockResolvedValue(localConfigs);
214
- const result = await service.getConfigByType('local', buildMockUser());
215
- expect(mockRepo.find).toHaveBeenCalledWith({
216
- where: {
217
- storage: 'local',
218
- isActive: true
219
- }
220
- });
221
- expect(result).toEqual(localConfigs);
222
- });
223
- it('scopes the lookup to the current company when company feature is enabled', async ()=>{
224
- mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
225
- mockRepo.find.mockResolvedValue([]);
226
- await service.getConfigByType('aws', buildMockUser({
227
- companyId: 'company-5'
228
- }));
229
- expect(mockRepo.find).toHaveBeenCalledWith({
230
- where: {
231
- storage: 'aws',
232
- isActive: true,
233
- companyId: 'company-5'
234
- }
235
- });
236
- });
237
- it('returns an empty array when no configs match', async ()=>{
238
- mockRepo.find.mockResolvedValue([]);
239
- const result = await service.getConfigByType('azure');
240
- expect(result).toEqual([]);
241
- });
242
- });
243
- describe('beforeDeleteOperation', ()=>{
244
- it('rejects deleting the default storage config', async ()=>{
245
- mockRepo.find.mockResolvedValue([
246
- buildStorageConfig({
247
- isDefault: true
248
- })
249
- ]);
250
- await expect(service.beforeDeleteOperation({
251
- id: 'config-uuid-1'
252
- }, null, {})).rejects.toThrow('Cannot delete the default storage config');
253
- });
254
- it('allows deleting a non-default storage config', async ()=>{
255
- mockRepo.find.mockResolvedValue([]);
256
- await expect(service.beforeDeleteOperation({
257
- id: 'config-uuid-1'
258
- }, null, {})).resolves.toBeUndefined();
259
- });
260
- });
261
- });