@morojs/moro 1.6.0 → 1.6.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.
- package/README.md +256 -74
- package/dist/core/auth/morojs-adapter.js +20 -20
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/config/file-loader.d.ts +6 -1
- package/dist/core/config/file-loader.js +249 -19
- package/dist/core/config/file-loader.js.map +1 -1
- package/dist/core/config/index.d.ts +12 -41
- package/dist/core/config/index.js +54 -65
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.d.ts +7 -0
- package/dist/core/config/loader.js +269 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.d.ts +2 -2
- package/dist/core/config/schema.js +44 -52
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +3 -10
- package/dist/core/config/utils.js +58 -31
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/config/validation.d.ts +17 -0
- package/dist/core/config/validation.js +131 -0
- package/dist/core/config/validation.js.map +1 -0
- package/dist/core/database/adapters/drizzle.d.ts +1 -1
- package/dist/core/database/adapters/drizzle.js +11 -18
- package/dist/core/database/adapters/drizzle.js.map +1 -1
- package/dist/core/database/adapters/index.d.ts +7 -7
- package/dist/core/database/adapters/index.js +29 -19
- package/dist/core/database/adapters/index.js.map +1 -1
- package/dist/core/database/adapters/mongodb.d.ts +1 -13
- package/dist/core/database/adapters/mongodb.js +10 -46
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +1 -14
- package/dist/core/database/adapters/mysql.js +9 -19
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.d.ts +2 -12
- package/dist/core/database/adapters/postgresql.js +9 -19
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.d.ts +1 -12
- package/dist/core/database/adapters/redis.js +13 -48
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/database/adapters/sqlite.d.ts +1 -3
- package/dist/core/database/adapters/sqlite.js +8 -19
- package/dist/core/database/adapters/sqlite.js.map +1 -1
- package/dist/core/database/index.d.ts +2 -2
- package/dist/core/database/index.js +18 -2
- package/dist/core/database/index.js.map +1 -1
- package/dist/core/docs/index.d.ts +9 -9
- package/dist/core/docs/index.js +35 -14
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/openapi-generator.d.ts +2 -2
- package/dist/core/docs/openapi-generator.js +16 -11
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/schema-to-openapi.d.ts +2 -2
- package/dist/core/docs/schema-to-openapi.js +11 -5
- package/dist/core/docs/schema-to-openapi.js.map +1 -1
- package/dist/core/docs/simple-docs.d.ts +1 -1
- package/dist/core/docs/simple-docs.js +9 -4
- package/dist/core/docs/simple-docs.js.map +1 -1
- package/dist/core/docs/swagger-ui.d.ts +2 -2
- package/dist/core/docs/swagger-ui.js +29 -26
- package/dist/core/docs/swagger-ui.js.map +1 -1
- package/dist/core/docs/zod-to-openapi.js +28 -31
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/events/event-bus.d.ts +1 -1
- package/dist/core/events/event-bus.js +10 -6
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/events/index.d.ts +2 -2
- package/dist/core/events/index.js +5 -1
- package/dist/core/events/index.js.map +1 -1
- package/dist/core/framework.d.ts +12 -19
- package/dist/core/framework.js +100 -277
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +1 -13
- package/dist/core/http/http-server.js +85 -175
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/index.d.ts +3 -4
- package/dist/core/http/index.js +8 -3
- package/dist/core/http/index.js.map +1 -1
- package/dist/core/http/router.d.ts +1 -13
- package/dist/core/http/router.js +43 -117
- package/dist/core/http/router.js.map +1 -1
- package/dist/core/logger/filters.d.ts +1 -1
- package/dist/core/logger/filters.js +23 -20
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.d.ts +3 -3
- package/dist/core/logger/index.js +24 -2
- package/dist/core/logger/index.js.map +1 -1
- package/dist/core/logger/logger.d.ts +14 -30
- package/dist/core/logger/logger.js +223 -398
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.d.ts +1 -1
- package/dist/core/logger/outputs.js +17 -8
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.js +47 -10
- package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cache/index.js +17 -10
- package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.js +7 -3
- package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +1 -3
- package/dist/core/middleware/built-in/adapters/cache/redis.js +9 -11
- package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.js +7 -3
- package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +7 -3
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +1 -3
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +10 -12
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cdn/index.js +17 -10
- package/dist/core/middleware/built-in/adapters/cdn/index.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/index.js +23 -4
- package/dist/core/middleware/built-in/adapters/index.js.map +1 -1
- package/dist/core/middleware/built-in/auth-helpers.js +22 -11
- package/dist/core/middleware/built-in/auth-helpers.js.map +1 -1
- package/dist/core/middleware/built-in/auth-providers.d.ts +1 -1
- package/dist/core/middleware/built-in/auth-providers.js +9 -4
- package/dist/core/middleware/built-in/auth-providers.js.map +1 -1
- package/dist/core/middleware/built-in/auth.d.ts +2 -2
- package/dist/core/middleware/built-in/auth.js +26 -93
- package/dist/core/middleware/built-in/auth.js.map +1 -1
- package/dist/core/middleware/built-in/cache.d.ts +2 -2
- package/dist/core/middleware/built-in/cache.js +12 -11
- package/dist/core/middleware/built-in/cache.js.map +1 -1
- package/dist/core/middleware/built-in/cdn.d.ts +2 -2
- package/dist/core/middleware/built-in/cdn.js +9 -5
- package/dist/core/middleware/built-in/cdn.js.map +1 -1
- package/dist/core/middleware/built-in/cookie.d.ts +1 -1
- package/dist/core/middleware/built-in/cookie.js +7 -3
- package/dist/core/middleware/built-in/cookie.js.map +1 -1
- package/dist/core/middleware/built-in/cors.d.ts +1 -1
- package/dist/core/middleware/built-in/cors.js +7 -3
- package/dist/core/middleware/built-in/cors.js.map +1 -1
- package/dist/core/middleware/built-in/csp.d.ts +1 -1
- package/dist/core/middleware/built-in/csp.js +8 -5
- package/dist/core/middleware/built-in/csp.js.map +1 -1
- package/dist/core/middleware/built-in/csrf.d.ts +1 -1
- package/dist/core/middleware/built-in/csrf.js +8 -5
- package/dist/core/middleware/built-in/csrf.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker.js +7 -3
- package/dist/core/middleware/built-in/error-tracker.js.map +1 -1
- package/dist/core/middleware/built-in/index.d.ts +27 -28
- package/dist/core/middleware/built-in/index.js +78 -48
- package/dist/core/middleware/built-in/index.js.map +1 -1
- package/dist/core/middleware/built-in/performance-monitor.js +7 -3
- package/dist/core/middleware/built-in/performance-monitor.js.map +1 -1
- package/dist/core/middleware/built-in/rate-limit.d.ts +1 -1
- package/dist/core/middleware/built-in/rate-limit.js +7 -3
- package/dist/core/middleware/built-in/rate-limit.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger.js +8 -5
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/middleware/built-in/session.d.ts +2 -2
- package/dist/core/middleware/built-in/session.js +15 -11
- package/dist/core/middleware/built-in/session.js.map +1 -1
- package/dist/core/middleware/built-in/sse.d.ts +1 -1
- package/dist/core/middleware/built-in/sse.js +14 -12
- package/dist/core/middleware/built-in/sse.js.map +1 -1
- package/dist/core/middleware/built-in/validation.d.ts +1 -1
- package/dist/core/middleware/built-in/validation.js +7 -3
- package/dist/core/middleware/built-in/validation.js.map +1 -1
- package/dist/core/middleware/index.d.ts +4 -4
- package/dist/core/middleware/index.js +28 -8
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +2 -19
- package/dist/core/modules/auto-discovery.js +74 -391
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/index.d.ts +2 -2
- package/dist/core/modules/index.js +9 -2
- package/dist/core/modules/index.js.map +1 -1
- package/dist/core/modules/modules.d.ts +3 -3
- package/dist/core/modules/modules.js +54 -23
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/index.d.ts +3 -4
- package/dist/core/networking/adapters/index.js +7 -3
- package/dist/core/networking/adapters/index.js.map +1 -1
- package/dist/core/networking/adapters/socketio-adapter.d.ts +1 -1
- package/dist/core/networking/adapters/socketio-adapter.js +40 -5
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +2 -2
- package/dist/core/networking/adapters/ws-adapter.js +43 -8
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/index.d.ts +2 -3
- package/dist/core/networking/index.js +7 -2
- package/dist/core/networking/index.js.map +1 -1
- package/dist/core/networking/service-discovery.js +12 -8
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/networking/websocket-adapter.js +2 -1
- package/dist/core/networking/websocket-adapter.js.map +1 -1
- package/dist/core/networking/websocket-manager.d.ts +3 -3
- package/dist/core/networking/websocket-manager.js +11 -9
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/routing/app-integration.d.ts +2 -2
- package/dist/core/routing/app-integration.js +12 -7
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/index.d.ts +2 -22
- package/dist/core/routing/index.js +27 -185
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/aws-lambda-adapter.d.ts +3 -3
- package/dist/core/runtime/aws-lambda-adapter.js +6 -2
- package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
- package/dist/core/runtime/base-adapter.d.ts +2 -2
- package/dist/core/runtime/base-adapter.js +7 -3
- package/dist/core/runtime/base-adapter.js.map +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.d.ts +3 -3
- package/dist/core/runtime/cloudflare-workers-adapter.js +6 -2
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
- package/dist/core/runtime/index.d.ts +12 -12
- package/dist/core/runtime/index.js +35 -22
- package/dist/core/runtime/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.d.ts +4 -4
- package/dist/core/runtime/node-adapter.js +49 -18
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/core/runtime/vercel-edge-adapter.d.ts +3 -3
- package/dist/core/runtime/vercel-edge-adapter.js +6 -2
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
- package/dist/core/utilities/circuit-breaker.js +5 -1
- package/dist/core/utilities/circuit-breaker.js.map +1 -1
- package/dist/core/utilities/container.js +22 -12
- package/dist/core/utilities/container.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +2 -2
- package/dist/core/utilities/hooks.js +12 -7
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/core/utilities/index.d.ts +4 -5
- package/dist/core/utilities/index.js +19 -5
- package/dist/core/utilities/index.js.map +1 -1
- package/dist/core/validation/adapters.d.ts +1 -1
- package/dist/core/validation/adapters.js +26 -15
- package/dist/core/validation/adapters.js.map +1 -1
- package/dist/core/validation/index.d.ts +4 -6
- package/dist/core/validation/index.js +28 -57
- package/dist/core/validation/index.js.map +1 -1
- package/dist/core/validation/schema-interface.js +9 -3
- package/dist/core/validation/schema-interface.js.map +1 -1
- package/dist/index.d.ts +52 -51
- package/dist/index.js +132 -23
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +10 -61
- package/dist/moro.js +237 -575
- package/dist/moro.js.map +1 -1
- package/dist/types/auth.js +9 -3
- package/dist/types/auth.js.map +1 -1
- package/dist/types/cache.js +2 -1
- package/dist/types/cdn.js +2 -1
- package/dist/types/config.d.ts +2 -70
- package/dist/types/config.js +2 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/core.d.ts +42 -36
- package/dist/types/core.js +2 -1
- package/dist/types/database.js +2 -1
- package/dist/types/discovery.js +2 -1
- package/dist/types/events.js +2 -1
- package/dist/types/hooks.d.ts +1 -1
- package/dist/types/hooks.js +2 -1
- package/dist/types/http.d.ts +1 -16
- package/dist/types/http.js +2 -1
- package/dist/types/logger.d.ts +0 -7
- package/dist/types/logger.js +2 -1
- package/dist/types/module.d.ts +0 -11
- package/dist/types/module.js +2 -1
- package/dist/types/runtime.d.ts +1 -1
- package/dist/types/runtime.js +2 -1
- package/dist/types/session.js +2 -1
- package/package.json +52 -19
- package/src/core/auth/morojs-adapter.ts +13 -18
- package/src/core/config/file-loader.ts +273 -13
- package/src/core/config/index.ts +34 -83
- package/src/core/config/loader.ts +633 -0
- package/src/core/config/schema.ts +33 -44
- package/src/core/config/utils.ts +31 -24
- package/src/core/config/validation.ts +140 -0
- package/src/core/database/README.md +16 -26
- package/src/core/database/adapters/drizzle.ts +6 -18
- package/src/core/database/adapters/index.ts +13 -13
- package/src/core/database/adapters/mongodb.ts +5 -53
- package/src/core/database/adapters/mysql.ts +4 -32
- package/src/core/database/adapters/postgresql.ts +5 -30
- package/src/core/database/adapters/redis.ts +8 -61
- package/src/core/database/adapters/sqlite.ts +3 -19
- package/src/core/database/index.ts +2 -2
- package/src/core/docs/index.ts +8 -8
- package/src/core/docs/openapi-generator.ts +4 -4
- package/src/core/docs/schema-to-openapi.ts +6 -3
- package/src/core/docs/simple-docs.ts +2 -2
- package/src/core/docs/swagger-ui.ts +16 -19
- package/src/core/docs/zod-to-openapi.ts +34 -34
- package/src/core/events/event-bus.ts +2 -2
- package/src/core/events/index.ts +2 -2
- package/src/core/framework.ts +67 -311
- package/src/core/http/http-server.ts +45 -190
- package/src/core/http/index.ts +3 -4
- package/src/core/http/router.ts +40 -129
- package/src/core/logger/filters.ts +5 -13
- package/src/core/logger/index.ts +3 -4
- package/src/core/logger/logger.ts +216 -435
- package/src/core/logger/outputs.ts +3 -1
- package/src/core/middleware/built-in/adapters/cache/file.ts +3 -3
- package/src/core/middleware/built-in/adapters/cache/index.ts +7 -7
- package/src/core/middleware/built-in/adapters/cache/memory.ts +2 -2
- package/src/core/middleware/built-in/adapters/cache/redis.ts +4 -18
- package/src/core/middleware/built-in/adapters/cdn/azure.ts +2 -2
- package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +2 -2
- package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +5 -16
- package/src/core/middleware/built-in/adapters/cdn/index.ts +7 -7
- package/src/core/middleware/built-in/adapters/index.ts +4 -4
- package/src/core/middleware/built-in/auth-helpers.ts +1 -1
- package/src/core/middleware/built-in/auth-providers.ts +1 -1
- package/src/core/middleware/built-in/auth.ts +21 -102
- package/src/core/middleware/built-in/cache.ts +6 -8
- package/src/core/middleware/built-in/cdn.ts +4 -4
- package/src/core/middleware/built-in/cookie.ts +2 -2
- package/src/core/middleware/built-in/cors.ts +2 -2
- package/src/core/middleware/built-in/csp.ts +3 -3
- package/src/core/middleware/built-in/csrf.ts +3 -3
- package/src/core/middleware/built-in/error-tracker.ts +1 -1
- package/src/core/middleware/built-in/index.ts +30 -38
- package/src/core/middleware/built-in/performance-monitor.ts +1 -1
- package/src/core/middleware/built-in/rate-limit.ts +2 -2
- package/src/core/middleware/built-in/request-logger.ts +1 -3
- package/src/core/middleware/built-in/session.ts +8 -7
- package/src/core/middleware/built-in/sse.ts +9 -11
- package/src/core/middleware/built-in/validation.ts +2 -2
- package/src/core/middleware/index.ts +6 -6
- package/src/core/modules/auto-discovery.ts +15 -478
- package/src/core/modules/index.ts +2 -2
- package/src/core/modules/modules.ts +12 -23
- package/src/core/networking/adapters/index.ts +3 -4
- package/src/core/networking/adapters/socketio-adapter.ts +3 -5
- package/src/core/networking/adapters/ws-adapter.ts +9 -8
- package/src/core/networking/index.ts +2 -3
- package/src/core/networking/service-discovery.ts +7 -6
- package/src/core/networking/websocket-manager.ts +7 -7
- package/src/core/routing/app-integration.ts +3 -3
- package/src/core/routing/index.ts +17 -201
- package/src/core/runtime/aws-lambda-adapter.ts +3 -3
- package/src/core/runtime/base-adapter.ts +2 -2
- package/src/core/runtime/cloudflare-workers-adapter.ts +3 -3
- package/src/core/runtime/index.ts +13 -13
- package/src/core/runtime/node-adapter.ts +10 -16
- package/src/core/runtime/vercel-edge-adapter.ts +3 -3
- package/src/core/utilities/hooks.ts +3 -3
- package/src/core/utilities/index.ts +4 -5
- package/src/core/validation/adapters.ts +1 -1
- package/src/core/validation/index.ts +16 -68
- package/src/index.ts +66 -73
- package/src/moro.ts +204 -685
- package/src/types/config.ts +2 -71
- package/src/types/core.ts +47 -49
- package/src/types/hooks.ts +1 -1
- package/src/types/http.ts +1 -23
- package/src/types/logger.ts +0 -9
- package/src/types/module.ts +0 -12
- package/src/types/runtime.ts +1 -1
- package/tsconfig.json +2 -4
- package/dist/core/config/config-manager.d.ts +0 -44
- package/dist/core/config/config-manager.js +0 -104
- package/dist/core/config/config-manager.js.map +0 -1
- package/dist/core/config/config-sources.d.ts +0 -21
- package/dist/core/config/config-sources.js +0 -499
- package/dist/core/config/config-sources.js.map +0 -1
- package/dist/core/config/config-validator.d.ts +0 -21
- package/dist/core/config/config-validator.js +0 -788
- package/dist/core/config/config-validator.js.map +0 -1
- package/dist/core/http/uws-http-server.d.ts +0 -64
- package/dist/core/http/uws-http-server.js +0 -688
- package/dist/core/http/uws-http-server.js.map +0 -1
- package/dist/core/middleware/built-in/jwt-helpers.d.ts +0 -118
- package/dist/core/middleware/built-in/jwt-helpers.js +0 -218
- package/dist/core/middleware/built-in/jwt-helpers.js.map +0 -1
- package/dist/core/networking/adapters/uws-adapter.d.ts +0 -44
- package/dist/core/networking/adapters/uws-adapter.js +0 -513
- package/dist/core/networking/adapters/uws-adapter.js.map +0 -1
- package/dist/core/utilities/package-utils.d.ts +0 -38
- package/dist/core/utilities/package-utils.js +0 -57
- package/dist/core/utilities/package-utils.js.map +0 -1
- package/jest.config.mjs +0 -41
- package/src/core/config/config-manager.ts +0 -133
- package/src/core/config/config-sources.ts +0 -596
- package/src/core/config/config-validator.ts +0 -1113
- package/src/core/http/uws-http-server.ts +0 -794
- package/src/core/middleware/built-in/jwt-helpers.ts +0 -243
- package/src/core/networking/adapters/uws-adapter.ts +0 -619
- package/src/core/utilities/package-utils.ts +0 -59
package/dist/moro.js
CHANGED
|
@@ -1,39 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Moro = void 0;
|
|
37
|
+
exports.createApp = createApp;
|
|
38
|
+
exports.createAppNode = createAppNode;
|
|
39
|
+
exports.createAppEdge = createAppEdge;
|
|
40
|
+
exports.createAppLambda = createAppLambda;
|
|
41
|
+
exports.createAppWorker = createAppWorker;
|
|
1
42
|
// Moro Framework - Modern TypeScript API Framework
|
|
2
43
|
// Built for developers who demand performance, elegance, and zero compromises
|
|
3
44
|
// Event-driven • Modular • Enterprise-ready • Developer-first
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { normalizeValidationError } from './core/validation/schema-interface.js';
|
|
45
|
+
const framework_1 = require("./core/framework");
|
|
46
|
+
const http_1 = require("./core/http");
|
|
47
|
+
const logger_1 = require("./core/logger");
|
|
48
|
+
const middleware_1 = require("./core/middleware");
|
|
49
|
+
const app_integration_1 = require("./core/routing/app-integration");
|
|
50
|
+
const docs_1 = require("./core/docs");
|
|
51
|
+
const fs_1 = require("fs");
|
|
52
|
+
const path_1 = require("path");
|
|
53
|
+
const events_1 = require("events");
|
|
14
54
|
// Configuration System Integration
|
|
15
|
-
|
|
55
|
+
const config_1 = require("./core/config");
|
|
16
56
|
// Runtime System Integration
|
|
17
|
-
|
|
18
|
-
|
|
57
|
+
const runtime_1 = require("./core/runtime");
|
|
58
|
+
class Moro extends events_1.EventEmitter {
|
|
19
59
|
coreFramework;
|
|
20
60
|
routes = [];
|
|
21
61
|
moduleCounter = 0;
|
|
22
62
|
loadedModules = new Set();
|
|
23
|
-
lazyModules = new Map();
|
|
24
63
|
routeHandlers = {};
|
|
25
|
-
moduleDiscovery; // Store for cleanup
|
|
26
|
-
autoDiscoveryOptions = null;
|
|
27
|
-
autoDiscoveryInitialized = false;
|
|
28
|
-
autoDiscoveryPromise = null;
|
|
29
64
|
// Enterprise event system integration
|
|
30
65
|
eventBus;
|
|
31
66
|
// Application logger
|
|
32
|
-
logger;
|
|
67
|
+
logger = (0, logger_1.createFrameworkLogger)('App');
|
|
33
68
|
// Intelligent routing system
|
|
34
|
-
intelligentRouting = new IntelligentRoutingManager();
|
|
69
|
+
intelligentRouting = new app_integration_1.IntelligentRoutingManager();
|
|
35
70
|
// Documentation system
|
|
36
|
-
documentation = new AppDocumentationManager();
|
|
71
|
+
documentation = new docs_1.AppDocumentationManager();
|
|
37
72
|
// Configuration system
|
|
38
73
|
config;
|
|
39
74
|
// Runtime system
|
|
@@ -41,48 +76,79 @@ export class Moro extends EventEmitter {
|
|
|
41
76
|
runtimeType;
|
|
42
77
|
// Middleware system
|
|
43
78
|
middlewareManager;
|
|
44
|
-
// Queued WebSocket registrations (for async adapter detection)
|
|
45
|
-
queuedWebSocketRegistrations = [];
|
|
46
79
|
constructor(options = {}) {
|
|
47
80
|
super(); // Call EventEmitter constructor
|
|
48
|
-
//
|
|
49
|
-
//
|
|
81
|
+
// Configure logger from environment variables BEFORE config system initialization
|
|
82
|
+
// This ensures the config loading process respects the log level
|
|
50
83
|
const envLogLevel = process.env.LOG_LEVEL || process.env.MORO_LOG_LEVEL;
|
|
51
84
|
if (envLogLevel) {
|
|
52
|
-
applyLoggingConfiguration({ level: envLogLevel }, undefined);
|
|
85
|
+
(0, logger_1.applyLoggingConfiguration)({ level: envLogLevel }, undefined);
|
|
86
|
+
}
|
|
87
|
+
// Initialize configuration system - create a deep copy for this instance
|
|
88
|
+
this.config = JSON.parse(JSON.stringify((0, config_1.initializeConfig)()));
|
|
89
|
+
// Apply logging configuration from the loaded config (this happens after config file processing)
|
|
90
|
+
if (this.config.logging) {
|
|
91
|
+
(0, logger_1.applyLoggingConfiguration)(this.config.logging, undefined);
|
|
53
92
|
}
|
|
54
|
-
//
|
|
93
|
+
// Apply additional logging configuration from createApp options (takes precedence)
|
|
55
94
|
if (options.logger !== undefined) {
|
|
56
|
-
applyLoggingConfiguration(undefined, options.logger);
|
|
95
|
+
(0, logger_1.applyLoggingConfiguration)(undefined, options.logger);
|
|
96
|
+
}
|
|
97
|
+
// Apply performance configuration from createApp options (takes precedence)
|
|
98
|
+
if (options.performance) {
|
|
99
|
+
if (options.performance.clustering) {
|
|
100
|
+
this.config.performance.clustering = {
|
|
101
|
+
...this.config.performance.clustering,
|
|
102
|
+
...options.performance.clustering,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (options.performance.compression) {
|
|
106
|
+
this.config.performance.compression = {
|
|
107
|
+
...this.config.performance.compression,
|
|
108
|
+
...options.performance.compression,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (options.performance.circuitBreaker) {
|
|
112
|
+
this.config.performance.circuitBreaker = {
|
|
113
|
+
...this.config.performance.circuitBreaker,
|
|
114
|
+
...options.performance.circuitBreaker,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
57
117
|
}
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
118
|
+
// Apply modules configuration from createApp options (takes precedence)
|
|
119
|
+
if (options.modules) {
|
|
120
|
+
if (options.modules.cache) {
|
|
121
|
+
this.config.modules.cache = {
|
|
122
|
+
...this.config.modules.cache,
|
|
123
|
+
...options.modules.cache,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (options.modules.rateLimit) {
|
|
127
|
+
this.config.modules.rateLimit = {
|
|
128
|
+
...this.config.modules.rateLimit,
|
|
129
|
+
...options.modules.rateLimit,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (options.modules.validation) {
|
|
133
|
+
this.config.modules.validation = {
|
|
134
|
+
...this.config.modules.validation,
|
|
135
|
+
...options.modules.validation,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
67
138
|
}
|
|
68
|
-
this.logger.info(`Configuration system initialized: ${
|
|
139
|
+
this.logger.info(`Configuration system initialized: ${this.config.server.environment}:${this.config.server.port}`);
|
|
69
140
|
// Initialize runtime system
|
|
70
141
|
this.runtimeType = options.runtime?.type || 'node';
|
|
71
|
-
this.runtimeAdapter = options.runtime?.adapter || createRuntimeAdapter(this.runtimeType);
|
|
142
|
+
this.runtimeAdapter = options.runtime?.adapter || (0, runtime_1.createRuntimeAdapter)(this.runtimeType);
|
|
72
143
|
this.logger.info(`Runtime system initialized: ${this.runtimeType}`, 'Runtime');
|
|
73
|
-
// Pass configuration from config to framework
|
|
144
|
+
// Pass logging configuration from config to framework
|
|
74
145
|
const frameworkOptions = {
|
|
75
146
|
...options,
|
|
76
147
|
logger: this.config.logging,
|
|
77
|
-
// Enable websockets if either config has it enabled OR user passed websocket options
|
|
78
|
-
websocket: this.config.websocket.enabled || options.websocket
|
|
79
|
-
? options.websocket || this.config.websocket || {}
|
|
80
|
-
: false,
|
|
81
|
-
config: this.config,
|
|
82
148
|
};
|
|
83
|
-
this.coreFramework = new
|
|
149
|
+
this.coreFramework = new framework_1.Moro(frameworkOptions);
|
|
84
150
|
// Initialize middleware system
|
|
85
|
-
this.middlewareManager = new MiddlewareManager();
|
|
151
|
+
this.middlewareManager = new middleware_1.MiddlewareManager();
|
|
86
152
|
// Integrate hooks system with HTTP server
|
|
87
153
|
const httpServer = this.coreFramework.httpServer;
|
|
88
154
|
if (httpServer && httpServer.setHookManager) {
|
|
@@ -103,10 +169,10 @@ export class Moro extends EventEmitter {
|
|
|
103
169
|
...this.getDefaultOptionsFromConfig(),
|
|
104
170
|
...options,
|
|
105
171
|
});
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
172
|
+
// Auto-discover modules if enabled
|
|
173
|
+
if (options.autoDiscover !== false) {
|
|
174
|
+
this.autoDiscoverModules(options.modulesPath || './modules');
|
|
175
|
+
}
|
|
110
176
|
// Emit initialization event through enterprise event bus
|
|
111
177
|
this.eventBus.emit('framework:initialized', {
|
|
112
178
|
options,
|
|
@@ -272,11 +338,6 @@ export class Moro extends EventEmitter {
|
|
|
272
338
|
version: moduleOrPath.version || '1.0.0',
|
|
273
339
|
});
|
|
274
340
|
}
|
|
275
|
-
// IMPORTANT: If modules are loaded manually after auto-discovery,
|
|
276
|
-
// ensure the final module handler is set up to maintain middleware order
|
|
277
|
-
if (this.autoDiscoveryInitialized) {
|
|
278
|
-
this.coreFramework.setupFinalModuleHandler();
|
|
279
|
-
}
|
|
280
341
|
return this;
|
|
281
342
|
}
|
|
282
343
|
// Database helper with events
|
|
@@ -290,36 +351,29 @@ export class Moro extends EventEmitter {
|
|
|
290
351
|
}
|
|
291
352
|
// WebSocket helper with events
|
|
292
353
|
websocket(namespace, handlers) {
|
|
293
|
-
// Queue the registration to be processed after adapter initialization
|
|
294
|
-
const registration = { namespace, handlers, processed: false };
|
|
295
|
-
this.queuedWebSocketRegistrations.push(registration);
|
|
296
|
-
// Try to process immediately if adapter is already ready
|
|
297
354
|
const adapter = this.coreFramework.getWebSocketAdapter();
|
|
298
|
-
if (adapter
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
355
|
+
if (!adapter) {
|
|
356
|
+
throw new Error('WebSocket features require a WebSocket adapter. Install socket.io or configure an adapter:\n' +
|
|
357
|
+
'npm install socket.io\n' +
|
|
358
|
+
'or\n' +
|
|
359
|
+
'new Moro({ websocket: { adapter: new SocketIOAdapter() } })');
|
|
302
360
|
}
|
|
303
|
-
// Otherwise, it will be processed when the server starts
|
|
304
|
-
return this;
|
|
305
|
-
}
|
|
306
|
-
processWebSocketRegistration(namespace, handlers, adapter) {
|
|
307
361
|
this.emit('websocket:registering', { namespace, handlers });
|
|
308
362
|
const ns = adapter.createNamespace(namespace);
|
|
309
363
|
Object.entries(handlers).forEach(([event, handler]) => {
|
|
310
|
-
ns.on('connection',
|
|
364
|
+
ns.on('connection', socket => {
|
|
311
365
|
this.emit('websocket:connection', { namespace, event, socket });
|
|
312
366
|
socket.on(event, (data, callback) => {
|
|
313
367
|
this.emit('websocket:event', { namespace, event, data });
|
|
314
368
|
Promise.resolve(handler(socket, data))
|
|
315
|
-
.then(
|
|
369
|
+
.then(result => {
|
|
316
370
|
this.emit('websocket:response', { namespace, event, result });
|
|
317
371
|
if (callback)
|
|
318
372
|
callback(result);
|
|
319
373
|
else if (result)
|
|
320
374
|
socket.emit(`${event}:response`, result);
|
|
321
375
|
})
|
|
322
|
-
.catch(
|
|
376
|
+
.catch(error => {
|
|
323
377
|
this.emit('websocket:error', { namespace, event, error });
|
|
324
378
|
const errorResponse = { success: false, error: error.message };
|
|
325
379
|
if (callback)
|
|
@@ -331,33 +385,7 @@ export class Moro extends EventEmitter {
|
|
|
331
385
|
});
|
|
332
386
|
});
|
|
333
387
|
this.emit('websocket:registered', { namespace, handlers });
|
|
334
|
-
|
|
335
|
-
async processQueuedWebSocketRegistrations() {
|
|
336
|
-
// Wait for WebSocket adapter to be ready
|
|
337
|
-
await this.coreFramework.ensureWebSocketReady();
|
|
338
|
-
const adapter = this.coreFramework.getWebSocketAdapter();
|
|
339
|
-
// Check if any unprocessed registrations exist
|
|
340
|
-
const unprocessedRegistrations = this.queuedWebSocketRegistrations.filter(r => !r.processed);
|
|
341
|
-
if (!adapter && unprocessedRegistrations.length > 0) {
|
|
342
|
-
throw new Error('WebSocket features require a WebSocket adapter.\n\n' +
|
|
343
|
-
'Option 1: Install socket.io (auto-detected):\n' +
|
|
344
|
-
' npm install socket.io\n' +
|
|
345
|
-
' const app = new Moro({ websocket: {} });\n\n' +
|
|
346
|
-
'Option 2: Configure a specific adapter:\n' +
|
|
347
|
-
" import { SocketIOAdapter } from '@morojs/moro';\n" +
|
|
348
|
-
' const app = new Moro({ websocket: { adapter: new SocketIOAdapter() } });\n\n' +
|
|
349
|
-
'Option 3: Enable in config file (moro.config.js):\n' +
|
|
350
|
-
' export default { websocket: { enabled: true } };');
|
|
351
|
-
}
|
|
352
|
-
if (adapter) {
|
|
353
|
-
// Process all unprocessed registrations
|
|
354
|
-
for (const registration of this.queuedWebSocketRegistrations) {
|
|
355
|
-
if (!registration.processed) {
|
|
356
|
-
this.processWebSocketRegistration(registration.namespace, registration.handlers, adapter);
|
|
357
|
-
registration.processed = true;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
388
|
+
return this;
|
|
361
389
|
}
|
|
362
390
|
listen(portOrCallback, hostOrCallback, callback) {
|
|
363
391
|
// Only available for Node.js runtime
|
|
@@ -399,18 +427,9 @@ export class Moro extends EventEmitter {
|
|
|
399
427
|
throw new Error('Port not specified and not found in configuration. Please provide a port number or configure it in moro.config.js/ts');
|
|
400
428
|
}
|
|
401
429
|
// Check if clustering is enabled for massive performance gains
|
|
402
|
-
// NOTE: uWebSockets.js does NOT support Node.js clustering - it's single-threaded only
|
|
403
|
-
const usingUWebSockets = this.config.server?.useUWebSockets || false;
|
|
404
430
|
if (this.config.performance?.clustering?.enabled) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
'uWebSockets is so fast that single-threaded performance often exceeds multi-threaded Node.js!', 'Cluster');
|
|
408
|
-
// Continue without clustering
|
|
409
|
-
}
|
|
410
|
-
else {
|
|
411
|
-
this.startWithClustering(port, host, callback);
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
431
|
+
this.startWithClustering(port, host, callback);
|
|
432
|
+
return;
|
|
414
433
|
}
|
|
415
434
|
this.eventBus.emit('server:starting', { port, runtime: this.runtimeType });
|
|
416
435
|
// Add documentation middleware first (if enabled)
|
|
@@ -435,139 +454,32 @@ export class Moro extends EventEmitter {
|
|
|
435
454
|
if (this.routes.length > 0) {
|
|
436
455
|
this.registerDirectRoutes();
|
|
437
456
|
}
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (intelligentRoutes.length > 0) {
|
|
451
|
-
this.logger.info(`Intelligent Routes: ${intelligentRoutes.length} registered`, 'Server');
|
|
452
|
-
}
|
|
453
|
-
this.eventBus.emit('server:started', { port, runtime: this.runtimeType });
|
|
454
|
-
if (callback)
|
|
455
|
-
callback();
|
|
456
|
-
};
|
|
457
|
-
if (host && typeof host === 'string') {
|
|
458
|
-
this.coreFramework.listen(port, host, actualCallback);
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
this.coreFramework.listen(port, actualCallback);
|
|
457
|
+
const actualCallback = () => {
|
|
458
|
+
const displayHost = host || 'localhost';
|
|
459
|
+
this.logger.info('Moro Server Started', 'Server');
|
|
460
|
+
this.logger.info(`Runtime: ${this.runtimeType}`, 'Server');
|
|
461
|
+
this.logger.info(`HTTP API: http://${displayHost}:${port}`, 'Server');
|
|
462
|
+
this.logger.info(`WebSocket: ws://${displayHost}:${port}`, 'Server');
|
|
463
|
+
this.logger.info('Native Node.js HTTP • Zero Dependencies • Maximum Performance', 'Server');
|
|
464
|
+
this.logger.info('Learn more at https://morojs.com', 'Server');
|
|
465
|
+
// Log intelligent routes info
|
|
466
|
+
const intelligentRoutes = this.intelligentRouting.getIntelligentRoutes();
|
|
467
|
+
if (intelligentRoutes.length > 0) {
|
|
468
|
+
this.logger.info(`Intelligent Routes: ${intelligentRoutes.length} registered`, 'Server');
|
|
462
469
|
}
|
|
470
|
+
this.eventBus.emit('server:started', { port, runtime: this.runtimeType });
|
|
471
|
+
if (callback)
|
|
472
|
+
callback();
|
|
463
473
|
};
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
.then(() => {
|
|
467
|
-
startServer();
|
|
468
|
-
})
|
|
469
|
-
.catch(error => {
|
|
470
|
-
this.logger.error('Initialization failed during server start', 'Framework', {
|
|
471
|
-
error: error instanceof Error ? error.message : String(error),
|
|
472
|
-
});
|
|
473
|
-
// For auto-discovery failures, start server anyway
|
|
474
|
-
// For WebSocket failures with queued registrations, error will propagate
|
|
475
|
-
if (error instanceof Error &&
|
|
476
|
-
error.message.includes('WebSocket features require a WebSocket adapter')) {
|
|
477
|
-
throw error;
|
|
478
|
-
}
|
|
479
|
-
startServer();
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
// Public method to manually initialize auto-discovery
|
|
483
|
-
// Useful for ensuring auth middleware is registered before auto-discovery
|
|
484
|
-
async initializeAutoDiscoveryNow() {
|
|
485
|
-
return this.ensureAutoDiscoveryComplete();
|
|
486
|
-
}
|
|
487
|
-
// Public API: Initialize modules explicitly after middleware setup
|
|
488
|
-
// This provides users with explicit control over module loading timing
|
|
489
|
-
// IMPORTANT: This forces module loading even if autoDiscovery.enabled is false
|
|
490
|
-
// Usage: app.initModules() or app.initModules({ paths: ['./my-modules'] })
|
|
491
|
-
initModules(options) {
|
|
492
|
-
this.logger.info('User-requested module initialization', 'ModuleSystem');
|
|
493
|
-
// If already initialized, do nothing
|
|
494
|
-
if (this.autoDiscoveryInitialized) {
|
|
495
|
-
this.logger.debug('Auto-discovery already completed, skipping', 'ModuleSystem');
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
// Store the options and mark that we want to force initialization
|
|
499
|
-
this.autoDiscoveryOptions = {
|
|
500
|
-
autoDiscover: {
|
|
501
|
-
enabled: true, // Force enabled regardless of original config
|
|
502
|
-
paths: options?.paths || ['./modules', './src/modules'],
|
|
503
|
-
patterns: options?.patterns || [
|
|
504
|
-
'**/*.module.{ts,js}',
|
|
505
|
-
'**/index.{ts,js}',
|
|
506
|
-
'**/*.config.{ts,js}',
|
|
507
|
-
],
|
|
508
|
-
recursive: options?.recursive ?? true,
|
|
509
|
-
loadingStrategy: options?.loadingStrategy || 'eager',
|
|
510
|
-
watchForChanges: options?.watchForChanges ?? false,
|
|
511
|
-
ignorePatterns: options?.ignorePatterns || [
|
|
512
|
-
'**/*.test.{ts,js}',
|
|
513
|
-
'**/*.spec.{ts,js}',
|
|
514
|
-
'**/node_modules/**',
|
|
515
|
-
],
|
|
516
|
-
loadOrder: options?.loadOrder || 'dependency',
|
|
517
|
-
failOnError: options?.failOnError ?? false,
|
|
518
|
-
maxDepth: options?.maxDepth ?? 5,
|
|
519
|
-
},
|
|
520
|
-
};
|
|
521
|
-
this.logger.debug('Module initialization options stored, will execute on next listen/getHandler call', 'ModuleSystem');
|
|
522
|
-
}
|
|
523
|
-
// Robust method to ensure auto-discovery is complete, handling race conditions
|
|
524
|
-
async ensureAutoDiscoveryComplete() {
|
|
525
|
-
// If already initialized, nothing to do
|
|
526
|
-
if (this.autoDiscoveryInitialized) {
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
// If auto-discovery is disabled, mark as initialized
|
|
530
|
-
if (!this.autoDiscoveryOptions) {
|
|
531
|
-
this.autoDiscoveryInitialized = true;
|
|
532
|
-
return;
|
|
474
|
+
if (host && typeof host === 'string') {
|
|
475
|
+
this.coreFramework.listen(port, host, actualCallback);
|
|
533
476
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
return this.autoDiscoveryPromise;
|
|
537
|
-
}
|
|
538
|
-
// Start auto-discovery
|
|
539
|
-
this.autoDiscoveryPromise = this.performAutoDiscovery();
|
|
540
|
-
try {
|
|
541
|
-
await this.autoDiscoveryPromise;
|
|
542
|
-
this.autoDiscoveryInitialized = true;
|
|
543
|
-
}
|
|
544
|
-
catch (error) {
|
|
545
|
-
// Reset promise on error so it can be retried
|
|
546
|
-
this.autoDiscoveryPromise = null;
|
|
547
|
-
throw error;
|
|
548
|
-
}
|
|
549
|
-
finally {
|
|
550
|
-
this.autoDiscoveryOptions = null; // Clear after attempt
|
|
477
|
+
else {
|
|
478
|
+
this.coreFramework.listen(port, actualCallback);
|
|
551
479
|
}
|
|
552
480
|
}
|
|
553
|
-
// Perform the actual auto-discovery work
|
|
554
|
-
async performAutoDiscovery(optionsOverride) {
|
|
555
|
-
const optionsToUse = optionsOverride || this.autoDiscoveryOptions;
|
|
556
|
-
if (!optionsToUse)
|
|
557
|
-
return;
|
|
558
|
-
this.logger.debug('Starting auto-discovery initialization', 'AutoDiscovery');
|
|
559
|
-
await this.initializeAutoDiscovery(optionsToUse);
|
|
560
|
-
this.logger.debug('Auto-discovery initialization completed', 'AutoDiscovery');
|
|
561
|
-
}
|
|
562
481
|
// Get handler for non-Node.js runtimes
|
|
563
482
|
getHandler() {
|
|
564
|
-
// Ensure auto-discovery is complete for non-Node.js runtimes
|
|
565
|
-
// This handles the case where users call getHandler() immediately after createApp()
|
|
566
|
-
this.ensureAutoDiscoveryComplete().catch(error => {
|
|
567
|
-
this.logger.error('Auto-discovery initialization failed for runtime handler', 'Framework', {
|
|
568
|
-
error: error instanceof Error ? error.message : String(error),
|
|
569
|
-
});
|
|
570
|
-
});
|
|
571
483
|
// Create a unified request handler that works with the runtime adapter
|
|
572
484
|
const handler = async (req, res) => {
|
|
573
485
|
// Add documentation middleware first (if enabled)
|
|
@@ -785,6 +697,7 @@ export class Moro extends EventEmitter {
|
|
|
785
697
|
}
|
|
786
698
|
catch (error) {
|
|
787
699
|
// Handle universal validation errors
|
|
700
|
+
const { normalizeValidationError } = require('./core/validation/schema-interface');
|
|
788
701
|
const normalizedError = normalizeValidationError(error);
|
|
789
702
|
res.status(400).json({
|
|
790
703
|
success: false,
|
|
@@ -854,266 +767,91 @@ export class Moro extends EventEmitter {
|
|
|
854
767
|
return true;
|
|
855
768
|
}
|
|
856
769
|
setupDefaultMiddleware(options) {
|
|
857
|
-
// CORS
|
|
858
|
-
if (
|
|
859
|
-
const corsOptions = typeof options.cors === 'object'
|
|
860
|
-
|
|
861
|
-
: this.config.security.cors
|
|
862
|
-
? this.config.security.cors
|
|
863
|
-
: {};
|
|
864
|
-
this.use(middleware.cors(corsOptions));
|
|
770
|
+
// CORS
|
|
771
|
+
if (options.cors !== false) {
|
|
772
|
+
const corsOptions = typeof options.cors === 'object' ? options.cors : {};
|
|
773
|
+
this.use(http_1.middleware.cors(corsOptions));
|
|
865
774
|
}
|
|
866
|
-
// Helmet
|
|
867
|
-
if (
|
|
868
|
-
this.use(middleware.helmet());
|
|
775
|
+
// Helmet
|
|
776
|
+
if (options.helmet !== false) {
|
|
777
|
+
this.use(http_1.middleware.helmet());
|
|
869
778
|
}
|
|
870
|
-
// Compression
|
|
871
|
-
if (
|
|
872
|
-
options.
|
|
873
|
-
|
|
874
|
-
? options.compression
|
|
875
|
-
: this.config.performance.compression
|
|
876
|
-
? this.config.performance.compression
|
|
877
|
-
: {};
|
|
878
|
-
this.use(middleware.compression(compressionOptions));
|
|
779
|
+
// Compression
|
|
780
|
+
if (options.compression !== false) {
|
|
781
|
+
const compressionOptions = typeof options.compression === 'object' ? options.compression : {};
|
|
782
|
+
this.use(http_1.middleware.compression(compressionOptions));
|
|
879
783
|
}
|
|
880
784
|
// Body size limiting
|
|
881
|
-
this.use(middleware.bodySize({ limit: '10mb' }));
|
|
785
|
+
this.use(http_1.middleware.bodySize({ limit: '10mb' }));
|
|
882
786
|
}
|
|
883
|
-
|
|
884
|
-
async initializeAutoDiscovery(options) {
|
|
885
|
-
const { ModuleDiscovery } = await import('./core/modules/auto-discovery.js');
|
|
886
|
-
// Merge auto-discovery configuration
|
|
887
|
-
const autoDiscoveryConfig = this.mergeAutoDiscoveryConfig(options);
|
|
888
|
-
if (!autoDiscoveryConfig.enabled) {
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
this.moduleDiscovery = new ModuleDiscovery(process.cwd());
|
|
787
|
+
autoDiscoverModules(modulesPath) {
|
|
892
788
|
try {
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
909
|
-
if (autoDiscoveryConfig.failOnError) {
|
|
910
|
-
throw new Error(`Module auto-discovery failed: ${errorMsg}`);
|
|
911
|
-
}
|
|
912
|
-
else {
|
|
913
|
-
this.logger.warn(`Module auto-discovery failed: ${errorMsg}`, 'ModuleDiscovery');
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
// Merge auto-discovery configuration from multiple sources
|
|
918
|
-
mergeAutoDiscoveryConfig(options) {
|
|
919
|
-
const defaultConfig = this.config.modules.autoDiscovery;
|
|
920
|
-
// Handle legacy modulesPath option
|
|
921
|
-
if (options.modulesPath && !options.autoDiscover) {
|
|
922
|
-
return {
|
|
923
|
-
...defaultConfig,
|
|
924
|
-
paths: [options.modulesPath],
|
|
925
|
-
};
|
|
926
|
-
}
|
|
927
|
-
// Handle boolean autoDiscover option
|
|
928
|
-
if (typeof options.autoDiscover === 'boolean') {
|
|
929
|
-
return {
|
|
930
|
-
...defaultConfig,
|
|
931
|
-
enabled: options.autoDiscover,
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
// Handle object autoDiscover option
|
|
935
|
-
if (typeof options.autoDiscover === 'object') {
|
|
936
|
-
return {
|
|
937
|
-
...defaultConfig,
|
|
938
|
-
...options.autoDiscover,
|
|
939
|
-
};
|
|
940
|
-
}
|
|
941
|
-
return defaultConfig;
|
|
942
|
-
}
|
|
943
|
-
// Load discovered modules based on strategy
|
|
944
|
-
async loadDiscoveredModules(modules, config) {
|
|
945
|
-
switch (config.loadingStrategy) {
|
|
946
|
-
case 'eager':
|
|
947
|
-
// Load all modules immediately
|
|
948
|
-
for (const module of modules) {
|
|
949
|
-
await this.loadModule(module);
|
|
950
|
-
}
|
|
951
|
-
break;
|
|
952
|
-
case 'lazy':
|
|
953
|
-
// Register modules for lazy loading
|
|
954
|
-
this.registerLazyModules(modules);
|
|
955
|
-
break;
|
|
956
|
-
case 'conditional':
|
|
957
|
-
// Load modules based on conditions
|
|
958
|
-
await this.loadConditionalModules(modules);
|
|
959
|
-
break;
|
|
960
|
-
default:
|
|
961
|
-
// Default to eager loading
|
|
962
|
-
for (const module of modules) {
|
|
963
|
-
await this.loadModule(module);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
// Register modules for lazy loading
|
|
968
|
-
registerLazyModules(modules) {
|
|
969
|
-
modules.forEach(module => {
|
|
970
|
-
// Store module for lazy loading when first route is accessed
|
|
971
|
-
this.lazyModules.set(module.name, module);
|
|
972
|
-
// Register placeholder routes that trigger lazy loading
|
|
973
|
-
if (module.routes) {
|
|
974
|
-
module.routes.forEach(route => {
|
|
975
|
-
const basePath = `/api/v${module.version}/${module.name}`;
|
|
976
|
-
const fullPath = `${basePath}${route.path}`;
|
|
977
|
-
// Note: Lazy loading will be implemented when route is accessed
|
|
978
|
-
// For now, we'll store the module for later loading
|
|
979
|
-
this.logger.debug(`Registered lazy route: ${route.method} ${fullPath}`, 'ModuleDiscovery');
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
});
|
|
983
|
-
this.logger.info(`Registered ${modules.length} modules for lazy loading`, 'ModuleDiscovery');
|
|
984
|
-
}
|
|
985
|
-
// Load modules conditionally based on environment or configuration
|
|
986
|
-
async loadConditionalModules(modules) {
|
|
987
|
-
for (const module of modules) {
|
|
988
|
-
const shouldLoad = this.shouldLoadModule(module);
|
|
989
|
-
if (shouldLoad) {
|
|
990
|
-
await this.loadModule(module);
|
|
991
|
-
}
|
|
992
|
-
else {
|
|
993
|
-
this.logger.debug(`Skipping module ${module.name} due to conditions`, 'ModuleDiscovery');
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
// Determine if a module should be loaded based on conditions
|
|
998
|
-
shouldLoadModule(module) {
|
|
999
|
-
const moduleConfig = module.config;
|
|
1000
|
-
// Check environment conditions
|
|
1001
|
-
if (moduleConfig?.conditions?.environment) {
|
|
1002
|
-
const requiredEnv = moduleConfig.conditions.environment;
|
|
1003
|
-
const currentEnv = process.env.NODE_ENV || 'development';
|
|
1004
|
-
if (Array.isArray(requiredEnv)) {
|
|
1005
|
-
if (!requiredEnv.includes(currentEnv)) {
|
|
1006
|
-
return false;
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
else if (requiredEnv !== currentEnv) {
|
|
1010
|
-
return false;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
// Check feature flags
|
|
1014
|
-
if (moduleConfig?.conditions?.features) {
|
|
1015
|
-
const requiredFeatures = moduleConfig.conditions.features;
|
|
1016
|
-
for (const feature of requiredFeatures) {
|
|
1017
|
-
if (!process.env[`FEATURE_${feature.toUpperCase()}`]) {
|
|
1018
|
-
return false;
|
|
789
|
+
if (!(0, fs_1.statSync)(modulesPath).isDirectory())
|
|
790
|
+
return;
|
|
791
|
+
const items = (0, fs_1.readdirSync)(modulesPath);
|
|
792
|
+
items.forEach(item => {
|
|
793
|
+
const fullPath = (0, path_1.join)(modulesPath, item);
|
|
794
|
+
if ((0, fs_1.statSync)(fullPath).isDirectory()) {
|
|
795
|
+
const indexPath = (0, path_1.join)(fullPath, 'index.ts');
|
|
796
|
+
try {
|
|
797
|
+
(0, fs_1.statSync)(indexPath);
|
|
798
|
+
// Module directory found, will be loaded later
|
|
799
|
+
this.logger.debug(`Discovered module: ${item}`, 'ModuleDiscovery');
|
|
800
|
+
}
|
|
801
|
+
catch {
|
|
802
|
+
// No index.ts, skip
|
|
803
|
+
}
|
|
1019
804
|
}
|
|
1020
|
-
}
|
|
805
|
+
});
|
|
1021
806
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
const customCondition = moduleConfig.conditions.custom;
|
|
1025
|
-
if (typeof customCondition === 'function') {
|
|
1026
|
-
return customCondition();
|
|
1027
|
-
}
|
|
807
|
+
catch {
|
|
808
|
+
// Modules directory doesn't exist, that's fine
|
|
1028
809
|
}
|
|
1029
|
-
return true;
|
|
1030
|
-
}
|
|
1031
|
-
// Handle module changes during development
|
|
1032
|
-
async handleModuleChanges(modules) {
|
|
1033
|
-
this.logger.info('Module changes detected, reloading...', 'ModuleDiscovery');
|
|
1034
|
-
// Unload existing modules (if supported)
|
|
1035
|
-
// For now, just log the change
|
|
1036
|
-
this.eventBus.emit('modules:changed', {
|
|
1037
|
-
modules: modules.map(m => ({ name: m.name, version: m.version })),
|
|
1038
|
-
timestamp: new Date(),
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
// Legacy method for backward compatibility
|
|
1042
|
-
autoDiscoverModules(modulesPath) {
|
|
1043
|
-
// Redirect to new system
|
|
1044
|
-
this.initializeAutoDiscovery({
|
|
1045
|
-
autoDiscover: {
|
|
1046
|
-
enabled: true,
|
|
1047
|
-
paths: [modulesPath],
|
|
1048
|
-
},
|
|
1049
|
-
});
|
|
1050
810
|
}
|
|
1051
811
|
async importModule(modulePath) {
|
|
1052
|
-
const module = await
|
|
812
|
+
const module = await Promise.resolve(`${modulePath}`).then(s => __importStar(require(s)));
|
|
1053
813
|
return module.default || module;
|
|
1054
814
|
}
|
|
1055
|
-
|
|
1056
|
-
* Node.js Clustering Implementation
|
|
1057
|
-
* This clustering algorithm is based on published research and Node.js best practices.
|
|
1058
|
-
*
|
|
1059
|
-
* IPC (Inter-Process Communication) Considerations:
|
|
1060
|
-
* - Excessive workers create IPC bottlenecks (Source: BetterStack Node.js Guide)
|
|
1061
|
-
* - Round-robin scheduling provides better load distribution (Node.js Documentation)
|
|
1062
|
-
* - Message passing overhead increases significantly with worker count
|
|
1063
|
-
*
|
|
1064
|
-
* Memory Management:
|
|
1065
|
-
* - ~2GB per worker prevents memory pressure and GC overhead
|
|
1066
|
-
* - Conservative heap limits reduce memory fragmentation
|
|
1067
|
-
*
|
|
1068
|
-
* References:
|
|
1069
|
-
* - Node.js Cluster Documentation: https://nodejs.org/api/cluster.html
|
|
1070
|
-
* - BetterStack Node.js Clustering: https://betterstack.com/community/guides/scaling-nodejs/node-clustering/
|
|
1071
|
-
*/
|
|
815
|
+
// Clustering support for massive performance gains with proper cleanup
|
|
1072
816
|
clusterWorkers = new Map();
|
|
1073
817
|
startWithClustering(port, host, callback) {
|
|
1074
|
-
|
|
818
|
+
const cluster = require('cluster');
|
|
819
|
+
const os = require('os');
|
|
820
|
+
// Smart worker count calculation based on actual bottlenecks
|
|
1075
821
|
let workerCount = this.config.performance?.clustering?.workers || os.cpus().length;
|
|
1076
|
-
//
|
|
1077
|
-
if (workerCount === 'auto') {
|
|
822
|
+
// Auto-optimize worker count based on system characteristics
|
|
823
|
+
if (workerCount === 'auto' || workerCount > 8) {
|
|
824
|
+
// For high-core machines, limit workers to prevent IPC/memory bottlenecks
|
|
1078
825
|
const cpuCount = os.cpus().length;
|
|
1079
826
|
const totalMemoryGB = os.totalmem() / (1024 * 1024 * 1024);
|
|
1080
|
-
//
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
const headroomGB = 4;
|
|
1085
|
-
memoryPerWorkerGB = Math.max(0.5, Math.floor((totalMemoryGB - headroomGB) / cpuCount));
|
|
827
|
+
// Optimal worker count formula based on research
|
|
828
|
+
if (cpuCount >= 16) {
|
|
829
|
+
// High-core machines: focus on memory/IPC efficiency
|
|
830
|
+
workerCount = Math.min(Math.ceil(totalMemoryGB / 2), 4); // 2GB per worker max, cap at 4
|
|
1086
831
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
else if (typeof workerCount === 'number') {
|
|
1097
|
-
// User specified a number - respect their choice
|
|
1098
|
-
this.logger.info(`Using user-specified worker count: ${workerCount}`, 'Cluster');
|
|
832
|
+
else if (cpuCount >= 8) {
|
|
833
|
+
// Mid-range machines: balanced approach
|
|
834
|
+
workerCount = Math.min(cpuCount / 2, 4);
|
|
835
|
+
}
|
|
836
|
+
else {
|
|
837
|
+
// Low-core machines: use all cores
|
|
838
|
+
workerCount = cpuCount;
|
|
839
|
+
}
|
|
840
|
+
this.logger.info(`Auto-optimized workers: ${workerCount} (CPU: ${cpuCount}, RAM: ${totalMemoryGB.toFixed(1)}GB)`, 'Cluster');
|
|
1099
841
|
}
|
|
1100
842
|
if (cluster.isPrimary) {
|
|
1101
|
-
this.logger.info(
|
|
843
|
+
this.logger.info(`🚀 Starting ${workerCount} workers for maximum performance`, 'Cluster');
|
|
1102
844
|
// Optimize cluster scheduling for high concurrency
|
|
1103
|
-
// Round-robin
|
|
1104
|
-
// Provides better load distribution than shared socket approach
|
|
1105
|
-
cluster.schedulingPolicy = cluster.SCHED_RR;
|
|
845
|
+
cluster.schedulingPolicy = cluster.SCHED_RR; // Round-robin scheduling
|
|
1106
846
|
// Set cluster settings for better performance
|
|
1107
847
|
cluster.setupMaster({
|
|
1108
|
-
exec: process.argv[1]
|
|
848
|
+
exec: process.argv[1],
|
|
1109
849
|
args: process.argv.slice(2),
|
|
1110
850
|
silent: false,
|
|
1111
851
|
});
|
|
1112
|
-
// IPC
|
|
1113
|
-
// Research shows excessive IPC can create bottlenecks in clustered applications
|
|
1114
|
-
// (Source: BetterStack - Node.js Clustering Guide)
|
|
852
|
+
// Optimize IPC to reduce communication overhead
|
|
1115
853
|
process.env.NODE_CLUSTER_SCHED_POLICY = 'rr'; // Ensure round-robin
|
|
1116
|
-
process.env.NODE_DISABLE_COLORS = '1'; // Reduce IPC message size
|
|
854
|
+
process.env.NODE_DISABLE_COLORS = '1'; // Reduce IPC message size
|
|
1117
855
|
// Graceful shutdown handler
|
|
1118
856
|
const gracefulShutdown = () => {
|
|
1119
857
|
this.logger.info('Gracefully shutting down cluster...', 'Cluster');
|
|
@@ -1129,25 +867,27 @@ export class Moro extends EventEmitter {
|
|
|
1129
867
|
// Handle process signals for graceful shutdown
|
|
1130
868
|
process.on('SIGINT', gracefulShutdown);
|
|
1131
869
|
process.on('SIGTERM', gracefulShutdown);
|
|
1132
|
-
// Fork workers with
|
|
870
|
+
// Fork workers with proper tracking and CPU affinity
|
|
1133
871
|
for (let i = 0; i < workerCount; i++) {
|
|
1134
|
-
const worker = cluster.fork(
|
|
872
|
+
const worker = cluster.fork({
|
|
873
|
+
WORKER_ID: i,
|
|
874
|
+
WORKER_CPU_AFFINITY: i % os.cpus().length, // Distribute workers across CPUs
|
|
875
|
+
});
|
|
1135
876
|
this.clusterWorkers.set(worker.process.pid, worker);
|
|
1136
|
-
this.logger.info(`Worker ${worker.process.pid} started`, 'Cluster');
|
|
1137
|
-
// Handle individual worker messages
|
|
877
|
+
this.logger.info(`Worker ${worker.process.pid} started (CPU ${i % os.cpus().length})`, 'Cluster');
|
|
878
|
+
// Handle individual worker messages (reuse handler)
|
|
1138
879
|
worker.on('message', this.handleWorkerMessage.bind(this));
|
|
1139
880
|
}
|
|
1140
|
-
//
|
|
881
|
+
// Handle worker exits with cleanup
|
|
1141
882
|
cluster.on('exit', (worker, code, signal) => {
|
|
1142
|
-
|
|
1143
|
-
this.clusterWorkers.delete(pid);
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
}
|
|
883
|
+
// Clean up worker tracking
|
|
884
|
+
this.clusterWorkers.delete(worker.process.pid);
|
|
885
|
+
this.logger.warn(`Worker ${worker.process.pid} died (${signal || code}). Restarting...`, 'Cluster');
|
|
886
|
+
// Restart worker with proper tracking
|
|
887
|
+
const newWorker = cluster.fork();
|
|
888
|
+
this.clusterWorkers.set(newWorker.process.pid, newWorker);
|
|
889
|
+
newWorker.on('message', this.handleWorkerMessage.bind(this));
|
|
890
|
+
this.logger.info(`Worker ${newWorker.process.pid} started`, 'Cluster');
|
|
1151
891
|
});
|
|
1152
892
|
// Master process callback
|
|
1153
893
|
if (callback)
|
|
@@ -1159,20 +899,12 @@ export class Moro extends EventEmitter {
|
|
|
1159
899
|
// Worker-specific optimizations for high concurrency
|
|
1160
900
|
process.env.UV_THREADPOOL_SIZE = '64';
|
|
1161
901
|
// Reduce logging contention in workers (major bottleneck)
|
|
1162
|
-
// Multiple workers writing to same log files creates I/O contention
|
|
1163
902
|
if (this.config.logging) {
|
|
1164
903
|
// Workers log less frequently to reduce I/O contention
|
|
1165
|
-
|
|
904
|
+
this.config.logging.level = 'warn'; // Only warnings and errors
|
|
1166
905
|
}
|
|
1167
|
-
//
|
|
1168
|
-
|
|
1169
|
-
const workerCount = Object.keys(cluster.workers || {}).length || 1;
|
|
1170
|
-
// Conservative memory allocation
|
|
1171
|
-
const heapSizePerWorkerMB = Math.min(Math.floor(((totalMemoryGB * 1024) / workerCount) * 0.8), // 80% of available memory
|
|
1172
|
-
1536 // Cap at 1.5GB (GC efficiency threshold from research)
|
|
1173
|
-
);
|
|
1174
|
-
process.env.NODE_OPTIONS = `--max-old-space-size=${heapSizePerWorkerMB}`;
|
|
1175
|
-
this.logger.debug(`Worker memory allocated: ${heapSizePerWorkerMB}MB heap (${workerCount} workers, ${totalMemoryGB.toFixed(1)}GB total)`, 'Worker');
|
|
906
|
+
// Memory optimization for workers
|
|
907
|
+
process.env.NODE_OPTIONS = '--max-old-space-size=1024'; // Limit memory per worker
|
|
1176
908
|
// Optimize V8 flags for better performance (Rust-level optimizations)
|
|
1177
909
|
if (process.env.NODE_ENV === 'production') {
|
|
1178
910
|
// Ultra-aggressive V8 optimizations for maximum performance
|
|
@@ -1248,36 +980,15 @@ export class Moro extends EventEmitter {
|
|
|
1248
980
|
worker: process.pid,
|
|
1249
981
|
});
|
|
1250
982
|
};
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
else {
|
|
1258
|
-
this.coreFramework.listen(port, workerCallback);
|
|
1259
|
-
}
|
|
1260
|
-
})
|
|
1261
|
-
.catch(error => {
|
|
1262
|
-
this.logger.error('WebSocket initialization failed in worker', 'Worker', {
|
|
1263
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1264
|
-
});
|
|
1265
|
-
// For WebSocket failures with queued registrations, error will propagate
|
|
1266
|
-
if (error instanceof Error &&
|
|
1267
|
-
error.message.includes('WebSocket features require a WebSocket adapter')) {
|
|
1268
|
-
throw error;
|
|
1269
|
-
}
|
|
1270
|
-
// Start anyway for other errors
|
|
1271
|
-
if (host) {
|
|
1272
|
-
this.coreFramework.listen(port, host, workerCallback);
|
|
1273
|
-
}
|
|
1274
|
-
else {
|
|
1275
|
-
this.coreFramework.listen(port, workerCallback);
|
|
1276
|
-
}
|
|
1277
|
-
});
|
|
983
|
+
if (host) {
|
|
984
|
+
this.coreFramework.listen(port, host, workerCallback);
|
|
985
|
+
}
|
|
986
|
+
else {
|
|
987
|
+
this.coreFramework.listen(port, workerCallback);
|
|
988
|
+
}
|
|
1278
989
|
}
|
|
1279
990
|
}
|
|
1280
|
-
//
|
|
991
|
+
// Reusable worker message handler (avoids creating new functions)
|
|
1281
992
|
handleWorkerMessage(message) {
|
|
1282
993
|
// Handle inter-worker communication if needed
|
|
1283
994
|
if (message.type === 'health-check') {
|
|
@@ -1287,81 +998,32 @@ export class Moro extends EventEmitter {
|
|
|
1287
998
|
// Log other worker messages
|
|
1288
999
|
this.logger.debug(`Worker message: ${JSON.stringify(message)}`, 'Cluster');
|
|
1289
1000
|
}
|
|
1290
|
-
/**
|
|
1291
|
-
* Gracefully close the application and clean up resources
|
|
1292
|
-
* This should be called in tests and during shutdown
|
|
1293
|
-
*/
|
|
1294
|
-
async close() {
|
|
1295
|
-
this.logger.debug('Closing Moro application...');
|
|
1296
|
-
// Flush logger buffer before shutdown
|
|
1297
|
-
try {
|
|
1298
|
-
// Use flushBuffer for immediate synchronous flush
|
|
1299
|
-
this.logger.flushBuffer();
|
|
1300
|
-
}
|
|
1301
|
-
catch (error) {
|
|
1302
|
-
// Ignore flush errors during shutdown
|
|
1303
|
-
}
|
|
1304
|
-
// Close the core framework with timeout
|
|
1305
|
-
if (this.coreFramework && this.coreFramework.httpServer) {
|
|
1306
|
-
try {
|
|
1307
|
-
await Promise.race([
|
|
1308
|
-
new Promise(resolve => {
|
|
1309
|
-
this.coreFramework.httpServer.close(() => {
|
|
1310
|
-
resolve();
|
|
1311
|
-
});
|
|
1312
|
-
}),
|
|
1313
|
-
new Promise(resolve => setTimeout(resolve, 2000)), // 2 second timeout
|
|
1314
|
-
]);
|
|
1315
|
-
}
|
|
1316
|
-
catch (error) {
|
|
1317
|
-
// Force close if graceful close fails
|
|
1318
|
-
this.logger.warn('Force closing HTTP server due to timeout');
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
// Clean up module discovery watchers
|
|
1322
|
-
if (this.moduleDiscovery && typeof this.moduleDiscovery.cleanup === 'function') {
|
|
1323
|
-
try {
|
|
1324
|
-
this.moduleDiscovery.cleanup();
|
|
1325
|
-
}
|
|
1326
|
-
catch (error) {
|
|
1327
|
-
// Ignore cleanup errors
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
// Clean up event listeners
|
|
1331
|
-
try {
|
|
1332
|
-
this.eventBus.removeAllListeners();
|
|
1333
|
-
this.removeAllListeners();
|
|
1334
|
-
}
|
|
1335
|
-
catch (error) {
|
|
1336
|
-
// Ignore cleanup errors
|
|
1337
|
-
}
|
|
1338
|
-
this.logger.debug('Moro application closed successfully');
|
|
1339
|
-
}
|
|
1340
1001
|
}
|
|
1002
|
+
exports.Moro = Moro;
|
|
1341
1003
|
// Export convenience function
|
|
1342
|
-
|
|
1004
|
+
function createApp(options) {
|
|
1343
1005
|
return new Moro(options);
|
|
1344
1006
|
}
|
|
1345
1007
|
// Runtime-specific convenience functions
|
|
1346
|
-
|
|
1008
|
+
function createAppNode(options) {
|
|
1347
1009
|
return new Moro({
|
|
1348
1010
|
...options,
|
|
1349
1011
|
runtime: { type: 'node' },
|
|
1350
1012
|
});
|
|
1351
1013
|
}
|
|
1352
|
-
|
|
1014
|
+
function createAppEdge(options) {
|
|
1353
1015
|
return new Moro({
|
|
1354
1016
|
...options,
|
|
1355
1017
|
runtime: { type: 'vercel-edge' },
|
|
1356
1018
|
});
|
|
1357
1019
|
}
|
|
1358
|
-
|
|
1020
|
+
function createAppLambda(options) {
|
|
1359
1021
|
return new Moro({
|
|
1360
1022
|
...options,
|
|
1361
1023
|
runtime: { type: 'aws-lambda' },
|
|
1362
1024
|
});
|
|
1363
1025
|
}
|
|
1364
|
-
|
|
1026
|
+
function createAppWorker(options) {
|
|
1365
1027
|
return new Moro({
|
|
1366
1028
|
...options,
|
|
1367
1029
|
runtime: { type: 'cloudflare-workers' },
|