@voyantjs/hono 0.5.0 → 0.6.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/README.md +12 -2
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +50 -6
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -0
- package/dist/auth/require-user.d.ts +3 -0
- package/dist/auth/require-user.d.ts.map +1 -0
- package/dist/auth/require-user.js +8 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/middleware/error-boundary.d.ts +2 -1
- package/dist/middleware/error-boundary.d.ts.map +1 -1
- package/dist/middleware/error-boundary.js +43 -25
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/middleware/require-permission.d.ts.map +1 -1
- package/dist/middleware/require-permission.js +4 -5
- package/dist/module.d.ts +14 -0
- package/dist/module.d.ts.map +1 -1
- package/dist/plugin.d.ts +25 -14
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +22 -18
- package/dist/types.d.ts +13 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +34 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +86 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @voyantjs/hono
|
|
2
2
|
|
|
3
|
-
Hono transport adapter for Voyant. Provides `createApp()`, middleware, auth
|
|
3
|
+
Hono transport adapter for Voyant. Provides `createApp()`, middleware, auth
|
|
4
|
+
helpers, and plugin expansion for mounting Voyant modules behind a Hono app.
|
|
4
5
|
|
|
5
6
|
## Install
|
|
6
7
|
|
|
@@ -17,10 +18,19 @@ const app = createApp({
|
|
|
17
18
|
db: (env) => getDb(env),
|
|
18
19
|
auth: { handler, resolve },
|
|
19
20
|
modules: [crmModule, productsModule, bookingsModule],
|
|
20
|
-
|
|
21
|
+
extensions: [smartbillFinanceExtension],
|
|
22
|
+
plugins: [
|
|
23
|
+
payloadCmsPlugin({
|
|
24
|
+
/* optional distribution bundle */
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
21
27
|
})
|
|
22
28
|
```
|
|
23
29
|
|
|
30
|
+
Use `modules`, `extensions`, and provider-backed route helpers as the default
|
|
31
|
+
composition surface. Use `plugins` when you want to register a reusable
|
|
32
|
+
distribution bundle that packages those pieces together.
|
|
33
|
+
|
|
24
34
|
The middleware chain is: container → requestId → logger → errorBoundary → CORS → health → auth handler → requireAuth → db → actor guards → module routes.
|
|
25
35
|
|
|
26
36
|
## Exports
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAS3B,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAS3B,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAoBlF,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,CAkI3D"}
|
package/dist/app.js
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
|
-
import { createContainer } from "@voyantjs/core";
|
|
1
|
+
import { createContainer, createEventBus, createQueryRunner } from "@voyantjs/core";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import { requireAuth } from "./middleware/auth.js";
|
|
4
4
|
import { cors } from "./middleware/cors.js";
|
|
5
5
|
import { db } from "./middleware/db.js";
|
|
6
|
-
import {
|
|
6
|
+
import { handleApiError, requestId } from "./middleware/error-boundary.js";
|
|
7
7
|
import { logger } from "./middleware/logger.js";
|
|
8
8
|
import { requireActor } from "./middleware/require-actor.js";
|
|
9
9
|
import { expandHonoPlugins } from "./plugin.js";
|
|
10
|
+
function resolveSurfaceMountPath(prefix, path, fallback) {
|
|
11
|
+
const normalized = path?.trim();
|
|
12
|
+
if (!normalized) {
|
|
13
|
+
return `${prefix}/${fallback}`;
|
|
14
|
+
}
|
|
15
|
+
if (normalized === "/") {
|
|
16
|
+
return prefix;
|
|
17
|
+
}
|
|
18
|
+
return `${prefix}/${normalized.replace(/^\/+|\/+$/g, "")}`;
|
|
19
|
+
}
|
|
10
20
|
export function createApp(config) {
|
|
11
21
|
const app = new Hono();
|
|
22
|
+
app.onError(handleApiError);
|
|
12
23
|
// Expand plugins into their constituent modules/extensions before mounting
|
|
13
24
|
const expanded = config.plugins ? expandHonoPlugins(config.plugins) : null;
|
|
14
25
|
const allModules = [...(config.modules ?? []), ...(expanded?.modules ?? [])];
|
|
15
26
|
const allExtensions = [...(config.extensions ?? []), ...(expanded?.extensions ?? [])];
|
|
27
|
+
const eventBus = config.eventBus ?? createEventBus();
|
|
28
|
+
const query = typeof config.query === "function"
|
|
29
|
+
? config.query
|
|
30
|
+
: config.query
|
|
31
|
+
? createQueryRunner(config.query)
|
|
32
|
+
: undefined;
|
|
16
33
|
// Module container — registered services are resolvable from routes
|
|
17
34
|
const container = createContainer();
|
|
18
35
|
for (const mod of allModules) {
|
|
@@ -20,16 +37,43 @@ export function createApp(config) {
|
|
|
20
37
|
container.register(mod.module.name, mod.module.service);
|
|
21
38
|
}
|
|
22
39
|
}
|
|
40
|
+
for (const sub of expanded?.subscribers ?? []) {
|
|
41
|
+
eventBus.subscribe(sub.event, sub.handler);
|
|
42
|
+
}
|
|
43
|
+
let bootstrapPromise = null;
|
|
44
|
+
function ensureRuntimeBootstrapped(bindings) {
|
|
45
|
+
if (!bootstrapPromise) {
|
|
46
|
+
bootstrapPromise = (async () => {
|
|
47
|
+
const ctx = { bindings, container, eventBus };
|
|
48
|
+
for (const plugin of config.plugins ?? []) {
|
|
49
|
+
await plugin.bootstrap?.(ctx);
|
|
50
|
+
}
|
|
51
|
+
for (const mod of allModules) {
|
|
52
|
+
await mod.module.bootstrap?.(ctx);
|
|
53
|
+
}
|
|
54
|
+
for (const ext of allExtensions) {
|
|
55
|
+
await ext.extension.bootstrap?.(ctx);
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
}
|
|
59
|
+
return bootstrapPromise;
|
|
60
|
+
}
|
|
23
61
|
app.use("*", async (c, next) => {
|
|
24
62
|
c.set("container", container);
|
|
63
|
+
c.set("eventBus", eventBus);
|
|
64
|
+
if (config.link) {
|
|
65
|
+
c.set("link", config.link);
|
|
66
|
+
}
|
|
67
|
+
if (query) {
|
|
68
|
+
c.set("query", query);
|
|
69
|
+
}
|
|
70
|
+
await ensureRuntimeBootstrapped(c.env);
|
|
25
71
|
return next();
|
|
26
72
|
});
|
|
27
73
|
// Request ID header
|
|
28
74
|
app.use("*", requestId);
|
|
29
75
|
// Structured logger
|
|
30
76
|
app.use("*", logger(config.logger));
|
|
31
|
-
// Global error boundary
|
|
32
|
-
app.use("*", errorBoundary);
|
|
33
77
|
// CORS (allowlist via env CORS_ALLOWLIST)
|
|
34
78
|
app.use("*", cors());
|
|
35
79
|
// Health check (public, no auth)
|
|
@@ -55,7 +99,7 @@ export function createApp(config) {
|
|
|
55
99
|
app.route(`/v1/admin/${mod.module.name}`, mod.adminRoutes);
|
|
56
100
|
}
|
|
57
101
|
if (mod.publicRoutes) {
|
|
58
|
-
app.route(
|
|
102
|
+
app.route(resolveSurfaceMountPath("/v1/public", mod.publicPath, mod.module.name), mod.publicRoutes);
|
|
59
103
|
}
|
|
60
104
|
if (mod.routes) {
|
|
61
105
|
app.route(`/v1/${mod.module.name}`, mod.routes);
|
|
@@ -67,7 +111,7 @@ export function createApp(config) {
|
|
|
67
111
|
app.route(`/v1/admin/${ext.extension.module}`, ext.adminRoutes);
|
|
68
112
|
}
|
|
69
113
|
if (ext.publicRoutes) {
|
|
70
|
-
app.route(
|
|
114
|
+
app.route(resolveSurfaceMountPath("/v1/public", ext.publicPath, ext.extension.module), ext.publicRoutes);
|
|
71
115
|
}
|
|
72
116
|
if (ext.routes) {
|
|
73
117
|
app.route(`/v1/${ext.extension.module}`, ext.routes);
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { generateNumericCode, randomBytesHex, sha256Base64Url, sha256Hex, unsignCookie, } from "./crypto.js";
|
|
2
|
+
export { requireUserId } from "./require-user.js";
|
|
2
3
|
export type { SessionAuthContext } from "./session-jwt.js";
|
|
3
4
|
export { extractBearerToken, verifySession } from "./session-jwt.js";
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,SAAS,EACT,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,SAAS,EACT,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/auth/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-user.d.ts","sourceRoot":"","sources":["../../src/auth/require-user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAInC,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAOhD"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export type { VoyantPermission } from "@voyantjs/core";
|
|
2
2
|
export { createApp } from "./app.js";
|
|
3
3
|
export type { SessionAuthContext } from "./auth/index.js";
|
|
4
|
-
export { extractBearerToken, generateNumericCode, randomBytesHex, sha256Base64Url, sha256Hex, unsignCookie, verifySession, } from "./auth/index.js";
|
|
5
|
-
export { consoleLoggerProvider, cors, db, errorBoundary, LIVE_LIMITS, logger, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
4
|
+
export { extractBearerToken, generateNumericCode, randomBytesHex, requireUserId, sha256Base64Url, sha256Hex, unsignCookie, verifySession, } from "./auth/index.js";
|
|
5
|
+
export { consoleLoggerProvider, cors, db, errorBoundary, handleApiError, LIVE_LIMITS, logger, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
6
6
|
export type { HonoExtension, HonoModule } from "./module.js";
|
|
7
|
-
export type { ExpandedHonoPlugins, HonoPlugin } from "./plugin.js";
|
|
8
|
-
export { defineHonoPlugin, expandHonoPlugins } from "./plugin.js";
|
|
9
|
-
export type { DbFactory, LogEntry, LoggerProvider, VoyantAppConfig, VoyantAuthIntegration, VoyantAuthPermissionArgs, VoyantAuthResolveArgs, VoyantBindings, VoyantDb, VoyantExecutionContext, VoyantRequestAuthContext, VoyantVariables, } from "./types.js";
|
|
7
|
+
export type { ExpandedHonoBundles, ExpandedHonoPlugins, HonoBundle, HonoPlugin, } from "./plugin.js";
|
|
8
|
+
export { defineHonoBundle, defineHonoPlugin, expandHonoBundles, expandHonoPlugins, } from "./plugin.js";
|
|
9
|
+
export type { DbFactory, LogEntry, LoggerProvider, VoyantAppConfig, VoyantAuthIntegration, VoyantAuthPermissionArgs, VoyantAuthResolveArgs, VoyantBindings, VoyantDb, VoyantExecutionContext, VoyantQueryRuntime, VoyantRequestAuthContext, VoyantVariables, } from "./types.js";
|
|
10
|
+
export { ApiHttpError, ForbiddenApiError, normalizeValidationError, parseJsonBody, parseOptionalJsonBody, parseQuery, RequestValidationError, UnauthorizedApiError, } from "./validation.js";
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
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,gBAAgB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,qBAAqB,EACrB,IAAI,EACJ,EAAE,EACF,aAAa,EACb,WAAW,EACX,MAAM,EACN,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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,eAAe,EACf,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,qBAAqB,EACrB,IAAI,EACJ,EAAE,EACF,aAAa,EACb,cAAc,EACd,WAAW,EACX,MAAM,EACN,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,SAAS,EACT,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,4 +1,5 @@
|
|
|
1
1
|
export { createApp } from "./app.js";
|
|
2
|
-
export { extractBearerToken, generateNumericCode, randomBytesHex, sha256Base64Url, sha256Hex, unsignCookie, verifySession, } from "./auth/index.js";
|
|
3
|
-
export { consoleLoggerProvider, cors, db, errorBoundary, LIVE_LIMITS, logger, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
4
|
-
export { defineHonoPlugin, expandHonoPlugins } from "./plugin.js";
|
|
2
|
+
export { extractBearerToken, generateNumericCode, randomBytesHex, requireUserId, sha256Base64Url, sha256Hex, unsignCookie, verifySession, } from "./auth/index.js";
|
|
3
|
+
export { consoleLoggerProvider, cors, db, errorBoundary, handleApiError, LIVE_LIMITS, logger, rateLimit, requestId, requireActor, requireAuth, requirePermission, } from "./middleware/index.js";
|
|
4
|
+
export { defineHonoBundle, defineHonoPlugin, expandHonoBundles, expandHonoPlugins, } from "./plugin.js";
|
|
5
|
+
export { ApiHttpError, ForbiddenApiError, normalizeValidationError, parseJsonBody, parseOptionalJsonBody, parseQuery, RequestValidationError, UnauthorizedApiError, } from "./validation.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { MiddlewareHandler } from "hono";
|
|
1
|
+
import type { Context, MiddlewareHandler } from "hono";
|
|
2
2
|
export declare const requestId: MiddlewareHandler;
|
|
3
|
+
export declare function handleApiError(err: unknown, c: Context): Response;
|
|
3
4
|
export declare const errorBoundary: MiddlewareHandler;
|
|
4
5
|
//# sourceMappingURL=error-boundary.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../../src/middleware/error-boundary.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../../src/middleware/error-boundary.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAYtD,eAAO,MAAM,SAAS,EAAE,iBAKvB,CAAA;AAID,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,QAAQ,CA+CjE;AAED,eAAO,MAAM,aAAa,EAAE,iBAM3B,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { apiErrorSchema } from "@voyantjs/types";
|
|
2
|
+
import { normalizeValidationError } from "../validation.js";
|
|
2
3
|
function generateRequestId() {
|
|
3
4
|
const bytes = new Uint8Array(16);
|
|
4
5
|
crypto.getRandomValues(bytes);
|
|
@@ -13,35 +14,52 @@ export const requestId = async (c, next) => {
|
|
|
13
14
|
await next();
|
|
14
15
|
};
|
|
15
16
|
const REDACT_HEADERS = new Set(["authorization", "x-api-key"]);
|
|
17
|
+
export function handleApiError(err, c) {
|
|
18
|
+
const id = c.res.headers.get("X-Request-Id") || generateRequestId();
|
|
19
|
+
const apiError = normalizeValidationError(err);
|
|
20
|
+
const errRecord = err instanceof Object ? err : {};
|
|
21
|
+
const code = apiError?.code ?? (typeof errRecord.code === "string" ? errRecord.code : undefined);
|
|
22
|
+
const status = apiError?.status ?? (typeof errRecord.status === "number" ? errRecord.status : 500);
|
|
23
|
+
const details = apiError?.details ??
|
|
24
|
+
(status < 500 && errRecord.details && typeof errRecord.details === "object"
|
|
25
|
+
? errRecord.details
|
|
26
|
+
: undefined);
|
|
27
|
+
const errorMessage = status < 500
|
|
28
|
+
? (apiError?.message ??
|
|
29
|
+
(typeof errRecord.message === "string" ? errRecord.message : "Bad Request"))
|
|
30
|
+
: "Internal Server Error";
|
|
31
|
+
try {
|
|
32
|
+
const headers = {};
|
|
33
|
+
c.req.raw.headers.forEach((value, key) => {
|
|
34
|
+
const lowerKey = key.toLowerCase();
|
|
35
|
+
headers[lowerKey] = REDACT_HEADERS.has(lowerKey) ? "[redacted]" : value;
|
|
36
|
+
});
|
|
37
|
+
console.error("[API:error]", {
|
|
38
|
+
id,
|
|
39
|
+
status,
|
|
40
|
+
code,
|
|
41
|
+
path: c.req.path,
|
|
42
|
+
method: c.req.method,
|
|
43
|
+
headers,
|
|
44
|
+
err: err instanceof Error ? err.message : String(err),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
/* ignore logging errors */
|
|
49
|
+
}
|
|
50
|
+
const statusCode = status >= 100 && status <= 599 ? status : 500;
|
|
51
|
+
return new Response(JSON.stringify(apiErrorSchema.parse({ error: errorMessage, code, requestId: id, details })), {
|
|
52
|
+
status: statusCode,
|
|
53
|
+
headers: {
|
|
54
|
+
"content-type": "application/json",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
16
58
|
export const errorBoundary = async (c, next) => {
|
|
17
59
|
try {
|
|
18
60
|
await next();
|
|
19
61
|
}
|
|
20
62
|
catch (err) {
|
|
21
|
-
|
|
22
|
-
const errRecord = err instanceof Object ? err : {};
|
|
23
|
-
const code = typeof errRecord.code === "string" ? errRecord.code : undefined;
|
|
24
|
-
const status = typeof errRecord.status === "number" ? errRecord.status : 500;
|
|
25
|
-
try {
|
|
26
|
-
const headers = {};
|
|
27
|
-
c.req.raw.headers.forEach((value, key) => {
|
|
28
|
-
const lowerKey = key.toLowerCase();
|
|
29
|
-
headers[lowerKey] = REDACT_HEADERS.has(lowerKey) ? "[redacted]" : value;
|
|
30
|
-
});
|
|
31
|
-
console.error("[API:error]", {
|
|
32
|
-
id,
|
|
33
|
-
status,
|
|
34
|
-
code,
|
|
35
|
-
path: c.req.path,
|
|
36
|
-
method: c.req.method,
|
|
37
|
-
headers,
|
|
38
|
-
err: err instanceof Error ? err.message : String(err),
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
/* ignore logging errors */
|
|
43
|
-
}
|
|
44
|
-
const statusCode = (status >= 100 && status <= 599 ? status : 500);
|
|
45
|
-
return c.json(apiErrorSchema.parse({ error: "Internal Server Error", code, requestId: id }), statusCode);
|
|
63
|
+
return handleApiError(err, c);
|
|
46
64
|
}
|
|
47
65
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { requireAuth } from "./auth.js";
|
|
2
2
|
export { cors } from "./cors.js";
|
|
3
3
|
export { db } from "./db.js";
|
|
4
|
-
export { errorBoundary, requestId } from "./error-boundary.js";
|
|
4
|
+
export { errorBoundary, handleApiError, requestId } from "./error-boundary.js";
|
|
5
5
|
export { consoleLoggerProvider, logger } from "./logger.js";
|
|
6
6
|
export { LIVE_LIMITS, rateLimit } from "./rate-limit.js";
|
|
7
7
|
export { requireActor } from "./require-actor.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
|
package/dist/middleware/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { requireAuth } from "./auth.js";
|
|
2
2
|
export { cors } from "./cors.js";
|
|
3
3
|
export { db } from "./db.js";
|
|
4
|
-
export { errorBoundary, requestId } from "./error-boundary.js";
|
|
4
|
+
export { errorBoundary, handleApiError, requestId } from "./error-boundary.js";
|
|
5
5
|
export { consoleLoggerProvider, logger } from "./logger.js";
|
|
6
6
|
export { LIVE_LIMITS, rateLimit } from "./rate-limit.js";
|
|
7
7
|
export { requireActor } from "./require-actor.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-permission.d.ts","sourceRoot":"","sources":["../../src/middleware/require-permission.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"require-permission.d.ts","sourceRoot":"","sources":["../../src/middleware/require-permission.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAG7C,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAepG,wBAAgB,iBAAiB,CAAC,SAAS,SAAS,cAAc,EAChE,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,EAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IACL,IAAI,CAAC,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAA;CACxC,GACA,iBAAiB,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,EAAE,eAAe,CAAA;CAC3B,CAAC,CA0CD"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { requireUserId } from "../auth/require-user.js";
|
|
2
|
+
import { ForbiddenApiError } from "../validation.js";
|
|
1
3
|
function hasScope(scopes, permission) {
|
|
2
4
|
if (!scopes || scopes.length === 0)
|
|
3
5
|
return false;
|
|
@@ -17,10 +19,7 @@ export function requirePermission(dbFactory, resource, action, opts) {
|
|
|
17
19
|
if (hasScope(scopes, permission)) {
|
|
18
20
|
return next();
|
|
19
21
|
}
|
|
20
|
-
const userId = c
|
|
21
|
-
if (!userId) {
|
|
22
|
-
return c.json({ error: "Unauthorized" }, 401);
|
|
23
|
-
}
|
|
22
|
+
const userId = requireUserId(c);
|
|
24
23
|
if (!opts?.auth?.hasPermission) {
|
|
25
24
|
return c.json({ error: "No auth permission checker configured" }, 500);
|
|
26
25
|
}
|
|
@@ -41,7 +40,7 @@ export function requirePermission(dbFactory, resource, action, opts) {
|
|
|
41
40
|
permission,
|
|
42
41
|
});
|
|
43
42
|
if (!allowed) {
|
|
44
|
-
|
|
43
|
+
throw new ForbiddenApiError();
|
|
45
44
|
}
|
|
46
45
|
return next();
|
|
47
46
|
};
|
package/dist/module.d.ts
CHANGED
|
@@ -14,6 +14,13 @@ export interface HonoModule {
|
|
|
14
14
|
adminRoutes?: Hono<any>;
|
|
15
15
|
/** Customer/partner/supplier-facing routes — mounted at `/v1/public/{module.name}`. */
|
|
16
16
|
publicRoutes?: Hono<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Optional override for the public mount path relative to `/v1/public`.
|
|
19
|
+
*
|
|
20
|
+
* Defaults to `{module.name}`. Use `"/"` to mount a module directly at the
|
|
21
|
+
* public root and omit the extra module segment.
|
|
22
|
+
*/
|
|
23
|
+
publicPath?: string;
|
|
17
24
|
}
|
|
18
25
|
export interface HonoExtension {
|
|
19
26
|
extension: Extension;
|
|
@@ -23,5 +30,12 @@ export interface HonoExtension {
|
|
|
23
30
|
adminRoutes?: Hono<any>;
|
|
24
31
|
/** Customer/partner/supplier-facing routes — mounted at `/v1/public/{extension.module}`. */
|
|
25
32
|
publicRoutes?: Hono<any>;
|
|
33
|
+
/**
|
|
34
|
+
* Optional override for the public mount path relative to `/v1/public`.
|
|
35
|
+
*
|
|
36
|
+
* Defaults to `{extension.module}`. Use `"/"` to mount an extension directly
|
|
37
|
+
* at the public root and omit the extra module segment.
|
|
38
|
+
*/
|
|
39
|
+
publicPath?: string;
|
|
26
40
|
}
|
|
27
41
|
//# sourceMappingURL=module.d.ts.map
|
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,gBAAgB,CAAA;AACvD,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;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvD,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"}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import type { LinkDefinition, Subscriber } from "@voyantjs/core";
|
|
1
|
+
import type { BootstrapHandler, LinkDefinition, Subscriber } from "@voyantjs/core";
|
|
2
2
|
import type { HonoExtension, HonoModule } from "./module.js";
|
|
3
3
|
/**
|
|
4
|
-
* Hono-flavoured
|
|
4
|
+
* Hono-flavoured bundle contribution surface.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
-
* wrappers that can carry HTTP
|
|
6
|
+
* `@voyantjs/hono` is the default HTTP transport adapter for Voyant. The
|
|
7
|
+
* preferred `HonoBundle` term describes reusable packages that contribute
|
|
8
|
+
* {@link HonoModule} / {@link HonoExtension} wrappers that can carry HTTP
|
|
9
|
+
* routes. `HonoPlugin` remains as a compatibility alias for the same shape.
|
|
9
10
|
*
|
|
10
11
|
* Registered via `createApp({ plugins: [...] })` — the app factory expands
|
|
11
|
-
* each
|
|
12
|
+
* each bundle into the underlying modules, extensions, subscribers, and link
|
|
12
13
|
* definitions before mounting them.
|
|
13
14
|
*/
|
|
14
|
-
export interface
|
|
15
|
-
/** Unique
|
|
15
|
+
export interface HonoBundle {
|
|
16
|
+
/** Unique bundle identifier (e.g. "payload-cms", "bokun"). */
|
|
16
17
|
name: string;
|
|
17
18
|
/** Optional version tag for diagnostics. */
|
|
18
19
|
version?: string;
|
|
20
|
+
/** Optional lazy runtime bootstrap executed once per app/isolate. */
|
|
21
|
+
bootstrap?: BootstrapHandler;
|
|
19
22
|
/** Hono modules (module + routes) contributed by the plugin. */
|
|
20
23
|
modules?: HonoModule[];
|
|
21
24
|
/** Hono extensions (extension + routes) contributed by the plugin. */
|
|
@@ -25,20 +28,28 @@ export interface HonoPlugin {
|
|
|
25
28
|
/** Link definitions contributed by the plugin. */
|
|
26
29
|
links?: LinkDefinition[];
|
|
27
30
|
}
|
|
31
|
+
/** @deprecated Prefer {@link HonoBundle}. */
|
|
32
|
+
export type HonoPlugin = HonoBundle;
|
|
28
33
|
/**
|
|
29
|
-
* Identity helper — returns the
|
|
34
|
+
* Identity helper — returns the bundle unchanged, purely for IDE inference.
|
|
30
35
|
*/
|
|
31
|
-
export declare function
|
|
32
|
-
|
|
36
|
+
export declare function defineHonoBundle<P extends HonoBundle>(bundle: P): P;
|
|
37
|
+
/** @deprecated Prefer {@link defineHonoBundle}. */
|
|
38
|
+
export declare const defineHonoPlugin: typeof defineHonoBundle;
|
|
39
|
+
export interface ExpandedHonoBundles {
|
|
33
40
|
modules: HonoModule[];
|
|
34
41
|
extensions: HonoExtension[];
|
|
35
42
|
subscribers: Subscriber[];
|
|
36
43
|
links: LinkDefinition[];
|
|
37
44
|
}
|
|
45
|
+
/** @deprecated Prefer {@link ExpandedHonoBundles}. */
|
|
46
|
+
export type ExpandedHonoPlugins = ExpandedHonoBundles;
|
|
38
47
|
/**
|
|
39
|
-
* Flatten a list of {@link
|
|
48
|
+
* Flatten a list of {@link HonoBundle} values into their constituent pieces.
|
|
40
49
|
*
|
|
41
|
-
* Throws if two
|
|
50
|
+
* Throws if two bundles declare the same `name`.
|
|
42
51
|
*/
|
|
43
|
-
export declare function
|
|
52
|
+
export declare function expandHonoBundles(bundles: ReadonlyArray<HonoBundle>): ExpandedHonoBundles;
|
|
53
|
+
/** @deprecated Prefer {@link expandHonoBundles}. */
|
|
54
|
+
export declare const expandHonoPlugins: typeof expandHonoBundles;
|
|
44
55
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElF,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,gEAAgE;IAChE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,sEAAsE;IACtE,UAAU,CAAC,EAAE,aAAa,EAAE,CAAA;IAC5B,wEAAwE;IACxE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAC1B,kDAAkD;IAClD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;CACzB;AAED,6CAA6C;AAC7C,MAAM,MAAM,UAAU,GAAG,UAAU,CAAA;AAEnC;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAEnE;AAED,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,yBAAmB,CAAA;AAEhD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,KAAK,EAAE,cAAc,EAAE,CAAA;CACxB;AAED,sDAAsD;AACtD,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAA;AAErD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,mBAAmB,CAoBzF;AAED,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,0BAAoB,CAAA"}
|
package/dist/plugin.js
CHANGED
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Identity helper — returns the
|
|
2
|
+
* Identity helper — returns the bundle unchanged, purely for IDE inference.
|
|
3
3
|
*/
|
|
4
|
-
export function
|
|
5
|
-
return
|
|
4
|
+
export function defineHonoBundle(bundle) {
|
|
5
|
+
return bundle;
|
|
6
6
|
}
|
|
7
|
+
/** @deprecated Prefer {@link defineHonoBundle}. */
|
|
8
|
+
export const defineHonoPlugin = defineHonoBundle;
|
|
7
9
|
/**
|
|
8
|
-
* Flatten a list of {@link
|
|
10
|
+
* Flatten a list of {@link HonoBundle} values into their constituent pieces.
|
|
9
11
|
*
|
|
10
|
-
* Throws if two
|
|
12
|
+
* Throws if two bundles declare the same `name`.
|
|
11
13
|
*/
|
|
12
|
-
export function
|
|
14
|
+
export function expandHonoBundles(bundles) {
|
|
13
15
|
const seen = new Set();
|
|
14
16
|
const modules = [];
|
|
15
17
|
const extensions = [];
|
|
16
18
|
const subscribers = [];
|
|
17
19
|
const links = [];
|
|
18
|
-
for (const
|
|
19
|
-
if (seen.has(
|
|
20
|
-
throw new Error(`Duplicate
|
|
20
|
+
for (const bundle of bundles) {
|
|
21
|
+
if (seen.has(bundle.name)) {
|
|
22
|
+
throw new Error(`Duplicate bundle name: "${bundle.name}"`);
|
|
21
23
|
}
|
|
22
|
-
seen.add(
|
|
23
|
-
if (
|
|
24
|
-
modules.push(...
|
|
25
|
-
if (
|
|
26
|
-
extensions.push(...
|
|
27
|
-
if (
|
|
28
|
-
subscribers.push(...
|
|
29
|
-
if (
|
|
30
|
-
links.push(...
|
|
24
|
+
seen.add(bundle.name);
|
|
25
|
+
if (bundle.modules)
|
|
26
|
+
modules.push(...bundle.modules);
|
|
27
|
+
if (bundle.extensions)
|
|
28
|
+
extensions.push(...bundle.extensions);
|
|
29
|
+
if (bundle.subscribers)
|
|
30
|
+
subscribers.push(...bundle.subscribers);
|
|
31
|
+
if (bundle.links)
|
|
32
|
+
links.push(...bundle.links);
|
|
31
33
|
}
|
|
32
34
|
return { modules, extensions, subscribers, links };
|
|
33
35
|
}
|
|
36
|
+
/** @deprecated Prefer {@link expandHonoBundles}. */
|
|
37
|
+
export const expandHonoPlugins = expandHonoBundles;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { VoyantVariables as CoreVoyantVariables, ModuleContainer, VoyantAuthContext, VoyantPermission } from "@voyantjs/core";
|
|
1
|
+
import type { VoyantVariables as CoreVoyantVariables, EventBus, LinkService, ModuleContainer, QueryGraphContext, QueryRunner, VoyantAuthContext, VoyantPermission } from "@voyantjs/core";
|
|
2
2
|
import type { KVStore } from "@voyantjs/utils/cache";
|
|
3
3
|
import type { NeonHttpDatabase } from "drizzle-orm/neon-http";
|
|
4
4
|
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
5
5
|
import type { Hono } from "hono";
|
|
6
6
|
import type { HonoExtension, HonoModule } from "./module.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { HonoBundle } from "./plugin.js";
|
|
8
8
|
export interface VoyantExecutionContext {
|
|
9
9
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
10
10
|
passThroughOnException?: () => void;
|
|
@@ -22,9 +22,16 @@ export interface VoyantBindings {
|
|
|
22
22
|
CACHE?: KVStore;
|
|
23
23
|
}
|
|
24
24
|
export type VoyantDb = PostgresJsDatabase | NeonHttpDatabase;
|
|
25
|
+
export type VoyantQueryRuntime = QueryRunner;
|
|
25
26
|
export type VoyantVariables = CoreVoyantVariables & {
|
|
26
27
|
db: VoyantDb;
|
|
28
|
+
/** Shared app/runtime container for explicit service resolution. */
|
|
27
29
|
container: ModuleContainer;
|
|
30
|
+
eventBus: EventBus;
|
|
31
|
+
/** Shared cross-module link runtime, when the app wires one in. */
|
|
32
|
+
link?: LinkService;
|
|
33
|
+
/** Shared cross-module query runtime, when the app wires one in. */
|
|
34
|
+
query?: VoyantQueryRuntime;
|
|
28
35
|
};
|
|
29
36
|
export type DbFactory<TBindings extends VoyantBindings = VoyantBindings> = (env: TBindings) => VoyantDb;
|
|
30
37
|
export type VoyantRequestAuthContext = VoyantAuthContext & {
|
|
@@ -60,7 +67,10 @@ export interface VoyantAppConfig<TBindings extends VoyantBindings = VoyantBindin
|
|
|
60
67
|
db: DbFactory<TBindings>;
|
|
61
68
|
modules?: HonoModule[];
|
|
62
69
|
extensions?: HonoExtension[];
|
|
63
|
-
plugins?:
|
|
70
|
+
plugins?: HonoBundle[];
|
|
71
|
+
eventBus?: EventBus;
|
|
72
|
+
link?: LinkService;
|
|
73
|
+
query?: QueryGraphContext | VoyantQueryRuntime;
|
|
64
74
|
auth?: VoyantAuthIntegration<TBindings>;
|
|
65
75
|
publicPaths?: string[];
|
|
66
76
|
logger?: LoggerProvider;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,IAAI,mBAAmB,EACtC,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;IAC/C,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG,kBAAkB,GAAG,gBAAgB,CAAA;AAC5D,MAAM,MAAM,eAAe,GAAG,mBAAmB,GAAG;IAClD,EAAE,EAAE,QAAQ,CAAA;IACZ,SAAS,EAAE,eAAe,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,SAAS,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc,IAAI,CACzE,GAAG,EAAE,SAAS,KACX,QAAQ,CAAA;AAEb,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,GAAG;IACzD,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,qBAAqB,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc;IACtF,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,SAAS,CAAA;IACd,EAAE,EAAE,QAAQ,CAAA;IACZ,GAAG,CAAC,EAAE,sBAAsB,CAAA;CAC7B;AAED,MAAM,WAAW,wBAAwB,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc,CACzF,SAAQ,qBAAqB,CAAC,SAAS,CAAC;IACxC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,IAAI,EAAE,wBAAwB,CAAA;CAC/B;AAED,MAAM,WAAW,qBAAqB,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc;IACtF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK;QAC5B,KAAK,EAAE,CACL,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,SAAS,EACd,GAAG,CAAC,EAAE,sBAAsB,KACzB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAClC,CAAA;IACD,OAAO,CAAC,EAAE,CACR,IAAI,EAAE,qBAAqB,CAAC,SAAS,CAAC,KACnC,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,GAAG,wBAAwB,GAAG,IAAI,CAAA;IAC/E,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;CAC1F;AAED,MAAM,WAAW,eAAe,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc;IAChF,EAAE,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IACxB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAA;IAC5B,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,IAAI,CAAC,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAA;IACvC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE,cAAc,CAAA;IAEvB,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;CAC5C"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import { type ZodType } from "zod";
|
|
3
|
+
export declare class ApiHttpError extends Error {
|
|
4
|
+
readonly status: number;
|
|
5
|
+
readonly code?: string;
|
|
6
|
+
readonly details?: Record<string, unknown>;
|
|
7
|
+
constructor(message: string, options: {
|
|
8
|
+
status: number;
|
|
9
|
+
code?: string;
|
|
10
|
+
details?: Record<string, unknown>;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export declare class RequestValidationError extends ApiHttpError {
|
|
14
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
15
|
+
}
|
|
16
|
+
export declare class UnauthorizedApiError extends ApiHttpError {
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class ForbiddenApiError extends ApiHttpError {
|
|
20
|
+
constructor(message?: string);
|
|
21
|
+
}
|
|
22
|
+
export declare function parseJsonBody<T>(c: Context, schema: ZodType<T>, options?: {
|
|
23
|
+
invalidJsonMessage?: string;
|
|
24
|
+
invalidBodyMessage?: string;
|
|
25
|
+
}): Promise<T>;
|
|
26
|
+
export declare function parseOptionalJsonBody<T>(c: Context, schema: ZodType<T>, options?: {
|
|
27
|
+
defaultValue?: unknown;
|
|
28
|
+
invalidBodyMessage?: string;
|
|
29
|
+
}): Promise<T>;
|
|
30
|
+
export declare function parseQuery<T>(c: Context, schema: ZodType<T>, options?: {
|
|
31
|
+
invalidQueryMessage?: string;
|
|
32
|
+
}): T;
|
|
33
|
+
export declare function normalizeValidationError(error: unknown): ApiHttpError | undefined;
|
|
34
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,KAAK,CAAA;AAE5C,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,CAAA;CAAE,GACrE,OAAO,CAAC,CAAC,CAAC,CAUZ;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;CAC5B,GACA,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED,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,CAUjF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ZodError } from "zod";
|
|
2
|
+
export class ApiHttpError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
details;
|
|
6
|
+
constructor(message, options) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "ApiHttpError";
|
|
9
|
+
this.status = options.status;
|
|
10
|
+
this.code = options.code;
|
|
11
|
+
this.details = options.details;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class RequestValidationError extends ApiHttpError {
|
|
15
|
+
constructor(message, details) {
|
|
16
|
+
super(message, {
|
|
17
|
+
status: 400,
|
|
18
|
+
code: "invalid_request",
|
|
19
|
+
details,
|
|
20
|
+
});
|
|
21
|
+
this.name = "RequestValidationError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class UnauthorizedApiError extends ApiHttpError {
|
|
25
|
+
constructor(message = "Unauthorized") {
|
|
26
|
+
super(message, {
|
|
27
|
+
status: 401,
|
|
28
|
+
code: "unauthorized",
|
|
29
|
+
});
|
|
30
|
+
this.name = "UnauthorizedApiError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class ForbiddenApiError extends ApiHttpError {
|
|
34
|
+
constructor(message = "Forbidden") {
|
|
35
|
+
super(message, {
|
|
36
|
+
status: 403,
|
|
37
|
+
code: "forbidden",
|
|
38
|
+
});
|
|
39
|
+
this.name = "ForbiddenApiError";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function toValidationError(error, fallbackMessage = "Invalid request") {
|
|
43
|
+
return new RequestValidationError(error.issues[0]?.message ?? fallbackMessage, {
|
|
44
|
+
issues: error.issues,
|
|
45
|
+
fields: error.flatten(),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function validate(schema, input, fallbackMessage) {
|
|
49
|
+
const parsed = schema.safeParse(input);
|
|
50
|
+
if (!parsed.success) {
|
|
51
|
+
throw toValidationError(parsed.error, fallbackMessage);
|
|
52
|
+
}
|
|
53
|
+
return parsed.data;
|
|
54
|
+
}
|
|
55
|
+
export async function parseJsonBody(c, schema, options) {
|
|
56
|
+
let input;
|
|
57
|
+
try {
|
|
58
|
+
input = await c.req.json();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
throw new RequestValidationError(options?.invalidJsonMessage ?? "Invalid JSON body");
|
|
62
|
+
}
|
|
63
|
+
return validate(schema, input, options?.invalidBodyMessage);
|
|
64
|
+
}
|
|
65
|
+
export async function parseOptionalJsonBody(c, schema, options) {
|
|
66
|
+
let input;
|
|
67
|
+
try {
|
|
68
|
+
input = await c.req.json();
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
input = options?.defaultValue ?? {};
|
|
72
|
+
}
|
|
73
|
+
return validate(schema, input, options?.invalidBodyMessage);
|
|
74
|
+
}
|
|
75
|
+
export function parseQuery(c, schema, options) {
|
|
76
|
+
return validate(schema, Object.fromEntries(new URL(c.req.url).searchParams), options?.invalidQueryMessage ?? "Invalid query parameters");
|
|
77
|
+
}
|
|
78
|
+
export function normalizeValidationError(error) {
|
|
79
|
+
if (error instanceof ApiHttpError) {
|
|
80
|
+
return error;
|
|
81
|
+
}
|
|
82
|
+
if (error instanceof ZodError) {
|
|
83
|
+
return toValidationError(error);
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/hono",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "FSL-1.1-Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -76,10 +76,11 @@
|
|
|
76
76
|
"dependencies": {
|
|
77
77
|
"drizzle-orm": "^0.45.2",
|
|
78
78
|
"hono": "^4.12.10",
|
|
79
|
-
"
|
|
80
|
-
"@voyantjs/
|
|
81
|
-
"@voyantjs/
|
|
82
|
-
"@voyantjs/
|
|
79
|
+
"zod": "^4.3.6",
|
|
80
|
+
"@voyantjs/core": "0.6.0",
|
|
81
|
+
"@voyantjs/db": "0.6.0",
|
|
82
|
+
"@voyantjs/types": "0.6.0",
|
|
83
|
+
"@voyantjs/utils": "0.6.0"
|
|
83
84
|
},
|
|
84
85
|
"devDependencies": {
|
|
85
86
|
"@cloudflare/workers-types": "^4.20260403.1",
|