release: WRNexusJS 0.3.0
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import type { Context, Middleware } from "./context.ts";
|
||||
|
||||
export interface Tenant {
|
||||
id: string;
|
||||
slug?: string;
|
||||
name?: string;
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export type TenantResolver = (ctx: Context) => Tenant | null | Promise<Tenant | null>;
|
||||
|
||||
export interface TenantMiddlewareOptions {
|
||||
required?: boolean;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export function tenantMiddleware(
|
||||
resolveTenant: TenantResolver,
|
||||
options: TenantMiddlewareOptions = {},
|
||||
): Middleware {
|
||||
return async (ctx, next) => {
|
||||
const tenant = await resolveTenant(ctx);
|
||||
ctx.tenant = tenant ?? undefined;
|
||||
if (!tenant && options.required !== false) {
|
||||
return new Response("Tenant not found", { status: options.status ?? 404 });
|
||||
}
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
export function tenantFromSubdomain(
|
||||
lookup: (slug: string, ctx: Context) => Tenant | null | Promise<Tenant | null>,
|
||||
rootDomains: string[] = [],
|
||||
): TenantResolver {
|
||||
return async (ctx) => {
|
||||
const host = ctx.url.hostname.toLowerCase();
|
||||
const root = rootDomains.find((domain) => host === domain || host.endsWith(`.${domain}`));
|
||||
const slug = root ? host.slice(0, -(root.length + 1)) : host.split(".")[0];
|
||||
if (!slug || slug === host || slug === "www") return null;
|
||||
return lookup(slug, ctx);
|
||||
};
|
||||
}
|
||||
|
||||
export function requireTenant(ctx: Context): Tenant {
|
||||
if (!ctx.tenant)
|
||||
throw new Error("WRN-TENANT-REQUIRED: tenant middleware has not resolved a tenant.");
|
||||
return ctx.tenant;
|
||||
}
|
||||
|
||||
/** Wrap a repository so every operation receives the current tenant id. */
|
||||
export function tenantScope<T extends object>(
|
||||
tenant: Tenant,
|
||||
repository: T,
|
||||
): T & { tenantId: string } {
|
||||
return Object.assign(Object.create(repository), { tenantId: tenant.id });
|
||||
}
|
||||
Reference in New Issue
Block a user