sync: claim removal fix, auto-crawl email, progress bar, search optimization

- Fix claim removal request flow
- Add email notification on auto-crawl skill discovery
- Add progress bar component
- Optimize Meilisearch sync and search indexing
- Improve skill parser and queries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
airano
2026-02-22 04:58:01 +03:30
parent b05cb21a65
commit 0713607693
15 changed files with 352 additions and 14 deletions

View File

@@ -64,6 +64,8 @@ export default async function ClaimPage({
success: {
title: t('success.title'),
description: t('success.description'),
pendingTitle: t('success.pendingTitle'),
pendingDescription: t('success.pendingDescription'),
viewRequests: t('success.viewRequests'),
},
addSuccess: {

View File

@@ -6,6 +6,7 @@ import { locales, localeDirection, type Locale } from '@/i18n';
import { Providers } from '../providers';
import { Suspense } from 'react';
import { QueryNotification } from '@/components/QueryNotification';
import { ProgressBar } from '@/components/ProgressBar';
import '../globals.css';
export async function generateMetadata({
@@ -70,6 +71,7 @@ export default async function LocaleLayout({
<Suspense fallback={null}>
<QueryNotification />
</Suspense>
<ProgressBar />
{children}
</NextIntlClientProvider>
</Providers>

View File

@@ -1,7 +1,7 @@
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { auth } from '@/lib/auth';
import { createDb, addRequestQueries, userQueries } from '@skillhub/db';
import { createDb, addRequestQueries, discoveredRepoQueries, userQueries } from '@skillhub/db';
import { sanitizeReason } from '@/lib/sanitize';
import { sendClaimSubmittedEmail } from '@/lib/email';
@@ -389,6 +389,26 @@ export async function POST(request: NextRequest) {
hasSkillMd: validation.hasSkillMd,
});
// Auto-approve and queue for crawling if SKILL.md found
if (validation.hasSkillMd && validation.skillPaths.length > 0) {
await addRequestQueries.updateStatus(db, requestId, {
status: 'approved',
});
// Queue repo for indexer crawling via discovered_repos
try {
await discoveredRepoQueries.upsert(db, {
id: `${parsed.owner}/${parsed.repo}`,
owner: parsed.owner,
repo: parsed.repo,
discoveredVia: 'add-request',
githubStars: 0,
});
} catch (err) {
console.warn('[Claim] Failed to queue repo for crawling:', err);
}
}
// Build appropriate response message
let message: string;
if (validation.skillPaths.length > 1) {

View File

@@ -124,6 +124,7 @@ export async function POST(request: NextRequest) {
// Check repository ownership using public API (no token needed for public repos)
let isOwner = false;
let repoDeleted = false;
let githubError: string | null = null;
try {
@@ -144,7 +145,7 @@ export async function POST(request: NextRequest) {
isOwner = true;
}
} else if (repoResponse.status === 404) {
githubError = 'Repository not found on GitHub';
repoDeleted = true;
} else if (repoResponse.status === 403) {
githubError = 'GitHub API rate limit exceeded';
}
@@ -160,23 +161,34 @@ export async function POST(request: NextRequest) {
);
}
if (!isOwner) {
if (!isOwner && !repoDeleted) {
return NextResponse.json(
{ error: 'You are not the owner of this repository', code: 'NOT_OWNER' },
{ status: 403 }
);
}
// Create the removal request (auto-approved since owner is verified)
// Create the removal request
const sanitizedReason = reason ? sanitizeReason(reason) : 'No reason provided';
const requestId = await removalRequestQueries.create(db, {
userId: dbUser.id,
skillId,
reason: sanitizedReason,
verifiedOwner: true,
verifiedOwner: !repoDeleted,
});
// Auto-approve: Block the skill from being re-indexed
if (repoDeleted) {
// Repo not found — submit for admin review instead of auto-approving
return NextResponse.json({
success: true,
requestId,
pending: true,
blocked: false,
message: 'Repository not found on GitHub. Your removal request has been submitted for admin review.',
});
}
// Owner verified — auto-approve: Block the skill from being re-indexed
await skillQueries.block(db, skillId);
// Update the request status to approved