Release Notes
v3.0.0
February 2026
Breaking Changes
Route Names Changes
eSaasRouteNames.Administrationremoved - UseeThemeSharedRouteNames.Administrationfrom@abpjs/theme-sharedinstead.
// Before (v2.9.0)
import { eSaasRouteNames } from '@abpjs/saas';
const admin = eSaasRouteNames.Administration; // ❌ Removed
// After (v3.0.0)
import { eThemeSharedRouteNames } from '@abpjs/theme-shared';
const admin = eThemeSharedRouteNames.Administration; // ✅ Use this instead
New Features
Route Providers
New route configuration system using RoutesService from @abpjs/core:
import { configureRoutes, initializeSaasRoutes, SAAS_ROUTE_CONFIG } from '@abpjs/saas';
import { getRoutesService } from '@abpjs/core';
// Option 1: Use configureRoutes with RoutesService
const routes = getRoutesService();
const addRoutes = configureRoutes(routes);
addRoutes();
// Option 2: Use initializeSaasRoutes helper
initializeSaasRoutes(routes);
// Option 3: Access the route configuration directly
console.log(SAAS_ROUTE_CONFIG);
// { path: '/saas', name: 'Saas::Menu:Saas', iconClass: 'fas fa-building', ... }
Also available as a provider object:
import { SAAS_ROUTE_PROVIDERS } from '@abpjs/saas';
const configure = SAAS_ROUTE_PROVIDERS.useFactory(routes);
configure();
Policy Names
New constants for permission checking:
import { eSaasPolicyNames } from '@abpjs/saas';
// Available policies:
// eSaasPolicyNames.Saas = 'Saas.Tenants || Saas.Editions'
// eSaasPolicyNames.Tenants = 'Saas.Tenants'
// eSaasPolicyNames.Editions = 'Saas.Editions'
Config Options
New SaasConfigOptions interface for module extensibility configuration:
import { SaasConfigOptions, eSaasComponents } from '@abpjs/saas';
const options: SaasConfigOptions = {
entityActionContributors: {
[eSaasComponents.Tenants]: [
(actions) => [...actions, { text: 'Custom Action', icon: 'fa fa-star' }]
]
},
entityPropContributors: {
[eSaasComponents.Tenants]: [
(props) => [...props, { name: 'customField', displayName: 'Custom' }]
]
}
};
Extensions System
New extension tokens and defaults for customizing SaaS components:
Entity Actions - Row-level actions in grids:
import {
EntityAction,
DEFAULT_EDITIONS_ENTITY_ACTIONS,
DEFAULT_TENANTS_ENTITY_ACTIONS,
DEFAULT_SAAS_ENTITY_ACTIONS,
SAAS_ENTITY_ACTION_CONTRIBUTORS,
} from '@abpjs/saas';
Toolbar Actions - Grid toolbar buttons:
import {
ToolbarAction,
DEFAULT_EDITIONS_TOOLBAR_ACTIONS,
DEFAULT_TENANTS_TOOLBAR_ACTIONS,
DEFAULT_SAAS_TOOLBAR_ACTIONS,
SAAS_TOOLBAR_ACTION_CONTRIBUTORS,
} from '@abpjs/saas';
Entity Props - Grid column definitions:
import {
EntityProp,
DEFAULT_EDITIONS_ENTITY_PROPS,
DEFAULT_TENANTS_ENTITY_PROPS,
DEFAULT_SAAS_ENTITY_PROPS,
SAAS_ENTITY_PROP_CONTRIBUTORS,
} from '@abpjs/saas';
Form Props - Create/Edit form fields:
import {
FormProp,
DEFAULT_EDITIONS_CREATE_FORM_PROPS,
DEFAULT_TENANTS_CREATE_FORM_PROPS,
DEFAULT_SAAS_CREATE_FORM_PROPS,
DEFAULT_EDITIONS_EDIT_FORM_PROPS,
DEFAULT_TENANTS_EDIT_FORM_PROPS,
DEFAULT_SAAS_EDIT_FORM_PROPS,
SAAS_CREATE_FORM_PROP_CONTRIBUTORS,
SAAS_EDIT_FORM_PROP_CONTRIBUTORS,
} from '@abpjs/saas';
Extensions Guard
New guard for loading extensions before route activation:
import {
saasExtensionsGuard,
useSaasExtensionsGuard,
SaasExtensionsGuard,
} from '@abpjs/saas';
// Function-based guard
const canActivate = await saasExtensionsGuard();
// React hook
function ProtectedRoute({ children }) {
const { isLoaded, loading } = useSaasExtensionsGuard();
if (loading) return <Loading />;
if (!isLoaded) return <Navigate to="/unauthorized" />;
return children;
}
New Exports
Config Subpackage:
eSaasPolicyNames- Policy name constantsSaasPolicyNameKey- Type for policy name valuesSAAS_ROUTE_CONFIG- Default route configuration objectconfigureRoutes()- Configure routes with custom RoutesServiceinitializeSaasRoutes()- Initialize routes immediatelySAAS_ROUTE_PROVIDERS- Route providers object
Models:
SaasConfigOptions- Configuration options interfaceSaasEntityActionContributors,SaasToolbarActionContributors- Contributor typesSaasEntityPropContributors,SaasCreateFormPropContributors,SaasEditFormPropContributors
Tokens Subpackage:
EntityAction<T>,ToolbarAction<T>,EntityProp<T>,FormProp<T>- Extension interfacesDEFAULT_EDITIONS_ENTITY_ACTIONS,DEFAULT_TENANTS_ENTITY_ACTIONS,DEFAULT_SAAS_ENTITY_ACTIONSDEFAULT_EDITIONS_TOOLBAR_ACTIONS,DEFAULT_TENANTS_TOOLBAR_ACTIONS,DEFAULT_SAAS_TOOLBAR_ACTIONSDEFAULT_EDITIONS_ENTITY_PROPS,DEFAULT_TENANTS_ENTITY_PROPS,DEFAULT_SAAS_ENTITY_PROPSDEFAULT_EDITIONS_CREATE_FORM_PROPS,DEFAULT_TENANTS_CREATE_FORM_PROPS,DEFAULT_SAAS_CREATE_FORM_PROPSDEFAULT_EDITIONS_EDIT_FORM_PROPS,DEFAULT_TENANTS_EDIT_FORM_PROPS,DEFAULT_SAAS_EDIT_FORM_PROPS- Contributor callback types:
EntityActionContributorCallback<T>,ToolbarActionContributorCallback<T>, etc. - Token symbols:
SAAS_ENTITY_ACTION_CONTRIBUTORS,SAAS_TOOLBAR_ACTION_CONTRIBUTORS, etc.
Guards Subpackage:
saasExtensionsGuard()- Async guard functionuseSaasExtensionsGuard()- React hookSaasExtensionsGuard- Class-based guard
v2.9.0
February 2026
- Version alignment with @abpjs/core
v2.7.0
February 2026
New Features
Route Names
New constants for SaaS route names (localization keys):
import { eSaasRouteNames } from '@abpjs/saas';
// Available route names:
// eSaasRouteNames.Saas = 'Saas::Menu:Saas'
// eSaasRouteNames.Tenants = 'Saas::Tenants'
// eSaasRouteNames.Editions = 'Saas::Editions'
Note:
Administrationwas removed in v3.0.0. UseeThemeSharedRouteNames.Administrationfrom@abpjs/theme-sharedinstead.
API Changes
-
eSaasComponents- Changed from TypeScriptenumtoconstobject for better tree-shaking and type inference:// Before (v2.4.0)
enum eSaasComponents {
Editions = 'Saas.EditionsComponent',
// ...
}
// After (v2.7.0)
const eSaasComponents = {
Editions: 'Saas.EditionsComponent',
// ...
} as const;
New Exports
eSaasRouteNames- Constants for route names (localization keys)SaasRouteNameKey- Type for SaaS route name valuesSaasComponentKey- Type for SaaS component key values
v2.4.0
February 2026
New Features
-
SaasService.apiNameproperty - New property for REST API configuration. Defaults to'default'. -
eSaasComponentsenum - New enum for component identifiers, useful for component registration and customization:import { eSaasComponents } from '@abpjs/saas';
// Available components:
// eSaasComponents.Editions = 'Saas.EditionsComponent'
// eSaasComponents.Tenants = 'Saas.TenantsComponent'
Breaking Changes
-
CreateTenantRequestinterface -adminEmailAddressandadminPasswordare now required fields (previously optional):// Before (v2.2.0)
interface CreateTenantRequest {
name: string;
editionId?: string;
adminEmailAddress?: string; // optional
adminPassword?: string; // optional
}
// After (v2.4.0)
interface CreateTenantRequest {
adminEmailAddress: string; // required
adminPassword: string; // required
name: string;
editionId?: string;
} -
UpdateTenantRequesttype - Now usesOmit<Tenant, 'editionName'>pattern, which includes allTenantfields excepteditionName:// Before (v2.2.0)
interface UpdateTenantRequest {
id?: string;
name: string;
editionId?: string;
concurrencyStamp?: string;
}
// After (v2.4.0)
type UpdateTenantRequest = Omit<Tenant, 'editionName'>;
// Includes: id, name, editionId, concurrencyStamp, activationState, activationEndDate, etc.
v2.2.0
February 2026
New Features
- Features Modal Management - Added built-in state management for features modal in both hooks:
useEditionshook:visibleFeatures,featuresProviderKey,onVisibleFeaturesChange(),openFeaturesModal()useTenantshook:visibleFeatures,featuresProviderKey,onVisibleFeaturesChange(),openFeaturesModal()
v2.1.1
February 2026
- Version alignment with @abpjs/core
v2.0.0
January 2026
New Features
-
SaasStateService- New state service for programmatic SaaS operations:Tenant Operations:
dispatchGetTenants(params?)- Fetch tenants and update internal statedispatchGetTenantById(id)- Fetch a single tenant by IDdispatchCreateTenant(body)- Create a new tenantdispatchUpdateTenant(body)- Update an existing tenantdispatchDeleteTenant(id)- Delete a tenantdispatchGetLatestTenants()- Fetch latest tenants (for dashboard widget)
Edition Operations:
dispatchGetEditions(params?)- Fetch editions and update internal statedispatchGetEditionById(id)- Fetch a single edition by IDdispatchCreateEdition(body)- Create a new editiondispatchUpdateEdition(body)- Update an existing editiondispatchDeleteEdition(id)- Delete an edition
Statistics Operations:
dispatchGetUsageStatistics()- Fetch usage statistics
State Getter Methods:
getTenants()/getTenantsTotalCount()- Access cached tenantsgetLatestTenants()- Access cached latest tenantsgetEditions()/getEditionsTotalCount()- Access cached editionsgetUsageStatistics()- Access cached usage statistics
Example
import { SaasStateService } from '@abpjs/saas';
import { RestService } from '@abpjs/core';
const restService = new RestService();
const stateService = new SaasStateService(restService);
// Fetch tenants
await stateService.dispatchGetTenants({ maxResultCount: 10 });
const tenants = stateService.getTenants();
console.log(`Found ${stateService.getTenantsTotalCount()} tenants`);
// Create a new tenant
await stateService.dispatchCreateTenant({
name: 'NewTenant',
adminEmailAddress: 'admin@newtenant.com',
adminPassword: 'Password123!',
editionId: 'edition-id',
});
// Fetch editions
await stateService.dispatchGetEditions();
const editions = stateService.getEditions();
// Get usage statistics
await stateService.dispatchGetUsageStatistics();
const stats = stateService.getUsageStatistics();
v1.0.0
January 2026
- Version alignment with @abpjs/core v1.0.0
v0.7.2 (Initial Release)
Components
-
TenantsComponent - Full tenant management UI with:
- Paginated list with search and sorting
- Create tenant with admin credentials
- Edit tenant with edition assignment
- Delete tenant with confirmation
- Connection string management (shared or separate database)
-
EditionsComponent - Edition management UI with:
- Paginated list with sorting
- Create/edit edition modal
- Delete edition with confirmation
- Usage statistics display
Hooks
-
useTenants - State management for tenants with:
fetchTenants()- Get paginated tenants with edition namescreateTenant()- Create tenant with admin credentialsupdateTenant()- Update tenantdeleteTenant()- Delete tenantgetDefaultConnectionString()- Get tenant's connection stringupdateDefaultConnectionString()- Set separate databasedeleteDefaultConnectionString()- Revert to shared database
-
useEditions - State management for editions with:
fetchEditions()- Get paginated editionscreateEdition()- Create editionupdateEdition()- Update editiondeleteEdition()- Delete editionfetchUsageStatistics()- Get edition usage counts
Services
- SaasService with methods for:
- Tenant CRUD operations
- Edition CRUD operations
- Connection string management
- Usage statistics
Constants
- SAAS_ROUTES - Pre-configured route definitions with policies
TypeScript
- Saas namespace with all types:
Tenant,TenantsResponse,TenantsQueryParamsCreateTenantRequest,UpdateTenantRequestEdition,EditionsResponse,EditionsQueryParamsCreateEditionRequest,UpdateEditionRequestDefaultConnectionStringRequestUsageStatisticsResponseStateinterface for state management