Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/trello

src/models.ts

164 lines · 4.7 KB · TypeScript
import type {
	JsonRecord,
	TrelloBoardSummary,
	TrelloCardSummary,
	TrelloCommentSummary,
	TrelloLabelSummary,
	TrelloListSummary,
	TrelloMemberSummary,
	TrelloOrganizationSummary,
} from './types.ts'

export const MEMBER_FIELDS = 'id,username,fullName,url,initials'
export const ORG_FIELDS = 'id,name,displayName,url'
export const BOARD_FIELDS = 'id,name,desc,closed,url,shortUrl,shortLink,idOrganization,dateLastActivity'
export const LIST_FIELDS = 'id,name,closed,idBoard,pos'
export const CARD_FIELDS =
	'id,name,desc,closed,idList,idBoard,url,shortUrl,due,dueComplete,pos,labels,idMembers,dateLastActivity'

function asString(value: unknown): string | null {
	return typeof value === 'string' ? value : null
}

function asBoolean(value: unknown): boolean | null {
	return typeof value === 'boolean' ? value : null
}

function asNumber(value: unknown): number | null {
	return typeof value === 'number' && Number.isFinite(value) ? value : null
}

export function memberSummary(
	member: Record<string, unknown> | null | undefined,
): TrelloMemberSummary | null {
	if (typeof member?.id !== 'string') return null
	return {
		id: member.id,
		username: asString(member.username),
		fullName: asString(member.fullName),
		url: asString(member.url),
		initials: asString(member.initials),
	}
}

export function organizationSummary(
	org: Record<string, unknown> | null | undefined,
): TrelloOrganizationSummary | null {
	if (typeof org?.id !== 'string') return null
	return {
		id: org.id,
		name: asString(org.name),
		displayName: asString(org.displayName),
		url: asString(org.url),
	}
}

export function boardSummary(
	board: Record<string, unknown> | null | undefined,
): TrelloBoardSummary | null {
	if (typeof board?.id !== 'string' || typeof board.name !== 'string') return null
	return {
		id: board.id,
		name: board.name,
		desc: asString(board.desc),
		closed: asBoolean(board.closed),
		url: asString(board.url),
		shortUrl: asString(board.shortUrl),
		shortLink: asString(board.shortLink),
		idOrganization: asString(board.idOrganization),
		dateLastActivity: asString(board.dateLastActivity),
	}
}

export function listSummary(
	list: Record<string, unknown> | null | undefined,
): TrelloListSummary | null {
	if (typeof list?.id !== 'string' || typeof list.name !== 'string') return null
	return {
		id: list.id,
		name: list.name,
		closed: asBoolean(list.closed),
		idBoard: asString(list.idBoard),
		pos: asNumber(list.pos),
	}
}

export function labelSummary(
	label: Record<string, unknown> | null | undefined,
): TrelloLabelSummary | null {
	if (typeof label?.id !== 'string') return null
	return {
		id: label.id,
		name: asString(label.name),
		color: asString(label.color),
	}
}

export function cardSummary(
	card: Record<string, unknown> | null | undefined,
): TrelloCardSummary | null {
	if (typeof card?.id !== 'string' || typeof card.name !== 'string') return null
	const labels = Array.isArray(card.labels)
		? card.labels
				.map((item) => (item && typeof item === 'object' ? labelSummary(item as JsonRecord) : null))
				.filter((item): item is TrelloLabelSummary => item !== null)
		: []
	const idMembers = Array.isArray(card.idMembers)
		? card.idMembers.filter((item): item is string => typeof item === 'string')
		: []
	return {
		id: card.id,
		name: card.name,
		desc: asString(card.desc),
		closed: asBoolean(card.closed),
		idList: asString(card.idList),
		idBoard: asString(card.idBoard),
		url: asString(card.url),
		shortUrl: asString(card.shortUrl),
		due: asString(card.due),
		dueComplete: asBoolean(card.dueComplete),
		pos: asNumber(card.pos),
		idMembers,
		labels,
		dateLastActivity: asString(card.dateLastActivity),
	}
}

export function commentSummary(
	action: Record<string, unknown> | null | undefined,
): TrelloCommentSummary | null {
	if (typeof action?.id !== 'string') return null
	const data = action.data && typeof action.data === 'object' ? (action.data as JsonRecord) : {}
	const card =
		data.card && typeof data.card === 'object' ? (data.card as { id?: unknown }) : null
	const creator =
		action.memberCreator && typeof action.memberCreator === 'object'
			? memberSummary(action.memberCreator as JsonRecord)
			: null
	return {
		id: action.id,
		text: asString(data.text),
		date: asString(action.date),
		cardId: typeof card?.id === 'string' ? card.id : null,
		memberCreator: creator,
	}
}

export function requireMapped<T>(
	value: T | null,
	action: string,
): T {
	if (!value) throw new Error(`${action}: Trello returned no matching record.`)
	return value
}

export function mapMany<T>(
	items: unknown,
	mapper: (item: Record<string, unknown>) => T | null,
): Array<T> {
	if (!Array.isArray(items)) return []
	return items
		.filter((item): item is Record<string, unknown> => Boolean(item && typeof item === 'object'))
		.map(mapper)
		.filter((item): item is T => item !== null)
}