169 lines
3.9 KiB
TypeScript
169 lines
3.9 KiB
TypeScript
import {
|
|
Controller,
|
|
Get,
|
|
Post,
|
|
Body,
|
|
Param,
|
|
UseGuards,
|
|
Request,
|
|
Query,
|
|
Inject,
|
|
} from '@nestjs/common';
|
|
import { CACHE_MANAGER } from '@nestjs/cache-manager';
|
|
import { Cache } from 'cache-manager';
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
import { JwtAuthGuard } from '../auth';
|
|
import { CreateCollectionDto, AddArticleDto, CreateQuickNoteDto } from './dto';
|
|
|
|
interface RequestWithUser extends Request {
|
|
user: {
|
|
id: string;
|
|
username: string;
|
|
};
|
|
}
|
|
|
|
@Controller('api/collections')
|
|
@UseGuards(JwtAuthGuard)
|
|
export class CollectionsController {
|
|
constructor(
|
|
private readonly prisma: PrismaService,
|
|
@Inject(CACHE_MANAGER) private cacheManager: Cache,
|
|
) {}
|
|
|
|
@Get()
|
|
async getAllCollections(
|
|
@Request() req: RequestWithUser,
|
|
@Query('limit') limit?: number,
|
|
@Query('cursor') cursor?: string,
|
|
) {
|
|
const cacheKey = `collections:${req.user.id}:${limit}:${cursor}`;
|
|
const cached = await this.cacheManager.get(cacheKey);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
|
|
const take = limit ? Number(limit) : 20;
|
|
const collections = await this.prisma.collection.findMany({
|
|
where: {
|
|
userId: req.user.id,
|
|
},
|
|
take: take + 1,
|
|
skip: cursor ? 1 : 0,
|
|
cursor: cursor ? { id: cursor } : undefined,
|
|
orderBy: [{ updatedAt: 'desc' }, { id: 'desc' }],
|
|
include: {
|
|
articles: true,
|
|
quickNotes: true,
|
|
notes: true,
|
|
},
|
|
});
|
|
|
|
let nextCursor: string | null = null;
|
|
if (collections.length > take) {
|
|
const nextItem = collections.pop()!;
|
|
nextCursor = nextItem.id;
|
|
}
|
|
|
|
const result = {
|
|
collections,
|
|
nextCursor,
|
|
};
|
|
|
|
await this.cacheManager.set(cacheKey, result, 300); // Cache for 5 minutes
|
|
return result;
|
|
}
|
|
|
|
@Post()
|
|
async createCollection(
|
|
@Body() data: CreateCollectionDto,
|
|
@Request() req: RequestWithUser,
|
|
) {
|
|
const collection = await this.prisma.collection.create({
|
|
data: {
|
|
...data,
|
|
userId: req.user.id,
|
|
},
|
|
include: {
|
|
articles: true,
|
|
quickNotes: true,
|
|
notes: true,
|
|
},
|
|
});
|
|
|
|
// Invalidate user's collections cache
|
|
const cachePattern = `collections:${req.user.id}:*`;
|
|
await this.cacheManager.del(cachePattern);
|
|
|
|
return collection;
|
|
}
|
|
|
|
@Post(':id/add-article')
|
|
async addArticleToCollection(
|
|
@Param('id') id: string,
|
|
@Body() articleData: AddArticleDto,
|
|
@Request() req: RequestWithUser,
|
|
) {
|
|
const existingArticle = await this.prisma.article.findUnique({
|
|
where: { url: articleData.url },
|
|
});
|
|
|
|
if (existingArticle) {
|
|
await this.prisma.collection.update({
|
|
where: { id },
|
|
data: {
|
|
articles: {
|
|
connect: { id: existingArticle.id },
|
|
},
|
|
},
|
|
});
|
|
|
|
// Invalidate cache for this collection
|
|
const cachePattern = `collections:${req.user.id}:*`;
|
|
await this.cacheManager.del(cachePattern);
|
|
|
|
return existingArticle;
|
|
}
|
|
|
|
const article = await this.prisma.article.create({
|
|
data: {
|
|
...articleData,
|
|
collections: {
|
|
connect: { id },
|
|
},
|
|
},
|
|
});
|
|
|
|
// Invalidate cache for this collection
|
|
const cachePattern = `collections:${req.user.id}:*`;
|
|
await this.cacheManager.del(cachePattern);
|
|
|
|
return article;
|
|
}
|
|
|
|
@Post(':id/quick-notes')
|
|
async addQuickNoteToCollection(
|
|
@Param('id') id: string,
|
|
@Body() quickNoteData: CreateQuickNoteDto,
|
|
@Request() req: RequestWithUser,
|
|
) {
|
|
const quickNote = await this.prisma.quickNote.create({
|
|
data: {
|
|
...quickNoteData,
|
|
shared: quickNoteData.shared ?? false,
|
|
collection: {
|
|
connect: { id },
|
|
},
|
|
user: {
|
|
connect: { id: req.user.id },
|
|
},
|
|
},
|
|
});
|
|
|
|
// Invalidate cache for this collection
|
|
const cachePattern = `collections:${req.user.id}:*`;
|
|
await this.cacheManager.del(cachePattern);
|
|
|
|
return quickNote;
|
|
}
|
|
}
|