@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,1387 @@
|
|
|
1
|
+
import { A as getOrCreateArray, C as InjectionToken, S as ForwardRef, T as MultipleProvidersFoundError, _ 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, m as Scope, n as __decorateParam, o as Optional, r as __decorateMetadata, t as __decorate, v as APP_INTERCEPTOR, w as ModuleVisibilityError, x as ERROR_CATALOG, y as APP_MIDDLEWARE } from "./decorate-GcSMAbKn.js";
|
|
2
|
+
import { A as UseGuards, E as applyDecorators, t as RouteManager } from "./route.manager-DRAZ5X04.js";
|
|
3
|
+
import { n as resolveErrorReporter, s as ForbiddenException, t as DiscoveryService } from "./discovery.service-BYm95SSD.js";
|
|
4
|
+
import { t as Container } from "./container-BqUHID4l.js";
|
|
5
|
+
import { t as REQUEST_CONTEXT } from "./request-context-C3nCGJNd.js";
|
|
6
|
+
import { n as verifySignedUrl, t as signUrl } from "./signed-url-CMmi0SIb.js";
|
|
7
|
+
import { a as isModule, i as getModuleMetadata, n as Module } from "./decorators-C8YBFCIk.js";
|
|
8
|
+
import { HTTPException } from "hono/http-exception";
|
|
9
|
+
import { toErrorBody } from "@velajs/errors";
|
|
10
|
+
//#region src/entrypoint/entrypoint.types.ts
|
|
11
|
+
function contributesEntrypoints(x) {
|
|
12
|
+
return typeof x === "object" && x !== null && typeof x.collectEntrypoints === "function";
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/entrypoint/entrypoint.registry.ts
|
|
16
|
+
const KIND_STORE_KEY = Symbol.for("vela:entrypoints:v1");
|
|
17
|
+
function kindStore() {
|
|
18
|
+
const g = globalThis;
|
|
19
|
+
return g[KIND_STORE_KEY] ??= /* @__PURE__ */ new Map();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Declare an entrypoint kind. Idempotent per `kind` (last declaration wins so
|
|
23
|
+
* an HMR-re-evaluated module can re-declare); typically called at module
|
|
24
|
+
* import time next to the decorator definition:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* export const WS_GATEWAY_METADATA = 'vela:ws:gateway';
|
|
28
|
+
* registerEntrypointKind({ kind: 'websocket', metaKey: WS_GATEWAY_METADATA, level: 'class' });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
function registerEntrypointKind(k) {
|
|
32
|
+
kindStore().set(k.kind, k);
|
|
33
|
+
}
|
|
34
|
+
/** All declared kinds (registration order). */
|
|
35
|
+
function getEntrypointKinds() {
|
|
36
|
+
return [...kindStore().values()];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The per-application view of every entrypoint: built once after
|
|
40
|
+
* `onApplicationBootstrap` hooks have run (so `ContributesEntrypoints`
|
|
41
|
+
* providers have finished their own discovery), queried by runtime adapters:
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* for (const ep of app.entrypoints.ofKind('websocket')) { ... }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* Per-app (never global): two applications in one process each build their
|
|
48
|
+
* own registry from their own container.
|
|
49
|
+
*/
|
|
50
|
+
var EntrypointRegistry = class EntrypointRegistry {
|
|
51
|
+
byKind = /* @__PURE__ */ new Map();
|
|
52
|
+
static async build(discovery, eagerInstances, options = {}) {
|
|
53
|
+
const registry = new EntrypointRegistry();
|
|
54
|
+
const filter = options.deferLazy ? { deferLazy: true } : void 0;
|
|
55
|
+
for (const kind of getEntrypointKinds()) if (kind.level === "class") for (const found of discovery.providersWithMeta(kind.metaKey, filter)) registry.add({
|
|
56
|
+
kind: kind.kind,
|
|
57
|
+
token: found.token,
|
|
58
|
+
instance: found.instance,
|
|
59
|
+
meta: found.meta
|
|
60
|
+
});
|
|
61
|
+
else for (const found of discovery.methodsWithMeta(kind.metaKey, filter)) registry.add({
|
|
62
|
+
kind: kind.kind,
|
|
63
|
+
token: found.class.token,
|
|
64
|
+
instance: found.class.instance,
|
|
65
|
+
methodName: found.methodName,
|
|
66
|
+
meta: found.meta
|
|
67
|
+
});
|
|
68
|
+
const contributed = [];
|
|
69
|
+
for (const instance of new Set(eagerInstances)) {
|
|
70
|
+
if (!contributesEntrypoints(instance)) continue;
|
|
71
|
+
contributed.push(...await instance.collectEntrypoints(discovery));
|
|
72
|
+
}
|
|
73
|
+
for (const kind of new Set(contributed.map((ep) => ep.kind))) registry.byKind.delete(kind);
|
|
74
|
+
for (const ep of contributed) registry.add(ep);
|
|
75
|
+
return registry;
|
|
76
|
+
}
|
|
77
|
+
add(ep) {
|
|
78
|
+
const list = this.byKind.get(ep.kind);
|
|
79
|
+
if (list) list.push(ep);
|
|
80
|
+
else this.byKind.set(ep.kind, [ep]);
|
|
81
|
+
}
|
|
82
|
+
ofKind(kind) {
|
|
83
|
+
return this.byKind.get(kind) ?? [];
|
|
84
|
+
}
|
|
85
|
+
kinds() {
|
|
86
|
+
return [...this.byKind.keys()];
|
|
87
|
+
}
|
|
88
|
+
all() {
|
|
89
|
+
return [...this.byKind.values()].flat();
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/lifecycle/index.ts
|
|
94
|
+
function hasOnModuleInit(instance) {
|
|
95
|
+
return instance !== null && typeof instance === "object" && typeof instance.onModuleInit === "function";
|
|
96
|
+
}
|
|
97
|
+
function hasOnApplicationBootstrap(instance) {
|
|
98
|
+
return instance !== null && typeof instance === "object" && typeof instance.onApplicationBootstrap === "function";
|
|
99
|
+
}
|
|
100
|
+
function hasOnModuleDestroy(instance) {
|
|
101
|
+
return instance !== null && typeof instance === "object" && typeof instance.onModuleDestroy === "function";
|
|
102
|
+
}
|
|
103
|
+
function hasBeforeApplicationShutdown(instance) {
|
|
104
|
+
return instance !== null && typeof instance === "object" && typeof instance.beforeApplicationShutdown === "function";
|
|
105
|
+
}
|
|
106
|
+
function hasOnApplicationShutdown(instance) {
|
|
107
|
+
return instance !== null && typeof instance === "object" && typeof instance.onApplicationShutdown === "function";
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/module/lazy-modules.ts
|
|
111
|
+
function isThenable(x) {
|
|
112
|
+
return x !== null && (typeof x === "object" || typeof x === "function") && typeof x.then === "function";
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Owns deferred-module state for one application: which module instances are
|
|
116
|
+
* still pending, which have been claimed by a container trigger, and how
|
|
117
|
+
* claimed groups get completed (construction + lifecycle-hook replay).
|
|
118
|
+
*
|
|
119
|
+
* Phases:
|
|
120
|
+
* - `'bootstrap'` (until the end of `callOnApplicationBootstrap`): completed
|
|
121
|
+
* groups are *absorbed* — their instances queue up for the application's
|
|
122
|
+
* normal hook phases, so a lazy module dragged in by an eager consumer gets
|
|
123
|
+
* today-identical semantics.
|
|
124
|
+
* - `'live'`: hooks replay at drain time (memoized, exactly once), then the
|
|
125
|
+
* instances are handed to the application for shutdown-hook symmetry.
|
|
126
|
+
*
|
|
127
|
+
* Sync/async duality: sync drains throw a descriptive error when a member
|
|
128
|
+
* factory or hook yields a thenable — lazy modules with async providers or
|
|
129
|
+
* hooks must be reached through an async seam (`materializeLazyModules()`,
|
|
130
|
+
* `resolveAsync`) or stay eager.
|
|
131
|
+
*/
|
|
132
|
+
var LazyModuleManager = class {
|
|
133
|
+
container;
|
|
134
|
+
pending = /* @__PURE__ */ new Map();
|
|
135
|
+
claimed = [];
|
|
136
|
+
absorbed = [];
|
|
137
|
+
phase = "bootstrap";
|
|
138
|
+
draining = false;
|
|
139
|
+
drainPromise;
|
|
140
|
+
onMaterialized;
|
|
141
|
+
constructor(container) {
|
|
142
|
+
this.container = container;
|
|
143
|
+
}
|
|
144
|
+
registerGroup(group) {
|
|
145
|
+
this.pending.set(group.moduleId, group);
|
|
146
|
+
}
|
|
147
|
+
/** Application sink for live-phase materializations (shutdown symmetry). */
|
|
148
|
+
setOnMaterialized(sink) {
|
|
149
|
+
this.onMaterialized = sink;
|
|
150
|
+
}
|
|
151
|
+
setPhaseLive() {
|
|
152
|
+
this.phase = "live";
|
|
153
|
+
}
|
|
154
|
+
isPending(moduleId) {
|
|
155
|
+
return this.pending.has(moduleId);
|
|
156
|
+
}
|
|
157
|
+
/** Tokens whose owning modules are ALL still pending are deferred. */
|
|
158
|
+
hasPendingModules() {
|
|
159
|
+
return this.pending.size > 0;
|
|
160
|
+
}
|
|
161
|
+
claim(moduleId) {
|
|
162
|
+
const group = this.pending.get(moduleId);
|
|
163
|
+
if (!group) return;
|
|
164
|
+
this.pending.delete(moduleId);
|
|
165
|
+
this.claimed.push(group);
|
|
166
|
+
}
|
|
167
|
+
hasClaimed() {
|
|
168
|
+
return this.claimed.length > 0;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A drain loop is running. The container consults this before its
|
|
172
|
+
* post-resolution drain: `constructGroupAsync` resolves members through
|
|
173
|
+
* `resolveAsync`, whose end-of-cascade check would otherwise re-enter and
|
|
174
|
+
* AWAIT the very drain promise it is executing inside — a self-referential
|
|
175
|
+
* await that never settles (with ≥2 claimed groups). Claims made while
|
|
176
|
+
* draining are picked up by the running loop instead.
|
|
177
|
+
*/
|
|
178
|
+
isDraining() {
|
|
179
|
+
return this.draining;
|
|
180
|
+
}
|
|
181
|
+
/** Instances constructed during the bootstrap phase, owed their hooks. */
|
|
182
|
+
takeAbsorbed() {
|
|
183
|
+
if (this.absorbed.length === 0) return [];
|
|
184
|
+
return this.absorbed.splice(0, this.absorbed.length);
|
|
185
|
+
}
|
|
186
|
+
drainSync() {
|
|
187
|
+
if (this.draining) return;
|
|
188
|
+
this.draining = true;
|
|
189
|
+
try {
|
|
190
|
+
while (this.claimed.length > 0) {
|
|
191
|
+
const batch = [];
|
|
192
|
+
while (this.claimed.length > 0) {
|
|
193
|
+
const group = this.claimed.shift();
|
|
194
|
+
batch.push({
|
|
195
|
+
group,
|
|
196
|
+
instances: this.constructGroupSync(group)
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
this.finishBatchSync(batch);
|
|
200
|
+
}
|
|
201
|
+
} finally {
|
|
202
|
+
this.draining = false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
drainAsync() {
|
|
206
|
+
if (this.draining) return this.drainPromise ?? Promise.resolve();
|
|
207
|
+
this.draining = true;
|
|
208
|
+
const run = (async () => {
|
|
209
|
+
try {
|
|
210
|
+
while (this.claimed.length > 0) {
|
|
211
|
+
const batch = [];
|
|
212
|
+
while (this.claimed.length > 0) {
|
|
213
|
+
const group = this.claimed.shift();
|
|
214
|
+
batch.push({
|
|
215
|
+
group,
|
|
216
|
+
instances: await this.constructGroupAsync(group)
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
await this.finishBatchAsync(batch);
|
|
220
|
+
}
|
|
221
|
+
} finally {
|
|
222
|
+
this.draining = false;
|
|
223
|
+
this.drainPromise = void 0;
|
|
224
|
+
}
|
|
225
|
+
})();
|
|
226
|
+
this.drainPromise = run;
|
|
227
|
+
return run;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Materialize every still-pending group whose providers compute entrypoints
|
|
231
|
+
* (`collectEntrypoints` on a class prototype). Called by the application
|
|
232
|
+
* right before the entrypoint-registry snapshot so computed contributions
|
|
233
|
+
* are never silently absent. The cost — those modules are effectively
|
|
234
|
+
* eager — is the documented price of contributing computed entrypoints.
|
|
235
|
+
*/
|
|
236
|
+
async materializeContributors() {
|
|
237
|
+
for (const group of [...this.pending.values()]) if (group.hasEntrypointContributor) this.claim(group.moduleId);
|
|
238
|
+
await this.drainAsync();
|
|
239
|
+
}
|
|
240
|
+
/** Materialize everything still pending (warmup / tests / node runtimes). */
|
|
241
|
+
async materializeAll() {
|
|
242
|
+
for (const moduleId of [...this.pending.keys()]) this.claim(moduleId);
|
|
243
|
+
await this.drainAsync();
|
|
244
|
+
}
|
|
245
|
+
groupTokensToConstruct(group) {
|
|
246
|
+
return group.tokens.filter((token) => this.container.getProviderScope(token) !== Scope.REQUEST);
|
|
247
|
+
}
|
|
248
|
+
constructGroupSync(group) {
|
|
249
|
+
const out = /* @__PURE__ */ new Set();
|
|
250
|
+
for (const token of this.groupTokensToConstruct(group)) try {
|
|
251
|
+
out.add(this.container.resolve(token, group.moduleId));
|
|
252
|
+
} catch (error) {
|
|
253
|
+
if (error instanceof Error && error.message.includes("returned a Promise")) throw this.describeSyncFailure(group.moduleId, error);
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
return [...out];
|
|
257
|
+
}
|
|
258
|
+
async constructGroupAsync(group) {
|
|
259
|
+
const out = /* @__PURE__ */ new Set();
|
|
260
|
+
for (const token of this.groupTokensToConstruct(group)) out.add(await this.container.resolveAsync(token, group.moduleId));
|
|
261
|
+
return [...out];
|
|
262
|
+
}
|
|
263
|
+
/** Reversed batch = dependency-before-consumer (see drainSync comment). */
|
|
264
|
+
orderBatch(batch) {
|
|
265
|
+
return [...batch].reverse();
|
|
266
|
+
}
|
|
267
|
+
finishBatchSync(batch) {
|
|
268
|
+
const ordered = this.orderBatch(batch);
|
|
269
|
+
if (this.phase === "bootstrap") {
|
|
270
|
+
for (const { instances } of ordered) this.absorbed.push(...instances);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
for (const { group, instances } of ordered) for (const instance of instances) if (hasOnModuleInit(instance) && isThenable(instance.onModuleInit())) throw this.describeSyncFailure(group.moduleId);
|
|
274
|
+
for (const { group, instances } of ordered) for (const instance of instances) if (hasOnApplicationBootstrap(instance) && isThenable(instance.onApplicationBootstrap())) throw this.describeSyncFailure(group.moduleId);
|
|
275
|
+
this.onMaterialized?.(ordered.flatMap((b) => b.instances));
|
|
276
|
+
}
|
|
277
|
+
async finishBatchAsync(batch) {
|
|
278
|
+
const ordered = this.orderBatch(batch);
|
|
279
|
+
if (this.phase === "bootstrap") {
|
|
280
|
+
for (const { instances } of ordered) this.absorbed.push(...instances);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
for (const { instances } of ordered) for (const instance of instances) if (hasOnModuleInit(instance)) await instance.onModuleInit();
|
|
284
|
+
for (const { instances } of ordered) for (const instance of instances) if (hasOnApplicationBootstrap(instance)) await instance.onApplicationBootstrap();
|
|
285
|
+
this.onMaterialized?.(ordered.flatMap((b) => b.instances));
|
|
286
|
+
}
|
|
287
|
+
describeSyncFailure(moduleId, cause) {
|
|
288
|
+
return new Error(`[vela] lazy module '${moduleId}' has async providers or lifecycle hooks and was triggered through a synchronous resolution path. Reach it through an async seam first (app.materializeLazyModules(), an async provider) or remove lazy: true.`, cause !== void 0 ? { cause } : void 0);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/openapi/scalar-ui.ts
|
|
293
|
+
function renderScalarUi(jsonUrl, title) {
|
|
294
|
+
const safeUrl = jsonUrl.replace(/"/g, """);
|
|
295
|
+
return `<!doctype html>
|
|
296
|
+
<html>
|
|
297
|
+
<head>
|
|
298
|
+
<title>${(title ?? "API Reference").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</title>
|
|
299
|
+
<meta charset="utf-8" />
|
|
300
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
301
|
+
</head>
|
|
302
|
+
<body>
|
|
303
|
+
<script id="api-reference" data-url="${safeUrl}"><\/script>
|
|
304
|
+
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
305
|
+
</body>
|
|
306
|
+
</html>`;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/openapi/swagger-ui.ts
|
|
310
|
+
function renderSwaggerUi(specUrl, title) {
|
|
311
|
+
const safeUrl = specUrl.replace(/"/g, """);
|
|
312
|
+
return `<!doctype html>
|
|
313
|
+
<html>
|
|
314
|
+
<head>
|
|
315
|
+
<title>${(title ?? "API Reference").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</title>
|
|
316
|
+
<meta charset="utf-8" />
|
|
317
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
318
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui.css" />
|
|
319
|
+
</head>
|
|
320
|
+
<body>
|
|
321
|
+
<div id="swagger-ui"></div>
|
|
322
|
+
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui-bundle.js"><\/script>
|
|
323
|
+
<script>
|
|
324
|
+
window.ui = SwaggerUIBundle({ url: "${safeUrl}", dom_id: '#swagger-ui' });
|
|
325
|
+
<\/script>
|
|
326
|
+
</body>
|
|
327
|
+
</html>`;
|
|
328
|
+
}
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region src/openapi/redoc-ui.ts
|
|
331
|
+
function renderRedocUi(specUrl, title) {
|
|
332
|
+
const safeUrl = specUrl.replace(/"/g, """);
|
|
333
|
+
return `<!doctype html>
|
|
334
|
+
<html>
|
|
335
|
+
<head>
|
|
336
|
+
<title>${(title ?? "API Reference").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</title>
|
|
337
|
+
<meta charset="utf-8" />
|
|
338
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
339
|
+
</head>
|
|
340
|
+
<body>
|
|
341
|
+
<redoc spec-url="${safeUrl}"></redoc>
|
|
342
|
+
<script src="https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"><\/script>
|
|
343
|
+
</body>
|
|
344
|
+
</html>`;
|
|
345
|
+
}
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/application.ts
|
|
348
|
+
var VelaApplication = class {
|
|
349
|
+
container;
|
|
350
|
+
routeManager;
|
|
351
|
+
instances = [];
|
|
352
|
+
honoApp = null;
|
|
353
|
+
entrypointRegistry = null;
|
|
354
|
+
disposed = false;
|
|
355
|
+
lazyManager;
|
|
356
|
+
knownInstances = /* @__PURE__ */ new Set();
|
|
357
|
+
constructor(container, routeManager) {
|
|
358
|
+
this.container = container;
|
|
359
|
+
this.routeManager = routeManager;
|
|
360
|
+
this.lazyManager = container.has(LazyModuleManager) ? container.resolve(LazyModuleManager) : void 0;
|
|
361
|
+
this.lazyManager?.setOnMaterialized((instances) => {
|
|
362
|
+
this.instances.push(...this.trackNew(instances));
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
trackNew(batch) {
|
|
366
|
+
const fresh = batch.filter((i) => !this.knownInstances.has(i));
|
|
367
|
+
for (const i of fresh) this.knownInstances.add(i);
|
|
368
|
+
return fresh;
|
|
369
|
+
}
|
|
370
|
+
/** Pre-build routes (handles async CRUD imports). Called by VelaFactory. */
|
|
371
|
+
async initRoutes() {
|
|
372
|
+
this.honoApp = await this.routeManager.build();
|
|
373
|
+
this.honoApp.onError((err, c) => {
|
|
374
|
+
const reporter = resolveErrorReporter(this.container);
|
|
375
|
+
if (err instanceof HTTPException) {
|
|
376
|
+
if (err.status >= 500) reporter.report(err, {
|
|
377
|
+
edge: "hono",
|
|
378
|
+
source: `${c.req.method} ${c.req.path}`
|
|
379
|
+
});
|
|
380
|
+
return err.getResponse();
|
|
381
|
+
}
|
|
382
|
+
reporter.report(err, {
|
|
383
|
+
edge: "hono",
|
|
384
|
+
source: `${c.req.method} ${c.req.path}`
|
|
385
|
+
});
|
|
386
|
+
const { body, status } = toErrorBody(err, { catalog: reporter.catalog });
|
|
387
|
+
return c.json(body, status);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
getApp() {
|
|
391
|
+
if (!this.honoApp) throw new Error("Routes not built. This should not happen — VelaFactory.create() builds routes automatically.");
|
|
392
|
+
return this.honoApp;
|
|
393
|
+
}
|
|
394
|
+
get fetch() {
|
|
395
|
+
return this.getApp().fetch;
|
|
396
|
+
}
|
|
397
|
+
getInstances() {
|
|
398
|
+
return this.instances;
|
|
399
|
+
}
|
|
400
|
+
getContainer() {
|
|
401
|
+
return this.container;
|
|
402
|
+
}
|
|
403
|
+
setInstances(instances) {
|
|
404
|
+
this.instances = instances;
|
|
405
|
+
this.knownInstances.clear();
|
|
406
|
+
for (const i of instances) this.knownInstances.add(i);
|
|
407
|
+
}
|
|
408
|
+
get(token) {
|
|
409
|
+
return this.container.resolve(token);
|
|
410
|
+
}
|
|
411
|
+
getHonoApp() {
|
|
412
|
+
return this.getApp();
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Every explicit controller route as the framework registered it (fully
|
|
416
|
+
* composed paths — the `vela route list` seam). Requires built routes;
|
|
417
|
+
* contributed routes (`@velajs/crud`) mount directly on Hono and are
|
|
418
|
+
* observable via `getHonoApp().routes` instead.
|
|
419
|
+
*/
|
|
420
|
+
describeRoutes() {
|
|
421
|
+
this.getApp();
|
|
422
|
+
return this.routeManager.getRouteDescriptions();
|
|
423
|
+
}
|
|
424
|
+
/** The global route prefix in effect ('' when none). */
|
|
425
|
+
getGlobalPrefix() {
|
|
426
|
+
return this.routeManager.getGlobalPrefix();
|
|
427
|
+
}
|
|
428
|
+
useGlobalPipes(...pipes) {
|
|
429
|
+
this.routeManager.useGlobalPipes(...pipes);
|
|
430
|
+
return this;
|
|
431
|
+
}
|
|
432
|
+
useGlobalGuards(...guards) {
|
|
433
|
+
this.routeManager.useGlobalGuards(...guards);
|
|
434
|
+
return this;
|
|
435
|
+
}
|
|
436
|
+
useGlobalInterceptors(...interceptors) {
|
|
437
|
+
this.routeManager.useGlobalInterceptors(...interceptors);
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
useGlobalFilters(...filters) {
|
|
441
|
+
this.routeManager.useGlobalFilters(...filters);
|
|
442
|
+
return this;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Register the application-wide {@link ExceptionHandler} imperatively — the
|
|
446
|
+
* sibling of `ErrorsModule.forRoot({ handler })`. A class is constructed
|
|
447
|
+
* through DI (`useClass`); a plain handler object is registered verbatim
|
|
448
|
+
* (`useValue`). Consumed by `resolveErrorReporter` at every transport edge,
|
|
449
|
+
* so it takes effect on the next request without a rebuild.
|
|
450
|
+
*
|
|
451
|
+
* ```ts
|
|
452
|
+
* app.useGlobalExceptionHandler({ report: (e) => sentry.capture(e) });
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
useGlobalExceptionHandler(handler) {
|
|
456
|
+
this.container.register(typeof handler === "function" ? {
|
|
457
|
+
provide: APP_EXCEPTION_HANDLER,
|
|
458
|
+
useClass: handler
|
|
459
|
+
} : {
|
|
460
|
+
provide: APP_EXCEPTION_HANDLER,
|
|
461
|
+
useValue: handler
|
|
462
|
+
});
|
|
463
|
+
return this;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Serve a pre-built OpenAPI document and one or more interactive doc UIs
|
|
467
|
+
* (Swagger UI, Scalar, ReDoc) on the underlying Hono app, mirroring the
|
|
468
|
+
* hono-crud docs convention. Edge-safe: each UI is a tiny self-contained
|
|
469
|
+
* HTML shell that loads its renderer from a CDN at runtime so nothing is
|
|
470
|
+
* bundled server-side and no extra dependency is required.
|
|
471
|
+
*
|
|
472
|
+
* Defaults: spec at `/openapi.json`, Scalar at `/scalar`, Swagger UI at
|
|
473
|
+
* `/docs`, ReDoc at `/redoc`. The deprecated `path` / `uiPath` aliases are
|
|
474
|
+
* retained for migration from the previous single-UI shape.
|
|
475
|
+
*
|
|
476
|
+
* ```ts
|
|
477
|
+
* const doc = createOpenApiDocument(AppModule);
|
|
478
|
+
* app.mountOpenApi({ document: doc }); // Scalar @ /scalar
|
|
479
|
+
* app.mountOpenApi({ document: doc, ui: 'all' }); // swagger + scalar + redoc
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
mountOpenApi(options) {
|
|
483
|
+
const app = this.getApp();
|
|
484
|
+
const doc = options.document;
|
|
485
|
+
const title = options.title;
|
|
486
|
+
const specPath = options.specPath ?? options.path ?? "/openapi.json";
|
|
487
|
+
app.get(specPath, (c) => c.json(doc));
|
|
488
|
+
const uiOption = options.ui;
|
|
489
|
+
let uis;
|
|
490
|
+
let singleStringUi = false;
|
|
491
|
+
if (uiOption === void 0) uis = ["scalar"];
|
|
492
|
+
else if (uiOption === "all") uis = [
|
|
493
|
+
"swagger",
|
|
494
|
+
"scalar",
|
|
495
|
+
"redoc"
|
|
496
|
+
];
|
|
497
|
+
else if (Array.isArray(uiOption)) uis = uiOption;
|
|
498
|
+
else {
|
|
499
|
+
uis = [uiOption];
|
|
500
|
+
singleStringUi = true;
|
|
501
|
+
}
|
|
502
|
+
for (const ui of uis) {
|
|
503
|
+
const legacyPath = singleStringUi && uis.length === 1 ? options.uiPath : void 0;
|
|
504
|
+
if (ui === "swagger") {
|
|
505
|
+
const path = legacyPath ?? options.swaggerPath ?? "/docs";
|
|
506
|
+
const html = renderSwaggerUi(specPath, title);
|
|
507
|
+
app.get(path, (c) => c.html(html));
|
|
508
|
+
} else if (ui === "redoc") {
|
|
509
|
+
const path = legacyPath ?? options.redocPath ?? "/redoc";
|
|
510
|
+
const html = renderRedocUi(specPath, title);
|
|
511
|
+
app.get(path, (c) => c.html(html));
|
|
512
|
+
} else {
|
|
513
|
+
const path = legacyPath ?? options.scalarPath ?? "/scalar";
|
|
514
|
+
const html = renderScalarUi(specPath, title);
|
|
515
|
+
app.get(path, (c) => c.html(html));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return this;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Pull instances materialized during the bootstrap phase (lazy modules
|
|
522
|
+
* dragged in by eager consumers) into the front of the instance list —
|
|
523
|
+
* dependency-before-consumer: a group absorbed because an eager provider
|
|
524
|
+
* injected it must be initialized before that consumer's hooks read it.
|
|
525
|
+
*/
|
|
526
|
+
absorbLazyInstances(prepend) {
|
|
527
|
+
const batch = this.trackNew(this.lazyManager?.takeAbsorbed() ?? []);
|
|
528
|
+
if (batch.length === 0) return batch;
|
|
529
|
+
if (prepend) this.instances = [...batch, ...this.instances];
|
|
530
|
+
else this.instances.push(...batch);
|
|
531
|
+
return batch;
|
|
532
|
+
}
|
|
533
|
+
async callOnModuleInit() {
|
|
534
|
+
this.absorbLazyInstances(true);
|
|
535
|
+
for (let i = 0; i < this.instances.length; i++) {
|
|
536
|
+
const instance = this.instances[i];
|
|
537
|
+
if (hasOnModuleInit(instance)) await instance.onModuleInit();
|
|
538
|
+
this.absorbLazyInstances(false);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
async callOnApplicationBootstrap() {
|
|
542
|
+
for (let i = 0; i < this.instances.length; i++) {
|
|
543
|
+
const instance = this.instances[i];
|
|
544
|
+
if (hasOnApplicationBootstrap(instance)) await instance.onApplicationBootstrap();
|
|
545
|
+
for (const late of this.absorbLazyInstances(false)) if (hasOnModuleInit(late)) await late.onModuleInit();
|
|
546
|
+
}
|
|
547
|
+
if (this.lazyManager) {
|
|
548
|
+
await this.lazyManager.materializeContributors();
|
|
549
|
+
let batch;
|
|
550
|
+
while ((batch = this.absorbLazyInstances(false)).length > 0) {
|
|
551
|
+
for (const late of batch) if (hasOnModuleInit(late)) await late.onModuleInit();
|
|
552
|
+
for (const late of batch) if (hasOnApplicationBootstrap(late)) await late.onApplicationBootstrap();
|
|
553
|
+
}
|
|
554
|
+
this.lazyManager.setPhaseLive();
|
|
555
|
+
}
|
|
556
|
+
const discovery = this.container.has(DiscoveryService) ? this.container.resolve(DiscoveryService) : new DiscoveryService(this.container);
|
|
557
|
+
this.entrypointRegistry = await EntrypointRegistry.build(discovery, this.instances, { deferLazy: true });
|
|
558
|
+
this.container.register({
|
|
559
|
+
provide: EntrypointRegistry,
|
|
560
|
+
useValue: this.entrypointRegistry
|
|
561
|
+
});
|
|
562
|
+
this.container.markGlobalToken(EntrypointRegistry);
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Materialize every still-pending lazy module (async-safe): construct the
|
|
566
|
+
* groups, replay their lifecycle hooks, and add their instances to the
|
|
567
|
+
* shutdown flow. Warmup escape hatch for tests and node runtimes that want
|
|
568
|
+
* eager-everything semantics back after bootstrap.
|
|
569
|
+
*/
|
|
570
|
+
async materializeLazyModules() {
|
|
571
|
+
await this.lazyManager?.materializeAll();
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Every entrypoint contributed by the module graph, grouped by kind —
|
|
575
|
+
* what runtime adapters/transports query instead of re-scanning providers:
|
|
576
|
+
* `app.entrypoints.ofKind('websocket')`.
|
|
577
|
+
*/
|
|
578
|
+
get entrypoints() {
|
|
579
|
+
if (!this.entrypointRegistry) throw new Error("Entrypoints are not built yet — they are assembled at the end of callOnApplicationBootstrap(). Finish bootstrapping before querying them.");
|
|
580
|
+
return this.entrypointRegistry;
|
|
581
|
+
}
|
|
582
|
+
async close(signal) {
|
|
583
|
+
const reversed = [...this.instances].reverse();
|
|
584
|
+
for (const instance of reversed) if (hasBeforeApplicationShutdown(instance)) await instance.beforeApplicationShutdown(signal);
|
|
585
|
+
for (const instance of reversed) if (hasOnModuleDestroy(instance)) await instance.onModuleDestroy();
|
|
586
|
+
for (const instance of reversed) if (hasOnApplicationShutdown(instance)) await instance.onApplicationShutdown(signal);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Full teardown: run shutdown lifecycle hooks ({@link close}) then dispose
|
|
590
|
+
* container-held instances (LIFO) and clear cached singletons. Use for
|
|
591
|
+
* graceful shutdown and dev HMR so old and new DI graphs never coexist.
|
|
592
|
+
*
|
|
593
|
+
* On runtimes/TS supporting explicit resource management this is also exposed
|
|
594
|
+
* as `Symbol.asyncDispose`, enabling `await using app = await VelaFactory.create(...)`.
|
|
595
|
+
*/
|
|
596
|
+
async dispose(signal) {
|
|
597
|
+
if (this.disposed) return;
|
|
598
|
+
this.disposed = true;
|
|
599
|
+
await this.close(signal);
|
|
600
|
+
await this.container.dispose();
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
const ASYNC_DISPOSE = Symbol.asyncDispose;
|
|
604
|
+
if (ASYNC_DISPOSE) VelaApplication.prototype[ASYNC_DISPOSE] = function() {
|
|
605
|
+
return this.dispose();
|
|
606
|
+
};
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/container/module-ref.ts
|
|
609
|
+
let ModuleRef = class ModuleRef {
|
|
610
|
+
container;
|
|
611
|
+
constructor(container) {
|
|
612
|
+
this.container = container;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Retrieve a provider instance from the DI container.
|
|
616
|
+
* Returns the existing singleton (or cached value) for the token.
|
|
617
|
+
*/
|
|
618
|
+
get(token) {
|
|
619
|
+
return this.container.resolve(token);
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Resolve a provider, creating a new instance for TRANSIENT-scoped providers.
|
|
623
|
+
* For SINGLETON-scoped providers this is equivalent to get().
|
|
624
|
+
*/
|
|
625
|
+
resolve(token) {
|
|
626
|
+
return this.container.resolve(token);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Instantiate a class outside of the DI container's singleton cache.
|
|
630
|
+
* Dependencies are resolved from the container. Each call returns a new instance.
|
|
631
|
+
*/
|
|
632
|
+
create(type) {
|
|
633
|
+
const sandbox = this.container.createDetached();
|
|
634
|
+
sandbox.register({
|
|
635
|
+
provide: type,
|
|
636
|
+
useClass: type,
|
|
637
|
+
scope: Scope.TRANSIENT
|
|
638
|
+
});
|
|
639
|
+
return sandbox.resolve(type);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
ModuleRef = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [Object])], ModuleRef);
|
|
643
|
+
//#endregion
|
|
644
|
+
//#region src/config/config.tokens.ts
|
|
645
|
+
const CONFIG_OPTIONS = new InjectionToken("CONFIG_OPTIONS");
|
|
646
|
+
/**
|
|
647
|
+
* Ambient environment record consumed by config-namespace factories
|
|
648
|
+
* (`registerAs`). It is the multi-runtime substitute for stratal's
|
|
649
|
+
* Cloudflare-specific `env` token: core never touches `process.env`.
|
|
650
|
+
*
|
|
651
|
+
* The token self-provides `{}` by default (so factories resolve even with no
|
|
652
|
+
* platform binding), and stays OVERRIDABLE — a platform adapter
|
|
653
|
+
* (`@velajs/cloudflare`) or a future `./config-node` subpath provides a global
|
|
654
|
+
* `CONFIG_ENV` and that registration wins over the default.
|
|
655
|
+
*/
|
|
656
|
+
const CONFIG_ENV = new InjectionToken("CONFIG_ENV", { factory: () => ({}) });
|
|
657
|
+
//#endregion
|
|
658
|
+
//#region src/http/url/signing-secret.ts
|
|
659
|
+
/**
|
|
660
|
+
* Optional DI token holding the HMAC secret used to sign / verify URLs. Provide
|
|
661
|
+
* it globally (e.g. from a platform adapter or a `@Global` module) so both
|
|
662
|
+
* {@link UrlGeneratorService} and the signed-URL guard can read it:
|
|
663
|
+
*
|
|
664
|
+
* ```ts
|
|
665
|
+
* { provide: URL_SIGNING_SECRET, useValue: env.URL_SIGNING_SECRET }
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
const URL_SIGNING_SECRET = new InjectionToken("URL_SIGNING_SECRET");
|
|
669
|
+
/** Key read from `CONFIG_ENV` when no explicit secret / token is available. */
|
|
670
|
+
const URL_SIGNING_SECRET_ENV_KEY = "URL_SIGNING_SECRET";
|
|
671
|
+
/**
|
|
672
|
+
* Resolve the signing secret from, in order: an explicit argument, the
|
|
673
|
+
* {@link URL_SIGNING_SECRET} token, then `CONFIG_ENV[URL_SIGNING_SECRET]`.
|
|
674
|
+
* Throws a descriptive error when none is available — signing must never fall
|
|
675
|
+
* back to an empty/implicit key.
|
|
676
|
+
*/
|
|
677
|
+
function resolveSigningSecret(explicit, token, env) {
|
|
678
|
+
const fromEnv = env?.[URL_SIGNING_SECRET_ENV_KEY];
|
|
679
|
+
const secret = explicit ?? token ?? (typeof fromEnv === "string" ? fromEnv : void 0);
|
|
680
|
+
if (!secret) throw new Error("No URL signing secret is available. Pass one explicitly, register a `URL_SIGNING_SECRET` provider, or set `URL_SIGNING_SECRET` in `CONFIG_ENV`.");
|
|
681
|
+
return secret;
|
|
682
|
+
}
|
|
683
|
+
//#endregion
|
|
684
|
+
//#region src/http/url/url-generator.service.ts
|
|
685
|
+
let UrlGeneratorService = class UrlGeneratorService {
|
|
686
|
+
routeManager;
|
|
687
|
+
secretToken;
|
|
688
|
+
env;
|
|
689
|
+
routeMap = null;
|
|
690
|
+
constructor(routeManager, secretToken, env = {}) {
|
|
691
|
+
this.routeManager = routeManager;
|
|
692
|
+
this.secretToken = secretToken;
|
|
693
|
+
this.env = env;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Build the path for a named route, filling `:param` placeholders from
|
|
697
|
+
* `params`. Params that don't match a placeholder become query-string
|
|
698
|
+
* entries; `opts.query` is merged after them.
|
|
699
|
+
*
|
|
700
|
+
* @throws if no route carries `name`, or a required `:param` is missing.
|
|
701
|
+
*/
|
|
702
|
+
urlFor(name, params, opts) {
|
|
703
|
+
const description = this.routes().get(name);
|
|
704
|
+
if (!description) throw new Error(`No route named "${String(name)}" was found. Give the route a name via \`@Get(path, { name: '${String(name)}' })\`.`);
|
|
705
|
+
const provided = { ...params ?? {} };
|
|
706
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
707
|
+
const path = description.path.replace(/:([A-Za-z0-9_]+)/g, (_match, key) => {
|
|
708
|
+
const value = provided[key];
|
|
709
|
+
if (value === void 0 || value === null) throw new Error(`Missing route param "${key}" for route "${String(name)}".`);
|
|
710
|
+
consumed.add(key);
|
|
711
|
+
return encodeURIComponent(String(value));
|
|
712
|
+
});
|
|
713
|
+
const query = new URLSearchParams();
|
|
714
|
+
for (const [key, value] of Object.entries(provided)) {
|
|
715
|
+
if (consumed.has(key) || value === void 0 || value === null) continue;
|
|
716
|
+
query.set(key, String(value));
|
|
717
|
+
}
|
|
718
|
+
for (const [key, value] of Object.entries(opts?.query ?? {})) {
|
|
719
|
+
if (value === void 0 || value === null) continue;
|
|
720
|
+
query.set(key, String(value));
|
|
721
|
+
}
|
|
722
|
+
const qs = query.toString();
|
|
723
|
+
return qs ? `${path}?${qs}` : path;
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Build a named-route URL and HMAC-sign it (path + query). The secret comes
|
|
727
|
+
* from `options.secret`, else the {@link URL_SIGNING_SECRET} token, else
|
|
728
|
+
* `CONFIG_ENV`; a descriptive error is thrown when none is available.
|
|
729
|
+
*/
|
|
730
|
+
async signedUrl(name, params, options = {}) {
|
|
731
|
+
return signUrl(this.urlFor(name, params), resolveSigningSecret(options.secret, this.secretToken, this.env), options.expiresIn !== void 0 ? { expiresIn: options.expiresIn } : void 0);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Lazily index named route descriptions. Rebuilt while empty (routes may not
|
|
735
|
+
* be built yet), cached once populated.
|
|
736
|
+
*/
|
|
737
|
+
routes() {
|
|
738
|
+
if (this.routeMap && this.routeMap.size > 0) return this.routeMap;
|
|
739
|
+
const map = /* @__PURE__ */ new Map();
|
|
740
|
+
for (const description of this.routeManager.getRouteDescriptions()) if (description.name && !map.has(description.name)) map.set(description.name, description);
|
|
741
|
+
this.routeMap = map;
|
|
742
|
+
return map;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
UrlGeneratorService = __decorate([
|
|
746
|
+
Injectable(),
|
|
747
|
+
__decorateParam(0, Inject(RouteManager)),
|
|
748
|
+
__decorateParam(1, Optional()),
|
|
749
|
+
__decorateParam(1, Inject(URL_SIGNING_SECRET)),
|
|
750
|
+
__decorateParam(2, Optional()),
|
|
751
|
+
__decorateParam(2, Inject(CONFIG_ENV)),
|
|
752
|
+
__decorateMetadata("design:paramtypes", [
|
|
753
|
+
typeof RouteManager === "undefined" ? Object : RouteManager,
|
|
754
|
+
String,
|
|
755
|
+
typeof Record === "undefined" ? Object : Record
|
|
756
|
+
])
|
|
757
|
+
], UrlGeneratorService);
|
|
758
|
+
//#endregion
|
|
759
|
+
//#region src/http/url/signed-url.guard.ts
|
|
760
|
+
let SignedUrlGuard = class SignedUrlGuard {
|
|
761
|
+
secretToken;
|
|
762
|
+
env;
|
|
763
|
+
constructor(secretToken, env = {}) {
|
|
764
|
+
this.secretToken = secretToken;
|
|
765
|
+
this.env = env;
|
|
766
|
+
}
|
|
767
|
+
async canActivate(context) {
|
|
768
|
+
const request = context.switchToHttp().getRequest();
|
|
769
|
+
const secret = resolveSigningSecret(void 0, this.secretToken, this.env);
|
|
770
|
+
if (!await verifySignedUrl(request.url, secret)) throw new ForbiddenException("Invalid or expired signed URL");
|
|
771
|
+
return true;
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
SignedUrlGuard = __decorate([
|
|
775
|
+
Injectable(),
|
|
776
|
+
__decorateParam(0, Optional()),
|
|
777
|
+
__decorateParam(0, Inject(URL_SIGNING_SECRET)),
|
|
778
|
+
__decorateParam(1, Optional()),
|
|
779
|
+
__decorateParam(1, Inject(CONFIG_ENV)),
|
|
780
|
+
__decorateMetadata("design:paramtypes", [String, typeof Record === "undefined" ? Object : Record])
|
|
781
|
+
], SignedUrlGuard);
|
|
782
|
+
/**
|
|
783
|
+
* Guards a route with {@link SignedUrlGuard} — the request must carry a valid,
|
|
784
|
+
* unexpired HMAC signature (produced by `UrlGeneratorService.signedUrl`).
|
|
785
|
+
*
|
|
786
|
+
* ```ts
|
|
787
|
+
* @Get('download', { name: 'file.download' })
|
|
788
|
+
* @SignedUrl()
|
|
789
|
+
* download() { ... }
|
|
790
|
+
* ```
|
|
791
|
+
*/
|
|
792
|
+
function SignedUrl() {
|
|
793
|
+
return applyDecorators(UseGuards(SignedUrlGuard));
|
|
794
|
+
}
|
|
795
|
+
//#endregion
|
|
796
|
+
//#region src/module/middleware.ts
|
|
797
|
+
var MiddlewareBuilder = class {
|
|
798
|
+
definitions = [];
|
|
799
|
+
apply(...middleware) {
|
|
800
|
+
const currentMiddleware = [...middleware];
|
|
801
|
+
let currentExcludes = [];
|
|
802
|
+
let currentPriority;
|
|
803
|
+
const proxy = {
|
|
804
|
+
exclude: (...routes) => {
|
|
805
|
+
currentExcludes = routes.map(normalizeRouteArg);
|
|
806
|
+
return proxy;
|
|
807
|
+
},
|
|
808
|
+
withPriority: (priority) => {
|
|
809
|
+
currentPriority = priority;
|
|
810
|
+
return proxy;
|
|
811
|
+
},
|
|
812
|
+
forRoutes: (...routes) => {
|
|
813
|
+
this.definitions.push({
|
|
814
|
+
middleware: currentMiddleware,
|
|
815
|
+
routes: routes.flatMap(resolveRouteArg),
|
|
816
|
+
excludes: [...currentExcludes],
|
|
817
|
+
...currentPriority !== void 0 ? { priority: currentPriority } : {}
|
|
818
|
+
});
|
|
819
|
+
currentExcludes = [];
|
|
820
|
+
currentPriority = void 0;
|
|
821
|
+
return this;
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
return proxy;
|
|
825
|
+
}
|
|
826
|
+
getDefinitions() {
|
|
827
|
+
return [...this.definitions];
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
function normalizeRouteArg(route) {
|
|
831
|
+
return typeof route === "string" ? { path: route } : route;
|
|
832
|
+
}
|
|
833
|
+
function resolveRouteArg(route) {
|
|
834
|
+
if (typeof route === "string") return [{ path: route }];
|
|
835
|
+
if (typeof route === "function") return [{ path: MetadataRegistry.getControllerPath(route) || "/" }];
|
|
836
|
+
return [route];
|
|
837
|
+
}
|
|
838
|
+
//#endregion
|
|
839
|
+
//#region src/module/module-loader.ts
|
|
840
|
+
const APP_TOKENS = /* @__PURE__ */ new Set([
|
|
841
|
+
APP_GUARD,
|
|
842
|
+
APP_PIPE,
|
|
843
|
+
APP_INTERCEPTOR,
|
|
844
|
+
APP_FILTER,
|
|
845
|
+
APP_MIDDLEWARE
|
|
846
|
+
]);
|
|
847
|
+
const DEFAULT_KEY = "default";
|
|
848
|
+
/**
|
|
849
|
+
* Structural check for `ContributesEntrypoints` on a provider's class —
|
|
850
|
+
* deliberately string-coupled to the interface's method name so the loader
|
|
851
|
+
* does not import from `entrypoint/` (layering).
|
|
852
|
+
*/
|
|
853
|
+
function declaresEntrypointContributor(provider) {
|
|
854
|
+
const cls = typeof provider === "function" ? provider : provider.useClass;
|
|
855
|
+
if (typeof cls !== "function") return false;
|
|
856
|
+
return typeof cls.prototype?.collectEntrypoints === "function";
|
|
857
|
+
}
|
|
858
|
+
function isDynamicModule(value) {
|
|
859
|
+
return typeof value === "object" && value !== null && "module" in value && typeof value.module === "function";
|
|
860
|
+
}
|
|
861
|
+
function implementsNestModule(cls) {
|
|
862
|
+
return typeof cls.prototype?.configure === "function";
|
|
863
|
+
}
|
|
864
|
+
function tokenOfProvider(provider) {
|
|
865
|
+
return typeof provider === "function" ? provider : provider.provide;
|
|
866
|
+
}
|
|
867
|
+
function keyOfImport(entry) {
|
|
868
|
+
return isDynamicModule(entry) ? entry.key ?? DEFAULT_KEY : DEFAULT_KEY;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* `ForwardRef.factory` is typed to return the broader `Token<T>` because the
|
|
872
|
+
* primitive is shared with provider injection. In module-imports position the
|
|
873
|
+
* runtime contract narrows: the factory must yield a module class or a
|
|
874
|
+
* `DynamicModule`. This helper validates the contract AND narrows the type
|
|
875
|
+
* without a structural cast.
|
|
876
|
+
*/
|
|
877
|
+
function unwrapModuleForwardRef(ref) {
|
|
878
|
+
const result = ref.factory();
|
|
879
|
+
if (typeof result === "function") return result;
|
|
880
|
+
if (isDynamicModule(result)) return result;
|
|
881
|
+
throw new Error(`forwardRef in module imports must resolve to a module class or DynamicModule; got ${typeof result === "object" ? "a non-module object" : typeof result}.`);
|
|
882
|
+
}
|
|
883
|
+
var ModuleLoader = class {
|
|
884
|
+
container;
|
|
885
|
+
router;
|
|
886
|
+
processedModules = /* @__PURE__ */ new Map();
|
|
887
|
+
processingStack = /* @__PURE__ */ new Set();
|
|
888
|
+
collectedControllers = /* @__PURE__ */ new Set();
|
|
889
|
+
registeredProviders = [];
|
|
890
|
+
moduleExportsCache = /* @__PURE__ */ new Map();
|
|
891
|
+
globalExports = /* @__PURE__ */ new Set();
|
|
892
|
+
consumerMiddlewareDefinitions = [];
|
|
893
|
+
appProviderCounter = 0;
|
|
894
|
+
appProviderTokens = /* @__PURE__ */ new Map([
|
|
895
|
+
[APP_GUARD, []],
|
|
896
|
+
[APP_PIPE, []],
|
|
897
|
+
[APP_INTERCEPTOR, []],
|
|
898
|
+
[APP_FILTER, []],
|
|
899
|
+
[APP_MIDDLEWARE, []]
|
|
900
|
+
]);
|
|
901
|
+
moduleIdByClassKey = /* @__PURE__ */ new Map();
|
|
902
|
+
seenModuleIds = /* @__PURE__ */ new Set();
|
|
903
|
+
lazyModuleIds = /* @__PURE__ */ new Set();
|
|
904
|
+
lazyGroups = /* @__PURE__ */ new Map();
|
|
905
|
+
constructor(container, router) {
|
|
906
|
+
this.container = container;
|
|
907
|
+
this.router = router;
|
|
908
|
+
}
|
|
909
|
+
load(rootModule) {
|
|
910
|
+
this.processModule(rootModule);
|
|
911
|
+
for (const controller of this.collectedControllers) this.router.registerController(controller);
|
|
912
|
+
const lazyManager = new LazyModuleManager(this.container);
|
|
913
|
+
for (const group of this.getLazyGroups()) lazyManager.registerGroup(group);
|
|
914
|
+
this.container.setLazyHook(lazyManager);
|
|
915
|
+
this.container.register({
|
|
916
|
+
provide: LazyModuleManager,
|
|
917
|
+
useValue: lazyManager
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
getModuleId(moduleClass, key) {
|
|
921
|
+
let perClass = this.moduleIdByClassKey.get(moduleClass);
|
|
922
|
+
if (perClass) {
|
|
923
|
+
const cached = perClass.get(key);
|
|
924
|
+
if (cached) return cached;
|
|
925
|
+
} else {
|
|
926
|
+
perClass = /* @__PURE__ */ new Map();
|
|
927
|
+
this.moduleIdByClassKey.set(moduleClass, perClass);
|
|
928
|
+
}
|
|
929
|
+
const baseName = moduleClass.name || "AnonModule";
|
|
930
|
+
let id = `${baseName}#${key}`;
|
|
931
|
+
let counter = 0;
|
|
932
|
+
while (this.seenModuleIds.has(id)) id = `${baseName}#${key}~${++counter}`;
|
|
933
|
+
this.seenModuleIds.add(id);
|
|
934
|
+
perClass.set(key, id);
|
|
935
|
+
return id;
|
|
936
|
+
}
|
|
937
|
+
isProcessed(moduleClass, key) {
|
|
938
|
+
return this.processedModules.get(moduleClass)?.has(key) ?? false;
|
|
939
|
+
}
|
|
940
|
+
markProcessed(moduleClass, key) {
|
|
941
|
+
let keys = this.processedModules.get(moduleClass);
|
|
942
|
+
if (!keys) {
|
|
943
|
+
keys = /* @__PURE__ */ new Set();
|
|
944
|
+
this.processedModules.set(moduleClass, keys);
|
|
945
|
+
}
|
|
946
|
+
keys.add(key);
|
|
947
|
+
}
|
|
948
|
+
getCachedExports(moduleClass, key) {
|
|
949
|
+
return this.moduleExportsCache.get(moduleClass)?.get(key);
|
|
950
|
+
}
|
|
951
|
+
cacheExports(moduleClass, key, exports) {
|
|
952
|
+
let perClass = this.moduleExportsCache.get(moduleClass);
|
|
953
|
+
if (!perClass) {
|
|
954
|
+
perClass = /* @__PURE__ */ new Map();
|
|
955
|
+
this.moduleExportsCache.set(moduleClass, perClass);
|
|
956
|
+
}
|
|
957
|
+
perClass.set(key, exports);
|
|
958
|
+
}
|
|
959
|
+
processModule(moduleClassOrDynamic) {
|
|
960
|
+
let moduleClass;
|
|
961
|
+
let extraImports = [];
|
|
962
|
+
let extraControllers = [];
|
|
963
|
+
let extraProviders = [];
|
|
964
|
+
let extraExports = [];
|
|
965
|
+
let key = DEFAULT_KEY;
|
|
966
|
+
if (isDynamicModule(moduleClassOrDynamic)) {
|
|
967
|
+
moduleClass = moduleClassOrDynamic.module;
|
|
968
|
+
extraImports = moduleClassOrDynamic.imports ?? [];
|
|
969
|
+
extraControllers = moduleClassOrDynamic.controllers ?? [];
|
|
970
|
+
extraProviders = moduleClassOrDynamic.providers ?? [];
|
|
971
|
+
extraExports = moduleClassOrDynamic.exports ?? [];
|
|
972
|
+
key = moduleClassOrDynamic.key ?? DEFAULT_KEY;
|
|
973
|
+
} else moduleClass = moduleClassOrDynamic;
|
|
974
|
+
if (this.isProcessed(moduleClass, key)) {
|
|
975
|
+
for (const controller of extraControllers) this.collectedControllers.add(controller);
|
|
976
|
+
return this.getCachedExports(moduleClass, key) ?? /* @__PURE__ */ new Set();
|
|
977
|
+
}
|
|
978
|
+
const stackKey = `${moduleClass.name}#${key}`;
|
|
979
|
+
if (this.processingStack.has(stackKey)) {
|
|
980
|
+
const chain = [...this.processingStack, stackKey].join(" -> ");
|
|
981
|
+
throw new Error(`Circular module dependency detected: ${chain}`);
|
|
982
|
+
}
|
|
983
|
+
if (!isModule(moduleClass)) if (isDynamicModule(moduleClassOrDynamic)) MetadataRegistry.setModuleOptions(moduleClass, {});
|
|
984
|
+
else throw new Error(`${moduleClass.name} is not a module. Add @Module() decorator to the class.`);
|
|
985
|
+
const metadata = getModuleMetadata(moduleClass);
|
|
986
|
+
if (!metadata) throw new Error(`Failed to get module metadata for ${moduleClass.name}`);
|
|
987
|
+
this.processingStack.add(stackKey);
|
|
988
|
+
const moduleId = this.getModuleId(moduleClass, key);
|
|
989
|
+
try {
|
|
990
|
+
const importedProviders = new Set(this.globalExports);
|
|
991
|
+
const importedModuleIds = /* @__PURE__ */ new Set();
|
|
992
|
+
const keysByClassInImports = /* @__PURE__ */ new Map();
|
|
993
|
+
const allImports = [...metadata.imports, ...extraImports];
|
|
994
|
+
for (const entry of allImports) {
|
|
995
|
+
const importedModule = entry instanceof ForwardRef ? unwrapModuleForwardRef(entry) : entry;
|
|
996
|
+
const importedModuleClass = isDynamicModule(importedModule) ? importedModule.module : importedModule;
|
|
997
|
+
const importedKey = keyOfImport(importedModule);
|
|
998
|
+
let keys = keysByClassInImports.get(importedModuleClass);
|
|
999
|
+
if (!keys) {
|
|
1000
|
+
keys = /* @__PURE__ */ new Set();
|
|
1001
|
+
keysByClassInImports.set(importedModuleClass, keys);
|
|
1002
|
+
}
|
|
1003
|
+
keys.add(importedKey);
|
|
1004
|
+
const importedId = this.getModuleId(importedModuleClass, importedKey);
|
|
1005
|
+
importedModuleIds.add(importedId);
|
|
1006
|
+
const importedStackKey = `${importedModuleClass.name}#${importedKey}`;
|
|
1007
|
+
if (entry instanceof ForwardRef && this.processingStack.has(importedStackKey)) continue;
|
|
1008
|
+
const exportedTokens = this.processModule(importedModule);
|
|
1009
|
+
for (const token of exportedTokens) importedProviders.add(token);
|
|
1010
|
+
}
|
|
1011
|
+
this.warnOnMixedDefaultAndKeyed(moduleClass.name, keysByClassInImports);
|
|
1012
|
+
const allProviders = [...metadata.providers, ...extraProviders];
|
|
1013
|
+
const allControllers = [...metadata.controllers, ...extraControllers];
|
|
1014
|
+
const allExports = [...metadata.exports, ...extraExports];
|
|
1015
|
+
const localProviders = /* @__PURE__ */ new Set();
|
|
1016
|
+
for (const provider of allProviders) {
|
|
1017
|
+
const tk = tokenOfProvider(provider);
|
|
1018
|
+
if (tk !== void 0) localProviders.add(tk);
|
|
1019
|
+
}
|
|
1020
|
+
for (const controller of allControllers) localProviders.add(controller);
|
|
1021
|
+
localProviders.add(moduleClass);
|
|
1022
|
+
const isGlobal = metadata.isGlobal || isDynamicModule(moduleClassOrDynamic) && moduleClassOrDynamic.global === true;
|
|
1023
|
+
const isLazy = metadata.lazy || isDynamicModule(moduleClassOrDynamic) && moduleClassOrDynamic.lazy === true;
|
|
1024
|
+
this.container.registerScope({
|
|
1025
|
+
moduleId,
|
|
1026
|
+
localProviders,
|
|
1027
|
+
importedModules: importedModuleIds,
|
|
1028
|
+
exportedTokens: new Set(allExports),
|
|
1029
|
+
isGlobal,
|
|
1030
|
+
lazy: isLazy
|
|
1031
|
+
});
|
|
1032
|
+
const lazyTokens = [];
|
|
1033
|
+
let hasEntrypointContributor = false;
|
|
1034
|
+
for (const provider of allProviders) {
|
|
1035
|
+
const registered = this.registerProvider(provider, moduleId);
|
|
1036
|
+
if (isLazy && registered !== void 0) {
|
|
1037
|
+
lazyTokens.push(registered);
|
|
1038
|
+
hasEntrypointContributor ||= declaresEntrypointContributor(provider);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
for (const controller of allControllers) {
|
|
1042
|
+
this.container.register(controller, moduleId);
|
|
1043
|
+
this.collectedControllers.add(controller);
|
|
1044
|
+
if (isLazy) lazyTokens.push(controller);
|
|
1045
|
+
}
|
|
1046
|
+
if (isLazy) {
|
|
1047
|
+
this.lazyModuleIds.add(moduleId);
|
|
1048
|
+
this.lazyGroups.set(moduleId, {
|
|
1049
|
+
moduleId,
|
|
1050
|
+
tokens: lazyTokens,
|
|
1051
|
+
hasEntrypointContributor
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
for (const controller of allControllers) MetadataRegistry.propagateControllerComponents(moduleClass, controller);
|
|
1055
|
+
this.markProcessed(moduleClass, key);
|
|
1056
|
+
const exports = this.buildExportSet(allExports, allProviders, importedProviders);
|
|
1057
|
+
this.cacheExports(moduleClass, key, exports);
|
|
1058
|
+
if (isGlobal) for (const token of exports) this.globalExports.add(token);
|
|
1059
|
+
if (implementsNestModule(moduleClass)) {
|
|
1060
|
+
if (!this.container.hasInScope(moduleClass, moduleId)) this.container.register(moduleClass, moduleId);
|
|
1061
|
+
const instance = this.container.resolve(moduleClass, moduleId);
|
|
1062
|
+
const builder = new MiddlewareBuilder();
|
|
1063
|
+
instance.configure(builder);
|
|
1064
|
+
this.consumerMiddlewareDefinitions.push(...builder.getDefinitions());
|
|
1065
|
+
}
|
|
1066
|
+
return exports;
|
|
1067
|
+
} finally {
|
|
1068
|
+
this.processingStack.delete(stackKey);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
warnOnMixedDefaultAndKeyed(parentName, keysByClass) {
|
|
1072
|
+
const mode = this.container.getDiagnostics();
|
|
1073
|
+
if (mode === "silent") return;
|
|
1074
|
+
for (const [cls, keys] of keysByClass) {
|
|
1075
|
+
if (keys.size < 2) continue;
|
|
1076
|
+
if (!keys.has(DEFAULT_KEY)) continue;
|
|
1077
|
+
const message = `[vela] ${cls.name} imported in both bare and keyed form in '${parentName}'. These resolve to distinct module instances; consumers asking for an exported token will hit MultipleProvidersFoundError. Use one form consistently.`;
|
|
1078
|
+
if (mode === "throw") throw new Error(message);
|
|
1079
|
+
console.warn(message);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
/** Registers the provider and returns the token it was registered under. */
|
|
1083
|
+
registerProvider(provider, moduleId) {
|
|
1084
|
+
if (typeof provider === "function") {
|
|
1085
|
+
this.container.register(provider, moduleId);
|
|
1086
|
+
this.registeredProviders.push(provider);
|
|
1087
|
+
return provider;
|
|
1088
|
+
}
|
|
1089
|
+
const token = provider.provide;
|
|
1090
|
+
if (!token) {
|
|
1091
|
+
this.container.register(provider, moduleId);
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
if (this.isAppToken(token)) {
|
|
1095
|
+
const syntheticToken = new InjectionToken(`${token.toString()}:${this.appProviderCounter++}`);
|
|
1096
|
+
this.container.register({
|
|
1097
|
+
...provider,
|
|
1098
|
+
provide: syntheticToken
|
|
1099
|
+
}, moduleId);
|
|
1100
|
+
this.registeredProviders.push(syntheticToken);
|
|
1101
|
+
getOrCreateArray(this.appProviderTokens, token).push(syntheticToken);
|
|
1102
|
+
return syntheticToken;
|
|
1103
|
+
}
|
|
1104
|
+
this.container.register(provider, moduleId);
|
|
1105
|
+
this.registeredProviders.push(token);
|
|
1106
|
+
return token;
|
|
1107
|
+
}
|
|
1108
|
+
isAppToken(token) {
|
|
1109
|
+
return APP_TOKENS.has(token);
|
|
1110
|
+
}
|
|
1111
|
+
buildExportSet(exports, providers, importedProviders) {
|
|
1112
|
+
const exportSet = /* @__PURE__ */ new Set();
|
|
1113
|
+
const providerTokens = /* @__PURE__ */ new Set();
|
|
1114
|
+
for (const p of providers) {
|
|
1115
|
+
const token = tokenOfProvider(p);
|
|
1116
|
+
if (token !== void 0) providerTokens.add(token);
|
|
1117
|
+
}
|
|
1118
|
+
for (const exported of exports) {
|
|
1119
|
+
const isLocalProvider = providerTokens.has(exported);
|
|
1120
|
+
const isImportedProvider = importedProviders.has(exported);
|
|
1121
|
+
if (!isLocalProvider && !isImportedProvider) {
|
|
1122
|
+
const name = typeof exported === "function" ? exported.name : String(exported);
|
|
1123
|
+
console.warn(`Warning: Exporting '${name}' which is neither a local provider nor imported from another module.`);
|
|
1124
|
+
}
|
|
1125
|
+
exportSet.add(exported);
|
|
1126
|
+
}
|
|
1127
|
+
return exportSet;
|
|
1128
|
+
}
|
|
1129
|
+
getControllers() {
|
|
1130
|
+
return [...this.collectedControllers];
|
|
1131
|
+
}
|
|
1132
|
+
getRegisteredProviders() {
|
|
1133
|
+
return [...this.registeredProviders];
|
|
1134
|
+
}
|
|
1135
|
+
getAppProviderTokens(token) {
|
|
1136
|
+
return [...this.appProviderTokens.get(token) ?? []];
|
|
1137
|
+
}
|
|
1138
|
+
getConsumerMiddlewareDefinitions() {
|
|
1139
|
+
return [...this.consumerMiddlewareDefinitions];
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Every lazy module instance recorded during load. Handed to the
|
|
1143
|
+
* LazyModuleManager at bootstrap; empty when no module opted in.
|
|
1144
|
+
*/
|
|
1145
|
+
getLazyGroups() {
|
|
1146
|
+
return [...this.lazyGroups.values()];
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* A token is deferred iff EVERY module bucket holding it belongs to a lazy
|
|
1150
|
+
* module instance — a token also registered by a non-lazy module stays on
|
|
1151
|
+
* the eager pass (and resolving it there claims the lazy sibling, which is
|
|
1152
|
+
* the "any use = init" semantic, not a bug).
|
|
1153
|
+
*/
|
|
1154
|
+
isLazyOnlyToken(token) {
|
|
1155
|
+
if (this.lazyModuleIds.size === 0) return false;
|
|
1156
|
+
const owners = this.container.getOwnerModuleIds(token);
|
|
1157
|
+
if (owners.length === 0) return false;
|
|
1158
|
+
return owners.every((id) => this.lazyModuleIds.has(id));
|
|
1159
|
+
}
|
|
1160
|
+
async resolveAllInstances() {
|
|
1161
|
+
const instanceSet = /* @__PURE__ */ new Set();
|
|
1162
|
+
for (const token of this.registeredProviders) try {
|
|
1163
|
+
if (this.container.getProviderScope(token) === Scope.REQUEST) continue;
|
|
1164
|
+
if (this.isLazyOnlyToken(token)) continue;
|
|
1165
|
+
const instance = await this.container.resolveAsync(token);
|
|
1166
|
+
instanceSet.add(instance);
|
|
1167
|
+
} catch (err) {
|
|
1168
|
+
if (err instanceof ModuleVisibilityError || err instanceof MultipleProvidersFoundError) throw err;
|
|
1169
|
+
this.routeError(err, `resolve provider`);
|
|
1170
|
+
}
|
|
1171
|
+
for (const controller of this.collectedControllers) try {
|
|
1172
|
+
if (this.container.getProviderScope(controller) === Scope.REQUEST) continue;
|
|
1173
|
+
if (this.isLazyOnlyToken(controller)) continue;
|
|
1174
|
+
const instance = await this.container.resolveAsync(controller);
|
|
1175
|
+
instanceSet.add(instance);
|
|
1176
|
+
} catch (err) {
|
|
1177
|
+
if (err instanceof ModuleVisibilityError || err instanceof MultipleProvidersFoundError) throw err;
|
|
1178
|
+
this.routeError(err, `resolve controller ${controller.name}`);
|
|
1179
|
+
}
|
|
1180
|
+
return [...instanceSet];
|
|
1181
|
+
}
|
|
1182
|
+
routeError(err, context) {
|
|
1183
|
+
const mode = this.container.getDiagnostics();
|
|
1184
|
+
if (mode === "silent") return;
|
|
1185
|
+
if (mode === "throw") throw err instanceof Error ? err : new Error(String(err));
|
|
1186
|
+
console.warn(`[vela] ${context} failed:`, err);
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
//#endregion
|
|
1190
|
+
//#region src/pipeline/app-providers.ts
|
|
1191
|
+
const SLOTS = [
|
|
1192
|
+
{
|
|
1193
|
+
token: APP_GUARD,
|
|
1194
|
+
bind: (rm) => rm.useGlobalGuardTokens.bind(rm)
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
token: APP_PIPE,
|
|
1198
|
+
bind: (rm) => rm.useGlobalPipeTokens.bind(rm)
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
token: APP_INTERCEPTOR,
|
|
1202
|
+
bind: (rm) => rm.useGlobalInterceptorTokens.bind(rm)
|
|
1203
|
+
},
|
|
1204
|
+
{
|
|
1205
|
+
token: APP_FILTER,
|
|
1206
|
+
bind: (rm) => rm.useGlobalFilterTokens.bind(rm)
|
|
1207
|
+
},
|
|
1208
|
+
{
|
|
1209
|
+
token: APP_MIDDLEWARE,
|
|
1210
|
+
bind: (rm) => rm.useGlobalMiddlewareTokens.bind(rm)
|
|
1211
|
+
}
|
|
1212
|
+
];
|
|
1213
|
+
/**
|
|
1214
|
+
* Bind every APP_* provider registered in the container as a global
|
|
1215
|
+
* component on the RouteManager. The single source of truth for app-level
|
|
1216
|
+
* pipeline configuration — used by both VelaFactory.create and
|
|
1217
|
+
* @velajs/testing's TestingModuleBuilder.compile.
|
|
1218
|
+
*/
|
|
1219
|
+
function bindAppProviders(routeManager, container, loader) {
|
|
1220
|
+
for (const { token, bind } of SLOTS) {
|
|
1221
|
+
const collected = loader.getAppProviderTokens(token);
|
|
1222
|
+
if (collected.length > 0) bind(routeManager)(...collected);
|
|
1223
|
+
else if (container.has(token)) bind(routeManager)(token);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
//#endregion
|
|
1227
|
+
//#region src/factory/bootstrap.ts
|
|
1228
|
+
/**
|
|
1229
|
+
* Wire the DI graph for `rootModule` and prepare the route manager — without
|
|
1230
|
+
* running lifecycle hooks or building the Hono app. The single primitive
|
|
1231
|
+
* shared by `VelaFactory.create` (HTTP), `@velajs/testing` (test), and any
|
|
1232
|
+
* non-HTTP consumer (CLI tools, custom runtimes).
|
|
1233
|
+
*
|
|
1234
|
+
* Framework-internal tokens (`Container`, `ModuleRef`, `APP_*`) are marked
|
|
1235
|
+
* global so they are resolvable from any module.
|
|
1236
|
+
*/
|
|
1237
|
+
async function bootstrap(rootModule, options = {}) {
|
|
1238
|
+
const container = new Container({ diagnostics: options.diagnostics });
|
|
1239
|
+
container.register({
|
|
1240
|
+
provide: Container,
|
|
1241
|
+
useValue: container
|
|
1242
|
+
});
|
|
1243
|
+
container.markGlobalToken(Container);
|
|
1244
|
+
container.register({
|
|
1245
|
+
provide: ModuleRef,
|
|
1246
|
+
useFactory: (c) => new ModuleRef(c),
|
|
1247
|
+
inject: [Container]
|
|
1248
|
+
});
|
|
1249
|
+
container.markGlobalToken(ModuleRef);
|
|
1250
|
+
container.register({
|
|
1251
|
+
provide: DiscoveryService,
|
|
1252
|
+
useFactory: (c) => new DiscoveryService(c),
|
|
1253
|
+
inject: [Container]
|
|
1254
|
+
});
|
|
1255
|
+
container.markGlobalToken(DiscoveryService);
|
|
1256
|
+
for (const t of [
|
|
1257
|
+
APP_GUARD,
|
|
1258
|
+
APP_PIPE,
|
|
1259
|
+
APP_INTERCEPTOR,
|
|
1260
|
+
APP_FILTER,
|
|
1261
|
+
APP_MIDDLEWARE,
|
|
1262
|
+
APP_EXCEPTION_HANDLER,
|
|
1263
|
+
ERROR_CATALOG
|
|
1264
|
+
]) container.markGlobalToken(t);
|
|
1265
|
+
container.register({
|
|
1266
|
+
provide: REQUEST_CONTEXT,
|
|
1267
|
+
scope: Scope.REQUEST,
|
|
1268
|
+
useFactory: () => {
|
|
1269
|
+
throw new Error("REQUEST_CONTEXT can only be resolved inside a request — it is seeded by RouteManager when the request enters the pipeline.");
|
|
1270
|
+
}
|
|
1271
|
+
});
|
|
1272
|
+
container.markGlobalToken(REQUEST_CONTEXT);
|
|
1273
|
+
const routeManager = new RouteManager(container, options);
|
|
1274
|
+
container.register({
|
|
1275
|
+
provide: RouteManager,
|
|
1276
|
+
useValue: routeManager
|
|
1277
|
+
});
|
|
1278
|
+
container.markGlobalToken(RouteManager);
|
|
1279
|
+
container.register(UrlGeneratorService);
|
|
1280
|
+
container.markGlobalToken(UrlGeneratorService);
|
|
1281
|
+
container.register(SignedUrlGuard);
|
|
1282
|
+
container.markGlobalToken(SignedUrlGuard);
|
|
1283
|
+
const loader = new ModuleLoader(container, routeManager);
|
|
1284
|
+
loader.load(rootModule);
|
|
1285
|
+
bindAppProviders(routeManager, container, loader);
|
|
1286
|
+
routeManager.registerConsumerMiddleware(loader.getConsumerMiddlewareDefinitions());
|
|
1287
|
+
if (options.globalPrefix) routeManager.setGlobalPrefix(options.globalPrefix);
|
|
1288
|
+
for (const handler of options.middleware ?? []) {
|
|
1289
|
+
const mw = { use: handler };
|
|
1290
|
+
routeManager.useGlobalMiddleware(mw);
|
|
1291
|
+
}
|
|
1292
|
+
container.computeEffectiveScopes();
|
|
1293
|
+
return {
|
|
1294
|
+
container,
|
|
1295
|
+
routeManager,
|
|
1296
|
+
loader
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
//#endregion
|
|
1300
|
+
//#region src/plugin/plugin.ts
|
|
1301
|
+
/**
|
|
1302
|
+
* Freeze and validate a plugin manifest. Returns the same object so it can
|
|
1303
|
+
* be used in `composePlugins([definePlugin(...), ...])`.
|
|
1304
|
+
*/
|
|
1305
|
+
function definePlugin(plugin) {
|
|
1306
|
+
if (!plugin.id) throw new Error("Plugin requires an id");
|
|
1307
|
+
if (!plugin.version) throw new Error("Plugin requires a version");
|
|
1308
|
+
if (!plugin.module) throw new Error("Plugin requires a module");
|
|
1309
|
+
return Object.freeze({ ...plugin });
|
|
1310
|
+
}
|
|
1311
|
+
var PluginRegistry = class {
|
|
1312
|
+
byId;
|
|
1313
|
+
constructor(plugins) {
|
|
1314
|
+
this.byId = /* @__PURE__ */ new Map();
|
|
1315
|
+
for (const p of plugins) {
|
|
1316
|
+
if (this.byId.has(p.id)) throw new Error(`Duplicate plugin id: '${p.id}'`);
|
|
1317
|
+
this.byId.set(p.id, p);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
list() {
|
|
1321
|
+
return [...this.byId.values()];
|
|
1322
|
+
}
|
|
1323
|
+
get(id) {
|
|
1324
|
+
return this.byId.get(id);
|
|
1325
|
+
}
|
|
1326
|
+
dependents(id) {
|
|
1327
|
+
return this.list().filter((p) => p.dependsOn?.includes(id) ?? false);
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
const PLUGIN_REGISTRY_TOKEN = new InjectionToken("PLUGIN_REGISTRY");
|
|
1331
|
+
let PluginRootModule = class PluginRootModule {};
|
|
1332
|
+
PluginRootModule = __decorate([Module({})], PluginRootModule);
|
|
1333
|
+
/**
|
|
1334
|
+
* Topologically sort plugins so each plugin's dependencies appear first.
|
|
1335
|
+
* Throws on missing dependencies and cycles.
|
|
1336
|
+
*/
|
|
1337
|
+
function topologicalSort(plugins) {
|
|
1338
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1339
|
+
for (const p of plugins) {
|
|
1340
|
+
if (byId.has(p.id)) throw new Error(`Duplicate plugin id: '${p.id}'`);
|
|
1341
|
+
byId.set(p.id, p);
|
|
1342
|
+
}
|
|
1343
|
+
const result = [];
|
|
1344
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
1345
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1346
|
+
const visit = (p, path) => {
|
|
1347
|
+
if (visited.has(p.id)) return;
|
|
1348
|
+
if (visiting.has(p.id)) {
|
|
1349
|
+
const cycle = [...path, p.id].join(" -> ");
|
|
1350
|
+
throw new Error(`Plugin cycle detected: ${cycle}`);
|
|
1351
|
+
}
|
|
1352
|
+
visiting.add(p.id);
|
|
1353
|
+
for (const depId of p.dependsOn ?? []) {
|
|
1354
|
+
const dep = byId.get(depId);
|
|
1355
|
+
if (!dep) throw new Error(`Plugin '${p.id}' depends on missing plugin '${depId}'`);
|
|
1356
|
+
visit(dep, [...path, p.id]);
|
|
1357
|
+
}
|
|
1358
|
+
visiting.delete(p.id);
|
|
1359
|
+
visited.add(p.id);
|
|
1360
|
+
result.push(p);
|
|
1361
|
+
};
|
|
1362
|
+
for (const p of plugins) visit(p, []);
|
|
1363
|
+
return result;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Compose a list of plugins into a single dynamic module that imports each
|
|
1367
|
+
* plugin's module in dependency order, registers a `PluginRegistry`, and
|
|
1368
|
+
* exposes it globally so any plugin can introspect peers.
|
|
1369
|
+
*/
|
|
1370
|
+
function composePlugins(plugins) {
|
|
1371
|
+
const sorted = topologicalSort(plugins);
|
|
1372
|
+
const registry = new PluginRegistry(sorted);
|
|
1373
|
+
return {
|
|
1374
|
+
module: PluginRootModule,
|
|
1375
|
+
imports: sorted.map((p) => p.module),
|
|
1376
|
+
providers: [{
|
|
1377
|
+
provide: PLUGIN_REGISTRY_TOKEN,
|
|
1378
|
+
useValue: registry
|
|
1379
|
+
}],
|
|
1380
|
+
exports: [PLUGIN_REGISTRY_TOKEN],
|
|
1381
|
+
global: true
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
//#endregion
|
|
1385
|
+
export { EntrypointRegistry as _, definePlugin as a, contributesEntrypoints as b, ModuleLoader as c, UrlGeneratorService as d, URL_SIGNING_SECRET as f, VelaApplication as g, ModuleRef as h, composePlugins as i, SignedUrl as l, CONFIG_OPTIONS as m, PluginRegistry as n, bootstrap as o, CONFIG_ENV as p, PluginRootModule as r, bindAppProviders as s, PLUGIN_REGISTRY_TOKEN as t, SignedUrlGuard as u, getEntrypointKinds as v, registerEntrypointKind as y };
|
|
1386
|
+
|
|
1387
|
+
//# sourceMappingURL=plugin-ByBlVOve.js.map
|