Skip to content

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

Package listing

@kody/calendly

src/models.ts

123 lines · 3.8 KB · TypeScript
import type {
	CalendlyAvailableTime,
	CalendlyEventTypeSummary,
	CalendlyInviteeSummary,
	CalendlyPageInfo,
	CalendlyScheduledEventSummary,
	CalendlyUserSummary,
	JsonRecord,
} from './types.ts'
import { uuidFromUri } from './client.ts'

function asRecord(value: unknown): JsonRecord {
	return value && typeof value === 'object' && !Array.isArray(value) ? (value as JsonRecord) : {}
}

function optionalText(value: unknown): string | null {
	return typeof value === 'string' && value.length > 0 ? value : null
}

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

function optionalNumber(value: unknown): number | null {
	return typeof value === 'number' ? value : null
}

function locationLabel(value: unknown): string | null {
	const record = asRecord(value)
	if (typeof record.location === 'string' && record.location.length > 0) return record.location
	if (typeof record.join_url === 'string' && record.join_url.length > 0) return record.join_url
	if (typeof record.type === 'string' && record.type.length > 0) return record.type
	return null
}

export function mapUser(value: unknown): CalendlyUserSummary {
	const record = asRecord(value)
	const uri = optionalText(record.uri) ?? ''
	return {
		uri,
		uuid: uri ? uuidFromUri(uri) : '',
		name: optionalText(record.name),
		slug: optionalText(record.slug),
		timezone: optionalText(record.timezone),
		schedulingUrl: optionalText(record.scheduling_url),
		organization: optionalText(record.current_organization),
	}
}

export function mapEventType(value: unknown): CalendlyEventTypeSummary {
	const record = asRecord(value)
	const uri = optionalText(record.uri) ?? ''
	return {
		uri,
		uuid: uri ? uuidFromUri(uri) : '',
		name: optionalText(record.name),
		slug: optionalText(record.slug),
		active: optionalBoolean(record.active),
		duration: optionalNumber(record.duration),
		kind: optionalText(record.kind),
		type: optionalText(record.type),
		schedulingUrl: optionalText(record.scheduling_url),
		color: optionalText(record.color),
		secret: optionalBoolean(record.secret),
	}
}

export function mapScheduledEvent(value: unknown): CalendlyScheduledEventSummary {
	const record = asRecord(value)
	const uri = optionalText(record.uri) ?? ''
	const counter = asRecord(record.invitees_counter)
	return {
		uri,
		uuid: uri ? uuidFromUri(uri) : '',
		name: optionalText(record.name),
		status: optionalText(record.status),
		startTime: optionalText(record.start_time),
		endTime: optionalText(record.end_time),
		eventType: optionalText(record.event_type),
		location: locationLabel(record.location),
		inviteesActive: optionalNumber(counter.active),
		inviteesLimit: optionalNumber(counter.limit),
		inviteesTotal: optionalNumber(counter.total),
		createdAt: optionalText(record.created_at),
	}
}

export function mapInvitee(value: unknown): CalendlyInviteeSummary {
	const record = asRecord(value)
	const uri = optionalText(record.uri) ?? ''
	return {
		uri,
		uuid: uri ? uuidFromUri(uri) : '',
		name: optionalText(record.name),
		email: optionalText(record.email),
		status: optionalText(record.status),
		timezone: optionalText(record.timezone),
		event: optionalText(record.event),
		cancelUrl: optionalText(record.cancel_url),
		rescheduleUrl: optionalText(record.reschedule_url),
		rescheduled: optionalBoolean(record.rescheduled),
		createdAt: optionalText(record.created_at),
	}
}

export function mapAvailableTime(value: unknown): CalendlyAvailableTime {
	const record = asRecord(value)
	return {
		status: optionalText(record.status),
		inviteesRemaining: optionalNumber(record.invitees_remaining),
		startTime: optionalText(record.start_time),
	}
}

export function emptyPageInfo(): CalendlyPageInfo {
	return {
		count: null,
		nextPageToken: null,
		previousPageToken: null,
		nextPage: null,
		previousPage: null,
	}
}