Skip to content

ManualsInsightsService

reference
2 min readUpdated

Kind: Service

Source: atloria-monorepo/apps/api/src/manuals-insights/manuals-insights.service.ts

ManualsInsightsService provides backend analytics and automation for the manuals knowledge base. It aggregates insight and deflection data, identifies ticket-topic clusters, generates draft documentation from those clusters, and reports freshness status for tracked manual content.

Methods

MethodSignatureReturnsDescription
insightsinsights(projectId: string, organizationId: string)unknownAuthed, org-scoped insights for a project: weakPages — published pages with 👎 feedback and/or search misses that match them.
deflectiondeflection(projectId: string, organizationId: string, days: unknown)unknownDeflection & CSAT cockpit (WS-D) for one project.
ticketTopicsticketTopics(projectId: string, organizationId: string, days: unknown)Promise<TicketTopicProposal[]>Authed, org-scoped list of content-loop proposals for a project: clusters of resolved QUESTION tickets that recur enough to deserve a page and aren't already…
generateDraftFromClustergenerateDraftFromCluster(projectId: string, organizationId: string, userId: string, topicKey: string)Promise<{ documentId: string; slug: string; state: string }>Turn one proposed cluster (by topicKey) into a GROUNDED DRAFT document: - build a neutral, PII-free question from the cluster's shared terms, - answer it via…
freshnessfreshness(projectId: string, slug: string)Promise<{ stale: boolean; tracked: boolean; since?: string; staleCount?: number; commit?: string }>PUBLIC reader-facing freshness for one manual page slug.

Dependencies

  • PrismaService
  • TechDocsRagService
  • DraftDocumentService

Where it refuses work

  • ManualsInsightsService stops the work with ForbiddenException when !project — “Project not found in your organization.”, in 4 places.
  • ManualsInsightsService stops the work with BadRequestException when !cluster — “No qualifying ticket topic for that key (too few tickets, or already documented).”.
  • ManualsInsightsService stops the work with an early return when !entitiesJson.
  • ManualsInsightsService stops the work with an early return when !Array.isArray(entities) || !entities.length.
  • ManualsInsightsService stops the work with an early return when !topicTerms.length.
  • ManualsInsightsService stops the work with an early return when !slug.

When something fails

  • ManualsInsightsService handles failure in 1 place: it discards it silently in all 1.

Diagram

mermaid
sequenceDiagram
  participant Client
  participant Controller
  participant Service as ManualsInsightsService
  participant Tickets as Ticket Data Source
  participant Manuals as Manuals Repository

  Client->>Controller: Request insights, topics, or freshness
  Controller->>Service: Call service method

  alt Ticket topic analysis
    Service->>Tickets: Load and cluster ticket data
    Tickets-->>Service: Ticket clusters
    Service-->>Controller: TicketTopicProposal[]
  else Generate draft
    Service->>Tickets: Read selected topic cluster
    Service->>Manuals: Create draft manual document
    Manuals-->>Service: documentId, slug, state
    Service-->>Controller: Draft metadata
  else Freshness check
    Service->>Manuals: Compare tracked content with source state
    Manuals-->>Service: Tracking and commit information
    Service-->>Controller: Freshness result
  end

  Controller-->>Client: API response

Usage

ts
import { Injectable } from '@nestjs/common';
import { ManualsInsightsService } from './manuals-insights.service';

@Injectable()
export class ManualsInsightsController {
  constructor(
    private readonly manualsInsightsService: ManualsInsightsService,
  ) {}

  async getTicketTopics() {
    return this.manualsInsightsService.ticketTopics();
  }

  async createDraftFromTopicCluster() {
    const draft =
      await this.manualsInsightsService.generateDraftFromCluster();

    return {
      documentId: draft.documentId,
      slug: draft.slug,
      state: draft.state,
    };
  }

  async getFreshness() {
    const freshness = await this.manualsInsightsService.freshness();

    return {
      stale: freshness.stale,
      tracked: freshness.tracked,
      staleCount: freshness.staleCount ?? 0,
      lastTrackedCommit: freshness.commit,
    };
  }
}

AI Coding Instructions

  • Inject ManualsInsightsService through NestJS dependency injection; do not instantiate it directly.
  • Use ticketTopics() before generating documentation drafts so draft creation is based on validated ticket clusters.
  • Treat generateDraftFromCluster() output as draft metadata; consumers should handle the returned state before publishing or exposing content.
  • Handle optional freshness() fields such as since, staleCount, and commit defensively when the manual is not tracked.
  • Keep insight and deflection endpoints read-oriented, and avoid adding write side effects outside explicit draft-generation workflows.

Relationships

  • DEPENDS_ON → PrismaService
  • DEPENDS_ON → TechDocsRagService
  • DEPENDS_ON → DraftDocumentService

Referenced By

  • ManualsInsightsController (DEPENDS_ON)
  • ManualsInsightsModule (MODULE_PROVIDES)

Was this page helpful?

Download as PDF