Skip to content

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

Package listing

@kody/datadog

src/dashboards.ts

128 lines · 5.3 KB · TypeScript
import { asStringArray, clean, datadogRequest, mutationPreview, positiveInt } from './core.ts'
import type { DatadogDashboardInput } from './types.ts'

function dashboardId(params: DatadogDashboardInput): string {
	const id = clean(params.dashboardId ?? params.id)
	if (!id) throw new Error('dashboardId is required.')
	return id
}

function summarizeDashboard(dashboard: any) {
	return {
		id: dashboard?.id ?? null,
		title: dashboard?.title ?? null,
		description: dashboard?.description ?? null,
		layoutType: dashboard?.layout_type ?? dashboard?.layoutType ?? null,
		url: dashboard?.url ?? null,
		authorHandle: dashboard?.author_handle ?? dashboard?.authorHandle ?? null,
		createdAt: dashboard?.created_at ?? dashboard?.createdAt ?? null,
		modifiedAt: dashboard?.modified_at ?? dashboard?.modifiedAt ?? null,
		isReadOnly: dashboard?.is_read_only ?? dashboard?.isReadOnly ?? null,
		widgetCount: Array.isArray(dashboard?.widgets) ? dashboard.widgets.length : null,
	}
}

function dashboardBody(params: DatadogDashboardInput): Record<string, unknown> {
	if (params.body && typeof params.body === 'object') return params.body
	const body: Record<string, unknown> = {}
	if (clean(params.title)) body.title = clean(params.title)
	if (clean(params.description)) body.description = clean(params.description)
	if (clean(params.layoutType)) body.layout_type = clean(params.layoutType)
	if (Array.isArray(params.widgets)) body.widgets = params.widgets
	if (Array.isArray(params.templateVariables)) body.template_variables = params.templateVariables
	if (params.isReadOnly != null) body.is_read_only = params.isReadOnly
	if (Array.isArray(params.notifyList)) body.notify_list = params.notifyList
	if (clean(params.reflowType)) body.reflow_type = clean(params.reflowType)
	const tags = asStringArray(params.tags)
	if (tags.length) body.tags = tags
	return body
}

/** List dashboards. GET /api/v1/dashboard */
export async function listDashboards(params: DatadogDashboardInput = {}) {
	const query: Record<string, unknown> = {}
	if (params.filterShared != null) query['filter[shared]'] = params.filterShared
	if (params.filterDeleted != null) query['filter[deleted]'] = params.filterDeleted
	if (params.count != null || params.pageSize != null) {
		query.count = positiveInt(params.count ?? params.pageSize, 100, 1000)
	}
	if (params.start != null) query.start = positiveInt(params.start, 0, 100_000)
	const body = await datadogRequest('/api/v1/dashboard', { ...params, query })
	const dashboards = Array.isArray(body?.dashboards) ? body.dashboards : Array.isArray(body) ? body : []
	return {
		count: dashboards.length,
		total: body?.total ?? dashboards.length,
		dashboards: dashboards.map(summarizeDashboard),
	}
}

/** Get one dashboard. GET /api/v1/dashboard/{dashboard_id} */
export async function getDashboard(params: DatadogDashboardInput = {}) {
	const id = dashboardId(params)
	const dashboard = await datadogRequest('/api/v1/dashboard/' + encodeURIComponent(id), params)
	return { dashboard: summarizeDashboard(dashboard), raw: dashboard }
}

/** Create a dashboard. Requires confirm. Pass dryRun: true to preview. */
export async function createDashboard(params: DatadogDashboardInput = {}) {
	const body = dashboardBody(params)
	if (!clean(body.title) || !clean(body.layout_type)) {
		throw new Error('Creating a dashboard requires title and layoutType (or a full body).')
	}
	if (!Array.isArray(body.widgets)) body.widgets = []
	const preview = mutationPreview(params, {
		action: 'create dashboard ' + clean(body.title),
		method: 'POST',
		path: '/api/v1/dashboard',
		body,
	})
	if (preview) return preview
	const created = await datadogRequest('/api/v1/dashboard', { ...params, method: 'POST', body })
	return { ok: true, action: 'create', dashboard: summarizeDashboard(created), raw: created }
}

/** Update a dashboard. Requires confirm. Pass dryRun: true to preview. */
export async function updateDashboard(params: DatadogDashboardInput = {}) {
	const id = dashboardId(params)
	const body = dashboardBody(params)
	const preview = mutationPreview(params, {
		action: 'update dashboard ' + id,
		method: 'PUT',
		path: '/api/v1/dashboard/' + encodeURIComponent(id),
		body,
	})
	if (preview) return preview
	const updated = await datadogRequest('/api/v1/dashboard/' + encodeURIComponent(id), {
		...params,
		method: 'PUT',
		body,
	})
	return { ok: true, action: 'update', dashboard: summarizeDashboard(updated), raw: updated }
}

/** Delete a dashboard. Requires confirm. Pass dryRun: true to preview. */
export async function deleteDashboard(params: DatadogDashboardInput = {}) {
	const id = dashboardId(params)
	const preview = mutationPreview(params, {
		action: 'delete dashboard ' + id,
		method: 'DELETE',
		path: '/api/v1/dashboard/' + encodeURIComponent(id),
	})
	if (preview) return preview
	const deleted = await datadogRequest('/api/v1/dashboard/' + encodeURIComponent(id), {
		...params,
		method: 'DELETE',
	})
	return { ok: true, action: 'delete', dashboardId: id, raw: deleted }
}

/**
 * List or get Datadog dashboards. Mutations live on named exports.
 * @example
 * import { listDashboards } from 'kody:@kody/datadog/dashboards'
 * const result = await listDashboards({ count: 20 })
 */
export default async function dashboards(params: DatadogDashboardInput = {}) {
	if (params.dashboardId || params.id) return await getDashboard(params)
	return await listDashboards(params)
}