91 lines
2.9 KiB
TypeScript
91 lines
2.9 KiB
TypeScript
import {
|
|
DailyTrendResponseSchema,
|
|
StrategyPerformanceResponseSchema,
|
|
SubredditPerformanceResponseSchema,
|
|
SuccessfulExamplesResponseSchema,
|
|
FunnelResponseSchema,
|
|
AiUsageSummaryResponseSchema,
|
|
} from '../../../../../packages/api-contracts/src/index.js';
|
|
import type { z } from 'zod';
|
|
import { createDashboardRequest } from '../../api/request.js';
|
|
|
|
type SubredditPerformanceResponse = z.infer<typeof SubredditPerformanceResponseSchema>;
|
|
type StrategyPerformanceResponse = z.infer<typeof StrategyPerformanceResponseSchema>;
|
|
type DailyTrendResponse = z.infer<typeof DailyTrendResponseSchema>;
|
|
type SuccessfulExamplesResponse = z.infer<typeof SuccessfulExamplesResponseSchema>;
|
|
type FunnelResponse = z.infer<typeof FunnelResponseSchema>;
|
|
type AiUsageSummaryResponse = z.infer<typeof AiUsageSummaryResponseSchema>;
|
|
|
|
async function parseResponse<T>(
|
|
response: Response,
|
|
schema: { parse(value: unknown): T },
|
|
): Promise<T> {
|
|
const payload: unknown = await response.json();
|
|
if (!response.ok) {
|
|
const message =
|
|
typeof payload === 'object' &&
|
|
payload !== null &&
|
|
'error' in payload &&
|
|
typeof payload.error === 'string'
|
|
? payload.error
|
|
: `Request failed (${response.status})`;
|
|
throw new Error(message);
|
|
}
|
|
return schema.parse(payload);
|
|
}
|
|
|
|
export interface PerformanceApi {
|
|
getSubredditPerformance(): Promise<SubredditPerformanceResponse>;
|
|
getStrategyPerformance(): Promise<StrategyPerformanceResponse>;
|
|
getDailyTrend(days: number): Promise<DailyTrendResponse>;
|
|
getSuccessfulExamples(): Promise<SuccessfulExamplesResponse>;
|
|
getFunnel(): Promise<FunnelResponse>;
|
|
getAiUsage(days: number): Promise<AiUsageSummaryResponse>;
|
|
}
|
|
|
|
export function createPerformanceApi(
|
|
fetchImplementation?: typeof fetch,
|
|
) {
|
|
const request = createDashboardRequest(fetchImplementation);
|
|
return {
|
|
async getSubredditPerformance() {
|
|
return parseResponse(
|
|
await request('/api/analytics/by-subreddit'),
|
|
SubredditPerformanceResponseSchema,
|
|
);
|
|
},
|
|
async getStrategyPerformance() {
|
|
return parseResponse(
|
|
await request('/api/analytics/by-strategy'),
|
|
StrategyPerformanceResponseSchema,
|
|
);
|
|
},
|
|
async getDailyTrend(days: number) {
|
|
return parseResponse(
|
|
await request(`/api/analytics/trend?days=${days}`),
|
|
DailyTrendResponseSchema,
|
|
);
|
|
},
|
|
async getSuccessfulExamples() {
|
|
return parseResponse(
|
|
await request('/api/successful'),
|
|
SuccessfulExamplesResponseSchema,
|
|
);
|
|
},
|
|
async getFunnel() {
|
|
return parseResponse(
|
|
await request('/api/analytics/funnel'),
|
|
FunnelResponseSchema,
|
|
);
|
|
},
|
|
async getAiUsage(days: number) {
|
|
return parseResponse(
|
|
await request(`/api/analytics/ai-usage?days=${days}`),
|
|
AiUsageSummaryResponseSchema,
|
|
);
|
|
},
|
|
} satisfies PerformanceApi;
|
|
}
|
|
|
|
export const performanceApi = createPerformanceApi();
|