Skip to content

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

Package listing

@kody/linear

src/create-comment.ts

100 lines · 3.1 KB · TypeScript
import { linearGraphql } from './client.ts'
import { COMMENT_FIELDS, mapComment } from './models.ts'
import type {
	DryRunResult,
	JsonRecord,
	LinearAuthInput,
	LinearCommentSummary,
} from './types.ts'
import {
	compactRecord,
	optionalBoolean,
	optionalString,
	requireRecord,
	requireString,
} from './types.ts'
import { requireAuthMode } from './auth.ts'

export type CreateCommentInput = LinearAuthInput & {
	/** Issue UUID or identifier (`ENG-123`). */
	issueId: string
	body: string
	parentId?: string
	confirm?: boolean
	dryRun?: boolean
}

function commentCreatePayload(input: CreateCommentInput): JsonRecord {
	return compactRecord({
		issueId: requireString(input.issueId, 'issueId'),
		body: requireString(input.body, 'body'),
		parentId: optionalString(input.parentId, 'parentId'),
	})
}

/**
 * Create a Linear comment. Requires `confirm: true`, or use `dryRun: true`.
 * Needs `comments:create` or `write`.
 * @example
 * import createComment from 'kody:@kody/linear/create-comment'
 * const preview = await createComment({
 *   issueId: 'ENG-123',
 *   body: 'Shipped in #482.',
 *   dryRun: true,
 * })
 */
export async function createComment(
	input: CreateCommentInput,
): Promise<LinearCommentSummary | DryRunResult<{ mutation: string; input: JsonRecord }>> {
	const payload = commentCreatePayload(input)
	if (input.dryRun) {
		return { dryRun: true, wouldCall: { mutation: 'commentCreate', input: payload } }
	}
	if (input.confirm !== true) {
		throw new Error(
			'Creating a Linear comment requires confirm: true after explicit user approval, or dryRun: true.',
		)
	}

	const result = await linearGraphql<{
		commentCreate: { success?: boolean; comment?: unknown }
	}>({
		...input,
		operation: 'commentCreate',
		query: `mutation CreateComment($input: CommentCreateInput!) {
			commentCreate(input: $input) {
				success
				comment { ${COMMENT_FIELDS} }
			}
		}`,
		variables: { input: payload },
	})
	if (!result.data.commentCreate?.success || !result.data.commentCreate.comment) {
		throw new Error('Linear commentCreate did not return a comment.')
	}
	return mapComment(result.data.commentCreate.comment)
}

/**
 * Create a Linear comment. Requires `confirm: true`, or use `dryRun: true`.
 * @example
 * import createComment from 'kody:@kody/linear/create-comment'
 * const preview = await createComment({ issueId: 'ENG-123', body: 'Noted', dryRun: true })
 */
export default async function createCommentEntrypoint(
	params: Partial<CreateCommentInput> & Record<string, unknown> = {},
) {
	const input = requireRecord(params, 'create-comment')
	return createComment({
		issueId: requireString(input.issueId, 'issueId'),
		body: requireString(input.body, 'body'),
		parentId: optionalString(input.parentId, 'parentId'),
		integrationName: optionalString(input.integrationName, 'integrationName'),
		integration: optionalString(input.integration, 'integration'),
		account: optionalString(input.account, 'account'),
		secretName: optionalString(input.secretName, 'secretName'),
		auth: requireAuthMode(input.auth),
		confirm: optionalBoolean(input.confirm, 'confirm'),
		dryRun: optionalBoolean(input.dryRun, 'dryRun'),
	})
}