1- import type { AnyReportRow , TimeBucket , ReportSummary } from './types' ;
1+ import type { AnyReportRow , BillingRow , TimeBucket , ReportSummary , UsageReportRow , TokenUsageRow } from './types' ;
22
33/** Group rows by a column value, returning a map of group key → rows */
44export function groupBy < T extends AnyReportRow > (
@@ -53,7 +53,7 @@ export function getTimeBucketKey(dateStr: string, bucket: TimeBucket): string {
5353}
5454
5555/** Group rows by time bucket, returning sorted entries */
56- export function timeBucket < T extends AnyReportRow > (
56+ export function timeBucket < T extends BillingRow > (
5757 rows : T [ ] ,
5858 bucket : TimeBucket ,
5959) : Map < string , T [ ] > {
@@ -92,9 +92,15 @@ export function topN<T extends AnyReportRow>(
9292 return ranked . slice ( 0 , n ) ;
9393}
9494
95+ /** Type guard for rows with billing fields */
96+ function isBillingRow ( row : AnyReportRow ) : row is BillingRow {
97+ return 'date' in row && 'grossAmount' in row ;
98+ }
99+
95100/** Compute summary metrics for a set of rows */
96101export function computeSummary ( rows : AnyReportRow [ ] ) : ReportSummary {
97- const dates = rows . map ( ( r ) => r . date ) . filter ( Boolean ) . sort ( ) ;
102+ const billingRows = rows . filter ( isBillingRow ) ;
103+ const dates = billingRows . map ( ( r ) => r . date ) . filter ( Boolean ) . sort ( ) ;
98104 const users = new Set < string > ( ) ;
99105 const organizations = new Set < string > ( ) ;
100106 const models = new Set < string > ( ) ;
@@ -109,30 +115,31 @@ export function computeSummary(rows: AnyReportRow[]): ReportSummary {
109115 let totalStorageGBH = 0 ;
110116 let totalTokens = 0 ;
111117
112- for ( const row of rows ) {
118+ for ( const row of billingRows ) {
113119 totalGrossAmount += row . grossAmount ;
114120 totalNetAmount += row . netAmount ;
115121 totalDiscountAmount += row . discountAmount ;
116122 totalQuantity += row . quantity ;
117123
118- if ( 'username' in row && row . username ) users . add ( row . username as string ) ;
119- if ( 'organization' in row && row . organization ) organizations . add ( row . organization as string ) ;
120- if ( 'model' in row && row . model ) models . add ( row . model as string ) ;
121- if ( 'repository' in row && ( row as Record < string , unknown > ) . repository ) repositories . add ( ( row as Record < string , unknown > ) . repository as string ) ;
122- if ( 'product' in row && ( row as Record < string , unknown > ) . product ) products . add ( ( row as Record < string , unknown > ) . product as string ) ;
124+ if ( 'username' in row && row . username ) users . add ( row . username ) ;
125+ if ( 'organization' in row && row . organization ) organizations . add ( row . organization ) ;
126+ if ( 'model' in row ) models . add ( row . model ) ;
127+ const usageRow = row as UsageReportRow ;
128+ if ( 'repository' in row && usageRow . repository ) repositories . add ( usageRow . repository ) ;
129+ if ( 'product' in row && row . product ) products . add ( String ( row . product ) ) ;
123130
124- // Accumulate unit-type-specific totals
131+ // Accumulate unit-type-specific totals for usage reports
125132 if ( 'unitType' in row ) {
126- const unitType = ( row as Record < string , unknown > ) . unitType ;
127- if ( unitType === 'minutes' ) totalMinutes += row . quantity ;
128- if ( unitType === 'gigabyte-hours' ) totalStorageGBH += row . quantity ;
133+ const u = row as UsageReportRow ;
134+ if ( u . unitType === 'minutes' ) totalMinutes += u . quantity ;
135+ if ( u . unitType === 'gigabyte-hours' ) totalStorageGBH += u . quantity ;
129136 }
130137
131138 // Accumulate token totals
132139 if ( 'totalInputTokens' in row ) {
133- const r = row as Record < string , number > ;
134- totalTokens += ( r . totalInputTokens ?? 0 ) + ( r . totalOutputTokens ?? 0 )
135- + ( r . totalCacheCreationTokens ?? 0 ) + ( r . totalCacheReadTokens ?? 0 ) ;
140+ const t = row as TokenUsageRow ;
141+ totalTokens += ( t . totalInputTokens ?? 0 ) + ( t . totalOutputTokens ?? 0 )
142+ + ( t . totalCacheCreationTokens ?? 0 ) + ( t . totalCacheReadTokens ?? 0 ) ;
136143 }
137144 }
138145
0 commit comments