apps/recallassess/recallassess-api/src/api/shared/services/base.service.ts
Base service for client-side API services Provides common utility methods without enforcing rigid structure Services can extend this to access helpers while maintaining flexibility
Properties |
|
Methods |
|
| Protected buildCompanyWhere | ||||||||||||
buildCompanyWhere(companyId: number, additionalWhere?: Record
|
||||||||||||
|
Build base WHERE clause with company scope Ensures all queries are scoped to the user's company
Parameters :
Returns :
Record<string, any>
Complete where clause object |
| Protected buildSearchWhere | ||||||||||||
buildSearchWhere(searchFields: string[], searchQuery?: string)
|
||||||||||||
|
Build a WHERE clause for search functionality Creates OR conditions for multiple fields
Parameters :
Returns :
[] | undefined
Array of search conditions or undefined if no query |
| Protected Async findByIdWithCompanyScope | ||||||||||||||||
findByIdWithCompanyScope(entityName: string, entityId: number, companyId: number)
|
||||||||||||||||
|
Find entity by ID with company scope verification Common pattern: get entity and ensure it belongs to the company
Parameters :
Returns :
Promise<any | null>
Entity if found and belongs to company, null otherwise |
| Protected getRepo | ||||||||
getRepo(repoName: string)
|
||||||||
|
Get a Prisma repository (table) dynamically Useful for generic operations across different entities
Parameters :
Returns :
any
The Prisma repository instance |
| Protected toDto | ||||||||||||
toDto(entity: any, dtoClass: unknown)
|
||||||||||||
Type parameters :
|
||||||||||||
|
Transform database entity to DTO using class-transformer
Parameters :
Returns :
TDto
Transformed DTO instance |
| Protected toDtoArray | ||||||||||||
toDtoArray(entities: any[], dtoClass: unknown)
|
||||||||||||
Type parameters :
|
||||||||||||
|
Transform array of database entities to DTOs
Parameters :
Returns :
TDto[]
Array of transformed DTO instances |
| Protected Async verifyCompanyOwnership | ||||||||||||||||
verifyCompanyOwnership(entityName: string, entityId: number, companyId: number)
|
||||||||||||||||
|
Verify that an entity belongs to a specific company Common security check to prevent cross-company data access
Parameters :
Returns :
Promise<boolean>
True if entity belongs to company, false otherwise |
| Protected Readonly prisma |
Type : BNestPrismaService
|
Decorators :
@Inject()
|
import { bnestPlainToDto, bnestPlainToDtoArray } from "@bish-nest/core";
import { BNestPrismaService } from "@bish-nest/core/services";
import { Inject, Injectable } from "@nestjs/common";
/**
* Base service for client-side API services
* Provides common utility methods without enforcing rigid structure
* Services can extend this to access helpers while maintaining flexibility
*/
@Injectable()
export abstract class CLBaseService {
@Inject() protected readonly prisma!: BNestPrismaService;
/**
* Transform database entity to DTO using class-transformer
* @param entity - Raw database entity
* @param dtoClass - DTO class constructor
* @returns Transformed DTO instance
*/
protected toDto<TDto>(entity: any, dtoClass: new () => TDto): TDto {
return bnestPlainToDto(entity, dtoClass);
}
/**
* Transform array of database entities to DTOs
* @param entities - Array of raw database entities
* @param dtoClass - DTO class constructor
* @returns Array of transformed DTO instances
*/
protected toDtoArray<TDto>(entities: any[], dtoClass: new () => TDto): TDto[] {
return bnestPlainToDtoArray(entities, dtoClass);
}
/**
* Verify that an entity belongs to a specific company
* Common security check to prevent cross-company data access
* @param entityName - Prisma model name (e.g., 'participant', 'participantGroup')
* @param entityId - Entity ID to check
* @param companyId - Company ID to verify ownership
* @returns True if entity belongs to company, false otherwise
*/
protected async verifyCompanyOwnership(
entityName: string,
entityId: number,
companyId: number,
): Promise<boolean> {
const repo = this.getRepo(entityName);
const entity = await repo.findFirst({
where: {
id: entityId,
company_id: companyId,
},
});
return !!entity;
}
/**
* Build a WHERE clause for search functionality
* Creates OR conditions for multiple fields
* @param searchFields - Array of field names to search in
* @param searchQuery - Search query string
* @returns Array of search conditions or undefined if no query
*/
protected buildSearchWhere(searchFields: string[], searchQuery?: string): any[] | undefined {
if (!searchQuery?.trim()) {
return undefined;
}
const trimmedQuery = searchQuery.trim();
return searchFields.map((field) => ({
[field]: { contains: trimmedQuery, mode: "insensitive" },
}));
}
/**
* Build base WHERE clause with company scope
* Ensures all queries are scoped to the user's company
* @param companyId - Company ID to scope queries to
* @param additionalWhere - Additional where conditions to merge
* @returns Complete where clause object
*/
protected buildCompanyWhere(companyId: number, additionalWhere?: Record<string, any>): Record<string, any> {
return {
company_id: companyId,
...additionalWhere,
};
}
/**
* Get a Prisma repository (table) dynamically
* Useful for generic operations across different entities
* @param repoName - The name of the Prisma repository (table)
* @returns The Prisma repository instance
* @throws Error if repository doesn't exist
*/
protected getRepo(repoName: string): any {
if (!(repoName in this.prisma.client)) {
throw new Error(`Repository "${repoName}" does not exist in Prisma Client.`);
}
return (this.prisma.client as any)[repoName];
}
/**
* Find entity by ID with company scope verification
* Common pattern: get entity and ensure it belongs to the company
* @param entityName - Prisma model name
* @param entityId - Entity ID
* @param companyId - Company ID to verify ownership
* @returns Entity if found and belongs to company, null otherwise
*/
protected async findByIdWithCompanyScope(
entityName: string,
entityId: number,
companyId: number,
): Promise<any | null> {
const repo = this.getRepo(entityName);
return await repo.findFirst({
where: {
id: entityId,
company_id: companyId,
},
});
}
}