Initial Commit
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
createTenantMiddleware,
|
||||
type TenantResolver,
|
||||
} from "@suaveplan/api-tenant";
|
||||
import type { Context, MiddlewareHandler, Next } from "hono";
|
||||
import { getTenantPluginInstruments } from "../otel/instruments.js";
|
||||
|
||||
/** Options accepted by {@link buildTenantPluginMiddleware}. */
|
||||
export interface BuildTenantPluginMiddlewareOptions {
|
||||
readonly resolver: TenantResolver;
|
||||
readonly required: boolean;
|
||||
readonly allowSuspended: boolean;
|
||||
readonly excludePaths?: readonly string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Hono middleware installed by `createTenantPlugin`'s
|
||||
* `onInit`. Composes `createTenantMiddleware` from `@suaveplan/api-tenant`
|
||||
* with an outer wrapper that records OTel resolution timing + outcome
|
||||
* for every request — even the short-circuited / unresolved paths.
|
||||
*
|
||||
* The inner middleware is the source of truth for `c.set("tenant",
|
||||
* tenant)`, status-gating (deleted/suspended/pending), and the `required`
|
||||
* branch. The wrapper just observes.
|
||||
*/
|
||||
export function buildTenantPluginMiddleware(
|
||||
options: BuildTenantPluginMiddlewareOptions
|
||||
): MiddlewareHandler {
|
||||
const { resolver, required, allowSuspended, excludePaths } = options;
|
||||
const inner = createTenantMiddleware({
|
||||
resolver,
|
||||
required,
|
||||
allowSuspended,
|
||||
...(excludePaths !== undefined ? { excludePaths } : {}),
|
||||
});
|
||||
return async function tenantPluginMiddleware(
|
||||
c: Context,
|
||||
next: Next
|
||||
): Promise<Response | undefined> {
|
||||
const instruments = getTenantPluginInstruments();
|
||||
const start = performance.now();
|
||||
try {
|
||||
const result = await inner(c, next);
|
||||
const elapsed = performance.now() - start;
|
||||
const tenant = c.get("tenant");
|
||||
instruments.resolutionsTotal.add(1, {
|
||||
outcome: tenant !== undefined ? "resolved" : "missing",
|
||||
strategy: resolver.name,
|
||||
});
|
||||
instruments.resolutionDurationMs.record(elapsed, {
|
||||
strategy: resolver.name,
|
||||
});
|
||||
return result ?? undefined;
|
||||
} catch (err) {
|
||||
const elapsed = performance.now() - start;
|
||||
instruments.resolutionsTotal.add(1, {
|
||||
outcome: "error",
|
||||
strategy: resolver.name,
|
||||
});
|
||||
instruments.resolutionDurationMs.record(elapsed, {
|
||||
strategy: resolver.name,
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user