stratal 0.0.19 → 0.0.20
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/dist/{base-email.provider-mjynzewK.mjs → base-email.provider-CfQCA08m.mjs} +1 -1
- package/dist/{base-email.provider-mjynzewK.mjs.map → base-email.provider-CfQCA08m.mjs.map} +1 -1
- package/dist/bin/quarry.mjs +6 -0
- package/dist/bin/quarry.mjs.map +1 -1
- package/dist/cache/index.d.mts +2 -154
- package/dist/cache/index.d.mts.map +1 -1
- package/dist/cache/index.mjs +3 -5
- package/dist/cache/index.mjs.map +1 -1
- package/dist/cache.service-DsnKuNyO.d.mts +156 -0
- package/dist/cache.service-DsnKuNyO.d.mts.map +1 -0
- package/dist/cache.tokens-B7Rw1C9Q.mjs +6 -0
- package/dist/cache.tokens-B7Rw1C9Q.mjs.map +1 -0
- package/dist/{command-DsQq56Lp.d.mts → command-Bu-PjJrX.d.mts} +2 -2
- package/dist/{command-DsQq56Lp.d.mts.map → command-Bu-PjJrX.d.mts.map} +1 -1
- package/dist/config/index.d.mts +3 -3
- package/dist/config/index.mjs +2 -2
- package/dist/{consumer-registry-Doom7BEh.d.mts → consumer-registry-B7yUNh0q.d.mts} +1 -1
- package/dist/{consumer-registry-Doom7BEh.d.mts.map → consumer-registry-B7yUNh0q.d.mts.map} +1 -1
- package/dist/{controller.decorator-LZY9aHYG.mjs → controller.decorator-DQzenvSN.mjs} +2 -2
- package/dist/{controller.decorator-LZY9aHYG.mjs.map → controller.decorator-DQzenvSN.mjs.map} +1 -1
- package/dist/cron/index.d.mts +2 -2
- package/dist/cron/index.mjs +1 -1
- package/dist/{cron-manager-C30t9UZM.mjs → cron-manager-7Symz_TE.mjs} +2 -2
- package/dist/{cron-manager-C30t9UZM.mjs.map → cron-manager-7Symz_TE.mjs.map} +1 -1
- package/dist/{cron-manager-RuPtFVLy.d.mts → cron-manager-BEsH1mjW.d.mts} +3 -3
- package/dist/{cron-manager-RuPtFVLy.d.mts.map → cron-manager-BEsH1mjW.d.mts.map} +1 -1
- package/dist/di/index.d.mts +1 -1
- package/dist/di/index.mjs +1 -1
- package/dist/email/index.d.mts +3 -3
- package/dist/email/index.mjs +7 -7
- package/dist/{en-rHmW6vD9.mjs → en-DSH_bhh6.mjs} +7 -1
- package/dist/en-DSH_bhh6.mjs.map +1 -0
- package/dist/{env-CamWD-U1.d.mts → env-D1rcZ8_r.d.mts} +1 -1
- package/dist/env-D1rcZ8_r.d.mts.map +1 -0
- package/dist/errors/index.d.mts +1 -1
- package/dist/errors/index.mjs +1 -1
- package/dist/{errors-B4pYgYON.mjs → errors-BdyV5PnY.mjs} +20 -9
- package/dist/errors-BdyV5PnY.mjs.map +1 -0
- package/dist/{errors-BUyUfr2Z.mjs → errors-Da3Pz2X7.mjs} +2 -2
- package/dist/{errors-BUyUfr2Z.mjs.map → errors-Da3Pz2X7.mjs.map} +1 -1
- package/dist/events/index.d.mts +2 -2
- package/dist/{gateway-context-cqZ8wMoi.mjs → gateway-context-CdJjpUCW.mjs} +4 -8
- package/dist/{gateway-context-cqZ8wMoi.mjs.map → gateway-context-CdJjpUCW.mjs.map} +1 -1
- package/dist/guards/index.d.mts +3 -3
- package/dist/guards/index.mjs +1 -1
- package/dist/{guards-DMbsAxSX.mjs → guards-DUk_Kzst.mjs} +1 -1
- package/dist/{guards-DMbsAxSX.mjs.map → guards-DUk_Kzst.mjs.map} +1 -1
- package/dist/{http-method.decorator-BT3ufnz8.mjs → http-method.decorator-DXwxAfb_.mjs} +3 -3
- package/dist/{http-method.decorator-BT3ufnz8.mjs.map → http-method.decorator-DXwxAfb_.mjs.map} +1 -1
- package/dist/i18n/index.d.mts +2 -2
- package/dist/i18n/index.mjs +2 -2
- package/dist/i18n/messages/en/index.d.mts +1 -1
- package/dist/i18n/messages/en/index.mjs +1 -1
- package/dist/i18n/utils/index.mjs +1 -1
- package/dist/i18n/validation/index.d.mts +2 -2
- package/dist/i18n/validation/index.mjs +2 -2
- package/dist/{i18n.module-CI_prYFD.mjs → i18n.module-BBlNNlcG.mjs} +191 -39
- package/dist/i18n.module-BBlNNlcG.mjs.map +1 -0
- package/dist/{index-SHx31sBJ.d.mts → index-7-hU3GTV.d.mts} +1 -1
- package/dist/{index-SHx31sBJ.d.mts.map → index-7-hU3GTV.d.mts.map} +1 -1
- package/dist/{index-B437eK7p.d.mts → index-Bnpfq6uk.d.mts} +58 -10
- package/dist/index-Bnpfq6uk.d.mts.map +1 -0
- package/dist/{index-DFhEeFfC.d.mts → index-C1KvMncZ.d.mts} +7 -1
- package/dist/{index-DFhEeFfC.d.mts.map → index-C1KvMncZ.d.mts.map} +1 -1
- package/dist/{index-Dnqm9ZB6.d.mts → index-CjaQ6_tZ.d.mts} +5 -5
- package/dist/{index-Dnqm9ZB6.d.mts.map → index-CjaQ6_tZ.d.mts.map} +1 -1
- package/dist/{index-DPFqRs8L.d.mts → index-D0US0X14.d.mts} +313 -204
- package/dist/index-D0US0X14.d.mts.map +1 -0
- package/dist/{index-CWRS7Ri3.d.mts → index-DBd_2wv8.d.mts} +1 -1
- package/dist/{index-CWRS7Ri3.d.mts.map → index-DBd_2wv8.d.mts.map} +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/logger/index.d.mts +1 -1
- package/dist/macroable/index.d.mts +1 -1
- package/dist/module/index.d.mts +2 -2
- package/dist/module/index.mjs +1 -1
- package/dist/{module-qGE_1duv.mjs → module-Dk2qTa77.mjs} +132 -4
- package/dist/module-Dk2qTa77.mjs.map +1 -0
- package/dist/openapi/index.d.mts +3 -3
- package/dist/openapi/index.mjs +2 -2
- package/dist/{openapi-tools.service-CYWGuhue.mjs → openapi-tools.service-Zs-Ewv7F.mjs} +1 -1
- package/dist/{openapi-tools.service-CYWGuhue.mjs.map → openapi-tools.service-Zs-Ewv7F.mjs.map} +1 -1
- package/dist/{openapi.service-Bv_NioM9.d.mts → openapi.service-BLgvn3hJ.d.mts} +3 -3
- package/dist/{openapi.service-Bv_NioM9.d.mts.map → openapi.service-BLgvn3hJ.d.mts.map} +1 -1
- package/dist/quarry/index.d.mts +6 -6
- package/dist/quarry/index.mjs +2 -2
- package/dist/{quarry-registry-DFfRRkA7.mjs → quarry-registry-DNEej-Db.mjs} +5 -5
- package/dist/{quarry-registry-DFfRRkA7.mjs.map → quarry-registry-DNEej-Db.mjs.map} +1 -1
- package/dist/queue/index.d.mts +2 -2
- package/dist/queue/index.mjs +1 -1
- package/dist/{queue.module-P-G-nCYz.mjs → queue.module-BCdCiySt.mjs} +3 -3
- package/dist/{queue.module-P-G-nCYz.mjs.map → queue.module-BCdCiySt.mjs.map} +1 -1
- package/dist/{r2-storage.provider-LdzK9tfG.mjs → r2-storage.provider-Co6F0ZYV.mjs} +3 -3
- package/dist/{r2-storage.provider-LdzK9tfG.mjs.map → r2-storage.provider-Co6F0ZYV.mjs.map} +1 -1
- package/dist/rate-limit.decorator--o6Q6p9w.mjs +55 -0
- package/dist/rate-limit.decorator--o6Q6p9w.mjs.map +1 -0
- package/dist/rate-limiter/index.d.mts +420 -0
- package/dist/rate-limiter/index.d.mts.map +1 -0
- package/dist/rate-limiter/index.mjs +365 -0
- package/dist/rate-limiter/index.mjs.map +1 -0
- package/dist/{resend.provider-bwILp0WI.mjs → resend.provider-M6qRLrcy.mjs} +2 -2
- package/dist/{resend.provider-bwILp0WI.mjs.map → resend.provider-M6qRLrcy.mjs.map} +1 -1
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.mjs +6 -6
- package/dist/seeder/index.d.mts +3 -3
- package/dist/seeder/index.mjs +1 -1
- package/dist/{seeder-BcqIFa2X.mjs → seeder-CJAOHEIo.mjs} +2 -2
- package/dist/{seeder-BcqIFa2X.mjs.map → seeder-CJAOHEIo.mjs.map} +1 -1
- package/dist/{setup-CtekcwuO.mjs → setup-CefZKV_e.mjs} +1 -1
- package/dist/{setup-CtekcwuO.mjs.map → setup-CefZKV_e.mjs.map} +1 -1
- package/dist/{signed-url-COX7cCWR.mjs → signed-url-BQPbv2In.mjs} +1 -1
- package/dist/{signed-url-COX7cCWR.mjs.map → signed-url-BQPbv2In.mjs.map} +1 -1
- package/dist/{smtp.provider-B07yuARi.mjs → smtp.provider-w0Ve52Xg.mjs} +2 -2
- package/dist/{smtp.provider-B07yuARi.mjs.map → smtp.provider-w0Ve52Xg.mjs.map} +1 -1
- package/dist/storage/index.d.mts +3 -3
- package/dist/storage/index.mjs +2 -2
- package/dist/storage/providers/index.d.mts +2 -2
- package/dist/storage/providers/index.mjs +1 -1
- package/dist/{storage-P6X4h9So.mjs → storage-1zw-6Yiz.mjs} +8 -8
- package/dist/{storage-P6X4h9So.mjs.map → storage-1zw-6Yiz.mjs.map} +1 -1
- package/dist/{storage-provider.interface-CC1nniHk.d.mts → storage-provider.interface-Bd6vA4ak.d.mts} +2 -2
- package/dist/{storage-provider.interface-CC1nniHk.d.mts.map → storage-provider.interface-Bd6vA4ak.d.mts.map} +1 -1
- package/dist/{stratal-BCiwCFN9.mjs → stratal-DeEcGgdq.mjs} +8 -8
- package/dist/stratal-DeEcGgdq.mjs.map +1 -0
- package/dist/{types-DIWemRad.d.mts → types-cySNS_lp.d.mts} +1 -1
- package/dist/types-cySNS_lp.d.mts.map +1 -0
- package/dist/{usage-generator-MBcRo0Q2.mjs → usage-generator-BUdlhnCK.mjs} +1 -1
- package/dist/{usage-generator-MBcRo0Q2.mjs.map → usage-generator-BUdlhnCK.mjs.map} +1 -1
- package/dist/{validation-Dbg3ehdP.mjs → validation-DtJwAv7O.mjs} +62 -8
- package/dist/validation-DtJwAv7O.mjs.map +1 -0
- package/dist/websocket/index.d.mts +8 -3
- package/dist/websocket/index.d.mts.map +1 -1
- package/dist/websocket/index.mjs +1 -1
- package/dist/workers/index.d.mts +2 -2
- package/dist/workers/index.mjs +1 -1
- package/package.json +10 -6
- package/dist/en-rHmW6vD9.mjs.map +0 -1
- package/dist/env-CamWD-U1.d.mts.map +0 -1
- package/dist/errors-B4pYgYON.mjs.map +0 -1
- package/dist/i18n.module-CI_prYFD.mjs.map +0 -1
- package/dist/index-B437eK7p.d.mts.map +0 -1
- package/dist/index-DPFqRs8L.d.mts.map +0 -1
- package/dist/module-qGE_1duv.mjs.map +0 -1
- package/dist/stratal-BCiwCFN9.mjs.map +0 -1
- package/dist/types-DIWemRad.d.mts.map +0 -1
- package/dist/validation-Dbg3ehdP.mjs.map +0 -1
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { A as Scope, D as runWithContainer, E as getContainer, H as ApplicationError, V as ROUTER_TOKENS, a as createHttpExceptionContext, c as DEFAULT_CONTENT_TYPE, d as ROUTER_CONTEXT_KEYS, f as ROUTE_METADATA_KEYS, k as ERROR_CODES, l as HTTP_METHODS, m as VERSION_NEUTRAL, p as SECURITY_SCHEMES, s as RouterContext, u as METHOD_STATUS_CODES, w as I18N_TOKENS } from "./errors-
|
|
1
|
+
import { A as Scope, D as runWithContainer, E as getContainer, H as ApplicationError, V as ROUTER_TOKENS, a as createHttpExceptionContext, c as DEFAULT_CONTENT_TYPE, d as ROUTER_CONTEXT_KEYS, f as ROUTE_METADATA_KEYS, k as ERROR_CODES, l as HTTP_METHODS, m as VERSION_NEUTRAL, p as SECURITY_SCHEMES, s as RouterContext, u as METHOD_STATUS_CODES, w as I18N_TOKENS } from "./errors-BdyV5PnY.mjs";
|
|
2
2
|
import { a as __decorate, d as CONTAINER_TOKEN, f as DI_TOKENS, g as getMethodInjections, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "./logger-V6Ms3QnQ.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { n as OPENAPI_TOKENS } from "./openapi-tools.service-
|
|
6
|
-
import { t as en_exports } from "./en-
|
|
7
|
-
import { i as getMethodGuards, r as getControllerGuards, t as GuardExecutionService } from "./guards-
|
|
8
|
-
import { n as getControllerOptions, r as getControllerRoute } from "./controller.decorator-
|
|
9
|
-
import { c as getWsOnMessageMethod, d as isGateway, o as getWsOnCloseMethod, s as getWsOnErrorMethod, t as GatewayContext } from "./gateway-context-
|
|
10
|
-
import "./http-method.decorator-
|
|
11
|
-
import { n as
|
|
12
|
-
import { t as
|
|
3
|
+
import { S as createThrottleMiddleware, b as ControllerRegistrationError, c as InvalidSignatureError, d as MissingRouteParamError, f as ResponseValidationError, g as RouteNotFoundError, h as SchemaValidationError, k as Module, l as MiddlewareNextCalledMultipleTimesError, o as DomainMismatchError, p as RouteNameNotFoundError, s as DuplicateRouteNameError, u as MissingEnvironmentVariableError, v as OpenAPIRouteRegistrationError, x as ControllerMethodNotFoundError, y as HonoAppAlreadyConfiguredError } from "./module-Dk2qTa77.mjs";
|
|
4
|
+
import { c as backendErrorMap, i as z, l as runWithErrorMapContext, r as validation_exports, t as OpenAPIHono } from "./validation-DtJwAv7O.mjs";
|
|
5
|
+
import { n as OPENAPI_TOKENS } from "./openapi-tools.service-Zs-Ewv7F.mjs";
|
|
6
|
+
import { t as en_exports } from "./en-DSH_bhh6.mjs";
|
|
7
|
+
import { i as getMethodGuards, r as getControllerGuards, t as GuardExecutionService } from "./guards-DUk_Kzst.mjs";
|
|
8
|
+
import { n as getControllerOptions, r as getControllerRoute } from "./controller.decorator-DQzenvSN.mjs";
|
|
9
|
+
import { c as getWsOnMessageMethod, d as isGateway, o as getWsOnCloseMethod, s as getWsOnErrorMethod, t as GatewayContext } from "./gateway-context-CdJjpUCW.mjs";
|
|
10
|
+
import "./http-method.decorator-DXwxAfb_.mjs";
|
|
11
|
+
import { n as getRateLimits } from "./rate-limit.decorator--o6Q6p9w.mjs";
|
|
12
|
+
import { n as verifySignedUrl, t as signUrl } from "./signed-url-BQPbv2In.mjs";
|
|
13
|
+
import { t as setupI18nCompiler } from "./setup-CefZKV_e.mjs";
|
|
13
14
|
import { inject } from "tsyringe";
|
|
14
15
|
import { createCoreContext, translate } from "@intlify/core-base";
|
|
15
16
|
import { swaggerUI } from "@hono/swagger-ui";
|
|
@@ -730,6 +731,67 @@ function createMiddlewareChain(classes) {
|
|
|
730
731
|
};
|
|
731
732
|
}
|
|
732
733
|
//#endregion
|
|
734
|
+
//#region src/router/trailing-slash.ts
|
|
735
|
+
/**
|
|
736
|
+
* Apply a trailing-slash mode to a URL or path.
|
|
737
|
+
*
|
|
738
|
+
* - `'ignore'` — return as-is.
|
|
739
|
+
* - `'always'` — append `/` to the pathname unless it already has one.
|
|
740
|
+
* Skipped when the last segment contains `.` (file-like paths) and for the
|
|
741
|
+
* root `/` path.
|
|
742
|
+
* - `'never'` — strip a trailing `/` from the pathname. Skipped for root.
|
|
743
|
+
*
|
|
744
|
+
* Preserves query string and hash. Handles both relative paths
|
|
745
|
+
* (`/foo?x=1`) and absolute URLs (`https://host/foo?x=1`).
|
|
746
|
+
*
|
|
747
|
+
* Used by URL-generation helpers and the redirect middleware so canonical
|
|
748
|
+
* form is computed in one place.
|
|
749
|
+
*/
|
|
750
|
+
function applyTrailingSlash(url, mode) {
|
|
751
|
+
if (mode === "ignore") return url;
|
|
752
|
+
const isAbsolute = /^https?:\/\//i.test(url);
|
|
753
|
+
const parsed = isAbsolute ? new URL(url) : new URL(url, "http://placeholder.local");
|
|
754
|
+
const path = parsed.pathname;
|
|
755
|
+
if (path === "/") return url;
|
|
756
|
+
const hasTrailing = path.endsWith("/");
|
|
757
|
+
if (mode === "always" && !hasTrailing) {
|
|
758
|
+
if (path.slice(path.lastIndexOf("/") + 1).includes(".")) return url;
|
|
759
|
+
parsed.pathname = `${path}/`;
|
|
760
|
+
} else if (mode === "never" && hasTrailing) parsed.pathname = path.slice(0, -1);
|
|
761
|
+
else return url;
|
|
762
|
+
return isAbsolute ? parsed.toString() : `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
763
|
+
}
|
|
764
|
+
//#endregion
|
|
765
|
+
//#region src/router/middleware/trailing-slash-redirect.ts
|
|
766
|
+
const REDIRECT_STATUS = 308;
|
|
767
|
+
/**
|
|
768
|
+
* Create a Hono middleware that canonicalises trailing slashes via 308 redirects.
|
|
769
|
+
*
|
|
770
|
+
* - `'ignore'` — returns `null`; routes match both `/foo` and `/foo/` natively
|
|
771
|
+
* (Hono handles this when constructed with `strict: false`).
|
|
772
|
+
* - `'always'` — non-trailing requests redirect to the trailing-slash form.
|
|
773
|
+
* Paths whose last segment contains `.` (e.g. `/api/openapi.json`) are skipped.
|
|
774
|
+
* - `'never'` — trailing requests redirect to the non-trailing form.
|
|
775
|
+
*
|
|
776
|
+
* Root (`/`) is always passed through unchanged.
|
|
777
|
+
*
|
|
778
|
+
* 308 is used so that POST/PUT/PATCH bodies survive the redirect.
|
|
779
|
+
*
|
|
780
|
+
* Location headers are emitted as path-relative URIs so the user agent
|
|
781
|
+
* resolves them against the effective request URI — sidestepping scheme
|
|
782
|
+
* mismatches behind HTTPS-terminating proxies that proxy HTTPS pages to an
|
|
783
|
+
* HTTP-speaking backend (which would otherwise produce a mixed-content block).
|
|
784
|
+
*/
|
|
785
|
+
function createTrailingSlashRedirect(mode) {
|
|
786
|
+
if (mode === "ignore") return null;
|
|
787
|
+
return async (c, next) => {
|
|
788
|
+
const url = new URL(c.req.url);
|
|
789
|
+
const canonicalPath = applyTrailingSlash(url.pathname, mode);
|
|
790
|
+
if (canonicalPath === url.pathname) return next();
|
|
791
|
+
return c.redirect(`${canonicalPath}${url.search}`, REDIRECT_STATUS);
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
//#endregion
|
|
733
795
|
//#region src/router/decorators/route.decorator.ts
|
|
734
796
|
/**
|
|
735
797
|
* Decorator to add OpenAPI metadata to a controller method using convention-based routing.
|
|
@@ -1138,10 +1200,12 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1138
1200
|
const controllerOpts = getControllerOptions(ControllerClass);
|
|
1139
1201
|
const controllerGuards = getControllerGuards(ControllerClass)?.guards ?? [];
|
|
1140
1202
|
const routerConfig = this.routerResolver?.resolveForController(ControllerClass) ?? { middleware: [] };
|
|
1203
|
+
const classThrottleMiddleware = Array.from(new Set(getRateLimits(ControllerClass).map(createThrottleMiddleware)));
|
|
1141
1204
|
const basePath = routerConfig.prefix ? this.joinPaths(routerConfig.prefix, controllerRoute) : controllerRoute;
|
|
1142
1205
|
const effectiveVersion = controllerOpts?.version ?? routerConfig.version;
|
|
1143
1206
|
const effectiveDomain = controllerOpts?.domain ?? routerConfig.domain;
|
|
1144
1207
|
if (isWsGateway) {
|
|
1208
|
+
const wsMiddleware = [...routerConfig.middleware, ...classThrottleMiddleware];
|
|
1145
1209
|
const expandedRoutes = this.registry.register({
|
|
1146
1210
|
method: "ws",
|
|
1147
1211
|
basePath,
|
|
@@ -1150,10 +1214,10 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1150
1214
|
controller: ControllerClass.name,
|
|
1151
1215
|
action: "ws",
|
|
1152
1216
|
hidden: routerConfig.hideFromDocs ?? false,
|
|
1153
|
-
middleware:
|
|
1217
|
+
middleware: wsMiddleware.map((m) => m.name)
|
|
1154
1218
|
});
|
|
1155
1219
|
for (const route of expandedRoutes) actions.set(route, () => {
|
|
1156
|
-
if (
|
|
1220
|
+
if (wsMiddleware.length > 0) this.app.use(route.path, createMiddlewareChain(wsMiddleware));
|
|
1157
1221
|
if (effectiveDomain) {
|
|
1158
1222
|
const domainHandler = createDomainMiddleware(effectiveDomain);
|
|
1159
1223
|
this.app.use(route.path, domainHandler);
|
|
@@ -1167,6 +1231,7 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1167
1231
|
this.controllerClasses.set(className, ControllerClass);
|
|
1168
1232
|
const prototype = ControllerClass.prototype;
|
|
1169
1233
|
if (prototype.handle) {
|
|
1234
|
+
const wildcardMiddleware = [...routerConfig.middleware, ...classThrottleMiddleware];
|
|
1170
1235
|
const expandedRoutes = this.registry.register({
|
|
1171
1236
|
method: "all",
|
|
1172
1237
|
basePath,
|
|
@@ -1175,10 +1240,10 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1175
1240
|
controller: className,
|
|
1176
1241
|
action: "handle",
|
|
1177
1242
|
hidden: routerConfig.hideFromDocs ?? false,
|
|
1178
|
-
middleware:
|
|
1243
|
+
middleware: wildcardMiddleware.map((m) => m.name)
|
|
1179
1244
|
});
|
|
1180
1245
|
for (const route of expandedRoutes) actions.set(route, () => {
|
|
1181
|
-
if (
|
|
1246
|
+
if (wildcardMiddleware.length > 0) this.app.use(route.path, createMiddlewareChain(wildcardMiddleware));
|
|
1182
1247
|
this.registerWildcardRoute(ControllerClass, route.path);
|
|
1183
1248
|
});
|
|
1184
1249
|
return;
|
|
@@ -1204,12 +1269,26 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1204
1269
|
const routerName = routerConfig.name;
|
|
1205
1270
|
const controllerName = controllerOpts?.name;
|
|
1206
1271
|
const effectiveNamePrefix = routerName && controllerName ? `${routerName}${controllerName}` : routerName ?? controllerName;
|
|
1207
|
-
const middlewareNames = routerConfig.middleware.map((m) => m.name);
|
|
1208
1272
|
for (const { method: methodName, meta } of methodMetadata) {
|
|
1209
1273
|
const resolved = this.resolveMethodAndPath(meta, methodName, basePath, className);
|
|
1210
1274
|
if (!resolved) continue;
|
|
1211
|
-
const
|
|
1212
|
-
|
|
1275
|
+
const methodThrottleMiddleware = getRateLimits(prototype, methodName).map(createThrottleMiddleware);
|
|
1276
|
+
const effectiveMiddleware = Array.from(new Set([
|
|
1277
|
+
...routerConfig.middleware,
|
|
1278
|
+
...classThrottleMiddleware,
|
|
1279
|
+
...methodThrottleMiddleware
|
|
1280
|
+
]));
|
|
1281
|
+
const middlewareNames = effectiveMiddleware.map((m) => m.name);
|
|
1282
|
+
const { httpMethod, fullPath, routeConfig: rawRouteConfig, statusCodeOverride } = resolved;
|
|
1283
|
+
let mergedParams = rawRouteConfig.params;
|
|
1284
|
+
if (routerConfig.params) {
|
|
1285
|
+
const prefixShape = routerConfig.params.shape;
|
|
1286
|
+
mergedParams = mergedParams ? mergedParams.extend(prefixShape) : routerConfig.params.extend({});
|
|
1287
|
+
}
|
|
1288
|
+
const routeConfig = mergedParams === rawRouteConfig.params ? rawRouteConfig : {
|
|
1289
|
+
...rawRouteConfig,
|
|
1290
|
+
params: mergedParams
|
|
1291
|
+
};
|
|
1213
1292
|
const hideFromDocs = routeConfig.hideFromDocs ?? routerHidden ?? controllerHidden;
|
|
1214
1293
|
let routeName;
|
|
1215
1294
|
if (routeConfig.name) routeName = effectiveNamePrefix ? `${effectiveNamePrefix}${routeConfig.name}` : routeConfig.name;
|
|
@@ -1251,7 +1330,7 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1251
1330
|
path: route.path,
|
|
1252
1331
|
methodName
|
|
1253
1332
|
});
|
|
1254
|
-
if (
|
|
1333
|
+
if (effectiveMiddleware.length > 0) this.app.use(route.path, createMiddlewareChain(effectiveMiddleware));
|
|
1255
1334
|
if (allGuards.length > 0) this.app.use(route.path, this.createGuardMiddleware(allGuards));
|
|
1256
1335
|
this.app.all(route.path, handler);
|
|
1257
1336
|
return;
|
|
@@ -1266,7 +1345,7 @@ let RouteRegistrationService = class RouteRegistrationService {
|
|
|
1266
1345
|
tags: metadata.tags,
|
|
1267
1346
|
hidden: route.hidden
|
|
1268
1347
|
});
|
|
1269
|
-
const wrappedHandler = this.wrapHandlerWithChain(handler,
|
|
1348
|
+
const wrappedHandler = this.wrapHandlerWithChain(handler, effectiveMiddleware, allGuards);
|
|
1270
1349
|
this.app.openapi(openApiRoute, wrappedHandler);
|
|
1271
1350
|
if (!route.hidden) {
|
|
1272
1351
|
const { hide: _, ...specRoute } = openApiRoute;
|
|
@@ -1629,12 +1708,16 @@ let HonoApp = class HonoApp extends OpenAPIHono {
|
|
|
1629
1708
|
* Used by private methods to register middleware without going through the override.
|
|
1630
1709
|
*/
|
|
1631
1710
|
nativeUse;
|
|
1632
|
-
constructor(container, logger) {
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1711
|
+
constructor(container, logger, application) {
|
|
1712
|
+
const trailingSlash = application.config.trailingSlash ?? "ignore";
|
|
1713
|
+
super({
|
|
1714
|
+
strict: false,
|
|
1715
|
+
defaultHook: (result, c) => {
|
|
1716
|
+
if (!result.success) throw new SchemaValidationError(result.error);
|
|
1717
|
+
const override = c.get("validationSuccessResponse");
|
|
1718
|
+
if (override) return override;
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1638
1721
|
this._container = container;
|
|
1639
1722
|
this._logger = logger;
|
|
1640
1723
|
this.nativeUse = this.use;
|
|
@@ -1649,6 +1732,8 @@ let HonoApp = class HonoApp extends OpenAPIHono {
|
|
|
1649
1732
|
}
|
|
1650
1733
|
return this.nativeUse(...args);
|
|
1651
1734
|
});
|
|
1735
|
+
const trailingSlashRedirect = createTrailingSlashRedirect(trailingSlash);
|
|
1736
|
+
if (trailingSlashRedirect) this.nativeUse("*", trailingSlashRedirect);
|
|
1652
1737
|
this.setupRequestScope();
|
|
1653
1738
|
this.applyGlobalMiddleware();
|
|
1654
1739
|
}
|
|
@@ -1691,7 +1776,12 @@ HonoApp = __decorate([
|
|
|
1691
1776
|
Transient(),
|
|
1692
1777
|
__decorateParam(0, inject(CONTAINER_TOKEN)),
|
|
1693
1778
|
__decorateParam(1, inject(LOGGER_TOKENS.LoggerService)),
|
|
1694
|
-
|
|
1779
|
+
__decorateParam(2, inject(DI_TOKENS.Application)),
|
|
1780
|
+
__decorateMetadata("design:paramtypes", [
|
|
1781
|
+
Object,
|
|
1782
|
+
Object,
|
|
1783
|
+
Object
|
|
1784
|
+
])
|
|
1695
1785
|
], HonoApp);
|
|
1696
1786
|
//#endregion
|
|
1697
1787
|
//#region src/router/services/locale-path.service.ts
|
|
@@ -1840,10 +1930,21 @@ VersioningService = __decorate([
|
|
|
1840
1930
|
], VersioningService);
|
|
1841
1931
|
//#endregion
|
|
1842
1932
|
//#region src/router/route-registry.ts
|
|
1933
|
+
const CONCRETE_HTTP_METHODS = [
|
|
1934
|
+
"get",
|
|
1935
|
+
"post",
|
|
1936
|
+
"put",
|
|
1937
|
+
"delete",
|
|
1938
|
+
"patch",
|
|
1939
|
+
"head",
|
|
1940
|
+
"options",
|
|
1941
|
+
"trace"
|
|
1942
|
+
];
|
|
1843
1943
|
let RouteRegistry = class RouteRegistry {
|
|
1844
1944
|
routes = [];
|
|
1845
1945
|
namedRoutes = /* @__PURE__ */ new Map();
|
|
1846
1946
|
_sortedCache = null;
|
|
1947
|
+
_routeToNameCache = null;
|
|
1847
1948
|
constructor(versioningService, localePathService) {
|
|
1848
1949
|
this.versioningService = versioningService;
|
|
1849
1950
|
this.localePathService = localePathService;
|
|
@@ -1894,6 +1995,7 @@ let RouteRegistry = class RouteRegistry {
|
|
|
1894
1995
|
}
|
|
1895
1996
|
}
|
|
1896
1997
|
this._sortedCache = null;
|
|
1998
|
+
this._routeToNameCache = null;
|
|
1897
1999
|
return expandedRoutes;
|
|
1898
2000
|
}
|
|
1899
2001
|
/** Get a named route by name */
|
|
@@ -1904,6 +2006,25 @@ let RouteRegistry = class RouteRegistry {
|
|
|
1904
2006
|
has(name) {
|
|
1905
2007
|
return this.namedRoutes.has(name);
|
|
1906
2008
|
}
|
|
2009
|
+
/**
|
|
2010
|
+
* Resolve a Hono-style route path pattern (e.g. as exposed by `c.req.routePath`)
|
|
2011
|
+
* back to its registered name, scoped to the request's HTTP method. Locale variant
|
|
2012
|
+
* paths resolve to the canonical primary route name. Method matching is
|
|
2013
|
+
* case-insensitive; routes registered with `'all'` resolve under any verb.
|
|
2014
|
+
*/
|
|
2015
|
+
findNameByRoute(method, path) {
|
|
2016
|
+
this._routeToNameCache ??= this.buildRouteToNameCache();
|
|
2017
|
+
return this._routeToNameCache.get(`${method.toLowerCase()}:${path}`);
|
|
2018
|
+
}
|
|
2019
|
+
buildRouteToNameCache() {
|
|
2020
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2021
|
+
for (const route of this.namedRoutes.values()) {
|
|
2022
|
+
const methods = route.method === "all" ? CONCRETE_HTTP_METHODS : [route.method];
|
|
2023
|
+
const paths = route.localePaths ? [route.path, ...route.localePaths] : [route.path];
|
|
2024
|
+
for (const m of methods) for (const p of paths) cache.set(`${m}:${p}`, route.name);
|
|
2025
|
+
}
|
|
2026
|
+
return cache;
|
|
2027
|
+
}
|
|
1907
2028
|
/** Get all routes sorted by specificity (static > param > wildcard, primary before locale) */
|
|
1908
2029
|
all() {
|
|
1909
2030
|
this._sortedCache ??= sortRoutesBySpecificity(this.routes);
|
|
@@ -1923,6 +2044,17 @@ RouteRegistry = __decorate([
|
|
|
1923
2044
|
//#endregion
|
|
1924
2045
|
//#region src/router/uri.ts
|
|
1925
2046
|
/**
|
|
2047
|
+
* Encode a value for use as a path parameter.
|
|
2048
|
+
*
|
|
2049
|
+
* Splits on `/` and encodes each segment with `encodeURIComponent`, so callers
|
|
2050
|
+
* can pass slash-containing values for catch-all params (e.g. `:slug{.+}`) and
|
|
2051
|
+
* still get a usable URL — `'auth/login'` becomes `'auth/login'`, not
|
|
2052
|
+
* `'auth%2Flogin'`. Single segments behave exactly like `encodeURIComponent`.
|
|
2053
|
+
*/
|
|
2054
|
+
function encodePathParam(value) {
|
|
2055
|
+
return value.split("/").map(encodeURIComponent).join("/");
|
|
2056
|
+
}
|
|
2057
|
+
/**
|
|
1926
2058
|
* Build a URL from a registered route, filling path/domain params and appending extras as query string.
|
|
1927
2059
|
*
|
|
1928
2060
|
* Pure function — no request context needed. Used by both the `Uri` class and the standalone `route()` function.
|
|
@@ -1945,7 +2077,7 @@ function buildRouteUrl(route, name, params) {
|
|
|
1945
2077
|
for (const paramName of route.paramNames) {
|
|
1946
2078
|
const value = allParams[paramName];
|
|
1947
2079
|
if (value === void 0) throw new MissingRouteParamError(paramName, name, route.path);
|
|
1948
|
-
url = url.replace(new RegExp(`:${paramName}(\\{[^}]*\\})?`),
|
|
2080
|
+
url = url.replace(new RegExp(`:${paramName}(\\{[^}]*\\})?`), encodePathParam(value));
|
|
1949
2081
|
consumedKeys.add(paramName);
|
|
1950
2082
|
}
|
|
1951
2083
|
let domain;
|
|
@@ -1968,9 +2100,11 @@ function buildRouteUrl(route, name, params) {
|
|
|
1968
2100
|
}
|
|
1969
2101
|
let Uri = class Uri {
|
|
1970
2102
|
_defaults = {};
|
|
1971
|
-
|
|
2103
|
+
trailingSlash;
|
|
2104
|
+
constructor(registry, routerContext, application) {
|
|
1972
2105
|
this.registry = registry;
|
|
1973
2106
|
this.routerContext = routerContext;
|
|
2107
|
+
this.trailingSlash = application.config.trailingSlash ?? "ignore";
|
|
1974
2108
|
}
|
|
1975
2109
|
/**
|
|
1976
2110
|
* Set default URL parameters for this request.
|
|
@@ -1985,6 +2119,16 @@ let Uri = class Uri {
|
|
|
1985
2119
|
};
|
|
1986
2120
|
}
|
|
1987
2121
|
/**
|
|
2122
|
+
* Read the currently configured default URL parameters.
|
|
2123
|
+
*
|
|
2124
|
+
* Used by frameworks that need to share these with the client (e.g. the
|
|
2125
|
+
* Inertia adapter ships them as a shared prop so `route()` calls in the
|
|
2126
|
+
* browser auto-fill the same sticky params as the server).
|
|
2127
|
+
*/
|
|
2128
|
+
getDefaults() {
|
|
2129
|
+
return { ...this._defaults };
|
|
2130
|
+
}
|
|
2131
|
+
/**
|
|
1988
2132
|
* Generate a URL from a named route.
|
|
1989
2133
|
*
|
|
1990
2134
|
* Keys matching `:param` placeholders fill the path.
|
|
@@ -2003,10 +2147,10 @@ let Uri = class Uri {
|
|
|
2003
2147
|
route(name, params, options) {
|
|
2004
2148
|
const registeredRoute = this.registry.get(name);
|
|
2005
2149
|
if (!registeredRoute) throw new RouteNameNotFoundError(name);
|
|
2006
|
-
let url = buildRouteUrl(registeredRoute, name, {
|
|
2150
|
+
let url = applyTrailingSlash(buildRouteUrl(registeredRoute, name, {
|
|
2007
2151
|
...this._defaults,
|
|
2008
2152
|
...params
|
|
2009
|
-
});
|
|
2153
|
+
}), this.trailingSlash);
|
|
2010
2154
|
if (options?.absolute && !url.startsWith("http")) url = `${new URL(this.routerContext.c.req.url).origin}${url}`;
|
|
2011
2155
|
return url;
|
|
2012
2156
|
}
|
|
@@ -2054,14 +2198,14 @@ let Uri = class Uri {
|
|
|
2054
2198
|
* Get the current request URL pathname (without query string).
|
|
2055
2199
|
*/
|
|
2056
2200
|
current() {
|
|
2057
|
-
return new URL(this.routerContext.c.req.url).pathname;
|
|
2201
|
+
return applyTrailingSlash(new URL(this.routerContext.c.req.url).pathname, this.trailingSlash);
|
|
2058
2202
|
}
|
|
2059
2203
|
/**
|
|
2060
2204
|
* Get the current request URL with query string (pathname + search).
|
|
2061
2205
|
*/
|
|
2062
2206
|
full() {
|
|
2063
2207
|
const parsed = new URL(this.routerContext.c.req.url);
|
|
2064
|
-
return `${parsed.pathname}${parsed.search}
|
|
2208
|
+
return applyTrailingSlash(`${parsed.pathname}${parsed.search}`, this.trailingSlash);
|
|
2065
2209
|
}
|
|
2066
2210
|
/**
|
|
2067
2211
|
* Get the previous request URL from the Referer header.
|
|
@@ -2093,7 +2237,7 @@ let Uri = class Uri {
|
|
|
2093
2237
|
* @param options - URL generation options
|
|
2094
2238
|
*/
|
|
2095
2239
|
to(path, queryParams, options) {
|
|
2096
|
-
let url = path;
|
|
2240
|
+
let url = applyTrailingSlash(path, this.trailingSlash);
|
|
2097
2241
|
if (queryParams) {
|
|
2098
2242
|
const entries = Object.entries(queryParams);
|
|
2099
2243
|
if (entries.length > 0) {
|
|
@@ -2113,7 +2257,7 @@ let Uri = class Uri {
|
|
|
2113
2257
|
query(path, queryParams) {
|
|
2114
2258
|
const parsed = new URL(path, "https://placeholder.local");
|
|
2115
2259
|
for (const [key, value] of Object.entries(queryParams)) parsed.searchParams.set(key, value);
|
|
2116
|
-
return `${parsed.pathname}${parsed.search}
|
|
2260
|
+
return applyTrailingSlash(`${parsed.pathname}${parsed.search}`, this.trailingSlash);
|
|
2117
2261
|
}
|
|
2118
2262
|
getAppSecret() {
|
|
2119
2263
|
const secret = this.routerContext.c.env.APP_SECRET;
|
|
@@ -2125,7 +2269,12 @@ Uri = __decorate([
|
|
|
2125
2269
|
Transient(),
|
|
2126
2270
|
__decorateParam(0, inject(ROUTER_TOKENS.RouteRegistry)),
|
|
2127
2271
|
__decorateParam(1, inject(ROUTER_TOKENS.RouterContext)),
|
|
2128
|
-
|
|
2272
|
+
__decorateParam(2, inject(DI_TOKENS.Application)),
|
|
2273
|
+
__decorateMetadata("design:paramtypes", [
|
|
2274
|
+
Object,
|
|
2275
|
+
Object,
|
|
2276
|
+
Object
|
|
2277
|
+
])
|
|
2129
2278
|
], Uri);
|
|
2130
2279
|
//#endregion
|
|
2131
2280
|
//#region src/router/route-url.ts
|
|
@@ -2155,9 +2304,12 @@ Uri = __decorate([
|
|
|
2155
2304
|
* ```
|
|
2156
2305
|
*/
|
|
2157
2306
|
function route(name, params) {
|
|
2158
|
-
const
|
|
2307
|
+
const container = getContainer();
|
|
2308
|
+
const registry = container.resolve(ROUTER_TOKENS.RouteRegistry);
|
|
2309
|
+
const application = container.resolve(DI_TOKENS.Application);
|
|
2310
|
+
const registeredRoute = registry.get(name);
|
|
2159
2311
|
if (!registeredRoute) throw new RouteNameNotFoundError(name);
|
|
2160
|
-
return buildRouteUrl(registeredRoute, name, params);
|
|
2312
|
+
return applyTrailingSlash(buildRouteUrl(registeredRoute, name, params), application.config.trailingSlash ?? "ignore");
|
|
2161
2313
|
}
|
|
2162
2314
|
//#endregion
|
|
2163
2315
|
//#region src/router/middleware/verify-signature.middleware.ts
|
|
@@ -2337,4 +2489,4 @@ I18nModule = _I18nModule = __decorate([Module({ providers: [
|
|
|
2337
2489
|
//#endregion
|
|
2338
2490
|
export { OpenAPIModule as A, LocaleNotSupportedError as B, validationErrorResponseSchema as C, createMiddlewareChain as D, getRouteMetadata as E, getMessages as F, I18nContextMiddleware as H, messages as I, buildDetectorOptions as L, MessageRegistry as M, MessageLoaderService as N, createDomainMiddleware as O, getLocales as P, resolveI18nOptions as R, uuidParamSchema as S, getRouteDecoratedMethods as T, OpenAPIConfigService as V, commonErrorSchemas as _, buildRouteUrl as a, paginationQuerySchema as b, LocalePathService as c, extractDomainParamNames as d, extractParamNames as f, toOpenAPIPath as g, sortRoutesBySpecificity as h, Uri as i, OpenAPIService as j, parseDomainPattern as k, HonoApp as l, getPathSpecificityScore as m, VerifySignatureMiddleware as n, RouteRegistry as o, generateConventionRouteName as p, route as r, VersioningService as s, I18nModule as t, RouteRegistrationService as u, errorResponseSchema as v, Route as w, successMessageSchema as x, paginatedResponseSchema as y, TranslationMissingError as z };
|
|
2339
2491
|
|
|
2340
|
-
//# sourceMappingURL=i18n.module-
|
|
2492
|
+
//# sourceMappingURL=i18n.module-BBlNNlcG.mjs.map
|