Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Successful in 1m0s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
127 lines
3.5 KiB
TypeScript
127 lines
3.5 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { getPayload } from 'payload';
|
|
import configPromise from '../../../payload.config';
|
|
import { upsertProductVector } from '../../../src/lib/qdrant';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
export const maxDuration = 120;
|
|
|
|
/**
|
|
* Internal endpoint called by the warmup script on every dev boot.
|
|
* Syncs posts, pages, and products from Payload CMS into Qdrant.
|
|
* NOT for form entries, media, or users.
|
|
*/
|
|
export async function GET() {
|
|
const results = { products: 0, posts: 0, pages: 0, errors: [] as string[] };
|
|
|
|
try {
|
|
const payload = await getPayload({ config: configPromise });
|
|
|
|
// ── Products ──
|
|
const { docs: products } = await payload.find({
|
|
collection: 'products',
|
|
limit: 1000,
|
|
depth: 0,
|
|
where: { _status: { equals: 'published' } },
|
|
});
|
|
|
|
for (const product of products) {
|
|
try {
|
|
const contentText = `${product.title} - SKU: ${product.sku}\n${product.description || ''}`;
|
|
await upsertProductVector(String(product.id), contentText, {
|
|
type: 'product',
|
|
data: {
|
|
title: product.title,
|
|
sku: product.sku,
|
|
slug: product.slug,
|
|
description: product.description,
|
|
},
|
|
});
|
|
results.products++;
|
|
} catch (e: any) {
|
|
results.errors.push(`product:${product.sku}: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
// ── Posts ──
|
|
const { docs: posts } = await payload.find({
|
|
collection: 'posts',
|
|
limit: 1000,
|
|
depth: 0,
|
|
where: { _status: { equals: 'published' } },
|
|
});
|
|
|
|
for (const post of posts) {
|
|
try {
|
|
const contentText = [
|
|
`Blog-Artikel: ${post.title}`,
|
|
post.excerpt ? `Zusammenfassung: ${post.excerpt}` : '',
|
|
post.category ? `Kategorie: ${post.category}` : '',
|
|
]
|
|
.filter(Boolean)
|
|
.join('\n');
|
|
|
|
await upsertProductVector(`post_${post.id}`, contentText, {
|
|
type: 'knowledge',
|
|
content: contentText,
|
|
data: {
|
|
title: post.title,
|
|
slug: post.slug,
|
|
},
|
|
});
|
|
results.posts++;
|
|
} catch (e: any) {
|
|
results.errors.push(`post:${post.slug}: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
// ── Pages ──
|
|
const { docs: pages } = await payload.find({
|
|
collection: 'pages',
|
|
limit: 1000,
|
|
depth: 0,
|
|
where: { _status: { equals: 'published' } },
|
|
});
|
|
|
|
for (const page of pages) {
|
|
try {
|
|
const contentText = [
|
|
`Seite: ${page.title}`,
|
|
page.excerpt ? `Beschreibung: ${page.excerpt}` : '',
|
|
]
|
|
.filter(Boolean)
|
|
.join('\n');
|
|
|
|
await upsertProductVector(`page_${page.id}`, contentText, {
|
|
type: 'knowledge',
|
|
content: contentText,
|
|
data: {
|
|
title: page.title,
|
|
slug: page.slug,
|
|
},
|
|
});
|
|
results.pages++;
|
|
} catch (e: any) {
|
|
results.errors.push(`page:${page.slug}: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
console.log(
|
|
`[Qdrant Sync] ✅ ${results.products} products, ${results.posts} posts, ${results.pages} pages synced`,
|
|
);
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
synced: {
|
|
products: results.products,
|
|
posts: results.posts,
|
|
pages: results.pages,
|
|
},
|
|
errors: results.errors.length > 0 ? results.errors : undefined,
|
|
});
|
|
} catch (error: any) {
|
|
console.error('[Qdrant Sync] ❌ Fatal error:', error);
|
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
}
|
|
}
|