basic structure setup

This commit is contained in:
dimitar committed 2026-01-10 19:41:04 +01:00
commit 71dfd86187
89 files changed
+41490

No files matched your search

+128
View File
@@ -0,0 +1,128 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Article, ArticleStatus } from './entities';
import {
CreateArticleDto,
UpdateArticleDto,
FindArticlesDto,
} from './articles.dto';
@Injectable()
export class ArticlesService {
constructor(
@InjectRepository(Article)
private readonly articleRepository: Repository<Article>,
) {}
async create(dto: CreateArticleDto): Promise<Article> {
const article = this.articleRepository.create({
...dto,
status: dto.status || ArticleStatus.DRAFT,
});
return await this.articleRepository.save(article);
}
async findAll(
dto: FindArticlesDto,
): Promise<{ data: Article[]; total: number }> {
const {
category,
author,
tag,
status = ArticleStatus.PUBLISHED,
search,
page = 1,
limit = 10,
} = dto;
const queryBuilder = this.articleRepository
.createQueryBuilder('article')
.leftJoinAndSelect('article.author', 'author')
.leftJoinAndSelect('article.category', 'category')
.where('article.status = :status', { status });
if (category) {
queryBuilder.andWhere('category.slug = :category', { category });
}
if (author) {
queryBuilder.andWhere('author.slug = :author', { author });
}
if (tag) {
queryBuilder.andWhere(':tag = ANY(article.tags)', { tag });
}
if (search) {
queryBuilder.andWhere(
'(article.title ILIKE :search OR article.content ILIKE :search)',
{ search: `%${search}%` },
);
}
const [data, total] = await queryBuilder
.orderBy('article.createdAt', 'DESC')
.skip((page - 1) * limit)
.take(limit)
.getManyAndCount();
return { data, total };
}
async findOne(id: string): Promise<Article> {
const article = await this.articleRepository.findOne({
where: { id },
relations: ['author', 'category'],
});
if (!article) {
throw new NotFoundException(`Article with ID ${id} not found`);
}
return article;
}
async findBySlug(slug: string): Promise<Article> {
const article = await this.articleRepository.findOne({
where: { slug },
relations: ['author', 'category'],
});
if (!article) {
throw new NotFoundException(`Article with slug ${slug} not found`);
}
return article;
}
async update(id: string, dto: UpdateArticleDto): Promise<Article> {
const article = await this.findOne(id);
Object.assign(article, dto);
return await this.articleRepository.save(article);
}
async remove(id: string): Promise<void> {
const article = await this.findOne(id);
await this.articleRepository.remove(article);
}
async syncFromStrapi(
strapiId: string,
data: Partial<CreateArticleDto>,
): Promise<Article> {
let article = await this.articleRepository.findOne({ where: { strapiId } });
if (!article) {
article = this.articleRepository.create({
strapiId,
...data,
status: data.status || ArticleStatus.DRAFT,
});
} else {
Object.assign(article, data);
}
return await this.articleRepository.save(article);
}
}