/home/techb158/cosmic.abdallabala.com/src/integrations/pmClients
Edit: /home/techb158/cosmic.abdallabala.com/src/integrations/pmClients/asanaClient.js (2694B)
const { fetchJson, buildRiskDescription } = require("./httpClient.js");
class AsanaClient {
constructor(options = {}) {
this.accessToken = options.accessToken;
this.projectGid = options.projectGid;
this.fetchImpl = options.fetchImpl;
if (!this.accessToken) throw new Error("Asana requires ASANA_ACCESS_TOKEN or a stored OAuth token");
}
headers() {
return { "Authorization": `Bearer ${this.accessToken}`, "Accept": "application/json", "Content-Type": "application/json" };
}
async testConnection() {
const result = await fetchJson("https://app.asana.com/api/1.0/users/me", { headers: this.headers() }, this.fetchImpl);
const user = result.data || result;
return { ok: true, provider: "Asana", account: user.name || user.email || user.gid, raw: user };
}
async createRiskWorkItem(risk, mitigations = [], integration = {}) {
const projectGid = integration.external_project_key || this.projectGid;
if (!projectGid) throw new Error("Asana live sync requires ASANA_PROJECT_GID or integration.external_project_key");
const result = await fetchJson("https://app.asana.com/api/1.0/tasks", {
method: "POST",
headers: this.headers(),
body: JSON.stringify({ data: { name: `[COSMIC Risk] ${risk.title}`, notes: buildRiskDescription(risk, mitigations), projects: [projectGid] } })
}, this.fetchImpl);
const task = result.data || result;
for (const mitigation of mitigations.slice(0, 10)) {
await fetchJson(`https://app.asana.com/api/1.0/tasks/${encodeURIComponent(task.gid)}/subtasks`, {
method: "POST",
headers: this.headers(),
body: JSON.stringify({ data: { name: mitigation.action || mitigation.title || mitigation.id, notes: `COSMIC mitigation status: ${mitigation.status || "Unknown"}` } })
}, this.fetchImpl);
}
return {
externalId: task.gid,
externalKey: task.gid,
externalUrl: task.permalink_url || "",
externalStatus: "Created"
};
}
async updateRiskWorkItem(mapping, risk, mitigations = []) {
const result = await fetchJson(`https://app.asana.com/api/1.0/tasks/${encodeURIComponent(mapping.external_item_id)}`, {
method: "PUT",
headers: this.headers(),
body: JSON.stringify({ data: { name: `[COSMIC Risk] ${risk.title}`, notes: buildRiskDescription(risk, mitigations) } })
}, this.fetchImpl);
const task = result.data || result;
return {
externalId: task.gid || mapping.external_item_id,
externalKey: task.gid || mapping.external_item_key,
externalUrl: task.permalink_url || mapping.external_url,
externalStatus: "Updated"
};
}
}
module.exports = { AsanaClient };