Skip to content

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

Package listing

@kody/gitlab

src/issues/update.ts

68 lines · 2.1 KB · TypeScript
import { isConfirmed, isDryRun, normalizeIssueLocator, pickAuthInput, request } from '../core.ts'
import { asRecord, readOptionalString, slimIssue } from '../shape.ts'

/**
 * Update a GitLab issue.
 *
 * Pass `dryRun: true` to preview the request. Live updates require `confirm: true`.
 *
 * @example
 * import updateGitlabIssue from 'kody:@kody/gitlab/issues/update'
 * const preview = await updateGitlabIssue({
 *   project: 'example-group/example-project',
 *   issueIid: 12,
 *   state_event: 'close',
 *   dryRun: true,
 * })
 */
export default async function updateGitlabIssue(params: Record<string, unknown> = {}) {
	const auth = pickAuthInput(params)
	const { projectId, projectPath, issueIid } = normalizeIssueLocator(params)
	const body: Record<string, unknown> = {}
	const title = readOptionalString(params.title)
	if (title) body.title = title
	const description = readOptionalString(params.description)
	if (description !== undefined && params.description !== undefined) body.description = description ?? ''
	const labels = readOptionalString(params.labels)
	if (labels) body.labels = labels
	const stateEvent = readOptionalString(params.state_event ?? params.stateEvent)
	if (stateEvent) body.state_event = stateEvent
	if (params.assignee_ids !== undefined) body.assignee_ids = params.assignee_ids
	if (params.milestone_id !== undefined) body.milestone_id = params.milestone_id

	if (Object.keys(body).length === 0) {
		throw new Error('Provide at least one field to update (title, description, labels, state_event, assignee_ids, milestone_id).')
	}

	if (isDryRun(params)) {
		return {
			dryRun: true,
			wouldUpdate: true,
			projectPath,
			issueIid,
			body,
			auth,
		}
	}

	if (!isConfirmed(params)) {
		throw new Error(
			`Updating ${projectPath}#${issueIid} requires dryRun: true (preview) or confirm: true (live write).`,
		)
	}

	const response = await request<Record<string, unknown>>({
		...auth,
		method: 'PUT',
		path: `/projects/${projectId}/issues/${issueIid}`,
		body,
		throwOnError: true,
		confirm: true,
	})

	return {
		...slimIssue(asRecord(response.data)),
		projectPath,
		auth: response.auth,
	}
}