@mbc-cqrs-serverless/tenant 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +199 -125
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,15 +1,19 @@
1
1
  ![MBC CQRS serverless framework](https://mbc-cqrs-serverless.mbc-net.com/img/mbc-cqrs-serverless.png)
2
2
 
3
- # MBC CQRS Serverless Framework - Tenant Package
3
+ # @mbc-cqrs-serverless/tenant
4
4
 
5
- ## Description
5
+ [![npm version](https://badge.fury.io/js/@mbc-cqrs-serverless%2Ftenant.svg)](https://www.npmjs.com/package/@mbc-cqrs-serverless/tenant)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
- The Tenant package provides multi-tenancy support for CQRS applications. It manages:
8
+ Multi-tenancy support for the MBC CQRS Serverless framework. Manage tenants, tenant groups, and role-based setting group assignments for enterprise SaaS applications.
9
+
10
+ ## Features
8
11
 
9
12
  - **Tenant Management**: Create, update, and manage tenant entities
10
- - **Tenant Groups**: Organize tenants into logical groups
13
+ - **Tenant Groups**: Organize related entities within tenants
14
+ - **Role-Based Settings**: Assign setting groups to user roles within tenants
15
+ - **Common Tenant**: Shared configuration across all tenants
11
16
  - **Tenant Isolation**: Automatic data isolation between tenants
12
- - **Tenant Settings**: Tenant-specific configuration management
13
17
 
14
18
  ## Installation
15
19
 
@@ -17,201 +21,271 @@ The Tenant package provides multi-tenancy support for CQRS applications. It mana
17
21
  npm install @mbc-cqrs-serverless/tenant
18
22
  ```
19
23
 
20
- ## Usage
21
-
22
- ### Basic Setup
24
+ ## Quick Start
23
25
 
24
- Import and configure the tenant module:
26
+ ### 1. Register the Module
25
27
 
26
28
  ```typescript
27
- import { TenantModule } from '@mbc-cqrs-serverless/tenant';
28
29
  import { Module } from '@nestjs/common';
30
+ import { TenantModule } from '@mbc-cqrs-serverless/tenant';
31
+ import { TenantDataSyncHandler } from './handlers/tenant-data-sync.handler';
29
32
 
30
33
  @Module({
31
34
  imports: [
32
35
  TenantModule.register({
33
- tableName: 'your-tenant-table',
36
+ enableController: true, // Optional: enable REST endpoints
37
+ dataSyncHandlers: [TenantDataSyncHandler], // Optional: custom sync handlers
34
38
  }),
35
39
  ],
36
40
  })
37
41
  export class AppModule {}
38
42
  ```
39
43
 
40
- ### Tenant Operations
41
-
42
- #### Create Tenant
44
+ ### 2. Use the Tenant Service
43
45
 
44
46
  ```typescript
47
+ import { Injectable } from '@nestjs/common';
45
48
  import { TenantService } from '@mbc-cqrs-serverless/tenant';
49
+ import { IInvoke } from '@mbc-cqrs-serverless/core';
46
50
 
47
51
  @Injectable()
48
- export class MyTenantService {
52
+ export class MyService {
49
53
  constructor(private readonly tenantService: TenantService) {}
50
54
 
51
- async createTenant(data: CreateTenantDto) {
52
- return this.tenantService.create({
53
- code: 'TENANT001',
54
- name: 'Acme Corporation',
55
- description: 'Enterprise customer',
56
- attributes: {
57
- plan: 'enterprise',
58
- maxUsers: 100,
55
+ async createTenant(data: any, opts: { invokeContext: IInvoke }) {
56
+ return this.tenantService.createTenant(
57
+ {
58
+ code: 'ACME',
59
+ name: 'Acme Corporation',
60
+ attributes: { plan: 'enterprise', maxUsers: 100 },
59
61
  },
60
- });
62
+ opts,
63
+ );
61
64
  }
62
65
  }
63
66
  ```
64
67
 
65
- #### Get Tenant
68
+ ## API Reference
66
69
 
67
- ```typescript
68
- async getTenant(tenantCode: string) {
69
- return this.tenantService.findByCode(tenantCode);
70
- }
70
+ ### TenantService
71
71
 
72
- async getAllTenants() {
73
- return this.tenantService.findAll();
74
- }
75
- ```
72
+ | Method | Description |
73
+ |--------|-------------|
74
+ | `createTenant(dto, context)` | Create a new tenant |
75
+ | `createCommonTenant(dto, context)` | Create the shared common tenant |
76
+ | `updateTenant(key, dto, context)` | Update tenant properties |
77
+ | `deleteTenant(key, context)` | Soft delete a tenant |
78
+ | `getTenant(key)` | Get tenant by pk/sk |
79
+ | `createTenantGroup(tenantGroupCode, dto, context)` | Create a tenant within a tenant group |
80
+ | `addTenantGroup(dto, context)` | Add a group to tenant role settings |
81
+ | `customizeSettingGroups(dto, context)` | Customize setting group order for a role |
76
82
 
77
- #### Update Tenant
83
+ ### TenantCreateDto
78
84
 
79
- ```typescript
80
- async updateTenant(tenantCode: string, data: UpdateTenantDto) {
81
- return this.tenantService.update(tenantCode, {
82
- name: data.name,
83
- attributes: data.attributes,
84
- });
85
- }
86
- ```
85
+ | Property | Type | Required | Description |
86
+ |----------|------|----------|-------------|
87
+ | `code` | string | Yes | Unique tenant identifier |
88
+ | `name` | string | Yes | Display name |
89
+ | `attributes` | object | No | Custom tenant properties |
90
+
91
+ ### TenantGroupAddDto
92
+
93
+ | Property | Type | Required | Description |
94
+ |----------|------|----------|-------------|
95
+ | `tenantCode` | string | Yes | Target tenant |
96
+ | `role` | string | Yes | User role to configure |
97
+ | `groupId` | string | Yes | Group to add to role settings |
87
98
 
88
- #### Delete Tenant
99
+ ## Usage Examples
100
+
101
+ ### Create Common Tenant
102
+
103
+ Create a shared tenant for common settings:
89
104
 
90
105
  ```typescript
91
- async deleteTenant(tenantCode: string) {
92
- return this.tenantService.delete(tenantCode);
106
+ async createCommonTenant(opts: { invokeContext: IInvoke }) {
107
+ return this.tenantService.createCommonTenant(
108
+ {
109
+ name: 'Common Settings',
110
+ attributes: { description: 'Shared across all tenants' },
111
+ },
112
+ opts,
113
+ );
93
114
  }
94
115
  ```
95
116
 
96
- ### Tenant Groups
97
-
98
- Organize tenants into groups for easier management:
99
-
100
- #### Create Tenant Group
117
+ ### Create Tenant
101
118
 
102
119
  ```typescript
103
- async createTenantGroup(data: CreateGroupDto) {
104
- return this.tenantService.createGroup({
105
- code: 'ENTERPRISE',
106
- name: 'Enterprise Customers',
107
- tenantCodes: ['TENANT001', 'TENANT002'],
108
- });
120
+ async createTenant(dto: CreateTenantDto, opts: { invokeContext: IInvoke }) {
121
+ return this.tenantService.createTenant(
122
+ {
123
+ code: dto.code,
124
+ name: dto.name,
125
+ attributes: {
126
+ plan: dto.plan,
127
+ maxUsers: dto.maxUsers,
128
+ features: dto.features,
129
+ },
130
+ },
131
+ opts,
132
+ );
109
133
  }
110
134
  ```
111
135
 
112
- #### Add Tenant to Group
136
+ ### Update Tenant
113
137
 
114
138
  ```typescript
115
- async addTenantToGroup(groupCode: string, tenantCode: string) {
116
- return this.tenantService.addToGroup({
117
- groupCode,
118
- tenantCode,
119
- });
139
+ async updateTenant(
140
+ tenantCode: string,
141
+ dto: UpdateTenantDto,
142
+ opts: { invokeContext: IInvoke },
143
+ ) {
144
+ const pk = `TENANT#${tenantCode}`;
145
+ const sk = 'TENANT';
146
+
147
+ return this.tenantService.updateTenant(
148
+ { pk, sk },
149
+ { name: dto.name, attributes: dto.attributes },
150
+ opts,
151
+ );
120
152
  }
121
153
  ```
122
154
 
123
- #### Update Tenant Group
155
+ ### Delete Tenant (Soft Delete)
124
156
 
125
157
  ```typescript
126
- async updateTenantGroup(groupCode: string, data: UpdateGroupDto) {
127
- return this.tenantService.updateGroup(groupCode, {
128
- name: data.name,
129
- tenantCodes: data.tenantCodes,
130
- });
158
+ async deleteTenant(tenantCode: string, opts: { invokeContext: IInvoke }) {
159
+ const pk = `TENANT#${tenantCode}`;
160
+ const sk = 'TENANT';
161
+
162
+ return this.tenantService.deleteTenant({ pk, sk }, opts);
131
163
  }
132
164
  ```
133
165
 
134
- ### Tenant Context
166
+ ### Role-Based Setting Groups
135
167
 
136
- Access current tenant in your services:
168
+ Configure which setting groups apply to different user roles:
137
169
 
138
170
  ```typescript
139
- import { TenantContext, InjectTenantContext } from '@mbc-cqrs-serverless/tenant';
171
+ // Add a group to admin role settings
172
+ async addGroupToAdminRole(tenantCode: string, groupId: string, opts: { invokeContext: IInvoke }) {
173
+ return this.tenantService.addTenantGroup(
174
+ {
175
+ tenantCode,
176
+ role: 'admin',
177
+ groupId,
178
+ },
179
+ opts,
180
+ );
181
+ }
140
182
 
141
- @Injectable()
142
- export class OrderService {
143
- constructor(
144
- @InjectTenantContext() private readonly tenantContext: TenantContext
145
- ) {}
146
-
147
- async createOrder(data: CreateOrderDto) {
148
- const tenantCode = this.tenantContext.getTenantCode();
149
- // Order is automatically associated with current tenant
150
- return this.orderRepository.create({
183
+ // Customize the order of setting groups for a role
184
+ async customizeRoleSettings(
185
+ tenantCode: string,
186
+ role: string,
187
+ settingGroups: string[],
188
+ opts: { invokeContext: IInvoke },
189
+ ) {
190
+ return this.tenantService.customizeSettingGroups(
191
+ {
151
192
  tenantCode,
152
- ...data,
153
- });
154
- }
193
+ role,
194
+ settingGroups, // Ordered list of group IDs
195
+ },
196
+ opts,
197
+ );
155
198
  }
156
199
  ```
157
200
 
158
- ### Common Tenant
201
+ ### Create Tenant Group
159
202
 
160
- Create a common tenant for shared data:
203
+ Create a tenant entity within a specific tenant group:
161
204
 
162
205
  ```typescript
163
- async createCommonTenant() {
164
- return this.tenantService.createCommonTenant({
165
- name: 'Common',
166
- description: 'Shared data across all tenants',
167
- });
206
+ async createDepartment(
207
+ tenantGroupCode: string,
208
+ dto: CreateDepartmentDto,
209
+ opts: { invokeContext: IInvoke },
210
+ ) {
211
+ return this.tenantService.createTenantGroup(
212
+ tenantGroupCode,
213
+ {
214
+ code: dto.code,
215
+ name: dto.name,
216
+ attributes: dto.attributes,
217
+ },
218
+ opts,
219
+ );
168
220
  }
169
221
  ```
170
222
 
171
- ## API Reference
223
+ ## Data Model
172
224
 
173
- ### TenantService
225
+ ### Tenant Key Pattern
174
226
 
175
- | Method | Description |
176
- |--------|-------------|
177
- | `create(dto)` | Create new tenant |
178
- | `update(code, dto)` | Update tenant |
179
- | `delete(code)` | Delete tenant |
180
- | `findByCode(code)` | Find tenant by code |
181
- | `findAll()` | Get all tenants |
182
- | `createGroup(dto)` | Create tenant group |
183
- | `updateGroup(code, dto)` | Update tenant group |
184
- | `addToGroup(dto)` | Add tenant to group |
185
- | `removeFromGroup(dto)` | Remove tenant from group |
186
-
187
- ### TenantContext
227
+ ```
228
+ pk: TENANT#[tenantCode]
229
+ sk: TENANT
188
230
 
189
- | Method | Description |
190
- |--------|-------------|
191
- | `getTenantCode()` | Get current tenant code |
192
- | `getTenant()` | Get current tenant entity |
193
- | `isCommonTenant()` | Check if common tenant |
231
+ Example:
232
+ pk: TENANT#ACME
233
+ sk: TENANT
234
+ ```
194
235
 
195
- ## Tenant Data Structure
236
+ ### Tenant Group Key Pattern
196
237
 
197
- ```typescript
198
- interface Tenant {
199
- pk: string; // Partition key
200
- sk: string; // Sort key
201
- code: string; // Unique tenant code
202
- name: string; // Display name
203
- description?: string; // Optional description
204
- attributes?: Record<string, any>; // Custom attributes
205
- createdAt: string; // Creation timestamp
206
- updatedAt: string; // Last update timestamp
238
+ ```
239
+ pk: TENANT#[tenantCode]
240
+ sk: [groupCode]
241
+
242
+ Example:
243
+ pk: TENANT#ACME
244
+ sk: SALES_DEPT
245
+ ```
246
+
247
+ ### Setting Groups Structure
248
+
249
+ Role-based setting groups are stored in tenant attributes:
250
+
251
+ ```json
252
+ {
253
+ "pk": "TENANT#ACME",
254
+ "sk": "TENANT",
255
+ "attributes": {
256
+ "setting": [
257
+ {
258
+ "tenantRole": "admin",
259
+ "groups": ["GROUP#ADMIN", "GROUP#POWER_USER"],
260
+ "setting_groups": ["GROUP#ADMIN", "GROUP#POWER_USER"],
261
+ "setting_groups_mode": "auto"
262
+ },
263
+ {
264
+ "tenantRole": "user",
265
+ "groups": ["GROUP#USER"],
266
+ "setting_groups": ["GROUP#USER"],
267
+ "setting_groups_mode": "customized"
268
+ }
269
+ ]
270
+ }
207
271
  }
208
272
  ```
209
273
 
274
+ ## Related Packages
275
+
276
+ | Package | Description |
277
+ |---------|-------------|
278
+ | [@mbc-cqrs-serverless/core](https://www.npmjs.com/package/@mbc-cqrs-serverless/core) | Core CQRS framework |
279
+ | [@mbc-cqrs-serverless/master](https://www.npmjs.com/package/@mbc-cqrs-serverless/master) | Hierarchical settings with tenant support |
280
+
210
281
  ## Documentation
211
282
 
212
- Visit https://mbc-cqrs-serverless.mbc-net.com/ to view the full documentation.
283
+ Full documentation available at [https://mbc-cqrs-serverless.mbc-net.com/](https://mbc-cqrs-serverless.mbc-net.com/)
284
+
285
+ - [Tenant Service Guide](https://mbc-cqrs-serverless.mbc-net.com/docs/tenant-service)
213
286
 
214
287
  ## License
215
288
 
216
- Copyright &copy; 2024, Murakami Business Consulting, Inc. https://www.mbc-net.com/
217
- This project and sub projects are under the MIT License.
289
+ Copyright © 2024-2025, Murakami Business Consulting, Inc. [https://www.mbc-net.com/](https://www.mbc-net.com/)
290
+
291
+ This project is under the [MIT License](../../LICENSE.txt).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mbc-cqrs-serverless/tenant",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "Multiple tenant management",
5
5
  "keywords": [
6
6
  "mbc",
@@ -44,5 +44,5 @@
44
44
  "dependencies": {
45
45
  "@mbc-cqrs-serverless/core": "^0.1.48-beta.0"
46
46
  },
47
- "gitHead": "4ab967474160873735b8cb816272a7012b8940d5"
47
+ "gitHead": "1870821803cfb045c9c4d6bc18d513fa2558de1c"
48
48
  }