@suveren/gateway 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -72,6 +72,7 @@ __export(index_exports, {
72
72
  signApproval: () => signApproval,
73
73
  signMandateProjection: () => signMandateProjection,
74
74
  validateBoundsParams: () => validateBoundsParams,
75
+ validateBoundsRequiredFor: () => validateBoundsRequiredFor,
75
76
  validateContextParams: () => validateContextParams,
76
77
  validateFrameParams: () => validateFrameParams,
77
78
  validateSubject: () => validateSubject,
@@ -378,6 +379,38 @@ function validateContextParams(params, profile) {
378
379
  }
379
380
  return { valid: errors.length === 0, errors };
380
381
  }
382
+ function validateBoundsRequiredFor(profile) {
383
+ const errors = [];
384
+ const boundsSchema = profile.boundsSchema;
385
+ if (!boundsSchema) return errors;
386
+ const actionTypes = boundsSchema.actionTypes ? [...boundsSchema.actionTypes] : void 0;
387
+ for (const [fieldName, fieldDef] of Object.entries(boundsSchema.fields)) {
388
+ const bt = fieldDef.boundType;
389
+ if (!bt) continue;
390
+ const requiredFor = bt.requiredFor;
391
+ if (requiredFor === void 0) continue;
392
+ if (!Array.isArray(requiredFor) || !requiredFor.every((v) => typeof v === "string")) {
393
+ errors.push(`Bound "${fieldName}": requiredFor must be a string array.`);
394
+ continue;
395
+ }
396
+ if (bt.kind !== "per_transaction") {
397
+ errors.push(
398
+ `Bound "${fieldName}": requiredFor is only meaningful on a per_transaction bound (found on kind "${bt.kind}") \u2014 every enforcement point ignores it there. Remove it.`
399
+ );
400
+ continue;
401
+ }
402
+ if (actionTypes) {
403
+ for (const actionType of requiredFor) {
404
+ if (!actionTypes.includes(actionType)) {
405
+ errors.push(
406
+ `Bound "${fieldName}": requiredFor names action type "${actionType}", which is not in this profile's boundsSchema.actionTypes registry [${actionTypes.join(", ")}]. It can never match a real execution and the requirement is dead.`
407
+ );
408
+ }
409
+ }
410
+ }
411
+ }
412
+ return errors;
413
+ }
381
414
  var CanonicalValueError = class extends Error {
382
415
  code;
383
416
  field;
@@ -820,6 +853,22 @@ function checkBoundsV4(request, profile, executionLog, now) {
820
853
  switch (bt.kind) {
821
854
  case "per_transaction": {
822
855
  const actual = request.execution[bt.of];
856
+ const engaged = !!bt.requiredFor?.length && actionType !== void 0 && bt.requiredFor.includes(actionType);
857
+ if (engaged) {
858
+ const missing = actual === void 0 || actual === null;
859
+ const numericActual = missing ? NaN : typeof actual === "number" ? actual : Number(actual);
860
+ const missingOrNonNumeric = missing || Number.isNaN(numericActual);
861
+ if (missingOrNonNumeric) {
862
+ errors.push({
863
+ code: "BOUND_EXCEEDED",
864
+ field: bt.of,
865
+ message: missing ? `Bound "${fieldName}" requires "${bt.of}" for "${actionType}" calls, but this call exposes no ${bt.of} to check against it. Refusing: the call cannot be shown to stay within ${fieldName}.` : `Bound "${fieldName}" requires a numeric "${bt.of}" for "${actionType}" calls, but this call's value (${String(actual)}) is not a number. Refusing: the call cannot be shown to stay within ${fieldName}.`,
866
+ bound: boundValue,
867
+ actual
868
+ });
869
+ continue;
870
+ }
871
+ }
823
872
  if (actual === void 0) continue;
824
873
  if (typeof boundValue !== "number" || typeof actual !== "number") {
825
874
  errors.push({
@@ -1266,6 +1315,7 @@ async function verifyReceiptSignature(receipt, publicKeyHex) {
1266
1315
  signApproval,
1267
1316
  signMandateProjection,
1268
1317
  validateBoundsParams,
1318
+ validateBoundsRequiredFor,
1269
1319
  validateContextParams,
1270
1320
  validateFrameParams,
1271
1321
  validateSubject,
@@ -287,6 +287,38 @@ function validateContextParams(params, profile) {
287
287
  }
288
288
  return { valid: errors.length === 0, errors };
289
289
  }
290
+ function validateBoundsRequiredFor(profile) {
291
+ const errors = [];
292
+ const boundsSchema = profile.boundsSchema;
293
+ if (!boundsSchema) return errors;
294
+ const actionTypes = boundsSchema.actionTypes ? [...boundsSchema.actionTypes] : void 0;
295
+ for (const [fieldName, fieldDef] of Object.entries(boundsSchema.fields)) {
296
+ const bt = fieldDef.boundType;
297
+ if (!bt) continue;
298
+ const requiredFor = bt.requiredFor;
299
+ if (requiredFor === void 0) continue;
300
+ if (!Array.isArray(requiredFor) || !requiredFor.every((v) => typeof v === "string")) {
301
+ errors.push(`Bound "${fieldName}": requiredFor must be a string array.`);
302
+ continue;
303
+ }
304
+ if (bt.kind !== "per_transaction") {
305
+ errors.push(
306
+ `Bound "${fieldName}": requiredFor is only meaningful on a per_transaction bound (found on kind "${bt.kind}") \u2014 every enforcement point ignores it there. Remove it.`
307
+ );
308
+ continue;
309
+ }
310
+ if (actionTypes) {
311
+ for (const actionType of requiredFor) {
312
+ if (!actionTypes.includes(actionType)) {
313
+ errors.push(
314
+ `Bound "${fieldName}": requiredFor names action type "${actionType}", which is not in this profile's boundsSchema.actionTypes registry [${actionTypes.join(", ")}]. It can never match a real execution and the requirement is dead.`
315
+ );
316
+ }
317
+ }
318
+ }
319
+ }
320
+ return errors;
321
+ }
290
322
  var CanonicalValueError = class extends Error {
291
323
  code;
292
324
  field;
@@ -729,6 +761,22 @@ function checkBoundsV4(request, profile, executionLog, now) {
729
761
  switch (bt.kind) {
730
762
  case "per_transaction": {
731
763
  const actual = request.execution[bt.of];
764
+ const engaged = !!bt.requiredFor?.length && actionType !== void 0 && bt.requiredFor.includes(actionType);
765
+ if (engaged) {
766
+ const missing = actual === void 0 || actual === null;
767
+ const numericActual = missing ? NaN : typeof actual === "number" ? actual : Number(actual);
768
+ const missingOrNonNumeric = missing || Number.isNaN(numericActual);
769
+ if (missingOrNonNumeric) {
770
+ errors.push({
771
+ code: "BOUND_EXCEEDED",
772
+ field: bt.of,
773
+ message: missing ? `Bound "${fieldName}" requires "${bt.of}" for "${actionType}" calls, but this call exposes no ${bt.of} to check against it. Refusing: the call cannot be shown to stay within ${fieldName}.` : `Bound "${fieldName}" requires a numeric "${bt.of}" for "${actionType}" calls, but this call's value (${String(actual)}) is not a number. Refusing: the call cannot be shown to stay within ${fieldName}.`,
774
+ bound: boundValue,
775
+ actual
776
+ });
777
+ continue;
778
+ }
779
+ }
732
780
  if (actual === void 0) continue;
733
781
  if (typeof boundValue !== "number" || typeof actual !== "number") {
734
782
  errors.push({
@@ -1174,6 +1222,7 @@ export {
1174
1222
  signApproval,
1175
1223
  signMandateProjection,
1176
1224
  validateBoundsParams,
1225
+ validateBoundsRequiredFor,
1177
1226
  validateContextParams,
1178
1227
  validateFrameParams,
1179
1228
  validateSubject,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humanagencyp/hap-core",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "Core types, cryptographic primitives, and verification logic for the Human Agency Protocol",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -13,7 +13,7 @@
13
13
  */
14
14
 
15
15
  import { createHash } from 'crypto';
16
- import type { AgentFrameParams, AgentBoundsParams, AgentContextParams, AgentProfile } from './types';
16
+ import type { AgentFrameParams, AgentBoundsParams, AgentContextParams, AgentProfile, BoundType } from './types';
17
17
 
18
18
  // ─── v0.3 Frame Functions ─────────────────────────────────────────────────────
19
19
 
@@ -179,6 +179,68 @@ export function validateContextParams(
179
179
  return { valid: errors.length === 0, errors };
180
180
  }
181
181
 
182
+ /**
183
+ * Authoring-time check for `per_transaction` bound `requiredFor` (v0.8+):
184
+ * entries must name a real `action_type` from the profile's declared
185
+ * `boundsSchema.actionTypes` registry, and the field is only meaningful on
186
+ * `per_transaction` bounds (see `BoundType`'s doc comment for why the other
187
+ * kinds don't carry it).
188
+ *
189
+ * This is NOT wired into `registerProfile` or any enforcement path — nothing
190
+ * in hap-core validates profile JSON at load time today (the pre-existing
191
+ * `requiredFor` on a context/scope constraint has the same gap), so adding
192
+ * an automatic refusal here would be new behaviour beyond this change's
193
+ * scope. Call it explicitly from an authoring tool, a hap-profiles CI check,
194
+ * or a test, to catch a `requiredFor` entry that can never match (misspelled
195
+ * action type) or is attached to a bound kind that silently ignores it.
196
+ *
197
+ * Returns an empty array when the profile has no boundsSchema or nothing to
198
+ * check — never throws.
199
+ */
200
+ export function validateBoundsRequiredFor(profile: AgentProfile): string[] {
201
+ const errors: string[] = [];
202
+ const boundsSchema = profile.boundsSchema;
203
+ if (!boundsSchema) return errors;
204
+
205
+ const actionTypes = boundsSchema.actionTypes ? [...boundsSchema.actionTypes] : undefined;
206
+
207
+ for (const [fieldName, fieldDef] of Object.entries(boundsSchema.fields)) {
208
+ const bt = fieldDef.boundType as (BoundType & { requiredFor?: unknown }) | undefined;
209
+ if (!bt) continue;
210
+ const requiredFor = (bt as { requiredFor?: unknown }).requiredFor;
211
+ if (requiredFor === undefined) continue;
212
+
213
+ if (!Array.isArray(requiredFor) || !requiredFor.every((v) => typeof v === 'string')) {
214
+ errors.push(`Bound "${fieldName}": requiredFor must be a string array.`);
215
+ continue;
216
+ }
217
+
218
+ if (bt.kind !== 'per_transaction') {
219
+ errors.push(
220
+ `Bound "${fieldName}": requiredFor is only meaningful on a per_transaction bound ` +
221
+ `(found on kind "${bt.kind}") — every enforcement point ignores it there. Remove it.`,
222
+ );
223
+ continue;
224
+ }
225
+
226
+ if (actionTypes) {
227
+ for (const actionType of requiredFor) {
228
+ if (!actionTypes.includes(actionType)) {
229
+ errors.push(
230
+ `Bound "${fieldName}": requiredFor names action type "${actionType}", which is not ` +
231
+ `in this profile's boundsSchema.actionTypes registry [${actionTypes.join(', ')}]. ` +
232
+ `It can never match a real execution and the requirement is dead.`,
233
+ );
234
+ }
235
+ }
236
+ }
237
+ // No actionTypes registry declared: membership cannot be checked (same
238
+ // tolerance the AS receipt route applies to pre-registry profiles).
239
+ }
240
+
241
+ return errors;
242
+ }
243
+
182
244
  // ─── Value Encoding (normative, v0.5+) ───────────────────────────────────────
183
245
 
184
246
  /**
@@ -546,6 +546,43 @@ function checkBoundsV4(
546
546
  switch (bt.kind) {
547
547
  case 'per_transaction': {
548
548
  const actual = request.execution[bt.of];
549
+
550
+ // `requiredFor`: for a listed action_type, absence (or a non-numeric
551
+ // value) is a denial, not a skip — see BoundType.per_transaction's
552
+ // doc comment for why. Unlisted action types, or no `requiredFor` at
553
+ // all, keep the pre-existing skip-on-absence behaviour below.
554
+ const engaged = !!bt.requiredFor?.length
555
+ && actionType !== undefined
556
+ && bt.requiredFor.includes(actionType);
557
+
558
+ if (engaged) {
559
+ // `null` is treated as "missing", not as the number 0 — JSON has no
560
+ // undefined, so a value lost somewhere upstream (an unmapped
561
+ // connector field serialized through JSON) commonly arrives as
562
+ // null. `Number(null) === 0` would otherwise read as "an amount of
563
+ // zero was declared and is within bound", which is the exact
564
+ // silent-pass this feature exists to close.
565
+ const missing = actual === undefined || actual === null;
566
+ const numericActual = missing ? NaN : (typeof actual === 'number' ? actual : Number(actual));
567
+ const missingOrNonNumeric = missing || Number.isNaN(numericActual);
568
+ if (missingOrNonNumeric) {
569
+ errors.push({
570
+ code: 'BOUND_EXCEEDED',
571
+ field: bt.of,
572
+ message: missing
573
+ ? `Bound "${fieldName}" requires "${bt.of}" for "${actionType}" calls, but this ` +
574
+ `call exposes no ${bt.of} to check against it. Refusing: the call cannot be ` +
575
+ `shown to stay within ${fieldName}.`
576
+ : `Bound "${fieldName}" requires a numeric "${bt.of}" for "${actionType}" calls, ` +
577
+ `but this call's value (${String(actual)}) is not a number. Refusing: the call ` +
578
+ `cannot be shown to stay within ${fieldName}.`,
579
+ bound: boundValue,
580
+ actual,
581
+ });
582
+ continue;
583
+ }
584
+ }
585
+
549
586
  if (actual === undefined) continue;
550
587
  if (typeof boundValue !== 'number' || typeof actual !== 'number') {
551
588
  errors.push({
@@ -218,8 +218,26 @@ export type BoundType =
218
218
  * Per-transaction cap. The execution context field named in `of` must
219
219
  * satisfy `execution[of] <= bound` for the current call. No cumulative
220
220
  * tracking. Used by: amount_max, recipient_max, booking_duration_max, etc.
221
+ *
222
+ * `requiredFor` (v0.8+) closes the converse: without it, a call that does
223
+ * not carry `of` at all is simply skipped — a 5,000 cap refuses 6,000 but
224
+ * permits a call that declares no value whatsoever, which is indistinguishable
225
+ * from an unenforced bound. The same hole, and the same fix, as
226
+ * `FieldConstraint.requiredFor` on a scope constraint (below): values drawn
227
+ * from the profile's `boundsSchema.actionTypes` registry. For a listed
228
+ * `action_type`, an execution whose context lacks `of` — or whose value is
229
+ * not a finite number — MUST be refused rather than skipped. For an
230
+ * unlisted (or when `requiredFor` is absent) action type, today's
231
+ * skip-on-absence behaviour is unchanged. Meaningful only on
232
+ * `per_transaction`; the other `BoundType` kinds have no per-call "value
233
+ * exposed or not" question — `cumulative_sum`/`cumulative_count` always read
234
+ * from the execution log regardless of what this call declares, and `enum`
235
+ * is a capability flag, not a runtime value — so the field does not exist
236
+ * on those variants and a profile that puts it there has it silently
237
+ * ignored by every enforcement point (TypeScript also refuses it when the
238
+ * profile is authored against this type rather than raw JSON).
221
239
  */
222
- | { kind: 'per_transaction'; of: string }
240
+ | { kind: 'per_transaction'; of: string; requiredFor?: string[] }
223
241
  /**
224
242
  * Cumulative sum within a time window. The SP maintains a running sum
225
243
  * of `execution[of]` across all prior executions in the window; the
@@ -520,6 +538,16 @@ export interface AgentProfile {
520
538
  boundsSchema?: {
521
539
  keyOrder: string[];
522
540
  fields: Record<string, ProfileBoundsField>;
541
+ /**
542
+ * v0.5+ registry of the action types this profile recognizes (e.g.
543
+ * `["send", "delete", "setup"]`). Every `execution.action_type` the
544
+ * Authority Server and gateway accept for this profile MUST be a member
545
+ * when the registry is declared (protocol.md → Bounds Schema, rule 2);
546
+ * it is also what a `per_transaction` bound's `requiredFor` draws from.
547
+ * Absent on profiles published before the registry existed — membership
548
+ * is then uncheckable, not a violation.
549
+ */
550
+ actionTypes?: readonly string[];
523
551
  };
524
552
 
525
553
  /**
@@ -176,6 +176,8 @@ var Hono = class Hono {
176
176
  /**
177
177
  * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
178
178
  *
179
+ * @deprecated Use `mount()` from `hono/mount` instead. `.mount()` will be removed in v5.
180
+ *
179
181
  * @see {@link https://hono.dev/docs/api/hono#mount}
180
182
  *
181
183
  * @param {string} path - base Path
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_helper_cookie_index = require("../../helper/cookie/index.js");
3
2
  const require_utils_accept = require("../../utils/accept.js");
3
+ const require_helper_cookie_index = require("../../helper/cookie/index.js");
4
4
  //#region src/middleware/language/language.ts
5
5
  const DEFAULT_OPTIONS = {
6
6
  order: [
@@ -0,0 +1,71 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_helper_route_index = require("../../helper/route/index.js");
3
+ //#region src/middleware/mount/index.ts
4
+ const defaultReplaceRequest = (c) => {
5
+ const pathPrefix = require_helper_route_index.routePath(c).replace(/\/\*$/, "");
6
+ const url = new URL(c.req.raw.url);
7
+ url.pathname = c.req.path.slice(pathPrefix.length) || "/";
8
+ return new Request(url, c.req.raw);
9
+ };
10
+ const defaultGetOptions = (c) => {
11
+ let executionContext = void 0;
12
+ try {
13
+ executionContext = c.executionCtx;
14
+ } catch {}
15
+ return [c.env, executionContext];
16
+ };
17
+ /**
18
+ * `mount()` allows you to mount applications built with other frameworks into your Hono application.
19
+ *
20
+ * @see {@link https://hono.dev/docs/api/hono#mount}
21
+ *
22
+ * @param {Function} applicationHandler - other Request Handler
23
+ * @param {MountOptions} [options] - options of `mount()`
24
+ * @returns {MiddlewareHandler} handler to register with `app.all()`
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { Router as IttyRouter } from 'itty-router'
29
+ * import { Hono } from 'hono'
30
+ * import { mount } from 'hono/mount'
31
+ * // Create itty-router application
32
+ * const ittyRouter = IttyRouter()
33
+ * // GET /itty-router/hello
34
+ * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
35
+ *
36
+ * const app = new Hono()
37
+ * app.all('/itty-router/*', mount(ittyRouter.handle))
38
+ * ```
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const app = new Hono()
43
+ * // Send the request to another application without modification.
44
+ * app.all('/app/*', mount(anotherApp, {
45
+ * replaceRequest: (req) => req,
46
+ * }))
47
+ * ```
48
+ */
49
+ const mount = (applicationHandler, options) => {
50
+ let replaceRequest;
51
+ let optionHandler;
52
+ if (options) {
53
+ if (typeof options === "function") optionHandler = options;
54
+ else {
55
+ optionHandler = options.optionHandler;
56
+ if (options.replaceRequest === false) replaceRequest = (request) => request;
57
+ else replaceRequest = options.replaceRequest;
58
+ }
59
+ }
60
+ const getOptions = optionHandler ? (c) => {
61
+ const options = optionHandler(c);
62
+ return Array.isArray(options) ? options : [options];
63
+ } : defaultGetOptions;
64
+ return async (c, next) => {
65
+ const res = await applicationHandler(replaceRequest ? replaceRequest(c.req.raw) : defaultReplaceRequest(c), ...getOptions(c));
66
+ if (res) return res;
67
+ await next();
68
+ };
69
+ };
70
+ //#endregion
71
+ exports.mount = mount;
@@ -189,7 +189,7 @@ var HonoRequest = class {
189
189
  return this.#validatedData?.[target];
190
190
  }
191
191
  /**
192
- * `.url()` can get the request url strings.
192
+ * `.url` can get the request url strings.
193
193
  *
194
194
  * @see {@link https://hono.dev/docs/api/request#url}
195
195
  *
@@ -205,7 +205,7 @@ var HonoRequest = class {
205
205
  return this.raw.url;
206
206
  }
207
207
  /**
208
- * `.method()` can get the method name of the request.
208
+ * `.method` can get the method name of the request.
209
209
  *
210
210
  * @see {@link https://hono.dev/docs/api/request#method}
211
211
  *
@@ -223,7 +223,7 @@ var HonoRequest = class {
223
223
  return this.#matchResult;
224
224
  }
225
225
  /**
226
- * `.matchedRoutes()` can return a matched route in the handler
226
+ * `.matchedRoutes` can return a matched route in the handler
227
227
  *
228
228
  * @deprecated
229
229
  *
@@ -253,7 +253,7 @@ var HonoRequest = class {
253
253
  return this.#matchResult[0].map(([[, route]]) => route);
254
254
  }
255
255
  /**
256
- * `routePath()` can retrieve the path registered within the handler
256
+ * `.routePath` can retrieve the path registered within the handler
257
257
  *
258
258
  * @deprecated
259
259
  *
@@ -175,6 +175,8 @@ var Hono = class Hono {
175
175
  /**
176
176
  * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
177
177
  *
178
+ * @deprecated Use `mount()` from `hono/mount` instead. `.mount()` will be removed in v5.
179
+ *
178
180
  * @see {@link https://hono.dev/docs/api/hono#mount}
179
181
  *
180
182
  * @param {string} path - base Path
@@ -0,0 +1,70 @@
1
+ import { routePath } from "../../helper/route/index.js";
2
+ //#region src/middleware/mount/index.ts
3
+ const defaultReplaceRequest = (c) => {
4
+ const pathPrefix = routePath(c).replace(/\/\*$/, "");
5
+ const url = new URL(c.req.raw.url);
6
+ url.pathname = c.req.path.slice(pathPrefix.length) || "/";
7
+ return new Request(url, c.req.raw);
8
+ };
9
+ const defaultGetOptions = (c) => {
10
+ let executionContext = void 0;
11
+ try {
12
+ executionContext = c.executionCtx;
13
+ } catch {}
14
+ return [c.env, executionContext];
15
+ };
16
+ /**
17
+ * `mount()` allows you to mount applications built with other frameworks into your Hono application.
18
+ *
19
+ * @see {@link https://hono.dev/docs/api/hono#mount}
20
+ *
21
+ * @param {Function} applicationHandler - other Request Handler
22
+ * @param {MountOptions} [options] - options of `mount()`
23
+ * @returns {MiddlewareHandler} handler to register with `app.all()`
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { Router as IttyRouter } from 'itty-router'
28
+ * import { Hono } from 'hono'
29
+ * import { mount } from 'hono/mount'
30
+ * // Create itty-router application
31
+ * const ittyRouter = IttyRouter()
32
+ * // GET /itty-router/hello
33
+ * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
34
+ *
35
+ * const app = new Hono()
36
+ * app.all('/itty-router/*', mount(ittyRouter.handle))
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const app = new Hono()
42
+ * // Send the request to another application without modification.
43
+ * app.all('/app/*', mount(anotherApp, {
44
+ * replaceRequest: (req) => req,
45
+ * }))
46
+ * ```
47
+ */
48
+ const mount = (applicationHandler, options) => {
49
+ let replaceRequest;
50
+ let optionHandler;
51
+ if (options) {
52
+ if (typeof options === "function") optionHandler = options;
53
+ else {
54
+ optionHandler = options.optionHandler;
55
+ if (options.replaceRequest === false) replaceRequest = (request) => request;
56
+ else replaceRequest = options.replaceRequest;
57
+ }
58
+ }
59
+ const getOptions = optionHandler ? (c) => {
60
+ const options = optionHandler(c);
61
+ return Array.isArray(options) ? options : [options];
62
+ } : defaultGetOptions;
63
+ return async (c, next) => {
64
+ const res = await applicationHandler(replaceRequest ? replaceRequest(c.req.raw) : defaultReplaceRequest(c), ...getOptions(c));
65
+ if (res) return res;
66
+ await next();
67
+ };
68
+ };
69
+ //#endregion
70
+ export { mount };
@@ -188,7 +188,7 @@ var HonoRequest = class {
188
188
  return this.#validatedData?.[target];
189
189
  }
190
190
  /**
191
- * `.url()` can get the request url strings.
191
+ * `.url` can get the request url strings.
192
192
  *
193
193
  * @see {@link https://hono.dev/docs/api/request#url}
194
194
  *
@@ -204,7 +204,7 @@ var HonoRequest = class {
204
204
  return this.raw.url;
205
205
  }
206
206
  /**
207
- * `.method()` can get the method name of the request.
207
+ * `.method` can get the method name of the request.
208
208
  *
209
209
  * @see {@link https://hono.dev/docs/api/request#method}
210
210
  *
@@ -222,7 +222,7 @@ var HonoRequest = class {
222
222
  return this.#matchResult;
223
223
  }
224
224
  /**
225
- * `.matchedRoutes()` can return a matched route in the handler
225
+ * `.matchedRoutes` can return a matched route in the handler
226
226
  *
227
227
  * @deprecated
228
228
  *
@@ -252,7 +252,7 @@ var HonoRequest = class {
252
252
  return this.#matchResult[0].map(([[, route]]) => route);
253
253
  }
254
254
  /**
255
- * `routePath()` can retrieve the path registered within the handler
255
+ * `.routePath` can retrieve the path registered within the handler
256
256
  *
257
257
  * @deprecated
258
258
  *
@@ -140,6 +140,8 @@ declare class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends
140
140
  /**
141
141
  * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
142
142
  *
143
+ * @deprecated Use `mount()` from `hono/mount` instead. `.mount()` will be removed in v5.
144
+ *
143
145
  * @see {@link https://hono.dev/docs/api/hono#mount}
144
146
  *
145
147
  * @param {string} path - base Path
@@ -4,7 +4,7 @@ import { JSX as JSX$1 } from "./intrinsic-elements.js";
4
4
  import { Context } from "./context.js";
5
5
  //#region src/jsx/base.d.ts
6
6
  export type Props = Record<string, any>;
7
- type FunctionComponentResult = HtmlEscapedString | Child[] | Promise<HtmlEscapedString | Child[]> | null;
7
+ type FunctionComponentResult = HtmlEscapedString | JSXNode | Child[] | Promise<HtmlEscapedString | JSXNode | Child[]> | null;
8
8
  export type FC<P = Props> = {
9
9
  (props: P): FunctionComponentResult;
10
10
  defaultProps?: Partial<P> | undefined;
@@ -0,0 +1,46 @@
1
+ import { MiddlewareHandler } from "../../types.js";
2
+ import { Context } from "../../context.js";
3
+ //#region src/middleware/mount/index.d.ts
4
+ type ApplicationHandler = (request: Request, ...args: any) => Response | Promise<Response>;
5
+ type MountOptionHandler = (c: Context) => unknown;
6
+ type MountReplaceRequest = (originalRequest: Request) => Request;
7
+ type MountOptions = MountOptionHandler | {
8
+ optionHandler?: MountOptionHandler;
9
+ replaceRequest?: MountReplaceRequest | false;
10
+ };
11
+ /**
12
+ * `mount()` allows you to mount applications built with other frameworks into your Hono application.
13
+ *
14
+ * @see {@link https://hono.dev/docs/api/hono#mount}
15
+ *
16
+ * @param {Function} applicationHandler - other Request Handler
17
+ * @param {MountOptions} [options] - options of `mount()`
18
+ * @returns {MiddlewareHandler} handler to register with `app.all()`
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { Router as IttyRouter } from 'itty-router'
23
+ * import { Hono } from 'hono'
24
+ * import { mount } from 'hono/mount'
25
+ * // Create itty-router application
26
+ * const ittyRouter = IttyRouter()
27
+ * // GET /itty-router/hello
28
+ * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
29
+ *
30
+ * const app = new Hono()
31
+ * app.all('/itty-router/*', mount(ittyRouter.handle))
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const app = new Hono()
37
+ * // Send the request to another application without modification.
38
+ * app.all('/app/*', mount(anotherApp, {
39
+ * replaceRequest: (req) => req,
40
+ * }))
41
+ * ```
42
+ */
43
+ export declare const mount: (applicationHandler: ApplicationHandler, options?: MountOptions) => MiddlewareHandler;
44
+ //#endregion
45
+ export type { ApplicationHandler, MountOptionHandler, MountOptions, MountReplaceRequest };
46
+ export {};
@@ -217,7 +217,7 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
217
217
  */
218
218
  valid<T extends keyof I & keyof ValidationTargets>(target: T): InputToDataByTarget<I, T>;
219
219
  /**
220
- * `.url()` can get the request url strings.
220
+ * `.url` can get the request url strings.
221
221
  *
222
222
  * @see {@link https://hono.dev/docs/api/request#url}
223
223
  *
@@ -231,7 +231,7 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
231
231
  */
232
232
  get url(): string;
233
233
  /**
234
- * `.method()` can get the method name of the request.
234
+ * `.method` can get the method name of the request.
235
235
  *
236
236
  * @see {@link https://hono.dev/docs/api/request#method}
237
237
  *
@@ -245,7 +245,7 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
245
245
  get method(): string;
246
246
  get [GET_MATCH_RESULT](): Result<[unknown, RouterRoute]>;
247
247
  /**
248
- * `.matchedRoutes()` can return a matched route in the handler
248
+ * `.matchedRoutes` can return a matched route in the handler
249
249
  *
250
250
  * @deprecated
251
251
  *
@@ -273,7 +273,7 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
273
273
  */
274
274
  get matchedRoutes(): RouterRoute[];
275
275
  /**
276
- * `routePath()` can retrieve the path registered within the handler
276
+ * `.routePath` can retrieve the path registered within the handler
277
277
  *
278
278
  * @deprecated
279
279
  *