eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
2 lines • 3.34 kB
JavaScript
import{isObject}from"#shared/guards.js";import{createSign}from"node:crypto";const installationTokenCache=new Map;async function resolveGitHubAppId(e){let t=e??process.env.GITHUB_APP_ID;if(t===void 0||t===``)throw Error(`githubChannel: GITHUB_APP_ID is required.`);let n=typeof t==`function`?await t():t;return String(n)}async function resolveGitHubPrivateKey(e){let t=e??process.env.GITHUB_APP_PRIVATE_KEY;if(!t)throw Error(`githubChannel: GITHUB_APP_PRIVATE_KEY is required.`);return normalizeGitHubPrivateKey(typeof t==`function`?await t():t)}async function resolveGitHubWebhookSecret(e){let t=e??process.env.GITHUB_WEBHOOK_SECRET;if(!t)throw Error(`githubChannel: GITHUB_WEBHOOK_SECRET is required.`);return typeof t==`function`?await t():t}function normalizeGitHubPrivateKey(e){return e.replace(/\\n/gu,`
`)}async function createGitHubAppJwt(e){let n=await resolveGitHubAppId(e.appId),r=await resolveGitHubPrivateKey(e.privateKey),i=Math.floor((e.now?.getTime()??Date.now())/1e3),a={alg:`RS256`,typ:`JWT`},o={exp:i+600,iat:i-60,iss:n},s=`${base64UrlJson(a)}.${base64UrlJson(o)}`;return`${s}.${createSign(`RSA-SHA256`).update(s).sign(r,`base64url`)}`}async function resolveGitHubInstallationToken(e){let t=e.credentials?.installationToken;if(t!==void 0)return typeof t==`function`?await t():t;if(e.installationId===void 0)throw Error(`githubChannel: installationId is required for authenticated GitHub API calls.`);return createGitHubInstallationToken({api:e.api,appId:e.credentials?.appId,installationId:e.installationId,privateKey:e.credentials?.privateKey})}async function createGitHubInstallationToken(t){let r=await resolveGitHubAppId(t.appId),i=t.api?.apiBaseUrl??`https://api.github.com`,a=`${i}:${r}:${t.installationId}`,o=installationTokenCache.get(a);if(o!==void 0&&Date.now()<o.expiresAtMs-6e4)return o.token;let s=await createGitHubAppJwt({appId:r,privateKey:t.privateKey}),c=await(t.api?.fetch??fetch)(`${i}/app/installations/${t.installationId}/access_tokens`,{headers:{accept:`application/vnd.github+json`,authorization:`Bearer ${s}`,"x-github-api-version":`2022-11-28`},method:`POST`}),l=await parseJsonBody(c);if(!c.ok)throw Error(`githubChannel: create installation token failed with HTTP ${c.status}.`);if(!isObject(l)||typeof l.token!=`string`)throw Error(`githubChannel: installation token response did not include a token.`);let u=parseExpiryMs(l.expires_at);return installationTokenCache.set(a,{expiresAtMs:u,token:l.token}),l.token}function clearGitHubInstallationTokenCache(){installationTokenCache.clear()}function seedGitHubInstallationTokenForTests(e){let t=e.apiBaseUrl??`https://api.github.com`,r=e.appId??`test-app`;installationTokenCache.set(`${t}:${r}:${e.installationId}`,{expiresAtMs:Date.now()+3600*1e3,token:e.token})}function base64UrlJson(e){return Buffer.from(JSON.stringify(e)).toString(`base64url`)}async function parseJsonBody(e){let t=await e.text();if(!t)return null;try{return JSON.parse(t)}catch{return t}}function parseExpiryMs(e){if(typeof e==`string`){let t=Date.parse(e);if(Number.isFinite(t))return t}return Date.now()+3600*1e3}export{clearGitHubInstallationTokenCache,createGitHubAppJwt,createGitHubInstallationToken,normalizeGitHubPrivateKey,resolveGitHubAppId,resolveGitHubInstallationToken,resolveGitHubPrivateKey,resolveGitHubWebhookSecret,seedGitHubInstallationTokenForTests};