import { asStringArray, clean, datadogRequest, mutationPreview, positiveInt } from './core.ts'
import type { DatadogIncidentInput } from './types.ts'
function incidentId(params: DatadogIncidentInput): string {
const id = clean(params.incidentId ?? params.id)
if (!id) throw new Error('incidentId is required.')
return id
}
function summarizeIncident(item: any) {
const attributes = item?.attributes ?? item ?? {}
return {
id: item?.id ?? attributes.id ?? null,
title: attributes.title ?? null,
publicId: attributes.public_id ?? attributes.publicId ?? null,
state: attributes.state ?? null,
severity: attributes.fields?.severity?.value ?? attributes.severity ?? null,
customerImpacted: attributes.customer_impacted ?? attributes.customerImpacted ?? null,
created: attributes.created ?? attributes.created_at ?? null,
modified: attributes.modified ?? attributes.modified_at ?? null,
resolved: attributes.resolved ?? attributes.resolved_at ?? null,
}
}
function incidentPayload(params: DatadogIncidentInput, type = 'incidents') {
if (params.body && typeof params.body === 'object') return params.body
const attributes: Record<string, unknown> = { ...(params.attributes ?? {}) }
if (clean(params.title)) attributes.title = clean(params.title)
if (params.customerImpacted != null) attributes.customer_impacted = params.customerImpacted
if (params.fields && typeof params.fields === 'object') attributes.fields = params.fields
return {
data: {
type,
attributes,
},
}
}
/** List incidents. GET /api/v2/incidents */
export async function listIncidents(params: DatadogIncidentInput = {}) {
const query: Record<string, unknown> = {}
if (params.pageSize != null || params.perPage != null) {
query['page[size]'] = positiveInt(params.pageSize ?? params.perPage, 10, 100)
}
if (params.page != null) query['page[offset]'] = positiveInt(params.page, 0, 10_000)
const include = asStringArray(params.include)
if (include.length) query.include = include.join(',')
const body = await datadogRequest('/api/v2/incidents', { ...params, query })
const incidents = Array.isArray(body?.data) ? body.data : []
return {
count: incidents.length,
incidents: incidents.map(summarizeIncident),
meta: body?.meta ?? null,
}
}
/** Get one incident. GET /api/v2/incidents/{incident_id} */
export async function getIncident(params: DatadogIncidentInput = {}) {
const id = incidentId(params)
const include = asStringArray(params.include)
const query = include.length ? { include: include.join(',') } : undefined
const body = await datadogRequest('/api/v2/incidents/' + encodeURIComponent(id), {
...params,
query,
})
return { incident: summarizeIncident(body?.data ?? body), raw: body }
}
/** Search incidents. GET /api/v2/incidents/search */
export async function searchIncidents(params: DatadogIncidentInput = {}) {
const query: Record<string, unknown> = {}
if (clean(params.query)) query.query = clean(params.query)
if (params.pageSize != null || params.perPage != null) {
query['page[size]'] = positiveInt(params.pageSize ?? params.perPage, 10, 100)
}
if (params.page != null) query['page[offset]'] = positiveInt(params.page, 0, 10_000)
const include = asStringArray(params.include)
if (include.length) query.include = include.join(',')
const body = await datadogRequest('/api/v2/incidents/search', { ...params, query })
const incidents = Array.isArray(body?.data) ? body.data : []
return {
count: incidents.length,
incidents: incidents.map(summarizeIncident),
meta: body?.meta ?? null,
}
}
/** Create an incident. Requires confirm. Pass dryRun: true to preview. */
export async function createIncident(params: DatadogIncidentInput = {}) {
const payload = incidentPayload(params)
const title = clean((payload as any)?.data?.attributes?.title)
if (!title) throw new Error('Creating an incident requires title (or a full body).')
const preview = mutationPreview(params, {
action: 'create incident ' + title,
method: 'POST',
path: '/api/v2/incidents',
body: payload,
})
if (preview) return preview
const created = await datadogRequest('/api/v2/incidents', {
...params,
method: 'POST',
body: payload,
})
return { ok: true, action: 'create', incident: summarizeIncident(created?.data ?? created), raw: created }
}
/** Update an incident. Requires confirm. Pass dryRun: true to preview. */
export async function updateIncident(params: DatadogIncidentInput = {}) {
const id = incidentId(params)
const payload = incidentPayload(params)
;(payload as any).data.id = id
const preview = mutationPreview(params, {
action: 'update incident ' + id,
method: 'PATCH',
path: '/api/v2/incidents/' + encodeURIComponent(id),
body: payload,
})
if (preview) return preview
const updated = await datadogRequest('/api/v2/incidents/' + encodeURIComponent(id), {
...params,
method: 'PATCH',
body: payload,
})
return { ok: true, action: 'update', incident: summarizeIncident(updated?.data ?? updated), raw: updated }
}
/** Delete an incident. Requires confirm. Pass dryRun: true to preview. */
export async function deleteIncident(params: DatadogIncidentInput = {}) {
const id = incidentId(params)
const preview = mutationPreview(params, {
action: 'delete incident ' + id,
method: 'DELETE',
path: '/api/v2/incidents/' + encodeURIComponent(id),
})
if (preview) return preview
const deleted = await datadogRequest('/api/v2/incidents/' + encodeURIComponent(id), {
...params,
method: 'DELETE',
})
return { ok: true, action: 'delete', incidentId: id, raw: deleted }
}
/**
* List, search, or get Datadog incidents. Mutations live on named exports.
* @example
* import { listIncidents } from 'kody:@kody/datadog/incidents'
* const result = await listIncidents({ pageSize: 10 })
*/
export default async function incidents(params: DatadogIncidentInput = {}) {
if (params.incidentId || params.id) return await getIncident(params)
if (clean(params.query)) return await searchIncidents(params)
return await listIncidents(params)
}