Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -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;
}
};
}