@samveys/tenancy
Tenant resolution, scoped ORM queries, per-tenant databases, PostgreSQL row level security
import { currentTenant, enableRowLevelSecurity, requireTenant, runAsTenant, tenancy, tenantCache, … } from '@samveys/tenancy'
Function (9)
currentTenant
Function
The tenant of the current request or job; `undefined` outside tenant context.
function currentTenant(): Tenant | undefined;
Exported from packages/tenancy/src/tenancy.ts
enableRowLevelSecurity
Function
Turns on PostgreSQL row level security for `table`: rows are visible only when `tenant_id = current_setting('app.tenant_id')`. Use `withTenantSession` to set it per transaction. Superusers and table owners bypass RLS unless FORCE is set, so this also forces it.
function enableRowLevelSecurity(db: Database, table: string, column?: string): Promise<void>;
Exported from packages/tenancy/src/tenancy.ts
requireTenant
Function
The current tenant, or SVS_E114 when there is none (fail closed).
function requireTenant(): Tenant;
Exported from packages/tenancy/src/tenancy.ts
runAsTenant
Function
Runs `work` as `tenantId` (queue workers, scheduled tasks). The tenant is looked up again, so a job for a deleted or unknown tenant is refused (SVS_E114) instead of running unscoped.
function runAsTenant<T>(tenantId: string, lookup: TenantLookup, work: () => Promise<T> | T): Promise<T>;
Exported from packages/tenancy/src/tenancy.ts
tenancy
Function
The tenancy plugin: the `tenant` middleware, `ctx.tenant`, and database-per-tenant connections.
function tenancy(options: TenancyOptions): import("@samveys/core").Plugin<TenancyOptions>;
Exported from packages/tenancy/src/tenancy.ts
tenantCache
Function
The cache seen by the current tenant: every key, lock and funnel name is prefixed with the tenant id (`t:<id>:`), so tenants never read each other's entries.
function tenantCache(cache: CacheManager): CacheManager;
Exported from packages/tenancy/src/tenancy.ts
tenantDatabases
Function
Database-per-tenant mode: one manager per tenant, created on first use from `connection(tenant)` and cached. `for()` returns the current tenant's database; `close()` closes every opened one.
function tenantDatabases(connection: NonNullable<TenancyOptions['database']>): {
Exported from packages/tenancy/src/tenancy.ts
tenantScoped
Function
Tenant-scoped access to a model in single-database mode: every query filters on the tenant column, `create()` sets it, and a write naming another tenant is refused with SVS_E115.
function tenantScoped<M extends ModelCtor>(model: M, column?: string): {
Exported from packages/tenancy/src/tenancy.ts
withTenantSession
Function
Runs `work` in a transaction where `app.tenant_id` is the current tenant (`SET LOCAL`).
function withTenantSession<T>(db: Database, work: (trx: Transaction) => Promise<T>): Promise<T>;
Exported from packages/tenancy/src/tenancy.ts
Value (4)
domain
Value
`acme.example.com` → `acme.example.com` (the whole host, for tenants on their own domains).
const domain: () => TenantResolver;
Exported from packages/tenancy/src/tenancy.ts
header
Value
`X-Tenant: acme` (use only behind a gateway that sets it; clients could send any value).
const header: (name?: string) => TenantResolver;
Exported from packages/tenancy/src/tenancy.ts
path
Value
`/t/acme/...` with `prefix: 't'` → `acme`.
const path: (prefix?: string) => TenantResolver;
Exported from packages/tenancy/src/tenancy.ts
subdomain
Value
`acme.app.example.com` with `base: 'app.example.com'` → `acme`. Anything else resolves to nothing.
const subdomain: (base: string) => TenantResolver;
Exported from packages/tenancy/src/tenancy.ts
Interface (2)
TenancyOptions
Interface
No documentation comment.
interface TenancyOptions {
/** Resolvers tried in order: `domain()`, `subdomain()`, `path()`, `header()`. */
readonly resolvers: readonly TenantResolver[];
readonly lookup: TenantLookup;
/** Database per tenant: a connection for the tenant, registered lazily as `tenant:<id>`. */
readonly database?: (tenant: Tenant) => ConnectionConfig;
Exported from packages/tenancy/src/contracts.ts
Tenant
Interface
Public types of `@samveys/tenancy`. Locked once written: change with an ADR.
interface Tenant {
readonly id: string;
/** Optional per-tenant data (plan, settings). */
readonly data?: Readonly<Record<string, unknown>>;
}
Exported from packages/tenancy/src/contracts.ts
Type (2)
TenantLookup
Type
Looks a tenant up by identifier; `undefined` for an unknown tenant (→ 404 SVS_E114).
type TenantLookup = (identifier: string) => Promise<Tenant | undefined> | Tenant | undefined;
Exported from packages/tenancy/src/contracts.ts
TenantResolver
Type
Finds the tenant identifier of a request; `undefined` when the request carries none.
type TenantResolver = (ctx: HttpContext) => string | undefined;
Exported from packages/tenancy/src/contracts.ts