All files / core/roles role-repository.service.ts

93.93% Statements 31/33
58.33% Branches 7/12
100% Functions 5/5
93.54% Lines 29/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 661x 1x 1x 1x   1x     1x 102x   102x     2x 2x   2x       66x 59x   66x       61x 61x 61x   61x 61x 61x 61x     61x 61x 61x 61x 61x   61x             61x                   61x        
import { Injectable } from '@nestjs/common';
import { readdir, readFile } from 'fs/promises';
import { join, basename, extname } from 'path';
import matter from 'gray-matter';
import { IRoleDefinition } from '@gs-squad-mcp/core/roles';
import { SquadConfigService } from '@gs-squad-mcp/core/config';
 
@Injectable()
export class RoleRepositoryService {
  private rolesCache: Map<string, IRoleDefinition> | null = null;
 
  constructor(private readonly configService: SquadConfigService) {}
 
  async getAllRoles(): Promise<IRoleDefinition[]> {
    Eif (this.rolesCache === null) {
      await this.loadRoles();
    }
    return Array.from(this.rolesCache!.values());
  }
 
  async getRoleById(roleId: string): Promise<IRoleDefinition | null> {
    if (this.rolesCache === null) {
      await this.loadRoles();
    }
    return this.rolesCache!.get(roleId) || null;
  }
 
  private async loadRoles(): Promise<void> {
    const config = this.configService.getConfig();
    const agentsPath = config.agentsDirectoryPath;
    const rolesMap = new Map<string, IRoleDefinition>();
 
    try {
      const files = await readdir(agentsPath);
      const markdownFiles = files.filter(
        (file) => extname(file) === '.md'
      );
 
      for (const file of markdownFiles) {
        const filePath = join(agentsPath, file);
        const roleId = basename(file, '.md');
        const content = await readFile(filePath, 'utf-8');
        const parsed = matter(content);
 
        const role: IRoleDefinition = {
          id: roleId,
          name: parsed.data.name || roleId,
          description: parsed.data.description || '',
          body: parsed.content.trim()
        };
 
        rolesMap.set(roleId, role);
      }
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      throw new Error(
        `Failed to load roles from ${agentsPath}: ${errorMessage}`
      );
    }
 
    this.rolesCache = rolesMap;
  }
}