@velajs/vela 1.19.0 → 1.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -14
- package/dist/configurable-module.builder-5FGMaXG6.js +91 -0
- package/dist/configurable-module.builder-5FGMaXG6.js.map +1 -0
- package/dist/container-BqUHID4l.js +645 -0
- package/dist/container-BqUHID4l.js.map +1 -0
- package/dist/cron-matcher-C9qv5OUA.js +113 -0
- package/dist/cron-matcher-C9qv5OUA.js.map +1 -0
- package/dist/decorate-GcSMAbKn.js +528 -0
- package/dist/decorate-GcSMAbKn.js.map +1 -0
- package/dist/decorators-C8YBFCIk.js +53 -0
- package/dist/decorators-C8YBFCIk.js.map +1 -0
- package/dist/define-module-NOyOZNXD.js +235 -0
- package/dist/define-module-NOyOZNXD.js.map +1 -0
- package/dist/discovery.service-BYm95SSD.js +368 -0
- package/dist/discovery.service-BYm95SSD.js.map +1 -0
- package/dist/discovery.service-Cpf1QcZ5.d.ts +648 -0
- package/dist/i18n/index.d.ts +138 -10
- package/dist/i18n/index.js +270 -8
- package/dist/i18n/index.js.map +1 -0
- package/dist/index-D72EQfcC.d.ts +430 -0
- package/dist/index-DhShDLCM.d.ts +2310 -0
- package/dist/index.d.ts +6 -70
- package/dist/index.js +14 -76
- package/dist/internal.d.ts +13 -17
- package/dist/internal.js +6 -19
- package/dist/live/index.d.ts +2 -12
- package/dist/live/index.js +826 -16
- package/dist/live/index.js.map +1 -0
- package/dist/metadata.registry-D1od8ZBt.d.ts +842 -0
- package/dist/plugin-ByBlVOve.js +1387 -0
- package/dist/plugin-ByBlVOve.js.map +1 -0
- package/dist/queue/index.d.ts +247 -10
- package/dist/queue/index.js +384 -12
- package/dist/queue/index.js.map +1 -0
- package/dist/request-context-C3nCGJNd.js +26 -0
- package/dist/request-context-C3nCGJNd.js.map +1 -0
- package/dist/route.manager-DRAZ5X04.js +991 -0
- package/dist/route.manager-DRAZ5X04.js.map +1 -0
- package/dist/schedule-node/index.d.ts +32 -3
- package/dist/schedule-node/index.js +97 -3
- package/dist/schedule-node/index.js.map +1 -0
- package/dist/schedule.registry-DVm7Jp5w.d.ts +55 -0
- package/dist/seeder/index.d.ts +75 -5
- package/dist/seeder/index.js +105 -4
- package/dist/seeder/index.js.map +1 -0
- package/dist/signed-url-CMmi0SIb.js +56 -0
- package/dist/signed-url-CMmi0SIb.js.map +1 -0
- package/dist/signed-url-DKhgja4U.d.ts +16 -0
- package/dist/src-eb5CI6Xn.js +2151 -0
- package/dist/src-eb5CI6Xn.js.map +1 -0
- package/dist/storage/index.d.ts +57 -4
- package/dist/storage/index.js +22 -5
- package/dist/storage/index.js.map +1 -0
- package/dist/streaming/index.d.ts +2 -2
- package/dist/streaming/index.js +2 -1
- package/dist/websocket/index.d.ts +3 -12
- package/dist/websocket/index.js +2 -16
- package/dist/websocket-DXmB-MWJ.js +697 -0
- package/dist/websocket-DXmB-MWJ.js.map +1 -0
- package/dist/websocket-node/index.d.ts +108 -6
- package/dist/websocket-node/index.js +228 -6
- package/dist/websocket-node/index.js.map +1 -0
- package/package.json +66 -53
- package/dist/__tests__/workers/entry.d.ts +0 -9
- package/dist/__tests__/workers-als/entry-als.d.ts +0 -9
- package/dist/application.d.ts +0 -104
- package/dist/application.js +0 -364
- package/dist/cache/cache.decorators.d.ts +0 -2
- package/dist/cache/cache.decorators.js +0 -4
- package/dist/cache/cache.interceptor.d.ts +0 -9
- package/dist/cache/cache.interceptor.js +0 -60
- package/dist/cache/cache.module.d.ts +0 -7
- package/dist/cache/cache.module.js +0 -58
- package/dist/cache/cache.service.d.ts +0 -9
- package/dist/cache/cache.service.js +0 -42
- package/dist/cache/cache.store.d.ts +0 -12
- package/dist/cache/cache.store.js +0 -51
- package/dist/cache/cache.tokens.d.ts +0 -6
- package/dist/cache/cache.tokens.js +0 -5
- package/dist/cache/cache.types.d.ts +0 -41
- package/dist/cache/cache.types.js +0 -1
- package/dist/cache/index.d.ts +0 -8
- package/dist/cache/index.js +0 -7
- package/dist/cache/tiered-cache.store.d.ts +0 -19
- package/dist/cache/tiered-cache.store.js +0 -40
- package/dist/config/config.module.d.ts +0 -19
- package/dist/config/config.module.js +0 -98
- package/dist/config/config.service.d.ts +0 -20
- package/dist/config/config.service.js +0 -43
- package/dist/config/config.store.d.ts +0 -46
- package/dist/config/config.store.js +0 -119
- package/dist/config/config.tokens.d.ts +0 -13
- package/dist/config/config.tokens.js +0 -14
- package/dist/config/config.types.d.ts +0 -41
- package/dist/config/config.types.js +0 -4
- package/dist/config/index.d.ts +0 -7
- package/dist/config/index.js +0 -5
- package/dist/config/register-as.d.ts +0 -52
- package/dist/config/register-as.js +0 -39
- package/dist/constants.d.ts +0 -44
- package/dist/constants.js +0 -46
- package/dist/container/container.d.ts +0 -154
- package/dist/container/container.js +0 -849
- package/dist/container/decorators.d.ts +0 -17
- package/dist/container/decorators.js +0 -57
- package/dist/container/disposable.d.ts +0 -5
- package/dist/container/disposable.js +0 -33
- package/dist/container/index.d.ts +0 -6
- package/dist/container/index.js +0 -5
- package/dist/container/mixin.d.ts +0 -24
- package/dist/container/mixin.js +0 -26
- package/dist/container/module-ref.d.ts +0 -21
- package/dist/container/module-ref.js +0 -48
- package/dist/container/types.d.ts +0 -154
- package/dist/container/types.js +0 -49
- package/dist/cors/cors.module.d.ts +0 -7
- package/dist/cors/cors.module.js +0 -37
- package/dist/cors/cors.tokens.d.ts +0 -3
- package/dist/cors/cors.tokens.js +0 -2
- package/dist/cors/cors.types.d.ts +0 -8
- package/dist/cors/cors.types.js +0 -1
- package/dist/cors/index.d.ts +0 -3
- package/dist/cors/index.js +0 -2
- package/dist/crypto/signed-url.d.ts +0 -12
- package/dist/crypto/signed-url.js +0 -60
- package/dist/discovery/discoverable.decorator.d.ts +0 -38
- package/dist/discovery/discoverable.decorator.js +0 -42
- package/dist/discovery/discovery.service.d.ts +0 -102
- package/dist/discovery/discovery.service.js +0 -177
- package/dist/discovery/index.d.ts +0 -2
- package/dist/discovery/index.js +0 -2
- package/dist/entrypoint/entrypoint.registry.d.ts +0 -42
- package/dist/entrypoint/entrypoint.registry.js +0 -112
- package/dist/entrypoint/entrypoint.types.d.ts +0 -41
- package/dist/entrypoint/entrypoint.types.js +0 -3
- package/dist/entrypoint/execution-context.d.ts +0 -15
- package/dist/entrypoint/execution-context.js +0 -21
- package/dist/entrypoint/execution-scope.d.ts +0 -21
- package/dist/entrypoint/execution-scope.js +0 -28
- package/dist/entrypoint/index.d.ts +0 -4
- package/dist/entrypoint/index.js +0 -4
- package/dist/errors/http-exception.d.ts +0 -63
- package/dist/errors/http-exception.js +0 -142
- package/dist/errors/index.d.ts +0 -1
- package/dist/errors/index.js +0 -1
- package/dist/event-emitter/event-emitter.decorators.d.ts +0 -1
- package/dist/event-emitter/event-emitter.decorators.js +0 -10
- package/dist/event-emitter/event-emitter.module.d.ts +0 -2
- package/dist/event-emitter/event-emitter.module.js +0 -23
- package/dist/event-emitter/event-emitter.service.d.ts +0 -13
- package/dist/event-emitter/event-emitter.service.js +0 -127
- package/dist/event-emitter/event-emitter.subscriber.d.ts +0 -9
- package/dist/event-emitter/event-emitter.subscriber.js +0 -45
- package/dist/event-emitter/event-emitter.tokens.d.ts +0 -1
- package/dist/event-emitter/event-emitter.tokens.js +0 -1
- package/dist/event-emitter/event-emitter.types.d.ts +0 -5
- package/dist/event-emitter/event-emitter.types.js +0 -1
- package/dist/event-emitter/index.d.ts +0 -6
- package/dist/event-emitter/index.js +0 -5
- package/dist/exceptions/errors.module.d.ts +0 -40
- package/dist/exceptions/errors.module.js +0 -46
- package/dist/exceptions/exception-handler.d.ts +0 -56
- package/dist/exceptions/exception-handler.js +0 -17
- package/dist/exceptions/index.d.ts +0 -6
- package/dist/exceptions/index.js +0 -3
- package/dist/exceptions/reporter.d.ts +0 -21
- package/dist/exceptions/reporter.js +0 -70
- package/dist/factory/adapter.d.ts +0 -36
- package/dist/factory/adapter.js +0 -18
- package/dist/factory/bootstrap.d.ts +0 -23
- package/dist/factory/bootstrap.js +0 -110
- package/dist/factory.d.ts +0 -16
- package/dist/factory.js +0 -36
- package/dist/fetch/fetch.module.d.ts +0 -7
- package/dist/fetch/fetch.module.js +0 -31
- package/dist/fetch/fetch.service.d.ts +0 -24
- package/dist/fetch/fetch.service.js +0 -145
- package/dist/fetch/fetch.types.d.ts +0 -24
- package/dist/fetch/fetch.types.js +0 -1
- package/dist/fetch/index.d.ts +0 -3
- package/dist/fetch/index.js +0 -2
- package/dist/health/health.http.d.ts +0 -14
- package/dist/health/health.http.js +0 -75
- package/dist/health/health.indicator.d.ts +0 -9
- package/dist/health/health.indicator.js +0 -32
- package/dist/health/health.module.d.ts +0 -2
- package/dist/health/health.module.js +0 -26
- package/dist/health/health.service.d.ts +0 -7
- package/dist/health/health.service.js +0 -69
- package/dist/health/health.types.d.ts +0 -15
- package/dist/health/health.types.js +0 -1
- package/dist/health/index.d.ts +0 -6
- package/dist/health/index.js +0 -4
- package/dist/http/ambient.d.ts +0 -17
- package/dist/http/ambient.js +0 -44
- package/dist/http/argument-resolver.d.ts +0 -10
- package/dist/http/argument-resolver.js +0 -89
- package/dist/http/decorators.d.ts +0 -198
- package/dist/http/decorators.js +0 -321
- package/dist/http/execution-context.d.ts +0 -8
- package/dist/http/execution-context.js +0 -35
- package/dist/http/handler-executor.d.ts +0 -20
- package/dist/http/handler-executor.js +0 -133
- package/dist/http/index.d.ts +0 -12
- package/dist/http/index.js +0 -7
- package/dist/http/instantiate.d.ts +0 -4
- package/dist/http/instantiate.js +0 -45
- package/dist/http/lazy-param.decorator.d.ts +0 -37
- package/dist/http/lazy-param.decorator.js +0 -117
- package/dist/http/request-container.d.ts +0 -16
- package/dist/http/request-container.js +0 -19
- package/dist/http/request-context.d.ts +0 -13
- package/dist/http/request-context.js +0 -22
- package/dist/http/response-mapper.d.ts +0 -8
- package/dist/http/response-mapper.js +0 -42
- package/dist/http/route-contributor.d.ts +0 -68
- package/dist/http/route-contributor.js +0 -22
- package/dist/http/route-map.d.ts +0 -30
- package/dist/http/route-map.js +0 -27
- package/dist/http/route.manager.d.ts +0 -92
- package/dist/http/route.manager.js +0 -481
- package/dist/http/types.d.ts +0 -37
- package/dist/http/types.js +0 -1
- package/dist/http/url/index.d.ts +0 -4
- package/dist/http/url/index.js +0 -3
- package/dist/http/url/signed-url.guard.d.ts +0 -27
- package/dist/http/url/signed-url.guard.js +0 -62
- package/dist/http/url/signing-secret.d.ts +0 -20
- package/dist/http/url/signing-secret.js +0 -24
- package/dist/http/url/url-generator.service.d.ts +0 -52
- package/dist/http/url/url-generator.service.js +0 -104
- package/dist/i18n/deep-merge.d.ts +0 -2
- package/dist/i18n/deep-merge.js +0 -15
- package/dist/i18n/i18n.middleware.d.ts +0 -15
- package/dist/i18n/i18n.middleware.js +0 -94
- package/dist/i18n/i18n.module.d.ts +0 -13
- package/dist/i18n/i18n.module.js +0 -69
- package/dist/i18n/i18n.options.d.ts +0 -30
- package/dist/i18n/i18n.options.js +0 -16
- package/dist/i18n/i18n.service.d.ts +0 -20
- package/dist/i18n/i18n.service.js +0 -49
- package/dist/i18n/i18n.tokens.d.ts +0 -6
- package/dist/i18n/i18n.tokens.js +0 -3
- package/dist/i18n/i18n.types.d.ts +0 -6
- package/dist/i18n/i18n.types.js +0 -1
- package/dist/i18n/message-loader.service.d.ts +0 -21
- package/dist/i18n/message-loader.service.js +0 -90
- package/dist/i18n/message-registry.d.ts +0 -16
- package/dist/i18n/message-registry.js +0 -49
- package/dist/lifecycle/index.d.ts +0 -20
- package/dist/lifecycle/index.js +0 -15
- package/dist/live/live.cursor.d.ts +0 -22
- package/dist/live/live.cursor.js +0 -56
- package/dist/live/live.decorators.d.ts +0 -32
- package/dist/live/live.decorators.js +0 -46
- package/dist/live/live.delta.d.ts +0 -15
- package/dist/live/live.delta.js +0 -51
- package/dist/live/live.engine.d.ts +0 -88
- package/dist/live/live.engine.js +0 -471
- package/dist/live/live.invalidation.d.ts +0 -45
- package/dist/live/live.invalidation.js +0 -99
- package/dist/live/live.module.d.ts +0 -28
- package/dist/live/live.module.js +0 -87
- package/dist/live/live.tokens.d.ts +0 -9
- package/dist/live/live.tokens.js +0 -8
- package/dist/live/live.types.d.ts +0 -138
- package/dist/live/live.types.js +0 -1
- package/dist/live/presence.d.ts +0 -44
- package/dist/live/presence.js +0 -130
- package/dist/metadata.d.ts +0 -10
- package/dist/metadata.js +0 -20
- package/dist/module/configurable-module.builder.d.ts +0 -56
- package/dist/module/configurable-module.builder.js +0 -84
- package/dist/module/configurable-module.types.d.ts +0 -93
- package/dist/module/configurable-module.types.js +0 -5
- package/dist/module/decorators.d.ts +0 -10
- package/dist/module/decorators.js +0 -47
- package/dist/module/define-module.d.ts +0 -112
- package/dist/module/define-module.js +0 -232
- package/dist/module/graph.d.ts +0 -10
- package/dist/module/graph.js +0 -35
- package/dist/module/index.d.ts +0 -10
- package/dist/module/index.js +0 -7
- package/dist/module/lazy-modules.d.ts +0 -82
- package/dist/module/lazy-modules.js +0 -231
- package/dist/module/lazy-provider.d.ts +0 -65
- package/dist/module/lazy-provider.js +0 -111
- package/dist/module/middleware.d.ts +0 -30
- package/dist/module/middleware.js +0 -67
- package/dist/module/module-loader.d.ts +0 -58
- package/dist/module/module-loader.js +0 -484
- package/dist/module/stable-hash.d.ts +0 -15
- package/dist/module/stable-hash.js +0 -52
- package/dist/module/types.d.ts +0 -1
- package/dist/module/types.js +0 -1
- package/dist/openapi/decorators.d.ts +0 -34
- package/dist/openapi/decorators.js +0 -66
- package/dist/openapi/document.d.ts +0 -3
- package/dist/openapi/document.js +0 -316
- package/dist/openapi/index.d.ts +0 -7
- package/dist/openapi/index.js +0 -6
- package/dist/openapi/redoc-ui.d.ts +0 -1
- package/dist/openapi/redoc-ui.js +0 -19
- package/dist/openapi/scalar-ui.d.ts +0 -1
- package/dist/openapi/scalar-ui.js +0 -19
- package/dist/openapi/swagger-ui.d.ts +0 -1
- package/dist/openapi/swagger-ui.js +0 -23
- package/dist/openapi/types.d.ts +0 -182
- package/dist/openapi/types.js +0 -4
- package/dist/openapi/zod-to-json-schema.d.ts +0 -4
- package/dist/openapi/zod-to-json-schema.js +0 -57
- package/dist/pipeline/app-providers.d.ts +0 -10
- package/dist/pipeline/app-providers.js +0 -43
- package/dist/pipeline/component.manager.d.ts +0 -25
- package/dist/pipeline/component.manager.js +0 -66
- package/dist/pipeline/decorators.d.ts +0 -10
- package/dist/pipeline/decorators.js +0 -42
- package/dist/pipeline/index.d.ts +0 -12
- package/dist/pipeline/index.js +0 -7
- package/dist/pipeline/pipeline-runner.d.ts +0 -31
- package/dist/pipeline/pipeline-runner.js +0 -40
- package/dist/pipeline/pipes.d.ts +0 -48
- package/dist/pipeline/pipes.js +0 -104
- package/dist/pipeline/reflector.d.ts +0 -86
- package/dist/pipeline/reflector.js +0 -121
- package/dist/pipeline/scoped-components.d.ts +0 -26
- package/dist/pipeline/scoped-components.js +0 -27
- package/dist/pipeline/tokens.d.ts +0 -57
- package/dist/pipeline/tokens.js +0 -47
- package/dist/pipeline/types.d.ts +0 -64
- package/dist/pipeline/types.js +0 -1
- package/dist/plugin/plugin.d.ts +0 -31
- package/dist/plugin/plugin.js +0 -111
- package/dist/queue/inline.driver.d.ts +0 -30
- package/dist/queue/inline.driver.js +0 -58
- package/dist/queue/queue.binding.d.ts +0 -23
- package/dist/queue/queue.binding.js +0 -60
- package/dist/queue/queue.client.d.ts +0 -20
- package/dist/queue/queue.client.js +0 -33
- package/dist/queue/queue.decorators.d.ts +0 -23
- package/dist/queue/queue.decorators.js +0 -46
- package/dist/queue/queue.dispatch.d.ts +0 -36
- package/dist/queue/queue.dispatch.js +0 -109
- package/dist/queue/queue.module.d.ts +0 -32
- package/dist/queue/queue.module.js +0 -80
- package/dist/queue/queue.tokens.d.ts +0 -21
- package/dist/queue/queue.tokens.js +0 -34
- package/dist/queue/queue.types.d.ts +0 -61
- package/dist/queue/queue.types.js +0 -4
- package/dist/registry/index.d.ts +0 -2
- package/dist/registry/index.js +0 -1
- package/dist/registry/metadata.registry.d.ts +0 -73
- package/dist/registry/metadata.registry.js +0 -357
- package/dist/registry/paths.d.ts +0 -3
- package/dist/registry/paths.js +0 -15
- package/dist/registry/types.d.ts +0 -116
- package/dist/registry/types.js +0 -1
- package/dist/registry/util.d.ts +0 -3
- package/dist/registry/util.js +0 -8
- package/dist/schedule/cron-matcher.d.ts +0 -2
- package/dist/schedule/cron-matcher.js +0 -62
- package/dist/schedule/index.d.ts +0 -8
- package/dist/schedule/index.js +0 -5
- package/dist/schedule/schedule.decorators.d.ts +0 -2
- package/dist/schedule/schedule.decorators.js +0 -18
- package/dist/schedule/schedule.module.d.ts +0 -9
- package/dist/schedule/schedule.module.js +0 -28
- package/dist/schedule/schedule.registry.d.ts +0 -23
- package/dist/schedule/schedule.registry.js +0 -63
- package/dist/schedule/schedule.tokens.d.ts +0 -2
- package/dist/schedule/schedule.tokens.js +0 -2
- package/dist/schedule/schedule.types.d.ts +0 -8
- package/dist/schedule/schedule.types.js +0 -1
- package/dist/schedule-node/schedule-node.module.d.ts +0 -9
- package/dist/schedule-node/schedule-node.module.js +0 -28
- package/dist/schedule-node/schedule.executor.d.ts +0 -19
- package/dist/schedule-node/schedule.executor.js +0 -112
- package/dist/seeder/seeder.decorator.d.ts +0 -7
- package/dist/seeder/seeder.decorator.js +0 -15
- package/dist/seeder/seeder.module.d.ts +0 -16
- package/dist/seeder/seeder.module.js +0 -44
- package/dist/seeder/seeder.registry.d.ts +0 -23
- package/dist/seeder/seeder.registry.js +0 -83
- package/dist/seeder/seeder.tokens.d.ts +0 -2
- package/dist/seeder/seeder.tokens.js +0 -1
- package/dist/seeder/seeder.types.d.ts +0 -20
- package/dist/seeder/seeder.types.js +0 -1
- package/dist/serialization/index.d.ts +0 -2
- package/dist/serialization/index.js +0 -2
- package/dist/serialization/serialize.decorator.d.ts +0 -6
- package/dist/serialization/serialize.decorator.js +0 -7
- package/dist/serialization/serializer.interceptor.d.ts +0 -4
- package/dist/serialization/serializer.interceptor.js +0 -16
- package/dist/services/index.d.ts +0 -2
- package/dist/services/index.js +0 -1
- package/dist/services/logger.d.ts +0 -59
- package/dist/services/logger.js +0 -159
- package/dist/storage/path-template.d.ts +0 -9
- package/dist/storage/path-template.js +0 -20
- package/dist/storage/storage.types.d.ts +0 -41
- package/dist/storage/storage.types.js +0 -5
- package/dist/throttler/index.d.ts +0 -6
- package/dist/throttler/index.js +0 -5
- package/dist/throttler/throttler.decorators.d.ts +0 -3
- package/dist/throttler/throttler.decorators.js +0 -4
- package/dist/throttler/throttler.guard.d.ts +0 -9
- package/dist/throttler/throttler.guard.js +0 -72
- package/dist/throttler/throttler.module.d.ts +0 -7
- package/dist/throttler/throttler.module.js +0 -41
- package/dist/throttler/throttler.storage.d.ts +0 -10
- package/dist/throttler/throttler.storage.js +0 -44
- package/dist/throttler/throttler.tokens.d.ts +0 -6
- package/dist/throttler/throttler.tokens.js +0 -5
- package/dist/throttler/throttler.types.d.ts +0 -25
- package/dist/throttler/throttler.types.js +0 -1
- package/dist/validation/create-zod-dto.d.ts +0 -13
- package/dist/validation/create-zod-dto.js +0 -18
- package/dist/validation/index.d.ts +0 -3
- package/dist/validation/index.js +0 -2
- package/dist/validation/validation.pipe.d.ts +0 -4
- package/dist/validation/validation.pipe.js +0 -19
- package/dist/websocket/websocket.decorators.d.ts +0 -47
- package/dist/websocket/websocket.decorators.js +0 -80
- package/dist/websocket/websocket.module.d.ts +0 -35
- package/dist/websocket/websocket.module.js +0 -63
- package/dist/websocket/websocket.tokens.d.ts +0 -30
- package/dist/websocket/websocket.tokens.js +0 -27
- package/dist/websocket/websocket.types.d.ts +0 -102
- package/dist/websocket/websocket.types.js +0 -4
- package/dist/websocket/ws-argument-resolver.d.ts +0 -13
- package/dist/websocket/ws-argument-resolver.js +0 -40
- package/dist/websocket/ws-dispatcher.d.ts +0 -54
- package/dist/websocket/ws-dispatcher.js +0 -343
- package/dist/websocket/ws-exception.d.ts +0 -25
- package/dist/websocket/ws-exception.js +0 -42
- package/dist/websocket/ws-execution-context.d.ts +0 -9
- package/dist/websocket/ws-execution-context.js +0 -24
- package/dist/websocket/ws-server.d.ts +0 -31
- package/dist/websocket/ws-server.js +0 -74
- package/dist/websocket/ws-sync.d.ts +0 -47
- package/dist/websocket/ws-sync.js +0 -74
- package/dist/websocket-node/node-ws-client.d.ts +0 -24
- package/dist/websocket-node/node-ws-client.js +0 -49
- package/dist/websocket-node/redis-live.d.ts +0 -24
- package/dist/websocket-node/redis-live.js +0 -57
- package/dist/websocket-node/redis-sync.d.ts +0 -33
- package/dist/websocket-node/redis-sync.js +0 -56
- package/dist/websocket-node/register-gateways.d.ts +0 -20
- package/dist/websocket-node/register-gateways.js +0 -61
|
@@ -0,0 +1,2151 @@
|
|
|
1
|
+
import { C as InjectionToken, S as ForwardRef, _ as APP_GUARD, a as Injectable, b as APP_PIPE, g as APP_FILTER, h as APP_EXCEPTION_HANDLER, i as Inject, k as MetadataRegistry, n as __decorateParam, o as Optional, p as ParamType, r as __decorateMetadata, t as __decorate, v as APP_INTERCEPTOR, x as ERROR_CATALOG, y as APP_MIDDLEWARE } from "./decorate-GcSMAbKn.js";
|
|
2
|
+
import { G as getMetadata, H as joinPaths, I as ComponentManager, R as buildExecutionContext, U as toOpenApiPath, z as getRouteContributors } from "./route.manager-DRAZ5X04.js";
|
|
3
|
+
import { a as BadRequestException, t as DiscoveryService, v as ServiceUnavailableException, y as TooManyRequestsException } from "./discovery.service-BYm95SSD.js";
|
|
4
|
+
import { t as Container } from "./container-BqUHID4l.js";
|
|
5
|
+
import { g as VelaApplication, m as CONFIG_OPTIONS, o as bootstrap, p as CONFIG_ENV } from "./plugin-ByBlVOve.js";
|
|
6
|
+
import { t as REQUEST_CONTEXT } from "./request-context-C3nCGJNd.js";
|
|
7
|
+
import { i as getModuleMetadata, n as Module } from "./decorators-C8YBFCIk.js";
|
|
8
|
+
import { n as defineModule, r as stableHash } from "./define-module-NOyOZNXD.js";
|
|
9
|
+
import { t as ConfigurableModuleBuilder } from "./configurable-module.builder-5FGMaXG6.js";
|
|
10
|
+
import { i as INTERVAL_METADATA, n as ScheduleRegistry, r as CRON_METADATA } from "./cron-matcher-C9qv5OUA.js";
|
|
11
|
+
import { CORE_CATALOG, CORE_CATALOG as CORE_CATALOG$1, VelaError, composeCatalogs, composeCatalogs as composeCatalogs$1, defineErrorCatalog, isVelaError as isVelaError$1, toErrorBody as toErrorBody$1 } from "@velajs/errors";
|
|
12
|
+
import { contextStorage, getContext } from "hono/context-storage";
|
|
13
|
+
import { cors } from "hono/cors";
|
|
14
|
+
import { env, getRuntimeKey } from "hono/adapter";
|
|
15
|
+
//#region src/factory.ts
|
|
16
|
+
const VelaFactory = { async create(rootModule, options = {}) {
|
|
17
|
+
const { adapters = [], ...bootstrapOptions } = options;
|
|
18
|
+
const adapterMiddleware = adapters.flatMap((a) => a.requestMiddleware ?? []);
|
|
19
|
+
if (adapterMiddleware.length > 0) bootstrapOptions.middleware = [...adapterMiddleware, ...bootstrapOptions.middleware ?? []];
|
|
20
|
+
const { container, routeManager, loader } = await bootstrap(rootModule, bootstrapOptions);
|
|
21
|
+
const app = new VelaApplication(container, routeManager);
|
|
22
|
+
const instances = await loader.resolveAllInstances();
|
|
23
|
+
app.setInstances(instances);
|
|
24
|
+
await app.callOnModuleInit();
|
|
25
|
+
await app.callOnApplicationBootstrap();
|
|
26
|
+
const adapterContext = {
|
|
27
|
+
app,
|
|
28
|
+
container,
|
|
29
|
+
routeManager,
|
|
30
|
+
discovery: container.resolve(DiscoveryService)
|
|
31
|
+
};
|
|
32
|
+
for (const adapter of adapters) await adapter.onBootstrap?.(adapterContext);
|
|
33
|
+
await app.initRoutes();
|
|
34
|
+
for (const adapter of adapters) await adapter.onRoutesBuilt?.(adapterContext);
|
|
35
|
+
return app;
|
|
36
|
+
} };
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/module/graph.ts
|
|
39
|
+
function isDynamicModuleLike(value) {
|
|
40
|
+
return !!value && typeof value === "object" && "module" in value && typeof value.module === "function";
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Walks the module dependency graph from a root, unwrapping ForwardRef and
|
|
44
|
+
* dynamic-module imports along the way, and returns every controller
|
|
45
|
+
* reachable from it. Pure metadata read — no Container, no side effects.
|
|
46
|
+
*
|
|
47
|
+
* Used by createOpenApiDocument and any other consumer that needs a
|
|
48
|
+
* controller list without bootstrapping the application.
|
|
49
|
+
*/
|
|
50
|
+
function collectControllers(rootModule) {
|
|
51
|
+
const visited = /* @__PURE__ */ new Set();
|
|
52
|
+
const controllers = /* @__PURE__ */ new Set();
|
|
53
|
+
const visit = (entry) => {
|
|
54
|
+
const unwrapped = entry instanceof ForwardRef ? entry.factory() : entry;
|
|
55
|
+
const moduleClass = isDynamicModuleLike(unwrapped) ? unwrapped.module : unwrapped;
|
|
56
|
+
const extraControllers = isDynamicModuleLike(unwrapped) ? unwrapped.controllers ?? [] : [];
|
|
57
|
+
const extraImports = isDynamicModuleLike(unwrapped) ? unwrapped.imports ?? [] : [];
|
|
58
|
+
if (typeof moduleClass !== "function" || visited.has(moduleClass)) return;
|
|
59
|
+
visited.add(moduleClass);
|
|
60
|
+
const metadata = getModuleMetadata(moduleClass);
|
|
61
|
+
if (metadata) {
|
|
62
|
+
for (const controller of metadata.controllers) controllers.add(controller);
|
|
63
|
+
for (const imp of metadata.imports) visit(imp);
|
|
64
|
+
}
|
|
65
|
+
for (const controller of extraControllers) controllers.add(controller);
|
|
66
|
+
for (const imp of extraImports) visit(imp);
|
|
67
|
+
};
|
|
68
|
+
visit(rootModule);
|
|
69
|
+
return [...controllers];
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/openapi/decorators.ts
|
|
73
|
+
const API_DOC_METADATA = "vela:openapi:doc";
|
|
74
|
+
const API_TAGS_METADATA = "vela:openapi:tags";
|
|
75
|
+
const API_RESPONSES_METADATA = "vela:openapi:responses";
|
|
76
|
+
/**
|
|
77
|
+
* Attach OpenAPI documentation to a route handler (or controller).
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* @Get('/:id')
|
|
81
|
+
* @ApiDoc({ summary: 'Get a user', description: '...', operationId: 'getUser' })
|
|
82
|
+
* findOne(@Param('id') id: string) { ... }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
function ApiDoc(metadata) {
|
|
86
|
+
return (target, propertyKey) => {
|
|
87
|
+
if (propertyKey !== void 0) MetadataRegistry.setCustomHandlerMeta(target.constructor, propertyKey, API_DOC_METADATA, metadata);
|
|
88
|
+
else MetadataRegistry.setCustomClassMeta(target, API_DOC_METADATA, metadata);
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Attach OpenAPI tags to a controller or handler. Handler-level tags merge
|
|
93
|
+
* with controller-level tags; duplicates are de-duplicated in the output.
|
|
94
|
+
*/
|
|
95
|
+
function ApiTags(...tags) {
|
|
96
|
+
return (target, propertyKey) => {
|
|
97
|
+
if (propertyKey !== void 0) MetadataRegistry.setCustomHandlerMeta(target.constructor, propertyKey, API_TAGS_METADATA, tags);
|
|
98
|
+
else MetadataRegistry.setCustomClassMeta(target, API_TAGS_METADATA, tags);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function getApiDoc(target, propertyKey) {
|
|
102
|
+
if (propertyKey !== void 0) return MetadataRegistry.getCustomHandlerMeta(target, propertyKey, API_DOC_METADATA);
|
|
103
|
+
return MetadataRegistry.getCustomClassMeta(target, API_DOC_METADATA);
|
|
104
|
+
}
|
|
105
|
+
function getApiTags(target, propertyKey) {
|
|
106
|
+
if (propertyKey !== void 0) return MetadataRegistry.getCustomHandlerMeta(target, propertyKey, API_TAGS_METADATA);
|
|
107
|
+
return MetadataRegistry.getCustomClassMeta(target, API_TAGS_METADATA);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Document a response for a given status code. Stackable: apply multiple
|
|
111
|
+
* times on the same handler to declare different statuses.
|
|
112
|
+
*
|
|
113
|
+
* ```ts
|
|
114
|
+
* @Get('/:id')
|
|
115
|
+
* @ApiResponse(200, { description: 'Found', schema: UserDto })
|
|
116
|
+
* @ApiResponse(404, { description: 'Not found', schema: ErrorDto })
|
|
117
|
+
* findOne() { ... }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
function ApiResponse(status, options) {
|
|
121
|
+
return (target, propertyKey) => {
|
|
122
|
+
MetadataRegistry.appendCustomHandlerMeta(target.constructor, propertyKey, API_RESPONSES_METADATA, {
|
|
123
|
+
status,
|
|
124
|
+
...options
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function getApiResponses(target, propertyKey) {
|
|
129
|
+
return MetadataRegistry.getCustomHandlerMeta(target, propertyKey, API_RESPONSES_METADATA);
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/openapi/zod-to-json-schema.ts
|
|
133
|
+
function stripOpenApiIncompatible(schema) {
|
|
134
|
+
const out = { ...schema };
|
|
135
|
+
delete out.$schema;
|
|
136
|
+
if (Array.isArray(out.properties)) {} else if (out.properties && typeof out.properties === "object") {
|
|
137
|
+
const props = out.properties;
|
|
138
|
+
const cleaned = {};
|
|
139
|
+
for (const [key, val] of Object.entries(props)) cleaned[key] = stripOpenApiIncompatible(val);
|
|
140
|
+
out.properties = cleaned;
|
|
141
|
+
}
|
|
142
|
+
if (out.items && typeof out.items === "object") out.items = stripOpenApiIncompatible(out.items);
|
|
143
|
+
return out;
|
|
144
|
+
}
|
|
145
|
+
function zodToJsonSchema(schema) {
|
|
146
|
+
if (!schema || typeof schema !== "object") return {};
|
|
147
|
+
const maybe = schema.toJSONSchema;
|
|
148
|
+
if (typeof maybe === "function") try {
|
|
149
|
+
const result = maybe.call(schema);
|
|
150
|
+
if (result && typeof result === "object") return stripOpenApiIncompatible(result);
|
|
151
|
+
} catch {}
|
|
152
|
+
return {};
|
|
153
|
+
}
|
|
154
|
+
function ctorName(schema) {
|
|
155
|
+
if (!schema || typeof schema !== "object") return void 0;
|
|
156
|
+
return schema.constructor?.name;
|
|
157
|
+
}
|
|
158
|
+
function isOptional(schema) {
|
|
159
|
+
const name = ctorName(schema);
|
|
160
|
+
return name === "ZodOptional" || name === "ZodDefault";
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/openapi/document.ts
|
|
164
|
+
/**
|
|
165
|
+
* Tracks DTO classes referenced during document generation and registers
|
|
166
|
+
* each under `components.schemas`. Handles name collisions by suffixing.
|
|
167
|
+
*/
|
|
168
|
+
var ComponentsRegistry = class {
|
|
169
|
+
schemas = /* @__PURE__ */ new Map();
|
|
170
|
+
classToKey = /* @__PURE__ */ new WeakMap();
|
|
171
|
+
ref(dtoClass) {
|
|
172
|
+
const existing = this.classToKey.get(dtoClass);
|
|
173
|
+
if (existing) return { $ref: `#/components/schemas/${existing}` };
|
|
174
|
+
const baseName = dtoClass.name && dtoClass.name !== "" ? dtoClass.name : "Schema";
|
|
175
|
+
let key = baseName;
|
|
176
|
+
let counter = 2;
|
|
177
|
+
while (this.schemas.has(key)) key = `${baseName}${counter++}`;
|
|
178
|
+
this.classToKey.set(dtoClass, key);
|
|
179
|
+
const staticSchema = dtoClass.schema;
|
|
180
|
+
this.schemas.set(key, zodToJsonSchema(staticSchema));
|
|
181
|
+
return { $ref: `#/components/schemas/${key}` };
|
|
182
|
+
}
|
|
183
|
+
build() {
|
|
184
|
+
if (this.schemas.size === 0) return void 0;
|
|
185
|
+
return Object.fromEntries(this.schemas);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
function isDtoClass(value) {
|
|
189
|
+
return typeof value === "function" && value.schema != null;
|
|
190
|
+
}
|
|
191
|
+
function getParamSchema(param, paramtypes, registry) {
|
|
192
|
+
const metatype = param.metatype ?? paramtypes?.[param.index];
|
|
193
|
+
if (!metatype) return void 0;
|
|
194
|
+
if (isDtoClass(metatype)) return registry.ref(metatype);
|
|
195
|
+
const maybeSchema = metatype.schema;
|
|
196
|
+
if (maybeSchema) return zodToJsonSchema(maybeSchema);
|
|
197
|
+
}
|
|
198
|
+
function isParamOptional(param, paramtypes) {
|
|
199
|
+
const metatype = param.metatype ?? paramtypes?.[param.index];
|
|
200
|
+
if (metatype?.schema) return isOptional(metatype.schema);
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
function isLikelyJsonSchema(value) {
|
|
204
|
+
if (!value || typeof value !== "object") return false;
|
|
205
|
+
const v = value;
|
|
206
|
+
if (typeof v.toJSONSchema === "function") return false;
|
|
207
|
+
return "type" in v || "$ref" in v || "oneOf" in v || "anyOf" in v || "allOf" in v || "enum" in v || "const" in v;
|
|
208
|
+
}
|
|
209
|
+
function resolveResponseSchema(input, registry) {
|
|
210
|
+
if (input === void 0 || input === null) return void 0;
|
|
211
|
+
if (isDtoClass(input)) return registry.ref(input);
|
|
212
|
+
if (isLikelyJsonSchema(input)) return { ...input };
|
|
213
|
+
if (typeof input === "object" && typeof input.toJSONSchema === "function") return zodToJsonSchema(input);
|
|
214
|
+
}
|
|
215
|
+
function buildOperation(controller, route, pathString, registry) {
|
|
216
|
+
const handlerName = route.handlerName;
|
|
217
|
+
const paramMetadata = MetadataRegistry.getParameters(controller).get(handlerName) ?? [];
|
|
218
|
+
const paramtypes = Reflect.getMetadata("design:paramtypes", controller.prototype, handlerName);
|
|
219
|
+
const parameters = [];
|
|
220
|
+
let requestBody;
|
|
221
|
+
const declaredPathParams = /* @__PURE__ */ new Set();
|
|
222
|
+
const pathParamNames = [...pathString.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]);
|
|
223
|
+
for (const param of paramMetadata) if (param.type === ParamType.PARAM && param.name) {
|
|
224
|
+
declaredPathParams.add(param.name);
|
|
225
|
+
parameters.push({
|
|
226
|
+
name: param.name,
|
|
227
|
+
in: "path",
|
|
228
|
+
required: true,
|
|
229
|
+
schema: getParamSchema(param, paramtypes, registry) ?? { type: "string" }
|
|
230
|
+
});
|
|
231
|
+
} else if (param.type === ParamType.QUERY && param.name) parameters.push({
|
|
232
|
+
name: param.name,
|
|
233
|
+
in: "query",
|
|
234
|
+
required: !isParamOptional(param, paramtypes),
|
|
235
|
+
schema: getParamSchema(param, paramtypes, registry) ?? { type: "string" }
|
|
236
|
+
});
|
|
237
|
+
else if (param.type === ParamType.HEADERS && param.name) parameters.push({
|
|
238
|
+
name: param.name,
|
|
239
|
+
in: "header",
|
|
240
|
+
required: !isParamOptional(param, paramtypes),
|
|
241
|
+
schema: getParamSchema(param, paramtypes, registry) ?? { type: "string" }
|
|
242
|
+
});
|
|
243
|
+
else if (param.type === ParamType.BODY) {
|
|
244
|
+
const schema = getParamSchema(param, paramtypes, registry);
|
|
245
|
+
if (schema) requestBody = {
|
|
246
|
+
required: !isParamOptional(param, paramtypes),
|
|
247
|
+
content: { "application/json": { schema } }
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
for (const name of pathParamNames) if (!declaredPathParams.has(name)) parameters.push({
|
|
251
|
+
name,
|
|
252
|
+
in: "path",
|
|
253
|
+
required: true,
|
|
254
|
+
schema: { type: "string" }
|
|
255
|
+
});
|
|
256
|
+
const docMeta = getApiDoc(controller, handlerName);
|
|
257
|
+
const controllerTags = getApiTags(controller) ?? [];
|
|
258
|
+
const handlerTags = getApiTags(controller, handlerName) ?? [];
|
|
259
|
+
const docTags = docMeta?.tags ?? [];
|
|
260
|
+
const mergedTags = [.../* @__PURE__ */ new Set([
|
|
261
|
+
...controllerTags,
|
|
262
|
+
...handlerTags,
|
|
263
|
+
...docTags
|
|
264
|
+
])];
|
|
265
|
+
const responses = { "200": { description: "OK" } };
|
|
266
|
+
const apiResponses = getApiResponses(controller, handlerName) ?? [];
|
|
267
|
+
for (const entry of apiResponses) {
|
|
268
|
+
const key = String(entry.status);
|
|
269
|
+
const resolved = { description: entry.description };
|
|
270
|
+
const schema = resolveResponseSchema(entry.schema, registry);
|
|
271
|
+
if (schema) resolved.content = { "application/json": { schema } };
|
|
272
|
+
responses[key] = resolved;
|
|
273
|
+
}
|
|
274
|
+
const operation = { responses };
|
|
275
|
+
if (parameters.length > 0) operation.parameters = parameters;
|
|
276
|
+
if (requestBody) operation.requestBody = requestBody;
|
|
277
|
+
if (docMeta?.summary) operation.summary = docMeta.summary;
|
|
278
|
+
if (docMeta?.description) operation.description = docMeta.description;
|
|
279
|
+
const operationId = docMeta?.operationId ?? route.name;
|
|
280
|
+
if (operationId) operation.operationId = operationId;
|
|
281
|
+
if (docMeta?.deprecated) operation.deprecated = docMeta.deprecated;
|
|
282
|
+
if (mergedTags.length > 0) operation.tags = mergedTags;
|
|
283
|
+
return operation;
|
|
284
|
+
}
|
|
285
|
+
const VERB_WHITELIST = /* @__PURE__ */ new Set([
|
|
286
|
+
"get",
|
|
287
|
+
"post",
|
|
288
|
+
"put",
|
|
289
|
+
"patch",
|
|
290
|
+
"delete",
|
|
291
|
+
"options",
|
|
292
|
+
"head"
|
|
293
|
+
]);
|
|
294
|
+
function createOpenApiDocument(rootModule, options = {}) {
|
|
295
|
+
const paths = {};
|
|
296
|
+
const globalPrefix = options.globalPrefix ?? "";
|
|
297
|
+
const registry = new ComponentsRegistry();
|
|
298
|
+
const controllers = collectControllers(rootModule);
|
|
299
|
+
for (const controller of controllers) {
|
|
300
|
+
const controllerPath = MetadataRegistry.getControllerPath(controller);
|
|
301
|
+
const routes = MetadataRegistry.getRoutes(controller);
|
|
302
|
+
for (const route of routes) {
|
|
303
|
+
const method = route.method.toLowerCase();
|
|
304
|
+
if (!VERB_WHITELIST.has(method)) continue;
|
|
305
|
+
const pathString = toOpenApiPath(joinPaths(joinPaths(globalPrefix, controllerPath), route.path));
|
|
306
|
+
const operation = buildOperation(controller, route, pathString, registry);
|
|
307
|
+
const pathItem = paths[pathString] ?? {};
|
|
308
|
+
pathItem[method] = operation;
|
|
309
|
+
paths[pathString] = pathItem;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
for (const contributor of getRouteContributors()) {
|
|
313
|
+
if (!contributor.buildOpenApiPaths) continue;
|
|
314
|
+
for (const controller of controllers) {
|
|
315
|
+
const meta = getMetadata(contributor.claimsMetaKey, controller);
|
|
316
|
+
if (meta === void 0) continue;
|
|
317
|
+
const controllerPrefix = MetadataRegistry.getControllerPath(controller);
|
|
318
|
+
const contributedPaths = contributor.buildOpenApiPaths({
|
|
319
|
+
controller,
|
|
320
|
+
meta,
|
|
321
|
+
globalPrefix,
|
|
322
|
+
controllerPrefix
|
|
323
|
+
});
|
|
324
|
+
for (const [pathKey, pathItem] of Object.entries(contributedPaths)) paths[pathKey] = {
|
|
325
|
+
...paths[pathKey] ?? {},
|
|
326
|
+
...pathItem
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const seenTagNames = /* @__PURE__ */ new Set();
|
|
331
|
+
const collectedTagNames = [];
|
|
332
|
+
for (const pathItem of Object.values(paths)) for (const verb of VERB_WHITELIST) {
|
|
333
|
+
const operation = pathItem[verb];
|
|
334
|
+
if (!operation?.tags) continue;
|
|
335
|
+
for (const tagName of operation.tags) {
|
|
336
|
+
if (seenTagNames.has(tagName)) continue;
|
|
337
|
+
seenTagNames.add(tagName);
|
|
338
|
+
collectedTagNames.push(tagName);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const declaredTags = options.tags ?? [];
|
|
342
|
+
const declaredTagNames = new Set(declaredTags.map((t) => t.name));
|
|
343
|
+
const tags = [...declaredTags, ...collectedTagNames.filter((name) => !declaredTagNames.has(name)).map((name) => ({ name }))];
|
|
344
|
+
const document = {
|
|
345
|
+
openapi: "3.1.0",
|
|
346
|
+
info: {
|
|
347
|
+
title: options.info?.title ?? "Vela API",
|
|
348
|
+
version: options.info?.version ?? "1.0.0",
|
|
349
|
+
...options.info?.description ? { description: options.info.description } : {}
|
|
350
|
+
},
|
|
351
|
+
...options.servers?.length ? { servers: options.servers } : {},
|
|
352
|
+
paths
|
|
353
|
+
};
|
|
354
|
+
const schemas = registry.build();
|
|
355
|
+
if (schemas || options.securitySchemes) document.components = {
|
|
356
|
+
...schemas ? { schemas } : {},
|
|
357
|
+
...options.securitySchemes ? { securitySchemes: options.securitySchemes } : {}
|
|
358
|
+
};
|
|
359
|
+
if (options.security?.length) document.security = options.security;
|
|
360
|
+
if (tags.length > 0) document.tags = tags;
|
|
361
|
+
return document;
|
|
362
|
+
}
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region src/container/mixin.ts
|
|
365
|
+
/**
|
|
366
|
+
* Creates a reusable injectable mixin class from a base class.
|
|
367
|
+
* Applies @Injectable() so the returned class can be registered as a provider.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* function RoleGuardMixin(role: string) {
|
|
372
|
+
* class MixedRoleGuard implements CanActivate {
|
|
373
|
+
* canActivate(ctx: ExecutionContext) {
|
|
374
|
+
* return ctx.getRequest().headers.get('x-role') === role;
|
|
375
|
+
* }
|
|
376
|
+
* }
|
|
377
|
+
* return mixin(MixedRoleGuard);
|
|
378
|
+
* }
|
|
379
|
+
*
|
|
380
|
+
* const AdminGuard = RoleGuardMixin('admin');
|
|
381
|
+
*
|
|
382
|
+
* @UseGuards(AdminGuard)
|
|
383
|
+
* @Get('/admin')
|
|
384
|
+
* adminOnly() { ... }
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
function mixin(mixinClass) {
|
|
388
|
+
Injectable()(mixinClass);
|
|
389
|
+
return mixinClass;
|
|
390
|
+
}
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region src/http/lazy-param.decorator.ts
|
|
393
|
+
const CUSTOM_PARAM_TYPE = "custom";
|
|
394
|
+
/**
|
|
395
|
+
* Factory for parameter decorators whose value materializes lazily — the
|
|
396
|
+
* factory does not run during argument extraction; it runs the first time
|
|
397
|
+
* the handler reads a property on the resolved value.
|
|
398
|
+
*
|
|
399
|
+
* Why this exists: vela's argument resolver runs *before* guards
|
|
400
|
+
* (handler-executor order: extract args → guards → handler). A custom
|
|
401
|
+
* `createParamDecorator` factory that depends on guard-populated state
|
|
402
|
+
* (e.g. a value a guard places into `REQUEST_CONTEXT`) therefore observes
|
|
403
|
+
* an empty slot. `createLazyParamDecorator` defers factory execution to
|
|
404
|
+
* first property access on the proxied result, by which point guards have
|
|
405
|
+
* run and the slot is populated.
|
|
406
|
+
*
|
|
407
|
+
* The proxy explicitly short-circuits `prop === 'then'` so `await value`
|
|
408
|
+
* does not consider the proxy a thenable, which would otherwise trigger
|
|
409
|
+
* eager resolution. This single invariant is what makes the helper safe to
|
|
410
|
+
* pass through `async` boundaries without surprise.
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```ts
|
|
414
|
+
* const CurrentUser = createLazyParamDecorator(
|
|
415
|
+
* (_data: unknown, ctx: ExecutionContext) => {
|
|
416
|
+
* const reqCtx = ctx.getContext().get('container').resolve(REQUEST_CONTEXT);
|
|
417
|
+
* return reqCtx.get('user'); // populated by AuthGuard
|
|
418
|
+
* },
|
|
419
|
+
* );
|
|
420
|
+
*
|
|
421
|
+
* @UseGuards(AuthGuard)
|
|
422
|
+
* @Get('/me')
|
|
423
|
+
* me(@CurrentUser() user: User) {
|
|
424
|
+
* return { id: user.id }; // factory runs here, after AuthGuard
|
|
425
|
+
* }
|
|
426
|
+
* ```
|
|
427
|
+
*/
|
|
428
|
+
function createLazyParamDecorator(factory) {
|
|
429
|
+
return (data, ...pipes) => {
|
|
430
|
+
return (target, propertyKey, parameterIndex) => {
|
|
431
|
+
if (propertyKey === void 0) throw new Error("Parameter decorators can only be used on method parameters");
|
|
432
|
+
MetadataRegistry.addParameter(target.constructor, propertyKey, {
|
|
433
|
+
index: parameterIndex,
|
|
434
|
+
type: CUSTOM_PARAM_TYPE,
|
|
435
|
+
name: void 0,
|
|
436
|
+
factory: (_unused, ctx) => {
|
|
437
|
+
const execCtx = buildExecutionContext(ctx, target.constructor, propertyKey);
|
|
438
|
+
return createLazyProxy(() => factory(data, execCtx));
|
|
439
|
+
},
|
|
440
|
+
...pipes.length > 0 ? { pipes } : {}
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function createLazyProxy(produce) {
|
|
446
|
+
let resolved = false;
|
|
447
|
+
let value;
|
|
448
|
+
const materialize = () => {
|
|
449
|
+
if (!resolved) {
|
|
450
|
+
value = produce();
|
|
451
|
+
resolved = true;
|
|
452
|
+
}
|
|
453
|
+
return value;
|
|
454
|
+
};
|
|
455
|
+
return new Proxy(Object.create(null), {
|
|
456
|
+
get(_t, prop, receiver) {
|
|
457
|
+
if (prop === "then") return void 0;
|
|
458
|
+
const real = materialize();
|
|
459
|
+
if (real === null || real === void 0) return void 0;
|
|
460
|
+
const descriptor = Reflect.get(real, prop, receiver);
|
|
461
|
+
if (typeof descriptor === "function") return descriptor.bind(real);
|
|
462
|
+
return descriptor;
|
|
463
|
+
},
|
|
464
|
+
has(_t, prop) {
|
|
465
|
+
const real = materialize();
|
|
466
|
+
return real !== null && real !== void 0 && Reflect.has(real, prop);
|
|
467
|
+
},
|
|
468
|
+
ownKeys() {
|
|
469
|
+
const real = materialize();
|
|
470
|
+
if (real === null || real === void 0) return [];
|
|
471
|
+
return Reflect.ownKeys(real);
|
|
472
|
+
},
|
|
473
|
+
getOwnPropertyDescriptor(_t, prop) {
|
|
474
|
+
const real = materialize();
|
|
475
|
+
if (real === null || real === void 0) return void 0;
|
|
476
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(real, prop);
|
|
477
|
+
if (descriptor) descriptor.configurable = true;
|
|
478
|
+
return descriptor;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/http/ambient.ts
|
|
484
|
+
/**
|
|
485
|
+
* Returns Hono's `contextStorage()` middleware. Register it as the FIRST global
|
|
486
|
+
* middleware so `getCurrentContainer()` works everywhere downstream. When using
|
|
487
|
+
* `VelaFactory.create(module, { ambientContainer: true })` this is wired
|
|
488
|
+
* automatically — call this only for manual/raw Hono setups.
|
|
489
|
+
*/
|
|
490
|
+
function enableAmbientContainer() {
|
|
491
|
+
return contextStorage();
|
|
492
|
+
}
|
|
493
|
+
function tryGetContext() {
|
|
494
|
+
try {
|
|
495
|
+
return getContext();
|
|
496
|
+
} catch {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* The current request's DI container. Throws with actionable guidance if
|
|
502
|
+
* ambient access isn't enabled or this runs outside a request.
|
|
503
|
+
*/
|
|
504
|
+
function getCurrentContainer() {
|
|
505
|
+
const container = tryGetContext()?.get("container");
|
|
506
|
+
if (!container) throw new Error("getCurrentContainer() is unavailable: enable ambient access via VelaFactory.create(module, { ambientContainer: true }) (or app.use(enableAmbientContainer())) and only call it within a request.");
|
|
507
|
+
return container;
|
|
508
|
+
}
|
|
509
|
+
/** The current request's {@link RequestContext} (via the ambient container). */
|
|
510
|
+
function getCurrentRequestContext() {
|
|
511
|
+
return getCurrentContainer().resolve(REQUEST_CONTEXT);
|
|
512
|
+
}
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/http/request-container.ts
|
|
515
|
+
/**
|
|
516
|
+
* Returns the request-scoped child container for the current request.
|
|
517
|
+
*
|
|
518
|
+
* `@Inject(Container)` resolves the ROOT container (request children share the
|
|
519
|
+
* provider map and never rebind `Container`), so module authors who need
|
|
520
|
+
* request-scoped resolution from inside a handler, param-decorator factory, or
|
|
521
|
+
* scoped middleware must read the child seeded by RouteManager instead. The
|
|
522
|
+
* child is created before guards, pipes, params, and handlers run, so it is
|
|
523
|
+
* always present on the Vela request path.
|
|
524
|
+
*
|
|
525
|
+
* Throws outside a Vela-managed request rather than materializing an orphan
|
|
526
|
+
* child (mirrors the REQUEST_CONTEXT fail-fast).
|
|
527
|
+
*/
|
|
528
|
+
function getRequestContainer(c) {
|
|
529
|
+
const container = c.get("container");
|
|
530
|
+
if (!container) throw new Error("getRequestContainer(c) can only be called inside a Vela-managed request — the request child container is seeded by RouteManager when the request enters the pipeline.");
|
|
531
|
+
return container;
|
|
532
|
+
}
|
|
533
|
+
//#endregion
|
|
534
|
+
//#region src/services/logger.ts
|
|
535
|
+
var _Logger;
|
|
536
|
+
const LogLevel = {
|
|
537
|
+
VERBOSE: 0,
|
|
538
|
+
DEBUG: 1,
|
|
539
|
+
LOG: 2,
|
|
540
|
+
WARN: 3,
|
|
541
|
+
ERROR: 4,
|
|
542
|
+
SILENT: 5
|
|
543
|
+
};
|
|
544
|
+
const defaultWriter = (level, line, ...rest) => {
|
|
545
|
+
if (level === "ERROR") return console.error(line, ...rest);
|
|
546
|
+
if (level === "WARN") return console.warn(line, ...rest);
|
|
547
|
+
if (level === "DEBUG" || level === "VERBOSE") return console.debug(line, ...rest);
|
|
548
|
+
return console.log(line, ...rest);
|
|
549
|
+
};
|
|
550
|
+
function formatValue(v) {
|
|
551
|
+
if (typeof v === "string") return /[\s="\\]/.test(v) ? JSON.stringify(v) : v;
|
|
552
|
+
if (typeof v === "number" || typeof v === "boolean") return String(v);
|
|
553
|
+
try {
|
|
554
|
+
return JSON.stringify(v);
|
|
555
|
+
} catch {
|
|
556
|
+
return String(v);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
let Logger = class Logger {
|
|
560
|
+
static {
|
|
561
|
+
_Logger = this;
|
|
562
|
+
}
|
|
563
|
+
static level = LogLevel.LOG;
|
|
564
|
+
static globalLogger;
|
|
565
|
+
static globalContextProviders = [];
|
|
566
|
+
static globalWriter = defaultWriter;
|
|
567
|
+
context;
|
|
568
|
+
instanceContextProviders = [];
|
|
569
|
+
instanceWriter;
|
|
570
|
+
static setLogLevel(level) {
|
|
571
|
+
_Logger.level = level;
|
|
572
|
+
}
|
|
573
|
+
static overrideLogger(logger) {
|
|
574
|
+
_Logger.globalLogger = logger;
|
|
575
|
+
}
|
|
576
|
+
/** Register a context provider run on every log line from every logger. */
|
|
577
|
+
static addContextProvider(provider) {
|
|
578
|
+
_Logger.globalContextProviders.push(provider);
|
|
579
|
+
}
|
|
580
|
+
/** Remove all registered global context providers. */
|
|
581
|
+
static clearContextProviders() {
|
|
582
|
+
_Logger.globalContextProviders = [];
|
|
583
|
+
}
|
|
584
|
+
/** Replace the default console writer. Useful on edge runtimes that have
|
|
585
|
+
* a different output sink (e.g. `env.LOGS.writeDataPoint` on Workers). */
|
|
586
|
+
static setWriter(writer) {
|
|
587
|
+
_Logger.globalWriter = writer;
|
|
588
|
+
}
|
|
589
|
+
/** Restore the default console-based writer. */
|
|
590
|
+
static resetWriter() {
|
|
591
|
+
_Logger.globalWriter = defaultWriter;
|
|
592
|
+
}
|
|
593
|
+
constructor(context) {
|
|
594
|
+
if (context) this.context = context;
|
|
595
|
+
}
|
|
596
|
+
setContext(context) {
|
|
597
|
+
this.context = context;
|
|
598
|
+
}
|
|
599
|
+
/** Add a context provider that runs only for THIS logger instance.
|
|
600
|
+
* Children created via extend() inherit these providers by copy. */
|
|
601
|
+
addContextProvider(provider) {
|
|
602
|
+
this.instanceContextProviders.push(provider);
|
|
603
|
+
return this;
|
|
604
|
+
}
|
|
605
|
+
/** Override the writer for this logger (and any extend() children). */
|
|
606
|
+
setWriter(writer) {
|
|
607
|
+
this.instanceWriter = writer;
|
|
608
|
+
return this;
|
|
609
|
+
}
|
|
610
|
+
/** Create a child logger with a nested namespace. Context becomes
|
|
611
|
+
* `parent:child`; instance-level providers and writers are inherited
|
|
612
|
+
* by copy so later mutations on either logger stay isolated. */
|
|
613
|
+
extend(namespace) {
|
|
614
|
+
const newContext = this.context ? `${this.context}:${namespace}` : namespace;
|
|
615
|
+
const child = new _Logger(newContext);
|
|
616
|
+
child.instanceContextProviders = [...this.instanceContextProviders];
|
|
617
|
+
if (this.instanceWriter) child.instanceWriter = this.instanceWriter;
|
|
618
|
+
return child;
|
|
619
|
+
}
|
|
620
|
+
log(message, ...optionalParams) {
|
|
621
|
+
this.emit("LOG", LogLevel.LOG, message, optionalParams);
|
|
622
|
+
}
|
|
623
|
+
error(message, ...optionalParams) {
|
|
624
|
+
this.emit("ERROR", LogLevel.ERROR, message, optionalParams);
|
|
625
|
+
}
|
|
626
|
+
warn(message, ...optionalParams) {
|
|
627
|
+
this.emit("WARN", LogLevel.WARN, message, optionalParams);
|
|
628
|
+
}
|
|
629
|
+
debug(message, ...optionalParams) {
|
|
630
|
+
this.emit("DEBUG", LogLevel.DEBUG, message, optionalParams);
|
|
631
|
+
}
|
|
632
|
+
verbose(message, ...optionalParams) {
|
|
633
|
+
this.emit("VERBOSE", LogLevel.VERBOSE, message, optionalParams);
|
|
634
|
+
}
|
|
635
|
+
emit(levelName, levelValue, message, rest) {
|
|
636
|
+
if (_Logger.level > levelValue) return;
|
|
637
|
+
if (_Logger.globalLogger === false) return;
|
|
638
|
+
if (_Logger.globalLogger) {
|
|
639
|
+
const method = levelName.toLowerCase();
|
|
640
|
+
const fn = _Logger.globalLogger[method];
|
|
641
|
+
if (fn) fn.call(_Logger.globalLogger, message, ...rest);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
const line = this.formatMessage(levelName, message);
|
|
645
|
+
(this.instanceWriter ?? _Logger.globalWriter)(levelName, line, ...rest);
|
|
646
|
+
}
|
|
647
|
+
formatMessage(level, message) {
|
|
648
|
+
return `[Vela] ${(/* @__PURE__ */ new Date()).toISOString()} ${level}${this.context ? ` [${this.context}]` : ""} ${message}${this.formatContextObj(this.collectContext())}`;
|
|
649
|
+
}
|
|
650
|
+
collectContext() {
|
|
651
|
+
const result = {};
|
|
652
|
+
for (const provider of _Logger.globalContextProviders) try {
|
|
653
|
+
Object.assign(result, provider());
|
|
654
|
+
} catch {}
|
|
655
|
+
for (const provider of this.instanceContextProviders) try {
|
|
656
|
+
Object.assign(result, provider());
|
|
657
|
+
} catch {}
|
|
658
|
+
return result;
|
|
659
|
+
}
|
|
660
|
+
formatContextObj(obj) {
|
|
661
|
+
const parts = [];
|
|
662
|
+
for (const key of Object.keys(obj)) {
|
|
663
|
+
const value = obj[key];
|
|
664
|
+
if (value === void 0 || value === null) continue;
|
|
665
|
+
parts.push(`${key}=${formatValue(value)}`);
|
|
666
|
+
}
|
|
667
|
+
return parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
Logger = _Logger = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [String])], Logger);
|
|
671
|
+
//#endregion
|
|
672
|
+
//#region src/config/config.store.ts
|
|
673
|
+
/** Prototype-pollution guard for dot-notation segments. */
|
|
674
|
+
const DANGEROUS_KEYS = /* @__PURE__ */ new Set([
|
|
675
|
+
"__proto__",
|
|
676
|
+
"constructor",
|
|
677
|
+
"prototype"
|
|
678
|
+
]);
|
|
679
|
+
function runSchema(schema, config) {
|
|
680
|
+
if (typeof schema === "function") {
|
|
681
|
+
schema(config);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (schema && typeof schema.parse === "function") {
|
|
685
|
+
schema.parse(config);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
throw new Error("ConfigModule `validateSchema` must be a function or expose a `parse()` method");
|
|
689
|
+
}
|
|
690
|
+
let ConfigStore = class ConfigStore {
|
|
691
|
+
container;
|
|
692
|
+
config;
|
|
693
|
+
validateSchema;
|
|
694
|
+
namespaceKeys = /* @__PURE__ */ new Map();
|
|
695
|
+
cache = /* @__PURE__ */ new Map();
|
|
696
|
+
validated = false;
|
|
697
|
+
validationError;
|
|
698
|
+
constructor(container, config = {}, namespaces = [], validateSchema) {
|
|
699
|
+
this.container = container;
|
|
700
|
+
this.config = config;
|
|
701
|
+
this.validateSchema = validateSchema;
|
|
702
|
+
for (const ns of namespaces) this.namespaceKeys.set(ns.namespace, ns.KEY);
|
|
703
|
+
}
|
|
704
|
+
/** Read a value by dot-notation path; `undefined` if absent. */
|
|
705
|
+
get(path) {
|
|
706
|
+
this.ensureValidated();
|
|
707
|
+
return this.read(path);
|
|
708
|
+
}
|
|
709
|
+
/** Read a value by dot-notation path; throws if absent. */
|
|
710
|
+
getOrThrow(path) {
|
|
711
|
+
const value = this.get(path);
|
|
712
|
+
if (value === void 0) throw new Error(`Configuration key "${path}" was not found`);
|
|
713
|
+
return value;
|
|
714
|
+
}
|
|
715
|
+
/** Whether a dot-notation path resolves to a defined value. */
|
|
716
|
+
has(path) {
|
|
717
|
+
this.ensureValidated();
|
|
718
|
+
return this.read(path) !== void 0;
|
|
719
|
+
}
|
|
720
|
+
/** The full merged config object (flat record + resolved namespaces). */
|
|
721
|
+
all() {
|
|
722
|
+
this.ensureValidated();
|
|
723
|
+
return this.merged();
|
|
724
|
+
}
|
|
725
|
+
read(path) {
|
|
726
|
+
const [head, ...rest] = path.split(".");
|
|
727
|
+
if (head === void 0 || DANGEROUS_KEYS.has(head)) return void 0;
|
|
728
|
+
let current = this.namespaceKeys.has(head) ? this.resolveNamespace(head) : this.config[head];
|
|
729
|
+
for (const key of rest) {
|
|
730
|
+
if (DANGEROUS_KEYS.has(key)) return void 0;
|
|
731
|
+
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
732
|
+
current = current[key];
|
|
733
|
+
}
|
|
734
|
+
return current;
|
|
735
|
+
}
|
|
736
|
+
/** Resolve a namespace's KEY through the container on first use, then cache. */
|
|
737
|
+
resolveNamespace(namespace) {
|
|
738
|
+
if (this.cache.has(namespace)) return this.cache.get(namespace);
|
|
739
|
+
const key = this.namespaceKeys.get(namespace);
|
|
740
|
+
const value = key === void 0 ? void 0 : this.container.resolve(key);
|
|
741
|
+
this.cache.set(namespace, value);
|
|
742
|
+
return value;
|
|
743
|
+
}
|
|
744
|
+
merged() {
|
|
745
|
+
const out = { ...this.config };
|
|
746
|
+
for (const namespace of this.namespaceKeys.keys()) out[namespace] = this.resolveNamespace(namespace);
|
|
747
|
+
return out;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Validate the merged config once, on first read. Deferred (not at bootstrap)
|
|
751
|
+
* because the merged shape needs namespace factories — and their env — which
|
|
752
|
+
* are only available after bootstrap on edge runtimes.
|
|
753
|
+
*/
|
|
754
|
+
ensureValidated() {
|
|
755
|
+
if (this.validated) {
|
|
756
|
+
if (this.validationError) throw this.validationError;
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
this.validated = true;
|
|
760
|
+
if (!this.validateSchema) return;
|
|
761
|
+
try {
|
|
762
|
+
runSchema(this.validateSchema, this.merged());
|
|
763
|
+
} catch (err) {
|
|
764
|
+
this.validationError = err;
|
|
765
|
+
throw err;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
ConfigStore = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [
|
|
770
|
+
typeof Pick === "undefined" ? Object : Pick,
|
|
771
|
+
typeof Record === "undefined" ? Object : Record,
|
|
772
|
+
Array,
|
|
773
|
+
Object
|
|
774
|
+
])], ConfigStore);
|
|
775
|
+
//#endregion
|
|
776
|
+
//#region src/config/config.service.ts
|
|
777
|
+
let ConfigService = class ConfigService {
|
|
778
|
+
store;
|
|
779
|
+
constructor(store) {
|
|
780
|
+
this.store = store;
|
|
781
|
+
}
|
|
782
|
+
get(path, defaultValue) {
|
|
783
|
+
const value = this.store.get(path);
|
|
784
|
+
return value === void 0 ? defaultValue : value;
|
|
785
|
+
}
|
|
786
|
+
/** Read a config value; throws when the path is absent. */
|
|
787
|
+
getOrThrow(path) {
|
|
788
|
+
return this.store.getOrThrow(path);
|
|
789
|
+
}
|
|
790
|
+
/** Whether a config path resolves to a defined value. */
|
|
791
|
+
has(path) {
|
|
792
|
+
return this.store.has(path);
|
|
793
|
+
}
|
|
794
|
+
/** The full merged config object (flat record + resolved namespaces). */
|
|
795
|
+
getAll() {
|
|
796
|
+
return this.store.all();
|
|
797
|
+
}
|
|
798
|
+
};
|
|
799
|
+
ConfigService = __decorate([
|
|
800
|
+
Injectable(),
|
|
801
|
+
__decorateParam(0, Inject(ConfigStore)),
|
|
802
|
+
__decorateMetadata("design:paramtypes", [typeof ConfigStore === "undefined" ? Object : ConfigStore])
|
|
803
|
+
], ConfigService);
|
|
804
|
+
//#endregion
|
|
805
|
+
//#region src/config/config.module.ts
|
|
806
|
+
/**
|
|
807
|
+
* Carrier for the namespace `asProvider()` KEY providers ONLY. Split out of
|
|
808
|
+
* ConfigModule and marked `lazy: true` so those factories — which inject
|
|
809
|
+
* `CONFIG_ENV`, live per-request on edge runtimes — never run at bootstrap.
|
|
810
|
+
* ConfigModule itself stays EAGER (see below).
|
|
811
|
+
*/
|
|
812
|
+
var ConfigNamespacesModule = class {};
|
|
813
|
+
/**
|
|
814
|
+
* Build the lazy sub-module holding one KEY provider per namespace. Its `key`
|
|
815
|
+
* is derived from the owning ConfigModule instance key so multiple ConfigModule
|
|
816
|
+
* instances get distinct sub-module instances (no import-dedup collision).
|
|
817
|
+
*/
|
|
818
|
+
function namespacesSubModule(load, key) {
|
|
819
|
+
return {
|
|
820
|
+
module: ConfigNamespacesModule,
|
|
821
|
+
key: `config-ns:${key}`,
|
|
822
|
+
lazy: true,
|
|
823
|
+
providers: load.map((namespace) => namespace.asProvider()),
|
|
824
|
+
exports: load.map((namespace) => namespace.KEY)
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
const { ConfigurableModuleClass: ConfigurableModuleClass$5 } = defineModule({
|
|
828
|
+
name: "Config",
|
|
829
|
+
setup: ({ OPTIONS, options, key }) => {
|
|
830
|
+
const load = options.load ?? [];
|
|
831
|
+
const { validateSchema } = options;
|
|
832
|
+
return {
|
|
833
|
+
imports: load.length > 0 ? [namespacesSubModule(load, key)] : [],
|
|
834
|
+
providers: [
|
|
835
|
+
{
|
|
836
|
+
provide: CONFIG_OPTIONS,
|
|
837
|
+
useFactory: (opts) => opts.validate ? opts.validate(opts.config ?? {}) : opts.config ?? {},
|
|
838
|
+
inject: [OPTIONS]
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
provide: ConfigStore,
|
|
842
|
+
useFactory: (container, config) => new ConfigStore(container, config, load, validateSchema),
|
|
843
|
+
inject: [Container, CONFIG_OPTIONS]
|
|
844
|
+
},
|
|
845
|
+
ConfigService
|
|
846
|
+
],
|
|
847
|
+
exports: [
|
|
848
|
+
ConfigService,
|
|
849
|
+
ConfigStore,
|
|
850
|
+
CONFIG_OPTIONS,
|
|
851
|
+
...load.map((n) => n.KEY)
|
|
852
|
+
]
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
var ConfigModule = class extends ConfigurableModuleClass$5 {
|
|
857
|
+
/**
|
|
858
|
+
* Preserve (a) per-call generic inference over the flat config record and
|
|
859
|
+
* (b) the eager-validation contract: `validate` runs at call time so bad
|
|
860
|
+
* config fails fast, then is stripped so the derived `CONFIG_OPTIONS`
|
|
861
|
+
* provider is a passthrough (no double validation). `validateSchema` (the
|
|
862
|
+
* merged-config schema) is deferred to first read — its input needs env.
|
|
863
|
+
*/
|
|
864
|
+
static forRoot(options = {}) {
|
|
865
|
+
const validatedConfig = options.validate ? options.validate(options.config ?? {}) : options.config;
|
|
866
|
+
const { validate: _validate, ...rest } = options;
|
|
867
|
+
return super.forRoot({
|
|
868
|
+
...rest,
|
|
869
|
+
config: validatedConfig
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
//#endregion
|
|
874
|
+
//#region src/config/register-as.ts
|
|
875
|
+
/**
|
|
876
|
+
* Create a namespaced configuration factory (NestJS `registerAs` parity).
|
|
877
|
+
*
|
|
878
|
+
* The `KEY` is minted with `Symbol.for` so it keeps a stable identity across
|
|
879
|
+
* module re-evaluation (HMR / repeated imports) — a fresh `InjectionToken`
|
|
880
|
+
* would mint a new identity each eval and break dedup. It is typed as
|
|
881
|
+
* `InjectionToken<TConfig>` purely for injection-site DX.
|
|
882
|
+
*
|
|
883
|
+
* @example
|
|
884
|
+
* ```ts
|
|
885
|
+
* export const dbConfig = registerAs('database', (env: Env) => ({
|
|
886
|
+
* url: env.DATABASE_URL,
|
|
887
|
+
* pool: 10,
|
|
888
|
+
* }));
|
|
889
|
+
* // ConfigModule.forRoot({ load: [dbConfig] });
|
|
890
|
+
* // cfg.get('database.url'); // via ConfigService
|
|
891
|
+
* // constructor(@Inject(dbConfig.KEY) db: InferConfigType<typeof dbConfig>) {}
|
|
892
|
+
* ```
|
|
893
|
+
*/
|
|
894
|
+
function registerAs(namespace, factory) {
|
|
895
|
+
const KEY = Symbol.for(`vela:config:${namespace}`);
|
|
896
|
+
return {
|
|
897
|
+
KEY,
|
|
898
|
+
namespace,
|
|
899
|
+
factory,
|
|
900
|
+
asProvider() {
|
|
901
|
+
return {
|
|
902
|
+
provide: KEY,
|
|
903
|
+
useFactory: factory,
|
|
904
|
+
inject: [CONFIG_ENV]
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
//#endregion
|
|
910
|
+
//#region src/fetch/fetch.service.ts
|
|
911
|
+
const HTTP_MODULE_OPTIONS = new InjectionToken("HTTP_MODULE_OPTIONS");
|
|
912
|
+
var HttpRequestException = class extends Error {
|
|
913
|
+
status;
|
|
914
|
+
statusText;
|
|
915
|
+
response;
|
|
916
|
+
constructor(status, statusText, response) {
|
|
917
|
+
super(`HTTP ${status} ${statusText}`);
|
|
918
|
+
this.status = status;
|
|
919
|
+
this.statusText = statusText;
|
|
920
|
+
this.response = response;
|
|
921
|
+
this.name = "HttpRequestException";
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
let HttpService = class HttpService {
|
|
925
|
+
baseURL;
|
|
926
|
+
defaultHeaders;
|
|
927
|
+
defaultTimeout;
|
|
928
|
+
constructor(options) {
|
|
929
|
+
const opts = options ?? {};
|
|
930
|
+
this.baseURL = opts.baseURL ?? "";
|
|
931
|
+
this.defaultHeaders = opts.headers ?? {};
|
|
932
|
+
this.defaultTimeout = opts.timeout;
|
|
933
|
+
}
|
|
934
|
+
get(url, config) {
|
|
935
|
+
return this.request({
|
|
936
|
+
method: "GET",
|
|
937
|
+
url,
|
|
938
|
+
...config
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
post(url, body, config) {
|
|
942
|
+
return this.request({
|
|
943
|
+
method: "POST",
|
|
944
|
+
url,
|
|
945
|
+
body,
|
|
946
|
+
...config
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
put(url, body, config) {
|
|
950
|
+
return this.request({
|
|
951
|
+
method: "PUT",
|
|
952
|
+
url,
|
|
953
|
+
body,
|
|
954
|
+
...config
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
patch(url, body, config) {
|
|
958
|
+
return this.request({
|
|
959
|
+
method: "PATCH",
|
|
960
|
+
url,
|
|
961
|
+
body,
|
|
962
|
+
...config
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
delete(url, config) {
|
|
966
|
+
return this.request({
|
|
967
|
+
method: "DELETE",
|
|
968
|
+
url,
|
|
969
|
+
...config
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
head(url, config) {
|
|
973
|
+
return this.request({
|
|
974
|
+
method: "HEAD",
|
|
975
|
+
url,
|
|
976
|
+
...config
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
async request(config) {
|
|
980
|
+
const fullUrl = this.buildUrl(config.url, config.params);
|
|
981
|
+
const headers = {
|
|
982
|
+
...this.defaultHeaders,
|
|
983
|
+
...config.headers
|
|
984
|
+
};
|
|
985
|
+
const init = {
|
|
986
|
+
method: config.method,
|
|
987
|
+
headers
|
|
988
|
+
};
|
|
989
|
+
if (config.body !== void 0) if (typeof config.body === "string" || config.body instanceof FormData) init.body = config.body;
|
|
990
|
+
else {
|
|
991
|
+
init.body = JSON.stringify(config.body);
|
|
992
|
+
if (!headers["Content-Type"] && !headers["content-type"]) headers["Content-Type"] = "application/json";
|
|
993
|
+
}
|
|
994
|
+
const timeout = config.timeout ?? this.defaultTimeout;
|
|
995
|
+
if (timeout !== void 0) init.signal = AbortSignal.timeout(timeout);
|
|
996
|
+
const response = await fetch(fullUrl, init);
|
|
997
|
+
if (!response.ok) throw new HttpRequestException(response.status, response.statusText, response);
|
|
998
|
+
return {
|
|
999
|
+
data: await this.parseBody(response),
|
|
1000
|
+
status: response.status,
|
|
1001
|
+
statusText: response.statusText,
|
|
1002
|
+
headers: response.headers
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
buildUrl(url, params) {
|
|
1006
|
+
const base = this.baseURL ? `${this.baseURL}${url}` : url;
|
|
1007
|
+
if (!params || Object.keys(params).length === 0) return base;
|
|
1008
|
+
return `${base}?${new URLSearchParams(Object.entries(params).map(([k, v]) => [k, String(v)])).toString()}`;
|
|
1009
|
+
}
|
|
1010
|
+
async parseBody(response) {
|
|
1011
|
+
if (response.status === 204 || response.headers.get("content-length") === "0") return;
|
|
1012
|
+
if ((response.headers.get("content-type") ?? "").includes("application/json")) return response.json();
|
|
1013
|
+
return response.text();
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
HttpService = __decorate([
|
|
1017
|
+
Injectable(),
|
|
1018
|
+
__decorateParam(0, Optional()),
|
|
1019
|
+
__decorateParam(0, Inject(HTTP_MODULE_OPTIONS)),
|
|
1020
|
+
__decorateMetadata("design:paramtypes", [Object])
|
|
1021
|
+
], HttpService);
|
|
1022
|
+
//#endregion
|
|
1023
|
+
//#region src/fetch/fetch.module.ts
|
|
1024
|
+
const { ConfigurableModuleClass: ConfigurableModuleClass$4 } = new ConfigurableModuleBuilder({
|
|
1025
|
+
moduleName: "Http",
|
|
1026
|
+
optionsInjectionToken: HTTP_MODULE_OPTIONS
|
|
1027
|
+
}).build();
|
|
1028
|
+
let HttpModule = class HttpModule extends ConfigurableModuleClass$4 {};
|
|
1029
|
+
HttpModule = __decorate([Module({
|
|
1030
|
+
providers: [{
|
|
1031
|
+
provide: HTTP_MODULE_OPTIONS,
|
|
1032
|
+
useValue: {}
|
|
1033
|
+
}, HttpService],
|
|
1034
|
+
exports: [HttpService, HTTP_MODULE_OPTIONS]
|
|
1035
|
+
})], HttpModule);
|
|
1036
|
+
//#endregion
|
|
1037
|
+
//#region src/cors/cors.tokens.ts
|
|
1038
|
+
const CORS_OPTIONS = new InjectionToken("CORS_OPTIONS");
|
|
1039
|
+
//#endregion
|
|
1040
|
+
//#region src/cors/cors.module.ts
|
|
1041
|
+
function buildCorsMiddleware(options) {
|
|
1042
|
+
const corsMiddleware = cors({
|
|
1043
|
+
origin: options.origin ?? "*",
|
|
1044
|
+
allowMethods: options.allowMethods,
|
|
1045
|
+
allowHeaders: options.allowHeaders,
|
|
1046
|
+
exposeHeaders: options.exposeHeaders,
|
|
1047
|
+
credentials: options.credentials,
|
|
1048
|
+
maxAge: options.maxAge
|
|
1049
|
+
});
|
|
1050
|
+
return { use: (c, next) => corsMiddleware(c, next) };
|
|
1051
|
+
}
|
|
1052
|
+
const { ConfigurableModuleClass: ConfigurableModuleClass$3 } = defineModule({
|
|
1053
|
+
name: "Cors",
|
|
1054
|
+
optionsToken: CORS_OPTIONS,
|
|
1055
|
+
setup: ({ OPTIONS }) => ({
|
|
1056
|
+
providers: [{
|
|
1057
|
+
provide: APP_MIDDLEWARE,
|
|
1058
|
+
useFactory: (options) => buildCorsMiddleware(options),
|
|
1059
|
+
inject: [OPTIONS]
|
|
1060
|
+
}],
|
|
1061
|
+
exports: [OPTIONS]
|
|
1062
|
+
})
|
|
1063
|
+
});
|
|
1064
|
+
var CorsModule = class extends ConfigurableModuleClass$3 {};
|
|
1065
|
+
//#endregion
|
|
1066
|
+
//#region src/pipeline/reflector.ts
|
|
1067
|
+
/**
|
|
1068
|
+
* Decorator that attaches custom metadata to a class or method.
|
|
1069
|
+
* Read via Reflector in guards/interceptors.
|
|
1070
|
+
*
|
|
1071
|
+
* @example
|
|
1072
|
+
* ```ts
|
|
1073
|
+
* const Roles = (...roles: string[]) => SetMetadata('roles', roles);
|
|
1074
|
+
*
|
|
1075
|
+
* @Controller('/admin')
|
|
1076
|
+
* @Roles('admin')
|
|
1077
|
+
* class AdminController { ... }
|
|
1078
|
+
* ```
|
|
1079
|
+
*/
|
|
1080
|
+
function SetMetadata(key, value) {
|
|
1081
|
+
return (target, propertyKey) => {
|
|
1082
|
+
if (propertyKey !== void 0) MetadataRegistry.setCustomHandlerMeta(target.constructor, propertyKey, key, value);
|
|
1083
|
+
else MetadataRegistry.setCustomClassMeta(target, key, value);
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Reads custom metadata set by @SetMetadata().
|
|
1088
|
+
* Use in guards/interceptors via ExecutionContext.
|
|
1089
|
+
*
|
|
1090
|
+
* @example
|
|
1091
|
+
* ```ts
|
|
1092
|
+
* class RolesGuard implements CanActivate {
|
|
1093
|
+
* private reflector = new Reflector();
|
|
1094
|
+
*
|
|
1095
|
+
* canActivate(context: ExecutionContext): boolean {
|
|
1096
|
+
* const roles = this.reflector.get<string[]>('roles', context);
|
|
1097
|
+
* if (!roles) return true;
|
|
1098
|
+
* const user = ...; // extract from request
|
|
1099
|
+
* return roles.some(r => user.roles.includes(r));
|
|
1100
|
+
* }
|
|
1101
|
+
* }
|
|
1102
|
+
* ```
|
|
1103
|
+
*/
|
|
1104
|
+
var Reflector = class {
|
|
1105
|
+
/**
|
|
1106
|
+
* Create a type-safe decorator that sets metadata with a typed key.
|
|
1107
|
+
*
|
|
1108
|
+
* @example
|
|
1109
|
+
* ```ts
|
|
1110
|
+
* const Roles = Reflector.createDecorator<string[]>();
|
|
1111
|
+
* // Roles(['admin']) — class or method decorator
|
|
1112
|
+
* // reflector.get(Roles, context) — typed as string[] | undefined
|
|
1113
|
+
* ```
|
|
1114
|
+
*/
|
|
1115
|
+
static createDecorator(options) {
|
|
1116
|
+
const key = options?.key ?? `vela:custom:${crypto.randomUUID()}`;
|
|
1117
|
+
const decorator = (value) => SetMetadata(key, value);
|
|
1118
|
+
decorator.KEY = key;
|
|
1119
|
+
return decorator;
|
|
1120
|
+
}
|
|
1121
|
+
resolveKey(keyOrDecorator) {
|
|
1122
|
+
return typeof keyOrDecorator === "string" ? keyOrDecorator : keyOrDecorator.KEY;
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Get metadata value from handler first, then class.
|
|
1126
|
+
* Handler-level metadata takes priority over class-level.
|
|
1127
|
+
*/
|
|
1128
|
+
get(key, context) {
|
|
1129
|
+
const resolvedKey = this.resolveKey(key);
|
|
1130
|
+
const ctor = context.getClass();
|
|
1131
|
+
const handlerValue = MetadataRegistry.getCustomHandlerMeta(ctor, context.getHandler(), resolvedKey);
|
|
1132
|
+
if (handlerValue !== void 0) return handlerValue;
|
|
1133
|
+
return MetadataRegistry.getCustomClassMeta(ctor, resolvedKey);
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Get metadata only from the handler (method) level.
|
|
1137
|
+
*/
|
|
1138
|
+
getHandler(key, context) {
|
|
1139
|
+
const resolvedKey = this.resolveKey(key);
|
|
1140
|
+
return MetadataRegistry.getCustomHandlerMeta(context.getClass(), context.getHandler(), resolvedKey);
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Get metadata only from the class level.
|
|
1144
|
+
*/
|
|
1145
|
+
getClass(key, context) {
|
|
1146
|
+
const resolvedKey = this.resolveKey(key);
|
|
1147
|
+
return MetadataRegistry.getCustomClassMeta(context.getClass(), resolvedKey);
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Get all metadata values for a key from both handler and class.
|
|
1151
|
+
* Returns [handlerValue, classValue] (either may be undefined).
|
|
1152
|
+
*/
|
|
1153
|
+
getAll(key, context) {
|
|
1154
|
+
return [this.getHandler(key, context), this.getClass(key, context)];
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Returns handler value if defined, else class value, else undefined.
|
|
1158
|
+
* First defined value wins.
|
|
1159
|
+
*/
|
|
1160
|
+
getAllAndOverride(key, context) {
|
|
1161
|
+
return this.getHandler(key, context) ?? this.getClass(key, context);
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* Collects handler + class values, filters undefineds.
|
|
1165
|
+
* - 0 values → []
|
|
1166
|
+
* - 1 value → return it
|
|
1167
|
+
* - Arrays → concatenate
|
|
1168
|
+
* - Objects → Object.assign({}, ...values)
|
|
1169
|
+
* - Otherwise → wrap in array
|
|
1170
|
+
*/
|
|
1171
|
+
getAllAndMerge(key, context) {
|
|
1172
|
+
const [handlerValue, classValue] = this.getAll(key, context);
|
|
1173
|
+
const values = [];
|
|
1174
|
+
if (handlerValue !== void 0) values.push(handlerValue);
|
|
1175
|
+
if (classValue !== void 0) values.push(classValue);
|
|
1176
|
+
if (values.length === 0) return [];
|
|
1177
|
+
if (values.length === 1) return values[0];
|
|
1178
|
+
if (Array.isArray(values[0]) && Array.isArray(values[1])) return [...values[0], ...values[1]];
|
|
1179
|
+
if (typeof values[0] === "object" && values[0] !== null && !Array.isArray(values[0]) && typeof values[1] === "object" && values[1] !== null && !Array.isArray(values[1])) return Object.assign({}, values[0], values[1]);
|
|
1180
|
+
return values;
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
//#endregion
|
|
1184
|
+
//#region src/cache/cache.tokens.ts
|
|
1185
|
+
const CACHE_MANAGER = new InjectionToken("CACHE_MANAGER");
|
|
1186
|
+
const CACHE_MODULE_OPTIONS = new InjectionToken("CACHE_MODULE_OPTIONS");
|
|
1187
|
+
const CACHE_KEY_METADATA = "vela:cache-key";
|
|
1188
|
+
const CACHE_TTL_METADATA = "vela:cache-ttl";
|
|
1189
|
+
//#endregion
|
|
1190
|
+
//#region src/cache/cache.interceptor.ts
|
|
1191
|
+
let CacheInterceptor = class CacheInterceptor {
|
|
1192
|
+
cacheStore;
|
|
1193
|
+
options;
|
|
1194
|
+
reflector = new Reflector();
|
|
1195
|
+
constructor(cacheStore, options) {
|
|
1196
|
+
this.cacheStore = cacheStore;
|
|
1197
|
+
this.options = options;
|
|
1198
|
+
}
|
|
1199
|
+
async intercept(context, next) {
|
|
1200
|
+
const request = context.getRequest();
|
|
1201
|
+
if (request.method !== "GET") return next.handle();
|
|
1202
|
+
const customKey = this.reflector.getAllAndOverride(CACHE_KEY_METADATA, context);
|
|
1203
|
+
const url = new URL(request.url);
|
|
1204
|
+
const cacheKey = customKey ?? `cache:GET:${url.pathname}`;
|
|
1205
|
+
const cached = this.cacheStore.get(cacheKey);
|
|
1206
|
+
if (cached !== void 0) return cached;
|
|
1207
|
+
const result = await next.handle();
|
|
1208
|
+
const ttl = this.reflector.getAllAndOverride("vela:cache-ttl", context) ?? this.options.ttl ?? 5;
|
|
1209
|
+
this.cacheStore.set(cacheKey, result, ttl);
|
|
1210
|
+
return result;
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
CacheInterceptor = __decorate([
|
|
1214
|
+
Injectable(),
|
|
1215
|
+
__decorateParam(0, Inject(CACHE_MANAGER)),
|
|
1216
|
+
__decorateParam(1, Inject(CACHE_MODULE_OPTIONS)),
|
|
1217
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
1218
|
+
], CacheInterceptor);
|
|
1219
|
+
//#endregion
|
|
1220
|
+
//#region src/cache/cache.service.ts
|
|
1221
|
+
let CacheService = class CacheService {
|
|
1222
|
+
store;
|
|
1223
|
+
constructor(store) {
|
|
1224
|
+
this.store = store;
|
|
1225
|
+
}
|
|
1226
|
+
get(key) {
|
|
1227
|
+
return this.store.get(key);
|
|
1228
|
+
}
|
|
1229
|
+
set(key, value, ttl) {
|
|
1230
|
+
this.store.set(key, value, ttl);
|
|
1231
|
+
}
|
|
1232
|
+
del(key) {
|
|
1233
|
+
this.store.del(key);
|
|
1234
|
+
}
|
|
1235
|
+
clear() {
|
|
1236
|
+
this.store.clear();
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
CacheService = __decorate([
|
|
1240
|
+
Injectable(),
|
|
1241
|
+
__decorateParam(0, Inject(CACHE_MANAGER)),
|
|
1242
|
+
__decorateMetadata("design:paramtypes", [Object])
|
|
1243
|
+
], CacheService);
|
|
1244
|
+
//#endregion
|
|
1245
|
+
//#region src/cache/cache.store.ts
|
|
1246
|
+
var MemoryCacheStore = class {
|
|
1247
|
+
store = /* @__PURE__ */ new Map();
|
|
1248
|
+
defaultTtl;
|
|
1249
|
+
max;
|
|
1250
|
+
constructor(ttl = 5, max = 100) {
|
|
1251
|
+
this.defaultTtl = ttl;
|
|
1252
|
+
this.max = max;
|
|
1253
|
+
}
|
|
1254
|
+
get(key) {
|
|
1255
|
+
const entry = this.store.get(key);
|
|
1256
|
+
if (!entry) return void 0;
|
|
1257
|
+
if (Date.now() > entry.expiresAt) {
|
|
1258
|
+
this.store.delete(key);
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
return entry.value;
|
|
1262
|
+
}
|
|
1263
|
+
set(key, value, ttl) {
|
|
1264
|
+
if (!this.store.has(key) && this.store.size >= this.max) this.evict();
|
|
1265
|
+
const effectiveTtl = ttl ?? this.defaultTtl;
|
|
1266
|
+
this.store.set(key, {
|
|
1267
|
+
value,
|
|
1268
|
+
expiresAt: Date.now() + effectiveTtl * 1e3
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
del(key) {
|
|
1272
|
+
this.store.delete(key);
|
|
1273
|
+
}
|
|
1274
|
+
clear() {
|
|
1275
|
+
this.store.clear();
|
|
1276
|
+
}
|
|
1277
|
+
evict() {
|
|
1278
|
+
const now = Date.now();
|
|
1279
|
+
for (const [key, entry] of this.store) if (now > entry.expiresAt) this.store.delete(key);
|
|
1280
|
+
if (this.store.size >= this.max) {
|
|
1281
|
+
const firstKey = this.store.keys().next().value;
|
|
1282
|
+
if (firstKey !== void 0) this.store.delete(firstKey);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
//#endregion
|
|
1287
|
+
//#region src/cache/cache.module.ts
|
|
1288
|
+
const { ConfigurableModuleClass: ConfigurableModuleClass$2, MODULE_OPTIONS_TOKEN: MODULE_OPTIONS_TOKEN$1 } = new ConfigurableModuleBuilder({
|
|
1289
|
+
moduleName: "Cache",
|
|
1290
|
+
optionsInjectionToken: CACHE_MODULE_OPTIONS
|
|
1291
|
+
}).setExtras({ isGlobal: false }, (definition, { isGlobal }) => isGlobal ? {
|
|
1292
|
+
...definition,
|
|
1293
|
+
providers: [...definition.providers ?? [], {
|
|
1294
|
+
provide: APP_INTERCEPTOR,
|
|
1295
|
+
useExisting: CacheInterceptor
|
|
1296
|
+
}]
|
|
1297
|
+
} : definition).build();
|
|
1298
|
+
let CacheModule = class CacheModule extends ConfigurableModuleClass$2 {};
|
|
1299
|
+
CacheModule = __decorate([Module({
|
|
1300
|
+
providers: [
|
|
1301
|
+
CacheService,
|
|
1302
|
+
CacheInterceptor,
|
|
1303
|
+
{
|
|
1304
|
+
provide: CACHE_MANAGER,
|
|
1305
|
+
useFactory: (options) => options.store ?? new MemoryCacheStore(options.ttl ?? 5, options.max ?? 100),
|
|
1306
|
+
inject: [MODULE_OPTIONS_TOKEN$1]
|
|
1307
|
+
}
|
|
1308
|
+
],
|
|
1309
|
+
exports: [
|
|
1310
|
+
CACHE_MANAGER,
|
|
1311
|
+
CACHE_MODULE_OPTIONS,
|
|
1312
|
+
CacheService,
|
|
1313
|
+
CacheInterceptor
|
|
1314
|
+
]
|
|
1315
|
+
})], CacheModule);
|
|
1316
|
+
//#endregion
|
|
1317
|
+
//#region src/cache/tiered-cache.store.ts
|
|
1318
|
+
/**
|
|
1319
|
+
* Composes an ordered list of cache tiers (fastest first, e.g. in-memory L1 →
|
|
1320
|
+
* KV L2). Tiers may be sync ({@link CacheStore}) or async ({@link AsyncCacheStore}) —
|
|
1321
|
+
* results are awaited uniformly. Reads are read-through: the first tier with a
|
|
1322
|
+
* hit wins, and nearer tiers that missed are backfilled. Writes/deletes/clears
|
|
1323
|
+
* fan out to all tiers. Always async ({@link AsyncCacheStore}).
|
|
1324
|
+
*
|
|
1325
|
+
* Runtime-agnostic — the concrete tiers (memory here, KV in `@velajs/cloudflare`)
|
|
1326
|
+
* live wherever fits.
|
|
1327
|
+
*/
|
|
1328
|
+
var TieredCacheStore = class {
|
|
1329
|
+
tiers;
|
|
1330
|
+
constructor(tiers) {
|
|
1331
|
+
if (tiers.length === 0) throw new Error("TieredCacheStore requires at least one tier.");
|
|
1332
|
+
this.tiers = tiers;
|
|
1333
|
+
}
|
|
1334
|
+
async get(key) {
|
|
1335
|
+
for (let i = 0; i < this.tiers.length; i++) {
|
|
1336
|
+
const value = await this.tiers[i].get(key);
|
|
1337
|
+
if (value !== void 0) {
|
|
1338
|
+
for (let j = 0; j < i; j++) await this.tiers[j].set(key, value);
|
|
1339
|
+
return value;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
async set(key, value, ttl) {
|
|
1344
|
+
await Promise.all(this.tiers.map((tier) => tier.set(key, value, ttl)));
|
|
1345
|
+
}
|
|
1346
|
+
async del(key) {
|
|
1347
|
+
await Promise.all(this.tiers.map((tier) => tier.del(key)));
|
|
1348
|
+
}
|
|
1349
|
+
async clear() {
|
|
1350
|
+
await Promise.all(this.tiers.map((tier) => tier.clear()));
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
//#endregion
|
|
1354
|
+
//#region src/cache/cache.decorators.ts
|
|
1355
|
+
const CacheKey = (key) => SetMetadata(CACHE_KEY_METADATA, key);
|
|
1356
|
+
const CacheTTL = (seconds) => SetMetadata(CACHE_TTL_METADATA, seconds);
|
|
1357
|
+
//#endregion
|
|
1358
|
+
//#region src/module/lazy-provider.ts
|
|
1359
|
+
/**
|
|
1360
|
+
* Provide a zero-arg thunk `() => T` whose factory runs on FIRST CALL, not at
|
|
1361
|
+
* provider construction — for values that don't exist yet when the module
|
|
1362
|
+
* graph is built (Cloudflare bindings are only live at request time).
|
|
1363
|
+
*
|
|
1364
|
+
* The shared primitive replacing the hand-rolled
|
|
1365
|
+
* `useFactory: (...deps) => () => build(...deps)` closure that auth and
|
|
1366
|
+
* storage each copy-pasted.
|
|
1367
|
+
*
|
|
1368
|
+
* ```ts
|
|
1369
|
+
* lazyProvider({
|
|
1370
|
+
* provide: STORAGE_DRIVER_BUILDER,
|
|
1371
|
+
* inject: [MODULE_OPTIONS_TOKEN],
|
|
1372
|
+
* useFactory: (options) => options.driver(),
|
|
1373
|
+
* })
|
|
1374
|
+
* ```
|
|
1375
|
+
*/
|
|
1376
|
+
function lazyProvider(spec) {
|
|
1377
|
+
const memoize = spec.memoize ?? true;
|
|
1378
|
+
return {
|
|
1379
|
+
provide: spec.provide,
|
|
1380
|
+
inject: [...spec.inject ?? []],
|
|
1381
|
+
useFactory: (...deps) => {
|
|
1382
|
+
const build = () => spec.useFactory(...deps);
|
|
1383
|
+
if (!memoize) return build;
|
|
1384
|
+
let cached;
|
|
1385
|
+
return () => (cached ??= { value: build() }).value;
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
const GLOBAL_COMPONENT_TOKENS = {
|
|
1390
|
+
guard: APP_GUARD,
|
|
1391
|
+
pipe: APP_PIPE,
|
|
1392
|
+
interceptor: APP_INTERCEPTOR,
|
|
1393
|
+
filter: APP_FILTER,
|
|
1394
|
+
middleware: APP_MIDDLEWARE
|
|
1395
|
+
};
|
|
1396
|
+
/**
|
|
1397
|
+
* The one idiom for registering an app-wide component from a module's
|
|
1398
|
+
* providers. Returns registrations to spread:
|
|
1399
|
+
*
|
|
1400
|
+
* ```ts
|
|
1401
|
+
* providers: [MyService, ...provideGlobal('guard', AuthGuard)]
|
|
1402
|
+
* ```
|
|
1403
|
+
*
|
|
1404
|
+
* Class components are registered as providers and wired via `useExisting`
|
|
1405
|
+
* (so DI constructs them with their dependencies); instances via `useValue`.
|
|
1406
|
+
* Inside `defineModule`, prefer the equivalent `global:` contribution slot.
|
|
1407
|
+
*/
|
|
1408
|
+
function provideGlobal(kind, component) {
|
|
1409
|
+
const token = GLOBAL_COMPONENT_TOKENS[kind];
|
|
1410
|
+
if (typeof component === "function") return [component, {
|
|
1411
|
+
provide: token,
|
|
1412
|
+
useExisting: component
|
|
1413
|
+
}];
|
|
1414
|
+
return [{
|
|
1415
|
+
provide: token,
|
|
1416
|
+
useValue: component
|
|
1417
|
+
}];
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* A first-class side-effect-only module: contributes providers/exports without
|
|
1421
|
+
* being a configurable module — the supported form of the "empty marker
|
|
1422
|
+
* module" trick (i18n's `registerMessages`). Content-derived `key` makes
|
|
1423
|
+
* identical contributions dedup (HMR-idempotent) while distinct ones coexist.
|
|
1424
|
+
*
|
|
1425
|
+
* ```ts
|
|
1426
|
+
* export function registerMessages(messages: Messages): DynamicModule {
|
|
1427
|
+
* return sideEffectModule('I18nMessages', {
|
|
1428
|
+
* providers: [{ provide: I18N_MESSAGES, useValue: messages }],
|
|
1429
|
+
* exports: [I18N_MESSAGES],
|
|
1430
|
+
* });
|
|
1431
|
+
* }
|
|
1432
|
+
* ```
|
|
1433
|
+
*/
|
|
1434
|
+
function sideEffectModule(name, contributions = {}) {
|
|
1435
|
+
const { key, ...rest } = contributions;
|
|
1436
|
+
const moduleClass = { [name]: class {} }[name];
|
|
1437
|
+
Module({})(moduleClass);
|
|
1438
|
+
return {
|
|
1439
|
+
module: moduleClass,
|
|
1440
|
+
key: key ?? stableHash(rest),
|
|
1441
|
+
providers: rest.providers ?? [],
|
|
1442
|
+
controllers: rest.controllers ?? [],
|
|
1443
|
+
imports: rest.imports ?? [],
|
|
1444
|
+
exports: rest.exports ?? []
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* Blessed token-minting convention: always an `InjectionToken` (never a raw
|
|
1449
|
+
* string), named for diagnostics. Namespace it `'<pkg>:<area>:<thing>'`.
|
|
1450
|
+
*/
|
|
1451
|
+
function moduleToken(name) {
|
|
1452
|
+
return new InjectionToken(name);
|
|
1453
|
+
}
|
|
1454
|
+
//#endregion
|
|
1455
|
+
//#region src/event-emitter/event-emitter.service.ts
|
|
1456
|
+
function isWildcard(pattern) {
|
|
1457
|
+
return pattern.includes("*");
|
|
1458
|
+
}
|
|
1459
|
+
function compilePattern(pattern) {
|
|
1460
|
+
const regexStr = pattern.split(".").map((segment) => {
|
|
1461
|
+
if (segment === "**") return ".*";
|
|
1462
|
+
if (segment === "*") return "[^.]+";
|
|
1463
|
+
return segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1464
|
+
}).join("\\.");
|
|
1465
|
+
return new RegExp(`^${regexStr}$`);
|
|
1466
|
+
}
|
|
1467
|
+
let EventEmitter = class EventEmitter {
|
|
1468
|
+
exactListeners = /* @__PURE__ */ new Map();
|
|
1469
|
+
exactOnceListeners = /* @__PURE__ */ new Map();
|
|
1470
|
+
wildcardListeners = /* @__PURE__ */ new Map();
|
|
1471
|
+
on(event, handler) {
|
|
1472
|
+
if (isWildcard(event)) this.getOrCreateWildcard(event).handlers.add(handler);
|
|
1473
|
+
else {
|
|
1474
|
+
const handlers = this.exactListeners.get(event) ?? /* @__PURE__ */ new Set();
|
|
1475
|
+
handlers.add(handler);
|
|
1476
|
+
this.exactListeners.set(event, handlers);
|
|
1477
|
+
}
|
|
1478
|
+
return this;
|
|
1479
|
+
}
|
|
1480
|
+
once(event, handler) {
|
|
1481
|
+
this.on(event, handler);
|
|
1482
|
+
if (isWildcard(event)) this.getOrCreateWildcard(event).onceHandlers.add(handler);
|
|
1483
|
+
else {
|
|
1484
|
+
const onceSet = this.exactOnceListeners.get(event) ?? /* @__PURE__ */ new Set();
|
|
1485
|
+
onceSet.add(handler);
|
|
1486
|
+
this.exactOnceListeners.set(event, onceSet);
|
|
1487
|
+
}
|
|
1488
|
+
return this;
|
|
1489
|
+
}
|
|
1490
|
+
off(event, handler) {
|
|
1491
|
+
if (isWildcard(event)) {
|
|
1492
|
+
const entry = this.wildcardListeners.get(event);
|
|
1493
|
+
if (entry) {
|
|
1494
|
+
entry.handlers.delete(handler);
|
|
1495
|
+
entry.onceHandlers.delete(handler);
|
|
1496
|
+
if (entry.handlers.size === 0) this.wildcardListeners.delete(event);
|
|
1497
|
+
}
|
|
1498
|
+
} else {
|
|
1499
|
+
const handlers = this.exactListeners.get(event);
|
|
1500
|
+
if (handlers) {
|
|
1501
|
+
handlers.delete(handler);
|
|
1502
|
+
this.exactOnceListeners.get(event)?.delete(handler);
|
|
1503
|
+
if (handlers.size === 0) this.exactListeners.delete(event);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
return this;
|
|
1507
|
+
}
|
|
1508
|
+
async emit(event, ...args) {
|
|
1509
|
+
const toRemove = [];
|
|
1510
|
+
const exactHandlers = this.exactListeners.get(event);
|
|
1511
|
+
if (exactHandlers) {
|
|
1512
|
+
const onceSet = this.exactOnceListeners.get(event);
|
|
1513
|
+
await Promise.all([...exactHandlers].map(async (handler) => {
|
|
1514
|
+
await handler(...args);
|
|
1515
|
+
if (onceSet?.has(handler)) toRemove.push(() => this.off(event, handler));
|
|
1516
|
+
}));
|
|
1517
|
+
}
|
|
1518
|
+
for (const [pattern, entry] of this.wildcardListeners) {
|
|
1519
|
+
if (!entry.regex.test(event)) continue;
|
|
1520
|
+
await Promise.all([...entry.handlers].map(async (handler) => {
|
|
1521
|
+
await handler(...args);
|
|
1522
|
+
if (entry.onceHandlers.has(handler)) toRemove.push(() => this.off(pattern, handler));
|
|
1523
|
+
}));
|
|
1524
|
+
}
|
|
1525
|
+
for (const remove of toRemove) remove();
|
|
1526
|
+
}
|
|
1527
|
+
removeAllListeners(event) {
|
|
1528
|
+
if (event) if (isWildcard(event)) this.wildcardListeners.delete(event);
|
|
1529
|
+
else {
|
|
1530
|
+
this.exactListeners.delete(event);
|
|
1531
|
+
this.exactOnceListeners.delete(event);
|
|
1532
|
+
}
|
|
1533
|
+
else {
|
|
1534
|
+
this.exactListeners.clear();
|
|
1535
|
+
this.exactOnceListeners.clear();
|
|
1536
|
+
this.wildcardListeners.clear();
|
|
1537
|
+
}
|
|
1538
|
+
return this;
|
|
1539
|
+
}
|
|
1540
|
+
listenerCount(event) {
|
|
1541
|
+
let count = this.exactListeners.get(event)?.size ?? 0;
|
|
1542
|
+
for (const entry of this.wildcardListeners.values()) if (entry.regex.test(event)) count += entry.handlers.size;
|
|
1543
|
+
return count;
|
|
1544
|
+
}
|
|
1545
|
+
getOrCreateWildcard(pattern) {
|
|
1546
|
+
const existing = this.wildcardListeners.get(pattern);
|
|
1547
|
+
if (existing) return existing;
|
|
1548
|
+
const entry = {
|
|
1549
|
+
regex: compilePattern(pattern),
|
|
1550
|
+
handlers: /* @__PURE__ */ new Set(),
|
|
1551
|
+
onceHandlers: /* @__PURE__ */ new Set()
|
|
1552
|
+
};
|
|
1553
|
+
this.wildcardListeners.set(pattern, entry);
|
|
1554
|
+
return entry;
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
EventEmitter = __decorate([Injectable()], EventEmitter);
|
|
1558
|
+
//#endregion
|
|
1559
|
+
//#region src/event-emitter/event-emitter.tokens.ts
|
|
1560
|
+
const ON_EVENT_METADATA = "vela:on-event";
|
|
1561
|
+
//#endregion
|
|
1562
|
+
//#region src/event-emitter/event-emitter.subscriber.ts
|
|
1563
|
+
let EventEmitterSubscriber = class EventEmitterSubscriber {
|
|
1564
|
+
discovery;
|
|
1565
|
+
emitter;
|
|
1566
|
+
constructor(discovery, emitter) {
|
|
1567
|
+
this.discovery = discovery;
|
|
1568
|
+
this.emitter = emitter;
|
|
1569
|
+
}
|
|
1570
|
+
onApplicationBootstrap() {
|
|
1571
|
+
for (const found of this.discovery.methodsWithMeta(ON_EVENT_METADATA)) {
|
|
1572
|
+
const instance = found.class.instance;
|
|
1573
|
+
if (!instance) continue;
|
|
1574
|
+
const method = instance[found.methodName];
|
|
1575
|
+
if (typeof method === "function") this.emitter.on(found.meta.event, (...args) => method.apply(instance, args));
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
};
|
|
1579
|
+
EventEmitterSubscriber = __decorate([
|
|
1580
|
+
Injectable(),
|
|
1581
|
+
__decorateParam(0, Inject(DiscoveryService)),
|
|
1582
|
+
__decorateMetadata("design:paramtypes", [typeof DiscoveryService === "undefined" ? Object : DiscoveryService, typeof EventEmitter === "undefined" ? Object : EventEmitter])
|
|
1583
|
+
], EventEmitterSubscriber);
|
|
1584
|
+
//#endregion
|
|
1585
|
+
//#region src/event-emitter/event-emitter.module.ts
|
|
1586
|
+
let EventEmitterModule = class EventEmitterModule {};
|
|
1587
|
+
EventEmitterModule = __decorate([Module({
|
|
1588
|
+
lazy: true,
|
|
1589
|
+
providers: [EventEmitter, EventEmitterSubscriber],
|
|
1590
|
+
exports: [EventEmitter]
|
|
1591
|
+
})], EventEmitterModule);
|
|
1592
|
+
//#endregion
|
|
1593
|
+
//#region src/event-emitter/event-emitter.decorators.ts
|
|
1594
|
+
function OnEvent(event) {
|
|
1595
|
+
return (target, propertyKey) => {
|
|
1596
|
+
MetadataRegistry.appendCustomClassMeta(target.constructor, ON_EVENT_METADATA, {
|
|
1597
|
+
event,
|
|
1598
|
+
methodName: String(propertyKey)
|
|
1599
|
+
});
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
//#endregion
|
|
1603
|
+
//#region src/schedule/schedule.module.ts
|
|
1604
|
+
var _ScheduleModule;
|
|
1605
|
+
let ScheduleModule = _ScheduleModule = class ScheduleModule {
|
|
1606
|
+
static forRoot() {
|
|
1607
|
+
return { module: _ScheduleModule };
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
ScheduleModule = _ScheduleModule = __decorate([Module({
|
|
1611
|
+
lazy: true,
|
|
1612
|
+
providers: [ScheduleRegistry],
|
|
1613
|
+
exports: [ScheduleRegistry]
|
|
1614
|
+
})], ScheduleModule);
|
|
1615
|
+
//#endregion
|
|
1616
|
+
//#region src/schedule/schedule.decorators.ts
|
|
1617
|
+
function Cron(expression) {
|
|
1618
|
+
return (target, propertyKey) => {
|
|
1619
|
+
MetadataRegistry.appendCustomClassMeta(target.constructor, CRON_METADATA, {
|
|
1620
|
+
expression,
|
|
1621
|
+
methodName: String(propertyKey)
|
|
1622
|
+
});
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
function Interval(ms) {
|
|
1626
|
+
return (target, propertyKey) => {
|
|
1627
|
+
MetadataRegistry.appendCustomClassMeta(target.constructor, INTERVAL_METADATA, {
|
|
1628
|
+
ms,
|
|
1629
|
+
methodName: String(propertyKey)
|
|
1630
|
+
});
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
//#endregion
|
|
1634
|
+
//#region src/health/health.service.ts
|
|
1635
|
+
let HealthCheckService = class HealthCheckService {
|
|
1636
|
+
isShuttingDown = false;
|
|
1637
|
+
beforeApplicationShutdown() {
|
|
1638
|
+
this.isShuttingDown = true;
|
|
1639
|
+
}
|
|
1640
|
+
async check(indicators) {
|
|
1641
|
+
if (this.isShuttingDown) throw new ServiceUnavailableException({
|
|
1642
|
+
status: "shutting_down",
|
|
1643
|
+
info: {},
|
|
1644
|
+
error: {},
|
|
1645
|
+
details: {}
|
|
1646
|
+
});
|
|
1647
|
+
const results = await Promise.allSettled(indicators.map((fn) => fn()));
|
|
1648
|
+
const info = {};
|
|
1649
|
+
const error = {};
|
|
1650
|
+
const details = {};
|
|
1651
|
+
for (const result of results) if (result.status === "fulfilled") {
|
|
1652
|
+
const indicatorResult = result.value;
|
|
1653
|
+
for (const [key, value] of Object.entries(indicatorResult)) {
|
|
1654
|
+
details[key] = value;
|
|
1655
|
+
if (value.status === "up") info[key] = value;
|
|
1656
|
+
else error[key] = value;
|
|
1657
|
+
}
|
|
1658
|
+
} else {
|
|
1659
|
+
const message = result.reason instanceof Error ? result.reason.message : "Health check failed";
|
|
1660
|
+
const key = "unknown";
|
|
1661
|
+
const value = {
|
|
1662
|
+
status: "down",
|
|
1663
|
+
message
|
|
1664
|
+
};
|
|
1665
|
+
details[key] = value;
|
|
1666
|
+
error[key] = value;
|
|
1667
|
+
}
|
|
1668
|
+
const status = Object.keys(error).length > 0 ? "error" : "ok";
|
|
1669
|
+
const checkResult = {
|
|
1670
|
+
status,
|
|
1671
|
+
info,
|
|
1672
|
+
error,
|
|
1673
|
+
details
|
|
1674
|
+
};
|
|
1675
|
+
if (status === "error") throw new ServiceUnavailableException({ ...checkResult });
|
|
1676
|
+
return checkResult;
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
HealthCheckService = __decorate([Injectable()], HealthCheckService);
|
|
1680
|
+
//#endregion
|
|
1681
|
+
//#region src/health/health.indicator.ts
|
|
1682
|
+
let HealthIndicatorService = class HealthIndicatorService {
|
|
1683
|
+
check(key) {
|
|
1684
|
+
return {
|
|
1685
|
+
up(data) {
|
|
1686
|
+
return { [key]: {
|
|
1687
|
+
status: "up",
|
|
1688
|
+
...data
|
|
1689
|
+
} };
|
|
1690
|
+
},
|
|
1691
|
+
down(data) {
|
|
1692
|
+
return { [key]: {
|
|
1693
|
+
status: "down",
|
|
1694
|
+
...data
|
|
1695
|
+
} };
|
|
1696
|
+
}
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
};
|
|
1700
|
+
HealthIndicatorService = __decorate([Injectable()], HealthIndicatorService);
|
|
1701
|
+
//#endregion
|
|
1702
|
+
//#region src/health/health.http.ts
|
|
1703
|
+
let HttpHealthIndicator = class HttpHealthIndicator {
|
|
1704
|
+
indicator;
|
|
1705
|
+
constructor(indicator) {
|
|
1706
|
+
this.indicator = indicator;
|
|
1707
|
+
}
|
|
1708
|
+
async pingCheck(key, url, options) {
|
|
1709
|
+
const { method = "GET", headers, timeout = 5e3, expectedStatus } = options ?? {};
|
|
1710
|
+
try {
|
|
1711
|
+
const response = await fetch(url, {
|
|
1712
|
+
method,
|
|
1713
|
+
headers,
|
|
1714
|
+
signal: AbortSignal.timeout(timeout)
|
|
1715
|
+
});
|
|
1716
|
+
const statusCode = response.status;
|
|
1717
|
+
if (expectedStatus !== void 0 ? statusCode === expectedStatus : statusCode >= 200 && statusCode < 300) return this.indicator.check(key).up({ statusCode });
|
|
1718
|
+
return this.indicator.check(key).down({
|
|
1719
|
+
statusCode,
|
|
1720
|
+
message: response.statusText
|
|
1721
|
+
});
|
|
1722
|
+
} catch (error) {
|
|
1723
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1724
|
+
return this.indicator.check(key).down({ message });
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
async responseCheck(key, url, callback, options) {
|
|
1728
|
+
const { method = "GET", headers, timeout = 5e3 } = options ?? {};
|
|
1729
|
+
try {
|
|
1730
|
+
const response = await fetch(url, {
|
|
1731
|
+
method,
|
|
1732
|
+
headers,
|
|
1733
|
+
signal: AbortSignal.timeout(timeout)
|
|
1734
|
+
});
|
|
1735
|
+
const statusCode = response.status;
|
|
1736
|
+
if (await callback(response)) return this.indicator.check(key).up({ statusCode });
|
|
1737
|
+
return this.indicator.check(key).down({ statusCode });
|
|
1738
|
+
} catch (error) {
|
|
1739
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1740
|
+
return this.indicator.check(key).down({ message });
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1744
|
+
HttpHealthIndicator = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof HealthIndicatorService === "undefined" ? Object : HealthIndicatorService])], HttpHealthIndicator);
|
|
1745
|
+
//#endregion
|
|
1746
|
+
//#region src/health/health.module.ts
|
|
1747
|
+
let HealthModule = class HealthModule {};
|
|
1748
|
+
HealthModule = __decorate([Module({
|
|
1749
|
+
providers: [
|
|
1750
|
+
HealthCheckService,
|
|
1751
|
+
HealthIndicatorService,
|
|
1752
|
+
HttpHealthIndicator
|
|
1753
|
+
],
|
|
1754
|
+
exports: [
|
|
1755
|
+
HealthCheckService,
|
|
1756
|
+
HealthIndicatorService,
|
|
1757
|
+
HttpHealthIndicator
|
|
1758
|
+
]
|
|
1759
|
+
})], HealthModule);
|
|
1760
|
+
//#endregion
|
|
1761
|
+
//#region src/throttler/throttler.tokens.ts
|
|
1762
|
+
const THROTTLER_OPTIONS = new InjectionToken("THROTTLER_OPTIONS");
|
|
1763
|
+
const THROTTLER_STORAGE = new InjectionToken("THROTTLER_STORAGE");
|
|
1764
|
+
const THROTTLE_METADATA = "vela:throttle";
|
|
1765
|
+
const SKIP_THROTTLE_METADATA = "vela:skip-throttle";
|
|
1766
|
+
//#endregion
|
|
1767
|
+
//#region src/throttler/throttler.guard.ts
|
|
1768
|
+
let ThrottlerGuard = class ThrottlerGuard {
|
|
1769
|
+
options;
|
|
1770
|
+
storage;
|
|
1771
|
+
reflector = new Reflector();
|
|
1772
|
+
constructor(options, storage) {
|
|
1773
|
+
this.options = options;
|
|
1774
|
+
this.storage = storage;
|
|
1775
|
+
}
|
|
1776
|
+
async canActivate(context) {
|
|
1777
|
+
if (this.reflector.getAllAndOverride("vela:skip-throttle", context)) return true;
|
|
1778
|
+
const override = this.reflector.getAllAndOverride(THROTTLE_METADATA, context);
|
|
1779
|
+
const limit = override?.limit ?? this.options.limit;
|
|
1780
|
+
const ttl = override?.ttl ?? this.options.ttl;
|
|
1781
|
+
const request = context.getRequest();
|
|
1782
|
+
const tracker = this.options.getTracker ? this.options.getTracker(request) : request.headers.get("x-forwarded-for") ?? "anonymous";
|
|
1783
|
+
const className = context.getClass().name;
|
|
1784
|
+
const handlerName = String(context.getHandler());
|
|
1785
|
+
const key = this.options.generateKey ? this.options.generateKey(tracker, {
|
|
1786
|
+
className,
|
|
1787
|
+
handlerName
|
|
1788
|
+
}) : `throttler:${className}:${handlerName}:${tracker}`;
|
|
1789
|
+
const { count, ttlMs } = await this.storage.increment(key, ttl);
|
|
1790
|
+
const remaining = Math.max(0, limit - count);
|
|
1791
|
+
const resetSeconds = Math.ceil(ttlMs / 1e3);
|
|
1792
|
+
const honoContext = context.getContext();
|
|
1793
|
+
honoContext.header("X-RateLimit-Limit", String(limit));
|
|
1794
|
+
honoContext.header("X-RateLimit-Remaining", String(remaining));
|
|
1795
|
+
honoContext.header("X-RateLimit-Reset", String(resetSeconds));
|
|
1796
|
+
const rateLimitInfo = {
|
|
1797
|
+
limit,
|
|
1798
|
+
remaining,
|
|
1799
|
+
reset: resetSeconds
|
|
1800
|
+
};
|
|
1801
|
+
honoContext.set("rateLimit", rateLimitInfo);
|
|
1802
|
+
if (count > limit) {
|
|
1803
|
+
honoContext.header("Retry-After", String(resetSeconds));
|
|
1804
|
+
throw new TooManyRequestsException();
|
|
1805
|
+
}
|
|
1806
|
+
return true;
|
|
1807
|
+
}
|
|
1808
|
+
};
|
|
1809
|
+
ThrottlerGuard = __decorate([
|
|
1810
|
+
Injectable(),
|
|
1811
|
+
__decorateParam(0, Inject(THROTTLER_OPTIONS)),
|
|
1812
|
+
__decorateParam(1, Inject(THROTTLER_STORAGE)),
|
|
1813
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
1814
|
+
], ThrottlerGuard);
|
|
1815
|
+
//#endregion
|
|
1816
|
+
//#region src/throttler/throttler.storage.ts
|
|
1817
|
+
let ThrottlerStorage = class ThrottlerStorage {
|
|
1818
|
+
current = /* @__PURE__ */ new Map();
|
|
1819
|
+
previous = /* @__PURE__ */ new Map();
|
|
1820
|
+
lastSwap = Date.now();
|
|
1821
|
+
swapIntervalMs = 6e4;
|
|
1822
|
+
increment(key, ttlMs) {
|
|
1823
|
+
this.maybeSwap();
|
|
1824
|
+
const now = Date.now();
|
|
1825
|
+
let entry = this.current.get(key) ?? this.previous.get(key);
|
|
1826
|
+
if (!entry || now >= entry.resetTime) entry = {
|
|
1827
|
+
count: 0,
|
|
1828
|
+
resetTime: now + ttlMs
|
|
1829
|
+
};
|
|
1830
|
+
entry.count++;
|
|
1831
|
+
this.current.set(key, entry);
|
|
1832
|
+
return {
|
|
1833
|
+
count: entry.count,
|
|
1834
|
+
ttlMs: entry.resetTime - now
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
reset(key) {
|
|
1838
|
+
this.current.delete(key);
|
|
1839
|
+
this.previous.delete(key);
|
|
1840
|
+
}
|
|
1841
|
+
maybeSwap() {
|
|
1842
|
+
const now = Date.now();
|
|
1843
|
+
if (now - this.lastSwap < this.swapIntervalMs) return;
|
|
1844
|
+
this.previous = this.current;
|
|
1845
|
+
this.current = /* @__PURE__ */ new Map();
|
|
1846
|
+
this.lastSwap = now;
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
ThrottlerStorage = __decorate([Injectable()], ThrottlerStorage);
|
|
1850
|
+
//#endregion
|
|
1851
|
+
//#region src/throttler/throttler.module.ts
|
|
1852
|
+
const { ConfigurableModuleClass: ConfigurableModuleClass$1, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder({
|
|
1853
|
+
moduleName: "Throttler",
|
|
1854
|
+
optionsInjectionToken: THROTTLER_OPTIONS
|
|
1855
|
+
}).build();
|
|
1856
|
+
let ThrottlerModule = class ThrottlerModule extends ConfigurableModuleClass$1 {};
|
|
1857
|
+
ThrottlerModule = __decorate([Module({
|
|
1858
|
+
providers: [
|
|
1859
|
+
{
|
|
1860
|
+
provide: THROTTLER_STORAGE,
|
|
1861
|
+
useFactory: (options) => options.storage ?? new ThrottlerStorage(),
|
|
1862
|
+
inject: [MODULE_OPTIONS_TOKEN]
|
|
1863
|
+
},
|
|
1864
|
+
ThrottlerGuard,
|
|
1865
|
+
{
|
|
1866
|
+
provide: APP_GUARD,
|
|
1867
|
+
useExisting: ThrottlerGuard
|
|
1868
|
+
}
|
|
1869
|
+
],
|
|
1870
|
+
exports: [
|
|
1871
|
+
THROTTLER_OPTIONS,
|
|
1872
|
+
THROTTLER_STORAGE,
|
|
1873
|
+
ThrottlerGuard
|
|
1874
|
+
]
|
|
1875
|
+
})], ThrottlerModule);
|
|
1876
|
+
//#endregion
|
|
1877
|
+
//#region src/throttler/throttler.decorators.ts
|
|
1878
|
+
const Throttle = (config) => SetMetadata(THROTTLE_METADATA, config);
|
|
1879
|
+
const SkipThrottle = () => SetMetadata(SKIP_THROTTLE_METADATA, true);
|
|
1880
|
+
//#endregion
|
|
1881
|
+
//#region src/entrypoint/execution-scope.ts
|
|
1882
|
+
/**
|
|
1883
|
+
* Run one unit of non-HTTP work (a queue batch, a scheduled tick, an RPC
|
|
1884
|
+
* call) inside a fresh request-scoped child container — the non-HTTP
|
|
1885
|
+
* equivalent of the per-request child the HTTP pipeline creates:
|
|
1886
|
+
*
|
|
1887
|
+
* ```ts
|
|
1888
|
+
* await runInEntrypointScope(app.getContainer(), async (scope) => {
|
|
1889
|
+
* const consumer = scope.resolve(ep.token);
|
|
1890
|
+
* await consumer.process(batch);
|
|
1891
|
+
* });
|
|
1892
|
+
* ```
|
|
1893
|
+
*
|
|
1894
|
+
* Request-scoped providers (and singletons bubbled to request scope) resolve
|
|
1895
|
+
* per invocation instead of leaking one boot-time instance across every
|
|
1896
|
+
* dispatch; the child's request-scoped disposables are disposed (LIFO) when
|
|
1897
|
+
* `fn` settles — success or failure. `REQUEST_CONTEXT` is deliberately NOT
|
|
1898
|
+
* seeded: it is an HTTP primitive, and resolving it here keeps throwing its
|
|
1899
|
+
* explicit misuse error.
|
|
1900
|
+
*/
|
|
1901
|
+
async function runInEntrypointScope(container, fn) {
|
|
1902
|
+
const scope = container.createChild();
|
|
1903
|
+
try {
|
|
1904
|
+
return await fn(scope);
|
|
1905
|
+
} finally {
|
|
1906
|
+
if (scope.hasDisposables()) await scope.dispose();
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
//#endregion
|
|
1910
|
+
//#region src/entrypoint/execution-context.ts
|
|
1911
|
+
const WRONG_TRANSPORT = (accessor, kind) => () => {
|
|
1912
|
+
throw new Error(`${accessor} called on a '${kind}' entrypoint ExecutionContext — this handler runs over an entrypoint dispatch, not that transport. Use getType()/getPayload() to branch.`);
|
|
1913
|
+
};
|
|
1914
|
+
/**
|
|
1915
|
+
* Entrypoint sibling of `buildExecutionContext` (HTTP) and
|
|
1916
|
+
* `buildWsExecutionContext`: lets guards/interceptors/filters written against
|
|
1917
|
+
* `getClass()`/`getHandler()`/`getType()` run unchanged around queue batches,
|
|
1918
|
+
* scheduled ticks, and any custom entrypoint kind. Transport-specific
|
|
1919
|
+
* accessors throw rather than fabricate fakes.
|
|
1920
|
+
*/
|
|
1921
|
+
function buildEntrypointExecutionContext(kind, targetClass, handlerName, payload) {
|
|
1922
|
+
return {
|
|
1923
|
+
getType: () => kind,
|
|
1924
|
+
getClass: () => targetClass,
|
|
1925
|
+
getHandler: () => handlerName,
|
|
1926
|
+
getPayload: () => payload,
|
|
1927
|
+
getContext: WRONG_TRANSPORT("getContext()", kind),
|
|
1928
|
+
getRequest: WRONG_TRANSPORT("getRequest()", kind),
|
|
1929
|
+
switchToHttp: WRONG_TRANSPORT("switchToHttp()", kind),
|
|
1930
|
+
switchToWs: WRONG_TRANSPORT("switchToWs()", kind)
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
//#endregion
|
|
1934
|
+
//#region src/pipeline/scoped-components.ts
|
|
1935
|
+
const RESOLVERS = {
|
|
1936
|
+
guard: ComponentManager.resolveGuards.bind(ComponentManager),
|
|
1937
|
+
pipe: ComponentManager.resolvePipes.bind(ComponentManager),
|
|
1938
|
+
interceptor: ComponentManager.resolveInterceptors.bind(ComponentManager),
|
|
1939
|
+
filter: ComponentManager.resolveFilters.bind(ComponentManager),
|
|
1940
|
+
middleware: ComponentManager.resolveMiddleware.bind(ComponentManager)
|
|
1941
|
+
};
|
|
1942
|
+
/**
|
|
1943
|
+
* Public seam for custom dispatchers: the `@UseGuards`/`@UsePipes`/
|
|
1944
|
+
* `@UseInterceptors`/`@UseFilters` components scoped to a handler (class-level
|
|
1945
|
+
* then method-level, declaration order), resolved to instances through the
|
|
1946
|
+
* given container (classes constructed with DI; instances passed through).
|
|
1947
|
+
*
|
|
1948
|
+
* Order is preserved exactly as declared — conventions stay with the CALLER:
|
|
1949
|
+
* filters run closest-first, so dispatchers reverse them
|
|
1950
|
+
* (`resolveScopedComponents('filter', ...).reverse()`), and app-wide `APP_*`
|
|
1951
|
+
* components are a separate, transport-specific decision.
|
|
1952
|
+
*
|
|
1953
|
+
* Promoted to the public API by the QueueModule work (the "openness proof"):
|
|
1954
|
+
* it was the one capability custom entrypoint dispatchers needed that only
|
|
1955
|
+
* the internal `ComponentManager` provided.
|
|
1956
|
+
*/
|
|
1957
|
+
function resolveScopedComponents(type, targetClass, methodName, container) {
|
|
1958
|
+
const scoped = ComponentManager.getScopedComponents(type, targetClass, methodName);
|
|
1959
|
+
const resolve = RESOLVERS[type];
|
|
1960
|
+
return resolve(scoped, container);
|
|
1961
|
+
}
|
|
1962
|
+
//#endregion
|
|
1963
|
+
//#region src/pipeline/pipes.ts
|
|
1964
|
+
var ParseIntPipe = class {
|
|
1965
|
+
transform(value, metadata) {
|
|
1966
|
+
const parsed = parseInt(value, 10);
|
|
1967
|
+
if (isNaN(parsed)) throw new BadRequestException(`Validation failed (numeric string expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
1968
|
+
return parsed;
|
|
1969
|
+
}
|
|
1970
|
+
};
|
|
1971
|
+
var ParseFloatPipe = class {
|
|
1972
|
+
transform(value, metadata) {
|
|
1973
|
+
const parsed = parseFloat(value);
|
|
1974
|
+
if (isNaN(parsed)) throw new BadRequestException(`Validation failed (float string expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
1975
|
+
return parsed;
|
|
1976
|
+
}
|
|
1977
|
+
};
|
|
1978
|
+
var ParseBoolPipe = class {
|
|
1979
|
+
transform(value, metadata) {
|
|
1980
|
+
if (value === "true") return true;
|
|
1981
|
+
if (value === "false") return false;
|
|
1982
|
+
throw new BadRequestException(`Validation failed (boolean string expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
var DefaultValuePipe = class {
|
|
1986
|
+
defaultValue;
|
|
1987
|
+
constructor(defaultValue) {
|
|
1988
|
+
this.defaultValue = defaultValue;
|
|
1989
|
+
}
|
|
1990
|
+
transform(value, _metadata) {
|
|
1991
|
+
return value !== void 0 && value !== null ? value : this.defaultValue;
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
var RequiredPipe = class {
|
|
1995
|
+
transform(value, metadata) {
|
|
1996
|
+
if (value === void 0 || value === null || value === "") throw new BadRequestException(`Validation failed (value required)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
1997
|
+
return value;
|
|
1998
|
+
}
|
|
1999
|
+
};
|
|
2000
|
+
var ZodValidationPipe = class {
|
|
2001
|
+
schema;
|
|
2002
|
+
constructor(schema) {
|
|
2003
|
+
this.schema = schema;
|
|
2004
|
+
}
|
|
2005
|
+
transform(value, _metadata) {
|
|
2006
|
+
return this.schema.parse(value);
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2010
|
+
const UUID_VERSION_REGEX = {
|
|
2011
|
+
"3": /^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
2012
|
+
"4": /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
2013
|
+
"5": /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
2014
|
+
};
|
|
2015
|
+
var ParseUUIDPipe = class {
|
|
2016
|
+
options;
|
|
2017
|
+
constructor(options) {
|
|
2018
|
+
this.options = options;
|
|
2019
|
+
}
|
|
2020
|
+
transform(value, metadata) {
|
|
2021
|
+
if (!(this.options?.version ? UUID_VERSION_REGEX[this.options.version] : UUID_REGEX).test(value)) throw new BadRequestException(`Validation failed (uuid${this.options?.version ? ` v${this.options.version}` : ""} expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
2022
|
+
return value;
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
var ParseEnumPipe = class {
|
|
2026
|
+
allowedValues;
|
|
2027
|
+
valuesLabel;
|
|
2028
|
+
constructor(enumType) {
|
|
2029
|
+
const values = Object.values(enumType);
|
|
2030
|
+
this.allowedValues = new Set(values);
|
|
2031
|
+
this.valuesLabel = values.join(", ");
|
|
2032
|
+
}
|
|
2033
|
+
transform(value, metadata) {
|
|
2034
|
+
if (!this.allowedValues.has(value)) throw new BadRequestException(`Validation failed (${this.valuesLabel} expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
2035
|
+
return value;
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
var ParseArrayPipe = class {
|
|
2039
|
+
options;
|
|
2040
|
+
constructor(options) {
|
|
2041
|
+
this.options = options;
|
|
2042
|
+
}
|
|
2043
|
+
transform(value, metadata) {
|
|
2044
|
+
if (value === void 0 || value === null || value === "") {
|
|
2045
|
+
if (this.options?.optional) return [];
|
|
2046
|
+
throw new BadRequestException(`Validation failed (array expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
2047
|
+
}
|
|
2048
|
+
if (Array.isArray(value)) return value;
|
|
2049
|
+
if (typeof value === "string") {
|
|
2050
|
+
const sep = this.options?.separator ?? ",";
|
|
2051
|
+
return value.split(sep).map((v) => v.trim()).filter((v) => v.length > 0);
|
|
2052
|
+
}
|
|
2053
|
+
throw new BadRequestException(`Validation failed (array expected)${metadata.data ? ` for parameter '${metadata.data}'` : ""}`);
|
|
2054
|
+
}
|
|
2055
|
+
};
|
|
2056
|
+
//#endregion
|
|
2057
|
+
//#region src/exceptions/errors.module.ts
|
|
2058
|
+
/** Lower a `handler` option to an {@link APP_EXCEPTION_HANDLER} provider. */
|
|
2059
|
+
const handlerProvider = (handler) => typeof handler === "function" ? {
|
|
2060
|
+
provide: APP_EXCEPTION_HANDLER,
|
|
2061
|
+
useClass: handler
|
|
2062
|
+
} : {
|
|
2063
|
+
provide: APP_EXCEPTION_HANDLER,
|
|
2064
|
+
useValue: handler
|
|
2065
|
+
};
|
|
2066
|
+
const { ConfigurableModuleClass } = defineModule({
|
|
2067
|
+
name: "Errors",
|
|
2068
|
+
setup: ({ options }) => {
|
|
2069
|
+
const providers = [{
|
|
2070
|
+
provide: ERROR_CATALOG,
|
|
2071
|
+
useValue: composeCatalogs(CORE_CATALOG, ...options.catalogs ?? [])
|
|
2072
|
+
}];
|
|
2073
|
+
const exports = [ERROR_CATALOG];
|
|
2074
|
+
if (options.handler) {
|
|
2075
|
+
providers.push(handlerProvider(options.handler));
|
|
2076
|
+
exports.push(APP_EXCEPTION_HANDLER);
|
|
2077
|
+
}
|
|
2078
|
+
return {
|
|
2079
|
+
providers,
|
|
2080
|
+
exports
|
|
2081
|
+
};
|
|
2082
|
+
}
|
|
2083
|
+
});
|
|
2084
|
+
/**
|
|
2085
|
+
* Registers the application-wide error surface: the composed
|
|
2086
|
+
* {@link ERROR_CATALOG} that every transport edge redacts against, and an
|
|
2087
|
+
* optional {@link APP_EXCEPTION_HANDLER}. The imperative sibling is
|
|
2088
|
+
* `app.useGlobalExceptionHandler(handler)`.
|
|
2089
|
+
*
|
|
2090
|
+
* ```ts
|
|
2091
|
+
* @Module({
|
|
2092
|
+
* imports: [ErrorsModule.forRoot({ catalogs: [ordersCatalog], handler: SentryHandler })],
|
|
2093
|
+
* })
|
|
2094
|
+
* class AppModule {}
|
|
2095
|
+
* ```
|
|
2096
|
+
*/
|
|
2097
|
+
var ErrorsModule = class extends ConfigurableModuleClass {};
|
|
2098
|
+
//#endregion
|
|
2099
|
+
//#region src/validation/create-zod-dto.ts
|
|
2100
|
+
function createZodDto(schema, options = {}) {
|
|
2101
|
+
const className = options.name ?? "ZodDto";
|
|
2102
|
+
return { [className]: class {
|
|
2103
|
+
static schema = schema;
|
|
2104
|
+
constructor(initial) {
|
|
2105
|
+
if (initial && typeof initial === "object") Object.assign(this, initial);
|
|
2106
|
+
}
|
|
2107
|
+
} }[className];
|
|
2108
|
+
}
|
|
2109
|
+
//#endregion
|
|
2110
|
+
//#region src/validation/validation.pipe.ts
|
|
2111
|
+
var ValidationPipe = class {
|
|
2112
|
+
transform(value, metadata) {
|
|
2113
|
+
const metatype = metadata.metatype;
|
|
2114
|
+
if (!metatype?.schema?.parse) return value;
|
|
2115
|
+
try {
|
|
2116
|
+
return metatype.schema.parse(value);
|
|
2117
|
+
} catch (error) {
|
|
2118
|
+
if (error && typeof error === "object" && "issues" in error && Array.isArray(error.issues)) throw new BadRequestException({
|
|
2119
|
+
statusCode: 400,
|
|
2120
|
+
message: "Validation failed",
|
|
2121
|
+
errors: error.issues
|
|
2122
|
+
});
|
|
2123
|
+
throw error;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
//#endregion
|
|
2128
|
+
//#region src/serialization/serialize.decorator.ts
|
|
2129
|
+
const SERIALIZE_METADATA = "vela:serialize";
|
|
2130
|
+
function Serialize(dto) {
|
|
2131
|
+
return (target, propertyKey) => {
|
|
2132
|
+
MetadataRegistry.setCustomHandlerMeta(target.constructor, propertyKey, SERIALIZE_METADATA, dto);
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
//#endregion
|
|
2136
|
+
//#region src/serialization/serializer.interceptor.ts
|
|
2137
|
+
var SerializerInterceptor = class {
|
|
2138
|
+
async intercept(context, next) {
|
|
2139
|
+
const result = await next.handle();
|
|
2140
|
+
const controller = context.getClass();
|
|
2141
|
+
const handler = context.getHandler();
|
|
2142
|
+
const schema = MetadataRegistry.getCustomHandlerMeta(controller, handler, SERIALIZE_METADATA)?.schema;
|
|
2143
|
+
if (!schema?.parse) return result;
|
|
2144
|
+
if (Array.isArray(result)) return result.map((item) => schema.parse(item));
|
|
2145
|
+
return schema.parse(result);
|
|
2146
|
+
}
|
|
2147
|
+
};
|
|
2148
|
+
//#endregion
|
|
2149
|
+
export { CacheTTL as $, ThrottlerStorage as A, zodToJsonSchema as At, Cron as B, ZodValidationPipe as C, getRequestContainer as Ct, SkipThrottle as D, createLazyParamDecorator as Dt, runInEntrypointScope as E, getCurrentRequestContext as Et, THROTTLE_METADATA as F, EventEmitterSubscriber as G, ScheduleModule as H, HealthModule as I, lazyProvider as J, ON_EVENT_METADATA as K, HttpHealthIndicator as L, SKIP_THROTTLE_METADATA as M, ApiResponse as Mt, THROTTLER_OPTIONS as N, ApiTags as Nt, Throttle as O, mixin as Ot, THROTTLER_STORAGE as P, VelaFactory as Pt, CacheKey as Q, HealthIndicatorService as R, RequiredPipe as S, Logger as St, buildEntrypointExecutionContext as T, getCurrentContainer as Tt, OnEvent as U, Interval as V, EventEmitterModule as W, provideGlobal as X, moduleToken as Y, sideEffectModule as Z, ParseBoolPipe as _, registerAs as _t, env as a, CACHE_KEY_METADATA as at, ParseIntPipe as b, ConfigStore as bt, toErrorBody$1 as c, CACHE_TTL_METADATA as ct, Serialize as d, CorsModule as dt, TieredCacheStore as et, ValidationPipe as f, CORS_OPTIONS as ft, ParseArrayPipe as g, HttpService as gt, DefaultValuePipe as h, HttpRequestException as ht, defineErrorCatalog as i, CacheInterceptor as it, ThrottlerGuard as j, ApiDoc as jt, ThrottlerModule as k, createOpenApiDocument as kt, SerializerInterceptor as l, Reflector as lt, ErrorsModule as m, HTTP_MODULE_OPTIONS as mt, VelaError as n, MemoryCacheStore as nt, getRuntimeKey as o, CACHE_MANAGER as ot, createZodDto as p, HttpModule as pt, EventEmitter as q, composeCatalogs$1 as r, CacheService as rt, isVelaError$1 as s, CACHE_MODULE_OPTIONS as st, CORE_CATALOG$1 as t, CacheModule as tt, SERIALIZE_METADATA as u, SetMetadata as ut, ParseEnumPipe as v, ConfigModule as vt, resolveScopedComponents as w, enableAmbientContainer as wt, ParseUUIDPipe as x, LogLevel as xt, ParseFloatPipe as y, ConfigService as yt, HealthCheckService as z };
|
|
2150
|
+
|
|
2151
|
+
//# sourceMappingURL=src-eb5CI6Xn.js.map
|