@voyant-travel/hono 0.110.3 → 0.111.0
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/app.d.ts.map +1 -1
- package/dist/app.js +27 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lazy-routes.d.ts +67 -0
- package/dist/lazy-routes.d.ts.map +1 -0
- package/dist/lazy-routes.js +79 -0
- package/dist/module.d.ts +23 -0
- package/dist/module.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AA6B3B,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAY,eAAe,EAAE,MAAM,YAAY,CAAA;AA2C5F;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB,CAAC,SAAS,GAAG,OAAO;IACtD;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C;;;;;;;;OAQG;IACH,QAAQ,EAAE,OAAO,qBAAqB,EAAE,QAAQ,CAAA;CACjD;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,cAAc,EACxD,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,GACjC,IAAI,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GAAG,mBAAmB,CAAC,SAAS,CAAC,CA6a5F"}
|
package/dist/app.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createContainer, createEventBus, createQueryRunner, } from "@voyant-tra
|
|
|
2
2
|
import { createOutboxEventStore } from "@voyant-travel/db/outbox";
|
|
3
3
|
import { Hono } from "hono";
|
|
4
4
|
import { containerToServiceResolver, makeFrameworkLogger, wireWorkflowRuntime, } from "./app-workflows.js";
|
|
5
|
+
import { mountLazyRoutePaths, mountLazyRoutesAt } from "./lazy-routes.js";
|
|
5
6
|
import { createPathDbSelector } from "./lib/db-selector.js";
|
|
6
7
|
import { tryGetExecutionCtx } from "./lib/execution-ctx.js";
|
|
7
8
|
import { matchesPublicPath, normalizePathname } from "./lib/public-paths.js";
|
|
@@ -358,11 +359,22 @@ export function createApp(config) {
|
|
|
358
359
|
}
|
|
359
360
|
// Mount module routes
|
|
360
361
|
for (const mod of allModules) {
|
|
362
|
+
const adminPrefix = `/v1/admin/${mod.module.name}`;
|
|
363
|
+
const publicPrefix = resolveSurfaceMountPath("/v1/public", mod.publicPath, mod.module.name);
|
|
361
364
|
if (mod.adminRoutes) {
|
|
362
|
-
app.route(
|
|
365
|
+
app.route(adminPrefix, mod.adminRoutes);
|
|
363
366
|
}
|
|
364
367
|
if (mod.publicRoutes) {
|
|
365
|
-
app.route(
|
|
368
|
+
app.route(publicPrefix, mod.publicRoutes);
|
|
369
|
+
}
|
|
370
|
+
if (mod.lazyAdminRoutes) {
|
|
371
|
+
mountLazyRoutesAt(app, adminPrefix, mod.lazyAdminRoutes);
|
|
372
|
+
}
|
|
373
|
+
if (mod.lazyPublicRoutes) {
|
|
374
|
+
mountLazyRoutesAt(app, publicPrefix, mod.lazyPublicRoutes);
|
|
375
|
+
}
|
|
376
|
+
if (mod.lazyRoutes) {
|
|
377
|
+
mountLazyRoutePaths(app, mod.lazyRoutes.paths, mod.lazyRoutes.load);
|
|
366
378
|
}
|
|
367
379
|
if (mod.routes) {
|
|
368
380
|
app.route(`/v1/${mod.module.name}`, mod.routes);
|
|
@@ -370,11 +382,22 @@ export function createApp(config) {
|
|
|
370
382
|
}
|
|
371
383
|
// Mount extension routes
|
|
372
384
|
for (const ext of allExtensions) {
|
|
385
|
+
const adminPrefix = `/v1/admin/${ext.extension.module}`;
|
|
386
|
+
const publicPrefix = resolveSurfaceMountPath("/v1/public", ext.publicPath, ext.extension.module);
|
|
373
387
|
if (ext.adminRoutes) {
|
|
374
|
-
app.route(
|
|
388
|
+
app.route(adminPrefix, ext.adminRoutes);
|
|
375
389
|
}
|
|
376
390
|
if (ext.publicRoutes) {
|
|
377
|
-
app.route(
|
|
391
|
+
app.route(publicPrefix, ext.publicRoutes);
|
|
392
|
+
}
|
|
393
|
+
if (ext.lazyAdminRoutes) {
|
|
394
|
+
mountLazyRoutesAt(app, adminPrefix, ext.lazyAdminRoutes);
|
|
395
|
+
}
|
|
396
|
+
if (ext.lazyPublicRoutes) {
|
|
397
|
+
mountLazyRoutesAt(app, publicPrefix, ext.lazyPublicRoutes);
|
|
398
|
+
}
|
|
399
|
+
if (ext.lazyRoutes) {
|
|
400
|
+
mountLazyRoutePaths(app, ext.lazyRoutes.paths, ext.lazyRoutes.load);
|
|
378
401
|
}
|
|
379
402
|
if (ext.routes) {
|
|
380
403
|
app.route(`/v1/${ext.extension.module}`, ext.routes);
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type { SessionAuthContext } from "./auth/index.js";
|
|
|
4
4
|
export { constantTimeEqual, extractBearerToken, generateNumericCode, randomBytesHex, requireUserId, sha256Base64Url, sha256Hex, unsignCookie, verifySession, } from "./auth/index.js";
|
|
5
5
|
export type { DocumentDownloadEnvelope, DocumentDownloadResolution, DocumentDownloadResolver, DocumentDownloadResolverResult, StoredDocumentReference, } from "./document-download.js";
|
|
6
6
|
export { resolveStoredDocumentDownload } from "./document-download.js";
|
|
7
|
+
export { createLazyRouteHandler, type LazyHonoRoutes, type LazyRoutesLoader, mountLazyRoutePaths, mountLazyRoutesAt, } from "./lazy-routes.js";
|
|
7
8
|
export { createPathDbSelector, type PathDbSelectorOptions } from "./lib/db-selector.js";
|
|
8
9
|
export { clientIpKey, consoleLoggerProvider, cors, DEFAULT_IDEMPOTENCY_TTL_MS, db, enforceRateLimit, errorBoundary, handleApiError, type IdempotencyKeyOptions, idempotencyKey, LIVE_LIMITS, logger, purgeExpiredIdempotencyKeys, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
9
10
|
export type { HonoExtension, HonoModule } from "./module.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,eAAe,EACf,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AACvF,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,IAAI,EACJ,0BAA0B,EAC1B,EAAE,EACF,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,KAAK,qBAAqB,EAC1B,cAAc,EACd,WAAW,EACX,MAAM,EACN,2BAA2B,EAC3B,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC5D,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,6BAA6B,EAC7B,6BAA6B,EAC7B,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,+BAA+B,EAC/B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,KAAK,iCAAiC,EACtC,6CAA6C,EAC7C,iCAAiC,EACjC,sCAAsC,EACtC,kCAAkC,EAClC,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,EACrC,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EACvC,KAAK,4BAA4B,EACjC,KAAK,sCAAsC,EAC3C,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,+BAA+B,CAAA;AACtC,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,QAAQ,EACR,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,wBAAwB,EACxB,aAAa,EACb,qBAAqB,EACrB,UAAU,EACV,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,eAAe,EACf,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EACL,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AACvF,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,IAAI,EACJ,0BAA0B,EAC1B,EAAE,EACF,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,KAAK,qBAAqB,EAC1B,cAAc,EACd,WAAW,EACX,MAAM,EACN,2BAA2B,EAC3B,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC5D,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,6BAA6B,EAC7B,6BAA6B,EAC7B,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,+BAA+B,EAC/B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,KAAK,iCAAiC,EACtC,6CAA6C,EAC7C,iCAAiC,EACjC,sCAAsC,EACtC,kCAAkC,EAClC,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,EACrC,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EACvC,KAAK,4BAA4B,EACjC,KAAK,sCAAsC,EAC3C,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,+BAA+B,CAAA;AACtC,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,QAAQ,EACR,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,wBAAwB,EACxB,aAAa,EACb,qBAAqB,EACrB,UAAU,EACV,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { createApp } from "./app.js";
|
|
2
2
|
export { constantTimeEqual, extractBearerToken, generateNumericCode, randomBytesHex, requireUserId, sha256Base64Url, sha256Hex, unsignCookie, verifySession, } from "./auth/index.js";
|
|
3
3
|
export { resolveStoredDocumentDownload } from "./document-download.js";
|
|
4
|
+
export { createLazyRouteHandler, mountLazyRoutePaths, mountLazyRoutesAt, } from "./lazy-routes.js";
|
|
4
5
|
export { createPathDbSelector } from "./lib/db-selector.js";
|
|
5
6
|
export { clientIpKey, consoleLoggerProvider, cors, DEFAULT_IDEMPOTENCY_TTL_MS, db, enforceRateLimit, errorBoundary, handleApiError, idempotencyKey, LIVE_LIMITS, logger, purgeExpiredIdempotencyKeys, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
6
7
|
export { defineHonoBundle, defineHonoPlugin, expandHonoBundles, expandHonoPlugins, } from "./plugin.js";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-class lazy route mounting for `@voyant-travel/hono`.
|
|
3
|
+
*
|
|
4
|
+
* A module or extension can declare `lazyAdminRoutes` / `lazyPublicRoutes` as a
|
|
5
|
+
* loader (`() => import("./routes").then((m) => m.createRoutes(opts))`) instead
|
|
6
|
+
* of eager `adminRoutes` / `publicRoutes`. The route bundle is dynamically
|
|
7
|
+
* imported on first matching request and cached per isolate/process, so heavy
|
|
8
|
+
* route families don't inflate the main bundle or the Worker cold start.
|
|
9
|
+
*
|
|
10
|
+
* For deployment-local families that span MULTIPLE absolute path prefixes (e.g.
|
|
11
|
+
* an operator bundle exposing `/v1/uploads`, `/v1/admin/uploads`, `/v1/media/*`),
|
|
12
|
+
* the single-surface loaders don't fit. Such families declare `lazyRoutes`:
|
|
13
|
+
* `{ paths, load }` where `load` returns a sub-app whose routes are ABSOLUTE and
|
|
14
|
+
* `paths` are the explicit matchers the framework installs up front. This is the
|
|
15
|
+
* context-preserving replacement for the starter's `mountLazyRouteApp(...)`.
|
|
16
|
+
*
|
|
17
|
+
* The hard requirement (and the reason the starter's old `mountLazyRouteApp`
|
|
18
|
+
* was insufficient): the lazy routes must behave **exactly** like eager routes.
|
|
19
|
+
* Eager routes mounted via `app.route(...)` share the request context, so they
|
|
20
|
+
* see `c.var.db`, `c.var.container`, the resolved actor, etc. set by the
|
|
21
|
+
* `createApp` middleware pipeline. A naive `subApp.fetch(c.req.raw, c.env)`
|
|
22
|
+
* forward builds a fresh context and drops every `c.var`.
|
|
23
|
+
*
|
|
24
|
+
* So this dispatcher bridges the request-scoped context across the forward: it
|
|
25
|
+
* snapshots `c.var`, carries it on the forwarded `env` under a private symbol,
|
|
26
|
+
* and a wrapper middleware re-hydrates it onto the loaded sub-app's context
|
|
27
|
+
* before the real routes run. The db lease is *carried*, not re-acquired — the
|
|
28
|
+
* outer `db` middleware still owns its lifecycle (dispose), so there is no
|
|
29
|
+
* double-release.
|
|
30
|
+
*/
|
|
31
|
+
import type { Context, Hono as HonoType } from "hono";
|
|
32
|
+
type AnyHono = HonoType<any>;
|
|
33
|
+
/** Loads (and builds) the Hono sub-app for a lazy route surface. */
|
|
34
|
+
export type LazyRoutesLoader = () => Promise<AnyHono>;
|
|
35
|
+
/**
|
|
36
|
+
* A deployment-local lazy route family spanning explicit absolute path
|
|
37
|
+
* matchers. `load` returns a sub-app whose routes are ABSOLUTE; `paths` are the
|
|
38
|
+
* matchers the framework installs up front (no bundle import until a request
|
|
39
|
+
* matches).
|
|
40
|
+
*/
|
|
41
|
+
export interface LazyHonoRoutes {
|
|
42
|
+
paths: readonly string[];
|
|
43
|
+
load: LazyRoutesLoader;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build a cached, context-preserving request handler. `mountPrefix` is where the
|
|
47
|
+
* loaded routes are re-mounted in the wrapper sub-app so the forwarded absolute
|
|
48
|
+
* request URL matches: the surface prefix (e.g. `/v1/admin/flights`) for
|
|
49
|
+
* relative-route loaders, or `"/"` for loaders that already return absolute
|
|
50
|
+
* routes.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createLazyRouteHandler(mountPrefix: string, load: LazyRoutesLoader): (c: Context) => Promise<Response>;
|
|
53
|
+
/**
|
|
54
|
+
* Register a single lazy surface on `app` at `prefix` (loader returns RELATIVE
|
|
55
|
+
* routes). Matches both the prefix root (`POST /v1/admin/foo`) and any sub-path
|
|
56
|
+
* (`/v1/admin/foo/bar`).
|
|
57
|
+
*/
|
|
58
|
+
export declare function mountLazyRoutesAt(app: AnyHono, prefix: string, load: LazyRoutesLoader): void;
|
|
59
|
+
/**
|
|
60
|
+
* Register a multi-prefix lazy family on `app` at explicit `paths` (loader
|
|
61
|
+
* returns ABSOLUTE routes). One shared cached/context-bridging handler backs
|
|
62
|
+
* every path. Context-preserving replacement for the starter's
|
|
63
|
+
* `mountLazyRouteApp(...)`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function mountLazyRoutePaths(app: AnyHono, paths: readonly string[], load: LazyRoutesLoader): void;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=lazy-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-routes.d.ts","sourceRoot":"","sources":["../src/lazy-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,MAAM,CAAA;AAMrD,KAAK,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;AAE5B,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,IAAI,EAAE,gBAAgB,CAAA;CACvB;AAKD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,IA0ClE,GAAG,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAO7C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI5F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,EAAE,gBAAgB,GACrB,IAAI,CAKN"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { tryGetExecutionCtx } from "./lib/execution-ctx.js";
|
|
3
|
+
/** Private carrier key for snapshotting `c.var` across the forward. */
|
|
4
|
+
const LAZY_CONTEXT_CARRIER = Symbol.for("voyant.hono.lazyContextCarrier");
|
|
5
|
+
/**
|
|
6
|
+
* Build a cached, context-preserving request handler. `mountPrefix` is where the
|
|
7
|
+
* loaded routes are re-mounted in the wrapper sub-app so the forwarded absolute
|
|
8
|
+
* request URL matches: the surface prefix (e.g. `/v1/admin/flights`) for
|
|
9
|
+
* relative-route loaders, or `"/"` for loaders that already return absolute
|
|
10
|
+
* routes.
|
|
11
|
+
*/
|
|
12
|
+
export function createLazyRouteHandler(mountPrefix, load) {
|
|
13
|
+
let cached;
|
|
14
|
+
function getApp() {
|
|
15
|
+
// Cache the BUILT, wrapped sub-app; reset on failure so a transient
|
|
16
|
+
// import/config error can recover on the next request.
|
|
17
|
+
if (!cached) {
|
|
18
|
+
cached = load()
|
|
19
|
+
.then((routes) => {
|
|
20
|
+
const wrapped = new Hono();
|
|
21
|
+
// Re-throw handler errors instead of letting the wrapper sub-app's
|
|
22
|
+
// default Hono error handler swallow them into a plain 500. This
|
|
23
|
+
// propagates the throw back through `app.fetch` to the outer
|
|
24
|
+
// `createApp` pipeline, so lazy routes hit the same `errorBoundary` /
|
|
25
|
+
// `handleApiError` normalization (JSON error shape + structured
|
|
26
|
+
// logging) as eager `app.route(...)` mounts.
|
|
27
|
+
wrapped.onError((err) => {
|
|
28
|
+
throw err;
|
|
29
|
+
});
|
|
30
|
+
wrapped.use("*", async (cc, next) => {
|
|
31
|
+
const carried = cc.env?.[LAZY_CONTEXT_CARRIER];
|
|
32
|
+
if (carried) {
|
|
33
|
+
for (const [key, value] of Object.entries(carried)) {
|
|
34
|
+
// biome-ignore lint/suspicious/noExplicitAny: re-hydrating arbitrary context vars -- owner: hono.
|
|
35
|
+
cc.set(key, value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
await next();
|
|
39
|
+
});
|
|
40
|
+
wrapped.route(mountPrefix, routes);
|
|
41
|
+
return wrapped;
|
|
42
|
+
})
|
|
43
|
+
.catch((err) => {
|
|
44
|
+
cached = undefined;
|
|
45
|
+
throw err;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return cached;
|
|
49
|
+
}
|
|
50
|
+
return async (c) => {
|
|
51
|
+
const app = await getApp();
|
|
52
|
+
const snapshot = { ...c.var };
|
|
53
|
+
const env = { ...c.env, [LAZY_CONTEXT_CARRIER]: snapshot };
|
|
54
|
+
// biome-ignore lint/suspicious/noExplicitAny: forward the host execution context when present -- owner: hono.
|
|
55
|
+
return app.fetch(c.req.raw, env, tryGetExecutionCtx(c));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Register a single lazy surface on `app` at `prefix` (loader returns RELATIVE
|
|
60
|
+
* routes). Matches both the prefix root (`POST /v1/admin/foo`) and any sub-path
|
|
61
|
+
* (`/v1/admin/foo/bar`).
|
|
62
|
+
*/
|
|
63
|
+
export function mountLazyRoutesAt(app, prefix, load) {
|
|
64
|
+
const handler = createLazyRouteHandler(prefix, load);
|
|
65
|
+
app.all(prefix, handler);
|
|
66
|
+
app.all(`${prefix}/*`, handler);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Register a multi-prefix lazy family on `app` at explicit `paths` (loader
|
|
70
|
+
* returns ABSOLUTE routes). One shared cached/context-bridging handler backs
|
|
71
|
+
* every path. Context-preserving replacement for the starter's
|
|
72
|
+
* `mountLazyRouteApp(...)`.
|
|
73
|
+
*/
|
|
74
|
+
export function mountLazyRoutePaths(app, paths, load) {
|
|
75
|
+
const handler = createLazyRouteHandler("/", load);
|
|
76
|
+
for (const path of paths) {
|
|
77
|
+
app.all(path, handler);
|
|
78
|
+
}
|
|
79
|
+
}
|
package/dist/module.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Extension, Module } from "@voyant-travel/core";
|
|
2
2
|
import type { Hono } from "hono";
|
|
3
|
+
import type { LazyHonoRoutes, LazyRoutesLoader } from "./lazy-routes.js";
|
|
3
4
|
export interface HonoModule {
|
|
4
5
|
module: Module;
|
|
5
6
|
/**
|
|
@@ -14,6 +15,22 @@ export interface HonoModule {
|
|
|
14
15
|
adminRoutes?: Hono<any>;
|
|
15
16
|
/** Customer/partner/supplier-facing routes — mounted at `/v1/public/{module.name}`. */
|
|
16
17
|
publicRoutes?: Hono<any>;
|
|
18
|
+
/**
|
|
19
|
+
* Lazy variant of `adminRoutes` — the route bundle is dynamically imported on
|
|
20
|
+
* first request and cached per isolate. Mounted at `/v1/admin/{module.name}`
|
|
21
|
+
* with the request context bridged in, so it behaves identically to eager
|
|
22
|
+
* `adminRoutes`. Use for heavy route families to protect Worker cold start.
|
|
23
|
+
*/
|
|
24
|
+
lazyAdminRoutes?: LazyRoutesLoader;
|
|
25
|
+
/** Lazy variant of `publicRoutes` — mounted at `/v1/public/{publicPath ?? module.name}`. */
|
|
26
|
+
lazyPublicRoutes?: LazyRoutesLoader;
|
|
27
|
+
/**
|
|
28
|
+
* Deployment-local lazy family spanning explicit absolute path matchers (for
|
|
29
|
+
* route bundles that don't fit a single admin/public surface). The loader
|
|
30
|
+
* returns ABSOLUTE routes; the framework mounts + caches them with the request
|
|
31
|
+
* context bridged in. Context-preserving replacement for `mountLazyRouteApp`.
|
|
32
|
+
*/
|
|
33
|
+
lazyRoutes?: LazyHonoRoutes;
|
|
17
34
|
/**
|
|
18
35
|
* Optional override for the public mount path relative to `/v1/public`.
|
|
19
36
|
*
|
|
@@ -30,6 +47,12 @@ export interface HonoExtension {
|
|
|
30
47
|
adminRoutes?: Hono<any>;
|
|
31
48
|
/** Customer/partner/supplier-facing routes — mounted at `/v1/public/{extension.module}`. */
|
|
32
49
|
publicRoutes?: Hono<any>;
|
|
50
|
+
/** Lazy variant of `adminRoutes` — mounted at `/v1/admin/{extension.module}` (see HonoModule). */
|
|
51
|
+
lazyAdminRoutes?: LazyRoutesLoader;
|
|
52
|
+
/** Lazy variant of `publicRoutes` — mounted at `/v1/public/{publicPath ?? extension.module}`. */
|
|
53
|
+
lazyPublicRoutes?: LazyRoutesLoader;
|
|
54
|
+
/** Deployment-local lazy family at explicit absolute paths (see HonoModule). */
|
|
55
|
+
lazyRoutes?: LazyHonoRoutes;
|
|
33
56
|
/**
|
|
34
57
|
* Optional override for the public mount path relative to `/v1/public`.
|
|
35
58
|
*
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd;;;;;;OAMG;IAEH,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,kEAAkE;IAElE,WAAW,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACvB,uFAAuF;IAEvF,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,SAAS,CAAA;IACpB,0DAA0D;IAE1D,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,uEAAuE;IAEvE,WAAW,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACvB,4FAA4F;IAE5F,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB"}
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd;;;;;;OAMG;IAEH,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,kEAAkE;IAElE,WAAW,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACvB,uFAAuF;IAEvF,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACxB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAAA;IAClC,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,cAAc,CAAA;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,SAAS,CAAA;IACpB,0DAA0D;IAE1D,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,uEAAuE;IAEvE,WAAW,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACvB,4FAA4F;IAE5F,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACxB,kGAAkG;IAClG,eAAe,CAAC,EAAE,gBAAgB,CAAA;IAClC,iGAAiG;IACjG,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,gFAAgF;IAChF,UAAU,CAAC,EAAE,cAAc,CAAA;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyant-travel/hono",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.111.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -121,17 +121,17 @@
|
|
|
121
121
|
"zod": "^4.3.6",
|
|
122
122
|
"@voyant-travel/core": "^0.109.0",
|
|
123
123
|
"@voyant-travel/db": "^0.108.1",
|
|
124
|
-
"@voyant-travel/storage": "^0.
|
|
124
|
+
"@voyant-travel/storage": "^0.105.0",
|
|
125
125
|
"@voyant-travel/types": "^0.104.5",
|
|
126
126
|
"@voyant-travel/utils": "^0.105.2",
|
|
127
|
-
"@voyant-travel/workflows": "^0.109.
|
|
127
|
+
"@voyant-travel/workflows": "^0.109.2"
|
|
128
128
|
},
|
|
129
129
|
"devDependencies": {
|
|
130
130
|
"@cloudflare/workers-types": "^4.20260426.1",
|
|
131
131
|
"typescript": "^6.0.2",
|
|
132
132
|
"vitest": "^4.1.2",
|
|
133
133
|
"@voyant-travel/voyant-typescript-config": "^0.1.0",
|
|
134
|
-
"@voyant-travel/workflows-orchestrator": "^0.109.
|
|
134
|
+
"@voyant-travel/workflows-orchestrator": "^0.109.2"
|
|
135
135
|
},
|
|
136
136
|
"files": [
|
|
137
137
|
"dist"
|