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

100% Statements 33/33
91.66% Branches 11/12
100% Functions 5/5
100% Lines 31/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 664x 4x 4x 4x   4x     4x 15x   15x     9x 8x   7x       6x 6x   6x       14x 14x 14x   14x 14x 13x 13x     13x 13x 13x 13x 13x   12x             12x       2x 2x         12x        
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[]> {
    if (this.rolesCache === null) {
      await this.loadRoles();
    }
    return Array.from(this.rolesCache!.values());
  }
 
  async getRoleById(roleId: string): Promise<IRoleDefinition | null> {
    Eif (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;
  }
}