stratal 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{base-email.provider-CfQCA08m.mjs → base-email.provider-BWZHIjt8.mjs} +1 -1
- package/dist/{base-email.provider-CfQCA08m.mjs.map → base-email.provider-BWZHIjt8.mjs.map} +1 -1
- package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
- package/dist/bin/quarry.mjs +46 -109
- package/dist/bin/quarry.mjs.map +1 -1
- package/dist/cache/index.d.mts +6 -46
- package/dist/cache/index.d.mts.map +1 -1
- package/dist/cache/index.mjs +22 -67
- package/dist/cache/index.mjs.map +1 -1
- package/dist/{cache.service-DsnKuNyO.d.mts → cache.service-e34gV6tz.d.mts} +8 -8
- package/dist/{cache.service-DsnKuNyO.d.mts.map → cache.service-e34gV6tz.d.mts.map} +1 -1
- package/dist/{cache.tokens-B7Rw1C9Q.mjs → cache.tokens-ovi_c52J.mjs} +1 -1
- package/dist/{cache.tokens-B7Rw1C9Q.mjs.map → cache.tokens-ovi_c52J.mjs.map} +1 -1
- package/dist/{colors-DJaRDXoS.mjs → colors-axmupKdp.mjs} +1 -1
- package/dist/{colors-DJaRDXoS.mjs.map → colors-axmupKdp.mjs.map} +1 -1
- package/dist/{command-BgSlsS4M.mjs → command-BU4ApTo5.mjs} +2 -3
- package/dist/command-BU4ApTo5.mjs.map +1 -0
- package/dist/{command-Bu-PjJrX.d.mts → command-wXfvHbBZ.d.mts} +3 -2
- package/dist/command-wXfvHbBZ.d.mts.map +1 -0
- package/dist/config/index.d.mts +24 -11
- package/dist/config/index.d.mts.map +1 -1
- package/dist/config/index.mjs +33 -57
- package/dist/config/index.mjs.map +1 -1
- package/dist/{consumer-registry-B7yUNh0q.d.mts → consumer-registry-DHQtypr1.d.mts} +1 -1
- package/dist/{consumer-registry-B7yUNh0q.d.mts.map → consumer-registry-DHQtypr1.d.mts.map} +1 -1
- package/dist/container-storage-GpNNz79X.mjs +52 -0
- package/dist/container-storage-GpNNz79X.mjs.map +1 -0
- package/dist/{controller.decorator-DQzenvSN.mjs → controller.decorator-DIUazNU7.mjs} +8 -8
- package/dist/controller.decorator-DIUazNU7.mjs.map +1 -0
- package/dist/cron/index.d.mts +26 -5
- package/dist/cron/index.d.mts.map +1 -1
- package/dist/cron/index.mjs +1 -1
- package/dist/{cron-manager-7Symz_TE.mjs → cron-manager-9bpN9bu4.mjs} +42 -16
- package/dist/cron-manager-9bpN9bu4.mjs.map +1 -0
- package/dist/{cron-manager-BEsH1mjW.d.mts → cron-manager-CSTIBPcM.d.mts} +6 -13
- package/dist/cron-manager-CSTIBPcM.d.mts.map +1 -0
- package/dist/decorate-HgTKAYK8.mjs +16 -0
- package/dist/deep-merge-C8NgcXw4.mjs +18 -0
- package/dist/deep-merge-C8NgcXw4.mjs.map +1 -0
- package/dist/di/index.d.mts +2 -2
- package/dist/di/index.mjs +4 -3
- package/dist/di-BO1QIb5H.mjs +415 -0
- package/dist/di-BO1QIb5H.mjs.map +1 -0
- package/dist/email/index.d.mts +14 -89
- package/dist/email/index.d.mts.map +1 -1
- package/dist/email/index.mjs +30 -125
- package/dist/email/index.mjs.map +1 -1
- package/dist/en-BPP6h6y5.mjs +202 -0
- package/dist/en-BPP6h6y5.mjs.map +1 -0
- package/dist/{env-D1rcZ8_r.d.mts → env-DKSbuBi5.d.mts} +1 -1
- package/dist/env-DKSbuBi5.d.mts.map +1 -0
- package/dist/errors/index.d.mts +2 -2
- package/dist/errors/index.mjs +4 -2
- package/dist/errors-BBZTnjdq.mjs +333 -0
- package/dist/errors-BBZTnjdq.mjs.map +1 -0
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.d.mts.map +1 -1
- package/dist/events/index.mjs +1 -1
- package/dist/{events-COKixqnG.mjs → events-D1KdDaiP.mjs} +13 -11
- package/dist/events-D1KdDaiP.mjs.map +1 -0
- package/dist/exception-context-B4kM-M53.mjs +429 -0
- package/dist/exception-context-B4kM-M53.mjs.map +1 -0
- package/dist/{gateway-context-CdJjpUCW.mjs → gateway-context-CFe6a9gz.mjs} +20 -31
- package/dist/gateway-context-CFe6a9gz.mjs.map +1 -0
- package/dist/guards/index.d.mts +3 -3
- package/dist/guards/index.d.mts.map +1 -1
- package/dist/guards/index.mjs +1 -1
- package/dist/{guards-DUk_Kzst.mjs → guards-Ced-uNIF.mjs} +7 -5
- package/dist/guards-Ced-uNIF.mjs.map +1 -0
- package/dist/{http-method.decorator-DXwxAfb_.mjs → http-method.decorator-CdjKFJZZ.mjs} +7 -6
- package/dist/http-method.decorator-CdjKFJZZ.mjs.map +1 -0
- package/dist/i18n/index.d.mts +238 -3
- package/dist/i18n/index.d.mts.map +1 -0
- package/dist/i18n/index.mjs +39 -3
- package/dist/i18n/index.mjs.map +1 -0
- package/dist/i18n/messages/en/index.d.mts +2 -2
- package/dist/i18n/messages/en/index.mjs +2 -2
- package/dist/i18n/utils/index.d.mts +4 -26
- package/dist/i18n/utils/index.d.mts.map +1 -1
- package/dist/i18n/utils/index.mjs +2 -2
- package/dist/i18n/validation/index.d.mts +3 -2
- package/dist/i18n/validation/index.mjs +4 -2
- package/dist/i18n.module-BlXrtAlV.mjs +219 -0
- package/dist/i18n.module-BlXrtAlV.mjs.map +1 -0
- package/dist/i18n.tokens-hwRpmjRq.mjs +19 -0
- package/dist/i18n.tokens-hwRpmjRq.mjs.map +1 -0
- package/dist/{index-7-hU3GTV.d.mts → index-B4UBK-2T.d.mts} +1 -1
- package/dist/{index-7-hU3GTV.d.mts.map → index-B4UBK-2T.d.mts.map} +1 -1
- package/dist/index-BtlE9RuO.d.mts +124 -0
- package/dist/index-BtlE9RuO.d.mts.map +1 -0
- package/dist/{index-CjaQ6_tZ.d.mts → index-CW1YHSft.d.mts} +71 -167
- package/dist/index-CW1YHSft.d.mts.map +1 -0
- package/dist/{index-D0US0X14.d.mts → index-DEncMcC6.d.mts} +559 -2239
- package/dist/index-DEncMcC6.d.mts.map +1 -0
- package/dist/index-Dj5IMwtr.d.mts +44 -0
- package/dist/index-Dj5IMwtr.d.mts.map +1 -0
- package/dist/{index-C1KvMncZ.d.mts → index-KMgSCSM7.d.mts} +3 -108
- package/dist/index-KMgSCSM7.d.mts.map +1 -0
- package/dist/index.d.mts +5 -43
- package/dist/index.mjs +1 -1
- package/dist/{is-command-C6a7WTPw.mjs → is-command-CX5rAfZW.mjs} +2 -2
- package/dist/{is-command-C6a7WTPw.mjs.map → is-command-CX5rAfZW.mjs.map} +1 -1
- package/dist/{is-seeder-CebjZCDn.mjs → is-seeder-CYCtELlm.mjs} +1 -1
- package/dist/{is-seeder-CebjZCDn.mjs.map → is-seeder-CYCtELlm.mjs.map} +1 -1
- package/dist/logger/index.d.mts +2 -2
- package/dist/logger/index.mjs +170 -2
- package/dist/logger/index.mjs.map +1 -0
- package/dist/macroable/index.d.mts +1 -1
- package/dist/macroable/index.mjs +1 -1
- package/dist/{macroable-BmufBshB.mjs → macroable-DzlfzT50.mjs} +1 -1
- package/dist/{macroable-BmufBshB.mjs.map → macroable-DzlfzT50.mjs.map} +1 -1
- package/dist/metadata-BVkc4aUu.mjs +39 -0
- package/dist/metadata-BVkc4aUu.mjs.map +1 -0
- package/dist/module/index.d.mts +6 -24
- package/dist/module/index.d.mts.map +1 -1
- package/dist/module/index.mjs +2 -2
- package/dist/module-xYoHba6B.mjs +422 -0
- package/dist/module-xYoHba6B.mjs.map +1 -0
- package/dist/openapi/index.d.mts +3 -3
- package/dist/openapi/index.d.mts.map +1 -1
- package/dist/openapi/index.mjs +1 -2
- package/dist/openapi-C6lm0RmV.mjs +483 -0
- package/dist/openapi-C6lm0RmV.mjs.map +1 -0
- package/dist/{openapi.service-BLgvn3hJ.d.mts → openapi.service-CrLlsXAd.d.mts} +3 -3
- package/dist/openapi.service-CrLlsXAd.d.mts.map +1 -0
- package/dist/quarry/index.d.mts +5 -163
- package/dist/quarry/index.d.mts.map +1 -1
- package/dist/quarry/index.mjs +5 -5
- package/dist/quarry/runner.d.mts +184 -0
- package/dist/quarry/runner.d.mts.map +1 -0
- package/dist/quarry/runner.mjs +775 -0
- package/dist/quarry/runner.mjs.map +1 -0
- package/dist/quarry-registry-D4hIGScf.d.mts +69 -0
- package/dist/quarry-registry-D4hIGScf.d.mts.map +1 -0
- package/dist/quarry-registry-DkraZNwn.mjs +311 -0
- package/dist/quarry-registry-DkraZNwn.mjs.map +1 -0
- package/dist/queue/index.d.mts +3 -3
- package/dist/queue/index.mjs +27 -28
- package/dist/queue/index.mjs.map +1 -1
- package/dist/{queue.module-BCdCiySt.mjs → queue.module-DeWJ0tQM.mjs} +67 -112
- package/dist/queue.module-DeWJ0tQM.mjs.map +1 -0
- package/dist/{r2-storage.provider-Co6F0ZYV.mjs → r2-storage.provider-Hfm6LdZQ.mjs} +8 -5
- package/dist/r2-storage.provider-Hfm6LdZQ.mjs.map +1 -0
- package/dist/{rate-limit.decorator--o6Q6p9w.mjs → rate-limit.decorator-D69zdZbp.mjs} +6 -11
- package/dist/rate-limit.decorator-D69zdZbp.mjs.map +1 -0
- package/dist/rate-limiter/index.d.mts +11 -50
- package/dist/rate-limiter/index.d.mts.map +1 -1
- package/dist/rate-limiter/index.mjs +25 -30
- package/dist/rate-limiter/index.mjs.map +1 -1
- package/dist/{resend.provider-M6qRLrcy.mjs → resend.provider-Ur6tU7fK.mjs} +8 -7
- package/dist/resend.provider-Ur6tU7fK.mjs.map +1 -0
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.mjs +8 -7
- package/dist/{i18n.module-BBlNNlcG.mjs → router-Cy6DjkvP.mjs} +215 -855
- package/dist/router-Cy6DjkvP.mjs.map +1 -0
- package/dist/seeder/index.d.mts +6 -11
- package/dist/seeder/index.d.mts.map +1 -1
- package/dist/seeder/index.mjs +3 -3
- package/dist/{seeder-CJAOHEIo.mjs → seeder-BADTig4n.mjs} +17 -22
- package/dist/seeder-BADTig4n.mjs.map +1 -0
- package/dist/{signed-url-BQPbv2In.mjs → signed-url-BqUqt5dF.mjs} +1 -1
- package/dist/{signed-url-BQPbv2In.mjs.map → signed-url-BqUqt5dF.mjs.map} +1 -1
- package/dist/{smtp.provider-w0Ve52Xg.mjs → smtp.provider-C129sNBT.mjs} +7 -6
- package/dist/smtp.provider-C129sNBT.mjs.map +1 -0
- package/dist/storage/index.d.mts +15 -39
- package/dist/storage/index.d.mts.map +1 -1
- package/dist/storage/index.mjs +3 -3
- package/dist/storage/providers/index.d.mts +2 -2
- package/dist/storage/providers/index.mjs +1 -1
- package/dist/{storage-1zw-6Yiz.mjs → storage-BA3ppVYM.mjs} +70 -59
- package/dist/storage-BA3ppVYM.mjs.map +1 -0
- package/dist/{storage-provider.interface-Bd6vA4ak.d.mts → storage-provider.interface-DQMtT42e.d.mts} +2 -3
- package/dist/storage-provider.interface-DQMtT42e.d.mts.map +1 -0
- package/dist/storage.error-C6FY037a.mjs +8 -0
- package/dist/storage.error-C6FY037a.mjs.map +1 -0
- package/dist/{stratal-DeEcGgdq.mjs → stratal-Bdq4IdB3.mjs} +31 -183
- package/dist/stratal-Bdq4IdB3.mjs.map +1 -0
- package/dist/stratal-BsKmvP6J.d.mts +43 -0
- package/dist/stratal-BsKmvP6J.d.mts.map +1 -0
- package/dist/{types-cySNS_lp.d.mts → types-BaeHi67f.d.mts} +1 -1
- package/dist/types-BaeHi67f.d.mts.map +1 -0
- package/dist/{usage-generator-BUdlhnCK.mjs → usage-generator-DTqaUMR9.mjs} +6 -3
- package/dist/usage-generator-DTqaUMR9.mjs.map +1 -0
- package/dist/validation-DUzcjb8Q.mjs +49 -0
- package/dist/validation-DUzcjb8Q.mjs.map +1 -0
- package/dist/validation.context-XTysWJ3b.mjs +117 -0
- package/dist/validation.context-XTysWJ3b.mjs.map +1 -0
- package/dist/websocket/index.d.mts +7 -14
- package/dist/websocket/index.d.mts.map +1 -1
- package/dist/websocket/index.mjs +2 -2
- package/dist/workers/index.d.mts +2 -2
- package/dist/workers/index.mjs +3 -2
- package/dist/workers/index.mjs.map +1 -1
- package/dist/{index-Bnpfq6uk.d.mts → zod-DvWTfRpI.d.mts} +58 -133
- package/dist/zod-DvWTfRpI.d.mts.map +1 -0
- package/dist/zod-hMa3rSHV.mjs +72 -0
- package/dist/zod-hMa3rSHV.mjs.map +1 -0
- package/package.json +20 -20
- package/dist/command-BgSlsS4M.mjs.map +0 -1
- package/dist/command-Bu-PjJrX.d.mts.map +0 -1
- package/dist/controller.decorator-DQzenvSN.mjs.map +0 -1
- package/dist/cron-manager-7Symz_TE.mjs.map +0 -1
- package/dist/cron-manager-BEsH1mjW.d.mts.map +0 -1
- package/dist/en-DSH_bhh6.mjs +0 -308
- package/dist/en-DSH_bhh6.mjs.map +0 -1
- package/dist/env-D1rcZ8_r.d.mts.map +0 -1
- package/dist/errors-BdyV5PnY.mjs +0 -1725
- package/dist/errors-BdyV5PnY.mjs.map +0 -1
- package/dist/errors-Da3Pz2X7.mjs +0 -74
- package/dist/errors-Da3Pz2X7.mjs.map +0 -1
- package/dist/events-COKixqnG.mjs.map +0 -1
- package/dist/gateway-context-CdJjpUCW.mjs.map +0 -1
- package/dist/guards-DUk_Kzst.mjs.map +0 -1
- package/dist/http-method.decorator-DXwxAfb_.mjs.map +0 -1
- package/dist/i18n.module-BBlNNlcG.mjs.map +0 -1
- package/dist/index-Bnpfq6uk.d.mts.map +0 -1
- package/dist/index-C1KvMncZ.d.mts.map +0 -1
- package/dist/index-CjaQ6_tZ.d.mts.map +0 -1
- package/dist/index-D0US0X14.d.mts.map +0 -1
- package/dist/index-DBd_2wv8.d.mts +0 -263
- package/dist/index-DBd_2wv8.d.mts.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/logger-V6Ms3QnQ.mjs +0 -436
- package/dist/logger-V6Ms3QnQ.mjs.map +0 -1
- package/dist/module-Dk2qTa77.mjs +0 -860
- package/dist/module-Dk2qTa77.mjs.map +0 -1
- package/dist/openapi-tools.service-Zs-Ewv7F.mjs +0 -200
- package/dist/openapi-tools.service-Zs-Ewv7F.mjs.map +0 -1
- package/dist/openapi.service-BLgvn3hJ.d.mts.map +0 -1
- package/dist/quarry-registry-DNEej-Db.mjs +0 -688
- package/dist/quarry-registry-DNEej-Db.mjs.map +0 -1
- package/dist/queue.module-BCdCiySt.mjs.map +0 -1
- package/dist/r2-storage.provider-Co6F0ZYV.mjs.map +0 -1
- package/dist/rate-limit.decorator--o6Q6p9w.mjs.map +0 -1
- package/dist/resend.provider-M6qRLrcy.mjs.map +0 -1
- package/dist/seeder-CJAOHEIo.mjs.map +0 -1
- package/dist/setup-CefZKV_e.mjs +0 -37
- package/dist/setup-CefZKV_e.mjs.map +0 -1
- package/dist/smtp.provider-w0Ve52Xg.mjs.map +0 -1
- package/dist/storage-1zw-6Yiz.mjs.map +0 -1
- package/dist/storage-provider.interface-Bd6vA4ak.d.mts.map +0 -1
- package/dist/stratal-DeEcGgdq.mjs.map +0 -1
- package/dist/types-cySNS_lp.d.mts.map +0 -1
- package/dist/usage-generator-BUdlhnCK.mjs.map +0 -1
- package/dist/validation-DtJwAv7O.mjs +0 -248
- package/dist/validation-DtJwAv7O.mjs.map +0 -1
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { a as ContainerError, o as ROUTER_TOKENS } from "./di-BO1QIb5H.mjs";
|
|
2
|
+
import { t as Macroable } from "./macroable-DzlfzT50.mjs";
|
|
3
|
+
import { deleteCookie, getCookie, setCookie } from "hono/cookie";
|
|
4
|
+
import { stream, streamSSE, streamText } from "hono/streaming";
|
|
5
|
+
//#region src/router/constants.ts
|
|
6
|
+
/**
|
|
7
|
+
* Type-safe context keys for Hono router variables
|
|
8
|
+
* Using symbols to avoid string collisions
|
|
9
|
+
*/
|
|
10
|
+
const ROUTER_CONTEXT_KEYS = {
|
|
11
|
+
REQUEST_CONTAINER: "requestContainer",
|
|
12
|
+
LOCALE: "locale"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Metadata keys for storing route and controller configuration
|
|
16
|
+
* Using symbols to avoid collisions with other decorators
|
|
17
|
+
*/
|
|
18
|
+
const ROUTE_METADATA_KEYS = {
|
|
19
|
+
CONTROLLER_ROUTE: Symbol.for("stratal:controller:route"),
|
|
20
|
+
CONTROLLER_OPTIONS: Symbol.for("stratal:controller:options"),
|
|
21
|
+
CONTROLLER_MIDDLEWARES: Symbol.for("stratal:controller:middlewares"),
|
|
22
|
+
ROUTE_CONFIG: Symbol.for("stratal:route:config"),
|
|
23
|
+
DECORATED_METHODS: Symbol.for("stratal:decorated:methods"),
|
|
24
|
+
AUTH_GUARD: Symbol.for("stratal:auth:guard"),
|
|
25
|
+
GATEWAY_MARKER: Symbol.for("stratal:gateway:marker"),
|
|
26
|
+
WS_ON_MESSAGE: Symbol.for("stratal:ws:on-message"),
|
|
27
|
+
WS_ON_CLOSE: Symbol.for("stratal:ws:on-close"),
|
|
28
|
+
WS_ON_ERROR: Symbol.for("stratal:ws:on-error"),
|
|
29
|
+
RATE_LIMIT: Symbol.for("stratal:route:rate-limit")
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Security scheme identifiers for OpenAPI
|
|
33
|
+
* These reference the security scheme definitions in security.schemas.ts
|
|
34
|
+
*/
|
|
35
|
+
const SECURITY_SCHEMES = {
|
|
36
|
+
BEARER_AUTH: "bearerAuth",
|
|
37
|
+
API_KEY: "apiKey",
|
|
38
|
+
SESSION_COOKIE: "sessionCookie"
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* HTTP method mapping for RESTful controller methods
|
|
42
|
+
* Maps controller method names to HTTP verbs and path patterns
|
|
43
|
+
*/
|
|
44
|
+
const HTTP_METHODS = {
|
|
45
|
+
index: {
|
|
46
|
+
method: "get",
|
|
47
|
+
path: ""
|
|
48
|
+
},
|
|
49
|
+
show: {
|
|
50
|
+
method: "get",
|
|
51
|
+
path: "/:id"
|
|
52
|
+
},
|
|
53
|
+
create: {
|
|
54
|
+
method: "post",
|
|
55
|
+
path: ""
|
|
56
|
+
},
|
|
57
|
+
update: {
|
|
58
|
+
method: "put",
|
|
59
|
+
path: "/:id"
|
|
60
|
+
},
|
|
61
|
+
patch: {
|
|
62
|
+
method: "patch",
|
|
63
|
+
path: "/:id"
|
|
64
|
+
},
|
|
65
|
+
destroy: {
|
|
66
|
+
method: "delete",
|
|
67
|
+
path: "/:id"
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Default success status codes for RESTful controller methods
|
|
72
|
+
* Used by @Route() decorator to auto-derive response status
|
|
73
|
+
*/
|
|
74
|
+
const METHOD_STATUS_CODES = {
|
|
75
|
+
index: 200,
|
|
76
|
+
show: 200,
|
|
77
|
+
create: 201,
|
|
78
|
+
update: 200,
|
|
79
|
+
patch: 200,
|
|
80
|
+
destroy: 200
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Sentinel symbol to opt a controller out of versioning.
|
|
84
|
+
* When used as the version, no prefix is applied even when defaultVersion is set.
|
|
85
|
+
*/
|
|
86
|
+
const VERSION_NEUTRAL = Symbol.for("stratal:version:neutral");
|
|
87
|
+
/**
|
|
88
|
+
* Default content type for request bodies and responses
|
|
89
|
+
*/
|
|
90
|
+
const DEFAULT_CONTENT_TYPE = "application/json";
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/router/router-context.ts
|
|
93
|
+
/**
|
|
94
|
+
* Router context wrapper with helper methods
|
|
95
|
+
*
|
|
96
|
+
* Provides convenient access to Hono's context and common request/response operations.
|
|
97
|
+
* The native Hono context is available via the `c` property for advanced use cases.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* async index(ctx: RouterContext): Promise<Response> {
|
|
102
|
+
* // Use helper methods
|
|
103
|
+
* const users = await this.service.findAll()
|
|
104
|
+
* return ctx.json(users)
|
|
105
|
+
* }
|
|
106
|
+
*
|
|
107
|
+
* async show(ctx: RouterContext): Promise<Response> {
|
|
108
|
+
* // Access route params
|
|
109
|
+
* const id = ctx.param('id')
|
|
110
|
+
* const user = await this.service.findById(id)
|
|
111
|
+
* return ctx.json(user)
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* async create(ctx: RouterContext): Promise<Response> {
|
|
115
|
+
* // Parse request body
|
|
116
|
+
* const body = await ctx.body<CreateUserInput>()
|
|
117
|
+
* const user = await this.service.create(body)
|
|
118
|
+
* return ctx.json(user, 201)
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
var RouterContext = class extends Macroable {
|
|
123
|
+
c;
|
|
124
|
+
/**
|
|
125
|
+
* Native Hono context
|
|
126
|
+
* Access for advanced use cases not covered by helper methods
|
|
127
|
+
*/
|
|
128
|
+
constructor(c) {
|
|
129
|
+
super();
|
|
130
|
+
this.c = c;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Cloudflare-provided request properties (geo, TLS, bot management, etc.).
|
|
134
|
+
* Always available on Cloudflare Workers requests via `c.req.raw.cf`.
|
|
135
|
+
*/
|
|
136
|
+
get cf() {
|
|
137
|
+
return this.c.req.raw.cf;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get request-scoped DI container
|
|
141
|
+
* Contains request-specific services and context (AuthContext)
|
|
142
|
+
*
|
|
143
|
+
* @throws Error if container not initialized
|
|
144
|
+
*/
|
|
145
|
+
getContainer() {
|
|
146
|
+
const container = this.c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER);
|
|
147
|
+
if (!container) throw new ContainerError("Request container has not been initialized");
|
|
148
|
+
return container;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Set locale for the current request
|
|
152
|
+
*
|
|
153
|
+
* @param locale - Locale code (e.g., 'en', 'fr')
|
|
154
|
+
*/
|
|
155
|
+
setLocale(locale) {
|
|
156
|
+
this.c.set(ROUTER_CONTEXT_KEYS.LOCALE, locale);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get locale for the current request
|
|
160
|
+
*
|
|
161
|
+
* @returns Current locale code
|
|
162
|
+
*/
|
|
163
|
+
getLocale() {
|
|
164
|
+
return this.c.get(ROUTER_CONTEXT_KEYS.LOCALE) || "en";
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Return JSON response
|
|
168
|
+
*
|
|
169
|
+
* When data is null, automatically returns 204 No Content (configurable via status param).
|
|
170
|
+
*
|
|
171
|
+
* @param data - Data to serialize as JSON, or null for 204
|
|
172
|
+
* @param status - HTTP status code (default: 200, or 204 when data is null)
|
|
173
|
+
*/
|
|
174
|
+
json(data, status) {
|
|
175
|
+
if (data === null) return this.c.body(null, status ?? 204);
|
|
176
|
+
return this.c.json(data, status);
|
|
177
|
+
}
|
|
178
|
+
param(key) {
|
|
179
|
+
const all = this.c.req.valid("param") ?? {};
|
|
180
|
+
return key === void 0 ? all : all[key];
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get query parameter value
|
|
184
|
+
*
|
|
185
|
+
* @param key - Query parameter name
|
|
186
|
+
*/
|
|
187
|
+
query(key) {
|
|
188
|
+
const validated = this.c.req.valid("query");
|
|
189
|
+
return key ? validated[key] : validated;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get request header value
|
|
193
|
+
*
|
|
194
|
+
* @param name - Header name (case-insensitive)
|
|
195
|
+
*/
|
|
196
|
+
header(name) {
|
|
197
|
+
return this.c.req.header(name);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Read a cookie value from the current request.
|
|
201
|
+
*
|
|
202
|
+
* @param name - Cookie name
|
|
203
|
+
* @returns The cookie value, or `undefined` if the cookie is not present
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* const redirectTo = ctx.getCookie('redirectTo')
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
getCookie(name) {
|
|
211
|
+
return getCookie(this.c, name);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Set a cookie on the response.
|
|
215
|
+
*
|
|
216
|
+
* Cookie operations must run while the response is mutable — call this
|
|
217
|
+
* before returning the final `Response` from the handler.
|
|
218
|
+
*
|
|
219
|
+
* @param name - Cookie name
|
|
220
|
+
* @param value - Cookie value
|
|
221
|
+
* @param options - Cookie attributes (httpOnly, secure, sameSite, path, etc.)
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* ctx.setCookie('redirectTo', '/app/', {
|
|
226
|
+
* httpOnly: true,
|
|
227
|
+
* secure: true,
|
|
228
|
+
* sameSite: 'lax',
|
|
229
|
+
* path: '/',
|
|
230
|
+
* })
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
setCookie(name, value, options) {
|
|
234
|
+
setCookie(this.c, name, value, options);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Delete a cookie from the response.
|
|
238
|
+
*
|
|
239
|
+
* Pass the same `path` and `domain` options that were used when the cookie
|
|
240
|
+
* was set, otherwise the browser will not clear the matching cookie.
|
|
241
|
+
*
|
|
242
|
+
* @param name - Cookie name
|
|
243
|
+
* @param options - Cookie attributes used at set time (path, domain, etc.)
|
|
244
|
+
* @returns The deleted cookie's previous value, or `undefined`
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```typescript
|
|
248
|
+
* ctx.deleteCookie('redirectTo', { path: '/' })
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
deleteCookie(name, options) {
|
|
252
|
+
return deleteCookie(this.c, name, options);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get validated request body from OpenAPI route
|
|
256
|
+
* Returns pre-validated data that has passed schema validation
|
|
257
|
+
*
|
|
258
|
+
* @returns Validated JSON body
|
|
259
|
+
*/
|
|
260
|
+
body() {
|
|
261
|
+
return this.c.req.valid("json");
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Return text response
|
|
265
|
+
*
|
|
266
|
+
* @param text - Text content
|
|
267
|
+
* @param status - HTTP status code (default: 200)
|
|
268
|
+
*/
|
|
269
|
+
text(text, status) {
|
|
270
|
+
return this.c.text(text, status);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Return HTML response
|
|
274
|
+
*
|
|
275
|
+
* @param html - HTML content
|
|
276
|
+
* @param status - HTTP status code (default: 200)
|
|
277
|
+
*/
|
|
278
|
+
html(html, status) {
|
|
279
|
+
return this.c.html(html, status);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Generate a URL from a named route.
|
|
283
|
+
*
|
|
284
|
+
* Keys matching `:param` placeholders fill the path.
|
|
285
|
+
* Domain params are consumed from the same object.
|
|
286
|
+
* Extra keys become query string parameters.
|
|
287
|
+
*
|
|
288
|
+
* @param name - Named route identifier
|
|
289
|
+
* @param params - Route params + domain params + extra query params
|
|
290
|
+
* @param options - URL generation options (e.g., `{ absolute: true }`)
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* ctx.route('users.show', { id: '1' }) // '/v1/users/1'
|
|
295
|
+
* ctx.route('users.show', { id: '1', q: 'test' }) // '/v1/users/1?q=test'
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
route(name, params, options) {
|
|
299
|
+
return this.resolveUri().route(name, params, options);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get a domain parameter value from the current request.
|
|
303
|
+
* Domain params are set by the domain matching middleware.
|
|
304
|
+
*
|
|
305
|
+
* @param key - Domain parameter name (e.g., 'tenant' from '{tenant}.myapp.com')
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const tenant = ctx.domain('tenant')
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
domain(key) {
|
|
313
|
+
return this.c.get(`domain:${key}`);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Generate a signed URL from a named route.
|
|
317
|
+
*
|
|
318
|
+
* @param name - Named route identifier
|
|
319
|
+
* @param params - Route params (same as route())
|
|
320
|
+
* @param options - Signing options (e.g., expiresIn) and URL options
|
|
321
|
+
* @returns Signed URL string with signature query param
|
|
322
|
+
*/
|
|
323
|
+
async signedUrl(name, params, options) {
|
|
324
|
+
return this.resolveUri().signedRoute(name, params, options);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Check if the current request has a valid signature.
|
|
328
|
+
*
|
|
329
|
+
* @returns true if the URL signature is valid and not expired
|
|
330
|
+
*/
|
|
331
|
+
async hasValidSignature() {
|
|
332
|
+
return this.resolveUri().hasValidSignature();
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Redirect to another URL
|
|
336
|
+
*
|
|
337
|
+
* @param url - Target URL
|
|
338
|
+
* @param status - HTTP status code (default: 302)
|
|
339
|
+
*/
|
|
340
|
+
redirect(url, status) {
|
|
341
|
+
return this.c.redirect(url, status);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Return a streaming response (binary/generic)
|
|
345
|
+
*
|
|
346
|
+
* @param callback - Async function that writes to the stream
|
|
347
|
+
* @param onError - Optional error handler called if an error occurs during streaming
|
|
348
|
+
*/
|
|
349
|
+
stream(callback, onError) {
|
|
350
|
+
return stream(this.c, callback, onError);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Return a streaming text response
|
|
354
|
+
*
|
|
355
|
+
* Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.
|
|
356
|
+
*
|
|
357
|
+
* @param callback - Async function that writes text to the stream
|
|
358
|
+
* @param onError - Optional error handler called if an error occurs during streaming
|
|
359
|
+
*/
|
|
360
|
+
streamText(callback, onError) {
|
|
361
|
+
this.c.header("Content-Encoding", "Identity");
|
|
362
|
+
return streamText(this.c, callback, onError);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Return a Server-Sent Events (SSE) streaming response
|
|
366
|
+
*
|
|
367
|
+
* Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.
|
|
368
|
+
*
|
|
369
|
+
* @param callback - Async function that writes SSE events to the stream
|
|
370
|
+
* @param onError - Optional error handler called if an error occurs during streaming
|
|
371
|
+
*/
|
|
372
|
+
streamSSE(callback, onError) {
|
|
373
|
+
this.c.header("Content-Encoding", "Identity");
|
|
374
|
+
return streamSSE(this.c, callback, onError);
|
|
375
|
+
}
|
|
376
|
+
resolveUri() {
|
|
377
|
+
return this.getContainer().resolve(ROUTER_TOKENS.Uri);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
//#endregion
|
|
381
|
+
//#region src/errors/exception-context.ts
|
|
382
|
+
/**
|
|
383
|
+
* Create an HTTP exception context from a Hono context.
|
|
384
|
+
*
|
|
385
|
+
* @param c - The raw Hono context from the request
|
|
386
|
+
* @returns An {@link HttpExceptionContext} wrapping a RouterContext
|
|
387
|
+
*/
|
|
388
|
+
function createHttpExceptionContext(c) {
|
|
389
|
+
return {
|
|
390
|
+
type: "http",
|
|
391
|
+
ctx: new RouterContext(c)
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Create a queue exception context.
|
|
396
|
+
*
|
|
397
|
+
* @param queueName - The name of the queue being processed
|
|
398
|
+
* @returns A {@link QueueExceptionContext}
|
|
399
|
+
*/
|
|
400
|
+
function createQueueExceptionContext(queueName) {
|
|
401
|
+
return {
|
|
402
|
+
type: "queue",
|
|
403
|
+
queueName
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Create a cron exception context.
|
|
408
|
+
*
|
|
409
|
+
* @returns A {@link CronExceptionContext}
|
|
410
|
+
*/
|
|
411
|
+
function createCronExceptionContext() {
|
|
412
|
+
return { type: "cron" };
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Create a CLI command exception context.
|
|
416
|
+
*
|
|
417
|
+
* @param commandName - The name of the command that threw
|
|
418
|
+
* @returns A {@link CliExceptionContext}
|
|
419
|
+
*/
|
|
420
|
+
function createCliExceptionContext(commandName) {
|
|
421
|
+
return {
|
|
422
|
+
type: "cli",
|
|
423
|
+
commandName
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
//#endregion
|
|
427
|
+
export { RouterContext as a, METHOD_STATUS_CODES as c, SECURITY_SCHEMES as d, VERSION_NEUTRAL as f, createQueueExceptionContext as i, ROUTER_CONTEXT_KEYS as l, createCronExceptionContext as n, DEFAULT_CONTENT_TYPE as o, createHttpExceptionContext as r, HTTP_METHODS as s, createCliExceptionContext as t, ROUTE_METADATA_KEYS as u };
|
|
428
|
+
|
|
429
|
+
//# sourceMappingURL=exception-context-B4kM-M53.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exception-context-B4kM-M53.mjs","names":["honoGetCookie","honoDeleteCookie","honoStream","honoStreamText","honoStreamSSE"],"sources":["../src/router/constants.ts","../src/router/router-context.ts","../src/errors/exception-context.ts"],"sourcesContent":["/**\n * Type-safe context keys for Hono router variables\n * Using symbols to avoid string collisions\n */\nexport const ROUTER_CONTEXT_KEYS = {\n REQUEST_CONTAINER: 'requestContainer',\n LOCALE: 'locale'\n} as const satisfies Record<string, string>\n\n/**\n * Metadata keys for storing route and controller configuration\n * Using symbols to avoid collisions with other decorators\n */\nexport const ROUTE_METADATA_KEYS = {\n CONTROLLER_ROUTE: Symbol.for('stratal:controller:route'),\n CONTROLLER_OPTIONS: Symbol.for('stratal:controller:options'),\n CONTROLLER_MIDDLEWARES: Symbol.for('stratal:controller:middlewares'),\n ROUTE_CONFIG: Symbol.for('stratal:route:config'),\n DECORATED_METHODS: Symbol.for('stratal:decorated:methods'),\n AUTH_GUARD: Symbol.for('stratal:auth:guard'),\n GATEWAY_MARKER: Symbol.for('stratal:gateway:marker'),\n WS_ON_MESSAGE: Symbol.for('stratal:ws:on-message'),\n WS_ON_CLOSE: Symbol.for('stratal:ws:on-close'),\n WS_ON_ERROR: Symbol.for('stratal:ws:on-error'),\n RATE_LIMIT: Symbol.for('stratal:route:rate-limit'),\n} as const\n\n/**\n * Security scheme identifiers for OpenAPI\n * These reference the security scheme definitions in security.schemas.ts\n */\nexport const SECURITY_SCHEMES = {\n BEARER_AUTH: 'bearerAuth',\n API_KEY: 'apiKey',\n SESSION_COOKIE: 'sessionCookie'\n} as const\n\n/**\n * HTTP method mapping for RESTful controller methods\n * Maps controller method names to HTTP verbs and path patterns\n */\nexport const HTTP_METHODS = {\n index: { method: 'get', path: '' } as const,\n show: { method: 'get', path: '/:id' } as const,\n create: { method: 'post', path: '' } as const,\n update: { method: 'put', path: '/:id' } as const,\n patch: { method: 'patch', path: '/:id' } as const,\n destroy: { method: 'delete', path: '/:id' } as const\n} as const\n\n/**\n * Default success status codes for RESTful controller methods\n * Used by @Route() decorator to auto-derive response status\n */\nexport const METHOD_STATUS_CODES = {\n index: 200,\n show: 200,\n create: 201,\n update: 200,\n patch: 200,\n destroy: 200\n} as const\n\n/**\n * Sentinel symbol to opt a controller out of versioning.\n * When used as the version, no prefix is applied even when defaultVersion is set.\n */\nexport const VERSION_NEUTRAL = Symbol.for('stratal:version:neutral')\n\n/**\n * Default content type for request bodies and responses\n */\nexport const DEFAULT_CONTENT_TYPE = 'application/json'\n","import type { Context } from 'hono'\nimport {\n deleteCookie as honoDeleteCookie,\n getCookie as honoGetCookie,\n setCookie as honoSetCookie,\n} from 'hono/cookie'\nimport type { SSEStreamingApi } from 'hono/streaming'\nimport { stream as honoStream, streamSSE as honoStreamSSE, streamText as honoStreamText } from 'hono/streaming'\nimport type { CookieOptions } from 'hono/utils/cookie'\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status'\nimport type { StreamingApi } from 'hono/utils/stream'\nimport type { Container } from '../di/container'\nimport { ContainerError } from '../di/container.error'\nimport { Macroable } from '../macroable'\nimport { ROUTER_CONTEXT_KEYS } from './constants'\nimport type { RouteName, RouteParams } from './route-map'\nimport { ROUTER_TOKENS } from './router.tokens'\nimport type { RouterEnv } from './types'\nimport type { SignedUriOptions, Uri, UriOptions } from './uri'\n\nexport type ContextQueryResult<R extends Record<string, unknown> | undefined, K extends string | undefined> = K extends string ? string : R extends undefined ? Record<string, unknown> : R\n\n/**\n * Router context wrapper with helper methods\n *\n * Provides convenient access to Hono's context and common request/response operations.\n * The native Hono context is available via the `c` property for advanced use cases.\n *\n * @example\n * ```typescript\n * async index(ctx: RouterContext): Promise<Response> {\n * // Use helper methods\n * const users = await this.service.findAll()\n * return ctx.json(users)\n * }\n *\n * async show(ctx: RouterContext): Promise<Response> {\n * // Access route params\n * const id = ctx.param('id')\n * const user = await this.service.findById(id)\n * return ctx.json(user)\n * }\n *\n * async create(ctx: RouterContext): Promise<Response> {\n * // Parse request body\n * const body = await ctx.body<CreateUserInput>()\n * const user = await this.service.create(body)\n * return ctx.json(user, 201)\n * }\n * ```\n */\nexport class RouterContext<T extends RouterEnv = RouterEnv> extends Macroable {\n /**\n * Native Hono context\n * Access for advanced use cases not covered by helper methods\n */\n constructor(\n public readonly c: Context<T>\n ) {\n super()\n }\n\n /**\n * Cloudflare-provided request properties (geo, TLS, bot management, etc.).\n * Always available on Cloudflare Workers requests via `c.req.raw.cf`.\n */\n get cf(): CfProperties {\n return this.c.req.raw.cf!\n }\n\n /**\n * Get request-scoped DI container\n * Contains request-specific services and context (AuthContext)\n *\n * @throws Error if container not initialized\n */\n getContainer(): Container {\n const container = this.c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER)\n if (!container) {\n throw new ContainerError('Request container has not been initialized')\n }\n return container as Container\n }\n\n /**\n * Set locale for the current request\n *\n * @param locale - Locale code (e.g., 'en', 'fr')\n */\n setLocale(locale: string): void {\n this.c.set(ROUTER_CONTEXT_KEYS.LOCALE, locale)\n }\n\n /**\n * Get locale for the current request\n *\n * @returns Current locale code\n */\n getLocale(): string {\n const locale = this.c.get(ROUTER_CONTEXT_KEYS.LOCALE)\n return (locale as string) || 'en'\n }\n\n /**\n * Return JSON response\n *\n * When data is null, automatically returns 204 No Content (configurable via status param).\n *\n * @param data - Data to serialize as JSON, or null for 204\n * @param status - HTTP status code (default: 200, or 204 when data is null)\n */\n json(data: object | null, status?: ContentfulStatusCode): Response {\n if (data === null) {\n return this.c.body(null, status ?? 204)\n }\n return this.c.json(data, status)\n }\n\n /**\n * Get route parameter value(s).\n *\n * Reads the validated, Zod-coerced param record from `c.req.valid('param')`,\n * which is what `@hono/zod-openapi` populates for every route registered\n * via `app.openapi(...)`. Bare `c.req.param()` returns `undefined` for those\n * routes — always go through the validated record.\n *\n * - With a key → returns the single string value.\n * - With no args → returns the full `Record<string, string>` (or `{}` when\n * the matched route has no path params).\n *\n * @param key - Parameter name (e.g., 'id' for /users/:id)\n */\n param(): Record<string, string>\n param(key: string): string\n param(key?: string): string | Record<string, string> {\n const all = (this.c.req as unknown as { valid(target: 'param'): Record<string, string> | undefined }).valid('param') ?? {}\n return key === undefined ? all : all[key]\n }\n\n /**\n * Get query parameter value\n *\n * @param key - Query parameter name\n */\n query<R extends Record<string, unknown> | undefined = undefined, K extends string | undefined = undefined>(key?: K): ContextQueryResult<R, K> {\n const validated = (this.c.req as unknown as { valid(target: 'query'): Record<string, unknown> }).valid('query')\n return key ? validated[key] as ContextQueryResult<R, K> : validated as ContextQueryResult<R, K>\n }\n\n /**\n * Get request header value\n *\n * @param name - Header name (case-insensitive)\n */\n header(name: string): string | undefined {\n return this.c.req.header(name)\n }\n\n /**\n * Read a cookie value from the current request.\n *\n * @param name - Cookie name\n * @returns The cookie value, or `undefined` if the cookie is not present\n *\n * @example\n * ```typescript\n * const redirectTo = ctx.getCookie('redirectTo')\n * ```\n */\n getCookie(name: string): string | undefined {\n return honoGetCookie(this.c, name)\n }\n\n /**\n * Set a cookie on the response.\n *\n * Cookie operations must run while the response is mutable — call this\n * before returning the final `Response` from the handler.\n *\n * @param name - Cookie name\n * @param value - Cookie value\n * @param options - Cookie attributes (httpOnly, secure, sameSite, path, etc.)\n *\n * @example\n * ```typescript\n * ctx.setCookie('redirectTo', '/app/', {\n * httpOnly: true,\n * secure: true,\n * sameSite: 'lax',\n * path: '/',\n * })\n * ```\n */\n setCookie(name: string, value: string, options?: CookieOptions): void {\n honoSetCookie(this.c, name, value, options)\n }\n\n /**\n * Delete a cookie from the response.\n *\n * Pass the same `path` and `domain` options that were used when the cookie\n * was set, otherwise the browser will not clear the matching cookie.\n *\n * @param name - Cookie name\n * @param options - Cookie attributes used at set time (path, domain, etc.)\n * @returns The deleted cookie's previous value, or `undefined`\n *\n * @example\n * ```typescript\n * ctx.deleteCookie('redirectTo', { path: '/' })\n * ```\n */\n deleteCookie(name: string, options?: CookieOptions): string | undefined {\n return honoDeleteCookie(this.c, name, options)\n }\n\n /**\n * Get validated request body from OpenAPI route\n * Returns pre-validated data that has passed schema validation\n *\n * @returns Validated JSON body\n */\n body<T>(): Promise<T> {\n // Type assertion needed because req.valid() is type-safe per route\n // but this is a generic helper method that works across all routes\n return (this.c.req as unknown as { valid(target: 'json'): Promise<T> }).valid('json')\n }\n\n /**\n * Return text response\n *\n * @param text - Text content\n * @param status - HTTP status code (default: 200)\n */\n text(text: string, status?: ContentfulStatusCode): Response {\n return this.c.text(text, status)\n }\n\n /**\n * Return HTML response\n *\n * @param html - HTML content\n * @param status - HTTP status code (default: 200)\n */\n html(html: string, status?: ContentfulStatusCode): Response {\n return this.c.html(html, status)\n }\n\n /**\n * Generate a URL from a named route.\n *\n * Keys matching `:param` placeholders fill the path.\n * Domain params are consumed from the same object.\n * Extra keys become query string parameters.\n *\n * @param name - Named route identifier\n * @param params - Route params + domain params + extra query params\n * @param options - URL generation options (e.g., `{ absolute: true }`)\n *\n * @example\n * ```typescript\n * ctx.route('users.show', { id: '1' }) // '/v1/users/1'\n * ctx.route('users.show', { id: '1', q: 'test' }) // '/v1/users/1?q=test'\n * ```\n */\n route<N extends RouteName>(name: N, params?: RouteParams<N>, options?: UriOptions): string {\n return this.resolveUri().route(name, params, options)\n }\n\n /**\n * Get a domain parameter value from the current request.\n * Domain params are set by the domain matching middleware.\n *\n * @param key - Domain parameter name (e.g., 'tenant' from '{tenant}.myapp.com')\n *\n * @example\n * ```typescript\n * const tenant = ctx.domain('tenant')\n * ```\n */\n domain(key: string): string {\n return this.c.get(`domain:${key}`) as string\n }\n\n /**\n * Generate a signed URL from a named route.\n *\n * @param name - Named route identifier\n * @param params - Route params (same as route())\n * @param options - Signing options (e.g., expiresIn) and URL options\n * @returns Signed URL string with signature query param\n */\n async signedUrl<N extends RouteName>(name: N, params?: RouteParams<N>, options?: SignedUriOptions): Promise<string> {\n return this.resolveUri().signedRoute(name, params, options)\n }\n\n /**\n * Check if the current request has a valid signature.\n *\n * @returns true if the URL signature is valid and not expired\n */\n async hasValidSignature(): Promise<boolean> {\n return this.resolveUri().hasValidSignature()\n }\n\n /**\n * Redirect to another URL\n *\n * @param url - Target URL\n * @param status - HTTP status code (default: 302)\n */\n redirect(url: string, status?: RedirectStatusCode): Response {\n return this.c.redirect(url, status)\n }\n\n /**\n * Return a streaming response (binary/generic)\n *\n * @param callback - Async function that writes to the stream\n * @param onError - Optional error handler called if an error occurs during streaming\n */\n stream(callback: (stream: StreamingApi) => Promise<void>, onError?: (err: Error, stream: StreamingApi) => Promise<void>): Response {\n return honoStream(this.c, callback, onError)\n }\n\n /**\n * Return a streaming text response\n *\n * Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.\n *\n * @param callback - Async function that writes text to the stream\n * @param onError - Optional error handler called if an error occurs during streaming\n */\n streamText(callback: (stream: StreamingApi) => Promise<void>, onError?: (err: Error, stream: StreamingApi) => Promise<void>): Response {\n this.c.header('Content-Encoding', 'Identity')\n return honoStreamText(this.c, callback, onError)\n }\n\n /**\n * Return a Server-Sent Events (SSE) streaming response\n *\n * Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.\n *\n * @param callback - Async function that writes SSE events to the stream\n * @param onError - Optional error handler called if an error occurs during streaming\n */\n streamSSE(callback: (stream: SSEStreamingApi) => Promise<void>, onError?: (err: Error, stream: SSEStreamingApi) => Promise<void>): Response {\n this.c.header('Content-Encoding', 'Identity')\n return honoStreamSSE(this.c, callback, onError)\n }\n\n private resolveUri(): Uri {\n return this.getContainer().resolve<Uri>(ROUTER_TOKENS.Uri)\n }\n}\n","import type { Context } from 'hono'\nimport { RouterContext } from '../router/router-context'\nimport type { RouterEnv } from '../router/types'\n\n/**\n * Exception context for errors occurring during HTTP request handling.\n *\n * Provides access to the full {@link RouterContext} for building responses\n * with `ctx.json()`, `ctx.text()`, `ctx.html()`, etc.\n */\nexport interface HttpExceptionContext {\n readonly type: 'http'\n /** Stratal RouterContext — use for building HTTP responses */\n readonly ctx: RouterContext\n}\n\n/**\n * Exception context for errors occurring during queue message processing.\n */\nexport interface QueueExceptionContext {\n readonly type: 'queue'\n /** Name of the queue being processed */\n readonly queueName: string\n}\n\n/**\n * Exception context for errors occurring during scheduled cron execution.\n */\nexport interface CronExceptionContext {\n readonly type: 'cron'\n}\n\n/**\n * Exception context for errors occurring during CLI command execution.\n */\nexport interface CliExceptionContext {\n readonly type: 'cli'\n /** Name of the command that threw */\n readonly commandName: string\n}\n\n/**\n * Discriminated union of all exception context types.\n *\n * Narrow via `ctx.type` to access context-specific properties:\n *\n * @example\n * ```typescript\n * handler.renderable(MyError, (error, ctx) => {\n * if (ctx.type === 'http') {\n * return ctx.ctx.json({ message: 'Something went wrong' }, 500)\n * }\n * // Non-HTTP contexts: return undefined to use default rendering\n * })\n * ```\n */\nexport type ExceptionContext =\n | HttpExceptionContext\n | QueueExceptionContext\n | CronExceptionContext\n | CliExceptionContext\n\n/**\n * Create an HTTP exception context from a Hono context.\n *\n * @param c - The raw Hono context from the request\n * @returns An {@link HttpExceptionContext} wrapping a RouterContext\n */\nexport function createHttpExceptionContext(c: Context<RouterEnv>): HttpExceptionContext {\n return { type: 'http', ctx: new RouterContext(c) }\n}\n\n/**\n * Create a queue exception context.\n *\n * @param queueName - The name of the queue being processed\n * @returns A {@link QueueExceptionContext}\n */\nexport function createQueueExceptionContext(queueName: string): QueueExceptionContext {\n return { type: 'queue', queueName }\n}\n\n/**\n * Create a cron exception context.\n *\n * @returns A {@link CronExceptionContext}\n */\nexport function createCronExceptionContext(): CronExceptionContext {\n return { type: 'cron' }\n}\n\n/**\n * Create a CLI command exception context.\n *\n * @param commandName - The name of the command that threw\n * @returns A {@link CliExceptionContext}\n */\nexport function createCliExceptionContext(commandName: string): CliExceptionContext {\n return { type: 'cli', commandName }\n}\n"],"mappings":";;;;;;;;;AAIA,MAAa,sBAAsB;CACjC,mBAAmB;CACnB,QAAQ;CACT;;;;;AAMD,MAAa,sBAAsB;CACjC,kBAAkB,OAAO,IAAI,2BAA2B;CACxD,oBAAoB,OAAO,IAAI,6BAA6B;CAC5D,wBAAwB,OAAO,IAAI,iCAAiC;CACpE,cAAc,OAAO,IAAI,uBAAuB;CAChD,mBAAmB,OAAO,IAAI,4BAA4B;CAC1D,YAAY,OAAO,IAAI,qBAAqB;CAC5C,gBAAgB,OAAO,IAAI,yBAAyB;CACpD,eAAe,OAAO,IAAI,wBAAwB;CAClD,aAAa,OAAO,IAAI,sBAAsB;CAC9C,aAAa,OAAO,IAAI,sBAAsB;CAC9C,YAAY,OAAO,IAAI,2BAA2B;CACnD;;;;;AAMD,MAAa,mBAAmB;CAC9B,aAAa;CACb,SAAS;CACT,gBAAgB;CACjB;;;;;AAMD,MAAa,eAAe;CAC1B,OAAO;EAAE,QAAQ;EAAO,MAAM;EAAI;CAClC,MAAM;EAAE,QAAQ;EAAO,MAAM;EAAQ;CACrC,QAAQ;EAAE,QAAQ;EAAQ,MAAM;EAAI;CACpC,QAAQ;EAAE,QAAQ;EAAO,MAAM;EAAQ;CACvC,OAAO;EAAE,QAAQ;EAAS,MAAM;EAAQ;CACxC,SAAS;EAAE,QAAQ;EAAU,MAAM;EAAQ;CAC5C;;;;;AAMD,MAAa,sBAAsB;CACjC,OAAO;CACP,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,SAAS;CACV;;;;;AAMD,MAAa,kBAAkB,OAAO,IAAI,0BAA0B;;;;AAKpE,MAAa,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrBpC,IAAa,gBAAb,cAAoE,UAAU;CAM1D;;;;;CADlB,YACE,GACA;EACA,OAAO;EAFS,KAAA,IAAA;;;;;;CASlB,IAAI,KAAmB;EACrB,OAAO,KAAK,EAAE,IAAI,IAAI;;;;;;;;CASxB,eAA0B;EACxB,MAAM,YAAY,KAAK,EAAE,IAAI,oBAAoB,kBAAkB;EACnE,IAAI,CAAC,WACH,MAAM,IAAI,eAAe,6CAA6C;EAExE,OAAO;;;;;;;CAQT,UAAU,QAAsB;EAC9B,KAAK,EAAE,IAAI,oBAAoB,QAAQ,OAAO;;;;;;;CAQhD,YAAoB;EAElB,OADe,KAAK,EAAE,IAAI,oBAAoB,OAChC,IAAe;;;;;;;;;;CAW/B,KAAK,MAAqB,QAAyC;EACjE,IAAI,SAAS,MACX,OAAO,KAAK,EAAE,KAAK,MAAM,UAAU,IAAI;EAEzC,OAAO,KAAK,EAAE,KAAK,MAAM,OAAO;;CAmBlC,MAAM,KAA+C;EACnD,MAAM,MAAO,KAAK,EAAE,IAAkF,MAAM,QAAQ,IAAI,EAAE;EAC1H,OAAO,QAAQ,KAAA,IAAY,MAAM,IAAI;;;;;;;CAQvC,MAA2G,KAAmC;EAC5I,MAAM,YAAa,KAAK,EAAE,IAAuE,MAAM,QAAQ;EAC/G,OAAO,MAAM,UAAU,OAAmC;;;;;;;CAQ5D,OAAO,MAAkC;EACvC,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK;;;;;;;;;;;;;CAchC,UAAU,MAAkC;EAC1C,OAAOA,UAAc,KAAK,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;CAuBpC,UAAU,MAAc,OAAe,SAA+B;EACpE,UAAc,KAAK,GAAG,MAAM,OAAO,QAAQ;;;;;;;;;;;;;;;;;CAkB7C,aAAa,MAAc,SAA6C;EACtE,OAAOC,aAAiB,KAAK,GAAG,MAAM,QAAQ;;;;;;;;CAShD,OAAsB;EAGpB,OAAQ,KAAK,EAAE,IAAyD,MAAM,OAAO;;;;;;;;CASvF,KAAK,MAAc,QAAyC;EAC1D,OAAO,KAAK,EAAE,KAAK,MAAM,OAAO;;;;;;;;CASlC,KAAK,MAAc,QAAyC;EAC1D,OAAO,KAAK,EAAE,KAAK,MAAM,OAAO;;;;;;;;;;;;;;;;;;;CAoBlC,MAA2B,MAAS,QAAyB,SAA8B;EACzF,OAAO,KAAK,YAAY,CAAC,MAAM,MAAM,QAAQ,QAAQ;;;;;;;;;;;;;CAcvD,OAAO,KAAqB;EAC1B,OAAO,KAAK,EAAE,IAAI,UAAU,MAAM;;;;;;;;;;CAWpC,MAAM,UAA+B,MAAS,QAAyB,SAA6C;EAClH,OAAO,KAAK,YAAY,CAAC,YAAY,MAAM,QAAQ,QAAQ;;;;;;;CAQ7D,MAAM,oBAAsC;EAC1C,OAAO,KAAK,YAAY,CAAC,mBAAmB;;;;;;;;CAS9C,SAAS,KAAa,QAAuC;EAC3D,OAAO,KAAK,EAAE,SAAS,KAAK,OAAO;;;;;;;;CASrC,OAAO,UAAmD,SAAyE;EACjI,OAAOC,OAAW,KAAK,GAAG,UAAU,QAAQ;;;;;;;;;;CAW9C,WAAW,UAAmD,SAAyE;EACrI,KAAK,EAAE,OAAO,oBAAoB,WAAW;EAC7C,OAAOC,WAAe,KAAK,GAAG,UAAU,QAAQ;;;;;;;;;;CAWlD,UAAU,UAAsD,SAA4E;EAC1I,KAAK,EAAE,OAAO,oBAAoB,WAAW;EAC7C,OAAOC,UAAc,KAAK,GAAG,UAAU,QAAQ;;CAGjD,aAA0B;EACxB,OAAO,KAAK,cAAc,CAAC,QAAa,cAAc,IAAI;;;;;;;;;;;AC5R9D,SAAgB,2BAA2B,GAA6C;CACtF,OAAO;EAAE,MAAM;EAAQ,KAAK,IAAI,cAAc,EAAE;EAAE;;;;;;;;AASpD,SAAgB,4BAA4B,WAA0C;CACpF,OAAO;EAAE,MAAM;EAAS;EAAW;;;;;;;AAQrC,SAAgB,6BAAmD;CACjE,OAAO,EAAE,MAAM,QAAQ;;;;;;;;AASzB,SAAgB,0BAA0B,aAA0C;CAClF,OAAO;EAAE,MAAM;EAAO;EAAa"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { a as ApplicationError } from "./container-storage-GpNNz79X.mjs";
|
|
2
|
+
import { n as getMetadata, t as defineMetadata } from "./metadata-BVkc4aUu.mjs";
|
|
3
|
+
import "./errors-BBZTnjdq.mjs";
|
|
4
|
+
import { a as RouterContext, u as ROUTE_METADATA_KEYS } from "./exception-context-B4kM-M53.mjs";
|
|
5
|
+
import { t as Controller } from "./controller.decorator-DIUazNU7.mjs";
|
|
3
6
|
//#region src/websocket/decorators/gateway.decorator.ts
|
|
4
7
|
const GATEWAY_MARKER_KEY = ROUTE_METADATA_KEYS.GATEWAY_MARKER;
|
|
5
8
|
/**
|
|
@@ -33,7 +36,7 @@ const GATEWAY_MARKER_KEY = ROUTE_METADATA_KEYS.GATEWAY_MARKER;
|
|
|
33
36
|
function Gateway(route, options) {
|
|
34
37
|
return function(target) {
|
|
35
38
|
Controller(route, options)(target);
|
|
36
|
-
|
|
39
|
+
defineMetadata(GATEWAY_MARKER_KEY, true, target);
|
|
37
40
|
return target;
|
|
38
41
|
};
|
|
39
42
|
}
|
|
@@ -44,19 +47,11 @@ function Gateway(route, options) {
|
|
|
44
47
|
* @returns true if the class is decorated with @Gateway
|
|
45
48
|
*/
|
|
46
49
|
function isGateway(target) {
|
|
47
|
-
|
|
48
|
-
return Reflect.getMetadata(GATEWAY_MARKER_KEY, metadataTarget) === true;
|
|
50
|
+
return getMetadata(GATEWAY_MARKER_KEY, typeof target === "function" ? target : target.constructor) === true;
|
|
49
51
|
}
|
|
50
52
|
//#endregion
|
|
51
|
-
//#region src/websocket/
|
|
52
|
-
var
|
|
53
|
-
constructor(decorator, existingMethod) {
|
|
54
|
-
super("errors.websocketDuplicateEventHandler", ERROR_CODES.SYSTEM.WEBSOCKET_DUPLICATE_EVENT_HANDLER, {
|
|
55
|
-
decorator,
|
|
56
|
-
existingMethod
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
};
|
|
53
|
+
//#region src/websocket/websocket.error.ts
|
|
54
|
+
var WebSocketError = class extends ApplicationError {};
|
|
60
55
|
//#endregion
|
|
61
56
|
//#region src/websocket/decorators/ws-event.decorator.ts
|
|
62
57
|
const WS_ON_MESSAGE_KEY = ROUTE_METADATA_KEYS.WS_ON_MESSAGE;
|
|
@@ -67,9 +62,9 @@ const WS_ON_ERROR_KEY = ROUTE_METADATA_KEYS.WS_ON_ERROR;
|
|
|
67
62
|
* Throws if a different method already owns this key (prevents silent override).
|
|
68
63
|
*/
|
|
69
64
|
function defineSingleHandlerMetadata(key, propertyKey, target, decoratorName) {
|
|
70
|
-
const existing =
|
|
71
|
-
if (existing !== void 0 && existing !== propertyKey) throw new
|
|
72
|
-
|
|
65
|
+
const existing = getMetadata(key, target);
|
|
66
|
+
if (existing !== void 0 && existing !== propertyKey) throw new WebSocketError(`Duplicate @${decoratorName} handler: method "${String(existing)}" is already registered`);
|
|
67
|
+
defineMetadata(key, propertyKey, target);
|
|
73
68
|
}
|
|
74
69
|
/**
|
|
75
70
|
* Marks a method as the WebSocket message handler
|
|
@@ -132,28 +127,21 @@ function OnError() {
|
|
|
132
127
|
* Get the method name decorated with @OnMessage
|
|
133
128
|
*/
|
|
134
129
|
function getWsOnMessageMethod(target) {
|
|
135
|
-
return
|
|
130
|
+
return getMetadata(WS_ON_MESSAGE_KEY, target.prototype);
|
|
136
131
|
}
|
|
137
132
|
/**
|
|
138
133
|
* Get the method name decorated with @OnClose
|
|
139
134
|
*/
|
|
140
135
|
function getWsOnCloseMethod(target) {
|
|
141
|
-
return
|
|
136
|
+
return getMetadata(WS_ON_CLOSE_KEY, target.prototype);
|
|
142
137
|
}
|
|
143
138
|
/**
|
|
144
139
|
* Get the method name decorated with @OnError
|
|
145
140
|
*/
|
|
146
141
|
function getWsOnErrorMethod(target) {
|
|
147
|
-
return
|
|
142
|
+
return getMetadata(WS_ON_ERROR_KEY, target.prototype);
|
|
148
143
|
}
|
|
149
144
|
//#endregion
|
|
150
|
-
//#region src/websocket/errors/websocket-body-not-available.error.ts
|
|
151
|
-
var WebSocketBodyNotAvailableError = class extends ApplicationError {
|
|
152
|
-
constructor() {
|
|
153
|
-
super("errors.websocketBodyNotAvailable", ERROR_CODES.SYSTEM.WEBSOCKET_BODY_NOT_AVAILABLE);
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
//#endregion
|
|
157
145
|
//#region src/websocket/gateway-context.ts
|
|
158
146
|
/**
|
|
159
147
|
* WebSocket gateway context
|
|
@@ -173,6 +161,7 @@ var WebSocketBodyNotAvailableError = class extends ApplicationError {
|
|
|
173
161
|
* ```
|
|
174
162
|
*/
|
|
175
163
|
var GatewayContext = class extends RouterContext {
|
|
164
|
+
ws;
|
|
176
165
|
constructor(c, ws) {
|
|
177
166
|
super(c);
|
|
178
167
|
this.ws = ws;
|
|
@@ -205,13 +194,13 @@ var GatewayContext = class extends RouterContext {
|
|
|
205
194
|
/**
|
|
206
195
|
* Request body is not available in WebSocket gateways
|
|
207
196
|
*
|
|
208
|
-
* @throws
|
|
197
|
+
* @throws WebSocketError always — WebSocket upgrade requests do not have a body
|
|
209
198
|
*/
|
|
210
199
|
body() {
|
|
211
|
-
throw new
|
|
200
|
+
throw new WebSocketError("Request body is not available in WebSocket gateways");
|
|
212
201
|
}
|
|
213
202
|
};
|
|
214
203
|
//#endregion
|
|
215
|
-
export {
|
|
204
|
+
export { getWsOnCloseMethod as a, WebSocketError as c, OnMessage as i, Gateway as l, OnClose as n, getWsOnErrorMethod as o, OnError as r, getWsOnMessageMethod as s, GatewayContext as t, isGateway as u };
|
|
216
205
|
|
|
217
|
-
//# sourceMappingURL=gateway-context-
|
|
206
|
+
//# sourceMappingURL=gateway-context-CFe6a9gz.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-context-CFe6a9gz.mjs","names":[],"sources":["../src/websocket/decorators/gateway.decorator.ts","../src/websocket/websocket.error.ts","../src/websocket/decorators/ws-event.decorator.ts","../src/websocket/gateway-context.ts"],"sourcesContent":["import { defineMetadata, getMetadata } from '../../di/metadata'\nimport { ROUTE_METADATA_KEYS } from '../../router/constants'\nimport { Controller } from '../../router/decorators/controller.decorator'\nimport { type Constructor } from '../../types'\nimport type { GatewayOptions } from '../../websocket/types'\n\nconst GATEWAY_MARKER_KEY = ROUTE_METADATA_KEYS.GATEWAY_MARKER\n\n/**\n * Gateway decorator for WebSocket route registration\n *\n * Marks a class as a WebSocket gateway and stores route metadata.\n * Reuses the same metadata key as @Controller for middleware compatibility —\n * `getControllerRoute()`, `forRoutes()`, and the entire middleware system work\n * with zero changes.\n *\n * @param route - WebSocket route path (e.g., '/ws/chat')\n *\n * @example\n * ```typescript\n * import { type GatewayContext, Gateway, OnMessage, OnClose } from 'stratal/websocket'\n *\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnMessage()\n * handleMessage(evt: MessageEvent, ctx: GatewayContext) {\n * ctx.send('ack')\n * }\n *\n * @OnClose()\n * handleClose(evt: CloseEvent, ctx: GatewayContext) {\n * console.log('closed')\n * }\n * }\n * ```\n */\nexport function Gateway(route: string, options?: GatewayOptions) {\n return function <T extends Constructor>(target: T) {\n Controller(route, options)(target)\n defineMetadata(GATEWAY_MARKER_KEY, true, target)\n return target\n }\n}\n\n/**\n * Check if a class is a WebSocket gateway\n *\n * @param target - Class constructor or instance\n * @returns true if the class is decorated with @Gateway\n */\nexport function isGateway(target: object): boolean {\n const metadataTarget = typeof target === 'function' ? target : (target as { constructor: object }).constructor\n return getMetadata(GATEWAY_MARKER_KEY, metadataTarget) === true\n}\n","import { ApplicationError } from '../errors'\n\nexport class WebSocketError extends ApplicationError {}\n","import { defineMetadata, getMetadata } from '../../di/metadata'\nimport { ROUTE_METADATA_KEYS } from '../../router/constants'\nimport type { Constructor } from '../../types'\nimport { WebSocketError } from '../websocket.error'\n\nconst WS_ON_MESSAGE_KEY = ROUTE_METADATA_KEYS.WS_ON_MESSAGE\nconst WS_ON_CLOSE_KEY = ROUTE_METADATA_KEYS.WS_ON_CLOSE\nconst WS_ON_ERROR_KEY = ROUTE_METADATA_KEYS.WS_ON_ERROR\n\n/**\n * Define a single-handler metadata key on the prototype.\n * Throws if a different method already owns this key (prevents silent override).\n */\nfunction defineSingleHandlerMetadata(key: symbol, propertyKey: string | symbol, target: object, decoratorName: string): void {\n const existing = getMetadata<string | symbol>(key, target)\n if (existing !== undefined && existing !== propertyKey) {\n throw new WebSocketError(`Duplicate @${decoratorName} handler: method \"${String(existing)}\" is already registered`)\n }\n defineMetadata(key, propertyKey, target)\n}\n\n/**\n * Marks a method as the WebSocket message handler\n *\n * @example\n * ```typescript\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnMessage()\n * handleMessage(evt: MessageEvent, ctx: GatewayContext) {\n * ctx.send(evt.data)\n * }\n * }\n * ```\n */\nexport function OnMessage(): MethodDecorator {\n // `_target` is the class prototype (method decorator convention).\n // The getter functions below read from `target.prototype` symmetrically.\n return (_target: object, propertyKey: string | symbol) => {\n defineSingleHandlerMetadata(WS_ON_MESSAGE_KEY, propertyKey, _target, 'OnMessage')\n }\n}\n\n/**\n * Marks a method as the WebSocket close handler\n *\n * @example\n * ```typescript\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnClose()\n * handleClose(evt: CloseEvent, ctx: GatewayContext) {\n * console.log('closed')\n * }\n * }\n * ```\n */\nexport function OnClose(): MethodDecorator {\n return (_target: object, propertyKey: string | symbol) => {\n defineSingleHandlerMetadata(WS_ON_CLOSE_KEY, propertyKey, _target, 'OnClose')\n }\n}\n\n/**\n * Marks a method as the WebSocket error handler\n *\n * @example\n * ```typescript\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnError()\n * handleError(evt: Event, ctx: GatewayContext) {\n * console.error('WebSocket error', evt)\n * }\n * }\n * ```\n */\nexport function OnError(): MethodDecorator {\n return (_target: object, propertyKey: string | symbol) => {\n defineSingleHandlerMetadata(WS_ON_ERROR_KEY, propertyKey, _target, 'OnError')\n }\n}\n\n/**\n * Get the method name decorated with @OnMessage\n */\nexport function getWsOnMessageMethod(target: Constructor): string | undefined {\n return getMetadata<string>(WS_ON_MESSAGE_KEY, target.prototype as object)\n}\n\n/**\n * Get the method name decorated with @OnClose\n */\nexport function getWsOnCloseMethod(target: Constructor): string | undefined {\n return getMetadata<string>(WS_ON_CLOSE_KEY, target.prototype as object)\n}\n\n/**\n * Get the method name decorated with @OnError\n */\nexport function getWsOnErrorMethod(target: Constructor): string | undefined {\n return getMetadata<string>(WS_ON_ERROR_KEY, target.prototype as object)\n}\n","import type { Context } from 'hono'\nimport type { WSContext, WSReadyState } from 'hono/ws'\nimport type { ContextQueryResult } from '../router/router-context'\nimport { RouterContext } from '../router/router-context'\nimport type { RouterEnv } from '../router/types'\nimport { WebSocketError } from './websocket.error'\n\n/**\n * WebSocket gateway context\n *\n * Extends RouterContext with WebSocket-specific methods.\n * Inherits `getContainer()`, `param()`, `query()`, `header()`, `getLocale()`\n * from RouterContext. HTTP response methods (`json()`, `redirect()`, etc.) are\n * inherited but harmless post-upgrade.\n *\n * @example\n * ```typescript\n * @OnMessage()\n * handleMessage(evt: MessageEvent, ctx: GatewayContext) {\n * ctx.send('ack') // convenience method\n * ctx.header('Authorization') // upgrade request headers\n * }\n * ```\n */\nexport class GatewayContext extends RouterContext {\n constructor(c: Context<RouterEnv>, public readonly ws: WSContext) {\n super(c)\n }\n\n /** Send data through the WebSocket connection */\n send(data: string | ArrayBuffer | Uint8Array<ArrayBuffer>): void {\n this.ws.send(data)\n }\n\n /** Close the WebSocket connection */\n close(code?: number, reason?: string): void {\n this.ws.close(code, reason)\n }\n\n /** Current WebSocket ready state */\n get readyState(): WSReadyState {\n return this.ws.readyState\n }\n\n /**\n * Get route parameter value(s) from the raw request — WebSocket gateways are\n * not OpenAPI-registered, so reads come straight from Hono's matcher.\n *\n * - With a key → single string value.\n * - With no args → full `Record<string, string>` (or `{}` when none).\n *\n * @param key - Parameter name (e.g., 'id' for /ws/chat/:id)\n */\n override param(): Record<string, string>\n override param(key: string): string\n override param(key?: string): string | Record<string, string> {\n if (key === undefined) return this.c.req.param() ?? {}\n return this.c.req.param(key)!\n }\n\n /**\n * Get query parameter value from the raw request (no OpenAPI validation)\n *\n * @param key - Query parameter name\n */\n override query<R extends Record<string, unknown> | undefined = undefined, K extends string | undefined = undefined>(key?: K): ContextQueryResult<R, K> {\n if (key) {\n return this.c.req.query(key) as ContextQueryResult<R, K>\n }\n return this.c.req.query() as ContextQueryResult<R, K>\n }\n\n /**\n * Request body is not available in WebSocket gateways\n *\n * @throws WebSocketError always — WebSocket upgrade requests do not have a body\n */\n override body<T>(): Promise<T> {\n throw new WebSocketError('Request body is not available in WebSocket gateways')\n }\n}\n"],"mappings":";;;;;;AAMA,MAAM,qBAAqB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B/C,SAAgB,QAAQ,OAAe,SAA0B;CAC/D,OAAO,SAAiC,QAAW;EACjD,WAAW,OAAO,QAAQ,CAAC,OAAO;EAClC,eAAe,oBAAoB,MAAM,OAAO;EAChD,OAAO;;;;;;;;;AAUX,SAAgB,UAAU,QAAyB;CAEjD,OAAO,YAAY,oBADI,OAAO,WAAW,aAAa,SAAU,OAAmC,YAC7C,KAAK;;;;AClD7D,IAAa,iBAAb,cAAoC,iBAAiB;;;ACGrD,MAAM,oBAAoB,oBAAoB;AAC9C,MAAM,kBAAkB,oBAAoB;AAC5C,MAAM,kBAAkB,oBAAoB;;;;;AAM5C,SAAS,4BAA4B,KAAa,aAA8B,QAAgB,eAA6B;CAC3H,MAAM,WAAW,YAA6B,KAAK,OAAO;CAC1D,IAAI,aAAa,KAAA,KAAa,aAAa,aACzC,MAAM,IAAI,eAAe,cAAc,cAAc,oBAAoB,OAAO,SAAS,CAAC,yBAAyB;CAErH,eAAe,KAAK,aAAa,OAAO;;;;;;;;;;;;;;;;AAiB1C,SAAgB,YAA6B;CAG3C,QAAQ,SAAiB,gBAAiC;EACxD,4BAA4B,mBAAmB,aAAa,SAAS,YAAY;;;;;;;;;;;;;;;;;AAkBrF,SAAgB,UAA2B;CACzC,QAAQ,SAAiB,gBAAiC;EACxD,4BAA4B,iBAAiB,aAAa,SAAS,UAAU;;;;;;;;;;;;;;;;;AAkBjF,SAAgB,UAA2B;CACzC,QAAQ,SAAiB,gBAAiC;EACxD,4BAA4B,iBAAiB,aAAa,SAAS,UAAU;;;;;;AAOjF,SAAgB,qBAAqB,QAAyC;CAC5E,OAAO,YAAoB,mBAAmB,OAAO,UAAoB;;;;;AAM3E,SAAgB,mBAAmB,QAAyC;CAC1E,OAAO,YAAoB,iBAAiB,OAAO,UAAoB;;;;;AAMzE,SAAgB,mBAAmB,QAAyC;CAC1E,OAAO,YAAoB,iBAAiB,OAAO,UAAoB;;;;;;;;;;;;;;;;;;;;;AC7EzE,IAAa,iBAAb,cAAoC,cAAc;CACG;CAAnD,YAAY,GAAuB,IAA+B;EAChE,MAAM,EAAE;EADyC,KAAA,KAAA;;;CAKnD,KAAK,MAA4D;EAC/D,KAAK,GAAG,KAAK,KAAK;;;CAIpB,MAAM,MAAe,QAAuB;EAC1C,KAAK,GAAG,MAAM,MAAM,OAAO;;;CAI7B,IAAI,aAA2B;EAC7B,OAAO,KAAK,GAAG;;CAcjB,MAAe,KAA+C;EAC5D,IAAI,QAAQ,KAAA,GAAW,OAAO,KAAK,EAAE,IAAI,OAAO,IAAI,EAAE;EACtD,OAAO,KAAK,EAAE,IAAI,MAAM,IAAI;;;;;;;CAQ9B,MAAoH,KAAmC;EACrJ,IAAI,KACF,OAAO,KAAK,EAAE,IAAI,MAAM,IAAI;EAE9B,OAAO,KAAK,EAAE,IAAI,OAAO;;;;;;;CAQ3B,OAA+B;EAC7B,MAAM,IAAI,eAAe,sDAAsD"}
|
package/dist/guards/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { Y as Container, rt as RouterContext } from "../index-DEncMcC6.mjs";
|
|
2
|
+
import { r as LoggerService } from "../index-BtlE9RuO.mjs";
|
|
3
|
+
import { t as Constructor } from "../types-BaeHi67f.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/guards/types.d.ts
|
|
6
6
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/guards/types.ts","../../src/guards/use-guards.decorator.ts","../../src/guards/guard-execution.service.ts"],"mappings":";;;;;;;;AAqBA;;;;;;;;;;AAaA;;;;;UAbiB,WAAA;EAmBA;;;;AAKjB;;EAjBE,WAAA,CAAY,OAAA,EAAS,aAAA,aAA0B,OAAA;AAAA;;AAsCjD;;KAhCY,UAAA,GAAa,WAAA,CAAY,WAAA;;;AAuCrC;;KAjCY,KAAA,GAAQ,UAAA,GAAa,WAAA;;;;UAKhB,gBAAA;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/guards/types.ts","../../src/guards/use-guards.decorator.ts","../../src/guards/guard-execution.service.ts"],"mappings":";;;;;;;;AAqBA;;;;;;;;;;AAaA;;;;;UAbiB,WAAA;EAmBA;;;;AAKjB;;EAjBE,WAAA,CAAY,OAAA,EAAS,aAAA,aAA0B,OAAA;AAAA;;AAsCjD;;KAhCY,UAAA,GAAa,WAAA,CAAY,WAAA;;;AAuCrC;;KAjCY,KAAA,GAAQ,UAAA,GAAa,WAAA;;;;UAKhB,gBAAA;;ACajB;;;;;;;;;;;;;EDEE,WAAA;AAAA;;;;UAMe,aAAA;EACf,MAAA,EAAQ,KAAA;AAAA;;;;cAMG,kBAAA;;;;;;;AApDb;;;;;;;;;;AAaA;;;;;AAMA;;;;;AAKA;;;;;AAqBA;;;;;AAOA;;;;;;;;ACfA;;;;;;;;;;;;;iBAAgB,SAAA,CAAA,GAAa,MAAA,EAAQ,KAAA,KAAU,cAAA,GAAiB,eAAA;AAoBhE;;;;;AAWA;AAXA,iBAAgB,mBAAA,CAAoB,MAAA,WAAiB,aAAA;;;;;;;;iBAWrC,eAAA,CAAgB,MAAA,UAAgB,WAAA,oBAA+B,aAAA;;;;ADpE/E;;;;;cEVa,qBAAA;EAAA,iBACkB,MAAA;cAAA,MAAA,EAAQ,aAAA;EFgBiB;;AAMxD;;;;;AAMA;;EEjBQ,aAAA,CACJ,MAAA,EAAQ,KAAA,IACR,OAAA,EAAS,aAAA,EACT,SAAA,EAAW,SAAA,GACV,OAAA;EFae;;AAKpB;;;;;EALoB,QE2BV,YAAA;EFDoB;;;EAAA,QEcpB,eAAA;AAAA"}
|
package/dist/guards/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as GUARD_METADATA_KEY, i as getMethodGuards, n as UseGuards, r as getControllerGuards, t as GuardExecutionService } from "../guards-
|
|
1
|
+
import { a as GUARD_METADATA_KEY, i as getMethodGuards, n as UseGuards, r as getControllerGuards, t as GuardExecutionService } from "../guards-Ced-uNIF.mjs";
|
|
2
2
|
export { GUARD_METADATA_KEY, GuardExecutionService, UseGuards, getControllerGuards, getMethodGuards };
|