import type { IntercomArticle, IntercomContact, IntercomConversation, IntercomMe, IntercomPageInfo, JsonRecord, } 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 { return typeof value === 'number' && Number.isFinite(value) ? value : null } function asBoolean(value: unknown): boolean | null { return typeof value === 'boolean' ? value : null } export function mapMe(value: unknown): IntercomMe { const record = asRecord(value) const app = asRecord(record.app) const id = asString(record.id) if (!id) throw new Error('Intercom /me did not return an admin id.') return { id, type: asString(record.type) ?? 'admin', hasInboxSeat: asBoolean(record.has_inbox_seat), app: { idCode: asString(app.id_code), region: asString(app.region), }, } } export function mapContact(value: unknown): IntercomContact | null { const record = asRecord(value) const id = asString(record.id) if (!id) return null return { id, role: asString(record.role), email: asString(record.email), name: asString(record.name), externalId: asString(record.external_id), createdAt: asNumber(record.created_at), updatedAt: asNumber(record.updated_at), } } export function mapConversation(value: unknown): IntercomConversation | null { const record = asRecord(value) const id = asString(record.id) if (!id) return null const contacts = asRecord(record.contacts) const contactItems = Array.isArray(contacts.contacts) ? contacts.contacts : [] const source = asRecord(record.source) return { id, title: asString(record.title) ?? asString(source.subject), state: asString(record.state), open: asBoolean(record.open), createdAt: asNumber(record.created_at), updatedAt: asNumber(record.updated_at), contactIds: contactItems .map((item) => asString(asRecord(item).id)) .filter((item): item is string => Boolean(item)), } } export function mapArticle(value: unknown): IntercomArticle | null { const record = asRecord(value) const id = asString(record.id) ?? (record.id != null ? String(record.id) : null) if (!id) return null return { id, title: asString(record.title), state: asString(record.state), url: asString(record.url), authorId: asString(record.author_id) ?? (record.author_id != null ? String(record.author_id) : null), createdAt: asNumber(record.created_at), updatedAt: asNumber(record.updated_at), } } export function extractPageInfo(payload: unknown): IntercomPageInfo { const record = asRecord(payload) const pages = record.pages && typeof record.pages === 'object' ? asRecord(record.pages) : null const next = pages?.next let startingAfter: string | null = null if (next && typeof next === 'object') { const cursor = (next as { starting_after?: unknown }).starting_after if (typeof cursor === 'string' && cursor.length > 0) startingAfter = cursor } else if (typeof next === 'string' && next.length > 0) { startingAfter = next } const page = typeof pages?.page === 'number' ? pages.page : null const perPage = typeof pages?.per_page === 'number' ? pages.per_page : null const totalPages = typeof pages?.total_pages === 'number' ? pages.total_pages : null const totalCount = typeof record.total_count === 'number' ? record.total_count : null return { hasNextPage: Boolean(startingAfter) || (totalPages !== null && page !== null && page < totalPages), startingAfter, page, perPage, totalPages, totalCount, } } export function extractListItems(payload: unknown): Array { if (Array.isArray(payload)) return payload const record = asRecord(payload) if (Array.isArray(record.data)) return record.data if (Array.isArray(record.articles)) return record.articles if (Array.isArray(record.conversations)) return record.conversations if (Array.isArray(record.contacts)) return record.contacts return [] } export function compactDefined(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 }