import type { GitlabQuery } from './types.ts'
export function asRecord(value: unknown): Record<string, unknown> {
return value && typeof value === 'object' ? (value as Record<string, unknown>) : {}
}
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<string, unknown>) {
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<string, unknown>) {
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<string, unknown>) {
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<string, unknown>) {
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<string, unknown>,
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
}