import type { GitlabQuery } from './types.ts' export function asRecord(value: unknown): Record { return value && typeof value === 'object' ? (value as Record) : {} } export function asString(value: unknown): string | null { return typeof value === 'string' ? value : null } export function asNumber(value: unknown): number | null { return typeof value === 'number' && Number.isFinite(value) ? value : null } export function asBoolean(value: unknown): boolean | null { return typeof value === 'boolean' ? value : null } export function asStringArray(value: unknown): string[] { if (!Array.isArray(value)) return [] return value.filter((item): item is string => typeof item === 'string') } export function slimProject(data: Record) { return { id: asNumber(data.id), name: asString(data.name), pathWithNamespace: asString(data.path_with_namespace), description: asString(data.description), visibility: asString(data.visibility), defaultBranch: asString(data.default_branch), webUrl: asString(data.web_url), lastActivityAt: asString(data.last_activity_at), archived: asBoolean(data.archived), } } export function slimIssue(data: Record) { const author = asRecord(data.author) return { id: asNumber(data.id), iid: asNumber(data.iid), title: asString(data.title), state: asString(data.state), labels: asStringArray(data.labels), webUrl: asString(data.web_url), createdAt: asString(data.created_at), updatedAt: asString(data.updated_at), author: asString(author.username), } } export function slimMergeRequest(data: Record) { const author = asRecord(data.author) return { id: asNumber(data.id), iid: asNumber(data.iid), title: asString(data.title), state: asString(data.state), draft: asBoolean(data.draft) ?? asBoolean(data.work_in_progress), sourceBranch: asString(data.source_branch), targetBranch: asString(data.target_branch), mergeStatus: asString(data.merge_status), webUrl: asString(data.web_url), createdAt: asString(data.created_at), updatedAt: asString(data.updated_at), author: asString(author.username), } } export function slimPipeline(data: Record) { return { id: asNumber(data.id), iid: asNumber(data.iid), status: asString(data.status), ref: asString(data.ref), sha: asString(data.sha), source: asString(data.source), webUrl: asString(data.web_url), createdAt: asString(data.created_at), updatedAt: asString(data.updated_at), } } export function pickQuery( params: Record, keys: readonly string[], ): GitlabQuery { const query: GitlabQuery = {} for (const key of keys) { const value = params[key] if (value === undefined || value === null) continue if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { query[key] = value } } return query } export function readOptionalBoolean(value: unknown): boolean | undefined { return typeof value === 'boolean' ? value : undefined } export function readOptionalNumber(value: unknown): number | undefined { if (typeof value === 'number' && Number.isFinite(value)) return value if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value))) { return Number(value) } return undefined } export function readOptionalString(value: unknown): string | undefined { return typeof value === 'string' && value.trim() ? value.trim() : undefined }