# Universal Repository Pattern

## 🏛️ Universal Repository Pattern

### Three Access Methods

The `PrismaRepository` provides flexible model access:

```typescript
// 1. Dynamic model access - runtime model selection
const modelName = getModelNameFromConfig(); // 'user', 'post', etc.
const builder = repository.model(modelName);
const results = await builder.Where({ isActive: true }).ToArray();

// 2. Direct property access - convenient syntax
const users = await repository.user.Where({ age: { gte: 18 } }).ToArray();
const posts = await repository.post.Include({ user: true }).ToArray();

// 3. Bracket notation - programmatic access
const tableName = 'user';
const data = await repository[tableName].ToArray();
```

### Repository Utilities

```typescript
// Introspection and management
const modelNames = repository.getModelNames();
console.log('Available models:', modelNames); // ['test', 'user', 'post']

// Cache management (useful for testing)
repository.clearCache();

// Direct Prisma client access when needed
const prismaClient = repository.client;
const rawQuery = await prismaClient.$queryRaw`SELECT * FROM users`;
```

### Advanced Repository Patterns

```typescript
@Injectable()
export class AdvancedRepository extends PrismaRepository {
    constructor(databaseService: PrismaCoreService) {
        super(databaseService);
    }

    // Generic repository method
    async findByField<T>(
        modelName: string,
        field: string,
        value: any,
    ): Promise<T[]> {
        const builder = this.model(modelName);
        return await builder.Where({ [field]: value }).ToArray();
    }

    // Cross-model operations
    async getUsersWithPostCount() {
        const users = await this.user.ToEnumerable();

        return await AsyncEnumerable.from(users.ToArray())
            .Select(async (user) => ({
                ...user,
                postCount: await this.post.Where({ userId: user.id }).Count(),
            }))
            .ToArrayAsync();
    }

    // Bulk operations across models (Prisma ORM only)
    async cleanupInactiveData() {
        return await this.user.Transaction(async (tx) => {
            // Delete inactive users and their posts
            const inactiveUsers = await tx
                .Where({ isActive: false })
                .Select({ id: true })
                .ToArray();

            const userIds = inactiveUsers.map((u) => u.id);

            // Delete posts first (foreign key constraint)
            const deletedPosts = await this.post.DeleteMany({
                userId: { in: userIds },
            });

            // Then delete users
            const deletedUsers = await tx.DeleteMany({
                isActive: false,
            });

            return {
                deletedUsers: deletedUsers.count,
                deletedPosts: deletedPosts.count,
            };
        });
    }
}
```

## Next Steps

- [See performance benchmarks](./performance.md)
- [Learn about API reference](./api-reference.md)
- [Check troubleshooting guide](./troubleshooting.md)
