import type {
JsonRecord,
ZendeskArticle,
ZendeskMe,
ZendeskPageInfo,
ZendeskTicket,
ZendeskTicketComment,
ZendeskUser,
} from './types.ts'
function asRecord(value: unknown): JsonRecord {
return value && typeof value === 'object' && !Array.isArray(value)
? (value as JsonRecord)
: {}
}
function asString(value: unknown): string | null {
return typeof value === 'string' && value.length > 0 ? value : null
}
function asNumber(value: unknown): number | null {
if (typeof value === 'number' && Number.isFinite(value)) return value
if (typeof value === 'string' && value.trim().length > 0) {
const parsed = Number(value)
return Number.isFinite(parsed) ? parsed : null
}
return null
}
function asBoolean(value: unknown): boolean | null {
return typeof value === 'boolean' ? value : null
}
function requireId(value: unknown): number | null {
const id = asNumber(value)
return id === null ? null : id
}
export function mapMe(value: unknown): ZendeskMe {
const record = asRecord(value)
const user = record.user ? asRecord(record.user) : record
const id = requireId(user.id)
if (id === null) throw new Error('Zendesk /users/me did not return a user id.')
return {
id,
name: asString(user.name),
role: asString(user.role),
active: asBoolean(user.active),
}
}
export function mapTicket(value: unknown): ZendeskTicket | null {
const record = asRecord(value)
const ticket = record.ticket ? asRecord(record.ticket) : record
const id = requireId(ticket.id)
if (id === null) return null
return {
id,
subject: asString(ticket.subject),
status: asString(ticket.status),
priority: asString(ticket.priority),
type: asString(ticket.type),
requesterId: asNumber(ticket.requester_id),
assigneeId: asNumber(ticket.assignee_id),
createdAt: asString(ticket.created_at),
updatedAt: asString(ticket.updated_at),
}
}
export function mapTicketComment(value: unknown): ZendeskTicketComment | null {
const record = asRecord(value)
const id = requireId(record.id)
if (id === null) return null
return {
id,
authorId: asNumber(record.author_id),
public: asBoolean(record.public),
body: asString(record.plain_body) ?? asString(record.body),
createdAt: asString(record.created_at),
}
}
export function mapUser(value: unknown): ZendeskUser | null {
const record = asRecord(value)
const user = record.user ? asRecord(record.user) : record
const id = requireId(user.id)
if (id === null) return null
return {
id,
name: asString(user.name),
email: asString(user.email),
role: asString(user.role),
active: asBoolean(user.active),
createdAt: asString(user.created_at),
updatedAt: asString(user.updated_at),
}
}
export function mapArticle(value: unknown): ZendeskArticle | null {
const record = asRecord(value)
const article = record.article ? asRecord(record.article) : record
const id = requireId(article.id)
if (id === null) return null
return {
id,
title: asString(article.title),
locale: asString(article.locale),
sectionId: asNumber(article.section_id),
draft: asBoolean(article.draft),
htmlUrl: asString(article.html_url),
createdAt: asString(article.created_at),
updatedAt: asString(article.updated_at),
}
}
export function extractPageInfo(payload: unknown): ZendeskPageInfo {
const record = asRecord(payload)
const nextPage = asString(record.next_page)
const previousPage = asString(record.previous_page)
const count = asNumber(record.count)
const links = asRecord(record.links)
const meta = asRecord(record.meta)
const cursorNext = asString(links.next)
const hasMore = asBoolean(meta.has_more)
return {
hasNextPage: Boolean(nextPage || cursorNext || hasMore === true),
nextPage: nextPage ?? cursorNext,
previousPage,
count,
}
}
export function extractListItems(payload: unknown, keys: Array<string>): Array<unknown> {
if (Array.isArray(payload)) return payload
const record = asRecord(payload)
if (Array.isArray(record.results)) return record.results
for (const key of keys) {
if (Array.isArray(record[key])) return record[key] as Array<unknown>
}
return []
}
export function compactDefined<T extends JsonRecord>(value: T): T {
const output: JsonRecord = {}
for (const [key, item] of Object.entries(value)) {
if (item === undefined) continue
output[key] = item
}
return output as T
}