const express = require("express"); const cors = require("cors"); const bodyParser = require("body-parser"); const app = express(); const PORT = 3965; const msal = require("@azure/msal-node"); const { https } = require("follow-redirects"); const open = require("open"); let accessToken; let orgUrl; const msalConfig = { auth: { clientId: "", authority: "", redirectUri: "", }, }; let pca; async function getToken() { try { const tokenRequest = { scopes: [orgUrl + "/.default"], prompt: "select_account", openBrowser: async (url) => { await open(url); }, }; const authResponse = await pca.acquireTokenInteractive(tokenRequest); accessToken = authResponse.accessToken; return accessToken; } catch (err) { console.error("Error acquiring token interactively:", err); } } async function getCloudFlows() { try { const authResponse = await pca.acquireTokenInteractive(tokenRequest); accessToken = authResponse.accessToken; const options = { method: "GET", hostname: new URL(orgUrl).hostname, path: "/api/data/v9.2/workflows?$select=name,workflowid,category&$filter=category%20eq%205", headers: { Authorization: "Bearer " + accessToken, Accept: "application/json", }, maxRedirects: 100, }; const req = https.request(options, function (res) { const chunks = []; res.on("data", function (chunk) { chunks.push(chunk); }); res.on("end", function () { const body = Buffer.concat(chunks); const names = JSON.parse(body).value.filter(item => typeof item !== 'undefined').map(item => item.name); }); res.on("error", function (error) { console.error(error); }); }); req.end(); } catch (err) { console.error("Error acquiring token interactively:", err); } } let lastActivity = Date.now(); const IDLE_TIMEOUT_MS = 5 * 60 * 1000; app.use(bodyParser.json()); app.use( cors({ origin: "*", // You can restrict this to your Power Pages domain if you like //origin: "powerprompts.org", }) ); app.use((req, res, next) => { lastActivity = Date.now(); next(); }); app.get("/status", (req, res) => { res.json({ running: true, message: "Local helper is running.", }); }); app.post("/token", async (req, res) => { orgUrl = req.body.orgUrl; msalConfig.auth.clientId = req.body.clientId; msalConfig.auth.authority = req.body.authority; msalConfig.auth.redirectUri = req.body.redirectUri; pca = new msal.PublicClientApplication(msalConfig); const token = await getToken(); res.json({ "access_token": token }) }); setInterval(() => { const timeOutMin = 10; const idleTime = Date.now() - lastActivity; if (idleTime > IDLE_TIMEOUT_MS) { console.log(`Idle timeout (${timeOutMin} mins) reached, shutting down helper...`); process.exit(0); } }, 10 * 60 * 1000); app.listen(PORT, () => { console.log(`AI Commenter for Power Automate cloud flow's local helper listening on http://localhost:${PORT}`); });