@samveys/tenancy

Resolusi tenant, query ORM per tenant, database per tenant, row level security PostgreSQL

Versi
1.0.35 Nov 2026
Pasang
pnpm add @samveys/tenancy
Dokumentasi
README paket ini

Daftar ini dibaca dari versi 1.0.2; jalankan pnpm sync untuk memperbaruinya.

Import
import { currentTenant, enableRowLevelSecurity, requireTenant, runAsTenant, tenancy, tenantCache, … } from '@samveys/tenancy'

Fungsi (9)

currentTenant Fungsi

The tenant of the current request or job; `undefined` outside tenant context.

function currentTenant(): Tenant | undefined;

Diekspor dari packages/tenancy/src/tenancy.ts

enableRowLevelSecurity Fungsi

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

Diekspor dari packages/tenancy/src/tenancy.ts

requireTenant Fungsi

The current tenant, or SVS_E114 when there is none (fail closed).

function requireTenant(): Tenant;

Diekspor dari packages/tenancy/src/tenancy.ts

runAsTenant Fungsi

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

Diekspor dari packages/tenancy/src/tenancy.ts

tenancy Fungsi

The tenancy plugin: the `tenant` middleware, `ctx.tenant`, and database-per-tenant connections.

function tenancy(options: TenancyOptions): import("@samveys/core").Plugin<TenancyOptions>;

Diekspor dari packages/tenancy/src/tenancy.ts

tenantCache Fungsi

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;

Diekspor dari packages/tenancy/src/tenancy.ts

tenantDatabases Fungsi

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']>): {

Diekspor dari packages/tenancy/src/tenancy.ts

tenantScoped Fungsi

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): {

Diekspor dari packages/tenancy/src/tenancy.ts

withTenantSession Fungsi

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

Diekspor dari packages/tenancy/src/tenancy.ts

Nilai (4)

domain Nilai

`acme.example.com` → `acme.example.com` (the whole host, for tenants on their own domains).

const domain: () => TenantResolver;

Diekspor dari packages/tenancy/src/tenancy.ts

header Nilai

`X-Tenant: acme` (use only behind a gateway that sets it; clients could send any value).

const header: (name?: string) => TenantResolver;

Diekspor dari packages/tenancy/src/tenancy.ts

path Nilai

`/t/acme/...` with `prefix: 't'` → `acme`.

const path: (prefix?: string) => TenantResolver;

Diekspor dari packages/tenancy/src/tenancy.ts

subdomain Nilai

`acme.app.example.com` with `base: 'app.example.com'` → `acme`. Anything else resolves to nothing.

const subdomain: (base: string) => TenantResolver;

Diekspor dari packages/tenancy/src/tenancy.ts

Interface (2)

TenancyOptions Interface

Tidak ada komentar dokumentasi.

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;

Diekspor dari 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>>;
}

Diekspor dari packages/tenancy/src/contracts.ts

Tipe (2)

TenantLookup Tipe

Looks a tenant up by identifier; `undefined` for an unknown tenant (→ 404 SVS_E114).

type TenantLookup = (identifier: string) => Promise<Tenant | undefined> | Tenant | undefined;

Diekspor dari packages/tenancy/src/contracts.ts

TenantResolver Tipe

Finds the tenant identifier of a request; `undefined` when the request carries none.

type TenantResolver = (ctx: HttpContext) => string | undefined;

Diekspor dari packages/tenancy/src/contracts.ts