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

+156
View File
@@ -0,0 +1,156 @@
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { HttpService } from '@nestjs/axios';
import { lastValueFrom } from 'rxjs';
import { ArticlesService } from './articles.service';
import { CreateArticleDto } from './articles.dto';
import { ArticleStatus } from './entities';
interface StrapiArticle {
id: number;
documentId: string;
title: string;
description: string;
content: string;
slug: string;
publishedAt: string | null;
createdAt: string;
updatedAt: string;
}
interface StrapiResponse<T> {
data: T;
meta: {
pagination: {
page: number;
pageSize: number;
pageCount: number;
total: number;
};
};
}
@Injectable()
export class StrapiService {
private readonly logger = new Logger(StrapiService.name);
private readonly strapiUrl: string;
private readonly strapiApiToken: string;
constructor(
private readonly configService: ConfigService,
private readonly httpService: HttpService,
private readonly articlesService: ArticlesService,
) {
this.strapiUrl =
this.configService.get<string>('STRAPI_URL') || 'http://localhost:1337';
this.strapiApiToken =
this.configService.get<string>('STRAPI_API_TOKEN') || '';
}
private getHeaders() {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.strapiApiToken) {
headers['Authorization'] = `Bearer ${this.strapiApiToken}`;
}
return headers;
}
async syncArticles(): Promise<void> {
try {
this.logger.log('Starting articles sync from Strapi...');
const response = await lastValueFrom(
this.httpService.get<StrapiResponse<StrapiArticle[]>>(
`${this.strapiUrl}/api/articles`,
{
headers: this.getHeaders(),
},
),
);
const strapiArticles = response.data.data;
let syncedCount = 0;
for (const strapiArticle of strapiArticles) {
const articleData: Partial<CreateArticleDto> = {
title: strapiArticle.title,
excerpt: strapiArticle.description,
content: strapiArticle.content,
slug: strapiArticle.slug,
status: strapiArticle.publishedAt
? ArticleStatus.PUBLISHED
: ArticleStatus.DRAFT,
tags: [],
};
await this.articlesService.syncFromStrapi(
strapiArticle.documentId,
articleData,
);
syncedCount++;
}
this.logger.log(
`Successfully synced ${syncedCount} articles from Strapi`,
);
} catch (error) {
this.logger.error('Failed to sync articles from Strapi', error);
throw error;
}
}
async syncSingleArticle(strapiId: string): Promise<void> {
try {
this.logger.log(`Syncing single article from Strapi: ${strapiId}`);
const response = await lastValueFrom(
this.httpService.get<StrapiResponse<StrapiArticle>>(
`${this.strapiUrl}/api/articles/${strapiId}`,
{
headers: this.getHeaders(),
},
),
);
const strapiArticle = response.data.data;
const articleData: Partial<CreateArticleDto> = {
title: strapiArticle.title,
excerpt: strapiArticle.description,
content: strapiArticle.content,
slug: strapiArticle.slug,
status: strapiArticle.publishedAt
? ArticleStatus.PUBLISHED
: ArticleStatus.DRAFT,
tags: [],
};
await this.articlesService.syncFromStrapi(
strapiArticle.documentId,
articleData,
);
this.logger.log(`Successfully synced article: ${strapiArticle.title}`);
} catch (error) {
this.logger.error(
`Failed to sync article ${strapiId} from Strapi`,
error,
);
throw error;
}
}
async handleWebhook(
event: 'entry.create' | 'entry.update' | 'entry.delete',
data: { documentId: string },
): Promise<void> {
this.logger.log(`Received webhook event: ${event}`);
if (event === 'entry.delete') {
this.logger.log(`Handling delete for document: ${data.documentId}`);
return;
}
await this.syncSingleArticle(data.documentId);
}
}