@scpxl/nodejs-framework 1.0.49 → 1.0.56
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 +12 -7
- package/dist/api-requester/api-requester.js +1 -1
- package/dist/api-requester/api-requester.js.map +2 -2
- package/dist/api-requester/index.d.ts +1 -1
- package/dist/api-requester/index.d.ts.map +1 -1
- package/dist/api-requester/index.js.map +2 -2
- package/dist/application/base-application.d.ts +6 -5
- package/dist/application/base-application.d.ts.map +1 -1
- package/dist/application/base-application.interface.d.ts +2 -4
- package/dist/application/base-application.interface.d.ts.map +1 -1
- package/dist/application/base-application.js +23 -14
- package/dist/application/base-application.js.map +2 -2
- package/dist/application/command-application.d.ts.map +1 -1
- package/dist/application/command-application.js +2 -2
- package/dist/application/command-application.js.map +2 -2
- package/dist/application/index.d.ts +3 -3
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +4 -4
- package/dist/application/index.js.map +2 -2
- package/dist/application/web-application.d.ts +5 -5
- package/dist/application/web-application.d.ts.map +1 -1
- package/dist/application/web-application.js +6 -7
- package/dist/application/web-application.js.map +2 -2
- package/dist/application/worker-application.d.ts +2 -2
- package/dist/application/worker-application.d.ts.map +1 -1
- package/dist/application/worker-application.js +2 -2
- package/dist/application/worker-application.js.map +2 -2
- package/dist/auth/jwt.d.ts.map +1 -1
- package/dist/auth/jwt.js +2 -2
- package/dist/auth/jwt.js.map +2 -2
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js.map +2 -2
- package/dist/cli/index.js +192 -7029
- package/dist/cli/index.js.map +4 -4
- package/dist/cluster/cluster-manager.d.ts.map +1 -1
- package/dist/cluster/cluster-manager.js +1 -1
- package/dist/cluster/cluster-manager.js.map +2 -2
- package/dist/command/command.d.ts +1 -1
- package/dist/command/command.d.ts.map +1 -1
- package/dist/command/command.js.map +2 -2
- package/dist/config/env.d.ts +1 -1
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +1 -1
- package/dist/config/schema.js.map +2 -2
- package/dist/database/dynamic-entity.js +9 -9
- package/dist/database/dynamic-entity.js.map +2 -2
- package/dist/database/index.d.ts +3 -3
- package/dist/database/index.d.ts.map +1 -1
- package/dist/database/index.js +5 -5
- package/dist/database/index.js.map +2 -2
- package/dist/database/instance.d.ts +3 -3
- package/dist/database/instance.js +3 -3
- package/dist/database/instance.js.map +1 -1
- package/dist/database/manager.d.ts +1 -0
- package/dist/database/manager.d.ts.map +1 -1
- package/dist/database/manager.js +16 -3
- package/dist/database/manager.js.map +2 -2
- package/dist/error/error-reporter.js +1 -1
- package/dist/error/error-reporter.js.map +2 -2
- package/dist/error/index.d.ts +2 -3
- package/dist/error/index.d.ts.map +1 -1
- package/dist/error/index.js +8 -9
- package/dist/error/index.js.map +2 -2
- package/dist/event/controller/base.d.ts +2 -2
- package/dist/event/controller/base.d.ts.map +1 -1
- package/dist/event/controller/base.js +2 -2
- package/dist/event/controller/base.js.map +2 -2
- package/dist/event/index.d.ts +3 -3
- package/dist/event/index.d.ts.map +1 -1
- package/dist/event/index.js +5 -5
- package/dist/event/index.js.map +2 -2
- package/dist/event/manager.d.ts.map +1 -1
- package/dist/event/manager.interface.d.ts +2 -3
- package/dist/event/manager.interface.d.ts.map +1 -1
- package/dist/event/manager.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/lifecycle/index.d.ts +3 -3
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +1 -1
- package/dist/lifecycle/index.js.map +2 -2
- package/dist/lifecycle/lifecycle-manager.d.ts +6 -0
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-manager.js +28 -0
- package/dist/lifecycle/lifecycle-manager.js.map +2 -2
- package/dist/logger/logger.d.ts +20 -1
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +68 -96
- package/dist/logger/logger.js.map +2 -2
- package/dist/performance/cache-performance.d.ts.map +1 -1
- package/dist/performance/cache-performance.js +1 -1
- package/dist/performance/cache-performance.js.map +2 -2
- package/dist/performance/database-performance.d.ts.map +1 -1
- package/dist/performance/database-performance.js +1 -1
- package/dist/performance/database-performance.js.map +2 -2
- package/dist/performance/index.d.ts +3 -3
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/performance/index.js +3 -3
- package/dist/performance/index.js.map +1 -1
- package/dist/performance/performance-monitor.js +2 -2
- package/dist/performance/performance-monitor.js.map +2 -2
- package/dist/performance/performance-monitor.plugin.d.ts.map +1 -1
- package/dist/performance/performance-monitor.plugin.js +1 -1
- package/dist/performance/performance-monitor.plugin.js.map +2 -2
- package/dist/performance/queue-performance.d.ts.map +1 -1
- package/dist/performance/queue-performance.js +1 -1
- package/dist/performance/queue-performance.js.map +2 -2
- package/dist/performance/webserver-performance.d.ts.map +1 -1
- package/dist/performance/webserver-performance.js +1 -1
- package/dist/performance/webserver-performance.js.map +2 -2
- package/dist/performance/websocket-performance.d.ts.map +1 -1
- package/dist/performance/websocket-performance.js +1 -1
- package/dist/performance/websocket-performance.js.map +2 -2
- package/dist/queue/index.d.ts +2 -2
- package/dist/queue/index.d.ts.map +1 -1
- package/dist/queue/index.interface.d.ts +1 -1
- package/dist/queue/index.interface.d.ts.map +1 -1
- package/dist/queue/index.js.map +2 -2
- package/dist/queue/manager.d.ts +9 -2
- package/dist/queue/manager.d.ts.map +1 -1
- package/dist/queue/manager.js +44 -6
- package/dist/queue/manager.js.map +2 -2
- package/dist/queue/processor/base.d.ts +5 -5
- package/dist/queue/processor/base.d.ts.map +1 -1
- package/dist/queue/processor/base.js +2 -2
- package/dist/queue/processor/base.js.map +2 -2
- package/dist/queue/processor/processor.interface.d.ts +3 -3
- package/dist/queue/processor/processor.interface.d.ts.map +1 -1
- package/dist/queue/worker.d.ts +5 -0
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/queue/worker.interface.d.ts +1 -1
- package/dist/queue/worker.interface.d.ts.map +1 -1
- package/dist/queue/worker.js +9 -1
- package/dist/queue/worker.js.map +2 -2
- package/dist/redis/index.d.ts +1 -1
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +5 -4
- package/dist/redis/index.js.map +2 -2
- package/dist/redis/instance.js +1 -1
- package/dist/redis/instance.js.map +2 -2
- package/dist/redis/manager.d.ts +7 -1
- package/dist/redis/manager.d.ts.map +1 -1
- package/dist/redis/manager.js +20 -4
- package/dist/redis/manager.js.map +2 -2
- package/dist/request-context/index.d.ts +1 -1
- package/dist/request-context/index.d.ts.map +1 -1
- package/dist/request-context/index.js +5 -5
- package/dist/request-context/index.js.map +1 -1
- package/dist/schemas/entity-builder.d.ts +3 -3
- package/dist/schemas/entity-builder.d.ts.map +1 -1
- package/dist/schemas/entity-builder.js.map +1 -1
- package/dist/services/aws/s3.d.ts.map +1 -1
- package/dist/services/aws/s3.js +7 -10
- package/dist/services/aws/s3.js.map +2 -2
- package/dist/util/file.d.ts +13 -8
- package/dist/util/file.d.ts.map +1 -1
- package/dist/util/file.js +6 -28
- package/dist/util/file.js.map +2 -2
- package/dist/util/helper.js +2 -2
- package/dist/util/helper.js.map +2 -2
- package/dist/util/index.d.ts +2 -2
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +18 -18
- package/dist/util/index.js.map +2 -2
- package/dist/util/loader.js +3 -3
- package/dist/util/loader.js.map +2 -2
- package/dist/util/os.js +2 -2
- package/dist/util/os.js.map +2 -2
- package/dist/webserver/controller/auth-middleware.d.ts +1 -1
- package/dist/webserver/controller/auth-middleware.d.ts.map +1 -1
- package/dist/webserver/controller/auth-middleware.js +1 -1
- package/dist/webserver/controller/auth-middleware.js.map +2 -2
- package/dist/webserver/controller/base.d.ts +6 -6
- package/dist/webserver/controller/base.d.ts.map +1 -1
- package/dist/webserver/controller/base.interface.d.ts +1 -1
- package/dist/webserver/controller/base.interface.d.ts.map +1 -1
- package/dist/webserver/controller/base.js +4 -4
- package/dist/webserver/controller/base.js.map +2 -2
- package/dist/webserver/controller/entity.d.ts +4 -3
- package/dist/webserver/controller/entity.d.ts.map +1 -1
- package/dist/webserver/controller/entity.js +26 -17
- package/dist/webserver/controller/entity.js.map +2 -2
- package/dist/webserver/controller/example-auth.d.ts.map +1 -1
- package/dist/webserver/controller/example-auth.js +1 -1
- package/dist/webserver/controller/example-auth.js.map +2 -2
- package/dist/webserver/controller/health.d.ts.map +1 -1
- package/dist/webserver/controller/health.js +1 -1
- package/dist/webserver/controller/health.js.map +2 -2
- package/dist/webserver/define-action.d.ts +1 -1
- package/dist/webserver/define-action.d.ts.map +1 -1
- package/dist/webserver/define-action.js.map +1 -1
- package/dist/webserver/define-route.d.ts +1 -1
- package/dist/webserver/define-route.d.ts.map +1 -1
- package/dist/webserver/define-route.js.map +2 -2
- package/dist/webserver/index.d.ts +9 -9
- package/dist/webserver/index.d.ts.map +1 -1
- package/dist/webserver/index.js +14 -14
- package/dist/webserver/index.js.map +2 -2
- package/dist/webserver/webserver.d.ts +3 -3
- package/dist/webserver/webserver.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.d.ts +5 -5
- package/dist/webserver/webserver.interface.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.js.map +1 -1
- package/dist/webserver/webserver.js +9 -9
- package/dist/webserver/webserver.js.map +2 -2
- package/dist/websocket/controller/server/base.d.ts +2 -2
- package/dist/websocket/controller/server/base.js.map +1 -1
- package/dist/websocket/controllers/server/system.d.ts.map +1 -1
- package/dist/websocket/controllers/server/system.js +1 -1
- package/dist/websocket/controllers/server/system.js.map +2 -2
- package/dist/websocket/index.d.ts +9 -11
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +22 -22
- package/dist/websocket/index.js.map +2 -2
- package/dist/websocket/subscriber-middleware.d.ts.map +1 -1
- package/dist/websocket/subscriber-middleware.js.map +2 -2
- package/dist/websocket/subscriber-utils.d.ts.map +1 -1
- package/dist/websocket/subscriber-utils.js.map +2 -2
- package/dist/websocket/utils.d.ts.map +1 -1
- package/dist/websocket/utils.js +4 -2
- package/dist/websocket/utils.js.map +2 -2
- package/dist/websocket/websocket-auth.d.ts.map +1 -1
- package/dist/websocket/websocket-auth.js +3 -3
- package/dist/websocket/websocket-auth.js.map +2 -2
- package/dist/websocket/websocket-base.d.ts +2 -2
- package/dist/websocket/websocket-base.d.ts.map +1 -1
- package/dist/websocket/websocket-base.js +1 -1
- package/dist/websocket/websocket-base.js.map +2 -2
- package/dist/websocket/websocket-client-manager.d.ts +2 -0
- package/dist/websocket/websocket-client-manager.d.ts.map +1 -1
- package/dist/websocket/websocket-client-manager.js +11 -4
- package/dist/websocket/websocket-client-manager.js.map +2 -2
- package/dist/websocket/websocket-client.d.ts +10 -5
- package/dist/websocket/websocket-client.d.ts.map +1 -1
- package/dist/websocket/websocket-client.js +27 -5
- package/dist/websocket/websocket-client.js.map +2 -2
- package/dist/websocket/websocket-room-manager.js +1 -1
- package/dist/websocket/websocket-room-manager.js.map +1 -1
- package/dist/websocket/websocket-server.d.ts +7 -7
- package/dist/websocket/websocket-server.d.ts.map +1 -1
- package/dist/websocket/websocket-server.js +25 -20
- package/dist/websocket/websocket-server.js.map +2 -2
- package/dist/websocket/websocket-service.d.ts +2 -2
- package/dist/websocket/websocket-service.d.ts.map +1 -1
- package/dist/websocket/websocket-service.js +1 -1
- package/dist/websocket/websocket-service.js.map +2 -2
- package/dist/websocket/websocket.interface.d.ts +3 -5
- package/dist/websocket/websocket.interface.d.ts.map +1 -1
- package/dist/websocket/websocket.interface.js.map +2 -2
- package/package.json +68 -64
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RouteSchemaDefinition } from './webserver.interface.js';
|
|
2
1
|
import type { ControllerAction } from './controller/base.interface.js';
|
|
2
|
+
import type { RouteSchemaDefinition } from './webserver.interface.js';
|
|
3
3
|
/**
|
|
4
4
|
* Define a typed controller action with schema inference.
|
|
5
5
|
* This helper provides TypeScript type inference for controller methods based on Zod schemas.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-action.d.ts","sourceRoot":"","sources":["../../src/webserver/define-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"define-action.d.ts","sourceRoot":"","sources":["../../src/webserver/define-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,MAAM,SAAS,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACxF,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAChC,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE5B;;;GAGG;AAEH,wBAAgB,YAAY,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS,EAC/D,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAChC,gBAAgB,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/define-action.ts"],
|
|
4
|
-
"sourcesContent": ["import type {
|
|
4
|
+
"sourcesContent": ["import type { ControllerAction } from './controller/base.interface.js';\nimport type { RouteSchemaDefinition } from './webserver.interface.js';\n\n/**\n * Define a typed controller action with schema inference.\n * This helper provides TypeScript type inference for controller methods based on Zod schemas.\n *\n * @example\n * const helloSchema = {\n * body: z.object({ name: z.string() }),\n * response: { 200: z.object({ message: z.string() }) }\n * } satisfies RouteSchemaDefinition;\n *\n * class MyController extends WebServerBaseController {\n * hello = defineAction(helloSchema, async (request, reply) => {\n * // request.body is typed as { name: string }\n * return reply.send({ message: `Hello ${request.body.name}` });\n * });\n * }\n */\nexport function defineAction<Schema extends RouteSchemaDefinition<any, any, any, any, any>>(\n schema: Schema,\n handler: ControllerAction<Schema>,\n): ControllerAction<Schema>;\n\n/**\n * Define a controller action without a schema.\n * Useful for actions that don't need validation or type inference.\n */\n// eslint-disable-next-line no-redeclare\nexport function defineAction<Schema extends undefined = undefined>(\n handler: ControllerAction<Schema>,\n): ControllerAction<Schema>;\n\n// eslint-disable-next-line no-redeclare\nexport function defineAction<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined>(\n schemaOrHandler: Schema | ControllerAction<Schema>,\n handler?: ControllerAction<Schema>,\n): ControllerAction<Schema> {\n if (typeof schemaOrHandler === 'function') {\n // No schema provided, just return the handler\n return schemaOrHandler;\n }\n\n // Schema provided, return the handler\n // Note: The schema is attached for documentation/IDE purposes only\n // Actual validation happens at the route level\n if (!handler) {\n throw new Error('Handler is required when schema is provided');\n }\n\n return handler;\n}\n"],
|
|
5
5
|
"mappings": ";;AAmCO,SAAS,aACd,iBACA,SAC0B;AAC1B,MAAI,OAAO,oBAAoB,YAAY;AAEzC,WAAO;AAAA,EACT;AAKA,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,SAAO;AACT;AAjBgB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HTTPMethods } from 'fastify';
|
|
2
|
-
import { type RouteSchemaDefinition, type WebServerRoute } from './webserver.interface.js';
|
|
3
2
|
import type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';
|
|
3
|
+
import { type RouteSchemaDefinition, type WebServerRoute } from './webserver.interface.js';
|
|
4
4
|
export interface DefineRouteConfig<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined, Handler extends ControllerAction<Schema>> {
|
|
5
5
|
method: HTTPMethods | HTTPMethods[];
|
|
6
6
|
path: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-route.d.ts","sourceRoot":"","sources":["../../src/webserver/define-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"define-route.d.ts","sourceRoot":"","sources":["../../src/webserver/define-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AACpG,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EAEpB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,iBAAiB,CAChC,MAAM,SAAS,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,EACzE,OAAO,SAAS,gBAAgB,CAAC,MAAM,CAAC;IAExC,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,+BAA+B,CAC9C,MAAM,SAAS,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS;IAErF,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,2BAA2B,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CACzB,MAAM,SAAS,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,EACzE,OAAO,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACxC,MAAM,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC;AAE9D;;;;;;;;;;;;GAYG;AAEH,wBAAgB,WAAW,CAAC,MAAM,SAAS,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS,EAC/G,MAAM,EAAE,+BAA+B,CAAC,MAAM,CAAC,GAC9C,cAAc,CAAC;AA2BlB,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/define-route.ts"],
|
|
4
|
-
"sourcesContent": ["import type { HTTPMethods } from 'fastify';\nimport {\n type AnyRouteSchemaDefinition,\n type RouteSchemaDefinition,\n type WebServerRoute,\n WebServerRouteType,\n} from './webserver.interface.js';\
|
|
5
|
-
"mappings": ";;
|
|
4
|
+
"sourcesContent": ["import type { HTTPMethods } from 'fastify';\nimport type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';\nimport {\n type AnyRouteSchemaDefinition,\n type RouteSchemaDefinition,\n type WebServerRoute,\n WebServerRouteType,\n} from './webserver.interface.js';\n\nexport interface DefineRouteConfig<\n Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined,\n Handler extends ControllerAction<Schema>,\n> {\n method: HTTPMethods | HTTPMethods[];\n path: string;\n schema?: Schema;\n handler: Handler;\n}\n\nexport interface DefineRouteWithControllerConfig<\n Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined = undefined,\n> {\n method: HTTPMethods | HTTPMethods[];\n path: string;\n schema?: Schema;\n controller: WebServerBaseControllerType;\n action: string;\n}\n\n/**\n * Define a route with an inline handler function.\n * Provides full type inference for request parameters based on the schema.\n *\n * @example\n * const helloSchema = {\n * body: z.object({ name: z.string() }),\n * response: { 200: z.object({ message: z.string() }) }\n * } satisfies RouteSchemaDefinition;\n *\n * defineRoute({\n * method: 'POST',\n * path: '/hello',\n * schema: helloSchema,\n * handler: async (request, reply) => {\n * // request.body is typed as { name: string }\n * return reply.send({ message: `Hello ${request.body.name}` });\n * }\n * });\n */\nexport function defineRoute<\n Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined,\n Handler extends ControllerAction<Schema>,\n>(config: DefineRouteConfig<Schema, Handler>): WebServerRoute;\n\n/**\n * Define a route with a controller and action method.\n * Note: Type inference for controller actions is limited. Consider using inline handlers for full type safety.\n *\n * @example\n * defineRoute({\n * method: 'POST',\n * path: '/hello',\n * controller: HelloController,\n * action: 'create',\n * schema: helloSchema\n * });\n */\n// eslint-disable-next-line no-redeclare\nexport function defineRoute<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined = undefined>(\n config: DefineRouteWithControllerConfig<Schema>,\n): WebServerRoute;\n\n// eslint-disable-next-line no-redeclare\nexport function defineRoute<\n Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined,\n Handler extends ControllerAction<Schema>,\n>(config: DefineRouteConfig<Schema, Handler> | DefineRouteWithControllerConfig<Schema>): WebServerRoute {\n const route: WebServerRoute = {\n type: WebServerRouteType.Default,\n method: config.method,\n path: config.path,\n };\n\n if ('handler' in config) {\n route.handler = config.handler as ControllerAction<any>;\n } else if ('controller' in config && 'action' in config) {\n route.controller = config.controller;\n route.action = config.action;\n }\n\n if (config.schema) {\n route.schema = config.schema as AnyRouteSchemaDefinition;\n }\n\n return route;\n}\n\nexport type DefineRoute = typeof defineRoute;\n"],
|
|
5
|
+
"mappings": ";;AAEA;AAAA,EAIE;AAAA,OACK;AAkEA,SAAS,YAGd,QAAsG;AACtG,QAAM,QAAwB;AAAA,IAC5B,MAAM,mBAAmB;AAAA,IACzB,QAAQ,OAAO;AAAA,IACf,MAAM,OAAO;AAAA,EACf;AAEA,MAAI,aAAa,QAAQ;AACvB,UAAM,UAAU,OAAO;AAAA,EACzB,WAAW,gBAAgB,UAAU,YAAY,QAAQ;AACvD,UAAM,aAAa,OAAO;AAC1B,UAAM,SAAS,OAAO;AAAA,EACxB;AAEA,MAAI,OAAO,QAAQ;AACjB,UAAM,SAAS,OAAO;AAAA,EACxB;AAEA,SAAO;AACT;AAtBgB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
3
|
-
export { WebServerRouteType } from './webserver.interface.js';
|
|
4
|
-
export { default as WebServerBaseController } from './controller/base.js';
|
|
1
|
+
export type { AuthenticatedRequest, AuthenticatedRouteHandler, AuthenticatedUser, RouteHandler, } from './controller/auth-middleware.js';
|
|
2
|
+
export { withAuth } from './controller/auth-middleware.js';
|
|
5
3
|
export type { ControllerAction, ControllerRequest, WebServerBaseControllerConstructorParams, } from './controller/base.interface.js';
|
|
6
|
-
export { default as
|
|
4
|
+
export { default as WebServerBaseController } from './controller/base.js';
|
|
7
5
|
export { default as WebServerEntityController } from './controller/entity.js';
|
|
8
6
|
export { default as ExampleAuthController } from './controller/example-auth.js';
|
|
9
|
-
export { default as
|
|
10
|
-
export type { AuthenticatedUser, AuthenticatedRequest, AuthenticatedRouteHandler, RouteHandler, } from './controller/auth-middleware.js';
|
|
11
|
-
export { withAuth } from './controller/auth-middleware.js';
|
|
12
|
-
export { defineRoute } from './define-route.js';
|
|
7
|
+
export { default as WebServerHealthController } from './controller/health.js';
|
|
13
8
|
export { defineAction } from './define-action.js';
|
|
9
|
+
export { defineRoute } from './define-route.js';
|
|
10
|
+
export { default as RouteUtil } from './util.js';
|
|
11
|
+
export type { RouteHandler as TypedRouteHandler, RouteHandlerContext, RouteSchemaDefinition, WebServerConstructorParams, WebServerOptions, WebServerRoute, } from './webserver.interface.js';
|
|
12
|
+
export { WebServerRouteType } from './webserver.interface.js';
|
|
13
|
+
export { default as WebServer } from './webserver.js';
|
|
14
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webserver/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webserver/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,GACb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,wCAAwC,GACzC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,YAAY,EACV,YAAY,IAAI,iBAAiB,EACjC,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,gBAAgB,EAChB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/webserver/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { default as default2 } from "./webserver.js";
|
|
2
|
-
import { WebServerRouteType } from "./webserver.interface.js";
|
|
3
|
-
import { default as default3 } from "./controller/base.js";
|
|
4
|
-
import { default as default4 } from "./controller/health.js";
|
|
5
|
-
import { default as default5 } from "./controller/entity.js";
|
|
6
|
-
import { default as default6 } from "./controller/example-auth.js";
|
|
7
|
-
import { default as default7 } from "./util.js";
|
|
8
1
|
import { withAuth } from "./controller/auth-middleware.js";
|
|
9
|
-
import {
|
|
2
|
+
import { default as default2 } from "./controller/base.js";
|
|
3
|
+
import { default as default3 } from "./controller/entity.js";
|
|
4
|
+
import { default as default4 } from "./controller/example-auth.js";
|
|
5
|
+
import { default as default5 } from "./controller/health.js";
|
|
10
6
|
import { defineAction } from "./define-action.js";
|
|
7
|
+
import { defineRoute } from "./define-route.js";
|
|
8
|
+
import { default as default6 } from "./util.js";
|
|
9
|
+
import { WebServerRouteType } from "./webserver.interface.js";
|
|
10
|
+
import { default as default7 } from "./webserver.js";
|
|
11
11
|
export {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
default4 as ExampleAuthController,
|
|
13
|
+
default6 as RouteUtil,
|
|
14
|
+
default7 as WebServer,
|
|
15
|
+
default2 as WebServerBaseController,
|
|
16
|
+
default3 as WebServerEntityController,
|
|
17
|
+
default5 as WebServerHealthController,
|
|
18
18
|
WebServerRouteType,
|
|
19
19
|
defineAction,
|
|
20
20
|
defineRoute,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/index.ts"],
|
|
4
|
-
"sourcesContent": ["export {
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["export type {\n AuthenticatedRequest,\n AuthenticatedRouteHandler,\n AuthenticatedUser,\n RouteHandler,\n} from './controller/auth-middleware.js';\nexport { withAuth } from './controller/auth-middleware.js';\nexport type {\n ControllerAction,\n ControllerRequest,\n WebServerBaseControllerConstructorParams,\n} from './controller/base.interface.js';\nexport { default as WebServerBaseController } from './controller/base.js';\nexport { default as WebServerEntityController } from './controller/entity.js';\nexport { default as ExampleAuthController } from './controller/example-auth.js';\nexport { default as WebServerHealthController } from './controller/health.js';\nexport { defineAction } from './define-action.js';\nexport { defineRoute } from './define-route.js';\nexport { default as RouteUtil } from './util.js';\nexport type {\n RouteHandler as TypedRouteHandler,\n RouteHandlerContext,\n RouteSchemaDefinition,\n WebServerConstructorParams,\n WebServerOptions,\n WebServerRoute,\n} from './webserver.interface.js';\nexport { WebServerRouteType } from './webserver.interface.js';\nexport { default as WebServer } from './webserver.js';\n"],
|
|
5
|
+
"mappings": "AAMA,SAAS,gBAAgB;AAMzB,SAAoB,WAAXA,gBAA0C;AACnD,SAAoB,WAAXA,gBAA4C;AACrD,SAAoB,WAAXA,gBAAwC;AACjD,SAAoB,WAAXA,gBAA4C;AACrD,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAoB,WAAXA,gBAA4B;AASrC,SAAS,0BAA0B;AACnC,SAAoB,WAAXA,gBAA4B;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type FastifyInstance, type HTTPMethods } from 'fastify';
|
|
2
|
-
import { type AnyRouteSchemaDefinition, type WebServerConstructorParams } from './webserver.interface.js';
|
|
3
|
-
import type { ControllerAction } from './controller/base.interface.js';
|
|
4
|
-
import type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';
|
|
5
2
|
import { type ZodTypeProvider } from 'fastify-type-provider-zod';
|
|
3
|
+
import type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';
|
|
4
|
+
import type { ControllerAction } from './controller/base.interface.js';
|
|
5
|
+
import { type AnyRouteSchemaDefinition, type WebServerConstructorParams } from './webserver.interface.js';
|
|
6
6
|
declare module 'fastify' {
|
|
7
7
|
interface FastifyRequest {
|
|
8
8
|
startTime?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webserver.d.ts","sourceRoot":"","sources":["../../src/webserver/webserver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webserver.d.ts","sourceRoot":"","sources":["../../src/webserver/webserver.ts"],"names":[],"mappings":"AAKA,OAAgB,EACd,KAAK,eAAe,EAIpB,KAAK,WAAW,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAyC,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAKxG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAM1E,OAAO,KAAK,EAAE,gBAAgB,EAA+B,MAAM,gCAAgC,CAAC;AAEpG,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAIhC,MAAM,0BAA0B,CAAC;AAElC,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CACF;AAED,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAyB;IAEvC,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IAEnD,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,gBAAgB,CAAmB;IAEpC,aAAa,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC,CAAC;IAE3E,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,EAAE,0BAA0B,GAAG;QAAE,gBAAgB,EAAE,gBAAgB,CAAA;KAAE;IAuDvF;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBlC;;OAEG;YACW,iBAAiB;IAiD/B;;OAEG;IACH,OAAO,CAAC,cAAc;YAeR,QAAQ;YAeR,SAAS;YA8BT,UAAU;YA8CV,OAAO;YAMP,OAAO;IAIrB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,yBAAyB;IAcjC;;OAEG;YACW,eAAe;YAkPf,uBAAuB;IA4CrC,OAAO,CAAC,oBAAoB;IA8C5B,OAAO,CAAC,YAAY;IA6CP,WAAW,CAAC,EACvB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,GAChB,EAAE;QACD,kBAAkB,EAAE,GAAG,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;QACzC,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,wBAAwB,CAAC;QACvC,eAAe,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;KACzC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2CjB;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMlC,OAAO,CAAC,kBAAkB;IAgC1B;;OAEG;IACI,OAAO,IAAI,OAAO;IAIzB;;OAEG;IACI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlE;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { FastifyReply, FastifyRequest, HTTPMethods, RouteGenericInterface } from 'fastify';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { ApplicationConfig } from '../application/base-application.interface.js';
|
|
2
4
|
import type { DatabaseInstance } from '../database/index.js';
|
|
5
|
+
import type EventManager from '../event/manager.js';
|
|
6
|
+
import type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';
|
|
3
7
|
import type { QueueManager } from '../queue/index.js';
|
|
4
8
|
import type { RedisInstance } from '../redis/index.js';
|
|
5
9
|
import type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';
|
|
6
|
-
import type { ApplicationConfig } from '../application/base-application.interface.js';
|
|
7
|
-
import type EventManager from '../event/manager.js';
|
|
8
|
-
import type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';
|
|
9
|
-
import type { z } from 'zod';
|
|
10
10
|
export interface RouteSchemaDefinition<TParams extends z.ZodTypeAny | undefined = undefined, TQuery extends z.ZodTypeAny | undefined = undefined, TBody extends z.ZodTypeAny | undefined = undefined, TReply extends Record<number | `${number}`, z.ZodTypeAny> | undefined = undefined, THeaders extends z.ZodTypeAny | undefined = undefined> {
|
|
11
11
|
params?: TParams;
|
|
12
12
|
querystring?: TQuery;
|
|
@@ -24,7 +24,7 @@ export interface RouteHandlerContext<Schema extends RouteSchemaDefinition | unde
|
|
|
24
24
|
Reply?: Schema extends RouteSchemaDefinition<any, any, any, infer TReply, any> ? InferResponse<TReply> : RouteGenericInterface['Reply'];
|
|
25
25
|
}
|
|
26
26
|
export type AnyRouteSchemaDefinition = RouteSchemaDefinition<z.ZodTypeAny | undefined, z.ZodTypeAny | undefined, z.ZodTypeAny | undefined, Record<number | `${number}`, z.ZodTypeAny> | undefined, z.ZodTypeAny | undefined>;
|
|
27
|
-
export type RouteHandler<Schema extends RouteSchemaDefinition | undefined = undefined> = (request: FastifyRequest<RouteHandlerContext<Schema>>, reply: FastifyReply) => Promise<RouteHandlerContext<Schema>['Reply'] |
|
|
27
|
+
export type RouteHandler<Schema extends RouteSchemaDefinition | undefined = undefined> = (request: FastifyRequest<RouteHandlerContext<Schema>>, reply: FastifyReply) => Promise<RouteHandlerContext<Schema>['Reply'] | undefined> | RouteHandlerContext<Schema>['Reply'] | undefined;
|
|
28
28
|
export interface WebServerConstructorParams {
|
|
29
29
|
/** Application configuration */
|
|
30
30
|
applicationConfig: ApplicationConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webserver.interface.d.ts","sourceRoot":"","sources":["../../src/webserver/webserver.interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChG,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"webserver.interface.d.ts","sourceRoot":"","sources":["../../src/webserver/webserver.interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/webserver.interface.ts"],
|
|
4
|
-
"sourcesContent": ["import type { FastifyReply, FastifyRequest, HTTPMethods, RouteGenericInterface } from 'fastify';\nimport type {
|
|
4
|
+
"sourcesContent": ["import type { FastifyReply, FastifyRequest, HTTPMethods, RouteGenericInterface } from 'fastify';\nimport type { z } from 'zod';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type { DatabaseInstance } from '../database/index.js';\nimport type EventManager from '../event/manager.js';\nimport type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';\nimport type { QueueManager } from '../queue/index.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';\n\nexport interface RouteSchemaDefinition<\n TParams extends z.ZodTypeAny | undefined = undefined,\n TQuery extends z.ZodTypeAny | undefined = undefined,\n TBody extends z.ZodTypeAny | undefined = undefined,\n TReply extends Record<number | `${number}`, z.ZodTypeAny> | undefined = undefined,\n THeaders extends z.ZodTypeAny | undefined = undefined,\n> {\n params?: TParams;\n querystring?: TQuery;\n body?: TBody;\n response?: TReply;\n headers?: THeaders;\n}\n\ntype InferOrDefault<TZod extends z.ZodTypeAny | undefined, TFallback> = TZod extends z.ZodTypeAny\n ? z.input<TZod>\n : TFallback;\n\ntype InferResponse<TResponse> =\n TResponse extends Record<number | `${number}`, z.ZodTypeAny>\n ? z.output<TResponse[keyof TResponse]>\n : RouteGenericInterface['Reply'];\n\nexport interface RouteHandlerContext<Schema extends RouteSchemaDefinition | undefined = undefined>\n extends RouteGenericInterface {\n Params?: Schema extends RouteSchemaDefinition<infer TParams, any, any, any, any>\n ? InferOrDefault<TParams, RouteGenericInterface['Params']>\n : RouteGenericInterface['Params'];\n Querystring?: Schema extends RouteSchemaDefinition<any, infer TQuery, any, any, any>\n ? InferOrDefault<TQuery, RouteGenericInterface['Querystring']>\n : RouteGenericInterface['Querystring'];\n Body?: Schema extends RouteSchemaDefinition<any, any, infer TBody, any, any>\n ? InferOrDefault<TBody, RouteGenericInterface['Body']>\n : RouteGenericInterface['Body'];\n Headers?: Schema extends RouteSchemaDefinition<any, any, any, any, infer THeaders>\n ? InferOrDefault<THeaders, RouteGenericInterface['Headers']>\n : RouteGenericInterface['Headers'];\n Reply?: Schema extends RouteSchemaDefinition<any, any, any, infer TReply, any>\n ? InferResponse<TReply>\n : RouteGenericInterface['Reply'];\n}\n\nexport type AnyRouteSchemaDefinition = RouteSchemaDefinition<\n z.ZodTypeAny | undefined,\n z.ZodTypeAny | undefined,\n z.ZodTypeAny | undefined,\n Record<number | `${number}`, z.ZodTypeAny> | undefined,\n z.ZodTypeAny | undefined\n>;\n\nexport type RouteHandler<Schema extends RouteSchemaDefinition | undefined = undefined> = (\n request: FastifyRequest<RouteHandlerContext<Schema>>,\n reply: FastifyReply,\n) => Promise<RouteHandlerContext<Schema>['Reply'] | undefined> | RouteHandlerContext<Schema>['Reply'] | undefined;\n\nexport interface WebServerConstructorParams {\n /** Application configuration */\n applicationConfig: ApplicationConfig;\n\n /** Web server options */\n options: WebServerOptions;\n\n /** Web server routes */\n routes?: WebServerRoute[];\n\n /** Redis instance */\n redisInstance: RedisInstance;\n\n /** Queue manager */\n queueManager: QueueManager;\n\n /** Event manager */\n eventManager: EventManager;\n\n /** Database instance */\n databaseInstance: DatabaseInstance;\n\n /** Lifecycle manager */\n lifecycleManager: LifecycleManager;\n}\n\nexport enum WebServerRouteType {\n Default = 'default',\n Entity = 'entity',\n}\n\nexport interface BaseWebServerRoute {\n /** Route type */\n type?: WebServerRouteType;\n\n /** Route path */\n path: string;\n\n /** Route controller name */\n controllerName?: string;\n\n /** Route controller */\n controller?: WebServerBaseControllerType;\n\n /** Typed route handler */\n handler?: ControllerAction<any>;\n\n /** Zod-based schema definition */\n schema?: AnyRouteSchemaDefinition;\n}\n\nexport interface DefaultWebServerRoute extends BaseWebServerRoute {\n type: WebServerRouteType.Default;\n\n /** Route method */\n method: HTTPMethods | HTTPMethods[];\n\n /** Route action */\n action?: string;\n}\n\nexport interface EntityWebServerRoute extends BaseWebServerRoute {\n type: WebServerRouteType.Entity;\n\n /** Entity name */\n entityName: string;\n}\n\nexport type WebServerRoute = DefaultWebServerRoute | EntityWebServerRoute;\n\nexport interface EntityRouteDefinition {\n path: string;\n method: HTTPMethods | HTTPMethods[];\n action: string;\n}\n\nexport interface WebServerLogConfig {\n startUp?: boolean;\n /** Paths to exclude from request logging (e.g., ['/health', '/health/live', '/health/ready']) */\n excludePaths?: string[];\n}\n\nexport interface WebServerDebugOptions {\n printRoutes?: boolean;\n simulateSlowConnection?: {\n enabled?: boolean;\n delay?: number;\n };\n}\n\nexport interface WebServerCorsBaseOptions {\n /** Whether CORS is enabled */\n enabled: boolean;\n}\n\nexport interface WebServerCorsDisabledOptionsBase {\n enabled: false;\n}\n\nexport interface WebServerCorsEnabledOptionsBase {\n enabled: true;\n}\n\nexport interface WebServerCorsEnabledOptions extends WebServerCorsEnabledOptionsBase {\n urls: string[];\n}\n\nexport type WebServerCorsOptions = WebServerCorsDisabledOptionsBase | WebServerCorsEnabledOptions;\n\nexport interface WebServerErrorsOptions {\n verbose: boolean;\n}\n\nexport interface WebServerSecurityHelmetOptions {\n enabled?: boolean;\n contentSecurityPolicy?: boolean;\n crossOriginEmbedderPolicy?: boolean;\n crossOriginOpenerPolicy?: boolean;\n crossOriginResourcePolicy?: boolean;\n dnsPrefetchControl?: boolean;\n frameguard?: boolean;\n hidePoweredBy?: boolean;\n hsts?: boolean;\n ieNoOpen?: boolean;\n noSniff?: boolean;\n originAgentCluster?: boolean;\n permittedCrossDomainPolicies?: boolean;\n referrerPolicy?: boolean;\n xssFilter?: boolean;\n}\n\nexport interface WebServerSecurityRateLimitOptions {\n enabled?: boolean;\n max?: number;\n timeWindow?: string;\n ban?: number;\n cache?: number;\n}\n\nexport interface WebServerSecurityOptions {\n helmet?: WebServerSecurityHelmetOptions;\n rateLimit?: WebServerSecurityRateLimitOptions;\n}\n\nexport interface WebServerOptions {\n /** Web server host */\n host: string;\n\n /** Web server port */\n port: number;\n\n /** Maximum request body size in bytes (default: 25MB) */\n bodyLimit?: number;\n\n /** Connection timeout in milliseconds (default: 10s) */\n connectionTimeout?: number;\n\n /** Web server CORS options */\n cors?: WebServerCorsOptions;\n\n /** Web server error options */\n errors?: WebServerErrorsOptions;\n\n /** Web server controllers directory */\n controllersDirectory: string;\n\n /** Optional directory containing route definition files */\n routesDirectory?: string;\n\n log?: WebServerLogConfig;\n\n /** Web server security options (helmet, rate limiting) */\n security?: WebServerSecurityOptions;\n\n /** Web server debug options */\n debug?: WebServerDebugOptions;\n}\n\n// export interface WebServerLogParams {\n// /** Method */\n// Method: string;\n\n// /** Path */\n// Path: string;\n\n// /** Status code */\n// Status: number;\n\n// /** IP address */\n// IP?: string;\n\n// /** Execution time */\n// Time?: string;\n\n// [key: string]: unknown;\n// }\n"],
|
|
5
5
|
"mappings": "AA2FO,IAAK,qBAAL,kBAAKA,wBAAL;AACL,EAAAA,oBAAA,aAAU;AACV,EAAAA,oBAAA,YAAS;AAFC,SAAAA;AAAA,GAAA;",
|
|
6
6
|
"names": ["WebServerRouteType"]
|
|
7
7
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
|
-
import Fastify from "fastify";
|
|
5
4
|
import cors from "@fastify/cors";
|
|
6
5
|
import helmet from "@fastify/helmet";
|
|
7
|
-
import rateLimit from "@fastify/rate-limit";
|
|
8
6
|
import multipart from "@fastify/multipart";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
} from "
|
|
7
|
+
import rateLimit from "@fastify/rate-limit";
|
|
8
|
+
import Fastify from "fastify";
|
|
9
|
+
import { serializerCompiler, validatorCompiler } from "fastify-type-provider-zod";
|
|
10
|
+
import { WebServerHealthController } from "../index.js";
|
|
12
11
|
import { Logger } from "../logger/index.js";
|
|
12
|
+
import { enterRequestContext } from "../request-context/index.js";
|
|
13
13
|
import { File, Helper, Loader, Time } from "../util/index.js";
|
|
14
14
|
import WebServerUtil from "./util.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
import {
|
|
16
|
+
WebServerRouteType
|
|
17
|
+
} from "./webserver.interface.js";
|
|
18
18
|
class WebServer {
|
|
19
19
|
static {
|
|
20
20
|
__name(this, "WebServer");
|
|
@@ -198,7 +198,7 @@ class WebServer {
|
|
|
198
198
|
logParams.Time = formattedExecutionTime;
|
|
199
199
|
this.log("API Request", logParams);
|
|
200
200
|
}
|
|
201
|
-
async onError(
|
|
201
|
+
async onError(_request, _reply, error) {
|
|
202
202
|
Logger.error({ error });
|
|
203
203
|
}
|
|
204
204
|
async onClose() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/webserver.ts"],
|
|
4
|
-
"sourcesContent": ["import crypto from 'node:crypto';\nimport Fastify, {\n type FastifyInstance,\n type FastifyReply,\n type FastifyRequest,\n type FastifySchema,\n type HTTPMethods,\n} from 'fastify';\nimport cors from '@fastify/cors';\nimport helmet from '@fastify/helmet';\nimport rateLimit from '@fastify/rate-limit';\nimport multipart from '@fastify/multipart';\nimport {\n type AnyRouteSchemaDefinition,\n type WebServerConstructorParams,\n type WebServerOptions,\n type WebServerRoute,\n WebServerRouteType,\n} from './webserver.interface.js';\nimport { Logger } from '../logger/index.js';\nimport { File, Helper, Loader, Time } from '../util/index.js';\nimport WebServerUtil from './util.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport type { DatabaseInstance } from '../database/index.js';\nimport type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';\nimport type { QueueManager } from '../queue/index.js';\nimport { WebServerHealthController } from '../index.js';\nimport type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type EventManager from '../event/manager.js';\nimport { enterRequestContext } from '../request-context/index.js';\nimport { type ZodTypeProvider, serializerCompiler, validatorCompiler } from 'fastify-type-provider-zod';\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n startTime?: number;\n requestId?: string;\n }\n}\n\nclass WebServer {\n private logger: typeof Logger = Logger;\n\n private applicationConfig: ApplicationConfig;\n\n private options: WebServerOptions;\n private routes: WebServerRoute[];\n private readonly explicitRoutesConfigured: boolean;\n\n private redisInstance: RedisInstance;\n private queueManager: QueueManager;\n private eventManager: EventManager;\n private databaseInstance: DatabaseInstance;\n\n public fastifyServer: FastifyInstance<any, any, any, any, ZodTypeProvider>;\n\n private lifecycleManager: LifecycleManager;\n private _isReady = false;\n\n constructor(params: WebServerConstructorParams & { lifecycleManager: LifecycleManager }) {\n // Define default options\n const defaultOptions: Partial<WebServerOptions> = {\n host: '0.0.0.0',\n port: 3001,\n cors: {\n enabled: false,\n },\n errors: {\n verbose: false,\n },\n debug: {\n printRoutes: false,\n simulateSlowConnection: {\n enabled: false,\n delay: 250,\n },\n },\n log: {\n startUp: true,\n },\n };\n\n // Merge default options\n const mergedOptions = Helper.defaultsDeep(params.options, defaultOptions);\n\n this.applicationConfig = params.applicationConfig;\n\n this.options = mergedOptions;\n\n const staticRoutes = Array.isArray(params.routes) ? params.routes : [];\n this.explicitRoutesConfigured = Array.isArray(params.routes);\n this.routes = [...staticRoutes];\n\n this.redisInstance = params.redisInstance;\n this.queueManager = params.queueManager;\n this.eventManager = params.eventManager;\n this.databaseInstance = params.databaseInstance;\n this.lifecycleManager = params.lifecycleManager;\n\n // Create Fastify server\n const defaultBodyLimit = 25 * 1024 * 1024; // 25MB (safer default)\n const defaultConnectionTimeout = 10 * 1000; // 10 seconds (safer default)\n\n this.fastifyServer = Fastify({\n logger: false,\n bodyLimit: this.options.bodyLimit ?? defaultBodyLimit,\n connectionTimeout: this.options.connectionTimeout ?? defaultConnectionTimeout,\n }).withTypeProvider<ZodTypeProvider>();\n\n // Set up Zod validators and serializers for automatic schema validation\n this.fastifyServer.setValidatorCompiler(validatorCompiler);\n this.fastifyServer.setSerializerCompiler(serializerCompiler);\n }\n\n /**\n * Load web server.\n */\n public async load(): Promise<void> {\n // Configure security (helmet, rate limiting)\n await this.configureSecurity();\n\n // Configure hooks\n this.configureHooks();\n\n // Configure CORS\n this.configureCORS();\n\n // Configure multipart uploads\n this.configureMultipartUploads();\n\n // Configure routes\n await this.configureRoutes();\n }\n\n /**\n * Configure security features (Helmet, Rate Limiting)\n */\n private async configureSecurity(): Promise<void> {\n const security = this.options.security ?? {};\n\n // Configure Helmet for security headers\n const helmetConfig = security.helmet ?? { enabled: true };\n if (helmetConfig.enabled !== false) {\n await this.fastifyServer.register(helmet, {\n contentSecurityPolicy: helmetConfig.contentSecurityPolicy !== false,\n crossOriginEmbedderPolicy: helmetConfig.crossOriginEmbedderPolicy !== false,\n crossOriginOpenerPolicy: helmetConfig.crossOriginOpenerPolicy !== false,\n crossOriginResourcePolicy: helmetConfig.crossOriginResourcePolicy !== false,\n dnsPrefetchControl: helmetConfig.dnsPrefetchControl !== false,\n frameguard: helmetConfig.frameguard !== false,\n hidePoweredBy: helmetConfig.hidePoweredBy !== false,\n hsts: helmetConfig.hsts !== false,\n ieNoOpen: helmetConfig.ieNoOpen !== false,\n noSniff: helmetConfig.noSniff !== false,\n originAgentCluster: helmetConfig.originAgentCluster !== false,\n permittedCrossDomainPolicies: helmetConfig.permittedCrossDomainPolicies !== false,\n referrerPolicy: helmetConfig.referrerPolicy !== false,\n xssFilter: helmetConfig.xssFilter !== false,\n });\n }\n\n // Configure rate limiting\n const rateLimitConfig = security.rateLimit ?? { enabled: true };\n if (rateLimitConfig.enabled !== false) {\n await this.fastifyServer.register(rateLimit, {\n max: rateLimitConfig.max ?? 1000,\n timeWindow: rateLimitConfig.timeWindow ?? '1 minute',\n ban: rateLimitConfig.ban,\n cache: rateLimitConfig.cache ?? 5000,\n });\n }\n\n // Warn about wildcard CORS in production\n if (process.env.NODE_ENV === 'production' && this.options.cors?.enabled) {\n const corsConfig = this.options.cors as { enabled: true; urls: string[] };\n if (corsConfig.urls?.includes('*')) {\n this.logger.warn({\n message: 'Wildcard CORS (*) is enabled in production - this is a security risk',\n meta: {\n recommendation: 'Specify allowed origins explicitly',\n },\n });\n }\n }\n }\n\n /**\n * Configure hooks.\n */\n private configureHooks(): void {\n this.fastifyServer.addHook('onListen', async () => this.onListen());\n this.fastifyServer.addHook('onRequest', async request => this.onRequest(request));\n this.fastifyServer.addHook('onResponse', async (request, reply) => this.onResponse(request, reply));\n this.fastifyServer.addHook('onError', async (request, reply, error) => this.onError(request, reply, error));\n this.fastifyServer.addHook('onClose', async () => this.onClose());\n\n // if (process.env.NODE_ENV === 'local') {\n // this.fastifyServer.addHook('onSend', (request, reply, payload, done) => {\n // reply.header('Cache-Control', 'no-store');\n // done();\n // });\n // }\n }\n\n private async onListen(): Promise<void> {\n const address = this.fastifyServer.server.address();\n const port = typeof address === 'string' ? address : address?.port;\n\n if (this.options.log?.startUp) {\n this.log('Started', {\n Host: this.options.host,\n Port: port,\n // CORS: this.options.cors?.enabled && this.options.cors?..length > 0 ? this.options.corsUrls.join(', ') : 'Disabled',\n CORS: this.options.cors?.enabled ? this.options.cors.urls.join(', ') : 'Disabled',\n 'Fastify Version': this.fastifyServer.version,\n });\n }\n }\n\n private async onRequest(request: FastifyRequest): Promise<void> {\n if (\n this.options.debug?.simulateSlowConnection?.enabled &&\n this.options.debug?.simulateSlowConnection?.delay &&\n this.options.debug?.simulateSlowConnection?.delay > 0\n ) {\n await new Promise(resolve => setTimeout(resolve, this.options.debug?.simulateSlowConnection?.delay));\n }\n\n // Generate or use existing request ID for correlation\n const requestId = (request.headers['x-request-id'] as string | undefined) ?? crypto.randomUUID();\n request.requestId = requestId;\n\n // Default health check paths to ignore from logging\n const defaultPathsToIgnore: string[] = [];\n const configuredExcludePaths = this.options.log?.excludePaths ?? [];\n const pathsToIgnore = [...defaultPathsToIgnore, ...configuredExcludePaths];\n\n if (pathsToIgnore.includes(request.url) || request.method === 'OPTIONS') {\n // ...\n } else {\n const startTime = Time.now();\n request.startTime = startTime;\n\n // Initialize AsyncLocalStorage context for this request\n // Using enterWith() to set context for the current async execution\n enterRequestContext({ requestId, startTime });\n }\n }\n\n private async onResponse(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n // Add request ID to response headers for client-side correlation\n if (request.requestId) {\n reply.header('X-Request-ID', request.requestId);\n }\n\n // Clean up request-scoped EntityManager if it exists\n const em = (request as any).__entityManager;\n if (em && typeof em.clear === 'function') {\n em.clear();\n delete (request as any).__entityManager;\n }\n\n if (!request.startTime) {\n return;\n }\n\n const executionTime = Time.calculateElapsedTimeMs({\n startTime: request.startTime,\n });\n const formattedExecutionTime = Time.formatTime({\n time: executionTime,\n numDecimals: 3,\n });\n\n const ip = request.headers['x-forwarded-for'] ?? request.ip;\n\n const logParams: Record<string, unknown> = {\n Method: request.method,\n Path: request.url,\n Status: reply.statusCode,\n };\n\n if (process.env.NODE_ENV !== 'development') {\n logParams.IP = ip.toString();\n }\n\n logParams.Time = formattedExecutionTime;\n\n // if (cluster.isWorker && cluster.worker) {\n // logParams.Worker = cluster.worker.id;\n // }\n\n this.log('API Request', logParams);\n }\n\n private async onError(request: FastifyRequest, reply: FastifyReply, error: Error): Promise<void> {\n // Adjusted for Fastify types\n Logger.error({ error });\n // Implement any additional logic here\n }\n\n private async onClose(): Promise<void> {\n this.log('Stopped');\n }\n\n private configureCORS(): void {\n if (!this.options.cors?.enabled) {\n return;\n }\n\n // Handle wildcard origin for development\n const origin = this.options.cors.urls.includes('*') ? true : this.options.cors.urls;\n\n this.fastifyServer.register(cors, {\n origin,\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization'],\n preflightContinue: false,\n optionsSuccessStatus: 204,\n // credentials: true,\n });\n }\n\n private configureMultipartUploads(): void {\n this.fastifyServer.register(multipart, {\n // attachFieldsToBody: true,\n limits: {\n fieldNameSize: 100,\n fieldSize: 1024 * 1024 * 10,\n fields: 10,\n fileSize: 1024 * 1024 * 1024 * 10, // 10GB file size limit\n files: 1,\n headerPairs: 2000,\n },\n });\n }\n\n /**\n * Configure routes.\n */\n private async configureRoutes(): Promise<void> {\n if (this.options.routesDirectory && this.explicitRoutesConfigured) {\n const baseMessage =\n 'Invalid web server configuration: choose either \"routesDirectory\" for automatic discovery or provide a \"routes\" array.';\n const guidance =\n this.routes.length === 0\n ? ' Remove the empty routes array when using \"routesDirectory\".'\n : ' Remove one of these options so only a single routes source is configured.';\n\n throw new Error(`${baseMessage}${guidance}`);\n }\n\n await this.loadRoutesFromDirectory();\n\n // Check if controllers directory exists\n const controllersDirectoryExists = await File.pathExists(this.options.controllersDirectory ?? '');\n\n if (!controllersDirectoryExists) {\n const routesRequiringControllers = this.routes.length === 0 || this.routes.some(route => !route.handler);\n\n if (routesRequiringControllers) {\n Logger.warn({\n message: 'Web server controllers directory not found',\n meta: {\n Directory: this.options.controllersDirectory,\n },\n });\n\n return;\n }\n }\n\n // Load controllers\n const controllers = controllersDirectoryExists\n ? await Loader.loadModulesInDirectory({\n directory: this.options.controllersDirectory,\n extensions: ['.ts', '.js'],\n })\n : {};\n\n // Add health check routes\n this.routes.push(\n {\n type: WebServerRouteType.Default,\n method: 'GET',\n path: '/health/live',\n controller: WebServerHealthController,\n action: 'live',\n },\n {\n type: WebServerRouteType.Default,\n method: 'GET',\n path: '/health/ready',\n controller: WebServerHealthController,\n action: 'ready',\n },\n );\n\n // Go through each route\n for (const route of this.routes) {\n let ControllerClass: WebServerBaseControllerType;\n\n let controllerName;\n\n if (route.handler && !route.controller && !route.controllerName) {\n if (route.type && route.type !== WebServerRouteType.Default) {\n throw new Error('Handler-only routes are only supported for default route type');\n }\n\n if (!('method' in route)) {\n throw new Error('Handler-only routes require an HTTP method');\n }\n\n const schema = this.buildFastifySchema(route.schema);\n\n this.fastifyServer.route({\n method: route.method,\n url: route.path,\n handler: route.handler,\n ...(schema ? { schema } : {}),\n });\n\n continue;\n }\n\n if (route.controller) {\n ControllerClass = route.controller;\n\n controllerName = ControllerClass.name;\n } else if (route.controllerName) {\n ControllerClass = controllers[route.controllerName] as WebServerBaseControllerType;\n\n controllerName = route.controllerName;\n } else {\n throw new Error('Web server controller config not found');\n }\n\n if (typeof ControllerClass !== 'function') {\n const controllerPath = `${this.options.controllersDirectory}/${route.controllerName}.ts`;\n\n Logger.warn({\n message: 'Web server controller not found',\n meta: {\n Controller: route.controllerName,\n Path: controllerPath,\n Route: `${route.path}`,\n },\n });\n\n continue;\n }\n\n // Initialize controller instance\n const controllerInstance = new ControllerClass({\n applicationConfig: this.applicationConfig,\n webServerOptions: this.options,\n redisInstance: this.redisInstance,\n queueManager: this.queueManager,\n eventManager: this.eventManager,\n databaseInstance: this.databaseInstance,\n lifecycleManager: this.lifecycleManager,\n });\n\n let routeMethod;\n let routeAction;\n let routePath;\n\n switch (route.type) {\n case WebServerRouteType.Default: {\n routeMethod = route.method;\n routeAction = route.action;\n routePath = route.path;\n\n this.defineRoute({\n controllerInstance,\n controllerName,\n routeMethod,\n routePath,\n routeAction,\n routeSchema: route.schema,\n handlerOverride: route.handler?.bind(controllerInstance),\n });\n\n break;\n }\n case WebServerRouteType.Entity: {\n if (this.applicationConfig.database?.enabled === true) {\n const entityModel = await Loader.loadEntityModule({\n entitiesDirectory: this.applicationConfig.database.entitiesDirectory,\n entityName: route.entityName,\n });\n\n const entitySchemaSource = (entityModel as { schema?: { describe?: () => unknown } }).schema;\n\n if (entitySchemaSource && typeof entitySchemaSource.describe !== 'function') {\n const reportedType =\n typeof entitySchemaSource === 'object'\n ? (entitySchemaSource?.constructor?.name ?? 'object')\n : typeof entitySchemaSource;\n\n throw new Error(\n `Entity route auto-validation requires a Joi schema with a describe() method. ` +\n `Entity \"${route.entityName}\" provided a ${reportedType}. ` +\n `If you're using Zod (schema/schemaUpdate) for this entity, migrate to the new DynamicEntity helpers or ` +\n `attach typed route validators instead of relying on WebServerRouteType.Entity auto-validation.`,\n );\n }\n\n const entitySchemaDescription =\n typeof entitySchemaSource?.describe === 'function'\n ? (entitySchemaSource.describe() as\n | {\n keys?: Record<string, { type: string; flags?: { presence?: string }; [key: string]: unknown }>;\n [key: string]: unknown;\n }\n | undefined)\n : undefined;\n\n if (\n entitySchemaSource &&\n (entitySchemaDescription === undefined ||\n typeof entitySchemaDescription !== 'object' ||\n !('keys' in entitySchemaDescription))\n ) {\n const detectedType =\n entitySchemaDescription && typeof entitySchemaDescription === 'object'\n ? (entitySchemaDescription.constructor?.name ?? 'object')\n : typeof entitySchemaDescription;\n\n throw new Error(\n `Entity route auto-validation expected Joi.describe() output with a \"keys\" map, ` +\n `but entity \"${route.entityName}\" returned ${detectedType}. ` +\n `This usually means the entity uses Zod schemas. ` +\n `Switch the entity to use DynamicEntity.defineSchemas or provide Joi-based validation for \"${route.path}\".`,\n );\n }\n\n const schemaKeys = entitySchemaDescription?.keys;\n\n const formattedEntityValidationSchema =\n entitySchemaDescription && schemaKeys\n ? {\n type: 'object',\n properties: Object.fromEntries(\n Object.entries(schemaKeys).map(([key, value]) => [key, { type: value.type }]),\n ),\n required: Object.keys(schemaKeys).filter(\n // Dynamic schema inspection of joi describe output; keys are from trusted entity definitions\n // eslint-disable-next-line security/detect-object-injection\n key => schemaKeys[key].flags?.presence === 'required',\n ),\n }\n : {};\n\n const entityRouteDefinitions = WebServerUtil.getEntityRouteDefinitions({\n basePath: route.path,\n entityValidationSchema: formattedEntityValidationSchema,\n });\n\n for (const entityRouteDefinition of entityRouteDefinitions) {\n this.defineRoute({\n controllerInstance,\n controllerName,\n routeMethod: entityRouteDefinition.method,\n routePath: entityRouteDefinition.path,\n routeAction: entityRouteDefinition.action,\n routeSchema: route.schema,\n handlerOverride: route.handler?.bind(controllerInstance),\n });\n }\n }\n\n break;\n }\n }\n }\n\n if (this.options.debug?.printRoutes) {\n this.log(`Routes:\\n${this.fastifyServer.printRoutes()}`);\n }\n }\n\n private async loadRoutesFromDirectory(): Promise<void> {\n const { routesDirectory } = this.options;\n\n if (!routesDirectory) {\n return;\n }\n\n const directoryExists = await File.pathExists(routesDirectory);\n\n if (!directoryExists) {\n this.logger.warn({\n message: 'Web server routes directory not found',\n meta: {\n Directory: routesDirectory,\n },\n });\n\n return;\n }\n\n const routeModules = await Loader.loadModulesInDirectory<\n WebServerRoute | WebServerRoute[] | { routes?: WebServerRoute[] }\n >({\n directory: routesDirectory,\n extensions: ['.ts', '.js'],\n });\n\n const loadedRoutes: WebServerRoute[] = [];\n\n for (const [moduleName, exportedRoutes] of Object.entries(routeModules)) {\n const normalizedRoutes = this.normalizeRouteExport(exportedRoutes, moduleName);\n\n if (normalizedRoutes.length === 0) {\n continue;\n }\n\n loadedRoutes.push(...normalizedRoutes);\n }\n\n if (loadedRoutes.length > 0) {\n this.routes.push(...loadedRoutes);\n }\n }\n\n private normalizeRouteExport(exportedValue: unknown, moduleName: string): WebServerRoute[] {\n const ensureRouteArray = (value: unknown): WebServerRoute[] => {\n if (Array.isArray(value)) {\n return value;\n }\n\n if (value && typeof value === 'object') {\n const maybeRoute = value as { routes?: unknown };\n\n if (Array.isArray(maybeRoute.routes)) {\n return maybeRoute.routes as WebServerRoute[];\n }\n }\n\n return value ? [value as WebServerRoute] : [];\n };\n\n const routeCandidates = ensureRouteArray(exportedValue);\n const validRoutes: WebServerRoute[] = [];\n\n for (const [index, candidate] of routeCandidates.entries()) {\n if (this.isValidRoute(candidate)) {\n validRoutes.push(candidate);\n } else {\n this.logger.warn({\n message: 'Invalid web server route definition skipped',\n meta: {\n Module: moduleName,\n Index: index,\n },\n });\n }\n }\n\n if (validRoutes.length === 0 && routeCandidates.length > 0) {\n this.logger.warn({\n message: 'No valid routes exported from module',\n meta: {\n Module: moduleName,\n },\n });\n }\n\n return validRoutes;\n }\n\n private isValidRoute(route: unknown): route is WebServerRoute {\n if (!route || typeof route !== 'object') {\n return false;\n }\n\n const candidate = route as Record<string, unknown>;\n const routePath = candidate.path;\n\n if (typeof routePath !== 'string' || routePath.length === 0) {\n return false;\n }\n\n const routeType = candidate.type ?? WebServerRouteType.Default;\n\n const controllerProvided =\n typeof candidate.controller === 'function' || typeof candidate.controllerName === 'string';\n const handlerProvided = typeof candidate.handler === 'function';\n\n if (routeType === WebServerRouteType.Entity || routeType === 'entity') {\n return controllerProvided && typeof candidate.entityName === 'string' && candidate.entityName.length > 0;\n }\n\n // For default routes, either controller+action OR handler must be provided\n if (!controllerProvided && !handlerProvided) {\n return false;\n }\n\n const method = candidate.method;\n\n const isValidMethod =\n typeof method === 'string' ||\n (Array.isArray(method) && method.length > 0 && method.every(m => typeof m === 'string'));\n\n // If handler is provided, we don't need action\n if (handlerProvided) {\n return isValidMethod;\n }\n\n // If controller is provided, we need action\n const action = candidate.action;\n const isValidAction = typeof action === 'string' && action.length > 0;\n\n return isValidMethod && isValidAction;\n }\n\n public async defineRoute({\n controllerInstance,\n controllerName,\n routeMethod,\n routePath,\n routeAction,\n routeSchema,\n handlerOverride,\n }: {\n controllerInstance: any;\n controllerName: string;\n routeMethod: HTTPMethods | HTTPMethods[];\n routePath: string;\n routeAction?: string;\n routeSchema?: AnyRouteSchemaDefinition;\n handlerOverride?: ControllerAction<any>;\n }): Promise<void> {\n let handler = handlerOverride;\n\n if (!handler) {\n if (!routeAction) {\n throw new Error('Route action is required when handler override is not provided');\n }\n\n if (!/^[A-Za-z0-9_]+$/.test(routeAction) || ['__proto__', 'prototype', 'constructor'].includes(routeAction)) {\n throw new Error('Invalid controller action name');\n }\n\n const controllerHandler = controllerInstance[routeAction as keyof typeof controllerInstance];\n\n if (!controllerHandler) {\n Logger.warn({\n message: 'Web server controller action not found',\n meta: {\n Controller: controllerName,\n Action: routeAction,\n },\n });\n\n throw new Error('Web server controller action not found');\n }\n\n handler = controllerHandler.bind(controllerInstance) as ControllerAction<any>;\n }\n\n const fastifySchema = this.buildFastifySchema(routeSchema);\n\n if (!handler) {\n throw new Error('Route handler could not be resolved');\n }\n\n this.fastifyServer.route({\n method: routeMethod,\n url: routePath,\n handler: handler as unknown as (request: FastifyRequest, reply: FastifyReply) => unknown,\n ...(fastifySchema ? { schema: fastifySchema } : {}),\n });\n }\n\n /**\n * Start web server.\n */\n public async start(): Promise<void> {\n try {\n await this.fastifyServer.listen({\n host: this.options.host,\n port: this.options.port,\n });\n this._isReady = true;\n } catch (error) {\n Logger.error({ error });\n throw error;\n }\n }\n\n /**\n * Stop web server.\n */\n public async stop(): Promise<void> {\n this._isReady = false;\n // Close Fastify server\n await this.fastifyServer.close();\n }\n\n private buildFastifySchema(routeSchema?: AnyRouteSchemaDefinition): FastifySchema | undefined {\n if (!routeSchema) {\n return undefined;\n }\n\n const schema: FastifySchema = {};\n\n // With ZodTypeProvider, we can pass Zod schemas directly\n // The type provider handles validation automatically\n if (routeSchema.params) {\n schema.params = routeSchema.params;\n }\n\n if (routeSchema.querystring) {\n schema.querystring = routeSchema.querystring;\n }\n\n if (routeSchema.body) {\n schema.body = routeSchema.body;\n }\n\n if (routeSchema.headers) {\n schema.headers = routeSchema.headers;\n }\n\n if (routeSchema.response) {\n schema.response = routeSchema.response;\n }\n\n return schema;\n }\n\n /**\n * Check if web server is ready to accept traffic.\n */\n public isReady(): boolean {\n return this._isReady && this.fastifyServer.server?.listening === true;\n }\n\n /**\n * Log web server message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'webServer', message, meta });\n }\n}\n\nexport default WebServer;\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import crypto from 'node:crypto';\nimport cors from '@fastify/cors';\nimport helmet from '@fastify/helmet';\nimport multipart from '@fastify/multipart';\nimport rateLimit from '@fastify/rate-limit';\nimport Fastify, {\n type FastifyInstance,\n type FastifyReply,\n type FastifyRequest,\n type FastifySchema,\n type HTTPMethods,\n} from 'fastify';\nimport { serializerCompiler, validatorCompiler, type ZodTypeProvider } from 'fastify-type-provider-zod';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type { DatabaseInstance } from '../database/index.js';\nimport type EventManager from '../event/manager.js';\nimport { WebServerHealthController } from '../index.js';\nimport type { LifecycleManager } from '../lifecycle/lifecycle-manager.js';\nimport { Logger } from '../logger/index.js';\nimport type { QueueManager } from '../queue/index.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport { enterRequestContext } from '../request-context/index.js';\nimport { File, Helper, Loader, Time } from '../util/index.js';\nimport type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';\nimport WebServerUtil from './util.js';\nimport {\n type AnyRouteSchemaDefinition,\n type WebServerConstructorParams,\n type WebServerOptions,\n type WebServerRoute,\n WebServerRouteType,\n} from './webserver.interface.js';\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n startTime?: number;\n requestId?: string;\n }\n}\n\nclass WebServer {\n private logger: typeof Logger = Logger;\n\n private applicationConfig: ApplicationConfig;\n\n private options: WebServerOptions;\n private routes: WebServerRoute[];\n private readonly explicitRoutesConfigured: boolean;\n\n private redisInstance: RedisInstance;\n private queueManager: QueueManager;\n private eventManager: EventManager;\n private databaseInstance: DatabaseInstance;\n\n public fastifyServer: FastifyInstance<any, any, any, any, ZodTypeProvider>;\n\n private lifecycleManager: LifecycleManager;\n private _isReady = false;\n\n constructor(params: WebServerConstructorParams & { lifecycleManager: LifecycleManager }) {\n // Define default options\n const defaultOptions: Partial<WebServerOptions> = {\n host: '0.0.0.0',\n port: 3001,\n cors: {\n enabled: false,\n },\n errors: {\n verbose: false,\n },\n debug: {\n printRoutes: false,\n simulateSlowConnection: {\n enabled: false,\n delay: 250,\n },\n },\n log: {\n startUp: true,\n },\n };\n\n // Merge default options\n const mergedOptions = Helper.defaultsDeep(params.options, defaultOptions);\n\n this.applicationConfig = params.applicationConfig;\n\n this.options = mergedOptions;\n\n const staticRoutes = Array.isArray(params.routes) ? params.routes : [];\n this.explicitRoutesConfigured = Array.isArray(params.routes);\n this.routes = [...staticRoutes];\n\n this.redisInstance = params.redisInstance;\n this.queueManager = params.queueManager;\n this.eventManager = params.eventManager;\n this.databaseInstance = params.databaseInstance;\n this.lifecycleManager = params.lifecycleManager;\n\n // Create Fastify server\n const defaultBodyLimit = 25 * 1024 * 1024; // 25MB (safer default)\n const defaultConnectionTimeout = 10 * 1000; // 10 seconds (safer default)\n\n this.fastifyServer = Fastify({\n logger: false,\n bodyLimit: this.options.bodyLimit ?? defaultBodyLimit,\n connectionTimeout: this.options.connectionTimeout ?? defaultConnectionTimeout,\n }).withTypeProvider<ZodTypeProvider>();\n\n // Set up Zod validators and serializers for automatic schema validation\n this.fastifyServer.setValidatorCompiler(validatorCompiler);\n this.fastifyServer.setSerializerCompiler(serializerCompiler);\n }\n\n /**\n * Load web server.\n */\n public async load(): Promise<void> {\n // Configure security (helmet, rate limiting)\n await this.configureSecurity();\n\n // Configure hooks\n this.configureHooks();\n\n // Configure CORS\n this.configureCORS();\n\n // Configure multipart uploads\n this.configureMultipartUploads();\n\n // Configure routes\n await this.configureRoutes();\n }\n\n /**\n * Configure security features (Helmet, Rate Limiting)\n */\n private async configureSecurity(): Promise<void> {\n const security = this.options.security ?? {};\n\n // Configure Helmet for security headers\n const helmetConfig = security.helmet ?? { enabled: true };\n if (helmetConfig.enabled !== false) {\n await this.fastifyServer.register(helmet, {\n contentSecurityPolicy: helmetConfig.contentSecurityPolicy !== false,\n crossOriginEmbedderPolicy: helmetConfig.crossOriginEmbedderPolicy !== false,\n crossOriginOpenerPolicy: helmetConfig.crossOriginOpenerPolicy !== false,\n crossOriginResourcePolicy: helmetConfig.crossOriginResourcePolicy !== false,\n dnsPrefetchControl: helmetConfig.dnsPrefetchControl !== false,\n frameguard: helmetConfig.frameguard !== false,\n hidePoweredBy: helmetConfig.hidePoweredBy !== false,\n hsts: helmetConfig.hsts !== false,\n ieNoOpen: helmetConfig.ieNoOpen !== false,\n noSniff: helmetConfig.noSniff !== false,\n originAgentCluster: helmetConfig.originAgentCluster !== false,\n permittedCrossDomainPolicies: helmetConfig.permittedCrossDomainPolicies !== false,\n referrerPolicy: helmetConfig.referrerPolicy !== false,\n xssFilter: helmetConfig.xssFilter !== false,\n });\n }\n\n // Configure rate limiting\n const rateLimitConfig = security.rateLimit ?? { enabled: true };\n if (rateLimitConfig.enabled !== false) {\n await this.fastifyServer.register(rateLimit, {\n max: rateLimitConfig.max ?? 1000,\n timeWindow: rateLimitConfig.timeWindow ?? '1 minute',\n ban: rateLimitConfig.ban,\n cache: rateLimitConfig.cache ?? 5000,\n });\n }\n\n // Warn about wildcard CORS in production\n if (process.env.NODE_ENV === 'production' && this.options.cors?.enabled) {\n const corsConfig = this.options.cors as { enabled: true; urls: string[] };\n if (corsConfig.urls?.includes('*')) {\n this.logger.warn({\n message: 'Wildcard CORS (*) is enabled in production - this is a security risk',\n meta: {\n recommendation: 'Specify allowed origins explicitly',\n },\n });\n }\n }\n }\n\n /**\n * Configure hooks.\n */\n private configureHooks(): void {\n this.fastifyServer.addHook('onListen', async () => this.onListen());\n this.fastifyServer.addHook('onRequest', async request => this.onRequest(request));\n this.fastifyServer.addHook('onResponse', async (request, reply) => this.onResponse(request, reply));\n this.fastifyServer.addHook('onError', async (request, reply, error) => this.onError(request, reply, error));\n this.fastifyServer.addHook('onClose', async () => this.onClose());\n\n // if (process.env.NODE_ENV === 'local') {\n // this.fastifyServer.addHook('onSend', (request, reply, payload, done) => {\n // reply.header('Cache-Control', 'no-store');\n // done();\n // });\n // }\n }\n\n private async onListen(): Promise<void> {\n const address = this.fastifyServer.server.address();\n const port = typeof address === 'string' ? address : address?.port;\n\n if (this.options.log?.startUp) {\n this.log('Started', {\n Host: this.options.host,\n Port: port,\n // CORS: this.options.cors?.enabled && this.options.cors?..length > 0 ? this.options.corsUrls.join(', ') : 'Disabled',\n CORS: this.options.cors?.enabled ? this.options.cors.urls.join(', ') : 'Disabled',\n 'Fastify Version': this.fastifyServer.version,\n });\n }\n }\n\n private async onRequest(request: FastifyRequest): Promise<void> {\n if (\n this.options.debug?.simulateSlowConnection?.enabled &&\n this.options.debug?.simulateSlowConnection?.delay &&\n this.options.debug?.simulateSlowConnection?.delay > 0\n ) {\n await new Promise(resolve => setTimeout(resolve, this.options.debug?.simulateSlowConnection?.delay));\n }\n\n // Generate or use existing request ID for correlation\n const requestId = (request.headers['x-request-id'] as string | undefined) ?? crypto.randomUUID();\n request.requestId = requestId;\n\n // Default health check paths to ignore from logging\n const defaultPathsToIgnore: string[] = [];\n const configuredExcludePaths = this.options.log?.excludePaths ?? [];\n const pathsToIgnore = [...defaultPathsToIgnore, ...configuredExcludePaths];\n\n if (pathsToIgnore.includes(request.url) || request.method === 'OPTIONS') {\n // ...\n } else {\n const startTime = Time.now();\n request.startTime = startTime;\n\n // Initialize AsyncLocalStorage context for this request\n // Using enterWith() to set context for the current async execution\n enterRequestContext({ requestId, startTime });\n }\n }\n\n private async onResponse(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n // Add request ID to response headers for client-side correlation\n if (request.requestId) {\n reply.header('X-Request-ID', request.requestId);\n }\n\n // Clean up request-scoped EntityManager if it exists\n const em = (request as any).__entityManager;\n if (em && typeof em.clear === 'function') {\n em.clear();\n delete (request as any).__entityManager;\n }\n\n if (!request.startTime) {\n return;\n }\n\n const executionTime = Time.calculateElapsedTimeMs({\n startTime: request.startTime,\n });\n const formattedExecutionTime = Time.formatTime({\n time: executionTime,\n numDecimals: 3,\n });\n\n const ip = request.headers['x-forwarded-for'] ?? request.ip;\n\n const logParams: Record<string, unknown> = {\n Method: request.method,\n Path: request.url,\n Status: reply.statusCode,\n };\n\n if (process.env.NODE_ENV !== 'development') {\n logParams.IP = ip.toString();\n }\n\n logParams.Time = formattedExecutionTime;\n\n // if (cluster.isWorker && cluster.worker) {\n // logParams.Worker = cluster.worker.id;\n // }\n\n this.log('API Request', logParams);\n }\n\n private async onError(_request: FastifyRequest, _reply: FastifyReply, error: Error): Promise<void> {\n // Adjusted for Fastify types\n Logger.error({ error });\n // Implement any additional logic here\n }\n\n private async onClose(): Promise<void> {\n this.log('Stopped');\n }\n\n private configureCORS(): void {\n if (!this.options.cors?.enabled) {\n return;\n }\n\n // Handle wildcard origin for development\n const origin = this.options.cors.urls.includes('*') ? true : this.options.cors.urls;\n\n this.fastifyServer.register(cors, {\n origin,\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization'],\n preflightContinue: false,\n optionsSuccessStatus: 204,\n // credentials: true,\n });\n }\n\n private configureMultipartUploads(): void {\n this.fastifyServer.register(multipart, {\n // attachFieldsToBody: true,\n limits: {\n fieldNameSize: 100,\n fieldSize: 1024 * 1024 * 10,\n fields: 10,\n fileSize: 1024 * 1024 * 1024 * 10, // 10GB file size limit\n files: 1,\n headerPairs: 2000,\n },\n });\n }\n\n /**\n * Configure routes.\n */\n private async configureRoutes(): Promise<void> {\n if (this.options.routesDirectory && this.explicitRoutesConfigured) {\n const baseMessage =\n 'Invalid web server configuration: choose either \"routesDirectory\" for automatic discovery or provide a \"routes\" array.';\n const guidance =\n this.routes.length === 0\n ? ' Remove the empty routes array when using \"routesDirectory\".'\n : ' Remove one of these options so only a single routes source is configured.';\n\n throw new Error(`${baseMessage}${guidance}`);\n }\n\n await this.loadRoutesFromDirectory();\n\n // Check if controllers directory exists\n const controllersDirectoryExists = await File.pathExists(this.options.controllersDirectory ?? '');\n\n if (!controllersDirectoryExists) {\n const routesRequiringControllers = this.routes.length === 0 || this.routes.some(route => !route.handler);\n\n if (routesRequiringControllers) {\n Logger.warn({\n message: 'Web server controllers directory not found',\n meta: {\n Directory: this.options.controllersDirectory,\n },\n });\n\n return;\n }\n }\n\n // Load controllers\n const controllers = controllersDirectoryExists\n ? await Loader.loadModulesInDirectory({\n directory: this.options.controllersDirectory,\n extensions: ['.ts', '.js'],\n })\n : {};\n\n // Add health check routes\n this.routes.push(\n {\n type: WebServerRouteType.Default,\n method: 'GET',\n path: '/health/live',\n controller: WebServerHealthController,\n action: 'live',\n },\n {\n type: WebServerRouteType.Default,\n method: 'GET',\n path: '/health/ready',\n controller: WebServerHealthController,\n action: 'ready',\n },\n );\n\n // Go through each route\n for (const route of this.routes) {\n let ControllerClass: WebServerBaseControllerType;\n\n let controllerName: string;\n\n if (route.handler && !route.controller && !route.controllerName) {\n if (route.type && route.type !== WebServerRouteType.Default) {\n throw new Error('Handler-only routes are only supported for default route type');\n }\n\n if (!('method' in route)) {\n throw new Error('Handler-only routes require an HTTP method');\n }\n\n const schema = this.buildFastifySchema(route.schema);\n\n this.fastifyServer.route({\n method: route.method,\n url: route.path,\n handler: route.handler,\n ...(schema ? { schema } : {}),\n });\n\n continue;\n }\n\n if (route.controller) {\n ControllerClass = route.controller;\n\n controllerName = ControllerClass.name;\n } else if (route.controllerName) {\n ControllerClass = controllers[route.controllerName] as WebServerBaseControllerType;\n\n controllerName = route.controllerName;\n } else {\n throw new Error('Web server controller config not found');\n }\n\n if (typeof ControllerClass !== 'function') {\n const controllerPath = `${this.options.controllersDirectory}/${route.controllerName}.ts`;\n\n Logger.warn({\n message: 'Web server controller not found',\n meta: {\n Controller: route.controllerName,\n Path: controllerPath,\n Route: `${route.path}`,\n },\n });\n\n continue;\n }\n\n // Initialize controller instance\n const controllerInstance = new ControllerClass({\n applicationConfig: this.applicationConfig,\n webServerOptions: this.options,\n redisInstance: this.redisInstance,\n queueManager: this.queueManager,\n eventManager: this.eventManager,\n databaseInstance: this.databaseInstance,\n lifecycleManager: this.lifecycleManager,\n });\n\n let routeMethod: HTTPMethods | HTTPMethods[];\n let routeAction: string | undefined;\n let routePath: string;\n\n switch (route.type) {\n case WebServerRouteType.Default: {\n routeMethod = route.method;\n routeAction = route.action;\n routePath = route.path;\n\n this.defineRoute({\n controllerInstance,\n controllerName,\n routeMethod,\n routePath,\n routeAction,\n routeSchema: route.schema,\n handlerOverride: route.handler?.bind(controllerInstance),\n });\n\n break;\n }\n case WebServerRouteType.Entity: {\n if (this.applicationConfig.database?.enabled === true) {\n const entityModel = await Loader.loadEntityModule({\n entitiesDirectory: this.applicationConfig.database.entitiesDirectory,\n entityName: route.entityName,\n });\n\n const entitySchemaSource = (entityModel as { schema?: { describe?: () => unknown } }).schema;\n\n if (entitySchemaSource && typeof entitySchemaSource.describe !== 'function') {\n const reportedType =\n typeof entitySchemaSource === 'object'\n ? (entitySchemaSource?.constructor?.name ?? 'object')\n : typeof entitySchemaSource;\n\n throw new Error(\n `Entity route auto-validation requires a Joi schema with a describe() method. ` +\n `Entity \"${route.entityName}\" provided a ${reportedType}. ` +\n `If you're using Zod (schema/schemaUpdate) for this entity, migrate to the new DynamicEntity helpers or ` +\n `attach typed route validators instead of relying on WebServerRouteType.Entity auto-validation.`,\n );\n }\n\n const entitySchemaDescription =\n typeof entitySchemaSource?.describe === 'function'\n ? (entitySchemaSource.describe() as\n | {\n keys?: Record<string, { type: string; flags?: { presence?: string }; [key: string]: unknown }>;\n [key: string]: unknown;\n }\n | undefined)\n : undefined;\n\n if (\n entitySchemaSource &&\n (entitySchemaDescription === undefined ||\n typeof entitySchemaDescription !== 'object' ||\n !('keys' in entitySchemaDescription))\n ) {\n const detectedType =\n entitySchemaDescription && typeof entitySchemaDescription === 'object'\n ? (entitySchemaDescription.constructor?.name ?? 'object')\n : typeof entitySchemaDescription;\n\n throw new Error(\n `Entity route auto-validation expected Joi.describe() output with a \"keys\" map, ` +\n `but entity \"${route.entityName}\" returned ${detectedType}. ` +\n `This usually means the entity uses Zod schemas. ` +\n `Switch the entity to use DynamicEntity.defineSchemas or provide Joi-based validation for \"${route.path}\".`,\n );\n }\n\n const schemaKeys = entitySchemaDescription?.keys;\n\n const formattedEntityValidationSchema =\n entitySchemaDescription && schemaKeys\n ? {\n type: 'object',\n properties: Object.fromEntries(\n Object.entries(schemaKeys).map(([key, value]) => [key, { type: value.type }]),\n ),\n required: Object.keys(schemaKeys).filter(\n // Dynamic schema inspection of joi describe output; keys are from trusted entity definitions\n // eslint-disable-next-line security/detect-object-injection\n key => schemaKeys[key].flags?.presence === 'required',\n ),\n }\n : {};\n\n const entityRouteDefinitions = WebServerUtil.getEntityRouteDefinitions({\n basePath: route.path,\n entityValidationSchema: formattedEntityValidationSchema,\n });\n\n for (const entityRouteDefinition of entityRouteDefinitions) {\n this.defineRoute({\n controllerInstance,\n controllerName,\n routeMethod: entityRouteDefinition.method,\n routePath: entityRouteDefinition.path,\n routeAction: entityRouteDefinition.action,\n routeSchema: route.schema,\n handlerOverride: route.handler?.bind(controllerInstance),\n });\n }\n }\n\n break;\n }\n }\n }\n\n if (this.options.debug?.printRoutes) {\n this.log(`Routes:\\n${this.fastifyServer.printRoutes()}`);\n }\n }\n\n private async loadRoutesFromDirectory(): Promise<void> {\n const { routesDirectory } = this.options;\n\n if (!routesDirectory) {\n return;\n }\n\n const directoryExists = await File.pathExists(routesDirectory);\n\n if (!directoryExists) {\n this.logger.warn({\n message: 'Web server routes directory not found',\n meta: {\n Directory: routesDirectory,\n },\n });\n\n return;\n }\n\n const routeModules = await Loader.loadModulesInDirectory<\n WebServerRoute | WebServerRoute[] | { routes?: WebServerRoute[] }\n >({\n directory: routesDirectory,\n extensions: ['.ts', '.js'],\n });\n\n const loadedRoutes: WebServerRoute[] = [];\n\n for (const [moduleName, exportedRoutes] of Object.entries(routeModules)) {\n const normalizedRoutes = this.normalizeRouteExport(exportedRoutes, moduleName);\n\n if (normalizedRoutes.length === 0) {\n continue;\n }\n\n loadedRoutes.push(...normalizedRoutes);\n }\n\n if (loadedRoutes.length > 0) {\n this.routes.push(...loadedRoutes);\n }\n }\n\n private normalizeRouteExport(exportedValue: unknown, moduleName: string): WebServerRoute[] {\n const ensureRouteArray = (value: unknown): WebServerRoute[] => {\n if (Array.isArray(value)) {\n return value;\n }\n\n if (value && typeof value === 'object') {\n const maybeRoute = value as { routes?: unknown };\n\n if (Array.isArray(maybeRoute.routes)) {\n return maybeRoute.routes as WebServerRoute[];\n }\n }\n\n return value ? [value as WebServerRoute] : [];\n };\n\n const routeCandidates = ensureRouteArray(exportedValue);\n const validRoutes: WebServerRoute[] = [];\n\n for (const [index, candidate] of routeCandidates.entries()) {\n if (this.isValidRoute(candidate)) {\n validRoutes.push(candidate);\n } else {\n this.logger.warn({\n message: 'Invalid web server route definition skipped',\n meta: {\n Module: moduleName,\n Index: index,\n },\n });\n }\n }\n\n if (validRoutes.length === 0 && routeCandidates.length > 0) {\n this.logger.warn({\n message: 'No valid routes exported from module',\n meta: {\n Module: moduleName,\n },\n });\n }\n\n return validRoutes;\n }\n\n private isValidRoute(route: unknown): route is WebServerRoute {\n if (!route || typeof route !== 'object') {\n return false;\n }\n\n const candidate = route as Record<string, unknown>;\n const routePath = candidate.path;\n\n if (typeof routePath !== 'string' || routePath.length === 0) {\n return false;\n }\n\n const routeType = candidate.type ?? WebServerRouteType.Default;\n\n const controllerProvided =\n typeof candidate.controller === 'function' || typeof candidate.controllerName === 'string';\n const handlerProvided = typeof candidate.handler === 'function';\n\n if (routeType === WebServerRouteType.Entity || routeType === 'entity') {\n return controllerProvided && typeof candidate.entityName === 'string' && candidate.entityName.length > 0;\n }\n\n // For default routes, either controller+action OR handler must be provided\n if (!controllerProvided && !handlerProvided) {\n return false;\n }\n\n const method = candidate.method;\n\n const isValidMethod =\n typeof method === 'string' ||\n (Array.isArray(method) && method.length > 0 && method.every(m => typeof m === 'string'));\n\n // If handler is provided, we don't need action\n if (handlerProvided) {\n return isValidMethod;\n }\n\n // If controller is provided, we need action\n const action = candidate.action;\n const isValidAction = typeof action === 'string' && action.length > 0;\n\n return isValidMethod && isValidAction;\n }\n\n public async defineRoute({\n controllerInstance,\n controllerName,\n routeMethod,\n routePath,\n routeAction,\n routeSchema,\n handlerOverride,\n }: {\n controllerInstance: any;\n controllerName: string;\n routeMethod: HTTPMethods | HTTPMethods[];\n routePath: string;\n routeAction?: string;\n routeSchema?: AnyRouteSchemaDefinition;\n handlerOverride?: ControllerAction<any>;\n }): Promise<void> {\n let handler = handlerOverride;\n\n if (!handler) {\n if (!routeAction) {\n throw new Error('Route action is required when handler override is not provided');\n }\n\n if (!/^[A-Za-z0-9_]+$/.test(routeAction) || ['__proto__', 'prototype', 'constructor'].includes(routeAction)) {\n throw new Error('Invalid controller action name');\n }\n\n const controllerHandler = controllerInstance[routeAction as keyof typeof controllerInstance];\n\n if (!controllerHandler) {\n Logger.warn({\n message: 'Web server controller action not found',\n meta: {\n Controller: controllerName,\n Action: routeAction,\n },\n });\n\n throw new Error('Web server controller action not found');\n }\n\n handler = controllerHandler.bind(controllerInstance) as ControllerAction<any>;\n }\n\n const fastifySchema = this.buildFastifySchema(routeSchema);\n\n if (!handler) {\n throw new Error('Route handler could not be resolved');\n }\n\n this.fastifyServer.route({\n method: routeMethod,\n url: routePath,\n handler: handler as unknown as (request: FastifyRequest, reply: FastifyReply) => unknown,\n ...(fastifySchema ? { schema: fastifySchema } : {}),\n });\n }\n\n /**\n * Start web server.\n */\n public async start(): Promise<void> {\n try {\n await this.fastifyServer.listen({\n host: this.options.host,\n port: this.options.port,\n });\n this._isReady = true;\n } catch (error) {\n Logger.error({ error });\n throw error;\n }\n }\n\n /**\n * Stop web server.\n */\n public async stop(): Promise<void> {\n this._isReady = false;\n // Close Fastify server\n await this.fastifyServer.close();\n }\n\n private buildFastifySchema(routeSchema?: AnyRouteSchemaDefinition): FastifySchema | undefined {\n if (!routeSchema) {\n return undefined;\n }\n\n const schema: FastifySchema = {};\n\n // With ZodTypeProvider, we can pass Zod schemas directly\n // The type provider handles validation automatically\n if (routeSchema.params) {\n schema.params = routeSchema.params;\n }\n\n if (routeSchema.querystring) {\n schema.querystring = routeSchema.querystring;\n }\n\n if (routeSchema.body) {\n schema.body = routeSchema.body;\n }\n\n if (routeSchema.headers) {\n schema.headers = routeSchema.headers;\n }\n\n if (routeSchema.response) {\n schema.response = routeSchema.response;\n }\n\n return schema;\n }\n\n /**\n * Check if web server is ready to accept traffic.\n */\n public isReady(): boolean {\n return this._isReady && this.fastifyServer.server?.listening === true;\n }\n\n /**\n * Log web server message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'webServer', message, meta });\n }\n}\n\nexport default WebServer;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -16,7 +16,7 @@ import type { WebSocketServerBaseControllerConstructorParams } from './base.inte
|
|
|
16
16
|
* class MyController extends WebSocketServerBaseController {
|
|
17
17
|
* private em = this.databaseInstance.getEntityManager(); // LEAK!
|
|
18
18
|
* async handleMessage(ws, data) {
|
|
19
|
-
* await this.em.findOne(
|
|
19
|
+
* await this.em.findOne(User, { id: data.userId }); // Identity map grows forever
|
|
20
20
|
* }
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
@@ -26,7 +26,7 @@ import type { WebSocketServerBaseControllerConstructorParams } from './base.inte
|
|
|
26
26
|
* class MyController extends WebSocketServerBaseController {
|
|
27
27
|
* async handleMessage(ws, data) {
|
|
28
28
|
* await this.databaseInstance.withEntityManager(async (em) => {
|
|
29
|
-
* const user = await em.findOne(
|
|
29
|
+
* const user = await em.findOne(User, { id: data.userId });
|
|
30
30
|
* // em automatically cleaned up after this block
|
|
31
31
|
* });
|
|
32
32
|
* }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/websocket/controller/server/base.ts"],
|
|
4
|
-
"sourcesContent": ["import type DatabaseInstance from '../../../database/instance.js';\nimport type QueueManager from '../../../queue/manager.js';\nimport type { RedisInstance } from '../../../redis/index.js';\nimport type WebSocketServer from '../../websocket-server.js';\nimport type { WebSocketServerBaseControllerConstructorParams } from './base.interface.js';\n\n/**\n * Base WebSocket Server Controller\n *\n * \u26A0\uFE0F IMPORTANT MEMORY MANAGEMENT:\n *\n * WebSocket controllers are LONG-LIVED SINGLETONS - one instance handles\n * ALL client connections and messages throughout the application lifetime.\n *\n * \u274C WRONG - Memory Leak:\n * ```typescript\n * class MyController extends WebSocketServerBaseController {\n * private em = this.databaseInstance.getEntityManager(); // LEAK!\n * async handleMessage(ws, data) {\n * await this.em.findOne(
|
|
4
|
+
"sourcesContent": ["import type DatabaseInstance from '../../../database/instance.js';\nimport type QueueManager from '../../../queue/manager.js';\nimport type { RedisInstance } from '../../../redis/index.js';\nimport type WebSocketServer from '../../websocket-server.js';\nimport type { WebSocketServerBaseControllerConstructorParams } from './base.interface.js';\n\n/**\n * Base WebSocket Server Controller\n *\n * \u26A0\uFE0F IMPORTANT MEMORY MANAGEMENT:\n *\n * WebSocket controllers are LONG-LIVED SINGLETONS - one instance handles\n * ALL client connections and messages throughout the application lifetime.\n *\n * \u274C WRONG - Memory Leak:\n * ```typescript\n * class MyController extends WebSocketServerBaseController {\n * private em = this.databaseInstance.getEntityManager(); // LEAK!\n * async handleMessage(ws, data) {\n * await this.em.findOne(User, { id: data.userId }); // Identity map grows forever\n * }\n * }\n * ```\n *\n * \u2705 CORRECT - Per-message EntityManager:\n * ```typescript\n * class MyController extends WebSocketServerBaseController {\n * async handleMessage(ws, data) {\n * await this.databaseInstance.withEntityManager(async (em) => {\n * const user = await em.findOne(User, { id: data.userId });\n * // em automatically cleaned up after this block\n * });\n * }\n * }\n * ```\n *\n * @see DatabaseInstance.withEntityManager for safe EntityManager usage\n */\nexport default abstract class WebSocketServerBaseController {\n protected webSocketServer: WebSocketServer;\n protected redisInstance: RedisInstance;\n protected queueManager: QueueManager;\n protected databaseInstance: DatabaseInstance;\n\n constructor({\n webSocketServer,\n redisInstance,\n queueManager,\n databaseInstance,\n }: WebSocketServerBaseControllerConstructorParams) {\n this.webSocketServer = webSocketServer;\n this.redisInstance = redisInstance;\n this.queueManager = queueManager;\n this.databaseInstance = databaseInstance;\n }\n}\n"],
|
|
5
5
|
"mappings": ";;AAsCA,MAAO,8BAAqD;AAAA,EAtC5D,OAsC4D;AAAA;AAAA;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEV,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAmD;AACjD,SAAK,kBAAkB;AACvB,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,mBAAmB;AAAA,EAC1B;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|