Multitenancy Support
View SourceAshTypescript provides automatic tenant parameter handling for multitenant resources. This is commonly used in SaaS applications where each customer or organization needs isolated data access.
Overview
When a resource is configured with Ash multitenancy (using either :attribute or :context strategy), AshTypescript can automatically add tenant parameters to generated TypeScript function signatures, ensuring type-safe tenant isolation at compile time.
Configuration
The require_tenant_parameters setting controls how tenants are provided:
# config/config.exs
config :ash_typescript, require_tenant_parameters: trueWhen true (explicit tenants):
- Tenant must be provided as a parameter in every RPC call
- TypeScript enforces tenant parameter at compile time
- Best for frontend applications that manage tenant context in state
When false (default - implicit tenants):
- Tenant is extracted from the Phoenix connection (e.g., from session, JWT claims, or custom plug)
- No tenant parameter in TypeScript function signatures
Explicit Tenant Parameters
With require_tenant_parameters: true, tenant parameters are automatically added to all RPC function signatures:
// Tenant parameter required in function signature
const projects = await listProjects({
fields: ["id", "name", "status"],
tenant: "acme-corp" // Organization identifier
});
const invoice = await createInvoice({
input: {
customerId: "cust-456",
amount: 1500
},
fields: ["id", "invoiceNumber"],
tenant: "acme-corp"
});Type Safety
When enabled, the tenant parameter is enforced at the TypeScript level:
// TypeScript enforces tenant parameter
const projects = await listProjects({
fields: ["id", "name"]
// ❌ TypeScript Error: Property 'tenant' is missing
});
const projects = await listProjects({
fields: ["id", "name"],
tenant: "acme-corp" // ✅ Correct
});How It Works
When you configure a resource with multitenancy in Ash (see the Ash Multitenancy Guide), AshTypescript automatically detects this and handles tenant parameters appropriately based on your configuration.
When calling RPC actions with require_tenant_parameters: true, the tenant value is passed to Ash and applied according to your resource's multitenancy strategy (:attribute or :context):
// Tenant is automatically applied by Ash based on your resource configuration
const projects = await listProjects({
fields: ["id", "name"],
tenant: "acme-corp"
});Channel-based RPC
When using Phoenix channels, tenant parameters work identically to HTTP-based RPC:
import { listProjectsChannel } from './ash_rpc';
import { Channel } from "phoenix";
listProjectsChannel({
channel: myChannel,
fields: ["id", "name", "status"],
tenant: "acme-corp", // Tenant parameter required
resultHandler: (result) => {
if (result.success) {
console.log("Projects:", result.data);
}
}
});The tenant is included in the channel message payload and enforced server-side.
See Also
- Phoenix Channels - Learn about channel-based RPC
- Configuration Reference - View all configuration options
- Ash Multitenancy Guide - Understand Ash multitenancy strategies in depth