import * as z from "zod" import { defineAction } from "../../../automation/actions" import { ASANA_ATTACHMENT_SCHEMA, ASANA_PAGE_INFO_SCHEMA, ASANA_PROVIDER_ATTACHMENT_SCHEMA, ASANA_PROVIDER_PAGE_SCHEMA, getAsanaApi, toAsanaAttachment, toAsanaPageInfo, } from "@automate.ax/integration-contracts/asana" import { ASANA_ACCOUNT, ASANA_DEFAULT_SCOPE } from "./scopes" const ATTACHMENT_FIELDS = "gid,name,resource_type,resource_subtype,created_at,download_url,host,parent.gid,parent.name,parent.resource_type,permanent_url,size,view_url" const ATTACHMENT_RESPONSE_SCHEMA = z.looseObject({ data: ASANA_PROVIDER_ATTACHMENT_SCHEMA, }) const ATTACHMENT_PAGE_RESPONSE_SCHEMA = ASANA_PROVIDER_PAGE_SCHEMA.extend({ data: ASANA_PROVIDER_ATTACHMENT_SCHEMA.array(), }) const EMPTY_RESPONSE_SCHEMA = z.looseObject({ data: z.looseObject({}) }) /** Gets one Asana attachment. */ export const getAsanaAttachment = defineAction("Get Asana attachment") .describe("Gets one Asana attachment and its download metadata.") .account(ASANA_ACCOUNT, ASANA_DEFAULT_SCOPE) .input(z.object({ attachmentId: z.string().min(1) })) .output(ASANA_ATTACHMENT_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => toAsanaAttachment( ( await getAsanaApi(account.secret).call( `/attachments/${input.attachmentId}`, { query: { opt_fields: ATTACHMENT_FIELDS }, responseSchema: ATTACHMENT_RESPONSE_SCHEMA, }, ) ).data, ), ) /** Lists attachments on an Asana task. */ export const listAsanaTaskAttachments = defineAction( "List Asana task attachments", ) .describe("Lists files and external attachments on an Asana task.") .account(ASANA_ACCOUNT, ASANA_DEFAULT_SCOPE) .input( z.object({ limit: z.number().int().min(1).max(100).prefault(100), offset: z.string().min(1).optional(), taskId: z.string().min(1), }), ) .output( z.object({ attachments: ASANA_ATTACHMENT_SCHEMA.array(), pageInfo: ASANA_PAGE_INFO_SCHEMA, }), ) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => { const result = await getAsanaApi(account.secret).call("/attachments", { query: { limit: input.limit, offset: input.offset, opt_fields: ATTACHMENT_FIELDS, parent: input.taskId, }, responseSchema: ATTACHMENT_PAGE_RESPONSE_SCHEMA, }) return { attachments: result.data.map(toAsanaAttachment), pageInfo: toAsanaPageInfo(result), } }) /** Uploads a file to an Asana task. */ export const uploadAsanaTaskAttachment = defineAction( "Upload Asana task attachment", ) .describe("Uploads a file attachment to an Asana task.") .account(ASANA_ACCOUNT, ASANA_DEFAULT_SCOPE) .input( z.object({ file: z.instanceof(File), taskId: z.string().min(1), }), ) .output(ASANA_ATTACHMENT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { const formData = new FormData() formData.set("file", input.file, input.file.name) formData.set("parent", input.taskId) return toAsanaAttachment( ( await getAsanaApi(account.secret).call("/attachments", { formData, query: { opt_fields: ATTACHMENT_FIELDS }, responseSchema: ATTACHMENT_RESPONSE_SCHEMA, }) ).data, ) }) /** Deletes an Asana attachment. */ export const deleteAsanaAttachment = defineAction("Delete Asana attachment") .describe("Permanently deletes an Asana attachment.") .account(ASANA_ACCOUNT, ASANA_DEFAULT_SCOPE) .input(z.object({ attachmentId: z.string().min(1) })) .output(z.void()) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { await getAsanaApi(account.secret).call( `/attachments/${input.attachmentId}`, { httpMethod: "DELETE", responseSchema: EMPTY_RESPONSE_SCHEMA }, ) })