@voyant-travel/hono 0.116.2 → 0.117.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +27 -5
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +24 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/openapi-validation.d.ts +20 -0
- package/dist/openapi-validation.d.ts.map +1 -0
- package/dist/openapi-validation.js +26 -0
- package/dist/openapi.d.ts +90 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +114 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +12 -0
- package/package.json +10 -4
package/dist/app.d.ts
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import { type LazyRoutesLoader } from "./lazy-routes.js";
|
|
2
3
|
import type { VoyantAppConfig, VoyantBindings, VoyantVariables } from "./types.js";
|
|
4
|
+
/** The composed app's Hono env (bindings + framework request variables). */
|
|
5
|
+
type MountEnv<TBindings extends VoyantBindings> = {
|
|
6
|
+
Bindings: TBindings;
|
|
7
|
+
Variables: VoyantVariables;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A lazy route family recorded at mount time so a build-time OpenAPI generator
|
|
11
|
+
* can eager-load it and merge its `.openapi()` operations (voyant#2114). Mirrors
|
|
12
|
+
* `LazyMount` in `./openapi.ts` (kept structurally identical, but declared here
|
|
13
|
+
* to avoid pulling the build-time-only openapi module into the runtime path).
|
|
14
|
+
*/
|
|
15
|
+
export interface LazyMount {
|
|
16
|
+
/** Absolute surface mount prefix, or `"/"` for absolute `lazyRoutes`. */
|
|
17
|
+
prefix: string;
|
|
18
|
+
load: LazyRoutesLoader;
|
|
19
|
+
}
|
|
3
20
|
/**
|
|
4
21
|
* App handle returned alongside the Hono instance. Carries `ready()` for
|
|
5
22
|
* headless / sibling-process deployments that need to fire the lazy
|
|
@@ -35,6 +52,13 @@ export interface VoyantAppExtensions<TBindings = unknown> {
|
|
|
35
52
|
* await withDbFromEnv(env, (db) => drainOutbox(db, app.eventBus))
|
|
36
53
|
*/
|
|
37
54
|
eventBus: import("@voyant-travel/core").EventBus;
|
|
55
|
+
/**
|
|
56
|
+
* Lazy route families recorded at mount time (the wildcard dispatch stubs in
|
|
57
|
+
* `lazy-routes.ts` don't reach the composed `OpenAPIHono` registry). A
|
|
58
|
+
* build-time OpenAPI generator reads this to eager-load + merge their
|
|
59
|
+
* `.openapi()` operations via `mergeLazyOpenApiPaths`. Never read at runtime.
|
|
60
|
+
*/
|
|
61
|
+
lazyMounts: LazyMount[];
|
|
38
62
|
}
|
|
39
63
|
/**
|
|
40
64
|
* Low-level app factory: given an already-resolved `modules`/`extensions` set
|
|
@@ -43,8 +67,6 @@ export interface VoyantAppExtensions<TBindings = unknown> {
|
|
|
43
67
|
* from a manifest + registry + capabilities and delegates here. Use `mountApp`
|
|
44
68
|
* directly only when you have the resolved set in hand (tests, advanced hosts).
|
|
45
69
|
*/
|
|
46
|
-
export declare function mountApp<TBindings extends VoyantBindings>(config: VoyantAppConfig<TBindings>): Hono<
|
|
47
|
-
|
|
48
|
-
Variables: VoyantVariables;
|
|
49
|
-
}> & VoyantAppExtensions<TBindings>;
|
|
70
|
+
export declare function mountApp<TBindings extends VoyantBindings>(config: VoyantAppConfig<TBindings>): Hono<MountEnv<TBindings>> & VoyantAppExtensions<TBindings>;
|
|
71
|
+
export {};
|
|
50
72
|
//# sourceMappingURL=app.d.ts.map
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAQhC,OAAO,EAAE,KAAK,gBAAgB,EAA0C,MAAM,kBAAkB,CAAA;AA0BhG,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAY,eAAe,EAAE,MAAM,YAAY,CAAA;AAI5F,4EAA4E;AAC5E,KAAK,QAAQ,CAAC,SAAS,SAAS,cAAc,IAAI;IAChD,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,EAAE,eAAe,CAAA;CAC3B,CAAA;AAuBD;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,gBAAgB,CAAA;CACvB;AAED;;;;;;;;;;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;IAChD;;;;;OAKG;IACH,UAAU,EAAE,SAAS,EAAE,CAAA;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,SAAS,SAAS,cAAc,EACvD,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,GACjC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAsf5D"}
|
package/dist/app.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
// agent-quality: file-size exception — app.ts is the framework composition root;
|
|
2
|
+
// splitting it is intentional follow-up work, not part of voyant#2114.
|
|
3
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
1
4
|
import { createContainer, createEventBus, createQueryRunner, } from "@voyant-travel/core";
|
|
2
5
|
import { createOutboxEventStore } from "@voyant-travel/db/outbox";
|
|
3
|
-
import { Hono } from "hono";
|
|
4
6
|
import { assembleAnonymousPaths } from "./anonymous-paths.js";
|
|
5
7
|
import { containerToServiceResolver, makeFrameworkLogger, wireWorkflowRuntime, } from "./app-workflows.js";
|
|
6
8
|
import { mountLazyRoutePaths, mountLazyRoutesAt } from "./lazy-routes.js";
|
|
@@ -45,7 +47,13 @@ function buildRateLimitPolicy(config, env, bucket, defaults) {
|
|
|
45
47
|
* directly only when you have the resolved set in hand (tests, advanced hosts).
|
|
46
48
|
*/
|
|
47
49
|
export function mountApp(config) {
|
|
48
|
-
|
|
50
|
+
// Composed root is an OpenAPIHono (a drop-in Hono superclass) so module routes
|
|
51
|
+
// authored with `.openapi()` register here and the spec can be generated via
|
|
52
|
+
// `@voyant-travel/hono/openapi` at build time. The doc *generator*
|
|
53
|
+
// (`@asteasolutions/zod-to-openapi` + `openapi3-ts`) is only reachable through
|
|
54
|
+
// `getOpenAPIDocument`, so it tree-shakes out of the Worker bundle; the
|
|
55
|
+
// OpenAPIHono registry + validator glue (~35 KB) is the only runtime cost.
|
|
56
|
+
const app = new OpenAPIHono();
|
|
49
57
|
// Observability sink (RFC #1553) — resolved once and reused by both the
|
|
50
58
|
// outer onError and the forwarded auth sub-app catch point below.
|
|
51
59
|
const reporter = config.reporter ?? noopReporter;
|
|
@@ -408,6 +416,13 @@ export function mountApp(config) {
|
|
|
408
416
|
scopes: c.get("scopes"),
|
|
409
417
|
}));
|
|
410
418
|
}
|
|
419
|
+
// Lazy route families recorded for build-time OpenAPI merging. The wildcard
|
|
420
|
+
// dispatch stubs registered by `mountLazyRoutesAt`/`mountLazyRoutePaths` never
|
|
421
|
+
// reach the composed OpenAPIHono registry, so the spec generator replays these
|
|
422
|
+
// loaders (see `mergeLazyOpenApiPaths`). Recorded in the same loop that mounts
|
|
423
|
+
// them so the prefix logic is single-sourced here. Cheap array pushes — no
|
|
424
|
+
// eager `import()` and no runtime read.
|
|
425
|
+
const lazyMounts = [];
|
|
411
426
|
// Mount module routes
|
|
412
427
|
for (const mod of allModules) {
|
|
413
428
|
const adminPrefix = `/v1/admin/${mod.module.name}`;
|
|
@@ -420,12 +435,15 @@ export function mountApp(config) {
|
|
|
420
435
|
}
|
|
421
436
|
if (mod.lazyAdminRoutes) {
|
|
422
437
|
mountLazyRoutesAt(app, adminPrefix, mod.lazyAdminRoutes);
|
|
438
|
+
lazyMounts.push({ prefix: adminPrefix, load: mod.lazyAdminRoutes });
|
|
423
439
|
}
|
|
424
440
|
if (mod.lazyPublicRoutes) {
|
|
425
441
|
mountLazyRoutesAt(app, publicPrefix, mod.lazyPublicRoutes);
|
|
442
|
+
lazyMounts.push({ prefix: publicPrefix, load: mod.lazyPublicRoutes });
|
|
426
443
|
}
|
|
427
444
|
if (mod.lazyRoutes) {
|
|
428
445
|
mountLazyRoutePaths(app, mod.lazyRoutes.paths, mod.lazyRoutes.load);
|
|
446
|
+
lazyMounts.push({ prefix: "/", load: mod.lazyRoutes.load });
|
|
429
447
|
}
|
|
430
448
|
if (mod.routes) {
|
|
431
449
|
app.route(`/v1/${mod.module.name}`, mod.routes);
|
|
@@ -443,12 +461,15 @@ export function mountApp(config) {
|
|
|
443
461
|
}
|
|
444
462
|
if (ext.lazyAdminRoutes) {
|
|
445
463
|
mountLazyRoutesAt(app, adminPrefix, ext.lazyAdminRoutes);
|
|
464
|
+
lazyMounts.push({ prefix: adminPrefix, load: ext.lazyAdminRoutes });
|
|
446
465
|
}
|
|
447
466
|
if (ext.lazyPublicRoutes) {
|
|
448
467
|
mountLazyRoutesAt(app, publicPrefix, ext.lazyPublicRoutes);
|
|
468
|
+
lazyMounts.push({ prefix: publicPrefix, load: ext.lazyPublicRoutes });
|
|
449
469
|
}
|
|
450
470
|
if (ext.lazyRoutes) {
|
|
451
471
|
mountLazyRoutePaths(app, ext.lazyRoutes.paths, ext.lazyRoutes.load);
|
|
472
|
+
lazyMounts.push({ prefix: "/", load: ext.lazyRoutes.load });
|
|
452
473
|
}
|
|
453
474
|
if (ext.routes) {
|
|
454
475
|
app.route(`/v1/${ext.extension.module}`, ext.routes);
|
|
@@ -468,6 +489,7 @@ export function mountApp(config) {
|
|
|
468
489
|
// the real `env`.
|
|
469
490
|
const augmented = app;
|
|
470
491
|
augmented.eventBus = eventBus;
|
|
492
|
+
augmented.lazyMounts = lazyMounts;
|
|
471
493
|
augmented.ready = (bindings) => ensureRuntimeBootstrapped(bindings ?? {});
|
|
472
494
|
return augmented;
|
|
473
495
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { clientIpKey, consoleLoggerProvider, cors, DEFAULT_IDEMPOTENCY_TTL_MS, d
|
|
|
12
12
|
export type { HonoExtension, HonoModule } from "./module.js";
|
|
13
13
|
export type { ErrorEvent, Reporter } from "./observability/index.js";
|
|
14
14
|
export { consoleReporter, getRequestId, noopReporter, runWithRequestId, safeCaptureException, } from "./observability/index.js";
|
|
15
|
+
export { openApiValidationHook } from "./openapi-validation.js";
|
|
15
16
|
export type { ExpandedHonoBundles, ExpandedHonoPlugins, HonoBundle, HonoPlugin, } from "./plugin.js";
|
|
16
17
|
export { defineHonoBundle, defineHonoPlugin, expandHonoBundles, expandHonoPlugins, } from "./plugin.js";
|
|
17
18
|
export type { CreatePublicCapabilityOptions, PublicCapabilityCookieOptions, PublicCapabilityPayload, VerifyPublicCapabilityOptions, } from "./public-capability.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { createLazyRouteHandler, mountLazyRoutePaths, mountLazyRoutesAt, } from
|
|
|
7
7
|
export { createPathDbSelector } from "./lib/db-selector.js";
|
|
8
8
|
export { clientIpKey, consoleLoggerProvider, cors, DEFAULT_IDEMPOTENCY_TTL_MS, db, enforceRateLimit, errorBoundary, handleApiError, idempotencyKey, isStaffRbacEnforced, LIVE_LIMITS, logger, purgeExpiredIdempotencyKeys, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
9
9
|
export { consoleReporter, getRequestId, noopReporter, runWithRequestId, safeCaptureException, } from "./observability/index.js";
|
|
10
|
+
export { openApiValidationHook } from "./openapi-validation.js";
|
|
10
11
|
export { defineHonoBundle, defineHonoPlugin, expandHonoBundles, expandHonoPlugins, } from "./plugin.js";
|
|
11
12
|
export { createPublicCapabilityToken, extractPublicCapabilityToken, serializePublicCapabilityCookie, verifyPublicCapabilityToken, } from "./public-capability.js";
|
|
12
13
|
export { createDrizzlePublicDocumentDeliveryGrantStore, createPublicDocumentDeliveryGrant, createPublicDocumentDeliveryHonoModule, createPublicDocumentDeliveryRoutes, resolvePublicDocumentDeliveryGrant, revokePublicDocumentDeliveryGrant, } from "./public-document-delivery.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Hook } from "@hono/zod-openapi";
|
|
2
|
+
/**
|
|
3
|
+
* Shared `OpenAPIHono` `defaultHook` (voyant#2114).
|
|
4
|
+
*
|
|
5
|
+
* `@hono/zod-openapi` validates `request` schemas before the handler runs;
|
|
6
|
+
* without a hook it returns `@hono/zod-validator`'s raw `safeParse` result as a
|
|
7
|
+
* bare 400, bypassing the framework's `parseQuery`/`parseJsonBody` path and the
|
|
8
|
+
* shared `{ error, code: "invalid_request", requestId, details }` contract that
|
|
9
|
+
* clients and the error-boundary rely on. This hook re-routes failures through
|
|
10
|
+
* the same `RequestValidationError` so `.openapi()` routes stay on-contract.
|
|
11
|
+
*
|
|
12
|
+
* Every module that constructs an `OpenAPIHono` must pass it:
|
|
13
|
+
*
|
|
14
|
+
* new OpenAPIHono<Env>({ defaultHook: openApiValidationHook })
|
|
15
|
+
*
|
|
16
|
+
* (Validation runs on the instance that owns the route, so a hook on the
|
|
17
|
+
* composed root app does NOT cover mounted module sub-apps.)
|
|
18
|
+
*/
|
|
19
|
+
export declare const openApiValidationHook: Hook<any, any, any, unknown>;
|
|
20
|
+
//# sourceMappingURL=openapi-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-validation.d.ts","sourceRoot":"","sources":["../src/openapi-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAG7C;;;;;;;;;;;;;;;;GAgBG;AAIH,eAAO,MAAM,qBAAqB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAI9D,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { normalizeValidationError, RequestValidationError } from "./validation.js";
|
|
2
|
+
/**
|
|
3
|
+
* Shared `OpenAPIHono` `defaultHook` (voyant#2114).
|
|
4
|
+
*
|
|
5
|
+
* `@hono/zod-openapi` validates `request` schemas before the handler runs;
|
|
6
|
+
* without a hook it returns `@hono/zod-validator`'s raw `safeParse` result as a
|
|
7
|
+
* bare 400, bypassing the framework's `parseQuery`/`parseJsonBody` path and the
|
|
8
|
+
* shared `{ error, code: "invalid_request", requestId, details }` contract that
|
|
9
|
+
* clients and the error-boundary rely on. This hook re-routes failures through
|
|
10
|
+
* the same `RequestValidationError` so `.openapi()` routes stay on-contract.
|
|
11
|
+
*
|
|
12
|
+
* Every module that constructs an `OpenAPIHono` must pass it:
|
|
13
|
+
*
|
|
14
|
+
* new OpenAPIHono<Env>({ defaultHook: openApiValidationHook })
|
|
15
|
+
*
|
|
16
|
+
* (Validation runs on the instance that owns the route, so a hook on the
|
|
17
|
+
* composed root app does NOT cover mounted module sub-apps.)
|
|
18
|
+
*/
|
|
19
|
+
// Typed as the library's own `defaultHook` shape (`Hook<any, E, any, any>`) so
|
|
20
|
+
// it stays assignable for every module's specific `OpenAPIHono<Env>`.
|
|
21
|
+
// biome-ignore lint/suspicious/noExplicitAny: matches @hono/zod-openapi's defaultHook signature
|
|
22
|
+
export const openApiValidationHook = (result) => {
|
|
23
|
+
if (!result.success) {
|
|
24
|
+
throw normalizeValidationError(result.error) ?? new RequestValidationError("Invalid request");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
+
import type { Hono } from "hono";
|
|
3
|
+
import type { LazyRoutesLoader } from "./lazy-routes.js";
|
|
4
|
+
/**
|
|
5
|
+
* OpenAPI document generation for composed Voyant apps (voyant#2114).
|
|
6
|
+
*
|
|
7
|
+
* The app returned by `createApp`/`mountApp` is an `OpenAPIHono` under the hood
|
|
8
|
+
* (typed as `Hono` for callers), so the helpers here cast to reach
|
|
9
|
+
* `getOpenAPIDocument`. Only routes authored via `createRoute(...).openapi(...)`
|
|
10
|
+
* contribute operations — plain routes are absent until migrated.
|
|
11
|
+
*
|
|
12
|
+
* Import these from `@voyant-travel/hono/openapi`, never from the package
|
|
13
|
+
* barrel: `getOpenAPIDocument` pulls in `@asteasolutions/zod-to-openapi`, which
|
|
14
|
+
* must stay out of the Worker runtime bundle. This module is meant for
|
|
15
|
+
* build-time generation only.
|
|
16
|
+
*/
|
|
17
|
+
export interface OpenApiInfo {
|
|
18
|
+
title: string;
|
|
19
|
+
version: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
/** OpenAPI spec extension fields (`x-*`), matching the doc's `InfoObject`. */
|
|
22
|
+
[extension: `x-${string}`]: unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface OpenApiServer {
|
|
25
|
+
url: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
[extension: `x-${string}`]: unknown;
|
|
28
|
+
}
|
|
29
|
+
export interface GenerateOpenApiOptions {
|
|
30
|
+
info: OpenApiInfo;
|
|
31
|
+
servers?: OpenApiServer[];
|
|
32
|
+
}
|
|
33
|
+
type AnyApp = Hono<any, any, any>;
|
|
34
|
+
/**
|
|
35
|
+
* An OpenAPI 3.1 document, as produced by `OpenAPIHono`. Named via the direct
|
|
36
|
+
* dependency's method type so the inferred type stays portable (TS2883).
|
|
37
|
+
*/
|
|
38
|
+
export type OpenApiDocument = ReturnType<OpenAPIHono["getOpenAPI31Document"]>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate a single OpenAPI 3.1 document covering every `.openapi()` route
|
|
41
|
+
* mounted on the composed app, with module base paths already merged in
|
|
42
|
+
* (honojs/middleware#952).
|
|
43
|
+
*/
|
|
44
|
+
export declare function generateOpenApiDocument(app: AnyApp, options: GenerateOpenApiOptions): OpenApiDocument;
|
|
45
|
+
/**
|
|
46
|
+
* Voyant's two published API surfaces, keyed by path prefix. Admin routes mount
|
|
47
|
+
* under `/v1/admin/*` and storefront/public routes under `/v1/public/*`; the
|
|
48
|
+
* legacy `/v1/*` surface is intentionally excluded from the published docs.
|
|
49
|
+
*/
|
|
50
|
+
export type ApiSurface = "admin" | "storefront";
|
|
51
|
+
/**
|
|
52
|
+
* Narrow a composed document to a single surface by path prefix, producing the
|
|
53
|
+
* `framework-admin` / `framework-storefront` documents that replace the
|
|
54
|
+
* hand-authored specs. Components are carried over verbatim (the generator may
|
|
55
|
+
* over-include shared component schemas, which is harmless).
|
|
56
|
+
*/
|
|
57
|
+
export declare function selectSurface(doc: OpenApiDocument, surface: ApiSurface): OpenApiDocument;
|
|
58
|
+
/**
|
|
59
|
+
* A lazy-mounted route family recorded by `mountApp` for build-time spec
|
|
60
|
+
* merging. `prefix` is the absolute surface mount (`/v1/admin/<name>`,
|
|
61
|
+
* `/v1/public/...`) for relative-route loaders, or `"/"` for absolute
|
|
62
|
+
* `lazyRoutes` loaders. `load` is the same loader the runtime dispatcher caches
|
|
63
|
+
* — it constructs (but does not serve) the sub-app via `import(...)`.
|
|
64
|
+
*/
|
|
65
|
+
export interface LazyMount {
|
|
66
|
+
prefix: string;
|
|
67
|
+
load: LazyRoutesLoader;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Eager-merge lazy route families into a generated base document (voyant#2114).
|
|
71
|
+
*
|
|
72
|
+
* Lazy families mount at runtime as wildcard dispatch stubs (see
|
|
73
|
+
* `lazy-routes.ts`), so their `.openapi()` operations never reach the composed
|
|
74
|
+
* `OpenAPIHono` registry and are invisible to `generateOpenApiDocument`. This
|
|
75
|
+
* runs each loader at build time, and for any that return an `OpenAPIHono`,
|
|
76
|
+
* re-mounts it into a throwaway `OpenAPIHono` at its real prefix — reusing the
|
|
77
|
+
* exact prefix-merge semantics `OpenAPIHono.route(...)` applies to eager mounts
|
|
78
|
+
* — then shallow-merges the resulting `paths` + `components.*` into `base`.
|
|
79
|
+
*
|
|
80
|
+
* Plain `Hono` sub-apps (no `.openapi()` routes) carry no registry and are
|
|
81
|
+
* skipped without error. A loader that throws is skipped with a warning so one
|
|
82
|
+
* bad family can't break generation. `base` wins on path/component collisions
|
|
83
|
+
* (which shouldn't happen given distinct prefixes), with a dev-time warning.
|
|
84
|
+
*
|
|
85
|
+
* Build-time only — same module-level constraint as the rest of this file
|
|
86
|
+
* (`@asteasolutions/zod-to-openapi` stays out of the Worker bundle).
|
|
87
|
+
*/
|
|
88
|
+
export declare function mergeLazyOpenApiPaths(base: OpenApiDocument, mounts: readonly LazyMount[], options: GenerateOpenApiOptions): Promise<OpenApiDocument>;
|
|
89
|
+
export {};
|
|
90
|
+
//# sourceMappingURL=openapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8EAA8E;IAC9E,CAAC,SAAS,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAA;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,CAAC,SAAS,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAA;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAA;IACjB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;CAC1B;AAGD,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAEjC;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAA;AAE7E;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,sBAAsB,GAC9B,eAAe,CASjB;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,YAAY,CAAA;AAO/C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,GAAG,eAAe,CAMxF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,gBAAgB,CAAA;CACvB;AAYD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,eAAe,CAAC,CA8D1B"}
|
package/dist/openapi.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
+
/**
|
|
3
|
+
* Generate a single OpenAPI 3.1 document covering every `.openapi()` route
|
|
4
|
+
* mounted on the composed app, with module base paths already merged in
|
|
5
|
+
* (honojs/middleware#952).
|
|
6
|
+
*/
|
|
7
|
+
export function generateOpenApiDocument(app, options) {
|
|
8
|
+
// The composed app is an `OpenAPIHono` (built in `mountApp`) presented to
|
|
9
|
+
// callers as `Hono`; this build-time seam narrows it back to read the doc.
|
|
10
|
+
const oapi = app;
|
|
11
|
+
return oapi.getOpenAPI31Document({
|
|
12
|
+
openapi: "3.1.0",
|
|
13
|
+
info: options.info,
|
|
14
|
+
...(options.servers ? { servers: options.servers } : {}),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const SURFACE_PREFIX = {
|
|
18
|
+
admin: "/v1/admin",
|
|
19
|
+
storefront: "/v1/public",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Narrow a composed document to a single surface by path prefix, producing the
|
|
23
|
+
* `framework-admin` / `framework-storefront` documents that replace the
|
|
24
|
+
* hand-authored specs. Components are carried over verbatim (the generator may
|
|
25
|
+
* over-include shared component schemas, which is harmless).
|
|
26
|
+
*/
|
|
27
|
+
export function selectSurface(doc, surface) {
|
|
28
|
+
const prefix = SURFACE_PREFIX[surface];
|
|
29
|
+
const paths = Object.fromEntries(Object.entries(doc.paths ?? {}).filter(([path]) => path.startsWith(prefix)));
|
|
30
|
+
return { ...doc, paths };
|
|
31
|
+
}
|
|
32
|
+
/** Detect an `OpenAPIHono` sub-app (carries the `.openapi()` route registry). */
|
|
33
|
+
function isOpenApiHono(value) {
|
|
34
|
+
return (typeof value === "object" &&
|
|
35
|
+
value !== null &&
|
|
36
|
+
typeof value.getOpenAPI31Document === "function" &&
|
|
37
|
+
"openAPIRegistry" in value);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Eager-merge lazy route families into a generated base document (voyant#2114).
|
|
41
|
+
*
|
|
42
|
+
* Lazy families mount at runtime as wildcard dispatch stubs (see
|
|
43
|
+
* `lazy-routes.ts`), so their `.openapi()` operations never reach the composed
|
|
44
|
+
* `OpenAPIHono` registry and are invisible to `generateOpenApiDocument`. This
|
|
45
|
+
* runs each loader at build time, and for any that return an `OpenAPIHono`,
|
|
46
|
+
* re-mounts it into a throwaway `OpenAPIHono` at its real prefix — reusing the
|
|
47
|
+
* exact prefix-merge semantics `OpenAPIHono.route(...)` applies to eager mounts
|
|
48
|
+
* — then shallow-merges the resulting `paths` + `components.*` into `base`.
|
|
49
|
+
*
|
|
50
|
+
* Plain `Hono` sub-apps (no `.openapi()` routes) carry no registry and are
|
|
51
|
+
* skipped without error. A loader that throws is skipped with a warning so one
|
|
52
|
+
* bad family can't break generation. `base` wins on path/component collisions
|
|
53
|
+
* (which shouldn't happen given distinct prefixes), with a dev-time warning.
|
|
54
|
+
*
|
|
55
|
+
* Build-time only — same module-level constraint as the rest of this file
|
|
56
|
+
* (`@asteasolutions/zod-to-openapi` stays out of the Worker bundle).
|
|
57
|
+
*/
|
|
58
|
+
export async function mergeLazyOpenApiPaths(base, mounts, options) {
|
|
59
|
+
const throwaway = new OpenAPIHono();
|
|
60
|
+
let mergedAny = false;
|
|
61
|
+
for (const { prefix, load } of mounts) {
|
|
62
|
+
let subApp;
|
|
63
|
+
try {
|
|
64
|
+
subApp = await load();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
+
console.warn(`[voyant] openapi: lazy loader for "${prefix}" failed, skipping: ${message}`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!isOpenApiHono(subApp)) {
|
|
72
|
+
// Plain Hono (or anything without the registry) contributes no docs.
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
// `route("/", subApp)` reproduces what an absolute-path (`lazyRoutes`)
|
|
76
|
+
// family does at runtime; a relative-surface loader merges at its prefix.
|
|
77
|
+
throwaway.route(prefix === "/" ? "/" : prefix, subApp);
|
|
78
|
+
mergedAny = true;
|
|
79
|
+
}
|
|
80
|
+
if (!mergedAny)
|
|
81
|
+
return base;
|
|
82
|
+
const lazyDoc = throwaway.getOpenAPI31Document({
|
|
83
|
+
openapi: "3.1.0",
|
|
84
|
+
info: options.info,
|
|
85
|
+
...(options.servers ? { servers: options.servers } : {}),
|
|
86
|
+
});
|
|
87
|
+
const paths = { ...(base.paths ?? {}) };
|
|
88
|
+
for (const [path, item] of Object.entries(lazyDoc.paths ?? {})) {
|
|
89
|
+
if (path in paths) {
|
|
90
|
+
console.warn(`[voyant] openapi: lazy path "${path}" collides with an eager route; keeping eager.`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
paths[path] = item;
|
|
94
|
+
}
|
|
95
|
+
const merged = { ...base, paths };
|
|
96
|
+
const lazyComponents = lazyDoc.components;
|
|
97
|
+
if (lazyComponents) {
|
|
98
|
+
const baseComponents = (base.components ?? {});
|
|
99
|
+
const mergedComponents = {};
|
|
100
|
+
const groups = new Set([...Object.keys(baseComponents), ...Object.keys(lazyComponents)]);
|
|
101
|
+
for (const group of groups) {
|
|
102
|
+
const baseGroup = (baseComponents[group] ?? {});
|
|
103
|
+
const lazyGroup = lazyComponents[group] ?? {};
|
|
104
|
+
const combined = { ...lazyGroup };
|
|
105
|
+
for (const [key, value] of Object.entries(baseGroup)) {
|
|
106
|
+
combined[key] = value; // base wins
|
|
107
|
+
}
|
|
108
|
+
mergedComponents[group] = combined;
|
|
109
|
+
}
|
|
110
|
+
;
|
|
111
|
+
merged.components = mergedComponents;
|
|
112
|
+
}
|
|
113
|
+
return merged;
|
|
114
|
+
}
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,KAAK,CAAA;AAI5C,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAGxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAClC;CAQJ;AAED,qBAAa,sBAAuB,SAAQ,YAAY;gBAC1C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQ/D;AAED,qBAAa,oBAAqB,SAAQ,YAAY;gBACxC,OAAO,SAAiB;CAOrC;AAED,qBAAa,iBAAkB,SAAQ,YAAY;gBACrC,OAAO,SAAc;CAOlC;AAqBD,wBAAsB,aAAa,CAAC,CAAC,EACnC,CAAC,EAAE,OAAO,EACV,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACxF,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,CAAC,EAAE,OAAO,EACV,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GACA,OAAO,CAAC,CAAC,CAAC,CAcZ;AAkBD,wBAAgB,UAAU,CAAC,CAAC,EAC1B,CAAC,EAAE,OAAO,EACV,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,OAAO,CAAC,EAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,CAAC,CAMH;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAsBjF"}
|
package/dist/validation.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HTTPException } from "hono/http-exception";
|
|
1
2
|
import { ZodError } from "zod";
|
|
2
3
|
import { DEFAULT_REQUEST_BODY_LIMIT_BYTES } from "./middleware/body-size.js";
|
|
3
4
|
export class ApiHttpError extends Error {
|
|
@@ -102,5 +103,16 @@ export function normalizeValidationError(error) {
|
|
|
102
103
|
if (error instanceof ZodError) {
|
|
103
104
|
return toValidationError(error);
|
|
104
105
|
}
|
|
106
|
+
if (error instanceof HTTPException) {
|
|
107
|
+
// Hono's request validators throw HTTPException before our validation hook
|
|
108
|
+
// runs — most notably HTTPException(400, "Malformed JSON in request body")
|
|
109
|
+
// from the JSON body parser on `.openapi()` routes. Map it onto the
|
|
110
|
+
// framework error contract so bad client input is a structured 4xx, not a
|
|
111
|
+
// 500 (voyant#2114).
|
|
112
|
+
return new ApiHttpError(error.message, {
|
|
113
|
+
status: error.status,
|
|
114
|
+
code: error.status === 400 ? "invalid_request" : undefined,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
105
117
|
return undefined;
|
|
106
118
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyant-travel/hono",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.117.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"import": "./dist/app.js",
|
|
15
15
|
"default": "./dist/app.js"
|
|
16
16
|
},
|
|
17
|
+
"./openapi": {
|
|
18
|
+
"types": "./dist/openapi.d.ts",
|
|
19
|
+
"import": "./dist/openapi.js",
|
|
20
|
+
"default": "./dist/openapi.js"
|
|
21
|
+
},
|
|
17
22
|
"./module": {
|
|
18
23
|
"types": "./dist/module.d.ts",
|
|
19
24
|
"import": "./dist/module.js",
|
|
@@ -126,6 +131,7 @@
|
|
|
126
131
|
}
|
|
127
132
|
},
|
|
128
133
|
"dependencies": {
|
|
134
|
+
"@hono/zod-openapi": "^1.4.0",
|
|
129
135
|
"drizzle-orm": "^0.45.2",
|
|
130
136
|
"hono": "^4.12.10",
|
|
131
137
|
"zod": "^4.3.6",
|
|
@@ -134,14 +140,14 @@
|
|
|
134
140
|
"@voyant-travel/storage": "^0.105.0",
|
|
135
141
|
"@voyant-travel/types": "^0.106.0",
|
|
136
142
|
"@voyant-travel/utils": "^0.105.4",
|
|
137
|
-
"@voyant-travel/workflows": "^0.111.
|
|
143
|
+
"@voyant-travel/workflows": "^0.111.9"
|
|
138
144
|
},
|
|
139
145
|
"devDependencies": {
|
|
140
146
|
"@cloudflare/workers-types": "^4.20260426.1",
|
|
141
147
|
"typescript": "^6.0.2",
|
|
142
148
|
"vitest": "^4.1.2",
|
|
143
|
-
"@voyant-travel/
|
|
144
|
-
"@voyant-travel/
|
|
149
|
+
"@voyant-travel/workflows-orchestrator": "^0.111.9",
|
|
150
|
+
"@voyant-travel/voyant-typescript-config": "^0.1.0"
|
|
145
151
|
},
|
|
146
152
|
"files": [
|
|
147
153
|
"dist"
|