Spaces:
Running
Running
Download api/v2/_services/certificationSystem.ts from Sarvesh213/getcert-backend: direct link, hf CLI and curl.
- Browser
- Download file 5.3 kB
-
https://huggingface.co/spaces/Sarvesh213/getcert-backend/resolve/main/api/v2/_services/certificationSystem.ts
- Command line
-
hf download hf://spaces/Sarvesh213/getcert-backend/api/v2/_services/certificationSystem.ts
-
curl -L -o certificationSystem.ts https://huggingface.co/spaces/Sarvesh213/getcert-backend/resolve/main/api/v2/_services/certificationSystem.ts
5.3 kB
| import type { CertificatePayload, CertificationTrack, ScoreBreakdown, ValidationSummary } from '../_types.js'; | |
| import { getSupabaseAdmin, getSupabaseClientForRequest } from '../_shared/supabaseAdmin.js'; | |
| function makeCertificateId(skill: string, track: CertificationTrack = 'verifiedcert'): string { | |
| const date = new Date(); | |
| const y = date.getUTCFullYear(); | |
| const m = String(date.getUTCMonth() + 1).padStart(2, '0'); | |
| const d = String(date.getUTCDate()).padStart(2, '0'); | |
| const suffix = Math.random().toString(36).slice(2, 10).toUpperCase(); | |
| const normalizedSkill = skill.replace(/[^a-zA-Z0-9]/g, '').slice(0, 6).toUpperCase() || 'SKILL'; | |
| const prefix = track === 'free_completion' ? 'FC' : track === 'quickcert' ? 'QC' : track === 'ytcert' ? 'YT' : 'VC'; | |
| return `${prefix}-${normalizedSkill}-${y}${m}${d}-${suffix}`; | |
| } | |
| export async function issueCertificate(input: { | |
| userId: string; | |
| name: string; | |
| email: string; | |
| skill: string; | |
| projectTitle: string; | |
| githubUrl: string; | |
| proofUrl: string; | |
| liveDemoUrl?: string; | |
| finalScore?: number; | |
| scoreBreakdown?: ScoreBreakdown; | |
| validationSummary?: ValidationSummary; | |
| projectType?: string; | |
| commitCount?: number; | |
| paymentRequestId?: string; | |
| paymentTxnId?: string | null; | |
| extraMetadata?: Record<string, unknown>; | |
| authToken?: string | null; | |
| track?: CertificationTrack; | |
| }): Promise<CertificatePayload> { | |
| const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY; | |
| const supabase = (!input.authToken && serviceRoleKey) ? getSupabaseAdmin() : getSupabaseClientForRequest(input.authToken); | |
| const certTrack = input.track || 'verifiedcert'; | |
| if (input.paymentRequestId) { | |
| const { data: existing } = await supabase | |
| .from('certificates') | |
| .select('user_id, topic, project_title, issued_at, metadata') | |
| .eq('metadata->>payment_request_id', input.paymentRequestId) | |
| .order('issued_at', { ascending: false }) | |
| .limit(1) | |
| .maybeSingle(); | |
| if (existing) { | |
| return { | |
| certificateId: (existing.metadata as any)?.certificate_id || makeCertificateId(existing.topic || input.skill, certTrack), | |
| userId: existing.user_id, | |
| name: (existing.metadata as any)?.username || (existing as any).username || input.name, | |
| skill: existing.topic, | |
| projectTitle: existing.project_title || input.projectTitle, | |
| githubUrl: (existing.metadata as any)?.github_repo_url || (existing.metadata as any)?.github_url || input.githubUrl, | |
| proofUrl: (existing.metadata as any)?.live_demo_url || (existing.metadata as any)?.proof_url || input.proofUrl, | |
| issuedAt: existing.issued_at, | |
| track: certTrack, | |
| }; | |
| } | |
| } | |
| const certificateId = makeCertificateId(input.skill, certTrack); | |
| const payload: CertificatePayload = { | |
| certificateId, | |
| userId: input.userId, | |
| name: input.name, | |
| skill: input.skill, | |
| projectTitle: input.projectTitle, | |
| githubUrl: input.githubUrl, | |
| proofUrl: input.proofUrl, | |
| issuedAt: new Date().toISOString(), | |
| track: certTrack, | |
| }; | |
| const normalizedScoreBreakdown = input.scoreBreakdown | |
| ? { | |
| interview_score: input.scoreBreakdown.interviewScore, | |
| github_validation_score: input.scoreBreakdown.githubValidationScore, | |
| proof_validation_score: input.scoreBreakdown.proofValidationScore, | |
| commit_score: input.scoreBreakdown.commitScore, | |
| structure_score: input.scoreBreakdown.structureScore, | |
| readme_score: input.scoreBreakdown.readmeScore, | |
| } | |
| : null; | |
| const normalizedValidationSummary = input.validationSummary | |
| ? { | |
| overall_passed: input.validationSummary.overallPassed, | |
| commit_passed: input.validationSummary.commitPassed, | |
| readme_passed: input.validationSummary.readmePassed, | |
| proof_passed: input.validationSummary.proofPassed, | |
| commit_count: input.validationSummary.commitCount, | |
| file_count: input.validationSummary.fileCount, | |
| meaningful_file_count: input.validationSummary.meaningfulFileCount, | |
| readme_richness: input.validationSummary.readmeRichness, | |
| suspicious_signals: input.validationSummary.suspiciousSignals, | |
| } | |
| : null; | |
| const { error } = await supabase.from('certificates').insert({ | |
| user_id: input.userId, | |
| topic: input.skill, | |
| project_title: input.projectTitle, | |
| metadata: { | |
| certificate_id: certificateId, | |
| username: input.name, | |
| email: input.email, | |
| course_topic: input.skill, | |
| project_topic: input.projectTitle, | |
| github_repo_url: input.githubUrl, | |
| live_demo_url: input.liveDemoUrl || input.proofUrl, | |
| final_score: input.finalScore ?? null, | |
| score_breakdown: normalizedScoreBreakdown, | |
| project_type: input.projectType || null, | |
| commit_count: input.commitCount ?? null, | |
| validation_summary: normalizedValidationSummary, | |
| github_url: input.githubUrl, | |
| proof_url: input.proofUrl, | |
| getcert_version: 'v2', | |
| certification_track: certTrack, | |
| payment_request_id: input.paymentRequestId || null, | |
| payment_txn_id: input.paymentTxnId || null, | |
| ...(input.extraMetadata || {}), | |
| }, | |
| issued_at: payload.issuedAt, | |
| }); | |
| if (error) { | |
| throw new Error(`Failed to issue certificate: ${error.message}`); | |
| } | |
| return payload; | |
| } | |