import { ClsService } from "nestjs-cls"; import { AbstractRepository } from "../../../core/neo4j/abstracts/abstract.repository"; import { Neo4jService } from "../../../core/neo4j/services/neo4j.service"; import { SecurityService } from "../../../core/security/services/security.service"; import { TokenUsageReportDimension, TokenUsageReportMetric, TokenUsageTargetLabel } from "../common/tokenusage.target-labels"; import { TokenUsage, TokenUsageDescriptor } from "../entities/tokenusage"; import { TokenUsageReportBreakdownEntity } from "../entities/tokenusage-report-breakdown"; import { TokenUsageReportSummaryEntity } from "../entities/tokenusage-report-summary"; import { TokenUsageReportTimelineEntity } from "../entities/tokenusage-report-timeline"; /** * Self-service token-usage reporting: the caller's OWN company, nothing else. * * This is the deliberate mirror image of TokenUsageAdminRepository. That class * carries a file-level lint-ignore and omits buildDefaultMatch() because a * platform-wide dashboard must not be scoped to the caller. THIS class must be * scoped, so every query below goes through buildDefaultMatch(), which injects * the CLS company filter. There is deliberately no file-level ignore header * here, and no companyId parameter anywhere in this file: a self-service caller * cannot name a company, so there is nothing to spoof. * * Rollup RETURNs are scalar columns, not graph nodes, so readOne()/readMany() * cannot map them - entityFactory.createGraphList expects nodes. Same shape and * same rationale as TokenUsageRepository.findAggregatedByDateAndType in this * folder, which is the canonical company-scoped aggregation. * * EVERY traversal constrains its target label. The company traversal inherits * the label constraint from Neo4jService.initQuery()'s preamble, which binds * (company:Company {id: $companyId}); the target traversal below constrains * (grp:). The write bug fixed in tokenusage.repository.ts left * label-less nodes on exactly these relationships, and an unconstrained match * returns them. * * It does NOT override onModuleInit: the :TokenUsage indexes belong to * TokenUsageRepository, and duplicating the CREATE INDEX would be a second * writer for one schema object. */ export declare class TokenUsageReportRepository extends AbstractRepository { private readonly targetLabels; protected readonly descriptor: import("../../..").EntityDescriptor; constructor(neo4j: Neo4jService, securityService: SecurityService, clsService: ClsService, targetLabels?: TokenUsageTargetLabel[]); /** * Two rows: the requested window and the equal-length span immediately * preceding it, which is what the KPI tile's delta is measured against. * * Both rows are ALWAYS returned, zero-filled when the database has nothing — * the tiles then never have to branch on a missing window. */ findSummary(params: { from: string; to: string; }): Promise; /** * One row per (bucket, operation type). `stackBy` is accepted for signature * parity with the administrative timeline but only "type" is meaningful inside * a single tenant, so it is not interpolated anywhere. */ findTimeline(params: { from: string; to: string; granularity: "day" | "week" | "month"; stackBy: "type"; }): Promise; /** * Ranked rows for one dimension, ordered by the SELECTED metric. * * Ordering by the selected metric rather than unconditionally by cost is not * cosmetic: credits are max(minCreditsPerRecord, round4(cost / creditCost)), * and that floor breaks proportionality for cheap calls — so a credits panel * ranked by cost is visibly mis-ordered whenever the two diverge. * * Everything past `limit` is folded into a single "other" row so the shares * still sum to 100 percent. */ findBreakdown(params: { from: string; to: string; dimension: TokenUsageReportDimension; targetLabel?: string; metric: TokenUsageReportMetric; limit: number; }): Promise; /** * The six metric columns, identical in all three queries. * * `tokens` is projected as a column of its own so ORDER BY can name it — a * Cypher ORDER BY cannot reference an expression built from two aggregates * unless that expression is itself projected. */ private _metricProjection; private _metrics; /** * Resolves the requested label against the host application's allowlist and * returns the ALLOWLIST'S OWN string, never the caller's. An empty allowlist * means the app never opted in, so every target request is refused. */ private _resolveTarget; /** * Neo4j hands integers back as driver Integer objects. Same helper, same * shape, as TokenUsageRepository.toNumber — AbstractRepository does not * provide one, and the aggregation path is the only place that needs it. */ private toNumber; } //# sourceMappingURL=tokenusage.report.repository.d.ts.map