node-server-engine 1.2.9 → 1.3.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 (40) hide show
  1. package/.env.example +4 -1
  2. package/README.md +128 -107
  3. package/dist/entities/Endpoint/Endpoint.d.ts +2 -0
  4. package/dist/entities/Endpoint/Endpoint.js +11 -2
  5. package/dist/entities/Endpoint/Endpoint.js.map +1 -1
  6. package/dist/entities/Endpoint/Endpoint.types.d.ts +3 -0
  7. package/dist/entities/Endpoint/Endpoint.types.js.map +1 -1
  8. package/dist/entities/Server/Server.js +1 -1
  9. package/dist/entities/Server/Server.js.map +1 -1
  10. package/dist/middleware/fileUploader/fileUploader.js +45 -3
  11. package/dist/middleware/fileUploader/fileUploader.js.map +1 -1
  12. package/dist/middleware/multiPartFileUploader/index.d.ts +1 -0
  13. package/dist/middleware/multiPartFileUploader/index.js +11 -0
  14. package/dist/middleware/multiPartFileUploader/index.js.map +1 -1
  15. package/dist/middleware/multiPartFileUploader/multiPartFileUploader.d.ts +4 -3
  16. package/dist/middleware/multiPartFileUploader/multiPartFileUploader.js +169 -105
  17. package/dist/middleware/multiPartFileUploader/multiPartFileUploader.js.map +1 -1
  18. package/dist/middleware/multiPartFileUploader/multiPartFileUploader.types.d.ts +20 -0
  19. package/dist/middleware/multiPartFileUploader/multiPartFileUploader.types.js +2 -0
  20. package/dist/middleware/multiPartFileUploader/multiPartFileUploader.types.js.map +1 -0
  21. package/dist/middleware/multiPartFileUploader/validate/index.d.ts +1 -0
  22. package/dist/middleware/multiPartFileUploader/validate/index.js +17 -0
  23. package/dist/middleware/multiPartFileUploader/validate/index.js.map +1 -0
  24. package/dist/middleware/multiPartFileUploader/validate/validate.d.ts +4 -0
  25. package/dist/middleware/multiPartFileUploader/validate/validate.js +28 -0
  26. package/dist/middleware/multiPartFileUploader/validate/validate.js.map +1 -0
  27. package/dist/utils/index.d.ts +1 -0
  28. package/dist/utils/index.js +11 -11
  29. package/dist/utils/index.js.map +1 -1
  30. package/package.json +3 -1
  31. package/src/entities/Endpoint/Endpoint.ts +22 -3
  32. package/src/entities/Endpoint/Endpoint.types.ts +3 -0
  33. package/src/entities/Server/Server.ts +0 -2
  34. package/src/middleware/fileUploader/fileUploader.ts +51 -2
  35. package/src/middleware/multiPartFileUploader/index.ts +1 -0
  36. package/src/middleware/multiPartFileUploader/multiPartFileUploader.ts +193 -128
  37. package/src/middleware/multiPartFileUploader/multiPartFileUploader.types.ts +23 -0
  38. package/src/middleware/multiPartFileUploader/validate/index.ts +1 -0
  39. package/src/middleware/multiPartFileUploader/validate/validate.ts +27 -0
  40. package/src/utils/index.ts +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Server.js","names":["_fs","_interopRequireDefault","require","_path","_promises","_express","_cors","_ws","_SocketClient","_Server2","_Endpoint","_EngineError","_LifecycleController","_PubSub","_utils","_jwt","_report","_tlsConfig","namespace","Server","exports","config","_classCallCheck2","default","_defineProperty2","AbortController","validate","reportDebug","message","endpoints","globalMiddleware","errorMiddleware","initCallbacks","shutdownCallbacks","syncCallbacks","cron","auth","noFetch","checkEnvironment","process","env","RUN_MIGRATION","UNDO_MIGRATION","SQL_HOST","envAssert","isHost","SQL_USER","isString","SQL_PASSWORD","SQL_DB","NODE_ENV","PORT","isPort","SECONDARY_PORT","app","express","use","cors","origin","CORS_ORIGIN","methods","allowedHeaders","registerMiddleware","httpServer","createHttpServer","secondaryApp","secondaryMiddleware","defaultErrorMiddleware","forEach","middleware","secondaryHttpServer","disable","server","headersTimeout","keepAliveTimeout","webSocket","attachWebSocket","_createClass2","key","value","init","initKeySets","callback","runCallback","Promise","all","map","PubSub","job","runCronJob","resolve","listen","reportInfo","data","port","secondaryPort","nodeEnv","handleSignal","watchTlsCaFileChange","shutdown","listening","address","on","error","reportError","exit","close","wss","clients","socket","socketKillTimeout","WEBSOCKET_CLOSE_TIMEOUT","parseInt","setTimeout","readyState","CLOSING","OPEN","terminate","LifecycleController","shutdownRunningInstances","abortController","abort","shutdownKeySets","shutdownSignals","signal","removeAllListeners","getApp","getSecondaryApp","defaultMiddleware","path","endpoint","register","options","WebSocketServer","request","SocketClient","client","catch","file","fs","watch","event","loadTlsConfig","setSecureContext","tlsConfig","handler","name","interval","setTimeoutPromise","undefined","Error","function","apply","parameters","some","Endpoint","EngineError","Object","values","validator","Array"],"sources":["../../../src/entities/Server/Server.ts"],"sourcesContent":["import fs from 'fs';\nimport http from 'http';\nimport https from 'https';\nimport { AddressInfo } from 'net';\nimport path from 'path';\nimport { setTimeout as setTimeoutPromise } from 'timers/promises';\nimport { ValidatorSpec } from 'envalid';\nimport express, { Application } from 'express';\nimport cors from 'cors';\nimport { Server as WebSocketServer } from 'ws';\nimport { SocketClient } from '../SocketClient';\nimport {\n defaultMiddleware,\n defaultErrorMiddleware,\n secondaryMiddleware,\n shutdownSignals\n} from './Server.const';\nimport {\n ServerOptions,\n ServerCronJon,\n ServerAuthConfig,\n ServerWebSocketConfig,\n ServerGlobalMiddleware,\n ServerErrorMiddleWare,\n ServerCallback\n} from './Server.types';\nimport { Endpoint } from 'entities/Endpoint';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { PubSub } from 'entities/PubSub';\nimport { checkEnvironment, envAssert, createHttpServer } from 'utils';\nimport { initKeySets, shutdownKeySets } from 'utils/jwt';\nimport { reportInfo, reportError, reportDebug } from 'utils/report';\nimport { tlsConfig, loadTlsConfig, TlsConfig } from 'utils/tlsConfig';\n\nconst namespace = 'engine:Server';\n\n/** Main server class */\nexport class Server {\n /** The express application powering the main endpoints */\n private app: Application;\n /** The node HTTP(S) server, serving the main express application */\n private httpServer: http.Server | https.Server;\n /** The express application powering the support endpoints */\n private secondaryApp: Application;\n /** The node HTTP(S) server, serving the secondary express application */\n private secondaryHttpServer: http.Server | https.Server;\n /** List of endpoint instances that the server should handle */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private endpoints: Array<Endpoint<any>>;\n /** Mapping of env variable name with functions that should run to check their validity */\n private checkEnvironment: Record<string, ValidatorSpec<unknown>>;\n /** Middleware that should run on every request before the endpoint specific logic */\n private globalMiddleware: Array<ServerGlobalMiddleware>;\n /** Error middleware that should run on every request after the endpoint specific logic, but before the generic global middleware */\n private errorMiddleware: Array<\n ServerGlobalMiddleware | ServerErrorMiddleWare\n >;\n /** Functions that should be called on server startup */\n private initCallbacks: Array<ServerCallback>;\n /** Functions that should be called on server shutdown */\n private shutdownCallbacks: Array<ServerCallback>;\n /** When set to true, this indicates that init callbacks should run synchronously in the order they are declared. By default they all run in parallel */\n private syncCallbacks: boolean;\n /** Config to set regularly running jobs on the server */\n private cron?: Array<ServerCronJon>;\n /** Global auth related configuration */\n private auth: ServerAuthConfig;\n /** WebSocket server instance, if configured */\n private wss?: WebSocketServer;\n /** Abort controller that handles signals for the server */\n private abortController = new AbortController();\n\n /** Create a server */\n public constructor(config: ServerOptions) {\n this.validate(config);\n\n reportDebug({\n namespace,\n message: `Creating server`\n });\n\n this.endpoints = config.endpoints;\n this.globalMiddleware = config.globalMiddleware ?? [];\n this.errorMiddleware = config.errorMiddleware ?? [];\n this.initCallbacks = config.initCallbacks ?? [];\n this.shutdownCallbacks = config.shutdownCallbacks ?? [];\n this.syncCallbacks = config.syncCallbacks ?? false;\n this.cron = config.cron;\n this.auth = { noFetch: false, ...config.auth };\n\n // The minimal environment check is different between the migration modes of execution and the regular server execution mode\n // When running in migration mode, we only check that we have SQL related environment variables\n this.checkEnvironment =\n process.env.RUN_MIGRATION === 'true' ||\n process.env.UNDO_MIGRATION === 'true'\n ? {\n SQL_HOST: envAssert.isHost(),\n SQL_USER: envAssert.isString(),\n SQL_PASSWORD: envAssert.isString(),\n SQL_DB: envAssert.isString()\n }\n : {\n NODE_ENV: envAssert.isString(),\n PORT: envAssert.isPort(),\n SECONDARY_PORT: envAssert.isPort(),\n ...config.checkEnvironment\n };\n\n checkEnvironment(this.checkEnvironment);\n\n // Create the primary express core that serves the business logic\n this.app = express();\n\n this.app.use(\n cors({\n origin: process.env.CORS_ORIGIN ?? '*',\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization']\n })\n );\n\n this.registerMiddleware(this.app);\n this.httpServer = createHttpServer(this.app);\n\n // Create a secondary express core that servers metrics and analytics\n // This will be served on a different port, allowing to specify different firewall rules for these routes\n this.secondaryApp = express();\n [...secondaryMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (middleware) this.secondaryApp.use(middleware);\n }\n );\n this.secondaryHttpServer = createHttpServer(this.secondaryApp);\n\n // Remove the express headers\n this.app.disable('x-powered-by');\n this.secondaryApp.disable('x-powered-by');\n\n // We remove all node timeout on connections and requests\n // This responsibility is delegated to the front-facing load balancer\n [this.httpServer, this.secondaryHttpServer].forEach((server) => {\n server.headersTimeout = 0;\n server.keepAliveTimeout = 0;\n });\n\n if (config.webSocket) {\n this.attachWebSocket(config.webSocket);\n }\n }\n\n /** Start the server */\n public async init(): Promise<void> {\n reportDebug({ namespace, message: `Starting Server` });\n // Fetch the keys for JWT authentication\n // Ignore in test environment as we do symmetrical token signing\n if (process.env.NODE_ENV !== 'test' && !this.auth.noFetch)\n await initKeySets();\n // Run all the init callbacks\n // We can either run them all 1/1 synchronously or run them all in parallel (default)\n // Callback can either be direct function or an object with function and parameters attributes\n\n if (this.syncCallbacks) {\n for (const callback of this.initCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.initCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Initialize the Pub/Sub module\n await PubSub.init();\n // Run all the cronjob\n if (this.cron) {\n this.cron.forEach((job) => {\n this.runCronJob(job);\n });\n }\n\n // Start listening to requests\n await Promise.all([\n new Promise<void>((resolve) =>\n this.httpServer.listen(process.env.PORT, () => {\n resolve();\n })\n ),\n new Promise<void>((resolve) =>\n this.secondaryHttpServer.listen(process.env.SECONDARY_PORT, () => {\n resolve();\n })\n )\n ]);\n reportInfo({\n message: 'SERVER_RUNNING',\n data: {\n port: process.env.PORT,\n secondaryPort: process.env.SECONDARY_PORT,\n nodeEnv: process.env.NODE_ENV\n }\n });\n\n this.handleSignal();\n\n // Watch TSL config files changing\n this.watchTlsCaFileChange();\n }\n\n /** Graceful shutdown */\n public async shutdown(): Promise<void> {\n reportDebug({ namespace, message: `Shutting down Server` });\n\n // Stop listening to HTTP requests\n await Promise.all(\n [this.httpServer, this.secondaryHttpServer].map((server) => {\n // Ignore if the server was already stopped\n // We have observed cases where SIGTERM was thrown multiple times\n if (!server.listening) return;\n const { port } = server.address() as AddressInfo;\n server.on('close', (error: unknown) => {\n if (error) {\n reportError(error);\n process.exit(1);\n } else {\n reportInfo({\n message: `Stopped listening to requests on port ${port}`\n });\n }\n });\n server.close();\n })\n );\n\n // Close all socket connections\n if (this.wss) {\n // First ask then to close gracefully\n this.wss.clients.forEach((socket) => {\n socket.close();\n });\n // Hard terminate all connections still open after a defined time\n const socketKillTimeout = process.env.WEBSOCKET_CLOSE_TIMEOUT\n ? parseInt(process.env.WEBSOCKET_CLOSE_TIMEOUT)\n : 5000;\n await new Promise<void>((resolve) => {\n setTimeout(() => {\n (this.wss as WebSocketServer).clients.forEach((socket) => {\n if (\n socket.readyState === socket.CLOSING ||\n socket.readyState === socket.OPEN\n ) {\n socket.terminate();\n }\n });\n resolve();\n }, socketKillTimeout);\n });\n }\n\n // Run all the shutdown callback\n if (this.syncCallbacks) {\n for (const callback of this.shutdownCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.shutdownCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Shutdown all the running entities\n await LifecycleController.shutdownRunningInstances();\n\n // Abort all the cronjob\n if (this.abortController) this.abortController.abort();\n\n // Stop the keyset timers\n shutdownKeySets();\n\n shutdownSignals.forEach((signal) => process.removeAllListeners(signal));\n }\n\n /** Get the express app instance of the server */\n public getApp(): Application {\n return this.app;\n }\n\n /** Get the express app instance of the server */\n public getSecondaryApp(): Application {\n return this.secondaryApp;\n }\n\n /** Registers all the middleware with the express app */\n private registerMiddleware(app: Application): void {\n // Global middleware can specify a path to which they apply\n [...defaultMiddleware, ...this.globalMiddleware].forEach((middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n });\n // Call the register method of each endpoint\n this.endpoints.forEach((endpoint) => {\n endpoint.register(app);\n });\n // Add error middleware\n [...this.errorMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n }\n );\n }\n\n /** Add a handler for WebSocket connections */\n private attachWebSocket(options: ServerWebSocketConfig): void {\n this.wss = new WebSocketServer({\n ...options.server,\n server: this.httpServer\n })\n .on('connection', (webSocket, request) => {\n new SocketClient(webSocket, request, options.client);\n })\n .on('error', (error) => {\n reportError(error);\n });\n }\n\n /** Call shutdown if signal gets sent to the process */\n private handleSignal(): void {\n shutdownSignals.forEach((signal) =>\n process.on(signal, () => {\n (async (): Promise<void> => {\n reportInfo(`Received shutdown signal [${signal}]`);\n await this.shutdown();\n })().catch((error) => {\n reportError(error);\n });\n })\n );\n }\n\n /** Watch the TLS certificate change event */\n private watchTlsCaFileChange(): void {\n [\n 'TLS_REQUEST_KEY',\n 'TLS_REQUEST_KEY_PASSPHRASE',\n 'TLS_REQUEST_CERT',\n 'TLS_REQUEST_CA',\n 'TLS_SERVER_KEY',\n 'TLS_SERVER_KEY_PASSPHRASE',\n 'TLS_SERVER_CERT',\n 'TLS_CA'\n ].forEach((key) => {\n const file = process.env[key];\n if (file)\n fs.watch(path.resolve(file), (event) => {\n if (event !== 'change') return;\n reportInfo(`Reloading TLS config [${file} changed]`);\n loadTlsConfig();\n (this.httpServer as https.Server).setSecureContext(\n tlsConfig as TlsConfig\n );\n });\n });\n }\n\n /** Executes a recurring job */\n private runCronJob(job: ServerCronJon): void {\n (async (): Promise<void> => {\n reportInfo({ message: `Starting scheduled job \"${job.handler.name}\"` });\n try {\n await job.handler();\n reportInfo({\n message: `Job \"${job.handler.name}\" finished, starting again in ${job.interval} seconds`\n });\n await setTimeoutPromise(job.interval * 1000, undefined, {\n signal: this.abortController.signal\n });\n this.runCronJob(job);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n reportDebug({\n namespace,\n message: `Scheduled job \"${job.handler?.name}\" has been aborted`\n });\n } else {\n throw error;\n }\n }\n })().catch((error) => {\n reportError(error);\n });\n }\n\n /** Run a shutdown/init callback */\n private runCallback(callback: ServerCallback): unknown {\n return typeof callback === 'function'\n ? callback()\n : callback.function.apply(null, callback.parameters ?? []);\n }\n\n /**\n * Validate the Server constructor configuration\n */\n private validate(config: ServerOptions): void {\n if (\n !config.endpoints ||\n config.endpoints.some((endpoint) => !(endpoint instanceof Endpoint))\n )\n throw new EngineError(\n 'Server endpoints should be declared and all be Endpoint instances'\n );\n\n if (\n config.checkEnvironment &&\n Object.values(config.checkEnvironment).some(\n (validator) => typeof validator !== 'function'\n )\n )\n throw new EngineError(\n 'Some of the environment checks are not valid functions'\n );\n\n if (\n config.initCallbacks &&\n (!(config.initCallbacks instanceof Array) ||\n config.initCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Init callbacks is not a list of functions');\n\n if (\n config.shutdownCallbacks &&\n (!(config.shutdownCallbacks instanceof Array) ||\n config.shutdownCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Shutdown callbacks is not a list of functions');\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"Server.js","names":["_fs","_interopRequireDefault","require","_path","_promises","_express","_cors","_ws","_SocketClient","_Server2","_Endpoint","_EngineError","_LifecycleController","_PubSub","_utils","_jwt","_report","_tlsConfig","namespace","Server","exports","config","_classCallCheck2","default","_defineProperty2","AbortController","validate","reportDebug","message","endpoints","globalMiddleware","errorMiddleware","initCallbacks","shutdownCallbacks","syncCallbacks","cron","auth","noFetch","checkEnvironment","process","env","RUN_MIGRATION","UNDO_MIGRATION","SQL_HOST","envAssert","isHost","SQL_USER","isString","SQL_PASSWORD","SQL_DB","NODE_ENV","PORT","isPort","SECONDARY_PORT","app","express","use","cors","origin","CORS_ORIGIN","methods","allowedHeaders","registerMiddleware","httpServer","createHttpServer","secondaryApp","secondaryMiddleware","defaultErrorMiddleware","forEach","middleware","secondaryHttpServer","disable","server","headersTimeout","keepAliveTimeout","webSocket","attachWebSocket","_createClass2","key","value","init","initKeySets","callback","runCallback","Promise","all","map","PubSub","job","runCronJob","resolve","listen","reportInfo","data","port","secondaryPort","nodeEnv","handleSignal","watchTlsCaFileChange","shutdown","listening","address","on","error","reportError","exit","close","wss","clients","socket","socketKillTimeout","WEBSOCKET_CLOSE_TIMEOUT","parseInt","setTimeout","readyState","CLOSING","OPEN","terminate","LifecycleController","shutdownRunningInstances","abortController","abort","shutdownKeySets","shutdownSignals","signal","removeAllListeners","getApp","getSecondaryApp","defaultMiddleware","path","endpoint","register","options","WebSocketServer","request","SocketClient","client","catch","file","fs","watch","event","loadTlsConfig","setSecureContext","tlsConfig","handler","name","interval","setTimeoutPromise","undefined","Error","function","apply","parameters","some","Endpoint","EngineError","Object","values","validator","Array"],"sources":["../../../src/entities/Server/Server.ts"],"sourcesContent":["import fs from 'fs';\nimport http from 'http';\nimport https from 'https';\nimport { AddressInfo } from 'net';\nimport path from 'path';\nimport { setTimeout as setTimeoutPromise } from 'timers/promises';\nimport { ValidatorSpec } from 'envalid';\nimport express, { Application } from 'express';\nimport cors from 'cors';\nimport { Server as WebSocketServer } from 'ws';\nimport { SocketClient } from '../SocketClient';\nimport {\n defaultMiddleware,\n defaultErrorMiddleware,\n secondaryMiddleware,\n shutdownSignals\n} from './Server.const';\nimport {\n ServerOptions,\n ServerCronJon,\n ServerAuthConfig,\n ServerWebSocketConfig,\n ServerGlobalMiddleware,\n ServerErrorMiddleWare,\n ServerCallback\n} from './Server.types';\nimport { Endpoint } from 'entities/Endpoint';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { PubSub } from 'entities/PubSub';\nimport { checkEnvironment, envAssert, createHttpServer } from 'utils';\nimport { initKeySets, shutdownKeySets } from 'utils/jwt';\nimport { reportInfo, reportError, reportDebug } from 'utils/report';\nimport { tlsConfig, loadTlsConfig, TlsConfig } from 'utils/tlsConfig';\n\nconst namespace = 'engine:Server';\n\n/** Main server class */\nexport class Server {\n /** The express application powering the main endpoints */\n private app: Application;\n /** The node HTTP(S) server, serving the main express application */\n private httpServer: http.Server | https.Server;\n /** The express application powering the support endpoints */\n private secondaryApp: Application;\n /** The node HTTP(S) server, serving the secondary express application */\n private secondaryHttpServer: http.Server | https.Server;\n /** List of endpoint instances that the server should handle */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private endpoints: Array<Endpoint<any>>;\n /** Mapping of env variable name with functions that should run to check their validity */\n private checkEnvironment: Record<string, ValidatorSpec<unknown>>;\n /** Middleware that should run on every request before the endpoint specific logic */\n private globalMiddleware: Array<ServerGlobalMiddleware>;\n /** Error middleware that should run on every request after the endpoint specific logic, but before the generic global middleware */\n private errorMiddleware: Array<\n ServerGlobalMiddleware | ServerErrorMiddleWare\n >;\n /** Functions that should be called on server startup */\n private initCallbacks: Array<ServerCallback>;\n /** Functions that should be called on server shutdown */\n private shutdownCallbacks: Array<ServerCallback>;\n /** When set to true, this indicates that init callbacks should run synchronously in the order they are declared. By default they all run in parallel */\n private syncCallbacks: boolean;\n /** Config to set regularly running jobs on the server */\n private cron?: Array<ServerCronJon>;\n /** Global auth related configuration */\n private auth: ServerAuthConfig;\n /** WebSocket server instance, if configured */\n private wss?: WebSocketServer;\n /** Abort controller that handles signals for the server */\n private abortController = new AbortController();\n\n /** Create a server */\n public constructor(config: ServerOptions) {\n this.validate(config);\n\n reportDebug({\n namespace,\n message: `Creating server`\n });\n\n this.endpoints = config.endpoints;\n this.globalMiddleware = config.globalMiddleware ?? [];\n this.errorMiddleware = config.errorMiddleware ?? [];\n this.initCallbacks = config.initCallbacks ?? [];\n this.shutdownCallbacks = config.shutdownCallbacks ?? [];\n this.syncCallbacks = config.syncCallbacks ?? false;\n this.cron = config.cron;\n this.auth = { noFetch: false, ...config.auth };\n\n // The minimal environment check is different between the migration modes of execution and the regular server execution mode\n // When running in migration mode, we only check that we have SQL related environment variables\n this.checkEnvironment =\n process.env.RUN_MIGRATION === 'true' ||\n process.env.UNDO_MIGRATION === 'true'\n ? {\n SQL_HOST: envAssert.isHost(),\n SQL_USER: envAssert.isString(),\n SQL_PASSWORD: envAssert.isString(),\n SQL_DB: envAssert.isString()\n }\n : {\n NODE_ENV: envAssert.isString(),\n PORT: envAssert.isPort(),\n SECONDARY_PORT: envAssert.isPort(),\n ...config.checkEnvironment\n };\n\n checkEnvironment(this.checkEnvironment);\n\n // Create the primary express core that serves the business logic\n this.app = express();\n\n this.app.use(\n cors({\n origin: process.env.CORS_ORIGIN ?? '*',\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization']\n })\n );\n\n this.registerMiddleware(this.app);\n this.httpServer = createHttpServer(this.app);\n\n // Create a secondary express core that servers metrics and analytics\n // This will be served on a different port, allowing to specify different firewall rules for these routes\n this.secondaryApp = express();\n [...secondaryMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (middleware) this.secondaryApp.use(middleware);\n }\n );\n this.secondaryHttpServer = createHttpServer(this.secondaryApp);\n\n // Remove the express headers\n this.app.disable('x-powered-by');\n this.secondaryApp.disable('x-powered-by');\n\n // We remove all node timeout on connections and requests\n // This responsibility is delegated to the front-facing load balancer\n [this.httpServer, this.secondaryHttpServer].forEach((server) => {\n server.headersTimeout = 0;\n server.keepAliveTimeout = 0;\n });\n\n if (config.webSocket) {\n this.attachWebSocket(config.webSocket);\n }\n }\n\n /** Start the server */\n public async init(): Promise<void> {\n reportDebug({ namespace, message: `Starting Server` });\n // Fetch the keys for JWT authentication\n // Ignore in test environment as we do symmetrical token signing\n if (process.env.NODE_ENV !== 'test' && !this.auth.noFetch)\n await initKeySets();\n // Run all the init callbacks\n // We can either run them all 1/1 synchronously or run them all in parallel (default)\n // Callback can either be direct function or an object with function and parameters attributes\n\n if (this.syncCallbacks) {\n for (const callback of this.initCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.initCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Initialize the Pub/Sub module\n await PubSub.init();\n // Run all the cronjob\n if (this.cron) {\n this.cron.forEach((job) => {\n this.runCronJob(job);\n });\n }\n\n // Start listening to requests\n await Promise.all([\n new Promise<void>((resolve) =>\n this.httpServer.listen(process.env.PORT, () => {\n resolve();\n })\n ),\n new Promise<void>((resolve) =>\n this.secondaryHttpServer.listen(process.env.SECONDARY_PORT, () => {\n resolve();\n })\n )\n ]);\n reportInfo({\n message: 'SERVER_RUNNING',\n data: {\n port: process.env.PORT,\n secondaryPort: process.env.SECONDARY_PORT,\n nodeEnv: process.env.NODE_ENV\n }\n });\n\n this.handleSignal();\n\n // Watch TSL config files changing\n this.watchTlsCaFileChange();\n }\n\n /** Graceful shutdown */\n public async shutdown(): Promise<void> {\n reportDebug({ namespace, message: `Shutting down Server` });\n\n // Stop listening to HTTP requests\n await Promise.all(\n [this.httpServer, this.secondaryHttpServer].map((server) => {\n // Ignore if the server was already stopped\n // We have observed cases where SIGTERM was thrown multiple times\n if (!server.listening) return;\n const { port } = server.address() as AddressInfo;\n server.on('close', (error: unknown) => {\n if (error) {\n reportError(error);\n process.exit(1);\n } else {\n reportInfo({\n message: `Stopped listening to requests on port ${port}`\n });\n }\n });\n server.close();\n })\n );\n\n // Close all socket connections\n if (this.wss) {\n // First ask then to close gracefully\n this.wss.clients.forEach((socket) => {\n socket.close();\n });\n // Hard terminate all connections still open after a defined time\n const socketKillTimeout = process.env.WEBSOCKET_CLOSE_TIMEOUT\n ? parseInt(process.env.WEBSOCKET_CLOSE_TIMEOUT)\n : 5000;\n await new Promise<void>((resolve) => {\n setTimeout(() => {\n (this.wss as WebSocketServer).clients.forEach((socket) => {\n if (\n socket.readyState === socket.CLOSING ||\n socket.readyState === socket.OPEN\n ) {\n socket.terminate();\n }\n });\n resolve();\n }, socketKillTimeout);\n });\n }\n\n // Run all the shutdown callback\n if (this.syncCallbacks) {\n for (const callback of this.shutdownCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.shutdownCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Shutdown all the running entities\n await LifecycleController.shutdownRunningInstances();\n\n // Abort all the cronjob\n if (this.abortController) this.abortController.abort();\n\n // Stop the keyset timers\n shutdownKeySets();\n\n shutdownSignals.forEach((signal) => process.removeAllListeners(signal));\n }\n\n /** Get the express app instance of the server */\n public getApp(): Application {\n return this.app;\n }\n\n /** Get the express app instance of the server */\n public getSecondaryApp(): Application {\n return this.secondaryApp;\n }\n\n /** Registers all the middleware with the express app */\n private registerMiddleware(app: Application): void {\n // Global middleware can specify a path to which they apply\n [...defaultMiddleware, ...this.globalMiddleware].forEach((middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n });\n // Call the register method of each endpoint\n this.endpoints.forEach((endpoint) => {\n endpoint.register(app);\n });\n // Add error middleware\n [...this.errorMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n }\n );\n }\n\n /** Add a handler for WebSocket connections */\n private attachWebSocket(options: ServerWebSocketConfig): void {\n this.wss = new WebSocketServer({\n ...options.server,\n server: this.httpServer\n })\n .on('connection', (webSocket, request) => {\n new SocketClient(webSocket, request, options.client);\n })\n .on('error', (error) => {\n reportError(error);\n });\n }\n\n /** Call shutdown if signal gets sent to the process */\n private handleSignal(): void {\n shutdownSignals.forEach((signal) =>\n process.on(signal, () => {\n (async (): Promise<void> => {\n reportInfo(`Received shutdown signal [${signal}]`);\n await this.shutdown();\n })().catch((error) => {\n reportError(error);\n });\n })\n );\n }\n\n /** Watch the TLS certificate change event */\n private watchTlsCaFileChange(): void {\n [\n 'TLS_REQUEST_KEY',\n 'TLS_REQUEST_CERT',\n 'TLS_REQUEST_CA',\n 'TLS_SERVER_KEY',\n 'TLS_SERVER_CERT',\n 'TLS_CA'\n ].forEach((key) => {\n const file = process.env[key];\n if (file)\n fs.watch(path.resolve(file), (event) => {\n if (event !== 'change') return;\n reportInfo(`Reloading TLS config [${file} changed]`);\n loadTlsConfig();\n (this.httpServer as https.Server).setSecureContext(\n tlsConfig as TlsConfig\n );\n });\n });\n }\n\n /** Executes a recurring job */\n private runCronJob(job: ServerCronJon): void {\n (async (): Promise<void> => {\n reportInfo({ message: `Starting scheduled job \"${job.handler.name}\"` });\n try {\n await job.handler();\n reportInfo({\n message: `Job \"${job.handler.name}\" finished, starting again in ${job.interval} seconds`\n });\n await setTimeoutPromise(job.interval * 1000, undefined, {\n signal: this.abortController.signal\n });\n this.runCronJob(job);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n reportDebug({\n namespace,\n message: `Scheduled job \"${job.handler?.name}\" has been aborted`\n });\n } else {\n throw error;\n }\n }\n })().catch((error) => {\n reportError(error);\n });\n }\n\n /** Run a shutdown/init callback */\n private runCallback(callback: ServerCallback): unknown {\n return typeof callback === 'function'\n ? callback()\n : callback.function.apply(null, callback.parameters ?? []);\n }\n\n /**\n * Validate the Server constructor configuration\n */\n private validate(config: ServerOptions): void {\n if (\n !config.endpoints ||\n config.endpoints.some((endpoint) => !(endpoint instanceof Endpoint))\n )\n throw new EngineError(\n 'Server endpoints should be declared and all be Endpoint instances'\n );\n\n if (\n config.checkEnvironment &&\n Object.values(config.checkEnvironment).some(\n (validator) => typeof validator !== 'function'\n )\n )\n throw new EngineError(\n 'Some of the environment checks are not valid functions'\n );\n\n if (\n config.initCallbacks &&\n (!(config.initCallbacks instanceof Array) ||\n config.initCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Init callbacks is not a list of functions');\n\n if (\n config.shutdownCallbacks &&\n (!(config.shutdownCallbacks instanceof Array) ||\n config.shutdownCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Shutdown callbacks is not a list of functions');\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -9,6 +9,8 @@ var _WebError = require("../../entities/WebError");
9
9
  var _report = require("../../utils/report");
10
10
  var _multer = _interopRequireDefault(require("multer"));
11
11
  var _validate = require("./validate");
12
+ var _path = _interopRequireDefault(require("path"));
13
+ var _bytes = _interopRequireDefault(require("bytes"));
12
14
  const namespace = 'engine:middleware:fileUploader';
13
15
 
14
16
  /**
@@ -32,8 +34,8 @@ function fileUploader(filesOptions, validator) {
32
34
  const upload = (0, _multer.default)({
33
35
  storage,
34
36
  limits: {
35
- fileSize: 10 * 1024 * 1024
36
- } // Limit file size to 10MB
37
+ fileSize: 32 * 1024 * 1024
38
+ } // Default global limit (10MB)
37
39
  }).any();
38
40
  upload(request, response, async err => {
39
41
  if (err) {
@@ -102,7 +104,47 @@ function fileUploader(filesOptions, validator) {
102
104
  }
103
105
  }));
104
106
  }
105
- request.body.files = uploadedFiles;
107
+
108
+ // Validate each uploaded file
109
+ for (const file of uploadedFiles) {
110
+ const fileOption = filesOptions.find(option => option.key === file.fieldname);
111
+ if (!fileOption) continue;
112
+
113
+ // MIME Type Validation
114
+ if (fileOption.mimeTypes && !fileOption.mimeTypes.includes(file.mimetype)) {
115
+ return next(new _WebError.WebError({
116
+ statusCode: 400,
117
+ errorCode: 'invalid-mime-type',
118
+ message: `Invalid file type for ${file.fieldname}`,
119
+ data: {
120
+ expected: fileOption.mimeTypes,
121
+ received: file.mimetype
122
+ }
123
+ }));
124
+ }
125
+
126
+ // Max File Size Validation
127
+ if (fileOption.maxSize) {
128
+ const maxSizeInBytes = (0, _bytes.default)(fileOption.maxSize);
129
+ if (maxSizeInBytes && file.size > maxSizeInBytes) {
130
+ return next(new _WebError.WebError({
131
+ statusCode: 400,
132
+ errorCode: 'file-too-large',
133
+ message: `File ${file.originalname} exceeds the allowed size`,
134
+ data: {
135
+ maxSize: fileOption.maxSize,
136
+ receivedSize: file.size
137
+ }
138
+ }));
139
+ }
140
+ }
141
+
142
+ // No Extension Handling
143
+ if (fileOption.noExtension) {
144
+ file.originalname = _path.default.basename(file.originalname, _path.default.extname(file.originalname));
145
+ }
146
+ }
147
+ request.files = uploadedFiles;
106
148
  next();
107
149
  });
108
150
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fileUploader.js","names":["_WebError","require","_report","_multer","_interopRequireDefault","_validate","namespace","fileUploader","filesOptions","validator","request","response","next","reportDebug","message","data","storage","multer","memoryStorage","upload","limits","fileSize","any","err","error","uploadedFiles","Array","isArray","files","Object","values","flat","map","file","originalname","validate","uploadedFileKeys","fieldname","missingFiles","filter","option","required","includes","key","length","WebError","statusCode","errorCode","body"],"sources":["../../../src/middleware/fileUploader/fileUploader.ts"],"sourcesContent":["import { Request, Response, NextFunction } from 'express';\nimport { Schema } from 'express-validator';\nimport { WebError } from 'entities/WebError';\nimport { reportDebug } from 'utils/report';\nimport multer from 'multer';\nimport { FileUploaderConfig } from './fileUploader.types';\nimport { validate } from './validate';\n\nconst namespace = 'engine:middleware:fileUploader';\n\n/**\n * Middleware for handling file uploads.\n * @param filesOptions Configuration options for expected files.\n * @param validator Validation schema for request fields.\n */\nexport function fileUploader(\n filesOptions: Array<FileUploaderConfig>,\n validator: Schema\n) {\n return async (\n request: Request,\n response: Response,\n next: NextFunction\n ): Promise<void> => {\n reportDebug({\n namespace,\n message: 'Received request to upload file',\n data: { filesOptions, validator }\n });\n\n // Setup multer with memory storage\n const storage = multer.memoryStorage();\n const upload = multer({\n storage,\n limits: { fileSize: 10 * 1024 * 1024 } // Limit file size to 10MB\n }).any();\n\n upload(request, response, async (err) => {\n if (err) {\n reportDebug({\n namespace,\n message: 'Multer upload error',\n data: { error: err.message }\n });\n return next(err);\n }\n\n // Ensure `request.files` is properly typed\n let uploadedFiles: Express.Multer.File[] = [];\n if (Array.isArray(request.files)) {\n uploadedFiles = request.files;\n } else if (typeof request.files === 'object') {\n uploadedFiles = Object.values(request.files).flat();\n }\n\n // Log uploaded files\n reportDebug({\n namespace,\n message: 'Files Received',\n data: { uploadedFiles: uploadedFiles.map((file) => file.originalname) }\n });\n\n // Validate request body fields\n try {\n await validate(request, validator);\n } catch (error) {\n reportDebug({\n namespace,\n message: 'Validation failed',\n data: { error }\n });\n return next(error);\n }\n\n // Extract uploaded field names\n const uploadedFileKeys = uploadedFiles.map((file) => file.fieldname);\n\n // Check for missing required files\n const missingFiles = filesOptions.filter(\n (option) => option.required && !uploadedFileKeys.includes(option.key)\n );\n\n if (missingFiles.length > 0) {\n reportDebug({\n namespace,\n message: 'Missing required files',\n data: { missingFiles, uploadedFileKeys }\n });\n\n return next(\n new WebError({\n statusCode: 400,\n errorCode: 'missing-field',\n message: 'Some required files have not been uploaded',\n data: { missingFiles, uploadedFileKeys }\n })\n );\n }\n\n request.body.files = uploadedFiles;\n\n next();\n });\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"fileUploader.js","names":["_WebError","require","_report","_multer","_interopRequireDefault","_validate","_path","_bytes","namespace","fileUploader","filesOptions","validator","request","response","next","reportDebug","message","data","storage","multer","memoryStorage","upload","limits","fileSize","any","err","error","uploadedFiles","Array","isArray","files","Object","values","flat","map","file","originalname","validate","uploadedFileKeys","fieldname","missingFiles","filter","option","required","includes","key","length","WebError","statusCode","errorCode","fileOption","find","mimeTypes","mimetype","expected","received","maxSize","maxSizeInBytes","bytes","size","receivedSize","noExtension","path","basename","extname"],"sources":["../../../src/middleware/fileUploader/fileUploader.ts"],"sourcesContent":["import { Request, Response, NextFunction } from 'express';\nimport { Schema } from 'express-validator';\nimport { WebError } from 'entities/WebError';\nimport { reportDebug } from 'utils/report';\nimport multer from 'multer';\nimport { FileUploaderConfig } from './fileUploader.types';\nimport { validate } from './validate';\nimport path from 'path';\nimport bytes from 'bytes';\n\nconst namespace = 'engine:middleware:fileUploader';\n\n/**\n * Middleware for handling file uploads.\n * @param filesOptions Configuration options for expected files.\n * @param validator Validation schema for request fields.\n */\nexport function fileUploader(\n filesOptions: Array<FileUploaderConfig>,\n validator: Schema\n) {\n return async (\n request: Request,\n response: Response,\n next: NextFunction\n ): Promise<void> => {\n reportDebug({\n namespace,\n message: 'Received request to upload file',\n data: { filesOptions, validator }\n });\n\n // Setup multer with memory storage\n const storage = multer.memoryStorage();\n const upload = multer({\n storage,\n limits: { fileSize: 32 * 1024 * 1024 } // Default global limit (10MB)\n }).any();\n\n upload(request, response, async (err) => {\n if (err) {\n reportDebug({\n namespace,\n message: 'Multer upload error',\n data: { error: err.message }\n });\n return next(err);\n }\n\n // Ensure `request.files` is properly typed\n let uploadedFiles: Express.Multer.File[] = [];\n if (Array.isArray(request.files)) {\n uploadedFiles = request.files;\n } else if (typeof request.files === 'object') {\n uploadedFiles = Object.values(request.files).flat();\n }\n\n // Log uploaded files\n reportDebug({\n namespace,\n message: 'Files Received',\n data: { uploadedFiles: uploadedFiles.map((file) => file.originalname) }\n });\n\n // Validate request body fields\n try {\n await validate(request, validator);\n } catch (error) {\n reportDebug({\n namespace,\n message: 'Validation failed',\n data: { error }\n });\n return next(error);\n }\n\n // Extract uploaded field names\n const uploadedFileKeys = uploadedFiles.map((file) => file.fieldname);\n\n // Check for missing required files\n const missingFiles = filesOptions.filter(\n (option) => option.required && !uploadedFileKeys.includes(option.key)\n );\n\n if (missingFiles.length > 0) {\n reportDebug({\n namespace,\n message: 'Missing required files',\n data: { missingFiles, uploadedFileKeys }\n });\n\n return next(\n new WebError({\n statusCode: 400,\n errorCode: 'missing-field',\n message: 'Some required files have not been uploaded',\n data: { missingFiles, uploadedFileKeys }\n })\n );\n }\n\n // Validate each uploaded file\n for (const file of uploadedFiles) {\n const fileOption = filesOptions.find(\n (option) => option.key === file.fieldname\n );\n\n if (!fileOption) continue;\n\n // MIME Type Validation\n if (\n fileOption.mimeTypes &&\n !fileOption.mimeTypes.includes(file.mimetype)\n ) {\n return next(\n new WebError({\n statusCode: 400,\n errorCode: 'invalid-mime-type',\n message: `Invalid file type for ${file.fieldname}`,\n data: { expected: fileOption.mimeTypes, received: file.mimetype }\n })\n );\n }\n\n // Max File Size Validation\n if (fileOption.maxSize) {\n const maxSizeInBytes = bytes(fileOption.maxSize);\n if (maxSizeInBytes && file.size > maxSizeInBytes) {\n return next(\n new WebError({\n statusCode: 400,\n errorCode: 'file-too-large',\n message: `File ${file.originalname} exceeds the allowed size`,\n data: { maxSize: fileOption.maxSize, receivedSize: file.size }\n })\n );\n }\n }\n\n // No Extension Handling\n if (fileOption.noExtension) {\n file.originalname = path.basename(\n file.originalname,\n path.extname(file.originalname)\n );\n }\n }\n\n request.files = uploadedFiles;\n\n next();\n });\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1,2 @@
1
1
  export * from './multiPartFileUploader';
2
+ export * from './multiPartFileUploader.types';
@@ -14,4 +14,15 @@ Object.keys(_multiPartFileUploader).forEach(function (key) {
14
14
  }
15
15
  });
16
16
  });
17
+ var _multiPartFileUploader2 = require("./multiPartFileUploader.types");
18
+ Object.keys(_multiPartFileUploader2).forEach(function (key) {
19
+ if (key === "default" || key === "__esModule") return;
20
+ if (key in exports && exports[key] === _multiPartFileUploader2[key]) return;
21
+ Object.defineProperty(exports, key, {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _multiPartFileUploader2[key];
25
+ }
26
+ });
27
+ });
17
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_multiPartFileUploader","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get"],"sources":["../../../src/middleware/multiPartFileUploader/index.ts"],"sourcesContent":["export * from './multiPartFileUploader';\n"],"mappings":";;;;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,sBAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,sBAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,sBAAA,CAAAK,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_multiPartFileUploader","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_multiPartFileUploader2"],"sources":["../../../src/middleware/multiPartFileUploader/index.ts"],"sourcesContent":["export * from './multiPartFileUploader';\nexport * from './multiPartFileUploader.types';\n"],"mappings":";;;;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,sBAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,sBAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,sBAAA,CAAAK,GAAA;IAAA;EAAA;AAAA;AACA,IAAAK,uBAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,uBAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,uBAAA,CAAAL,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,uBAAA,CAAAL,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
@@ -1,3 +1,4 @@
1
- import express from 'express';
2
- declare function multiPartFileUploader(req: express.Request, res: express.Response, next: express.NextFunction): Promise<void>;
3
- export { multiPartFileUploader };
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { Schema } from 'express-validator';
3
+ import { MultiPartFileUploaderConfig } from './multiPartFileUploader.types';
4
+ export declare function multiPartFileUploader(filesOption: MultiPartFileUploaderConfig, validator: Schema): (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -9,148 +9,212 @@ var _multer = _interopRequireDefault(require("multer"));
9
9
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
10
10
  var _path = _interopRequireDefault(require("path"));
11
11
  var _utils = require("../../utils");
12
- const TEMP_DIR = process.env.TEMP_CHUNK_FOLDER || './uploads/temp_chunks';
12
+ var _WebError = require("../../entities/WebError");
13
+ var _validate = require("./validate");
13
14
  const namespace = 'engine:middleware:multiPartFileUploader';
15
+ const TEMP_DIR = _path.default.join(process.env.FILE_STORAGE_FOLDER || './uploads', 'temp_chunks');
16
+ const FILE_DIR = _path.default.join(process.env.FILE_STORAGE_FOLDER || './uploads', 'completed_files');
17
+ _fsExtra.default.ensureDirSync(FILE_DIR);
14
18
  _fsExtra.default.ensureDirSync(TEMP_DIR);
15
19
  const storage = _multer.default.memoryStorage();
16
- async function multiPartFileUploader(req, res, next) {
17
- try {
18
- const uploadSingle = (0, _multer.default)({
19
- storage
20
- }).single('file');
21
- uploadSingle(req, res, async err => {
22
- if (err) {
23
- (0, _utils.reportError)('Error uploading chunk');
24
- return next(err);
25
- }
26
- const {
27
- filename,
28
- totalChunks,
29
- chunkIndex,
30
- uniqueID
31
- } = req.body;
32
- if (!filename || !totalChunks || chunkIndex === undefined || !uniqueID || !req.file) {
33
- req.body.uploadDetails = {
34
- status: 'failed',
35
- message: 'Missing required fields',
36
- details: {
20
+ function multiPartFileUploader(filesOption, validator) {
21
+ return async (req, res, next) => {
22
+ try {
23
+ (0, _utils.reportDebug)({
24
+ namespace,
25
+ message: 'Starting file upload middleware'
26
+ });
27
+ const uploadSingle = (0, _multer.default)({
28
+ storage
29
+ }).single('file');
30
+ uploadSingle(req, res, async err => {
31
+ if (err) {
32
+ (0, _utils.reportError)('Error uploading chunk');
33
+ return next(new _WebError.WebError({
34
+ statusCode: 500,
35
+ errorCode: 'upload-failed',
36
+ message: 'Error uploading file chunk',
37
+ data: {
38
+ error: err.message
39
+ }
40
+ }));
41
+ }
42
+ try {
43
+ (0, _utils.reportDebug)({
44
+ namespace,
45
+ message: 'Validating request'
46
+ });
47
+ await (0, _validate.validate)(req, validator);
48
+ } catch (error) {
49
+ (0, _utils.reportDebug)({
50
+ namespace,
51
+ message: 'Validation failed',
52
+ data: {
53
+ error
54
+ }
55
+ });
56
+ return next(new _WebError.WebError({
57
+ statusCode: 400,
58
+ errorCode: 'validation-failed',
59
+ message: 'Validation failed for file upload',
60
+ data: {
61
+ error: error.message
62
+ }
63
+ }));
64
+ }
65
+ const {
66
+ filename,
67
+ totalChunks,
68
+ chunkIndex,
69
+ uniqueID
70
+ } = req.body;
71
+ (0, _utils.reportDebug)({
72
+ namespace,
73
+ message: 'Received chunk data',
74
+ data: {
37
75
  filename,
38
76
  totalChunks,
39
77
  chunkIndex,
40
- uniqueID,
41
- receivedChunk: !!req.file
78
+ uniqueID
42
79
  }
43
- };
44
- (0, _utils.reportDebug)({
45
- namespace,
46
- message: `Missing required fields`,
47
- data: {
48
- status: 'failed',
49
- details: {
80
+ });
81
+ if (!filename || !totalChunks || chunkIndex === undefined || !uniqueID || !req.file) {
82
+ return next(new _WebError.WebError({
83
+ statusCode: 400,
84
+ errorCode: 'missing-field',
85
+ message: 'Missing required fields',
86
+ data: {
50
87
  filename,
51
88
  totalChunks,
52
89
  chunkIndex,
53
- uniqueID
90
+ uniqueID,
91
+ receivedChunk: !!req.file
54
92
  }
55
- }
56
- });
57
- return next();
58
- }
59
- const sessionFolder = _path.default.join(TEMP_DIR, uniqueID);
60
- _fsExtra.default.ensureDirSync(sessionFolder);
61
- const chunkPath = _path.default.join(sessionFolder, `${filename}.part${chunkIndex}`);
62
- try {
63
- await _fsExtra.default.writeFile(chunkPath, req.file.buffer);
64
- } catch (writeErr) {
65
- (0, _utils.reportError)(`Failed to write chunk ${chunkIndex}: ${writeErr.message}`);
66
- return next(writeErr);
67
- }
68
- const uploadedChunks = await _fsExtra.default.readdir(sessionFolder);
69
- if (uploadedChunks.length === parseInt(totalChunks, 10)) {
70
- (0, _utils.reportDebug)({
71
- namespace,
72
- message: `All chunks uploaded. Merging file...`
73
- });
74
- try {
75
- await mergeChunks(filename, totalChunks, sessionFolder);
76
- } catch (mergeErr) {
77
- (0, _utils.reportError)(`File merging failed: ${mergeErr.message}`);
78
- return next(mergeErr);
93
+ }));
79
94
  }
80
- const finalFilePath = _path.default.join(sessionFolder, filename);
81
- if (!_fsExtra.default.existsSync(finalFilePath)) {
82
- (0, _utils.reportError)('File merging failed: File does not exist');
83
- return next(new Error('File merging failed'));
95
+ if (filesOption?.maxSize && req.file.size > parseInt(filesOption?.maxSize, 10)) {
96
+ return next(new _WebError.WebError({
97
+ statusCode: 400,
98
+ errorCode: 'chunk-too-large',
99
+ message: 'Uploaded chunk exceeds the maximum allowed size',
100
+ data: {
101
+ maxSize: filesOption.maxSize,
102
+ receivedSize: req.file.size
103
+ }
104
+ }));
84
105
  }
85
- req.body.uploadDetails = {
86
- status: 'completed',
87
- message: 'File uploaded and merged successfully',
88
- details: {
89
- filename,
90
- uniqueID
91
- }
92
- };
106
+ const sessionFolder = _path.default.join(TEMP_DIR, uniqueID);
107
+ _fsExtra.default.ensureDirSync(sessionFolder);
108
+ const chunkPath = _path.default.join(sessionFolder, `${filename}.part${chunkIndex}`);
109
+ try {
110
+ (0, _utils.reportDebug)({
111
+ namespace,
112
+ message: 'Writing chunk to disk',
113
+ data: {
114
+ chunkPath
115
+ }
116
+ });
117
+ await _fsExtra.default.writeFile(chunkPath, req.file.buffer);
118
+ } catch (writeErr) {
119
+ return next(new _WebError.WebError({
120
+ statusCode: 500,
121
+ errorCode: 'chunk-write-failed',
122
+ message: 'Failed to write chunk',
123
+ data: {
124
+ chunkIndex,
125
+ error: writeErr.message
126
+ }
127
+ }));
128
+ }
129
+ const uploadedChunks = await _fsExtra.default.readdir(sessionFolder);
93
130
  (0, _utils.reportDebug)({
94
131
  namespace,
95
- message: `File merged successfully`,
132
+ message: 'Uploaded chunk count',
96
133
  data: {
97
- status: 'completed',
98
- details: {
99
- filename,
100
- uniqueID
101
- }
134
+ uploadedChunks: uploadedChunks.length,
135
+ totalChunks
102
136
  }
103
137
  });
104
- return next();
105
- }
106
- (0, _utils.reportDebug)({
107
- namespace,
108
- message: `Chunk uploaded successfully`,
109
- data: {
110
- filename,
111
- uniqueID,
112
- chunkIndex,
113
- totalChunks
138
+ if (uploadedChunks.length === parseInt(totalChunks, 10)) {
139
+ try {
140
+ const finalFilePath = _path.default.join(FILE_DIR, `${uniqueID}_${filename}`);
141
+ await mergeChunks(filename, totalChunks, sessionFolder, finalFilePath);
142
+ req.multipartFile = {
143
+ isPending: false,
144
+ originalname: filename,
145
+ uniqueID,
146
+ filePath: finalFilePath
147
+ };
148
+ } catch (mergeErr) {
149
+ return next(new _WebError.WebError({
150
+ statusCode: 500,
151
+ errorCode: 'file-merge-failed',
152
+ message: 'Error merging file chunks',
153
+ data: {
154
+ error: mergeErr.message
155
+ }
156
+ }));
157
+ }
158
+ return next();
114
159
  }
115
- });
116
- req.body.uploadDetails = {
117
- status: 'pending',
118
- message: 'Chunk uploaded successfully',
119
- details: {
120
- filename,
160
+ req.multipartFile = {
161
+ isPending: true,
162
+ originalname: filename,
121
163
  uniqueID,
122
164
  chunkIndex,
123
165
  totalChunks
166
+ };
167
+ next();
168
+ });
169
+ } catch (error) {
170
+ next(new _WebError.WebError({
171
+ statusCode: 500,
172
+ errorCode: 'unexpected-error',
173
+ message: 'Unexpected error in file upload',
174
+ data: {
175
+ error: error.message
124
176
  }
125
- };
126
- return next();
127
- });
128
- } catch (error) {
129
- (0, _utils.reportError)(`Failed to upload or process chunk: ${error.message}`);
130
- next(error);
131
- }
177
+ }));
178
+ }
179
+ };
132
180
  }
133
- async function mergeChunks(filename, totalChunks, sessionFolder) {
134
- const finalFilePath = _path.default.join(sessionFolder, filename);
181
+ async function mergeChunks(filename, totalChunks, sessionFolder, finalFilePath) {
135
182
  const writeStream = _fsExtra.default.createWriteStream(finalFilePath);
183
+ (0, _utils.reportDebug)({
184
+ namespace,
185
+ message: 'Merging file chunks',
186
+ data: {
187
+ finalFilePath
188
+ }
189
+ });
136
190
  for (let i = 0; i < parseInt(totalChunks, 10); i++) {
137
191
  const partPath = _path.default.join(sessionFolder, `${filename}.part${i}`);
138
192
  try {
139
193
  const chunkData = await _fsExtra.default.readFile(partPath);
140
194
  writeStream.write(chunkData);
141
195
  } catch (error) {
142
- (0, _utils.reportError)(`Error reading chunk ${i}: ${error.message}`);
143
- throw error;
196
+ throw new _WebError.WebError({
197
+ statusCode: 500,
198
+ errorCode: 'chunk-read-failed',
199
+ message: `Error reading chunk ${i}`,
200
+ data: {
201
+ error: error.message
202
+ }
203
+ });
144
204
  }
145
205
  _fsExtra.default.remove(partPath).catch(err => (0, _utils.reportError)(`Error removing part ${partPath}: ${err.message}`));
146
206
  }
147
207
  writeStream.end();
148
208
  return new Promise((resolve, reject) => {
149
209
  writeStream.on('finish', () => resolve(undefined));
150
- writeStream.on('error', error => {
151
- (0, _utils.reportError)(`Error merging chunks: ${error.message}`);
152
- reject(error);
153
- });
210
+ writeStream.on('error', error => reject(new _WebError.WebError({
211
+ statusCode: 500,
212
+ errorCode: 'file-merge-error',
213
+ message: 'Error merging file chunks',
214
+ data: {
215
+ error: error.message
216
+ }
217
+ })));
154
218
  });
155
219
  }
156
220
  //# sourceMappingURL=multiPartFileUploader.js.map