phase-9: domain-driven architecture complete

- Restructured server layer with 5 domains: shared, screener, portfolio, calls, finance
- Migrated 58 TypeScript files to domain-driven structure
- Updated CLAUDE.md with new architecture documentation
- Added .gitignore rules for .md files (except CLAUDE.md)
- Removed unused CatalystAnalyst import from app.ts
- Fixed lint errors: removed unused imports, fixed regex escape, added console suppressions
- Verified no sensitive data in git history
- Server code compiles cleanly with TypeScript strict mode
This commit is contained in:
Sai Kiran Vella
2026-06-06 13:21:24 -04:00
committed by saikiranvella
parent c7e39c3e4e
commit c388b6d83c
88 changed files with 3576 additions and 3493 deletions
@@ -0,0 +1,54 @@
import type { FastifyInstance, FastifyRequest } from 'fastify';
import { ScreenerEngine } from './ScreenerEngine';
import { CatalystCache } from '../../domains/shared';
import type { LiveAssetResult } from '../../domains/shared';
import { screenSchema } from '../../domains/shared/types/schemas';
export class ScreenerController {
constructor(
private readonly engine: ScreenerEngine,
private readonly catalystCache: CatalystCache,
) {}
register(app: FastifyInstance): void {
app.post(
'/api/screen',
{ schema: screenSchema, config: { rateLimit: { max: 10, timeWindow: '1 minute' } } },
this.screen.bind(this),
);
app.get(
'/api/screen/catalysts',
{ config: { rateLimit: { max: 10, timeWindow: '1 minute' } } },
this.catalysts.bind(this),
);
}
private static serializeAssets(arr: LiveAssetResult[]) {
return arr.map((r) => ({
...r,
asset: {
ticker: r.asset.ticker,
type: r.asset.type,
currentPrice: r.asset.currentPrice,
metrics: r.asset.metrics,
displayMetrics: r.asset.getDisplayMetrics(),
},
}));
}
private async screen(req: FastifyRequest) {
const tickers = (req.body as { tickers: string[] }).tickers.map((t) => t.toUpperCase());
const results = await this.engine.screenTickers(tickers);
return {
...results,
STOCK: ScreenerController.serializeAssets(results.STOCK as LiveAssetResult[]),
ETF: ScreenerController.serializeAssets(results.ETF as LiveAssetResult[]),
BOND: ScreenerController.serializeAssets(results.BOND as LiveAssetResult[]),
};
}
private async catalysts() {
const { tickers, stories } = await this.catalystCache.get();
return { tickers, stories };
}
}