import { RuntimeError } from '@botpress/sdk' import type { Version3Models } from 'jira.js' import { newIssuesInputSchema, newIssuesOutputSchema } from '../misc/custom-schemas' import type { Implementation } from '../misc/types' import { buildRuntimeError, getClient, resolveIssueTypeIds, serializeErrorForLog, textToAdfDocument } from '../utils' type IssueInput = Version3Models.IssueUpdateDetails export const newIssues: Implementation['actions']['newIssues'] = async ({ client, ctx, input, logger }) => { const validatedInput = newIssuesInputSchema.parse(input) if (validatedInput.issues.length === 0) { throw new RuntimeError('At least one issue must be provided') } if (validatedInput.issues.length > 50) { throw new RuntimeError(`Jira allows up to 50 issues per batch; received ${validatedInput.issues.length}`) } const jiraClient = await getClient({ client, ctx, logger }) try { const issueTypeIds = await resolveIssueTypeIds(jiraClient, validatedInput.issues) const issueUpdates: IssueInput[] = validatedInput.issues.map((i) => { const issueTypeId = issueTypeIds.get(`${i.projectKey}::${i.issueType}`)! const fields: NonNullable = { summary: i.summary, issuetype: { id: issueTypeId }, project: { key: i.projectKey }, } if (i.description !== undefined) fields.description = textToAdfDocument(i.description) if (i.parentKey !== undefined) fields.parent = { key: i.parentKey } if (i.assigneeId !== undefined) fields.assignee = { accountId: i.assigneeId } return { fields } }) const response = await jiraClient.newIssues({ issueUpdates }) const created = (response.issues ?? []).map((c) => ({ issueKey: c.key })) const errors = (response.errors ?? []).map((e) => { const fieldErrors = (e.elementErrors?.errors ?? {}) as Record const detail = [ ...(e.elementErrors?.errorMessages ?? []), ...Object.entries(fieldErrors).map(([k, v]) => `${k}: ${v}`), ].join('; ') return { index: e.failedElementNumber, message: detail.length > 0 ? detail : `HTTP ${e.status ?? 'unknown'}`, } }) logger.forBot().info(`Successful - New Issues - ${created.length} created, ${errors.length} failed`) return newIssuesOutputSchema.parse({ created, errors }) } catch (error) { logger.forBot().debug(`'New Issues' exception ${serializeErrorForLog(error)}`) throw buildRuntimeError('Failed to create issues', error) } }