@scpxl/nodejs-framework 1.0.22 → 1.0.25
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 +264 -26
- package/dist/api-requester/api-requester.d.ts +32 -0
- package/dist/api-requester/api-requester.d.ts.map +1 -0
- package/dist/api-requester/api-requester.js +2 -1
- package/dist/api-requester/api-requester.js.map +2 -2
- package/dist/api-requester/index.d.ts +3 -0
- package/dist/api-requester/index.d.ts.map +1 -0
- package/dist/application/base-application.d.ts +106 -0
- package/dist/application/base-application.d.ts.map +1 -0
- package/dist/application/base-application.interface.d.ts +162 -0
- package/dist/application/base-application.interface.d.ts.map +1 -0
- package/dist/application/base-application.js +7 -3
- package/dist/application/base-application.js.map +2 -2
- package/dist/application/command-application.d.ts +18 -0
- package/dist/application/command-application.d.ts.map +1 -0
- package/dist/application/command-application.interface.d.ts +26 -0
- package/dist/application/command-application.interface.d.ts.map +1 -0
- package/dist/application/index.d.ts +5 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/web-application.d.ts +43 -0
- package/dist/application/web-application.d.ts.map +1 -0
- package/dist/application/web-application.interface.d.ts +21 -0
- package/dist/application/web-application.interface.d.ts.map +1 -0
- package/dist/application/web-application.js +1 -0
- package/dist/application/web-application.js.map +2 -2
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/jwt.d.ts +25 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/manager.d.ts +107 -0
- package/dist/cache/manager.d.ts.map +1 -0
- package/dist/cache/manager.js +2 -1
- package/dist/cache/manager.js.map +2 -2
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +12591 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cluster/cluster-manager.d.ts +18 -0
- package/dist/cluster/cluster-manager.d.ts.map +1 -0
- package/dist/cluster/cluster-manager.interface.d.ts +23 -0
- package/dist/cluster/cluster-manager.interface.d.ts.map +1 -0
- package/dist/cluster/cluster-manager.js +45 -8
- package/dist/cluster/cluster-manager.js.map +2 -2
- package/dist/cluster/index.d.ts +2 -0
- package/dist/cluster/index.d.ts.map +1 -0
- package/dist/command/command-manager.d.ts +19 -0
- package/dist/command/command-manager.d.ts.map +1 -0
- package/dist/command/command.d.ts +27 -0
- package/dist/command/command.d.ts.map +1 -0
- package/dist/command/command.interface.d.ts +11 -0
- package/dist/command/command.interface.d.ts.map +1 -0
- package/dist/command/index.d.ts +3 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/config/env.d.ts +11 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/schema.d.ts +432 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/database/dynamic-entity-form-decorators.d.ts +31 -0
- package/dist/database/dynamic-entity-form-decorators.d.ts.map +1 -0
- package/dist/database/dynamic-entity-form-decorators.js.map +1 -1
- package/dist/database/dynamic-entity.d.ts +18 -0
- package/dist/database/dynamic-entity.d.ts.map +1 -0
- package/dist/database/dynamic-entity.js +11 -1
- package/dist/database/dynamic-entity.js.map +2 -2
- package/dist/database/index.d.ts +5 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/instance.d.ts +36 -0
- package/dist/database/instance.d.ts.map +1 -0
- package/dist/database/instance.interface.d.ts +5 -0
- package/dist/database/instance.interface.d.ts.map +1 -0
- package/dist/database/manager.d.ts +27 -0
- package/dist/database/manager.d.ts.map +1 -0
- package/dist/database/manager.interface.d.ts +18 -0
- package/dist/database/manager.interface.d.ts.map +1 -0
- package/dist/database/manager.js +3 -2
- package/dist/database/manager.js.map +2 -2
- package/dist/error/error-reporter.d.ts +109 -0
- package/dist/error/error-reporter.d.ts.map +1 -0
- package/dist/error/error-reporter.js +32 -29
- package/dist/error/error-reporter.js.map +2 -2
- package/dist/error/error.interface.d.ts +126 -0
- package/dist/error/error.interface.d.ts.map +1 -0
- package/dist/error/framework-errors.d.ts +113 -0
- package/dist/error/framework-errors.d.ts.map +1 -0
- package/dist/error/index.d.ts +6 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +3 -2
- package/dist/error/index.js.map +2 -2
- package/dist/event/controller/base.d.ts +23 -0
- package/dist/event/controller/base.d.ts.map +1 -0
- package/dist/event/controller/base.interface.d.ts +11 -0
- package/dist/event/controller/base.interface.d.ts.map +1 -0
- package/dist/event/controller/base.js +2 -1
- package/dist/event/controller/base.js.map +2 -2
- package/dist/event/index.d.ts +5 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/event/manager.d.ts +21 -0
- package/dist/event/manager.d.ts.map +1 -0
- package/dist/event/manager.interface.d.ts +137 -0
- package/dist/event/manager.interface.d.ts.map +1 -0
- package/dist/event/manager.js +5 -4
- package/dist/event/manager.js.map +2 -2
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lifecycle/exit.d.ts +11 -0
- package/dist/lifecycle/exit.d.ts.map +1 -0
- package/dist/lifecycle/exit.js.map +2 -2
- package/dist/lifecycle/index.d.ts +7 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-manager.d.ts +66 -0
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-manager.js +6 -11
- package/dist/lifecycle/lifecycle-manager.js.map +2 -2
- package/dist/lifecycle/shutdown-controller.d.ts +15 -0
- package/dist/lifecycle/shutdown-controller.d.ts.map +1 -0
- package/dist/lifecycle/types.d.ts +28 -0
- package/dist/lifecycle/types.d.ts.map +1 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/logger.d.ts +59 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.interface.d.ts +2 -0
- package/dist/logger/logger.interface.d.ts.map +1 -0
- package/dist/logger/logger.js +11 -3
- package/dist/logger/logger.js.map +2 -2
- package/dist/performance/cache-performance.d.ts +64 -0
- package/dist/performance/cache-performance.d.ts.map +1 -0
- package/dist/performance/database-performance.d.ts +40 -0
- package/dist/performance/database-performance.d.ts.map +1 -0
- package/dist/performance/index.d.ts +8 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/performance-monitor.d.ts +68 -0
- package/dist/performance/performance-monitor.d.ts.map +1 -0
- package/dist/performance/performance-monitor.js +10 -3
- package/dist/performance/performance-monitor.js.map +2 -2
- package/dist/performance/performance-monitor.plugin.d.ts +24 -0
- package/dist/performance/performance-monitor.plugin.d.ts.map +1 -0
- package/dist/performance/queue-performance.d.ts +46 -0
- package/dist/performance/queue-performance.d.ts.map +1 -0
- package/dist/performance/webserver-performance.d.ts +69 -0
- package/dist/performance/webserver-performance.d.ts.map +1 -0
- package/dist/performance/websocket-performance.d.ts +44 -0
- package/dist/performance/websocket-performance.d.ts.map +1 -0
- package/dist/queue/index.d.ts +6 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.interface.d.ts +10 -0
- package/dist/queue/index.interface.d.ts.map +1 -0
- package/dist/queue/job.interface.d.ts +43 -0
- package/dist/queue/job.interface.d.ts.map +1 -0
- package/dist/queue/manager.d.ts +44 -0
- package/dist/queue/manager.d.ts.map +1 -0
- package/dist/queue/manager.interface.d.ts +18 -0
- package/dist/queue/manager.interface.d.ts.map +1 -0
- package/dist/queue/processor/base.d.ts +29 -0
- package/dist/queue/processor/base.d.ts.map +1 -0
- package/dist/queue/processor/base.js +2 -1
- package/dist/queue/processor/base.js.map +2 -2
- package/dist/queue/processor/processor.interface.d.ts +16 -0
- package/dist/queue/processor/processor.interface.d.ts.map +1 -0
- package/dist/queue/worker.d.ts +14 -0
- package/dist/queue/worker.d.ts.map +1 -0
- package/dist/queue/worker.interface.d.ts +13 -0
- package/dist/queue/worker.interface.d.ts.map +1 -0
- package/dist/redis/index.d.ts +3 -0
- package/dist/redis/index.d.ts.map +1 -0
- package/dist/redis/instance.d.ts +32 -0
- package/dist/redis/instance.d.ts.map +1 -0
- package/dist/redis/instance.interface.d.ts +9 -0
- package/dist/redis/instance.interface.d.ts.map +1 -0
- package/dist/redis/manager.d.ts +15 -0
- package/dist/redis/manager.d.ts.map +1 -0
- package/dist/redis/manager.interface.d.ts +8 -0
- package/dist/redis/manager.interface.d.ts.map +1 -0
- package/dist/redis/manager.js +16 -16
- package/dist/redis/manager.js.map +2 -2
- package/dist/request-context/index.d.ts +3 -0
- package/dist/request-context/index.d.ts.map +1 -0
- package/dist/request-context/request-context.d.ts +108 -0
- package/dist/request-context/request-context.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.d.ts +46 -0
- package/dist/request-context/request-context.interface.d.ts.map +1 -0
- package/dist/schemas/common.d.ts +197 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +108 -0
- package/dist/schemas/common.js.map +7 -0
- package/dist/schemas/index.d.ts +6 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/index.js.map +7 -0
- package/dist/services/aws/index.d.ts +2 -0
- package/dist/services/aws/index.d.ts.map +1 -0
- package/dist/services/aws/s3.d.ts +54 -0
- package/dist/services/aws/s3.d.ts.map +1 -0
- package/dist/services/aws/s3.interface.d.ts +14 -0
- package/dist/services/aws/s3.interface.d.ts.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/util/file.d.ts +58 -0
- package/dist/util/file.d.ts.map +1 -0
- package/dist/util/helper.d.ts +51 -0
- package/dist/util/helper.d.ts.map +1 -0
- package/dist/util/helper.js +72 -10
- package/dist/util/helper.js.map +2 -2
- package/dist/util/image.d.ts +12 -0
- package/dist/util/image.d.ts.map +1 -0
- package/dist/util/index.d.ts +11 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/loader.d.ts +21 -0
- package/dist/util/loader.d.ts.map +1 -0
- package/dist/util/loader.js +5 -2
- package/dist/util/loader.js.map +2 -2
- package/dist/util/num.d.ts +13 -0
- package/dist/util/num.d.ts.map +1 -0
- package/dist/util/os.d.ts +6 -0
- package/dist/util/os.d.ts.map +1 -0
- package/dist/util/str.d.ts +39 -0
- package/dist/util/str.d.ts.map +1 -0
- package/dist/util/time.d.ts +19 -0
- package/dist/util/time.d.ts.map +1 -0
- package/dist/util/time.interface.d.ts +12 -0
- package/dist/util/time.interface.d.ts.map +1 -0
- package/dist/util/timing.d.ts +36 -0
- package/dist/util/timing.d.ts.map +1 -0
- package/dist/util/timing.interface.d.ts +47 -0
- package/dist/util/timing.interface.d.ts.map +1 -0
- package/dist/util/url.d.ts +7 -0
- package/dist/util/url.d.ts.map +1 -0
- package/dist/webserver/controller/auth-middleware.d.ts +21 -0
- package/dist/webserver/controller/auth-middleware.d.ts.map +1 -0
- package/dist/webserver/controller/base.d.ts +41 -0
- package/dist/webserver/controller/base.d.ts.map +1 -0
- package/dist/webserver/controller/base.interface.d.ts +50 -0
- package/dist/webserver/controller/base.interface.d.ts.map +1 -0
- package/dist/webserver/controller/base.js +4 -4
- package/dist/webserver/controller/base.js.map +2 -2
- package/dist/webserver/controller/entity.d.ts +94 -0
- package/dist/webserver/controller/entity.d.ts.map +1 -0
- package/dist/webserver/controller/entity.js.map +2 -2
- package/dist/webserver/controller/example-auth.d.ts +12 -0
- package/dist/webserver/controller/example-auth.d.ts.map +1 -0
- package/dist/webserver/controller/health.d.ts +13 -0
- package/dist/webserver/controller/health.d.ts.map +1 -0
- package/dist/webserver/controller/health.js +0 -14
- package/dist/webserver/controller/health.js.map +2 -2
- package/dist/webserver/define-action.d.ts +26 -0
- package/dist/webserver/define-action.d.ts.map +1 -0
- package/dist/webserver/define-action.js +16 -0
- package/dist/webserver/define-action.js.map +7 -0
- package/dist/webserver/define-route.d.ts +53 -0
- package/dist/webserver/define-route.d.ts.map +1 -0
- package/dist/webserver/define-route.js +11 -6
- package/dist/webserver/define-route.js.map +2 -2
- package/dist/webserver/index.d.ts +14 -0
- package/dist/webserver/index.d.ts.map +1 -0
- package/dist/webserver/index.js +2 -0
- package/dist/webserver/index.js.map +2 -2
- package/dist/webserver/util.d.ts +10 -0
- package/dist/webserver/util.d.ts.map +1 -0
- package/dist/webserver/util.js +5 -2
- package/dist/webserver/util.js.map +2 -2
- package/dist/webserver/webserver.d.ts +93 -0
- package/dist/webserver/webserver.d.ts.map +1 -0
- package/dist/webserver/webserver.interface.d.ts +181 -0
- package/dist/webserver/webserver.interface.d.ts.map +1 -0
- package/dist/webserver/webserver.interface.js.map +1 -1
- package/dist/webserver/webserver.js +30 -33
- package/dist/webserver/webserver.js.map +2 -2
- package/dist/websocket/controller/client/base.d.ts +12 -0
- package/dist/websocket/controller/client/base.d.ts.map +1 -0
- package/dist/websocket/controller/client/base.interface.d.ts +12 -0
- package/dist/websocket/controller/client/base.interface.d.ts.map +1 -0
- package/dist/websocket/controller/server/base.d.ts +13 -0
- package/dist/websocket/controller/server/base.d.ts.map +1 -0
- package/dist/websocket/controller/server/base.interface.d.ts +13 -0
- package/dist/websocket/controller/server/base.interface.d.ts.map +1 -0
- package/dist/websocket/controllers/client/system.d.ts +6 -0
- package/dist/websocket/controllers/client/system.d.ts.map +1 -0
- package/dist/websocket/controllers/server/system.d.ts +7 -0
- package/dist/websocket/controllers/server/system.d.ts.map +1 -0
- package/dist/websocket/index.d.ts +9 -0
- package/dist/websocket/index.d.ts.map +1 -0
- package/dist/websocket/index.js +2 -0
- package/dist/websocket/index.js.map +2 -2
- package/dist/websocket/routes/client/system.d.ts +3 -0
- package/dist/websocket/routes/client/system.d.ts.map +1 -0
- package/dist/websocket/routes/server/system.d.ts +3 -0
- package/dist/websocket/routes/server/system.d.ts.map +1 -0
- package/dist/websocket/utils.d.ts +9 -0
- package/dist/websocket/utils.d.ts.map +1 -0
- package/dist/websocket/websocket-auth.d.ts +17 -0
- package/dist/websocket/websocket-auth.d.ts.map +1 -0
- package/dist/websocket/websocket-auth.js +46 -0
- package/dist/websocket/websocket-auth.js.map +7 -0
- package/dist/websocket/websocket-base.d.ts +19 -0
- package/dist/websocket/websocket-base.d.ts.map +1 -0
- package/dist/websocket/websocket-client-manager.d.ts +53 -0
- package/dist/websocket/websocket-client-manager.d.ts.map +1 -0
- package/dist/websocket/websocket-client-manager.interface.d.ts +8 -0
- package/dist/websocket/websocket-client-manager.interface.d.ts.map +1 -0
- package/dist/websocket/websocket-client-manager.js +6 -5
- package/dist/websocket/websocket-client-manager.js.map +2 -2
- package/dist/websocket/websocket-client.d.ts +64 -0
- package/dist/websocket/websocket-client.d.ts.map +1 -0
- package/dist/websocket/websocket-client.interface.d.ts +14 -0
- package/dist/websocket/websocket-client.interface.d.ts.map +1 -0
- package/dist/websocket/websocket-client.js +97 -3
- package/dist/websocket/websocket-client.js.map +2 -2
- package/dist/websocket/websocket-room-manager.d.ts +32 -0
- package/dist/websocket/websocket-room-manager.d.ts.map +1 -0
- package/dist/websocket/websocket-server.d.ts +102 -0
- package/dist/websocket/websocket-server.d.ts.map +1 -0
- package/dist/websocket/websocket-server.interface.d.ts +16 -0
- package/dist/websocket/websocket-server.interface.d.ts.map +1 -0
- package/dist/websocket/websocket-server.js +62 -50
- package/dist/websocket/websocket-server.js.map +2 -2
- package/dist/websocket/websocket-service.d.ts +44 -0
- package/dist/websocket/websocket-service.d.ts.map +1 -0
- package/dist/websocket/websocket.interface.d.ts +137 -0
- package/dist/websocket/websocket.interface.d.ts.map +1 -0
- package/dist/websocket/websocket.interface.js.map +2 -2
- package/package.json +21 -24
- package/pxl.js +0 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/webserver/controller/entity.ts"],
|
|
4
|
-
"sourcesContent": ["import 'reflect-metadata';\nimport path from 'path';\nimport type { EntityManager, FilterQuery, Populate } from '@mikro-orm/core';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport { StatusCodes } from 'http-status-codes';\nimport BaseController from './base.js';\nimport type { DynamicEntity } from '../../database/dynamic-entity.js';\nimport { generateFormFields } from '../../database/dynamic-entity-form-decorators.js';\nimport { Helper } from '../../util/index.js';\nimport type { WebServerBaseControllerConstructorParams } from './base.interface.js';\n\nexport default abstract class EntityController extends BaseController {\n protected abstract entityName: string;\n\n protected entityManager: EntityManager;\n\n // Cache for entity modules to avoid repeated dynamic imports\n private static entityCache = new Map<string, typeof DynamicEntity>();\n\n constructor(props: WebServerBaseControllerConstructorParams) {\n super(props);\n\n const { databaseInstance } = props;\n\n this.entityManager = databaseInstance.getEntityManager();\n }\n\n protected getEntity = async (): Promise<typeof DynamicEntity | undefined> => {\n if (!this.applicationConfig.database || this.applicationConfig.database.enabled !== true) {\n throw new Error(`Database not enabled (Entity: ${this.entityName})`);\n }\n\n // Check cache first\n const cacheKey = `${this.applicationConfig.database.entitiesDirectory}:${this.entityName}`;\n if (EntityController.entityCache.has(cacheKey)) {\n return EntityController.entityCache.get(cacheKey);\n }\n\n // Define entity module path\n const entityModulePath = path.join(\n this.applicationConfig.database.entitiesDirectory,\n `${this.entityName}.${Helper.getScriptFileExtension()}`,\n );\n\n // Import entity module\n const entityModule = await import(entityModulePath);\n\n if (!entityModule?.[this.entityName]) {\n throw new Error(`Entity not found (Entity: ${this.entityName})`);\n }\n\n // Get entity class\n const EntityClass = entityModule[this.entityName];\n\n // Cache the entity for future use\n EntityController.entityCache.set(cacheKey, EntityClass);\n\n return EntityClass;\n };\n\n private getEntityProperties(entityClass: any): string[] {\n const properties: string[] = [];\n\n const reservedPropertyKeys = ['constructor', 'toJSON'];\n\n for (const propertyKey of Object.getOwnPropertyNames(entityClass.prototype)) {\n if (propertyKey.startsWith('__')) {\n continue;\n } else if (reservedPropertyKeys.includes(propertyKey)) {\n continue;\n }\n\n properties.push(propertyKey);\n }\n\n return properties;\n }\n\n public options = async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n const formFields = generateFormFields({ model: EntityClass });\n\n this.sendSuccessResponse({\n reply,\n data: {\n formFields,\n },\n });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n public metadata = async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n const formFields = generateFormFields({ model: EntityClass });\n\n this.sendSuccessResponse({\n reply,\n data: {\n formFields,\n },\n });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n // Pre-getMany hook (can be overridden in the child controller)\n protected async preGetMany(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n // Post-getMany hook (can be overridden in the child controller)\n // await this.postGetMany({ entityManager: this.entityManager, request, reply, data });\n protected async postGetMany(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n data: {\n items: any[];\n total: number;\n page: number;\n totalPages: number;\n limit: number;\n };\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n public getMany = async (\n request: FastifyRequest<{\n Querystring: {\n page: string;\n limit: string;\n filters: string;\n sort: string;\n 'sort-order': string;\n search: string;\n [key: string]: any;\n };\n }>,\n reply: FastifyReply,\n ) => {\n try {\n // Call preGetMany hook\n await this.preGetMany({\n entityManager: this.entityManager,\n request,\n reply,\n });\n\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n // Pagination parameters\n const page = parseInt(request.query.page) || 1;\n const limit = parseInt(request.query.limit);\n const offset = (page - 1) * (limit > 0 ? limit : 0);\n\n // Filtering and sorting\n const filters = request.query.filters ? JSON.parse(request.query.filters) : {};\n const sortOrder = request.query['sort-order'] || 'ASC';\n const orderBy = request.query.sort ? { [request.query.sort]: sortOrder } : { id: sortOrder };\n\n const normalizedQuery: { [key: string]: any } = {};\n\n for (const key in request.query) {\n // Skip prototype pollution attempts\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n\n // Only process own properties\n if (!Object.prototype.hasOwnProperty.call(request.query, key)) {\n continue;\n }\n\n if (key.endsWith('[]')) {\n const normalizedKey = key.slice(0, -2);\n\n // Safe property assignment\n if (normalizedKey !== '__proto__' && normalizedKey !== 'constructor' && normalizedKey !== 'prototype') {\n Reflect.set(normalizedQuery, normalizedKey, Reflect.get(request.query, key));\n }\n } else {\n Reflect.set(normalizedQuery, key, Reflect.get(request.query, key));\n }\n }\n\n // Build query options\n const options: {\n limit?: number;\n offset?: number;\n filters: FilterQuery<any>;\n orderBy: { [key: string]: string };\n } = {\n filters,\n offset,\n orderBy,\n };\n\n if (limit > 0) {\n options.limit = limit;\n }\n\n const entityProperties = this.getEntityProperties(EntityClass);\n const reservedQueryKeys = ['page', 'limit', 'filters', 'sort', 'populate', 'search'];\n const searchQuery = request.query.search || '';\n\n for (const key in normalizedQuery) {\n // Skip prototype pollution attempts\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n\n // Only process own properties\n if (!Object.prototype.hasOwnProperty.call(normalizedQuery, key)) {\n continue;\n }\n\n if (reservedQueryKeys.includes(key)) {\n continue;\n }\n\n if (!entityProperties.includes(key)) {\n const [relation, subProperty] = key.split('.');\n\n if (relation && subProperty) {\n // Validate relation and subProperty names\n if (\n relation === '__proto__' ||\n relation === 'constructor' ||\n relation === 'prototype' ||\n subProperty === '__proto__' ||\n subProperty === 'constructor' ||\n subProperty === 'prototype'\n ) {\n continue;\n }\n\n let queryValue = Reflect.get(normalizedQuery, key);\n\n if (!queryValue) continue;\n\n if (typeof queryValue === 'string' && queryValue.includes(',')) {\n queryValue = queryValue.split(',');\n }\n\n if (Array.isArray(queryValue)) {\n Reflect.set(options.filters, relation, {\n [subProperty]: { $in: queryValue },\n });\n } else {\n Reflect.set(options.filters, relation, {\n [subProperty]: queryValue,\n });\n }\n }\n\n continue;\n }\n\n let queryValue = Reflect.get(normalizedQuery, key);\n\n if (!queryValue) {\n continue;\n }\n\n if (typeof queryValue === 'string' && queryValue.includes(',')) {\n queryValue = queryValue.split(',');\n }\n\n if (Array.isArray(queryValue)) {\n Reflect.set(options.filters, key, { $in: queryValue });\n } else {\n Reflect.set(options.filters, key, queryValue);\n }\n }\n\n // Add search filter if a search query is provided\n if (searchQuery) {\n const searchFields = EntityClass.getSearchFields();\n\n options.filters.$or = searchFields\n .filter(field => {\n const isIntegerField = ['id', 'originId'].includes(field);\n\n return !isIntegerField;\n })\n .map(field => {\n return {\n [field]: { $like: `%${searchQuery}%` },\n };\n });\n }\n\n const populate = request.query.populate ? request.query.populate.split(',') : [];\n\n // Fetch items from the database\n const [items, total] = await this.entityManager.findAndCount(this.entityName, options.filters, {\n limit: options.limit,\n offset: options.offset,\n orderBy: options.orderBy,\n populate,\n });\n\n const totalPages = limit > 0 ? Math.ceil(total / limit) : 1;\n\n const data = {\n items,\n total,\n page,\n totalPages,\n limit: limit > 0 ? limit : total,\n };\n\n // Call postGetMany hook\n await this.postGetMany({\n entityManager: this.entityManager,\n request,\n reply,\n data,\n });\n\n reply.send({\n data: data.items,\n total_items: data.total,\n page: data.page,\n total_pages: data.totalPages,\n limit: data.limit,\n });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n protected async preGetOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n protected async postGetOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n item: any;\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n public getOne = async (\n request: FastifyRequest<{\n Params: { id: number };\n Querystring: { populate: string };\n }>,\n reply: FastifyReply,\n ) => {\n try {\n await this.preGetOne({\n entityManager: this.entityManager,\n request,\n reply,\n });\n\n const queryPopulate = request.query.populate || null;\n const populateList: string[] = queryPopulate ? queryPopulate.split(',') : [];\n\n // Ensure populate is typed correctly for MikroORM\n const populate = populateList.map(field => `${field}.*`) as unknown as Populate<\n object,\n `${string}.*` | `${string}.$infer`\n >;\n\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n return;\n }\n\n const id = request.params.id;\n\n const item = await this.entityManager.findOne(this.entityName, { id }, { populate });\n\n if (!item) {\n return this.sendNotFoundResponse(reply, `${EntityClass.singularNameCapitalized} not found`);\n }\n\n await this.postGetOne({\n entityManager: this.entityManager,\n request,\n reply,\n item,\n });\n\n this.sendSuccessResponse({ reply, data: item });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n protected preCreateOne = ({\n request,\n reply,\n }: {\n request: FastifyRequest;\n reply: FastifyReply;\n }): { request: FastifyRequest; reply: FastifyReply } => {\n return { request, reply };\n };\n\n protected async postCreateOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n item: any;\n }): Promise<void> {}\n\n public createOne = async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n return;\n }\n\n // Listen for preCreateOne hook\n if (this.preCreateOne) {\n const { request: preCreateOneRequest } = await this.preCreateOne({\n request,\n reply,\n });\n if (preCreateOneRequest) {\n request = preCreateOneRequest;\n }\n }\n\n const { error, value } = EntityClass.validate(request.body, true);\n\n if (error) {\n return this.sendErrorResponse({ reply, error: error.message });\n }\n\n const item = this.entityManager.create(this.entityName, value);\n\n await this.entityManager.persistAndFlush(item);\n\n // Call postCreateOne hook\n await this.postCreateOne({\n entityManager: this.entityManager,\n request,\n reply,\n item,\n });\n\n this.sendSuccessResponse({ reply, data: item, statusCode: StatusCodes.CREATED });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n protected async postUpdateOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n item: any;\n }): Promise<void> {}\n\n public updateOne = async (request: FastifyRequest<{ Params: { id: number } }>, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n return;\n }\n\n const id = request.params.id;\n\n const { error, value } = EntityClass.validate(request.body, false);\n\n if (error) {\n return this.sendErrorResponse({ reply, error: error.message });\n }\n\n const item = await this.entityManager.findOne(this.entityName, { id });\n\n if (!item) {\n return this.sendNotFoundResponse(reply, `${EntityClass.singularNameCapitalized} not found`);\n }\n\n this.entityManager.assign(item, value);\n\n await this.entityManager.persistAndFlush(item);\n\n // Call postUpdateOne hook\n await this.postUpdateOne({\n entityManager: this.entityManager,\n request,\n reply,\n item,\n });\n\n this.sendSuccessResponse({ reply, data: item });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n public deleteOne = async (request: FastifyRequest<{ Params: { id: number } }>, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n const id = request.params.id;\n\n const item = await this.entityManager.findOne(this.entityName, { id });\n\n if (!item) {\n return this.sendNotFoundResponse(reply, `${EntityClass.singularNameCapitalized} not found`);\n }\n\n await this.entityManager.removeAndFlush(item);\n\n reply.status(StatusCodes.NO_CONTENT).send();\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import 'reflect-metadata';\nimport path from 'path';\nimport type { EntityManager, FilterQuery, Populate } from '@mikro-orm/core';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport { StatusCodes } from 'http-status-codes';\nimport BaseController from './base.js';\nimport type { DynamicEntity } from '../../database/dynamic-entity.js';\nimport { generateFormFields } from '../../database/dynamic-entity-form-decorators.js';\nimport { Helper } from '../../util/index.js';\nimport type { WebServerBaseControllerConstructorParams } from './base.interface.js';\n\nexport default abstract class EntityController extends BaseController {\n protected abstract entityName: string;\n\n protected entityManager: EntityManager;\n\n // Cache for entity modules to avoid repeated dynamic imports\n private static entityCache = new Map<string, typeof DynamicEntity>();\n\n constructor(props: WebServerBaseControllerConstructorParams) {\n super(props);\n\n const { databaseInstance } = props;\n\n this.entityManager = databaseInstance.getEntityManager();\n }\n\n protected getEntity = async (): Promise<typeof DynamicEntity | undefined> => {\n if (!this.applicationConfig.database || this.applicationConfig.database.enabled !== true) {\n throw new Error(`Database not enabled (Entity: ${this.entityName})`);\n }\n\n // Check cache first\n const cacheKey = `${this.applicationConfig.database.entitiesDirectory}:${this.entityName}`;\n if (EntityController.entityCache.has(cacheKey)) {\n return EntityController.entityCache.get(cacheKey);\n }\n\n // Define entity module path\n const entityModulePath = path.join(\n this.applicationConfig.database.entitiesDirectory,\n `${this.entityName}.${Helper.getScriptFileExtension()}`,\n );\n\n // Import entity module\n const entityModule = await import(entityModulePath);\n\n if (!entityModule?.[this.entityName]) {\n throw new Error(`Entity not found (Entity: ${this.entityName})`);\n }\n\n // Get entity class\n const EntityClass = entityModule[this.entityName];\n\n // Cache the entity for future use\n EntityController.entityCache.set(cacheKey, EntityClass);\n\n return EntityClass;\n };\n\n private getEntityProperties(entityClass: any): string[] {\n const properties: string[] = [];\n\n const reservedPropertyKeys = ['constructor', 'toJSON'];\n\n for (const propertyKey of Object.getOwnPropertyNames(entityClass.prototype)) {\n if (propertyKey.startsWith('__')) {\n continue;\n } else if (reservedPropertyKeys.includes(propertyKey)) {\n continue;\n }\n\n properties.push(propertyKey);\n }\n\n return properties;\n }\n\n public options = async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n const formFields = generateFormFields({ model: EntityClass });\n\n this.sendSuccessResponse({\n reply,\n data: {\n formFields,\n },\n });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n public metadata = async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n const formFields = generateFormFields({ model: EntityClass });\n\n this.sendSuccessResponse({\n reply,\n data: {\n formFields,\n },\n });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n // Pre-getMany hook (can be overridden in the child controller)\n protected async preGetMany(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n // Post-getMany hook (can be overridden in the child controller)\n // await this.postGetMany({ entityManager: this.entityManager, request, reply, data });\n protected async postGetMany(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n data: {\n items: any[];\n total: number;\n page: number;\n totalPages: number;\n limit: number;\n };\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n public getMany = async (\n request: FastifyRequest<{\n Querystring: {\n page: string;\n limit: string;\n filters: string;\n sort: string;\n 'sort-order': string;\n search: string;\n [key: string]: any;\n };\n }>,\n reply: FastifyReply,\n ) => {\n try {\n // Call preGetMany hook\n await this.preGetMany({\n entityManager: this.entityManager,\n request,\n reply,\n });\n\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n // Pagination parameters\n const page = parseInt(request.query.page) || 1;\n const limit = parseInt(request.query.limit);\n const offset = (page - 1) * (limit > 0 ? limit : 0);\n\n // Filtering and sorting\n const filters = request.query.filters ? JSON.parse(request.query.filters) : {};\n const sortOrder = request.query['sort-order'] || 'ASC';\n const orderBy = request.query.sort ? { [request.query.sort]: sortOrder } : { id: sortOrder };\n\n const normalizedQuery: { [key: string]: any } = {};\n\n for (const key in request.query) {\n // Skip prototype pollution attempts\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n\n // Only process own properties\n if (!Object.prototype.hasOwnProperty.call(request.query, key)) {\n continue;\n }\n\n if (key.endsWith('[]')) {\n const normalizedKey = key.slice(0, -2);\n\n // Safe property assignment\n if (normalizedKey !== '__proto__' && normalizedKey !== 'constructor' && normalizedKey !== 'prototype') {\n Reflect.set(normalizedQuery, normalizedKey, Reflect.get(request.query, key));\n }\n } else {\n Reflect.set(normalizedQuery, key, Reflect.get(request.query, key));\n }\n }\n\n // Build query options\n const options: {\n limit?: number;\n offset?: number;\n filters: FilterQuery<any>;\n orderBy: { [key: string]: string };\n } = {\n filters,\n offset,\n orderBy,\n };\n\n if (limit > 0) {\n options.limit = limit;\n }\n\n const entityProperties = this.getEntityProperties(EntityClass);\n const reservedQueryKeys = ['page', 'limit', 'filters', 'sort', 'populate', 'search'];\n const searchQuery = request.query.search || '';\n\n for (const key in normalizedQuery) {\n // Skip prototype pollution attempts\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n\n // Only process own properties\n if (!Object.prototype.hasOwnProperty.call(normalizedQuery, key)) {\n continue;\n }\n\n if (reservedQueryKeys.includes(key)) {\n continue;\n }\n\n if (!entityProperties.includes(key)) {\n const [relation, subProperty] = key.split('.');\n\n if (relation && subProperty) {\n // Validate relation and subProperty names\n if (\n relation === '__proto__' ||\n relation === 'constructor' ||\n relation === 'prototype' ||\n subProperty === '__proto__' ||\n subProperty === 'constructor' ||\n subProperty === 'prototype'\n ) {\n continue;\n }\n\n let queryValue = Reflect.get(normalizedQuery, key);\n\n if (!queryValue) continue;\n\n if (typeof queryValue === 'string' && queryValue.includes(',')) {\n queryValue = queryValue.split(',');\n }\n\n if (Array.isArray(queryValue)) {\n Reflect.set(options.filters, relation, {\n [subProperty]: { $in: queryValue },\n });\n } else {\n Reflect.set(options.filters, relation, {\n [subProperty]: queryValue,\n });\n }\n }\n\n continue;\n }\n\n let queryValue = Reflect.get(normalizedQuery, key);\n\n if (!queryValue) {\n continue;\n }\n\n if (typeof queryValue === 'string' && queryValue.includes(',')) {\n queryValue = queryValue.split(',');\n }\n\n if (Array.isArray(queryValue)) {\n Reflect.set(options.filters, key, { $in: queryValue });\n } else {\n Reflect.set(options.filters, key, queryValue);\n }\n }\n\n // Add search filter if a search query is provided\n if (searchQuery) {\n const searchFields = EntityClass.getSearchFields();\n\n options.filters.$or = searchFields\n .filter(field => {\n const isIntegerField = ['id', 'originId'].includes(field);\n\n return !isIntegerField;\n })\n .map(field => {\n return {\n [field]: { $like: `%${searchQuery}%` },\n };\n });\n }\n\n const populate = request.query.populate ? request.query.populate.split(',') : [];\n\n // Fetch items from the database\n const [items, total] = await this.entityManager.findAndCount(this.entityName, options.filters, {\n limit: options.limit,\n offset: options.offset,\n orderBy: options.orderBy,\n populate,\n });\n\n const totalPages = limit > 0 ? Math.ceil(total / limit) : 1;\n\n const data = {\n items,\n total,\n page,\n totalPages,\n limit: limit > 0 ? limit : total,\n };\n\n // Call postGetMany hook\n await this.postGetMany({\n entityManager: this.entityManager,\n request,\n reply,\n data,\n });\n\n reply.send({\n data: data.items,\n total_items: data.total,\n page: data.page,\n total_pages: data.totalPages,\n limit: data.limit,\n });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n protected async preGetOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n protected async postGetOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n item: any;\n }): Promise<void> {\n // Default implementation: do nothing\n }\n\n public getOne = async (\n request: FastifyRequest<{\n Params: { id: number };\n Querystring: { populate: string };\n }>,\n reply: FastifyReply,\n ) => {\n try {\n await this.preGetOne({\n entityManager: this.entityManager,\n request,\n reply,\n });\n\n const queryPopulate = request.query.populate || null;\n const populateList: string[] = queryPopulate ? queryPopulate.split(',') : [];\n\n // Ensure populate is typed correctly for MikroORM\n const populate = populateList.map(field => `${field}.*`) as unknown as Populate<\n object,\n `${string}.*` | `${string}.$infer`\n >;\n\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n return;\n }\n\n const id = request.params.id;\n\n const item = await this.entityManager.findOne(this.entityName, { id }, { populate });\n\n if (!item) {\n return this.sendNotFoundResponse(reply, `${EntityClass.singularNameCapitalized} not found`);\n }\n\n await this.postGetOne({\n entityManager: this.entityManager,\n request,\n reply,\n item,\n });\n\n this.sendSuccessResponse({ reply, data: item });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n protected preCreateOne = ({\n request,\n reply,\n }: {\n request: FastifyRequest;\n reply: FastifyReply;\n }): { request: FastifyRequest; reply: FastifyReply } => {\n return { request, reply };\n };\n\n protected async postCreateOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n item: any;\n }): Promise<void> {}\n\n public createOne = async (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n return;\n }\n\n // Listen for preCreateOne hook\n if (this.preCreateOne) {\n const { request: preCreateOneRequest } = await this.preCreateOne({\n request,\n reply,\n });\n if (preCreateOneRequest) {\n request = preCreateOneRequest;\n }\n }\n\n const { error, value } = EntityClass.validate(request.body, true);\n\n if (error) {\n return this.sendErrorResponse({ reply, error: error.message });\n }\n\n const item = this.entityManager.create(this.entityName, value as object);\n\n await this.entityManager.persistAndFlush(item);\n\n // Call postCreateOne hook\n await this.postCreateOne({\n entityManager: this.entityManager,\n request,\n reply,\n item,\n });\n\n this.sendSuccessResponse({ reply, data: item, statusCode: StatusCodes.CREATED });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n protected async postUpdateOne(_: {\n entityManager: EntityManager;\n request: FastifyRequest;\n reply: FastifyReply;\n item: any;\n }): Promise<void> {}\n\n public updateOne = async (request: FastifyRequest<{ Params: { id: number } }>, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n return;\n }\n\n const id = request.params.id;\n\n const { error, value } = EntityClass.validate(request.body, false);\n\n if (error) {\n return this.sendErrorResponse({ reply, error: error.message });\n }\n\n const item = await this.entityManager.findOne(this.entityName, { id });\n\n if (!item) {\n return this.sendNotFoundResponse(reply, `${EntityClass.singularNameCapitalized} not found`);\n }\n\n this.entityManager.assign(item, value as object);\n\n await this.entityManager.persistAndFlush(item);\n\n // Call postUpdateOne hook\n await this.postUpdateOne({\n entityManager: this.entityManager,\n request,\n reply,\n item,\n });\n\n this.sendSuccessResponse({ reply, data: item });\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n\n public deleteOne = async (request: FastifyRequest<{ Params: { id: number } }>, reply: FastifyReply) => {\n try {\n const EntityClass = await this.getEntity();\n\n if (!EntityClass) {\n this.sendErrorResponse({ reply, error: 'Entity not found' });\n\n return;\n }\n\n const id = request.params.id;\n\n const item = await this.entityManager.findOne(this.entityName, { id });\n\n if (!item) {\n return this.sendNotFoundResponse(reply, `${EntityClass.singularNameCapitalized} not found`);\n }\n\n await this.entityManager.removeAndFlush(item);\n\n reply.status(StatusCodes.NO_CONTENT).send();\n } catch (error) {\n this.sendErrorResponse({ reply, error });\n }\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["queryValue"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
+
import WebServerBaseController from './base.js';
|
|
3
|
+
/**
|
|
4
|
+
* Example controller demonstrating simplified authentication
|
|
5
|
+
*/
|
|
6
|
+
export default class ExampleAuthController extends WebServerBaseController {
|
|
7
|
+
getUserTickers: import("./auth-middleware.js").RouteHandler;
|
|
8
|
+
getUserOrders: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
9
|
+
getUserProfile: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
10
|
+
private withAuthentication;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=example-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-auth.d.ts","sourceRoot":"","sources":["../../../src/webserver/controller/example-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,uBAAmD,MAAM,WAAW,CAAC;AAG5E;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,uBAAuB;IAEjE,cAAc,8CAWmB;IAGjC,aAAa,GAAU,SAAS,cAAc,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAexF;IAGK,cAAc,GAAU,SAAS,cAAc,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAWzF;YAGY,kBAAkB;CAcjC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
+
import BaseController from './base.js';
|
|
3
|
+
export default class HealthController extends BaseController {
|
|
4
|
+
/**
|
|
5
|
+
* Liveness probe: process is up and not in stopping phase.
|
|
6
|
+
*/
|
|
7
|
+
live: (_: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Readiness probe: service dependencies are available & lifecycle is RUNNING with aggregated readiness.
|
|
10
|
+
*/
|
|
11
|
+
ready: (_: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../src/webserver/controller/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,cAAc,MAAM,WAAW,CAAC;AAGvC,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,cAAc;IAC1D;;OAEG;IACI,IAAI,GAAU,GAAG,cAAc,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAQzE;IAEF;;OAEG;IACI,KAAK,GAAU,GAAG,cAAc,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CA6B1E;CACH"}
|
|
@@ -43,20 +43,6 @@ class HealthController extends BaseController {
|
|
|
43
43
|
}
|
|
44
44
|
reply.send({ ready: true, phase, probes, aggregatedReadiness: true });
|
|
45
45
|
}, "ready");
|
|
46
|
-
async checkDatabaseConnection() {
|
|
47
|
-
try {
|
|
48
|
-
return await this.databaseInstance.isConnected();
|
|
49
|
-
} catch {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async checkRedisConnection() {
|
|
54
|
-
try {
|
|
55
|
-
return await this.redisInstance.isConnected();
|
|
56
|
-
} catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
46
|
}
|
|
61
47
|
export {
|
|
62
48
|
HealthController as default
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/webserver/controller/health.ts"],
|
|
4
|
-
"sourcesContent": ["import type { FastifyReply, FastifyRequest } from 'fastify';\nimport BaseController from './base.js';\nimport { LifecyclePhase } from '../../lifecycle/types.js';\n\nexport default class HealthController extends BaseController {\n /**\n * Liveness probe: process is up and not in stopping phase.\n */\n public live = async (_: FastifyRequest, reply: FastifyReply): Promise<void> => {\n const phase = this.lifecycleManager.phase;\n const shuttingDown = phase === LifecyclePhase.STOPPING || phase === LifecyclePhase.STOPPED;\n if (shuttingDown) {\n reply.code(503).send({ live: false, phase });\n return;\n }\n reply.send({ live: true, phase });\n };\n\n /**\n * Readiness probe: service dependencies are available & lifecycle is RUNNING with aggregated readiness.\n */\n public ready = async (_: FastifyRequest, reply: FastifyReply): Promise<void> => {\n const phase = this.lifecycleManager.phase;\n const readinessStatus = await this.lifecycleManager.getReadinessStatus();\n\n // Convert readiness check results to probe format for backward compatibility\n const probes: Record<string, { healthy: boolean; required: boolean }> = {};\n for (const check of readinessStatus.checks) {\n probes[check.name] = { healthy: check.ready, required: true };\n }\n\n const requiredFailures = Object.entries(probes)\n .filter(([, v]) => v.required && !v.healthy)\n .map(([k]) => k);\n\n const ready = readinessStatus.ready;\n\n if (!ready) {\n reply.code(503).send({\n ready: false,\n phase,\n probes,\n notReady: phase !== LifecyclePhase.RUNNING ? 'lifecycle-phase' : 'readiness-checks-failed',\n failed: requiredFailures,\n aggregatedReadiness: true,\n });\n return;\n }\n\n reply.send({ ready: true, phase, probes, aggregatedReadiness: true });\n };\n
|
|
5
|
-
"mappings": ";;AACA,OAAO,oBAAoB;AAC3B,SAAS,sBAAsB;AAE/B,MAAO,yBAAuC,eAAe;AAAA,EAJ7D,OAI6D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAIpD,OAAO,8BAAO,GAAmB,UAAuC;AAC7E,UAAM,QAAQ,KAAK,iBAAiB;AACpC,UAAM,eAAe,UAAU,eAAe,YAAY,UAAU,eAAe;AACnF,QAAI,cAAc;AAChB,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,OAAO,MAAM,CAAC;AAC3C;AAAA,IACF;AACA,UAAM,KAAK,EAAE,MAAM,MAAM,MAAM,CAAC;AAAA,EAClC,GARc;AAAA;AAAA;AAAA;AAAA,EAaP,QAAQ,8BAAO,GAAmB,UAAuC;AAC9E,UAAM,QAAQ,KAAK,iBAAiB;AACpC,UAAM,kBAAkB,MAAM,KAAK,iBAAiB,mBAAmB;AAGvE,UAAM,SAAkE,CAAC;AACzE,eAAW,SAAS,gBAAgB,QAAQ;AAC1C,aAAO,MAAM,IAAI,IAAI,EAAE,SAAS,MAAM,OAAO,UAAU,KAAK;AAAA,IAC9D;AAEA,UAAM,mBAAmB,OAAO,QAAQ,MAAM,EAC3C,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,EAC1C,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AAEjB,UAAM,QAAQ,gBAAgB;AAE9B,QAAI,CAAC,OAAO;AACV,YAAM,KAAK,GAAG,EAAE,KAAK;AAAA,QACnB,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,UAAU,UAAU,eAAe,UAAU,oBAAoB;AAAA,QACjE,QAAQ;AAAA,QACR,qBAAqB;AAAA,MACvB,CAAC;AACD;AAAA,IACF;AAEA,UAAM,KAAK,EAAE,OAAO,MAAM,OAAO,QAAQ,qBAAqB,KAAK,CAAC;AAAA,EACtE,GA7Be;
|
|
4
|
+
"sourcesContent": ["import type { FastifyReply, FastifyRequest } from 'fastify';\nimport BaseController from './base.js';\nimport { LifecyclePhase } from '../../lifecycle/types.js';\n\nexport default class HealthController extends BaseController {\n /**\n * Liveness probe: process is up and not in stopping phase.\n */\n public live = async (_: FastifyRequest, reply: FastifyReply): Promise<void> => {\n const phase = this.lifecycleManager.phase;\n const shuttingDown = phase === LifecyclePhase.STOPPING || phase === LifecyclePhase.STOPPED;\n if (shuttingDown) {\n reply.code(503).send({ live: false, phase });\n return;\n }\n reply.send({ live: true, phase });\n };\n\n /**\n * Readiness probe: service dependencies are available & lifecycle is RUNNING with aggregated readiness.\n */\n public ready = async (_: FastifyRequest, reply: FastifyReply): Promise<void> => {\n const phase = this.lifecycleManager.phase;\n const readinessStatus = await this.lifecycleManager.getReadinessStatus();\n\n // Convert readiness check results to probe format for backward compatibility\n const probes: Record<string, { healthy: boolean; required: boolean }> = {};\n for (const check of readinessStatus.checks) {\n probes[check.name] = { healthy: check.ready, required: true };\n }\n\n const requiredFailures = Object.entries(probes)\n .filter(([, v]) => v.required && !v.healthy)\n .map(([k]) => k);\n\n const ready = readinessStatus.ready;\n\n if (!ready) {\n reply.code(503).send({\n ready: false,\n phase,\n probes,\n notReady: phase !== LifecyclePhase.RUNNING ? 'lifecycle-phase' : 'readiness-checks-failed',\n failed: requiredFailures,\n aggregatedReadiness: true,\n });\n return;\n }\n\n reply.send({ ready: true, phase, probes, aggregatedReadiness: true });\n };\n}\n"],
|
|
5
|
+
"mappings": ";;AACA,OAAO,oBAAoB;AAC3B,SAAS,sBAAsB;AAE/B,MAAO,yBAAuC,eAAe;AAAA,EAJ7D,OAI6D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAIpD,OAAO,8BAAO,GAAmB,UAAuC;AAC7E,UAAM,QAAQ,KAAK,iBAAiB;AACpC,UAAM,eAAe,UAAU,eAAe,YAAY,UAAU,eAAe;AACnF,QAAI,cAAc;AAChB,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,OAAO,MAAM,CAAC;AAC3C;AAAA,IACF;AACA,UAAM,KAAK,EAAE,MAAM,MAAM,MAAM,CAAC;AAAA,EAClC,GARc;AAAA;AAAA;AAAA;AAAA,EAaP,QAAQ,8BAAO,GAAmB,UAAuC;AAC9E,UAAM,QAAQ,KAAK,iBAAiB;AACpC,UAAM,kBAAkB,MAAM,KAAK,iBAAiB,mBAAmB;AAGvE,UAAM,SAAkE,CAAC;AACzE,eAAW,SAAS,gBAAgB,QAAQ;AAC1C,aAAO,MAAM,IAAI,IAAI,EAAE,SAAS,MAAM,OAAO,UAAU,KAAK;AAAA,IAC9D;AAEA,UAAM,mBAAmB,OAAO,QAAQ,MAAM,EAC3C,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,EAC1C,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AAEjB,UAAM,QAAQ,gBAAgB;AAE9B,QAAI,CAAC,OAAO;AACV,YAAM,KAAK,GAAG,EAAE,KAAK;AAAA,QACnB,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,UAAU,UAAU,eAAe,UAAU,oBAAoB;AAAA,QACjE,QAAQ;AAAA,QACR,qBAAqB;AAAA,MACvB,CAAC;AACD;AAAA,IACF;AAEA,UAAM,KAAK,EAAE,OAAO,MAAM,OAAO,QAAQ,qBAAqB,KAAK,CAAC;AAAA,EACtE,GA7Be;AA8BjB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RouteSchemaDefinition } from './webserver.interface.js';
|
|
2
|
+
import type { ControllerAction } from './controller/base.interface.js';
|
|
3
|
+
/**
|
|
4
|
+
* Define a typed controller action with schema inference.
|
|
5
|
+
* This helper provides TypeScript type inference for controller methods based on Zod schemas.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const helloSchema = {
|
|
9
|
+
* body: z.object({ name: z.string() }),
|
|
10
|
+
* response: { 200: z.object({ message: z.string() }) }
|
|
11
|
+
* } satisfies RouteSchemaDefinition;
|
|
12
|
+
*
|
|
13
|
+
* class MyController extends WebServerBaseController {
|
|
14
|
+
* hello = defineAction(helloSchema, async (request, reply) => {
|
|
15
|
+
* // request.body is typed as { name: string }
|
|
16
|
+
* return reply.send({ message: `Hello ${request.body.name}` });
|
|
17
|
+
* });
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
export declare function defineAction<Schema extends RouteSchemaDefinition<any, any, any, any, any>>(schema: Schema, handler: ControllerAction<Schema>): ControllerAction<Schema>;
|
|
21
|
+
/**
|
|
22
|
+
* Define a controller action without a schema.
|
|
23
|
+
* Useful for actions that don't need validation or type inference.
|
|
24
|
+
*/
|
|
25
|
+
export declare function defineAction<Schema extends undefined = undefined>(handler: ControllerAction<Schema>): ControllerAction<Schema>;
|
|
26
|
+
//# sourceMappingURL=define-action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-action.d.ts","sourceRoot":"","sources":["../../src/webserver/define-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEvE;;;;;;;;;;;;;;;;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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
function defineAction(schemaOrHandler, handler) {
|
|
4
|
+
if (typeof schemaOrHandler === "function") {
|
|
5
|
+
return schemaOrHandler;
|
|
6
|
+
}
|
|
7
|
+
if (!handler) {
|
|
8
|
+
throw new Error("Handler is required when schema is provided");
|
|
9
|
+
}
|
|
10
|
+
return handler;
|
|
11
|
+
}
|
|
12
|
+
__name(defineAction, "defineAction");
|
|
13
|
+
export {
|
|
14
|
+
defineAction
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=define-action.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/webserver/define-action.ts"],
|
|
4
|
+
"sourcesContent": ["import type { RouteSchemaDefinition } from './webserver.interface.js';\nimport type { ControllerAction } from './controller/base.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
|
+
"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
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { HTTPMethods } from 'fastify';
|
|
2
|
+
import { type RouteSchemaDefinition, type WebServerRoute } from './webserver.interface.js';
|
|
3
|
+
import type { ControllerAction, WebServerBaseControllerType } from './controller/base.interface.js';
|
|
4
|
+
export interface DefineRouteConfig<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined, Handler extends ControllerAction<Schema>> {
|
|
5
|
+
method: HTTPMethods | HTTPMethods[];
|
|
6
|
+
path: string;
|
|
7
|
+
schema?: Schema;
|
|
8
|
+
handler: Handler;
|
|
9
|
+
}
|
|
10
|
+
export interface DefineRouteWithControllerConfig<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined = undefined> {
|
|
11
|
+
method: HTTPMethods | HTTPMethods[];
|
|
12
|
+
path: string;
|
|
13
|
+
schema?: Schema;
|
|
14
|
+
controller: WebServerBaseControllerType;
|
|
15
|
+
action: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Define a route with an inline handler function.
|
|
19
|
+
* Provides full type inference for request parameters based on the schema.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const helloSchema = {
|
|
23
|
+
* body: z.object({ name: z.string() }),
|
|
24
|
+
* response: { 200: z.object({ message: z.string() }) }
|
|
25
|
+
* } satisfies RouteSchemaDefinition;
|
|
26
|
+
*
|
|
27
|
+
* defineRoute({
|
|
28
|
+
* method: 'POST',
|
|
29
|
+
* path: '/hello',
|
|
30
|
+
* schema: helloSchema,
|
|
31
|
+
* handler: async (request, reply) => {
|
|
32
|
+
* // request.body is typed as { name: string }
|
|
33
|
+
* return reply.send({ message: `Hello ${request.body.name}` });
|
|
34
|
+
* }
|
|
35
|
+
* });
|
|
36
|
+
*/
|
|
37
|
+
export declare function defineRoute<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined, Handler extends ControllerAction<Schema>>(config: DefineRouteConfig<Schema, Handler>): WebServerRoute;
|
|
38
|
+
/**
|
|
39
|
+
* Define a route with a controller and action method.
|
|
40
|
+
* Note: Type inference for controller actions is limited. Consider using inline handlers for full type safety.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* defineRoute({
|
|
44
|
+
* method: 'POST',
|
|
45
|
+
* path: '/hello',
|
|
46
|
+
* controller: HelloController,
|
|
47
|
+
* action: 'create',
|
|
48
|
+
* schema: helloSchema
|
|
49
|
+
* });
|
|
50
|
+
*/
|
|
51
|
+
export declare function defineRoute<Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined = undefined>(config: DefineRouteWithControllerConfig<Schema>): WebServerRoute;
|
|
52
|
+
export type DefineRoute = typeof defineRoute;
|
|
53
|
+
//# sourceMappingURL=define-route.d.ts.map
|
|
@@ -0,0 +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,EAEL,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EAEpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAEpG,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"}
|
|
@@ -3,15 +3,20 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
3
3
|
import {
|
|
4
4
|
WebServerRouteType
|
|
5
5
|
} from "./webserver.interface.js";
|
|
6
|
-
function defineRoute(
|
|
6
|
+
function defineRoute(config) {
|
|
7
7
|
const route = {
|
|
8
8
|
type: WebServerRouteType.Default,
|
|
9
|
-
method,
|
|
10
|
-
path
|
|
11
|
-
handler
|
|
9
|
+
method: config.method,
|
|
10
|
+
path: config.path
|
|
12
11
|
};
|
|
13
|
-
if (
|
|
14
|
-
route.
|
|
12
|
+
if ("handler" in config) {
|
|
13
|
+
route.handler = config.handler;
|
|
14
|
+
} else if ("controller" in config && "action" in config) {
|
|
15
|
+
route.controller = config.controller;
|
|
16
|
+
route.action = config.action;
|
|
17
|
+
}
|
|
18
|
+
if (config.schema) {
|
|
19
|
+
route.schema = config.schema;
|
|
15
20
|
}
|
|
16
21
|
return route;
|
|
17
22
|
}
|
|
@@ -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';\nimport type { ControllerAction } from './controller/base.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 function defineRoute<\n Schema extends RouteSchemaDefinition<any, any, any, any, any> | undefined,\n Handler extends ControllerAction<Schema>,\n>({ method
|
|
5
|
-
"mappings": ";;AACA;AAAA,EAIE;AAAA,OACK;
|
|
4
|
+
"sourcesContent": ["import type { HTTPMethods } from 'fastify';\nimport {\n type AnyRouteSchemaDefinition,\n type RouteSchemaDefinition,\n type WebServerRoute,\n WebServerRouteType,\n} from './webserver.interface.js';\nimport type { ControllerAction, WebServerBaseControllerType } from './controller/base.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": ";;AACA;AAAA,EAIE;AAAA,OACK;AAmEA,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
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { default as WebServer } from './webserver.js';
|
|
2
|
+
export type { RouteHandler as TypedRouteHandler, RouteHandlerContext, RouteSchemaDefinition, WebServerConstructorParams, WebServerOptions, WebServerRoute, } from './webserver.interface.js';
|
|
3
|
+
export { WebServerRouteType } from './webserver.interface.js';
|
|
4
|
+
export { default as WebServerBaseController } from './controller/base.js';
|
|
5
|
+
export type { ControllerAction, ControllerRequest, WebServerBaseControllerConstructorParams, } from './controller/base.interface.js';
|
|
6
|
+
export { default as WebServerHealthController } from './controller/health.js';
|
|
7
|
+
export { default as WebServerEntityController } from './controller/entity.js';
|
|
8
|
+
export { default as ExampleAuthController } from './controller/example-auth.js';
|
|
9
|
+
export { default as RouteUtil } from './util.js';
|
|
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';
|
|
13
|
+
export { defineAction } from './define-action.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webserver/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACtD,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,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,wCAAwC,GACzC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,yBAAyB,EACzB,YAAY,GACb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/webserver/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { default as default6 } from "./controller/example-auth.js";
|
|
|
7
7
|
import { default as default7 } from "./util.js";
|
|
8
8
|
import { withAuth } from "./controller/auth-middleware.js";
|
|
9
9
|
import { defineRoute } from "./define-route.js";
|
|
10
|
+
import { defineAction } from "./define-action.js";
|
|
10
11
|
export {
|
|
11
12
|
default6 as ExampleAuthController,
|
|
12
13
|
default7 as RouteUtil,
|
|
@@ -15,6 +16,7 @@ export {
|
|
|
15
16
|
default5 as WebServerEntityController,
|
|
16
17
|
default4 as WebServerHealthController,
|
|
17
18
|
WebServerRouteType,
|
|
19
|
+
defineAction,
|
|
18
20
|
defineRoute,
|
|
19
21
|
withAuth
|
|
20
22
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { default as WebServer } from './webserver.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 WebServerBaseController } from './controller/base.js';\nexport type {\n ControllerAction,\n ControllerRequest,\n WebServerBaseControllerConstructorParams,\n} from './controller/base.interface.js';\nexport { default as WebServerHealthController } from './controller/health.js';\nexport { default as WebServerEntityController } from './controller/entity.js';\nexport { default as ExampleAuthController } from './controller/example-auth.js';\nexport { default as RouteUtil } from './util.js';\nexport type {\n AuthenticatedUser,\n AuthenticatedRequest,\n AuthenticatedRouteHandler,\n RouteHandler,\n} from './controller/auth-middleware.js';\nexport { withAuth } from './controller/auth-middleware.js';\nexport { defineRoute } from './define-route.js';\n"],
|
|
5
|
-
"mappings": "AAAA,SAAoB,WAAXA,gBAA4B;AASrC,SAAS,0BAA0B;AACnC,SAAoB,WAAXA,gBAA0C;AAMnD,SAAoB,WAAXA,gBAA4C;AACrD,SAAoB,WAAXA,gBAA4C;AACrD,SAAoB,WAAXA,gBAAwC;AACjD,SAAoB,WAAXA,gBAA4B;AAOrC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;",
|
|
4
|
+
"sourcesContent": ["export { default as WebServer } from './webserver.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 WebServerBaseController } from './controller/base.js';\nexport type {\n ControllerAction,\n ControllerRequest,\n WebServerBaseControllerConstructorParams,\n} from './controller/base.interface.js';\nexport { default as WebServerHealthController } from './controller/health.js';\nexport { default as WebServerEntityController } from './controller/entity.js';\nexport { default as ExampleAuthController } from './controller/example-auth.js';\nexport { default as RouteUtil } from './util.js';\nexport type {\n AuthenticatedUser,\n AuthenticatedRequest,\n AuthenticatedRouteHandler,\n RouteHandler,\n} from './controller/auth-middleware.js';\nexport { withAuth } from './controller/auth-middleware.js';\nexport { defineRoute } from './define-route.js';\nexport { defineAction } from './define-action.js';\n"],
|
|
5
|
+
"mappings": "AAAA,SAAoB,WAAXA,gBAA4B;AASrC,SAAS,0BAA0B;AACnC,SAAoB,WAAXA,gBAA0C;AAMnD,SAAoB,WAAXA,gBAA4C;AACrD,SAAoB,WAAXA,gBAA4C;AACrD,SAAoB,WAAXA,gBAAwC;AACjD,SAAoB,WAAXA,gBAA4B;AAOrC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { EntityRouteDefinition } from './webserver.interface.js';
|
|
2
|
+
declare function getEntityRouteDefinitions({ basePath, entityValidationSchema, }: {
|
|
3
|
+
basePath: string;
|
|
4
|
+
entityValidationSchema: any;
|
|
5
|
+
}): EntityRouteDefinition[];
|
|
6
|
+
declare const _default: {
|
|
7
|
+
getEntityRouteDefinitions: typeof getEntityRouteDefinitions;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/webserver/util.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAyB,MAAM,0BAA0B,CAAC;AAE7F,iBAAS,yBAAyB,CAAC,EACjC,QAAQ,EACR,sBAAsB,GACvB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB,EAAE,GAAG,CAAC;CAC7B,GAAG,qBAAqB,EAAE,CAkE1B;;;;AAED,wBAGE"}
|
package/dist/webserver/util.js
CHANGED
|
@@ -37,12 +37,15 @@ function getEntityRouteDefinitions({
|
|
|
37
37
|
action: "createOne",
|
|
38
38
|
validationSchema: entityValidationSchema
|
|
39
39
|
});
|
|
40
|
+
const updateOneValidationSchemas = [idValidationSchema];
|
|
41
|
+
if (entityValidationSchema) {
|
|
42
|
+
updateOneValidationSchemas.push(entityValidationSchema);
|
|
43
|
+
}
|
|
40
44
|
routeDefinitions.push({
|
|
41
45
|
path: `${basePath}/:id`,
|
|
42
46
|
method: "PUT",
|
|
43
47
|
action: "updateOne",
|
|
44
|
-
validationSchema:
|
|
45
|
-
// TODO: Need to merge with idValidationSchema
|
|
48
|
+
validationSchema: updateOneValidationSchemas
|
|
46
49
|
});
|
|
47
50
|
routeDefinitions.push({
|
|
48
51
|
path: `${basePath}/:id`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/webserver/util.ts"],
|
|
4
|
-
"sourcesContent": ["import type { HTTPMethods } from 'fastify';\nimport type { EntityRouteDefinition, RouteValidationSchema } from './webserver.interface.js';\n\nfunction getEntityRouteDefinitions({\n basePath,\n entityValidationSchema,\n}: {\n basePath: string;\n entityValidationSchema: any;\n}): EntityRouteDefinition[] {\n const routeDefinitions: EntityRouteDefinition[] = [];\n\n const idValidationSchema: RouteValidationSchema = {\n type: 'params',\n schema: {\n properties: {\n id: { type: 'integer' },\n },\n required: ['id'],\n type: 'object',\n },\n };\n\n // Options\n routeDefinitions.push({\n path: `${basePath}/options`,\n method: 'GET' as HTTPMethods,\n action: 'options',\n });\n\n // Get many\n routeDefinitions.push({\n path: `${basePath}`,\n method: 'GET' as HTTPMethods,\n action: 'getMany',\n });\n\n // Get one\n routeDefinitions.push({\n path: `${basePath}/:id`,\n method: 'GET' as HTTPMethods,\n action: 'getOne',\n validationSchema: idValidationSchema,\n });\n\n // Create one\n routeDefinitions.push({\n path: `${basePath}`,\n method: 'POST' as HTTPMethods,\n action: 'createOne',\n validationSchema: entityValidationSchema,\n });\n\n // Update one\n routeDefinitions.push({\n path: `${basePath}/:id`,\n method: 'PUT' as HTTPMethods,\n action: 'updateOne',\n validationSchema:
|
|
5
|
-
"mappings": ";;AAGA,SAAS,0BAA0B;AAAA,EACjC;AAAA,EACA;AACF,GAG4B;AAC1B,QAAM,mBAA4C,CAAC;AAEnD,QAAM,qBAA4C;AAAA,IAChD,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU;AAAA,MACxB;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AAGA,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA
|
|
4
|
+
"sourcesContent": ["import type { HTTPMethods } from 'fastify';\nimport type { EntityRouteDefinition, RouteValidationSchema } from './webserver.interface.js';\n\nfunction getEntityRouteDefinitions({\n basePath,\n entityValidationSchema,\n}: {\n basePath: string;\n entityValidationSchema: any;\n}): EntityRouteDefinition[] {\n const routeDefinitions: EntityRouteDefinition[] = [];\n\n const idValidationSchema: RouteValidationSchema = {\n type: 'params',\n schema: {\n properties: {\n id: { type: 'integer' },\n },\n required: ['id'],\n type: 'object',\n },\n };\n\n // Options\n routeDefinitions.push({\n path: `${basePath}/options`,\n method: 'GET' as HTTPMethods,\n action: 'options',\n });\n\n // Get many\n routeDefinitions.push({\n path: `${basePath}`,\n method: 'GET' as HTTPMethods,\n action: 'getMany',\n });\n\n // Get one\n routeDefinitions.push({\n path: `${basePath}/:id`,\n method: 'GET' as HTTPMethods,\n action: 'getOne',\n validationSchema: idValidationSchema,\n });\n\n // Create one\n routeDefinitions.push({\n path: `${basePath}`,\n method: 'POST' as HTTPMethods,\n action: 'createOne',\n validationSchema: entityValidationSchema,\n });\n\n // Update one - merge params and body validation\n const updateOneValidationSchemas: RouteValidationSchema[] = [idValidationSchema];\n if (entityValidationSchema) {\n updateOneValidationSchemas.push(entityValidationSchema);\n }\n\n routeDefinitions.push({\n path: `${basePath}/:id`,\n method: 'PUT' as HTTPMethods,\n action: 'updateOne',\n validationSchema: updateOneValidationSchemas,\n });\n\n // Delete one\n routeDefinitions.push({\n path: `${basePath}/:id`,\n method: 'DELETE' as HTTPMethods,\n action: 'deleteOne',\n validationSchema: idValidationSchema,\n });\n\n return routeDefinitions;\n}\n\nexport default {\n // getEntityRoutes,\n getEntityRouteDefinitions,\n};\n"],
|
|
5
|
+
"mappings": ";;AAGA,SAAS,0BAA0B;AAAA,EACjC;AAAA,EACA;AACF,GAG4B;AAC1B,QAAM,mBAA4C,CAAC;AAEnD,QAAM,qBAA4C;AAAA,IAChD,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU;AAAA,MACxB;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AAGA,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AAGD,QAAM,6BAAsD,CAAC,kBAAkB;AAC/E,MAAI,wBAAwB;AAC1B,+BAA2B,KAAK,sBAAsB;AAAA,EACxD;AAEA,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AAGD,mBAAiB,KAAK;AAAA,IACpB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB,CAAC;AAED,SAAO;AACT;AAxES;AA0ET,IAAO,eAAQ;AAAA;AAAA,EAEb;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
import { type ZodTypeProvider } from 'fastify-type-provider-zod';
|
|
6
|
+
declare module 'fastify' {
|
|
7
|
+
interface FastifyRequest {
|
|
8
|
+
startTime?: number;
|
|
9
|
+
requestId?: string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
declare class WebServer {
|
|
13
|
+
private logger;
|
|
14
|
+
private applicationConfig;
|
|
15
|
+
private options;
|
|
16
|
+
private routes;
|
|
17
|
+
private redisInstance;
|
|
18
|
+
private queueManager;
|
|
19
|
+
private eventManager;
|
|
20
|
+
private databaseInstance;
|
|
21
|
+
fastifyServer: FastifyInstance<any, any, any, any, ZodTypeProvider>;
|
|
22
|
+
private lifecycleManager;
|
|
23
|
+
private _isReady;
|
|
24
|
+
constructor(params: WebServerConstructorParams & {
|
|
25
|
+
lifecycleManager: LifecycleManager;
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Load web server.
|
|
29
|
+
*/
|
|
30
|
+
load(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Configure security features (Helmet, Rate Limiting)
|
|
33
|
+
*/
|
|
34
|
+
private configureSecurity;
|
|
35
|
+
/**
|
|
36
|
+
* Configure hooks.
|
|
37
|
+
*/
|
|
38
|
+
private configureHooks;
|
|
39
|
+
private onListen;
|
|
40
|
+
private onRequest;
|
|
41
|
+
private onResponse;
|
|
42
|
+
private onError;
|
|
43
|
+
private onClose;
|
|
44
|
+
private configureCORS;
|
|
45
|
+
private configureMultipartUploads;
|
|
46
|
+
/**
|
|
47
|
+
* Configure routes.
|
|
48
|
+
*/
|
|
49
|
+
private configureRoutes;
|
|
50
|
+
private loadRoutesFromDirectory;
|
|
51
|
+
private normalizeRouteExport;
|
|
52
|
+
private isValidRoute;
|
|
53
|
+
defineRoute({ controllerInstance, controllerName, routeMethod, routePath, routeAction, routeSchema, handlerOverride, legacyValidation, }: {
|
|
54
|
+
controllerInstance: any;
|
|
55
|
+
controllerName: string;
|
|
56
|
+
routeMethod: HTTPMethods | HTTPMethods[];
|
|
57
|
+
routePath: string;
|
|
58
|
+
routeAction?: string;
|
|
59
|
+
routeSchema?: AnyRouteSchemaDefinition;
|
|
60
|
+
handlerOverride?: ControllerAction<any>;
|
|
61
|
+
legacyValidation?: {
|
|
62
|
+
type: 'body' | 'query' | 'params';
|
|
63
|
+
schema: {
|
|
64
|
+
[key: string]: any;
|
|
65
|
+
};
|
|
66
|
+
} | Array<{
|
|
67
|
+
type: 'body' | 'query' | 'params';
|
|
68
|
+
schema: {
|
|
69
|
+
[key: string]: any;
|
|
70
|
+
};
|
|
71
|
+
}>;
|
|
72
|
+
}): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Start web server.
|
|
75
|
+
*/
|
|
76
|
+
start(): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Stop web server.
|
|
79
|
+
*/
|
|
80
|
+
stop(): Promise<void>;
|
|
81
|
+
private buildFastifySchema;
|
|
82
|
+
private buildLegacySchema;
|
|
83
|
+
/**
|
|
84
|
+
* Check if web server is ready to accept traffic.
|
|
85
|
+
*/
|
|
86
|
+
isReady(): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Log web server message
|
|
89
|
+
*/
|
|
90
|
+
log(message: string, meta?: Record<string, unknown>): void;
|
|
91
|
+
}
|
|
92
|
+
export default WebServer;
|
|
93
|
+
//# sourceMappingURL=webserver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webserver.d.ts","sourceRoot":"","sources":["../../src/webserver/webserver.ts"],"names":[],"mappings":"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"}
|