feat(seo): generate slugs for brands, categories and products, add GET /sitemap and the Postman collection

This commit is contained in:
MastersGame
2026-11-14 11:08:51 +01:00
parent d07c4df52d
commit 657e8a6b30
26 changed files with 750 additions and 12 deletions

View File

@@ -3,6 +3,8 @@ import { BrandHiboutikRepository } from '../../hiboutik/brand.hiboutik.repositor
import { BrandDatabaseRepository } from '../../database/brand.database.repository';
import { BrandConverter } from '../../models/converter/brand.converter';
import { forEachSafely } from '../../utils/sync';
import { SlugService } from '../slug/slug.service';
import { SlugEntityType } from '../../../prisma/generated/client';
@Injectable()
export class BrandHiboutikService {
@@ -12,9 +14,10 @@ export class BrandHiboutikService {
private readonly brandHiboutikRepository: BrandHiboutikRepository,
private readonly brandDatabaseRepository: BrandDatabaseRepository,
private readonly brandConverter: BrandConverter,
private readonly slugService: SlugService,
) {}
/** Mirrors Hiboutik brands: upserts each of them, then deletes the brands missing from Hiboutik. */
/** Mirrors Hiboutik brands: upserts each of them, deletes the brands missing from Hiboutik, then gives a slug to the new ones. */
async syncBrands() {
const hiboutikBrands = await this.brandHiboutikRepository.getBrands();
// One upsert per brand: an invalid brand must not prevent the others from being saved
@@ -27,6 +30,7 @@ export class BrandHiboutikService {
// Hiboutik is trusted: a successful (2xx) answer, even an empty list, is the truth. An HTTP error throws before this point.
const nbDeleted = await this.brandDatabaseRepository.deleteMissing(hiboutikBrands.map((dto) => dto.brand_id));
await this.slugService.assignMissingSlugs(SlugEntityType.BRAND);
this.logger.log(
`Brands sync ended: ${hiboutikBrands.length - nbFailed}/${hiboutikBrands.length} synced, ${nbFailed} failed, ${nbDeleted} deleted.`,
);