Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 20 additions & 13 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { logger } from "./logger";
import { loggingMiddleware } from "./middleware/logging";
import { FeedService } from "./services/feed.service";

Copilot AI Jan 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SmartMixService import was removed from line 8, but FeedService (line 7) still depends on SmartMixService in its constructor. This will cause a runtime dependency injection failure. Verify that SmartMixService is still needed and either restore the import or update FeedService to remove the dependency.

Suggested change
import { FeedService } from "./services/feed.service";
import { FeedService } from "./services/feed.service";
import { SmartMixService } from "./services/smartmix.service";

Copilot uses AI. Check for mistakes.
import { HackerNewsService } from "./services/hackernews.service";
import { SmartMixService } from "./services/smartmix.service";
import { AnalyticsService } from "./services/analytics.service";
import {
getServicesStatus,
Expand All @@ -31,7 +30,7 @@ app.use(
"https://news.andreello.dev.br",
],
credentials: true,
})
}),
);

app.get("/", (c) => {
Expand Down Expand Up @@ -69,7 +68,7 @@ app.get("/api/news/tabnews", async (c) => {
error:
error instanceof Error ? error.message : "Erro ao carregar TabNews",
},
500
500,
);
}
});
Expand All @@ -93,7 +92,7 @@ app.get("/api/news/hackernews", async (c) => {
? error.message
: "Erro ao carregar Hacker News",
},
500
500,
);
}
});
Expand Down Expand Up @@ -127,7 +126,7 @@ app.get("/api/feed", async (c) => {
{
error: error instanceof Error ? error.message : "Failed to load feed",
},
500
500,
);
}
});
Expand Down Expand Up @@ -158,7 +157,7 @@ app.get("/api/comments/:username/:slug", async (c) => {
? error.message
: "Erro ao carregar comentários",
},
500
500,
);
}
});
Expand All @@ -177,7 +176,7 @@ app.get("/api/services/status", async (c) => {
{
error: "Falha ao carregar status dos serviços",
},
500
500,
);
}
});
Expand Down Expand Up @@ -205,9 +204,12 @@ app.get("/api/analytics/trending", async (c) => {
});
return c.json(
{
error: error instanceof Error ? error.message : "Failed to load trending topics",
error:
error instanceof Error
? error.message
: "Failed to load trending topics",
},
500
500,
);
}
});
Expand All @@ -218,7 +220,9 @@ app.get("/api/analytics/stats", async (c) => {

const [warehouseStats, processingStats] = await Promise.all([
analyticsService.getWarehouseStats(),
analyticsService.getProcessingStats(new Date(Date.now() - 24 * 60 * 60 * 1000)),
analyticsService.getProcessingStats(
new Date(Date.now() - 24 * 60 * 60 * 1000),
),
]);

c.header("Cache-Control", "public, max-age=300");
Expand All @@ -236,9 +240,12 @@ app.get("/api/analytics/stats", async (c) => {
});
return c.json(
{
error: error instanceof Error ? error.message : "Failed to load analytics stats",
error:
error instanceof Error
? error.message
: "Failed to load analytics stats",
},
500
500,
);
}
});
Expand All @@ -258,7 +265,7 @@ app.notFound((c) => {
"GET /api/analytics/stats",
],
},
404
404,
);
});

Expand Down
179 changes: 0 additions & 179 deletions src/service.ts

This file was deleted.

28 changes: 13 additions & 15 deletions src/services/analytics.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { inject, singleton } from "tsyringe";
import { LoggerService } from "./logger.service";
import { DataWarehouseService } from "./data-warehouse.service";
import { ProcessingLogsService } from "./processing-logs.service";
import { StorageService } from "./storage.service";
import type {
AnalyticsPeriod,
AnalyticsResponse,
Expand All @@ -15,8 +14,7 @@ import type {
export class AnalyticsService {
constructor(
@inject(LoggerService) private logger: LoggerService,
@inject(DataWarehouseService) private warehouse: DataWarehouseService,
@inject(ProcessingLogsService) private processingLogs: ProcessingLogsService
@inject(StorageService) private storage: StorageService
) {}

async getTrendingTopics(period: AnalyticsPeriod = "7d"): Promise<AnalyticsResponse> {
Expand All @@ -25,9 +23,9 @@ export class AnalyticsService {

try {
const [trending, commented, stats] = await Promise.all([
this.warehouse.getTrendingKeywords(period, 15),
this.warehouse.getMostCommentedTopics(period, 10),
this.warehouse.getWarehouseStats(),
this.storage.getTrendingKeywords(period, 15),
this.storage.getMostCommentedTopics(period, 10),
this.storage.getWarehouseStats(),
]);

const mergedTrending = this.mergeTrendingResults(trending, commented);
Expand Down Expand Up @@ -62,13 +60,13 @@ export class AnalyticsService {
const stats: SourceStats[] = [];

for (const source of sources) {
const topNews = await this.warehouse.getTopRankedBySource(source, 100);
const topNews = await this.storage.getTopRankedBySource(source, 100);

if (topNews.length === 0) continue;

const avgScore =
topNews.reduce((sum, item) => sum + item.score, 0) / topNews.length;

topNews.reduce((sum: number, item) => sum + item.score, 0) /
topNews.length;
const keywordCounts = new Map<string, number>();
for (const item of topNews) {
const titleWords = this.extractKeywordsFromTitle(item.title);
Expand All @@ -94,7 +92,7 @@ export class AnalyticsService {
}

async getWarehouseStats(): Promise<WarehouseStats> {
return this.warehouse.getWarehouseStats();
return this.storage.getWarehouseStats();
}

async getProcessingStats(since: Date): Promise<{
Expand All @@ -104,10 +102,10 @@ export class AnalyticsService {
mix: { total: number; successful: number; failed: number; avgDuration: number };
}> {
const [fetch, enrich, rank, mix] = await Promise.all([
this.processingLogs.getStepStats("fetch", since),
this.processingLogs.getStepStats("enrich", since),
this.processingLogs.getStepStats("rank", since),
this.processingLogs.getStepStats("mix", since),
this.storage.getStepStats("fetch", since),
this.storage.getStepStats("enrich", since),
this.storage.getStepStats("rank", since),
this.storage.getStepStats("mix", since),
]);

return { fetch, enrich, rank, mix };
Expand Down
6 changes: 3 additions & 3 deletions src/services/enrichment.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { inject, singleton } from "tsyringe";
import { LoggerService } from "./logger.service";
import { GeminiService } from "./gemini.service";
import { ProcessingLogsService } from "./processing-logs.service";
import { StorageService } from "./storage.service";
import type { NewsItem, EnrichedNewsItem, Source } from "../types";

interface KeywordExtractionResult {
Expand Down Expand Up @@ -34,7 +34,7 @@ export class EnrichmentService {
constructor(
@inject(LoggerService) private logger: LoggerService,
@inject(GeminiService) private geminiService: GeminiService,
@inject(ProcessingLogsService) private processingLogs: ProcessingLogsService
@inject(StorageService) private storage: StorageService
) {}

async enrichNewsItem(item: NewsItem): Promise<EnrichedNewsItem> {
Expand Down Expand Up @@ -79,7 +79,7 @@ export class EnrichmentService {
};
} finally {
const duration = Date.now() - startTime;
await this.processingLogs.log(
await this.storage.log(
"enrich",
item.source,
item.id,
Expand Down
Loading
Loading