edited ci file
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { z } from 'zod'
|
||||
import { api } from '../client'
|
||||
import type { SecretLeak, VulnerabilityFinding } from '../../types/api'
|
||||
|
||||
// ── Zod schemas ───────────────────────────────────────────────────────────────
|
||||
|
||||
const secretLeakSchema = z.object({
|
||||
id: z.number(),
|
||||
repoId: z.number(),
|
||||
commitSha: z.string(),
|
||||
ref: z.string(),
|
||||
patternName: z.string(),
|
||||
description: z.string(),
|
||||
severity: z.string(),
|
||||
matchSample: z.string(),
|
||||
dismissed: z.boolean(),
|
||||
dismissedBy: z.string().optional(),
|
||||
dismissedAt: z.string().nullable().optional(),
|
||||
detectedAt: z.string(),
|
||||
})
|
||||
|
||||
const vulnerabilityFindingSchema = z.object({
|
||||
id: z.number(),
|
||||
repoId: z.number(),
|
||||
vulnId: z.string(),
|
||||
purl: z.string(),
|
||||
version: z.string(),
|
||||
summary: z.string(),
|
||||
details: z.string().optional(),
|
||||
cvssScore: z.number(),
|
||||
fixedVersion: z.string(),
|
||||
dismissed: z.boolean(),
|
||||
dismissedBy: z.string().optional(),
|
||||
dismissedAt: z.string().nullable().optional(),
|
||||
detectedAt: z.string(),
|
||||
})
|
||||
|
||||
// ── Secret Leak queries ───────────────────────────────────────────────────────
|
||||
|
||||
/** Active secret leaks for a repo. */
|
||||
export function useSecretLeaks(owner: string, repo: string) {
|
||||
return useQuery({
|
||||
queryKey: ['repos', owner, repo, 'secrets', 'leaks'],
|
||||
queryFn: () =>
|
||||
api.get<SecretLeak[]>(
|
||||
`/api/v1/repos/${owner}/${repo}/secrets/leaks`,
|
||||
z.array(secretLeakSchema),
|
||||
),
|
||||
enabled: Boolean(owner && repo),
|
||||
refetchInterval: 30_000,
|
||||
})
|
||||
}
|
||||
|
||||
/** Dismiss a secret leak. */
|
||||
export function useDismissSecretLeak(owner: string, repo: string) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (leakId: number) =>
|
||||
api.post(
|
||||
`/api/v1/repos/${owner}/${repo}/secrets/leaks/${leakId}/dismiss`,
|
||||
z.unknown(),
|
||||
undefined,
|
||||
),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['repos', owner, repo, 'secrets', 'leaks'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ── Vulnerability queries ─────────────────────────────────────────────────────
|
||||
|
||||
/** Active vulnerability findings for a repo. */
|
||||
export function useVulnerabilities(owner: string, repo: string) {
|
||||
return useQuery({
|
||||
queryKey: ['repos', owner, repo, 'vulnerabilities'],
|
||||
queryFn: () =>
|
||||
api.get<VulnerabilityFinding[]>(
|
||||
`/api/v1/repos/${owner}/${repo}/vulnerabilities`,
|
||||
z.array(vulnerabilityFindingSchema),
|
||||
),
|
||||
enabled: Boolean(owner && repo),
|
||||
refetchInterval: 30_000,
|
||||
})
|
||||
}
|
||||
|
||||
/** Trigger a vulnerability scan. */
|
||||
export function useScanVulnerabilities(owner: string, repo: string) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: () =>
|
||||
api.post<VulnerabilityFinding[]>(
|
||||
`/api/v1/repos/${owner}/${repo}/vulnerabilities/scan`,
|
||||
z.array(vulnerabilityFindingSchema),
|
||||
undefined,
|
||||
),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['repos', owner, repo, 'vulnerabilities'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/** Dismiss a vulnerability finding. */
|
||||
export function useDismissVulnerability(owner: string, repo: string) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (findingId: number) =>
|
||||
api.post(
|
||||
`/api/v1/repos/${owner}/${repo}/vulnerabilities/${findingId}/dismiss`,
|
||||
z.unknown(),
|
||||
undefined,
|
||||
),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['repos', owner, repo, 'vulnerabilities'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user