source-code/
portofolio-backend
Public
typescript123 lines3.6 KB
import {
Controller,
Get,
Post,
Param,
Query,
UseGuards,
Inject,
Logger,
} from '@nestjs/common';
import { GithubSyncService } from './github-sync.service';
import { GithubProxyService } from './github-proxy.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import * as cacheManager from 'cache-manager';
@Controller('github')
export class GithubController {
private readonly logger = new Logger(GithubController.name);
constructor(
private readonly githubSyncService: GithubSyncService,
private readonly githubProxyService: GithubProxyService,
@Inject(CACHE_MANAGER) private readonly cacheManager: cacheManager.Cache,
) {}
/**
* Manually triggers GitHub repository synchronization.
* Admin only - protected by JWT Guard.
*/
@UseGuards(JwtAuthGuard)
@Post('sync')
async syncRepos() {
this.logger.log('Admin triggered manual GitHub synchronization');
return this.githubSyncService.syncPortfolioRepos();
}
/**
* Returns a list of repositories that contain .portfolio.json with include: true
* (Fetched directly from DB to save GitHub API quota).
*/
@Get('repos')
async getRepos() {
return this.githubSyncService.getRepos();
}
/**
* Proxies file tree requests. Cached for 1 hour.
*/
@Get('repos/:repoName/tree')
async getTree(
@Param('repoName') repoName: string,
@Query('path') path: string = '',
) {
const cacheKey = `github:tree:${repoName}:${path}`;
const cached = await this.cacheManager.get(cacheKey);
if (cached) {
this.logger.debug(`Cache hit for repository tree: ${cacheKey}`);
return cached;
}
const data = await this.githubProxyService.getRepoTree(repoName, path);
await this.cacheManager.set(cacheKey, data, 3600000); // 1 hour
return data;
}
/**
* Proxies file content requests. Decodes contents and returns lines/size metadata.
* Cached for 1 hour.
*/
@Get('repos/:repoName/file')
async getFile(
@Param('repoName') repoName: string,
@Query('path') path: string,
) {
const cacheKey = `github:file:${repoName}:${path}`;
const cached = await this.cacheManager.get(cacheKey);
if (cached) {
this.logger.debug(`Cache hit for repository file: ${cacheKey}`);
return cached;
}
const data = await this.githubProxyService.getRepoFile(repoName, path);
await this.cacheManager.set(cacheKey, data, 3600000); // 1 hour
return data;
}
/**
* Proxies README.md request. Cached for 1 hour.
*/
@Get('repos/:repoName/readme')
async getReadme(@Param('repoName') repoName: string) {
const cacheKey = `github:readme:${repoName}`;
const cached = await this.cacheManager.get(cacheKey);
if (cached) {
this.logger.debug(`Cache hit for repository readme: ${cacheKey}`);
return cached;
}
const data = await this.githubProxyService.getRepoReadme(repoName);
await this.cacheManager.set(cacheKey, data, 3600000); // 1 hour
return data;
}
/**
* Returns repository metadata (stars, forks, watchers, releases, contributors).
* Cached for 1 hour.
*/
@Get('repos/:repoName/metadata')
async getMetadata(@Param('repoName') repoName: string) {
const cacheKey = `github:metadata:${repoName}`;
const cached = await this.cacheManager.get(cacheKey);
if (cached) {
this.logger.debug(`Cache hit for repository metadata: ${cacheKey}`);
return cached;
}
const data = await this.githubProxyService.getRepoMetadata(repoName);
await this.cacheManager.set(cacheKey, data, 3600000); // 1 hour
return data;
}
}
About
Fullstack portfolio backend built with NestJS, Prisma, and PostgreSQL. Features JWT authentication, throttler rate limits, cache management, and automated GitHub repository synchronization.
linknre.codes
TypeScriptNestJSPostgreSQLPrisma