@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
package/fesm/562.js ADDED
@@ -0,0 +1,786 @@
1
+ import * as __rspack_external_sharp from "sharp";
2
+ import * as __rspack_external_path from "path";
3
+ import * as __rspack_external_uuid from "uuid";
4
+ import * as __rspack_external_fs from "fs";
5
+ import * as __rspack_external_mime_types_1e2a4730 from "mime-types";
6
+ import * as __rspack_external_passport from "passport";
7
+ import * as __rspack_external_fs_promises_e1851c9c from "fs/promises";
8
+ export const __rspack_esm_id = 562;
9
+ export const __rspack_esm_ids = [562];
10
+ export const __webpack_modules__ = {
11
+ 969(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
12
+
13
+ // EXPORTS
14
+ __webpack_require__.d(__webpack_exports__, {
15
+ u: () => (/* reexport */ FileServeMiddleware)
16
+ });
17
+
18
+ // EXTERNAL MODULE: external "@nestjs/common"
19
+ var common_ = __webpack_require__(157);
20
+ ;// CONCATENATED MODULE: external "fs"
21
+
22
+ // EXTERNAL MODULE: external "path"
23
+ var external_path_ = __webpack_require__(521);
24
+ ;// CONCATENATED MODULE: external "mime-types"
25
+
26
+ ;// CONCATENATED MODULE: external "passport"
27
+
28
+ // EXTERNAL MODULE: external "@flusys/nestjs-shared/constants"
29
+ var constants_ = __webpack_require__(140);
30
+ // EXTERNAL MODULE: ./projects/nestjs-storage/src/config/message-keys.ts
31
+ var message_keys = __webpack_require__(450);
32
+ // EXTERNAL MODULE: ./projects/nestjs-storage/src/services/upload.service.ts + 1 modules
33
+ var upload_service = __webpack_require__(18);
34
+ ;// CONCATENATED MODULE: ./projects/nestjs-storage/src/middlewares/file-serve.middleware.ts
35
+ function _ts_decorate(decorators, target, key, desc) {
36
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
37
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
38
+ r = Reflect.decorate(decorators, target, key, desc);
39
+ } else {
40
+ for(var i = decorators.length - 1; i >= 0; i--){
41
+ if (d = decorators[i]) {
42
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
43
+ }
44
+ }
45
+ }
46
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
47
+ }
48
+ function _ts_metadata(metadataKey, metadataValue) {
49
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
50
+ return Reflect.metadata(metadataKey, metadataValue);
51
+ }
52
+ }
53
+ function _ts_param(paramIndex, decorator) {
54
+ return function(target, key) {
55
+ decorator(target, key, paramIndex);
56
+ };
57
+ }
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+ /** MIME type prefixes that can be displayed inline in browser */ const VIEWABLE_TYPE_PREFIXES = [
67
+ 'image/',
68
+ 'video/',
69
+ 'audio/',
70
+ 'text/',
71
+ 'application/pdf',
72
+ 'application/json',
73
+ 'application/xml'
74
+ ];
75
+ class FileServeMiddleware {
76
+ uploadService;
77
+ uploadDir = process.cwd();
78
+ constructor(uploadService){
79
+ this.uploadService = uploadService;
80
+ }
81
+ async use(req, res, next) {
82
+ await new Promise((resolvePromise)=>{
83
+ __rspack_external_passport["default"].authenticate('jwt', {
84
+ session: false
85
+ }, (err, user)=>{
86
+ if (err || !user) {
87
+ this.sendErrorResponse(res, new common_.UnauthorizedException({
88
+ message: 'Authentication required',
89
+ messageKey: constants_.AUTH_MESSAGES.TOKEN_INVALID
90
+ }));
91
+ resolvePromise();
92
+ return;
93
+ }
94
+ req.user = user;
95
+ this.serveFile(req, res).finally(resolvePromise);
96
+ })(req, res, next);
97
+ });
98
+ }
99
+ async serveFile(req, res) {
100
+ try {
101
+ const normalizedPath = this.extractFilePath(req);
102
+ const fullPath = await this.resolveFilePath(normalizedPath);
103
+ const stats = (0,__rspack_external_fs.statSync)(fullPath);
104
+ if (!stats.isFile()) {
105
+ throw new common_.NotFoundException({
106
+ message: `Not a file: ${normalizedPath}`,
107
+ messageKey: message_keys/* .FILE_MESSAGES.NOT_FOUND */.uA.NOT_FOUND,
108
+ messageVariables: {
109
+ path: normalizedPath
110
+ }
111
+ });
112
+ }
113
+ const mimeType = this.getMimeType(fullPath);
114
+ this.setResponseHeaders(res, stats.size, mimeType, normalizedPath);
115
+ this.streamFile(res, fullPath, normalizedPath);
116
+ } catch (error) {
117
+ this.sendErrorResponse(res, error);
118
+ }
119
+ }
120
+ /** Extract and validate file path from request URL */ extractFilePath(req) {
121
+ const urlPath = req.path || req.url;
122
+ const match = urlPath.match(/\/storage\/upload\/file\/(.+)/);
123
+ const normalizedPath = match ? match[1] : '';
124
+ if (!normalizedPath) {
125
+ throw new common_.BadRequestException({
126
+ message: 'File path is required',
127
+ messageKey: message_keys/* .UPLOAD_MESSAGES.NO_FILE_PATH */.dS.NO_FILE_PATH
128
+ });
129
+ }
130
+ return normalizedPath;
131
+ }
132
+ /** Resolve file path using multiple fallback strategies */ async resolveFilePath(normalizedPath) {
133
+ // Strategy 1: Path relative to CWD (new format: key includes basePath)
134
+ let fullPath = (0,external_path_.join)(this.uploadDir, normalizedPath);
135
+ const resolvedPath = (0,external_path_.resolve)(fullPath);
136
+ // Prevent path traversal attacks (boundary-safe: avoids matching sibling dirs like uploadDir + '-evil')
137
+ if (resolvedPath !== this.uploadDir && !resolvedPath.startsWith(this.uploadDir + external_path_.sep)) {
138
+ throw new common_.BadRequestException({
139
+ message: 'Invalid file path',
140
+ messageKey: message_keys/* .UPLOAD_MESSAGES.INVALID_FILE_PATH */.dS.INVALID_FILE_PATH
141
+ });
142
+ }
143
+ if ((0,__rspack_external_fs.existsSync)(fullPath)) {
144
+ return fullPath;
145
+ }
146
+ // Try fallback strategies with basePath
147
+ const basePath = await this.uploadService.getLocalStorageBasePath();
148
+ if (basePath) {
149
+ const fallbackPath = this.tryFallbackPaths(normalizedPath, basePath);
150
+ if (fallbackPath) {
151
+ return fallbackPath;
152
+ }
153
+ }
154
+ throw new common_.NotFoundException({
155
+ message: `File not found: ${normalizedPath}`,
156
+ messageKey: message_keys/* .FILE_MESSAGES.NOT_FOUND */.uA.NOT_FOUND,
157
+ messageVariables: {
158
+ path: normalizedPath
159
+ }
160
+ });
161
+ }
162
+ /** Try basePath-based fallback strategies */ tryFallbackPaths(normalizedPath, basePath) {
163
+ const normalizedBasePath = basePath.replace(/^\.\//, '').replace(/\/$/, '');
164
+ const pathStartsWithBase = normalizedPath.startsWith(normalizedBasePath + '/') || normalizedPath.startsWith(normalizedBasePath);
165
+ if (pathStartsWithBase) {
166
+ // Strategy 2: basePath + remaining path
167
+ const remainingPath = normalizedPath.substring(normalizedBasePath.length).replace(/^\//, '');
168
+ const fallbackPath = (0,external_path_.join)(basePath, remainingPath);
169
+ if ((0,__rspack_external_fs.existsSync)(fallbackPath)) return fallbackPath;
170
+ } else {
171
+ // Strategy 3: Old format - prepend basePath
172
+ const fallbackPath = (0,external_path_.join)(basePath, normalizedPath);
173
+ if ((0,__rspack_external_fs.existsSync)(fallbackPath)) return fallbackPath;
174
+ }
175
+ return null;
176
+ }
177
+ /** Get MIME type with SVG special handling */ getMimeType(fullPath) {
178
+ if (fullPath.toLowerCase().endsWith('.svg')) {
179
+ return 'image/svg+xml';
180
+ }
181
+ return __rspack_external_mime_types_1e2a4730.lookup(fullPath) || 'application/octet-stream';
182
+ }
183
+ /** Set response headers for file serving */ setResponseHeaders(res, size, mimeType, normalizedPath) {
184
+ const isViewable = VIEWABLE_TYPE_PREFIXES.some((type)=>mimeType.startsWith(type));
185
+ const filename = normalizedPath.split('/').pop() || 'download';
186
+ const contentDisposition = isViewable ? 'inline' : `attachment; filename="${encodeURIComponent(filename)}"`;
187
+ res.set({
188
+ 'Content-Type': mimeType,
189
+ 'Content-Length': size,
190
+ 'Content-Disposition': contentDisposition,
191
+ 'Cache-Control': 'public, max-age=3600',
192
+ 'Accept-Ranges': 'bytes',
193
+ 'Cross-Origin-Resource-Policy': 'cross-origin',
194
+ 'Access-Control-Allow-Origin': '*',
195
+ 'X-Content-Type-Options': 'nosniff'
196
+ });
197
+ }
198
+ /** Stream file to response with error handling */ streamFile(res, fullPath, normalizedPath) {
199
+ const stream = (0,__rspack_external_fs.createReadStream)(fullPath);
200
+ stream.pipe(res);
201
+ stream.on('error', ()=>{
202
+ if (!res.headersSent) {
203
+ this.sendErrorResponse(res, new common_.NotFoundException({
204
+ message: `Failed to serve file: ${normalizedPath}`,
205
+ messageKey: message_keys/* .FILE_MESSAGES.NOT_FOUND */.uA.NOT_FOUND,
206
+ messageVariables: {
207
+ path: normalizedPath
208
+ }
209
+ }));
210
+ }
211
+ });
212
+ res.on('close', ()=>stream.destroy());
213
+ }
214
+ /** Send consistent error response */ sendErrorResponse(res, error) {
215
+ if (res.headersSent) {
216
+ return;
217
+ }
218
+ const isHttpException = error instanceof common_.NotFoundException || error instanceof common_.BadRequestException || error instanceof common_.UnauthorizedException;
219
+ const response = isHttpException ? error.getResponse() : null;
220
+ const statusCode = isHttpException ? error.getStatus() : 404;
221
+ const message = response?.message ?? 'File not found';
222
+ const messageKey = response?.messageKey ?? message_keys/* .FILE_MESSAGES.NOT_FOUND */.uA.NOT_FOUND;
223
+ const messageVariables = response?.messageVariables;
224
+ res.status(statusCode).json({
225
+ success: false,
226
+ message,
227
+ messageKey,
228
+ messageVariables,
229
+ error: statusCode === 401 ? 'Unauthorized' : statusCode === 400 ? 'Bad Request' : 'Not Found',
230
+ statusCode
231
+ });
232
+ }
233
+ }
234
+ FileServeMiddleware = _ts_decorate([
235
+ (0,common_.Injectable)(),
236
+ _ts_param(0, (0,common_.Inject)(upload_service/* .UploadService */.B)),
237
+ _ts_metadata("design:type", Function),
238
+ _ts_metadata("design:paramtypes", [
239
+ typeof upload_service/* .UploadService */.B === "undefined" ? Object : upload_service/* .UploadService */.B
240
+ ])
241
+ ], FileServeMiddleware);
242
+
243
+ ;// CONCATENATED MODULE: ./projects/nestjs-storage/src/middlewares/index.ts
244
+
245
+
246
+
247
+ },
248
+ 329(module, __webpack_exports__, __webpack_require__) {
249
+ __webpack_require__.a(module, async function (__rspack_load_async_deps, __rspack_async_done) { try {
250
+ /* import */ var _storage_module_js__rspack_import_0 = __webpack_require__(624);
251
+ var __rspack_async_deps = __rspack_load_async_deps([_storage_module_js__rspack_import_0]);
252
+ _storage_module_js__rspack_import_0 = (__rspack_async_deps.then ? (await __rspack_async_deps)() : __rspack_async_deps)[0];
253
+
254
+ __webpack_require__.d(__webpack_exports__, {
255
+ k: () => (/* reexport safe */ _storage_module_js__rspack_import_0.k)
256
+ });
257
+
258
+ __rspack_async_done();
259
+ } catch(e) { __rspack_async_done(e); } });
260
+
261
+ },
262
+ 624(module, __webpack_exports__, __webpack_require__) {
263
+ __webpack_require__.a(module, async function (__rspack_load_async_deps, __rspack_async_done) { try {
264
+ /* import */ var _flusys_nestjs_shared_modules__rspack_import_0 = __webpack_require__(236);
265
+ /* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(157);
266
+ /* import */ var _middlewares_index_js__rspack_import_2 = __webpack_require__(969);
267
+ /* import */ var _services_index_js__rspack_import_3 = __webpack_require__(148);
268
+ /* import */ var _config_storage_constants_js__rspack_import_9 = __webpack_require__(188);
269
+ /* import */ var _controllers_index_js__rspack_import_4 = __webpack_require__(488);
270
+ /* import */ var _enums_file_location_enum_js__rspack_import_8 = __webpack_require__(733);
271
+ /* import */ var _providers_index_js__rspack_import_5 = __webpack_require__(922);
272
+ /* import */ var _providers_local_provider_js__rspack_import_6 = __webpack_require__(632);
273
+ /* import */ var _services_storage_provider_config_service_js__rspack_import_7 = __webpack_require__(623);
274
+ function _ts_decorate(decorators, target, key, desc) {
275
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
276
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
277
+ r = Reflect.decorate(decorators, target, key, desc);
278
+ } else {
279
+ for(var i = decorators.length - 1; i >= 0; i--){
280
+ if (d = decorators[i]) {
281
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
282
+ }
283
+ }
284
+ }
285
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
286
+ }
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+ const logger = new _nestjs_common__rspack_import_1.Logger('StorageModule');
299
+ const CONTROLLERS = [
300
+ _controllers_index_js__rspack_import_4/* .FileManagerController */.AE,
301
+ _controllers_index_js__rspack_import_4/* .FolderController */.X$,
302
+ _controllers_index_js__rspack_import_4/* .StorageConfigController */.Iz,
303
+ _controllers_index_js__rspack_import_4/* .UploadController */.I7
304
+ ];
305
+ const EXPORTED_SERVICES = [
306
+ _services_index_js__rspack_import_3/* .StorageConfigService */.tP,
307
+ _services_index_js__rspack_import_3/* .StorageDataSourceProvider */.M0,
308
+ _services_index_js__rspack_import_3/* .FileManagerService */.DL,
309
+ _services_index_js__rspack_import_3/* .FolderService */.kh,
310
+ _services_storage_provider_config_service_js__rspack_import_7/* .StorageProviderConfigService */.o,
311
+ _services_index_js__rspack_import_3/* .UploadService */.BB,
312
+ _providers_index_js__rspack_import_5/* .StorageFactoryService */.Lk
313
+ ];
314
+ // Register built-in provider
315
+ _providers_index_js__rspack_import_5/* .StorageProviderRegistry.register */.CG.register(_enums_file_location_enum_js__rspack_import_8/* .FileLocationEnum.LOCAL */.N.LOCAL, _providers_local_provider_js__rspack_import_6/* .LocalProvider */.T);
316
+ logger.log('Registered LocalProvider');
317
+ // Register optional providers (skip if dependencies not installed).
318
+ // Each `import()` below MUST stay a literal string, not a variable — a computed
319
+ // specifier can't be statically resolved by Rspack/Webpack ("the request of a
320
+ // dependency is an expression"), which silently drops the dynamic import instead
321
+ // of bundling it, even when the underlying package is installed.
322
+ async function registerOptionalProvider(location, name, dep, loader) {
323
+ try {
324
+ const providerModule = await loader();
325
+ _providers_index_js__rspack_import_5/* .StorageProviderRegistry.register */.CG.register(location, providerModule[name]);
326
+ logger.log(`Registered ${name}`);
327
+ } catch {
328
+ logger.debug(`${name} not available (install ${dep} to enable)`);
329
+ }
330
+ }
331
+ await registerOptionalProvider(_enums_file_location_enum_js__rspack_import_8/* .FileLocationEnum.AWS */.N.AWS, 'S3Provider', '@aws-sdk/client-s3', ()=>__webpack_require__.e(/* import() */ 591).then(__webpack_require__.bind(__webpack_require__, 970)));
332
+ await registerOptionalProvider(_enums_file_location_enum_js__rspack_import_8/* .FileLocationEnum.AZURE */.N.AZURE, 'AzureProvider', '@azure/storage-blob', ()=>__webpack_require__.e(/* import() */ 190).then(__webpack_require__.bind(__webpack_require__, 269)));
333
+ await registerOptionalProvider(_enums_file_location_enum_js__rspack_import_8/* .FileLocationEnum.SFTP */.N.SFTP, 'SftpProvider', 'ssh2-sftp-client', ()=>__webpack_require__.e(/* import() */ 918).then(__webpack_require__.bind(__webpack_require__, 5)));
334
+ class StorageModule {
335
+ configure(consumer) {
336
+ consumer.apply(_middlewares_index_js__rspack_import_2/* .FileServeMiddleware */.u).forRoutes({
337
+ path: 'storage/upload/file/*',
338
+ method: _nestjs_common__rspack_import_1.RequestMethod.GET
339
+ });
340
+ }
341
+ static forRoot(options) {
342
+ return {
343
+ module: StorageModule,
344
+ global: options.global ?? false,
345
+ imports: [
346
+ _flusys_nestjs_shared_modules__rspack_import_0.CacheModule,
347
+ _flusys_nestjs_shared_modules__rspack_import_0.UtilsModule
348
+ ],
349
+ controllers: options.includeController !== false ? CONTROLLERS : [],
350
+ providers: this.buildProviders(options),
351
+ exports: EXPORTED_SERVICES
352
+ };
353
+ }
354
+ static forRootAsync(options) {
355
+ return {
356
+ module: StorageModule,
357
+ global: options.global ?? false,
358
+ imports: [
359
+ ...options.imports || [],
360
+ _flusys_nestjs_shared_modules__rspack_import_0.CacheModule,
361
+ _flusys_nestjs_shared_modules__rspack_import_0.UtilsModule
362
+ ],
363
+ controllers: options.includeController !== false ? CONTROLLERS : [],
364
+ providers: [
365
+ ...this.createAsyncProviders(options),
366
+ ...this.buildProviders()
367
+ ],
368
+ exports: EXPORTED_SERVICES
369
+ };
370
+ }
371
+ // ─── Private Helpers ──────────────────────────────────────────────────────────
372
+ static buildProviders(options) {
373
+ const providers = [
374
+ ...EXPORTED_SERVICES,
375
+ _middlewares_index_js__rspack_import_2/* .FileServeMiddleware */.u
376
+ ];
377
+ if (options) {
378
+ providers.unshift({
379
+ provide: _config_storage_constants_js__rspack_import_9/* .STORAGE_MODULE_OPTIONS */.k0,
380
+ useValue: options
381
+ });
382
+ }
383
+ providers.push((0,_flusys_nestjs_shared_modules__rspack_import_0.createModuleEventsProvider)('storage', _config_storage_constants_js__rspack_import_9/* .STORAGE_MODULE_OPTIONS */.k0));
384
+ return providers;
385
+ }
386
+ static createAsyncProviders(options) {
387
+ if (options.useFactory) {
388
+ return [
389
+ {
390
+ provide: _config_storage_constants_js__rspack_import_9/* .STORAGE_MODULE_OPTIONS */.k0,
391
+ useFactory: async (...args)=>({
392
+ ...options,
393
+ config: await options.useFactory(...args)
394
+ }),
395
+ inject: options.inject || []
396
+ }
397
+ ];
398
+ }
399
+ const factoryClass = options.useClass || options.useExisting;
400
+ if (!factoryClass) return [];
401
+ const providers = [
402
+ {
403
+ provide: _config_storage_constants_js__rspack_import_9/* .STORAGE_MODULE_OPTIONS */.k0,
404
+ useFactory: async (factory)=>({
405
+ ...options,
406
+ config: await factory.createStorageOptions()
407
+ }),
408
+ inject: [
409
+ factoryClass
410
+ ]
411
+ }
412
+ ];
413
+ if (options.useClass) {
414
+ providers.push({
415
+ provide: options.useClass,
416
+ useClass: options.useClass
417
+ });
418
+ }
419
+ return providers;
420
+ }
421
+ }
422
+ StorageModule = _ts_decorate([
423
+ (0,_nestjs_common__rspack_import_1.Module)({})
424
+ ], StorageModule);
425
+
426
+ __webpack_require__.d(__webpack_exports__, {
427
+ k: () => (StorageModule)
428
+ });
429
+
430
+ __rspack_async_done();
431
+ } catch(e) { __rspack_async_done(e); } }, 1);
432
+
433
+ },
434
+ 922(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
435
+ /* import */ var _storage_factory_service_js__rspack_import_0 = __webpack_require__(192);
436
+ /* import */ var _storage_provider_registry_js__rspack_import_1 = __webpack_require__(264);
437
+ /* import */ var _local_provider_js__rspack_import_2 = __webpack_require__(632);
438
+ // Core exports
439
+
440
+
441
+ // Built-in provider (no external dependencies)
442
+ // Note: Optional storage providers are loaded dynamically
443
+ // Import them directly from their files when needed:
444
+ // - import { S3Provider } from '@flusys/nestjs-storage/providers/s3-provider.optional';
445
+ // - import { AzureProvider } from '@flusys/nestjs-storage/providers/azure-provider.optional';
446
+ // - import { SftpProvider } from '@flusys/nestjs-storage/providers/sftp-provider.optional';
447
+
448
+ __webpack_require__.d(__webpack_exports__, {
449
+ CG: () => (/* reexport safe */ _storage_provider_registry_js__rspack_import_1.C),
450
+ Lk: () => (/* reexport safe */ _storage_factory_service_js__rspack_import_0.L),
451
+ TZ: () => (/* reexport safe */ _local_provider_js__rspack_import_2.T)
452
+ });
453
+
454
+
455
+ },
456
+ 632(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
457
+
458
+ // EXPORTS
459
+ __webpack_require__.d(__webpack_exports__, {
460
+ T: () => (/* binding */ LocalProvider)
461
+ });
462
+
463
+ // EXTERNAL MODULE: external "@nestjs/common"
464
+ var common_ = __webpack_require__(157);
465
+ // EXTERNAL MODULE: external "@flusys/nestjs-shared/constants"
466
+ var constants_ = __webpack_require__(140);
467
+ // EXTERNAL MODULE: ./projects/nestjs-storage/src/utils/image-compressor.util.ts + 1 modules
468
+ var image_compressor_util = __webpack_require__(872);
469
+ ;// CONCATENATED MODULE: external "fs/promises"
470
+
471
+ // EXTERNAL MODULE: external "path"
472
+ var external_path_ = __webpack_require__(521);
473
+ // EXTERNAL MODULE: external "uuid"
474
+ var external_uuid_ = __webpack_require__(37);
475
+ ;// CONCATENATED MODULE: ./projects/nestjs-storage/src/providers/local-provider.ts
476
+ /**
477
+ * LOCAL File System Provider
478
+ *
479
+ * This provider uses Node.js built-in 'fs' module - NO external dependencies required!
480
+ * Perfect for same-server storage scenarios.
481
+ *
482
+ * Usage:
483
+ * import { LocalProvider } from '@flusys/nestjs-storage/providers/local-provider';
484
+ * import { StorageProviderRegistry, FileLocationEnum } from '@flusys/nestjs-storage';
485
+ *
486
+ * StorageProviderRegistry.register(FileLocationEnum.LOCAL, LocalProvider);
487
+ */
488
+
489
+
490
+
491
+
492
+
493
+ /**
494
+ * Local File System Storage Provider
495
+ * Uses Node.js built-in fs module - no external dependencies
496
+ */ class LocalProvider {
497
+ basePath = '';
498
+ baseUrl = '';
499
+ relativeBasePath = '';
500
+ /**
501
+ * SECURITY: Validates that a target path does not escape the base directory
502
+ * Prevents path traversal attacks using ../ sequences
503
+ * @throws Error if path traversal is detected
504
+ */ validatePathWithinBase(targetPath) {
505
+ const normalizedBasePath = external_path_.resolve(this.basePath);
506
+ const normalizedTargetPath = external_path_.resolve(targetPath);
507
+ if (!normalizedTargetPath.startsWith(normalizedBasePath + external_path_.sep) && normalizedTargetPath !== normalizedBasePath) {
508
+ throw new common_.BadRequestException({
509
+ message: 'Invalid path: Path traversal attempt detected',
510
+ messageKey: constants_.SYSTEM_MESSAGES.PATH_TRAVERSAL_DETECTED
511
+ });
512
+ }
513
+ }
514
+ /**
515
+ * SECURITY: Validates file key format to prevent malicious input
516
+ * @throws Error if key contains suspicious patterns
517
+ */ validateKeyFormat(key) {
518
+ if (!key || typeof key !== 'string' || key.trim().length === 0) {
519
+ throw new common_.BadRequestException({
520
+ message: 'Invalid file key: empty or invalid',
521
+ messageKey: constants_.SYSTEM_MESSAGES.INVALID_FILE_KEY
522
+ });
523
+ }
524
+ if (key.includes('\0')) {
525
+ throw new common_.BadRequestException({
526
+ message: 'Invalid file key: contains null bytes',
527
+ messageKey: constants_.SYSTEM_MESSAGES.INVALID_FILE_KEY
528
+ });
529
+ }
530
+ }
531
+ /**
532
+ * Initialize Local File System provider with configuration
533
+ * @param config.basePath - Base path for file storage (default: './uploads')
534
+ * @param config.baseUrl - Optional base URL for generating file URLs
535
+ */ async initialize(config) {
536
+ // Store original relative path for key generation
537
+ this.relativeBasePath = config?.basePath || './uploads';
538
+ // Resolve to absolute path for file operations
539
+ this.basePath = external_path_.resolve(this.relativeBasePath);
540
+ this.baseUrl = config?.baseUrl || '';
541
+ // Ensure base directory exists
542
+ await __rspack_external_fs_promises_e1851c9c.mkdir(this.basePath, {
543
+ recursive: true
544
+ });
545
+ }
546
+ async uploadFile(file, options) {
547
+ let processedBuffer = file.buffer;
548
+ let contentType = file.mimetype;
549
+ const fileName = `${(0,external_uuid_.v4)()}-${file.originalname}`;
550
+ // Compress image if needed
551
+ if (options.compress && file.mimetype.startsWith('image/')) {
552
+ const result = await image_compressor_util/* .ImageCompressor.compress */.J.compress(file.buffer, file.mimetype, {
553
+ maxWidth: options.maxWidth,
554
+ maxHeight: options.maxHeight,
555
+ quality: options.quality,
556
+ format: options.format
557
+ });
558
+ processedBuffer = result.buffer;
559
+ contentType = result.format;
560
+ }
561
+ // Build file path
562
+ const folderPath = options.folderPath ? external_path_.join(this.basePath, options.folderPath) : this.basePath;
563
+ // SECURITY: Validate path does not escape base directory
564
+ this.validatePathWithinBase(folderPath);
565
+ const filePath = external_path_.join(folderPath, fileName);
566
+ // SECURITY: Double-check final file path
567
+ this.validatePathWithinBase(filePath);
568
+ // Ensure directory exists
569
+ await __rspack_external_fs_promises_e1851c9c.mkdir(folderPath, {
570
+ recursive: true
571
+ });
572
+ // Write file to disk
573
+ await __rspack_external_fs_promises_e1851c9c.writeFile(filePath, processedBuffer);
574
+ // Generate key that includes the base path (relative to cwd)
575
+ // This makes the key self-contained for serving files
576
+ const relativeKey = external_path_.join(this.relativeBasePath, options.folderPath || '', fileName).replace(/\\/g, '/'); // Normalize path separators
577
+ return {
578
+ name: fileName,
579
+ key: relativeKey,
580
+ size: processedBuffer.length,
581
+ contentType
582
+ };
583
+ }
584
+ async uploadMultipleFiles(files, options) {
585
+ return Promise.all(files.map((file)=>this.uploadFile(file, options)));
586
+ }
587
+ async deleteFile(key) {
588
+ try {
589
+ // SECURITY: Validate key format first
590
+ this.validateKeyFormat(key);
591
+ // Key now includes the basePath, resolve from cwd
592
+ let filePath = external_path_.resolve(key);
593
+ // SECURITY: Validate resolved path is within base directory
594
+ this.validatePathWithinBase(filePath);
595
+ // Check if file exists at the resolved path
596
+ try {
597
+ await __rspack_external_fs_promises_e1851c9c.access(filePath);
598
+ } catch {
599
+ // Fallback: try with basePath prefix (for old keys without basePath)
600
+ const fallbackPath = external_path_.join(this.basePath, key);
601
+ // SECURITY: Validate fallback path as well
602
+ this.validatePathWithinBase(fallbackPath);
603
+ try {
604
+ await __rspack_external_fs_promises_e1851c9c.access(fallbackPath);
605
+ filePath = fallbackPath;
606
+ } catch {
607
+ // File doesn't exist at either location - silent return
608
+ return;
609
+ }
610
+ }
611
+ await __rspack_external_fs_promises_e1851c9c.unlink(filePath);
612
+ } catch (error) {
613
+ // Re-throw security errors
614
+ if (error instanceof Error && error.message.includes('Invalid')) {
615
+ throw error;
616
+ }
617
+ // Silent failure for other errors
618
+ }
619
+ }
620
+ async deleteMultipleFiles(keys) {
621
+ await Promise.all(keys.map((key)=>this.deleteFile(key)));
622
+ }
623
+ async generatePresignedUrl(key, _expiresInSeconds) {
624
+ // Return public URL or relative path
625
+ // Note: Local storage doesn't support true presigned URLs
626
+ // If baseUrl is provided, return full URL with file serving endpoint, otherwise return relative path
627
+ if (this.baseUrl) {
628
+ // Construct URL with the file serving endpoint
629
+ const baseUrlWithoutTrailingSlash = this.baseUrl.replace(/\/$/, '');
630
+ return `${baseUrlWithoutTrailingSlash}/storage/upload/file/${key}`;
631
+ }
632
+ return `/storage/upload/file/${key}`;
633
+ }
634
+ async healthCheck() {
635
+ try {
636
+ await __rspack_external_fs_promises_e1851c9c.access(this.basePath);
637
+ return true;
638
+ } catch {
639
+ return false;
640
+ }
641
+ }
642
+ }
643
+
644
+
645
+ },
646
+ 872(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
647
+
648
+ // EXPORTS
649
+ __webpack_require__.d(__webpack_exports__, {
650
+ J: () => (/* binding */ ImageCompressor)
651
+ });
652
+
653
+ ;// CONCATENATED MODULE: external "sharp"
654
+
655
+ ;// CONCATENATED MODULE: ./projects/nestjs-storage/src/utils/image-compressor.util.ts
656
+
657
+ // Handle ESM/CJS interop - sharp exports differently in each module system
658
+ const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
659
+ /**
660
+ * Image Compression Utility
661
+ * Handles image compression and format conversion using sharp
662
+ */ class ImageCompressor {
663
+ /**
664
+ * Dynamically compresses an image based on its format and provided options.
665
+ * - Preserves original format if not overridden
666
+ * - Adjusts compression settings for each codec
667
+ */ static async compress(buffer, mimetype, options = {}) {
668
+ const { maxWidth = 1280, maxHeight = 1280, quality = 85, format = 'original' } = options;
669
+ // Skip processing for SVG
670
+ if (mimetype === 'image/svg+xml') {
671
+ return {
672
+ buffer,
673
+ format: mimetype
674
+ };
675
+ }
676
+ // Initialize sharp with improved error handling
677
+ const image = sharp(buffer, {
678
+ failOnError: false,
679
+ density: 300
680
+ });
681
+ // Apply initial resize
682
+ image.resize({
683
+ width: maxWidth,
684
+ height: maxHeight,
685
+ fit: 'inside',
686
+ withoutEnlargement: true
687
+ });
688
+ // Determine target format
689
+ let targetFormat = format !== 'original' ? format : mimetype.split('/')[1];
690
+ // Format-specific optimizations
691
+ switch(targetFormat.toLowerCase()){
692
+ case 'jpeg':
693
+ case 'jpg':
694
+ image.jpeg({
695
+ quality,
696
+ mozjpeg: true,
697
+ chromaSubsampling: '4:4:4'
698
+ });
699
+ break;
700
+ case 'png':
701
+ image.png({
702
+ compressionLevel: 9,
703
+ adaptiveFiltering: true,
704
+ palette: true,
705
+ quality,
706
+ colors: 256,
707
+ dither: 1.0
708
+ });
709
+ break;
710
+ case 'webp':
711
+ image.webp({
712
+ quality,
713
+ smartSubsample: true,
714
+ effort: 6,
715
+ lossless: quality === 100
716
+ });
717
+ break;
718
+ case 'avif':
719
+ image.avif({
720
+ quality,
721
+ effort: 6,
722
+ chromaSubsampling: '4:4:4'
723
+ });
724
+ break;
725
+ case 'tiff':
726
+ image.tiff({
727
+ quality,
728
+ compression: 'lzw',
729
+ predictor: 'horizontal',
730
+ pyramid: true
731
+ });
732
+ break;
733
+ case 'gif':
734
+ image.gif({
735
+ colours: 256,
736
+ effort: 10,
737
+ dither: 1
738
+ });
739
+ break;
740
+ case 'jp2':
741
+ image.jp2({
742
+ quality,
743
+ lossless: quality === 100
744
+ });
745
+ break;
746
+ default:
747
+ // Fallback to WebP for best compression/quality ratio
748
+ targetFormat = 'webp';
749
+ image.webp({
750
+ quality,
751
+ smartSubsample: true,
752
+ effort: 6
753
+ });
754
+ break;
755
+ }
756
+ try {
757
+ const compressedBuffer = await image.toBuffer();
758
+ return {
759
+ buffer: compressedBuffer,
760
+ format: `image/${targetFormat}`
761
+ };
762
+ } catch {
763
+ return {
764
+ buffer,
765
+ format: mimetype
766
+ };
767
+ }
768
+ }
769
+ }
770
+
771
+
772
+ },
773
+ 521(module) {
774
+
775
+ module.exports = __rspack_external_path;
776
+
777
+
778
+ },
779
+ 37(module) {
780
+
781
+ module.exports = __rspack_external_uuid;
782
+
783
+
784
+ },
785
+
786
+ };