Added auth functionality, initial work with views and field types
This commit is contained in:
115
MULTI_TENANT_MIGRATION.md
Normal file
115
MULTI_TENANT_MIGRATION.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Multi-Tenant Migration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide walks you through migrating existing services from the single-database architecture to the new multi-database per-tenant architecture.
|
||||
|
||||
## Architecture Comparison
|
||||
|
||||
### Before (Single Database)
|
||||
|
||||
```typescript
|
||||
// Single Prisma client, data segregated by tenantId column
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async findUserByEmail(tenantId: string, email: string) {
|
||||
return this.prisma.user.findFirst({
|
||||
where: { tenantId, email },
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### After (Multi-Database)
|
||||
|
||||
```typescript
|
||||
// Dynamic Knex connection per tenant, complete database isolation
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
constructor(private tenantDb: TenantDatabaseService) {}
|
||||
|
||||
async findUserByEmail(tenantId: string, email: string) {
|
||||
const knex = await this.tenantDb.getTenantKnex(tenantId);
|
||||
return User.query(knex).findOne({ email });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Step-by-Step Service Migration Examples
|
||||
|
||||
See full examples in the file for:
|
||||
|
||||
- AuthService migration
|
||||
- RBACService migration
|
||||
- ObjectService migration
|
||||
- Controller updates
|
||||
- Common query patterns
|
||||
- Testing strategies
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Query Patterns
|
||||
|
||||
**Simple Query**
|
||||
|
||||
```typescript
|
||||
// Prisma
|
||||
const user = await this.prisma.user.findUnique({ where: { tenantId, id } });
|
||||
|
||||
// Objection
|
||||
const knex = await this.tenantDb.getTenantKnex(tenantId);
|
||||
const user = await User.query(knex).findById(id);
|
||||
```
|
||||
|
||||
**Query with Relations**
|
||||
|
||||
```typescript
|
||||
// Prisma
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { tenantId, id },
|
||||
include: { roles: { include: { permissions: true } } },
|
||||
});
|
||||
|
||||
// Objection
|
||||
const user = await User.query(knex)
|
||||
.findById(id)
|
||||
.withGraphFetched("roles.permissions");
|
||||
```
|
||||
|
||||
**Create**
|
||||
|
||||
```typescript
|
||||
// Prisma
|
||||
const user = await this.prisma.user.create({ data: { ... } });
|
||||
|
||||
// Objection
|
||||
const user = await User.query(knex).insert({ ... });
|
||||
```
|
||||
|
||||
**Update**
|
||||
|
||||
```typescript
|
||||
// Prisma
|
||||
const user = await this.prisma.user.update({ where: { id }, data: { ... } });
|
||||
|
||||
// Objection
|
||||
const user = await User.query(knex).patchAndFetchById(id, { ... });
|
||||
```
|
||||
|
||||
**Delete**
|
||||
|
||||
```typescript
|
||||
// Prisma
|
||||
await this.prisma.user.delete({ where: { id } });
|
||||
|
||||
// Objection
|
||||
await User.query(knex).deleteById(id);
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [Knex.js Documentation](https://knexjs.org)
|
||||
- [Objection.js Documentation](https://vincit.github.io/objection.js)
|
||||
- [MULTI_TENANT_IMPLEMENTATION.md](./MULTI_TENANT_IMPLEMENTATION.md) - Full implementation details
|
||||
Reference in New Issue
Block a user