Skip to content

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

Package listing

@kody/linear

src/models.ts

158 lines · 4.3 KB · TypeScript
import type {
	JsonRecord,
	LinearCommentSummary,
	LinearIssueSummary,
	LinearNamedRef,
	LinearPageInfo,
	LinearProjectSummary,
	LinearTeamSummary,
	LinearWorkflowStateSummary,
} from './types.ts'

export const ISSUE_FIELDS = `
	id
	identifier
	title
	url
	priority
	createdAt
	updatedAt
	state { id name type }
	team { id name key }
	assignee { id name }
	project { id name }
`

export const COMMENT_FIELDS = `
	id
	body
	url
	createdAt
	updatedAt
	user { id name }
`

export const PROJECT_FIELDS = `
	id
	name
	url
	description
	status { id name type }
	startDate
	targetDate
	progress
`

export const TEAM_FIELDS = `
	id
	name
	key
	description
`

export const WORKFLOW_STATE_FIELDS = `
	id
	name
	type
	team { id name key }
`

export const PAGE_INFO_FIELDS = `
	pageInfo { hasNextPage endCursor }
`

export function namedRef(value: unknown): LinearNamedRef | null {
	if (!value || typeof value !== 'object') return null
	const record = value as JsonRecord
	if (typeof record.id !== 'string' || record.id.length === 0) return null
	return {
		id: record.id,
		name: typeof record.name === 'string' ? record.name : '',
		key: typeof record.key === 'string' ? record.key : undefined,
		type: typeof record.type === 'string' ? record.type : undefined,
	}
}

export function mapIssue(value: unknown): LinearIssueSummary {
	const record = (value && typeof value === 'object' ? value : {}) as JsonRecord
	return {
		id: String(record.id || ''),
		identifier: String(record.identifier || ''),
		title: String(record.title || ''),
		url: typeof record.url === 'string' ? record.url : null,
		priority: typeof record.priority === 'number' ? record.priority : null,
		createdAt: typeof record.createdAt === 'string' ? record.createdAt : null,
		updatedAt: typeof record.updatedAt === 'string' ? record.updatedAt : null,
		state: namedRef(record.state),
		team: namedRef(record.team),
		assignee: namedRef(record.assignee),
		project: namedRef(record.project),
	}
}

export function mapComment(value: unknown): LinearCommentSummary {
	const record = (value && typeof value === 'object' ? value : {}) as JsonRecord
	return {
		id: String(record.id || ''),
		body: typeof record.body === 'string' ? record.body : null,
		url: typeof record.url === 'string' ? record.url : null,
		createdAt: typeof record.createdAt === 'string' ? record.createdAt : null,
		updatedAt: typeof record.updatedAt === 'string' ? record.updatedAt : null,
		user: namedRef(record.user),
	}
}

export function mapProject(value: unknown): LinearProjectSummary {
	const record = (value && typeof value === 'object' ? value : {}) as JsonRecord
	const state =
		typeof record.state === 'string'
			? record.state
			: namedRef(record.status)?.name ?? namedRef(record.state)?.name ?? null
	return {
		id: String(record.id || ''),
		name: String(record.name || ''),
		url: typeof record.url === 'string' ? record.url : null,
		description: typeof record.description === 'string' ? record.description : null,
		state,
		startDate: typeof record.startDate === 'string' ? record.startDate : null,
		targetDate: typeof record.targetDate === 'string' ? record.targetDate : null,
		progress: typeof record.progress === 'number' ? record.progress : null,
	}
}

export function mapTeam(value: unknown): LinearTeamSummary {
	const record = (value && typeof value === 'object' ? value : {}) as JsonRecord
	return {
		id: String(record.id || ''),
		name: String(record.name || ''),
		key: String(record.key || ''),
		description: typeof record.description === 'string' ? record.description : null,
	}
}

export function mapWorkflowState(value: unknown): LinearWorkflowStateSummary {
	const record = (value && typeof value === 'object' ? value : {}) as JsonRecord
	return {
		id: String(record.id || ''),
		name: String(record.name || ''),
		type: String(record.type || ''),
		team: namedRef(record.team),
	}
}

export function nodesFromConnection<T>(value: unknown): Array<T> {
	if (!value || typeof value !== 'object') return []
	const record = value as { nodes?: unknown }
	return Array.isArray(record.nodes) ? (record.nodes as Array<T>) : []
}

export function pageInfoFromConnection(value: unknown): LinearPageInfo {
	const info =
		value && typeof value === 'object'
			? ((value as { pageInfo?: Record<string, unknown> }).pageInfo ?? {})
			: {}
	return {
		hasNextPage: Boolean(info.hasNextPage),
		endCursor: typeof info.endCursor === 'string' ? info.endCursor : null,
	}
}