xypriss 2.2.1 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -226,51 +226,106 @@ app.get(
226
226
 
227
227
  ## File Upload
228
228
 
229
- XyPriss provides seamless file upload support with full compatibility for multer and other multipart form-data parsers. No additional configuration needed - it works out of the box!
229
+ XyPriss provides powerful file upload support with **automatic error handling** and both class-based and functional APIs. No manual error handling required!
230
230
 
231
- ### Basic File Upload
231
+ ### Quick Start (Class-Based API - Recommended)
232
232
 
233
233
  ```typescript
234
234
  import { createServer } from "xypriss";
235
- import multer from "multer";
235
+ import { FileUploadAPI } from "xypriss";
236
236
 
237
237
  const app = createServer({
238
- server: { port: 3000 },
239
238
  fileUpload: {
239
+ enabled: true,
240
240
  maxFileSize: 5 * 1024 * 1024, // 5MB
241
- allowedMimeTypes: ["image/jpeg", "image/png", "application/pdf"]
242
- }
241
+ allowedMimeTypes: ["image/jpeg", "image/png"],
242
+ },
243
243
  });
244
244
 
245
- const upload = multer({ storage: multer.memoryStorage() });
246
-
247
- app.post("/upload", upload.single("file"), (req, res) => {
248
- if (!req.file) {
249
- return res.status(400).json({ error: "No file uploaded" });
250
- }
245
+ // Initialize file upload API
246
+ const fileUpload = new FileUploadAPI();
247
+ await fileUpload.initialize(app.options.fileUpload);
251
248
 
249
+ app.post("/upload", fileUpload.single("file"), (req, res) => {
250
+ // Automatic error handling - only success code here!
252
251
  res.json({
252
+ success: true,
253
253
  message: "File uploaded successfully",
254
254
  file: {
255
255
  name: req.file.originalname,
256
256
  size: req.file.size,
257
- type: req.file.mimetype
258
- }
257
+ type: req.file.mimetype,
258
+ },
259
+ });
260
+ });
261
+
262
+ app.start();
263
+ ```
264
+
265
+ ### Functional API (Simple)
266
+
267
+ ```typescript
268
+ import { createServer } from "xypriss";
269
+ import { uploadSingle } from "xypriss";
270
+
271
+ const app = createServer({
272
+ fileUpload: {
273
+ enabled: true,
274
+ maxFileSize: 5 * 1024 * 1024, // 5MB
275
+ storage: "memory",
276
+ },
277
+ });
278
+
279
+ app.post("/upload", uploadSingle("file"), (req, res) => {
280
+ // Automatic error handling - no try/catch needed!
281
+ res.json({
282
+ success: true,
283
+ file: req.file,
259
284
  });
260
285
  });
261
286
 
262
287
  app.start();
263
288
  ```
264
289
 
290
+ ### Automatic Error Responses
291
+
292
+ **File Too Large:**
293
+
294
+ ```json
295
+ {
296
+ "success": false,
297
+ "error": "File too large",
298
+ "message": "File size exceeds the maximum limit of 1.00MB",
299
+ "details": {
300
+ "maxSize": 1048576,
301
+ "maxSizeMB": "1.00",
302
+ "fileSize": "unknown"
303
+ }
304
+ }
305
+ ```
306
+
307
+ **File Type Not Allowed:**
308
+
309
+ ```json
310
+ {
311
+ "success": false,
312
+ "error": "File type not allowed",
313
+ "message": "File type 'application/exe' not allowed. Allowed types: image/jpeg, image/png"
314
+ }
315
+ ```
316
+
265
317
  ### Features
266
318
 
267
- - **Zero Configuration**: Works with existing multer code without changes
268
- - **Security**: Built-in file validation, virus scanning, and sanitization
269
- - **Flexible Storage**: Memory, disk, or cloud storage options
270
- - **Type Safety**: Full TypeScript support with proper type definitions
271
- - **Performance**: Optimized for large file uploads with streaming support
319
+ - ✅ **Automatic Error Handling**: Multer errors converted to user-friendly JSON responses
320
+ - ✅ **Class-Based API**: Modern `FileUploadAPI` class for better organization
321
+ - ✅ **Legacy Compatibility**: Functional API still available for simple use cases
322
+ - ✅ **Multipart Support**: Fixed multipart/form-data handling (no more "Unexpected end of form" errors)
323
+ - ✅ **Security**: Built-in file validation, type checking, and size limits
324
+ - ✅ **Flexible Storage**: Memory, disk, or custom storage backends
325
+ - ✅ **Type Safety**: Full TypeScript support with proper type definitions
326
+ - ✅ **Performance**: Optimized for large file uploads with streaming support
272
327
 
273
- For detailed configuration options, see the [File Upload Documentation](./docs/file-upload.md).
328
+ For comprehensive documentation, configuration options, and advanced usage, see the [File Upload Guide](./docs/file-upload.md).
274
329
 
275
330
  ---
276
331
 
@@ -291,17 +346,17 @@ const app = createServer({
291
346
  id: "api-server",
292
347
  port: 3001,
293
348
  routePrefix: "/api",
294
- allowedRoutes: ["/api/*"]
349
+ allowedRoutes: ["/api/*"],
295
350
  },
296
351
  {
297
352
  id: "admin-server",
298
353
  port: 3002,
299
354
  routePrefix: "/admin",
300
355
  allowedRoutes: ["/admin/*"],
301
- security: { level: "maximum" }
302
- }
303
- ]
304
- }
356
+ security: { level: "maximum" },
357
+ },
358
+ ],
359
+ },
305
360
  });
306
361
 
307
362
  // Routes are automatically distributed to appropriate servers
@@ -314,11 +369,11 @@ await app.startAllServers();
314
369
 
315
370
  ### Features
316
371
 
317
- - **Simple API**: `startAllServers()` and `stopAllServers()` hide complexity
318
- - **Automatic Route Distribution**: Routes are filtered and distributed automatically
319
- - **Server-Specific Overrides**: Each server can have different security, cache, and performance settings
320
- - **Microservices Ready**: Perfect for API versioning and service separation
321
- - **Load Balancing**: Built-in support for reverse proxy load balancing
372
+ - **Simple API**: `startAllServers()` and `stopAllServers()` hide complexity
373
+ - **Automatic Route Distribution**: Routes are filtered and distributed automatically
374
+ - **Server-Specific Overrides**: Each server can have different security, cache, and performance settings
375
+ - **Microservices Ready**: Perfect for API versioning and service separation
376
+ - **Load Balancing**: Built-in support for reverse proxy load balancing
322
377
 
323
378
  For comprehensive multi-server documentation, see the [Multi-Server Guide](./docs/multi-server.md).
324
379
 
@@ -0,0 +1,311 @@
1
+ 'use strict';
2
+
3
+ var FileUploadManager = require('./server/components/fastapi/FileUploadManager.js');
4
+
5
+ /**
6
+ * XyPriss File Upload API
7
+ *
8
+ * This module provides file upload middleware functions that can be used
9
+ * independently of the app instance initialization timing.
10
+ *
11
+ * Usage:
12
+ * ```typescript
13
+ * import { FileUploadAPI } from 'xypriss';
14
+ *
15
+ * const fileUpload = new FileUploadAPI();
16
+ * router.post('/upload', fileUpload.single('file'), (req, res) => {
17
+ * console.log(req.file);
18
+ * res.json({ success: true });
19
+ * });
20
+ * ```
21
+ */
22
+ /**
23
+ * File Upload API Class
24
+ * Provides a clean, class-based interface for file upload middleware
25
+ */
26
+ class FileUploadAPI {
27
+ constructor(logger) {
28
+ this.manager = null;
29
+ this.initialized = false;
30
+ // Use a default logger if none provided
31
+ this.logger =
32
+ logger ||
33
+ {
34
+ debug: console.debug.bind(console),
35
+ info: console.info.bind(console),
36
+ warn: console.warn.bind(console),
37
+ error: console.error.bind(console),
38
+ };
39
+ }
40
+ /**
41
+ * Initialize the file upload API with configuration
42
+ */
43
+ async initialize(options) {
44
+ if (this.initialized) {
45
+ return; // Already initialized
46
+ }
47
+ try {
48
+ this.logger.debug("server", "Initializing FileUploadAPI...");
49
+ this.manager = new FileUploadManager.FileUploadManager(options, this.logger);
50
+ await this.manager.initialize();
51
+ this.initialized = true;
52
+ this.logger.debug("server", `FileUploadAPI initialized, enabled: ${this.manager.isEnabled()}`);
53
+ }
54
+ catch (error) {
55
+ this.logger.error("server", "Failed to initialize FileUploadAPI:", error.message);
56
+ throw error;
57
+ }
58
+ }
59
+ /**
60
+ * Check if the file upload API is enabled
61
+ */
62
+ isEnabled() {
63
+ return this.manager?.isEnabled() === true;
64
+ }
65
+ /**
66
+ * Handle multer errors and convert them to proper HTTP responses
67
+ */
68
+ handleMulterError(err, req, res) {
69
+ if (err.code === "LIMIT_FILE_SIZE") {
70
+ const maxSize = this.manager?.getConfig()?.maxFileSize || 1024 * 1024;
71
+ const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2);
72
+ res.status(400).json({
73
+ success: false,
74
+ error: "File too large",
75
+ message: `File size exceeds the maximum limit of ${maxSizeMB}MB`,
76
+ details: {
77
+ maxSize,
78
+ maxSizeMB,
79
+ fileSize: req.file ? req.file.size : "unknown",
80
+ },
81
+ });
82
+ return;
83
+ }
84
+ if (err.code === "LIMIT_UNEXPECTED_FILE") {
85
+ res.status(400).json({
86
+ success: false,
87
+ error: "Unexpected field",
88
+ message: "Unexpected file field name",
89
+ });
90
+ return;
91
+ }
92
+ if (err.code === "LIMIT_FILE_COUNT") {
93
+ res.status(400).json({
94
+ success: false,
95
+ error: "Too many files",
96
+ message: "Too many files uploaded",
97
+ });
98
+ return;
99
+ }
100
+ // Handle custom file filter errors
101
+ if (err.message) {
102
+ if (err.message.includes("File too large")) {
103
+ res.status(400).json({
104
+ success: false,
105
+ error: "File too large",
106
+ message: err.message,
107
+ });
108
+ return;
109
+ }
110
+ if (err.message.includes("not allowed")) {
111
+ res.status(400).json({
112
+ success: false,
113
+ error: "File type not allowed",
114
+ message: err.message,
115
+ });
116
+ return;
117
+ }
118
+ }
119
+ // Generic multer error
120
+ res.status(400).json({
121
+ success: false,
122
+ error: "Upload error",
123
+ message: err.message || "An error occurred during file upload",
124
+ });
125
+ }
126
+ /**
127
+ * Create a middleware for uploading a single file
128
+ *
129
+ * @param fieldname - The name of the form field containing the file
130
+ * @returns Express middleware function
131
+ */
132
+ single(fieldname) {
133
+ return (req, res, next) => {
134
+ if (!this.isEnabled()) {
135
+ return res.status(500).json({
136
+ success: false,
137
+ error: "Configuration Error",
138
+ message: "File upload not enabled. Set fileUpload.enabled to true in server options.",
139
+ });
140
+ }
141
+ // Use multer middleware with built-in error handling
142
+ this.manager.single(fieldname)(req, res, (err) => {
143
+ if (err) {
144
+ this.handleMulterError(err, req, res);
145
+ }
146
+ else {
147
+ next();
148
+ }
149
+ });
150
+ };
151
+ }
152
+ /**
153
+ * Create a middleware for uploading multiple files with the same field name
154
+ *
155
+ * @param fieldname - The name of the form field containing the files
156
+ * @param maxCount - Maximum number of files to accept (optional)
157
+ * @returns Express middleware function
158
+ */
159
+ array(fieldname, maxCount) {
160
+ return (req, res, next) => {
161
+ if (!this.isEnabled()) {
162
+ return res.status(500).json({
163
+ success: false,
164
+ error: "Configuration Error",
165
+ message: "File upload not enabled. Set fileUpload.enabled to true in server options.",
166
+ });
167
+ }
168
+ this.manager.array(fieldname, maxCount)(req, res, (err) => {
169
+ if (err) {
170
+ this.handleMulterError(err, req, res);
171
+ }
172
+ else {
173
+ next();
174
+ }
175
+ });
176
+ };
177
+ }
178
+ /**
179
+ * Create a middleware for uploading multiple files with different field names
180
+ *
181
+ * @param fields - Array of field configurations
182
+ * @returns Express middleware function
183
+ */
184
+ fields(fields) {
185
+ return (req, res, next) => {
186
+ if (!this.isEnabled()) {
187
+ return res.status(500).json({
188
+ success: false,
189
+ error: "Configuration Error",
190
+ message: "File upload not enabled. Set fileUpload.enabled to true in server options.",
191
+ });
192
+ }
193
+ this.manager.fields(fields)(req, res, (err) => {
194
+ if (err) {
195
+ this.handleMulterError(err, req, res);
196
+ }
197
+ else {
198
+ next();
199
+ }
200
+ });
201
+ };
202
+ }
203
+ /**
204
+ * Create a middleware for uploading any files (accepts all files)
205
+ *
206
+ * @returns Express middleware function
207
+ */
208
+ any() {
209
+ return (req, res, next) => {
210
+ if (!this.isEnabled()) {
211
+ return res.status(500).json({
212
+ success: false,
213
+ error: "Configuration Error",
214
+ message: "File upload not enabled. Set fileUpload.enabled to true in server options.",
215
+ });
216
+ }
217
+ this.manager.any()(req, res, (err) => {
218
+ if (err) {
219
+ this.handleMulterError(err, req, res);
220
+ }
221
+ else {
222
+ next();
223
+ }
224
+ });
225
+ };
226
+ }
227
+ }
228
+ // Legacy function exports for backward compatibility
229
+ // These will be deprecated in favor of the class-based API
230
+ // Global instance for backward compatibility
231
+ let globalFileUploadAPI = null;
232
+ /**
233
+ * Initialize the global file upload manager (legacy)
234
+ * This is called automatically when the server starts with file upload enabled
235
+ */
236
+ function initializeFileUpload(options, logger) {
237
+ if (!globalFileUploadAPI) {
238
+ globalFileUploadAPI = new FileUploadAPI(logger);
239
+ }
240
+ globalFileUploadAPI.initialize(options);
241
+ }
242
+ /**
243
+ * Create a middleware for uploading a single file (legacy)
244
+ */
245
+ function uploadSingle(fieldname) {
246
+ return (req, res, next) => {
247
+ if (!globalFileUploadAPI) {
248
+ return res.status(500).json({
249
+ success: false,
250
+ error: "Configuration Error",
251
+ message: "File upload not initialized. Make sure fileUpload.enabled is true in server options.",
252
+ });
253
+ }
254
+ return globalFileUploadAPI.single(fieldname)(req, res, next);
255
+ };
256
+ }
257
+ /**
258
+ * Create a middleware for uploading multiple files with the same field name (legacy)
259
+ */
260
+ function uploadArray(fieldname, maxCount) {
261
+ return (req, res, next) => {
262
+ if (!globalFileUploadAPI) {
263
+ return res.status(500).json({
264
+ success: false,
265
+ error: "Configuration Error",
266
+ message: "File upload not initialized. Make sure fileUpload.enabled is true in server options.",
267
+ });
268
+ }
269
+ return globalFileUploadAPI.array(fieldname, maxCount)(req, res, next);
270
+ };
271
+ }
272
+ /**
273
+ * Create a middleware for uploading multiple files with different field names (legacy)
274
+ */
275
+ function uploadFields(fields) {
276
+ return (req, res, next) => {
277
+ if (!globalFileUploadAPI) {
278
+ return res.status(500).json({
279
+ success: false,
280
+ error: "Configuration Error",
281
+ message: "File upload not initialized. Make sure fileUpload.enabled is true in server options.",
282
+ });
283
+ }
284
+ return globalFileUploadAPI.fields(fields)(req, res, next);
285
+ };
286
+ }
287
+ /**
288
+ * Create a middleware for uploading any files (legacy)
289
+ */
290
+ function uploadAny() {
291
+ return (req, res, next) => {
292
+ if (!globalFileUploadAPI) {
293
+ return res.status(500).json({
294
+ success: false,
295
+ error: "Configuration Error",
296
+ message: "File upload not initialized. Make sure fileUpload.enabled is true in server options.",
297
+ });
298
+ }
299
+ return globalFileUploadAPI.any()(req, res, next);
300
+ };
301
+ }
302
+ // Export types for TypeScript users
303
+ // Types are available through the main types export
304
+
305
+ exports.FileUploadAPI = FileUploadAPI;
306
+ exports.initializeFileUpload = initializeFileUpload;
307
+ exports.uploadAny = uploadAny;
308
+ exports.uploadArray = uploadArray;
309
+ exports.uploadFields = uploadFields;
310
+ exports.uploadSingle = uploadSingle;
311
+ //# sourceMappingURL=file-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-upload.js","sources":["../../../src/file-upload.ts"],"sourcesContent":[null],"names":["FileUploadManager"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var fileUpload = require('./file-upload.js');
3
4
  var Router$1 = require('./server/routing/Router.js');
4
5
  var ServerFactory = require('./server/ServerFactory.js');
5
6
  var smartRoutes = require('./server/components/fastapi/smart-routes.js');
@@ -65,6 +66,13 @@ function Router() {
65
66
  });
66
67
  }
67
68
 
69
+ exports.FLA = fileUpload.FileUploadAPI;
70
+ exports.FileUploadAPI = fileUpload.FileUploadAPI;
71
+ exports.initializeFileUpload = fileUpload.initializeFileUpload;
72
+ exports.uploadAny = fileUpload.uploadAny;
73
+ exports.uploadArray = fileUpload.uploadArray;
74
+ exports.uploadFields = fileUpload.uploadFields;
75
+ exports.uploadSingle = fileUpload.uploadSingle;
68
76
  exports.XyPrissRouter = Router$1.XyPrissRouter;
69
77
  exports.createCacheMiddleware = ServerFactory.createCacheMiddleware;
70
78
  exports.createServer = ServerFactory.createServer;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":[null],"names":["XyPrissRouter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBiF;AAgCjF;;AAEG;SACa,MAAM,GAAA;IAClB,OAAO,IAAIA,sBAAa,CAAC;AACrB,QAAA,aAAa,EAAE,KAAK;AACpB,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,MAAM,EAAE,KAAK;AAChB,KAAA,CAAC,CAAC;AACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/index.ts"],"sourcesContent":[null],"names":["XyPrissRouter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBiF;AAoCjF;;AAEG;SACa,MAAM,GAAA;IAClB,OAAO,IAAIA,sBAAa,CAAC;AACrB,QAAA,aAAa,EAAE,KAAK;AACpB,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,MAAM,EAAE,KAAK;AAChB,KAAA,CAAC,CAAC;AACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -119,36 +119,62 @@ class XyPrissServer {
119
119
  this.app.uploadSingle = (fieldname) => {
120
120
  // Return a middleware that will be replaced after initialization
121
121
  return async (req, res, next) => {
122
- // If FileUploadManager is initialized, use it
123
- if (this.fileUploadManager?.isEnabled()) {
122
+ // If FileUploadManager is initialized and enabled, use it
123
+ if (this.fileUploadManager && this.fileUploadManager.isEnabled()) {
124
124
  return this.fileUploadManager.single(fieldname)(req, res, next);
125
125
  }
126
- // Otherwise, throw an error
127
- next(new Error("File upload not initialized yet. Make sure fileUpload.enabled is true in server options."));
126
+ // If file upload is configured but not ready yet, wait for initialization
127
+ if (this.options.fileUpload?.enabled) {
128
+ // Wait for initialization to complete
129
+ await this.initPromise;
130
+ if (this.fileUploadManager?.isEnabled()) {
131
+ return this.fileUploadManager.single(fieldname)(req, res, next);
132
+ }
133
+ }
134
+ // File upload not enabled or failed to initialize
135
+ next(new Error("File upload not enabled. Set fileUpload.enabled to true in server options."));
128
136
  };
129
137
  };
130
138
  this.app.uploadArray = (fieldname, maxCount) => {
131
139
  return async (req, res, next) => {
132
- if (this.fileUploadManager?.isEnabled()) {
140
+ if (this.fileUploadManager && this.fileUploadManager.isEnabled()) {
133
141
  return this.fileUploadManager.array(fieldname, maxCount)(req, res, next);
134
142
  }
135
- next(new Error("File upload not initialized yet. Make sure fileUpload.enabled is true in server options."));
143
+ if (this.options.fileUpload?.enabled) {
144
+ await this.initPromise;
145
+ if (this.fileUploadManager?.isEnabled()) {
146
+ return this.fileUploadManager.array(fieldname, maxCount)(req, res, next);
147
+ }
148
+ }
149
+ next(new Error("File upload not enabled. Set fileUpload.enabled to true in server options."));
136
150
  };
137
151
  };
138
152
  this.app.uploadFields = (fields) => {
139
153
  return async (req, res, next) => {
140
- if (this.fileUploadManager?.isEnabled()) {
154
+ if (this.fileUploadManager && this.fileUploadManager.isEnabled()) {
141
155
  return this.fileUploadManager.fields(fields)(req, res, next);
142
156
  }
143
- next(new Error("File upload not initialized yet. Make sure fileUpload.enabled is true in server options."));
157
+ if (this.options.fileUpload?.enabled) {
158
+ await this.initPromise;
159
+ if (this.fileUploadManager?.isEnabled()) {
160
+ return this.fileUploadManager.fields(fields)(req, res, next);
161
+ }
162
+ }
163
+ next(new Error("File upload not enabled. Set fileUpload.enabled to true in server options."));
144
164
  };
145
165
  };
146
166
  this.app.uploadAny = () => {
147
167
  return async (req, res, next) => {
148
- if (this.fileUploadManager?.isEnabled()) {
168
+ if (this.fileUploadManager && this.fileUploadManager.isEnabled()) {
149
169
  return this.fileUploadManager.any()(req, res, next);
150
170
  }
151
- next(new Error("File upload not initialized yet. Make sure fileUpload.enabled is true in server options."));
171
+ if (this.options.fileUpload?.enabled) {
172
+ await this.initPromise;
173
+ if (this.fileUploadManager?.isEnabled()) {
174
+ return this.fileUploadManager.any()(req, res, next);
175
+ }
176
+ }
177
+ next(new Error("File upload not enabled. Set fileUpload.enabled to true in server options."));
152
178
  };
153
179
  };
154
180
  this.app.upload = null; // Will be set after async initialization
@@ -270,10 +296,25 @@ class XyPrissServer {
270
296
  }
271
297
  async initializeDependentComponents() {
272
298
  // Initialize file upload manager
273
- this.logger.debug("server", "Initializing FileUploadManager...");
299
+ this.logger.debug("server", "🔄 Initializing FileUploadManager...");
274
300
  this.fileUploadManager = new FileUploadManager.FileUploadManager(this.options.fileUpload || {}, this.logger);
275
- await this.fileUploadManager.initialize();
276
- this.logger.debug("server", `FileUploadManager initialized, enabled: ${this.fileUploadManager.isEnabled()}`);
301
+ try {
302
+ await this.fileUploadManager.initialize();
303
+ this.logger.debug("server", `✅ FileUploadManager initialized, enabled: ${this.fileUploadManager.isEnabled()}`);
304
+ // Initialize the global file upload API
305
+ if (this.fileUploadManager.isEnabled()) {
306
+ const { initializeFileUpload } = await Promise.resolve().then(function () { return require('../file-upload.js'); });
307
+ initializeFileUpload(this.options.fileUpload || {}, this.logger);
308
+ this.logger.debug("server", "✅ Global file upload API initialized");
309
+ }
310
+ else {
311
+ this.logger.debug("server", "â„šī¸ File upload not enabled, skipping API initialization");
312
+ }
313
+ }
314
+ catch (error) {
315
+ this.logger.error("server", "❌ Failed to initialize FileUploadManager:", error.message);
316
+ throw error;
317
+ }
277
318
  // Add file upload methods to app if enabled
278
319
  if (this.fileUploadManager.isEnabled()) {
279
320
  this.logger.debug("server", "Adding file upload methods to app");