corsair 0.1.118 → 0.1.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-delivery-BriS3Ij2.d.ts → browser-delivery-r2cFLO4E.d.ts} +1 -1
- package/dist/chunk-3TC2WIUS.js +1 -0
- package/dist/chunk-A7MHZJ3T.js +66 -0
- package/dist/client/react/index.d.ts +3 -3
- package/dist/{connect-SH3XOJIW.js → connect-MCJ7RG5E.js} +1 -1
- package/dist/core.d.ts +24 -7
- package/dist/core.js +1 -1
- package/dist/hub/tunnel/run-tunnel.js +1 -1
- package/dist/hub.d.ts +9 -14
- package/dist/hub.js +1 -1
- package/dist/{index-BPXuQ2Mc.d.ts → index-Dzgq6g_o.d.ts} +1 -1
- package/dist/{index-Dd4o8Ywc.d.ts → index-hjOyk3fB.d.ts} +8 -2
- package/dist/{index-CmJW8nF3.d.ts → index-rSDS0vTc.d.ts} +2 -2
- package/dist/index.d.ts +10 -10
- package/dist/index.js +1 -1
- package/dist/{loop-KLFTGQSS.js → loop-EV4V7YYV.js} +1 -1
- package/dist/oauth.d.ts +2 -2
- package/dist/oauth.js +1 -1
- package/dist/setup-IDNN3RZB.js +1 -0
- package/dist/{setup-introspect-6KUC32UF.js → setup-introspect-FNOU5Z5O.js} +1 -1
- package/dist/setup.d.ts +3 -3
- package/dist/setup.js +1 -1
- package/dist/{tenant-match-utils-BlDVCKJp.d.ts → tenant-match-utils-dY__baGV.d.ts} +2 -2
- package/dist/tunnel.d.ts +5 -5
- package/dist/tunnel.js +1 -1
- package/dist/{types-BLWXcX1H.d.ts → types-BMqVYze1.d.ts} +1 -1
- package/dist/{types-D45IRV1V.d.ts → types-D-yPWPrk.d.ts} +39 -3
- package/package.json +5 -5
- package/dist/chunk-HE4Z5CZQ.js +0 -66
- package/dist/chunk-KL3FGSOP.js +0 -1
- package/dist/setup-J2LPDA5W.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as o}from"./chunk-SOY77BN4.js";var u="3000",f="/api/corsair";function m(r){return r.replace(/\/$/,"")}function I(r){let t=r?.deliveryUrl?.trim()||process.env.CORSAIR_DELIVERY_URL?.trim();if(t){let l=/^https?:\/\//i.test(t)?t:`https://${t}`;return m(l)}return`http://localhost:${process.env.PORT?.trim()||u}${f}`}var S="corsair.cloud",$="/api/corsair";import{chmodSync as R,existsSync as s,statSync as h}from"fs";import{createRequire as d}from"module";import{homedir as g}from"os";import{dirname as y,join as i}from"path";var _="0.71.0",v=d(o);function x(){let r=`@corsair-dev/frpc-${process.platform}-${process.arch}`;try{let t=i(y(v.resolve(`${r}/package.json`)),a());return s(t)?t:null}catch{return null}}function p(){return`${process.platform}-${process.arch}`}function a(){return process.platform==="win32"?"frpc.exe":"frpc"}function E(){return i(g(),".cache","corsair","frpc",_,p(),a())}function n(r){if(process.platform==="win32")return r;try{let t=h(r).mode&511,e=t|73;e!==t&&R(r,e)}catch{}return r}function b(){let r=process.env.CORSAIR_FRP_BIN;if(r&&s(r))return n(r);let t=x();if(t)return n(t);let e=E();if(s(e))return n(e);throw new Error(`frpc binary not found for ${p()}. If you use pnpm, run \`pnpm approve-builds corsair\` (or add corsair to onlyBuiltDependencies) and reinstall; otherwise reinstall corsair, or set CORSAIR_FRP_BIN to an frpc path (https://github.com/fatedier/frp/releases).`)}export{I as a,S as b,$ as c,_ as d,p as e,b as f};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import{a as me,b as Mt,c as Ht}from"./chunk-3TC2WIUS.js";import{a as yo,b as he,c as mo,d as v,e as $,f as ho,g as K,h as L,i as R,j as En,k as bo,l as ko,m as Ot,n as wo,o as Co}from"./chunk-VOH7OVWP.js";import{a as fo}from"./chunk-F2EV3CHK.js";import{ZodBoolean as Sc,ZodDate as _c,ZodEnum as Ec,ZodNullable as Dc,ZodNumber as Oc,ZodObject as Mc,ZodOptional as Hc,ZodRecord as Fc,ZodString as Uc,ZodType as Bc}from"zod";var Dn=["ably","abstract","abyssale","accrediblecertificates","activecampaign","activetrail","addresszen","aeroleads","affinda","agencyzoom","agentmail","agentql","agenty","agilitycms","ahrefs","aimlapi","airtable","aivoov","alchemy","algolia","allimagesai","alphavantage","altoviz","alttextai","amara","ambee","ambientweather","amcards","amplitude","anchorbrowser","anthropicadministrator","apaleo","api2pdf","apibible","apify","apilabz","apininjas","apipie","apisports","asana","asindataapi","asticaai","asyncinterview","attio","ayrshare","basecamp","baselinker","basin","betterstack","bigmailer","bigml","bitbucket","bitwarden","blazemeter","bluesky","boloforms","botpress","bouncer","box","bugsnag","cal","calendly","canva","canvas","chatbotkit","circleci","clientary","cloudflare","cloudinary","collegefootballdata","confluence","contentfulgraphql","crowterminal","cursor","customgpt","databricks","datadog","deepseek","devinmcp","diffbot","digitalocean","discord","dockerhub","dodopayments","doppler","dropbox","epicgames","exa","facebook","figma","firecrawl","fireflies","formbricks","gemini","github","gitlab","gmail","googleaddressvalidation","googlebigquery","googlecalendar","googlecloudvision","googledocs","googledrive","googlemaps","googlemeet","googlesheets","grafana","groqcloud","habitica","hackernews","harvest","hashnode","heygen","hubspot","huggingface","imgbb","insightoai","instagram","intercom","jira","kaggle","linear","linkedin","loyverse","mailchimp","mailtrap","monday","neon","nextdns","notion","ocrspace","ollama","onedrive","onepassword","openai","openrouter","openweathermap","oura","outlook","pagerduty","perplexityai","posthog","razorpay","reddit","resend","retailed","salesforce","securitytrails","sentry","serpapi","sharepoint","slack","spotify","strava","stripe","supabase","tally","tavily","tavilymcp","teams","telegram","todoist","toggl","trello","twentyonerisk","twilio","twitter","twitterapiio","twochat","typeform","unione","vapi","vercel","webflow","whatsapp","witai","wiza","workday","xquik","youcom","youtube","zendesk","zohomail","zoom","zoominfo"],vo={ably:"Ably",abstract:"Abstract",abyssale:"Abyssale",accrediblecertificates:"Accredible Certificates",activecampaign:"ActiveCampaign",activetrail:"Active Trail",addresszen:"Addresszen",aeroleads:"Aeroleads",affinda:"Affinda",agencyzoom:"AgencyZoom",agentmail:"AgentMail",agentql:"AgentQL",agenty:"Agenty",agilitycms:"Agility CMS",ahrefs:"Ahrefs",aimlapi:"AI/ML API",airtable:"Airtable",aivoov:"AiVOOV",alchemy:"Alchemy",algolia:"Algolia",allimagesai:"All Images AI",alphavantage:"Alpha Vantage",altoviz:"Altoviz",alttextai:"AltText.ai",amara:"Amara",ambee:"Ambee",ambientweather:"Ambient Weather",amcards:"AMcards",amplitude:"Amplitude",anchorbrowser:"Anchor Browser",anthropicadministrator:"Anthropic Administrator",apaleo:"Apaleo",api2pdf:"API2PDF",apibible:"API.Bible",apify:"Apify",apilabz:"API Labz",apininjas:"API Ninjas",apipie:"APIpie AI",apisports:"API-Sports",asana:"Asana",asindataapi:"ASIN Data API",asticaai:"Astica AI",asyncinterview:"Async Interview",attio:"Attio",ayrshare:"Ayrshare",basecamp:"Basecamp",baselinker:"BaseLinker",basin:"Basin",betterstack:"Better Stack",bigmailer:"BigMailer",bigml:"BigML",bitbucket:"Bitbucket",bitwarden:"Bitwarden",blazemeter:"BlazeMeter",bluesky:"Bluesky",boloforms:"Boloforms",botpress:"Botpress",bouncer:"Bouncer",box:"Box",bugsnag:"BugSnag",cal:"Cal",calendly:"Calendly",canva:"Canva",canvas:"Canvas LMS",chatbotkit:"ChatBotKit",circleci:"CircleCI",clientary:"Clientary",cloudflare:"Cloudflare",cloudinary:"Cloudinary",collegefootballdata:"College Football Data",confluence:"Confluence",contentfulgraphql:"Contentful GraphQL",crowterminal:"CrowTerminal",cursor:"Cursor",customgpt:"CustomGPT",databricks:"Databricks",datadog:"Datadog",deepseek:"DeepSeek",devinmcp:"Devin MCP",diffbot:"Diffbot",digitalocean:"DigitalOcean",discord:"Discord",dockerhub:"Docker Hub",dodopayments:"Dodo Payments",doppler:"Doppler",dropbox:"Dropbox",epicgames:"Epic Games",exa:"Exa",facebook:"Facebook",figma:"Figma",firecrawl:"Firecrawl",fireflies:"Fireflies",formbricks:"Formbricks",gemini:"Gemini",github:"GitHub",gitlab:"GitLab",gmail:"Gmail",googleaddressvalidation:"Google Address Validation",googlebigquery:"Google BigQuery",googlecalendar:"Google Calendar",googlecloudvision:"Google Cloud Vision",googledocs:"Google Docs",googledrive:"Google Drive",googlemaps:"Google Maps",googlemeet:"Google Meet",googlesheets:"Google Sheets",grafana:"Grafana",groqcloud:"GroqCloud",habitica:"Habitica",hackernews:"Hacker News",harvest:"Harvest",hashnode:"Hashnode",heygen:"HeyGen",hubspot:"HubSpot",huggingface:"Hugging Face",imgbb:"ImgBB",insightoai:"Insighto.ai",instagram:"Instagram",intercom:"Intercom",jira:"Jira",kaggle:"Kaggle",linear:"Linear",linkedin:"LinkedIn",loyverse:"Loyverse",mailchimp:"Mailchimp",mailtrap:"Mailtrap",monday:"Monday",neon:"Neon",nextdns:"NextDNS",notion:"Notion",ocrspace:"OCR.space",ollama:"Ollama",onedrive:"OneDrive",onepassword:"1Password",openai:"OpenAI",openrouter:"OpenRouter",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",perplexityai:"Perplexity AI",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",resend:"Resend",retailed:"Retailed",salesforce:"Salesforce",securitytrails:"SecurityTrails",sentry:"Sentry",serpapi:"Serpapi",sharepoint:"SharePoint",slack:"Slack",spotify:"Spotify",strava:"Strava",stripe:"Stripe",supabase:"Supabase",tally:"Tally",tavily:"Tavily",tavilymcp:"Tavily MCP",teams:"Teams",telegram:"Telegram",todoist:"Todoist",toggl:"Toggl",trello:"Trello",twentyonerisk:"TwentyOneRisk",twilio:"Twilio",twitter:"Twitter",twitterapiio:"Twitter API IO",twochat:"TwoChat",typeform:"Typeform",unione:"Unione",vapi:"Vapi",vercel:"Vercel",webflow:"Webflow",whatsapp:"WhatsApp",witai:"WitAi",wiza:"Wiza",workday:"Workday",xquik:"XQuik",youcom:"You.com",youtube:"YouTube",zendesk:"Zendesk",zohomail:"Zoho Mail",zoom:"Zoom",zoominfo:"ZoomInfo"};function be(e){let n=vo[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}function S(e){return typeof e=="string"&&e.length>0}function Ws(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function js(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function On(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!S(n.connectUrl)||!S(n.token)||!S(n.projectId))throw new Error("Hub API returned an incomplete connect session (expected connectUrl, token, and projectId)");let t={connectUrl:n.connectUrl,token:n.token,projectId:n.projectId,environmentId:S(n.environmentId)?n.environmentId:n.projectId};return S(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Mn(e){if(!Array.isArray(e))throw new Error("Hub API returned an invalid connections response (expected array)");let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;if(!S(r.tenantId)||!S(r.plugin)||!Ws(r.status)||!js(r.authType)||typeof r.connected!="boolean"||typeof r.verified!="boolean")continue;let o=Array.isArray(r.missingFields)?r.missingFields.filter(i=>typeof i=="string"):[];n.push({tenantId:r.tenantId,plugin:r.plugin,status:r.status,authType:r.authType,connected:r.connected,verified:r.verified,missingFields:o,reportedAt:S(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function Hn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!S(n.approvalUrl)||!S(n.token)||!S(n.projectId)||!S(n.expiresAt))throw new Error("Hub API returned an incomplete permission session (expected approvalUrl, token, projectId, and expiresAt)");return{approvalUrl:n.approvalUrl,token:n.token,projectId:n.projectId,expiresAt:n.expiresAt}}function Be(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(S(n.access_token))return{access_token:n.access_token,refresh_token:S(n.refresh_token)?n.refresh_token:void 0,expires_in:(()=>{if(typeof n.expires_in=="number")return n.expires_in;if(typeof n.expires_in=="string"&&n.expires_in.trim().length>0){let t=Number(n.expires_in);return Number.isFinite(t)?t:void 0}})(),scope:S(n.scope)?n.scope:void 0};throw new Error(S(n.error)?S(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Ks(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function qs(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;S(r.name)&&n.push({name:r.name,level:r.level==="integration"||r.level==="account"?r.level:"account",required:r.required===!0,configured:r.configured===!0})}return n}function Zs(e,n,t,r){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"?e:n?"ready":t.some(i=>i.level==="integration"&&i.required&&!i.configured)?"missing_integration":t.some(i=>i.level==="account"&&i.required&&i.configured)?"partial":(r.length>0,"not_started")}function Po(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!S(n.tenantId)||!Array.isArray(n.plugins))throw new Error("Connect status response was incomplete (expected tenantId and plugins)");let t=[];for(let r of n.plugins){if(!r||typeof r!="object")continue;let o=r;if(!S(o.plugin)||typeof o.connected!="boolean")continue;let i=o.authKind==="oauth"||o.authKind==="api_key"||o.authKind==="bot_token"?o.authKind:"api_key",s=qs(o.fields),a=Ks(o.missingRequiredFields),u=Zs(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:S(o.providerName)?o.providerName:o.plugin,authKind:i,status:u,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function Fn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function To(e){return e.replace(/\/$/,"")}function Ft(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return me()}catch{return null}}function Ao(e){let n=Ft(e);return n?{"x-corsair-delivery-url":n}:{}}async function xo(e){let n=e.headers.get("content-type")??"",t=await e.text();if(!t)return null;if(!n.includes("application/json")&&t.trimStart().startsWith("<"))throw new Error(`Hub API returned HTML instead of JSON (HTTP ${e.status}). Check HUB_API_URL and deploy the latest hub API.`);try{return JSON.parse(t)}catch{throw new Error(`Hub API returned invalid JSON (HTTP ${e.status})`)}}function Ro(e,n,t){if(n===404&&t)return t;let r=Fn(e);return r||`Hub API returned HTTP ${n}`}async function x(e){let n=To(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...Ao(e.hub)},body:JSON.stringify(e.body)}),r=await xo(t);if(!t.ok)throw new Error(Ro(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function N(e){let n=To(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...Ao(e.hub)}}),r=await xo(t);if(!t.ok)throw new Error(Ro(r,t.status,e.notFoundMessage));return e.parseResponse(r)}function Un(e){return e&&typeof e=="object"?e:{}}function Io(e){let n=Un(e);return{chatId:n.threadId,message:n.message,workflowId:n.workflowId??null,action:n.action}}async function Ut(e,n){return x({hub:e,path:"/threads",body:{tenantId:n.tenantId,message:n.message},parseResponse:t=>{let r=Un(t);return{chat:r.thread,reply:Io(r.reply)}}})}async function Bt(e,n){return x({hub:e,path:`/threads/${encodeURIComponent(n.chatId)}/messages`,body:{tenantId:n.tenantId,message:n.message},notFoundMessage:`Chat "${n.chatId}" not found`,parseResponse:Io})}async function Lt(e,n){return N({hub:e,path:`/threads?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Un(t).threads;return Array.isArray(r)?r:[]}})}async function Nt(e,n){return N({hub:e,path:`/threads/${encodeURIComponent(n.chatId)}/messages?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Chat "${n.chatId}" not found`,parseResponse:t=>{let r=Un(t).messages;return Array.isArray(r)?r:[]}})}import{randomUUID as Xs}from"crypto";var Gs="corsair:client-bridge";function $t(e){return new URL(e).origin}function Le(e){let n=JSON.stringify({type:Gs,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify($t(e.hubOrigin));return`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><script>
|
|
2
|
+
(function () {
|
|
3
|
+
var message = ${n};
|
|
4
|
+
var targetOrigin = ${t};
|
|
5
|
+
if (window.parent && window.parent !== window) {
|
|
6
|
+
window.parent.postMessage(message, targetOrigin);
|
|
7
|
+
}
|
|
8
|
+
})();
|
|
9
|
+
</script></body></html>`}var zs=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Wt(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:zs.has(n)}catch{return!1}}function cn(e){return e==="development"?"browser":"server"}function So(e){return cn(e)==="browser"}function _o(e){return Wt(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as Qs}from"crypto";var ke=60*1e3,Se=300*1e3;import{createHmac as Js,randomBytes as Vs,timingSafeEqual as Ys}from"crypto";function ae(){return Vs(16).toString("base64url")}function ln(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Js("sha256",t).update(e).digest("base64url")}function te(e,n){let t=n.trim();if(!t)return null;let r=e.split(".");if(r.length!==2)return null;let[o,i]=r;if(!o||!i)return null;let s=ln(o,t);try{if(!Ys(Buffer.from(i,"utf8"),Buffer.from(s,"utf8")))return null}catch{return null}let a;try{a=JSON.parse(Buffer.from(o,"base64url").toString("utf8"))}catch{return null}return a.exp*1e3<Date.now()?null:a}function Bn(e,n,t){let r=Math.floor(Date.now()/1e3),o={...e,iat:r,exp:t},i=Buffer.from(JSON.stringify(o)).toString("base64url"),s=ln(i,n);return`${i}.${s}`}function dn(e,n,t){let r=Math.floor(Date.now()/1e3);return Bn(e,n,r+Math.floor(t/1e3))}function _e(e){return decodeURIComponent(e)}function jt(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function Eo(e){let n=e.trim();return n.length>0?n:null}function Ne(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function $e(e,n){if(!Eo(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??Qs(16).toString("base64url"),iat:t,exp:t+Math.floor(ke/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=ln(o,n);return`${o}.${i}`}function we(e,n){return Eo(n)?te(e,n):null}function ea(e){let n=$t(e.hubOrigin),t={connectJti:e.requestId,projectId:e.projectId,hubSuccessUrl:e.hubOrigin,deliveryMode:e.deliveryMode,hubOrigin:n,requestId:e.requestId};switch(e.deliveryMode){case"connections.sync":return{...t,plugin:"connections.sync",tenantId:"*"};case"connect.create_link":return{...t,plugin:"connect.create_link",tenantId:e.tenantId,connectLinkPlugins:e.plugins}}}function Kt(e){let n=$e(ea(e),e.signingSecret);return Ne(e.deliveryUrl,n)}function Do(e){if(cn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=Xs(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:Kt(r)}}var pn="https://auth.corsair.dev";var ue=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function Ln(e){let n=(e.apiUrl?.trim()||pn).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim();if(!t||!r)throw new Error("Hub config requires non-empty projectApiKey and signingSecret");return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,""),redirectURL:e.redirectURL?.trim()||void 0,allowWorkflowExecution:e.allowWorkflowExecution??!1,tunnel:e.tunnel}}function na(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function F(e){let n=v(e).hub;if(!n||!na(n))throw new ue;return n}function Oo(e){return e.replace(/\/$/,"")}function Nn(e){return e.oauthCallbackUrl?Oo(e.oauthCallbackUrl.trim()):`${Oo(e.apiUrl)}/oauth/callback`}function We(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";throw new Error("Hub API key must start with ck_dev_ (development) or ck_prod_ (production)")}import{createCipheriv as Mo,createDecipheriv as Ho,randomBytes as $n,scrypt as ta}from"crypto";import{promisify as ra}from"util";var Fo=ra(ta),Wn="aes-256-gcm",Uo=12,jn=16,oa=16,gn=32;function ce(){return $n(gn).toString("base64")}async function le(e,n){let t=$n(oa),r=await Fo(n,t,gn),o=$n(Uo),i=Mo(Wn,r,o,{authTagLength:jn}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[t.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function z(e,n){let[t,r,o,i]=e.split(":");if(!t||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),u=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),c=await Fo(n,s,gn),d=Ho(Wn,c,a,{authTagLength:jn});return d.setAuthTag(u),Buffer.concat([d.update(l),d.final()]).toString("utf8")}function qt(e,n){let t=Buffer.from(n,"base64"),r=$n(Uo),o=Mo(Wn,t,r,{authTagLength:jn}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function fn(e,n){let[t,r,o]=e.split(":");if(!t||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),u=Buffer.from(o,"base64"),l=Ho(Wn,i,s,{authTagLength:jn});return l.setAuthTag(a),Buffer.concat([l.update(u),l.final()]).toString("utf8")}function Ce(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=qt(o,n);return t}function de(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=fn(o,n);return t}function yn(e,n,t){let r=de(e,n);return Ce(r,t)}function Bo(e,n,t){let r={};for(let o of t)r[`get_${o}`]=async()=>(await e())[o]??null,r[`set_${o}`]=async i=>{let s=[null,void 0,""].includes(i)?null:i;await n({[o]:s})};return r}var Zt=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function U(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...L[n].integration,...i],a=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let k=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!k)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:k.id,config:Zt(k.config),dek:k.dek??null},a},updateIntegration:async k=>{let b=await u.getIntegration();await o.db.updateTable("corsair_integrations").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",b.id).execute(),a=null}},l=null,c=async()=>{if(l)return l;let k=await u.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await z(k.dek,r),l},d=async()=>{let k=await u.getIntegration(),b=await c(),C=k.config;return!C||Object.keys(C).length===0?{}:de(C,b)},p=Promise.resolve(),g=k=>{let b=p.then(()=>f(k));return p=b.catch(()=>{}),b},f=async k=>{let b=await c(),C;try{C=await d()}catch(_){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,_),C={}}let P={...C};for(let[_,O]of Object.entries(k))O===null?delete P[_]:P[_]=O;let D=Ce(P,b);await u.updateIntegration({config:D})};return{get_dek:c,issue_new_dek:async()=>{let k=await u.getIntegration(),b=ce(),C={};if(k.dek){let D=await z(k.dek,r),_=k.config;_&&Object.keys(_).length>0&&(C=yn(_,D,b))}let P=await le(b,r);return await u.updateIntegration({config:C,dek:P}),l=b,b},...Bo(d,g,s)}}function M(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,u=[...L[n].account,...s],l=null,c=null,d=async()=>{if(c)return c;let w=!1;for(;;){let T=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!T){if(!w&&a){w=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return c={id:T.id,config:Zt(T.config),dek:T.dek??null},c}},p={kek:o,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(l)return l;let w=!1;for(;;){let T=await d(),A=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",T.id).executeTakeFirst();if(!A){if(!w&&a){w=!0,await a();continue}throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`)}return l={id:A.id,config:Zt(A.config),dek:A.dek??null},l}},updateAccount:async w=>{let T=await p.getAccount();await i.db.updateTable("corsair_accounts").set({...w.config!==void 0?{config:w.config}:{},...w.dek!==void 0?{dek:w.dek}:{},updated_at:new Date}).where("id","=",T.id).execute(),l=null}},g=null,f=null,h=async()=>{if(g)return g;let w=await p.getAccount();if(!w.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await z(w.dek,o),g},k=async()=>{if(f)return f;let w=await p.getIntegration();if(!w.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await z(w.dek,o),f},b=async()=>{let w=await p.getAccount(),T=await h(),A=w.config;return!A||Object.keys(A).length===0?{}:de(A,T)},C=async()=>{let w=await p.getIntegration(),T=await k(),A=w.config;return!A||Object.keys(A).length===0?{}:de(A,T)},P=Promise.resolve(),D=w=>{let T=P.then(()=>_(w));return P=T.catch(()=>{}),T},_=async w=>{let T=await h(),A;try{A=await b()}catch(I){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,I),A={}}let q={...A};for(let[I,X]of Object.entries(w))X===null?delete q[I]:q[I]=X;let ie=Ce(q,T);await p.updateAccount({config:ie})},O={get_dek:h,issue_new_dek:async()=>{let w=await p.getAccount(),T=ce(),A={};if(w.dek){let ie=await z(w.dek,o),I=w.config;I&&Object.keys(I).length>0&&(A=yn(I,ie,T))}let q=await le(T,o);return await p.updateAccount({config:A,dek:q}),g=T,T},...Bo(b,D,u)};return n==="oauth_2"&&(O.get_integration_credentials=async()=>{let w=await C();return{...w,client_id:w.client_id||null,client_secret:w.client_secret||null,redirect_url:w.redirect_url??null}}),O}async function Lo(e,n,t){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!r)throw new Error(`Integration "${n}" not found.`);let o=ce(),i=await le(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function No(e,n,t,r){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!o)throw new Error(`Integration "${n}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${t}" and integration "${n}".`);let s=ce(),a=await le(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var ia=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function ve(e){return ia.has(e)}function sa(e,n){return ve(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function aa(e){return!ve(e)}function ua(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function ca(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function la(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!ua(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function $o(e,n){if(!e)return!1;let t=K(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function da(e,n){let r=e.authConfig?.[n]?.integration??[];return[...L[n].integration,...r]}function pa(e,n){let r=e.authConfig?.[n]?.account??[];return[...L[n].account,...r]}function ga(e,n,t){let r=t.filter(a=>a.required&&!a.configured).map(a=>a.name),o=t.filter(a=>a.level==="integration"&&a.required&&!a.configured).map(a=>a.name),i=t.filter(a=>a.level==="account"&&a.required&&a.configured),s;return o.length>0?s="missing_integration":r.length===0?s="ready":i.length>0?s="partial":s="not_started",{plugin:e,authType:n,status:s,connected:la(n,t),fields:t,missingRequiredFields:r}}async function Ee(e,n,t){let r=R(n);if(!r||!e.database||!e.kek)return null;let o=t.trim()||"default",i=n.authConfig,s=i?.[r]?.integration??[],a=i?.[r]?.account??[],u=U({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=M({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),c=da(n,r),d=pa(n,r),p=[];for(let g of c)p.push({name:g,level:"integration",required:sa(r,g),configured:await $o(u,g)});for(let g of d)p.push({name:g,level:"account",required:aa(g),configured:await $o(l,g)});if(ca(r,p)){let g=p.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return ga(n.id,r,p)}async function mn(e,n,t={}){let r=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,i=[];for(let s of e.plugins){if(o&&!o.has(s.id))continue;let a=await Ee(e,s,r);a&&i.push(a)}return i}function Kn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var Wo=Symbol.for("corsair:internal"),jo=new WeakMap,Ko=new WeakMap;function fa(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function ya(e){if(e.database){let t=jo.get(e.database);return t||(t=new Map,jo.set(e.database,t)),t}let n=Ko.get(e);return n||(n=new Map,Ko.set(e,n)),n}function ma(e){return e.multiTenancy?{withTenant:()=>({}),[Wo]:e}:{[Wo]:e}}async function je(e,n){if(!e.database)return;let t=n.trim()||"default",r=ya(e),o=fa(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-IDNN3RZB.js");await a(ma(e),{tenantId:e.multiTenancy?t:void 0,silent:!0})})().finally(()=>{r.delete(o)});r.set(o,s),await s}import*as hn from"crypto";function Pe(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Gt(e,{maxAgeMs:n}={}){try{let t=e.includes(".")?e.split(".")[0]:e,r=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));if(r!==null&&typeof r=="object"&&"plugin"in r&&"tenantId"in r&&typeof r.plugin=="string"&&typeof r.tenantId=="string"){let o=r;return n!==void 0&&typeof o.iat=="number"&&Date.now()-o.iat>n?null:o}return null}catch{return null}}function Ke(e,n){let t=hn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var zt=600*1e3;function qn(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=hn.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(o,"base64url"),a=Buffer.from(i,"base64url");return s.length!==a.length||!hn.timingSafeEqual(s,a)?null:Gt(r,{maxAgeMs:zt})}function qo(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function Zo(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType,status:e.status,connected:e.connected,verified:e.verified,missingFields:e.missingFields,webhookLink:e.webhookLink,webhookSecret:e.webhookSecret}}async function qe(e,n){await x({hub:e,path:"/connections/report",body:qo(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function ha(e,n){try{let t=F(e);x({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof ue)return}}async function ba(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!R(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Ee(n,e.plugin,r);o&&zo(e.hub,Zo({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function Go(e,n){ha(e,n)}function zo(e,n){x({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function bn(e){ba(e).catch(()=>{})}async function pe(e,n){let t=v(e);if(!R(n.plugin))return;let o=await Ee(t,n.plugin,n.tenantId);o&&Go(e,Zo({tenantId:n.tenantId.trim()||"default",plugin:n.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:n.verified??o.connected,missingFields:o.missingRequiredFields,webhookLink:n.webhookLink,webhookSecret:n.webhookSecret}))}async function Zn(e,n,t){for(let r of e){if(r.id!==n)continue;let o=r.oauthWebhookTenantLinkResolver;return o?o(t):null}return null}var Jo=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function ka(e){let n=await e.database.db.selectFrom("corsair_integrations").selectAll().where("name","=",e.pluginId).executeTakeFirst();if(!n)throw new Error(`Integration '${e.pluginId}' not found. Run setupCorsair before registering webhook tenant links.`);let t=await e.database.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",e.tenantId).where("integration_id","=",n.id).executeTakeFirst();if(!t)throw new Error(`Account not found for tenant '${e.tenantId}' and integration '${e.pluginId}'.`);return{integrationId:n.id,accountId:t.id}}async function wa(e){let n=await e.database.db.selectFrom("corsair_accounts").selectAll().where("id","=",e.accountId).executeTakeFirst();if(!n?.dek)throw new Error(`Account '${e.accountId}' has no DEK.`);let t=await z(n.dek,e.kek),r=Jo(n.config),o={};Object.keys(r).length>0&&(o=de(r,t)),o[e.link.linkType]=e.link.externalId;let i=Ce(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function Ze(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:u}=await ka({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let c=M({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),d=`set_${i.linkType}`,p=c[d];typeof p=="function"&&(await p(i.externalId),l=!0)}l||await wa({database:n,kek:t,accountId:u,link:i})}async function Jt(e){let{database:n,kek:t,pluginId:r,linkType:o,externalId:i}=e,s=await n.db.selectFrom("corsair_accounts as accounts").innerJoin("corsair_integrations as integrations","integrations.id","accounts.integration_id").selectAll("accounts").where("integrations.name","=",r).execute();for(let a of s)if(a.dek)try{let u=await z(a.dek,t),c=Jo(a.config)[o];if(!c)continue;if(fn(c,u)===i)return a}catch{continue}return null}async function Gn(e){return(await Jt(e))?.tenant_id??null}async function Vo(e){return Gn({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as Yo from"querystring";function De(e){let{oauthConfig:n,clientId:t,redirectUri:r,state:o}=e,i={...n.authParams,client_id:t,redirect_uri:r,response_type:"code",scope:n.scopes.join(" "),state:o};return`${n.authUrl}?${Yo.stringify(i)}`}async function Qo(e,n){try{return await N({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function Ge(e,n,t,r){if(!n.subscribe)return;let o=F(e),i=await Qo(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await pe(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var W=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Xo(e){let n=e.oauthConfig;if(!n)throw new W("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Ca(e,n,t,r){let o=Co(e),i=await o.integrations.findByName(n);if(!i)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.accounts.findOne({tenant_id:t,integration_id:i.id}))return;let a=ce(),u=await le(a,r);await o.accounts.create({tenant_id:t,integration_id:i.id,config:{},dek:u})}async function Vt(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=v(e,()=>new W("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=$(s,n,p=>new W("plugin_not_found",p)),u=Xo(a),c=await U({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!c)throw new Error(`client_id not configured for '${n}'`);if(i){let p=new URL(De({oauthConfig:u,clientId:c,redirectUri:o,state:""}));return p.searchParams.delete("state"),{url:p.toString(),state:""}}let d=Ke(Pe(n,r),s.kek);return{url:De({oauthConfig:u,clientId:c,redirectUri:o,state:d}),state:d}}function va(e,n){return{...n??{},...e}}async function kn(e,n){let{code:t,state:r,redirectUri:o}=n,i=v(e,()=>new W("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new W("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let h=qn(r,i.kek);if(!h)throw new W("invalid_state","Invalid or tampered state parameter");s=h.plugin,a=h.tenantId}if(!i.database)throw new W("no_database","No database configured on corsair instance");let u=$(i,s,h=>new W("plugin_not_found",h)),l=Xo(u),c=U({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),d=await c.get_client_id(),p=await c.get_client_secret();if(!d||!p)throw new W("credentials_not_configured",`Credentials not configured for '${s}'`);await Ca(i.database,s,a,i.kek);let g=await zn(t,d,p,l,o);if(!g.access_token)throw new W("no_access_token",`No access_token returned from ${l.providerName}`);let f=M({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...u.authConfig?.oauth_2?.account??[]]});await f.set_access_token(g.access_token),g.refresh_token&&await f.set_refresh_token(g.refresh_token),g.expires_in&&await f.set_expires_at(String(Math.floor(Date.now()/1e3)+g.expires_in)),await pe(e,{plugin:u,tenantId:a}).catch(()=>{});try{let h=va(g,n.callbackParams),k=await Zn(i.plugins,s,h);if(k){try{let b=u.authConfig?.oauth_2?.account??[];await Ze({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:k,authType:"oauth_2",extraAccountFields:b})}catch(b){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,b)}i.hub&&qe(i.hub,{plugin:s,tenantId:a,link:k,authType:"oauth_2"})}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,h)}if(u.subscribe)try{await Ge(e,u,a,f)}catch(h){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,h)}return{plugin:s,tenantId:a}}async function Pa(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??Ge,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let u=t.plugins.find(c=>c.id===a.integrationName);if(!u?.subscribe)continue;let l=`${u.id}/${a.tenantId}`;try{let c=R(u)??"oauth_2",d=M({authType:c,integrationName:u.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...u.authConfig?.[c]?.account??[]]}),p=u.keyBuilder;if(p){let g=Object.create(d,{get_expires_at:{value:async()=>"0"}});await p({authType:c,keys:g,hub:t.hub},"endpoint")}await o(n,u,a.tenantId,d),i.push(l)}catch(c){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,c),s.push(l)}}return{renewed:i,failed:s}}async function ei(e){let n=v(e);if(!n.database)return{renewed:[],failed:[]};let t=await n.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id as tenantId","i.name as integrationName"]).where("a.dek","is not",null).execute();return Pa({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function Ta(e,n={}){let t=!1,r=()=>{t||(t=!0,ei(e).catch(i=>console.warn("[corsair:renewal] renewal pass failed:",i)).finally(()=>{t=!1}))};r();let o=setInterval(r,(n.intervalMinutes??45)*6e4);return o.unref?.(),()=>clearInterval(o)}async function ni(e){if(!v(e).database)throw new Error("A database must be configured to provision Corsair integrations");await Jn(e,{silent:!0})}async function ze(e,n){let t=v(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await je(t,n)}var Aa=Symbol.for("corsair:internal"),xa=new Set(["access_token","refresh_token","expires_at","scope"]);function Ra(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Ia(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!ve(t)&&!xa.has(t)):n.filter(t=>!ve(t))}function ti(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function Sa(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function _a(e){return{[Aa]:ti(e)}}async function Vn(e,n,t={}){let r=Nn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=ti(e),a=_a(e);for(let u of e.plugins){if(i&&!i.has(u.id))continue;let l=R(u);if(!l)continue;let c=Ra(l),d=t.providerNameOverrides?.[u.id]??be(u.id),p=await Ee(s,u,n),g=En(u,l),f=Ia(l,g),h={plugin:u.id,providerName:d,authKind:c,alreadyConfigured:p?.connected??!1};if(f.length>0&&(h.credentialFields=f),c==="oauth"){let b=t.oauthModeOverrides?.[u.id]??(l==="managed"?"managed":"byo");if(h.oauthMode=b,!t.skipOAuthUrlGeneration&&b!=="managed")try{let C=await Vt(a,u.id,{tenantId:n,redirectUri:r,hubConnect:!0});h.oauthUrl=C.url}catch(C){C instanceof Error&&/client_id not configured/i.test(C.message)||(h.setupError=C instanceof Error?C.message:`Could not prepare OAuth for ${u.id}`)}}o.push(h)}return o}async function ap(e,n,t={}){let r=v(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return Vn({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function ri(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await je(e.internalConfig??Sa(e),n)}async function oi(e,n){await ze(e,n)}async function ii(e,n){let t=We(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=me({deliveryUrl:n.deliveryUrl})),x({hub:e,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:On})}async function Yt(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await ri(t,n.tenantId);let r=await Vn(t,n.tenantId,{pluginIds:[n.plugin.id]});if(r.length===0)throw new Error(`Plugin '${n.plugin.id}' is not configured on this Corsair instance`);return ii(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function Yn(e,n){let t=v(e),r=F(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r,multiTenancy:t.multiTenancy,internalConfig:t};await oi(e,n.tenantId);let i=n.plugin?[n.plugin]:void 0,s=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,a=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,u=await Vn(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(u.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return ii(r,{tenantId:n.tenantId,plugins:u,deliveryUrl:n.deliveryUrl})}async function Qn(e,n){let t=n.tenantId.trim();if(!t)throw new Error("tenantId is required");let r=n.plugins.map(s=>s.trim()).filter(Boolean);if(r.length===0)throw new Error("At least one plugin is required");let o=v(e);if(!o.hub)throw new Error("Hub is not configured on this Corsair instance");if(!o.database)throw new Error("Database not configured");let i=await Ea(o.hub,{plugins:o.plugins,database:o.database,kek:o.kek,multiTenancy:o.multiTenancy},{tenantId:t,pluginIds:r});return{connectUrl:i.connectUrl,expiresAt:i.expiresAt}}async function Ea(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-FNOU5Z5O.js"),{postHubConnectSession:i}=await import("./connect-MCJ7RG5E.js"),s={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await o(s,t.tenantId);let a=await r(s,t.tenantId,{pluginIds:t.pluginIds});if(a.length===0)throw new Error("No connectable plugins found for this tenant");let u=a.find(l=>l.setupError);if(u)throw new Error(u.setupError??`Could not prepare connect link for ${u.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}function Je(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var J=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Da(e){let n=e.oauthConfig;if(!n)throw new J("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Qt(e,n){let t=v(e,()=>new J("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new J("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new J("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=qn(n,t.kek);if(!o)throw new J("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=$(t,i,p=>new J("plugin_not_found",p)),u=Da(a),c=await U({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!c)throw new J("client_id_not_configured",`client_id not configured for '${i}'`);let d=De({oauthConfig:u,clientId:c,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:u.providerName,oauthUrl:d,state:n}}import{AsyncLocalStorage as Ma}from"async_hooks";import{randomBytes as Ha}from"crypto";import{v4 as Fa}from"uuid";async function Xn(e,n){let t=We(e.projectApiKey),r={permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,expiresAt:n.expiresAt};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=me({deliveryUrl:n.deliveryUrl})),x({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:Hn})}function et(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Xt="Permission approval required. Set manual.approvalBaseUrl (or use hub for hosted approval) so an approval URL can be generated. Optionally set manual.onApprovalRequired to customize the agent message.";function nr(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function si(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function er(e){return et(e)}async function tr(e,n){if(nr(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?si(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await Xn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:Oa(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function Oa(e){try{return JSON.parse(e)}catch{return e}}async function nt(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await tr(e,n);return{...n,approvalUrl:r}}async function rr(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:u,tenantId:l,expiresAt:c,operationPath:d}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:u});let g=await tr({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(u),tenant_id:l,expires_at:c});return nr(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):er(g):Xt:r?g?er(g):`Action '${d}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Xt}var Ve=class extends Error{constructor(n){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError"}};var ui=new Ma,tt=class extends Error{endpointPath;riskLevel;constructor(n,t){super(`Action '${n}' is a '${t}' operation and is forbidden in readonly mode. Only read operations are permitted \u2014 rewrite the script to avoid write/destructive actions.`),this.name="ReadonlyForbiddenError",this.endpointPath=n,this.riskLevel=t}};function or(e){return ui.run(!0,e)}function ci(){return ui.getStore()===!0}function ir(e,n){if(ci()&&n!=="read")throw new tt(e,n)}var Ua={open:{read:"allow",write:"allow",destructive:"allow"},cautious:{read:"allow",write:"allow",destructive:"require_approval"},strict:{read:"allow",write:"require_approval",destructive:"deny"},readonly:{read:"allow",write:"deny",destructive:"deny"}};function Ba(e,n,t){return t!==void 0?t:Ua[n][e]}function sr(e){let n=/(\d+)(d|h|m|s)/g,t=0,r;for(;(r=n.exec(e))!==null;){let o=parseInt(r[1],10);switch(r[2]){case"d":t+=o*864e5;break;case"h":t+=o*36e5;break;case"m":t+=o*6e4;break;case"s":t+=o*1e3;break}}return t>0?t:600*1e3}function li(e){return{async find_by_permission_id(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst()},async find_by_token(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst()},async set_executing(n){e&&await e.db.updateTable("corsair_permissions").set({status:"executing",updated_at:new Date}).where("id","=",n).execute()},async set_completed(n){e&&await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}}}async function ai(e,n,t){let r=Date.now()+t;for(;Date.now()<r;){let o=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).executeTakeFirst();if(!o)return{result:"blocked",reason:"pending"};if(o.status==="approved")return{result:"allow",onComplete:async()=>{await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}};if(o.status==="denied")return{result:"blocked",reason:"denied"};if(o.status==="expired"||o.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(i=>setTimeout(i,500))}return{result:"blocked",reason:"timeout"}}async function di(e){let n=Ba(e.riskLevel,e.mode,e.override);if(n==="allow")return{result:"allow"};let t=e.meta?.irreversible?" (irreversible)":"",r=e.meta?.description?`${e.meta.description}${t}`:`${e.pluginId}.${e.endpointPath}${t}`;if(n==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
|
|
10
|
+
Action: ${r}`,`
|
|
11
|
+
To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let o=JSON.stringify(e.args),i=new Date().toISOString(),s=e.tenantId??"default",a=await e.db.db.selectFrom("corsair_permissions").selectAll().where("plugin","=",e.pluginId).where("endpoint","=",e.endpointPath).where("args","=",o).where("tenant_id","=",s).where("expires_at",">",i).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(a){if(a.status==="approved"){let f=e.db,h=a.id;return{result:"allow",onComplete:async()=>{await f.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",h).execute()}}}return a.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
|
|
12
|
+
Action: ${r}`,`
|
|
13
|
+
Permission ID: ${a.id}`,`
|
|
14
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?ai(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let u=Fa(),l=Ha(32).toString("hex"),c=e.timeoutMs??600*1e3,d=new Date(Date.now()+c).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:u,created_at:new Date,updated_at:new Date,token:l,plugin:e.pluginId,endpoint:e.endpointPath,args:o,tenant_id:s,status:"pending",expires_at:d}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
|
|
15
|
+
Action: ${r}`,`
|
|
16
|
+
Permission ID: ${u}`,`
|
|
17
|
+
Permission token: ${l}`,`
|
|
18
|
+
Expires at: ${d}`,`
|
|
19
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?ai(e.db,u,c):{result:"blocked",reason:"pending",id:u,token:l,expiresAt:d}}var E=class extends Error{status;code;extra;constructor(n,t,r,o={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=o}};function B(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function pi(e){let n={error:e.code,message:e.message,...e.extra};return B(e.status,n)}function Te(e){return new E(404,"not_found",e)}function ge(e,n={}){return new E(400,"bad_request",e,n)}function gi(e,n){return $(e,n,t=>Te(t))}async function fi(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=U({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),o=L[t].integration,i=r,s;try{s=await Promise.all(o.map(l=>i[`get_${l}`]()))}catch{s=o.map(()=>null)}let a=o.filter((l,c)=>s[c]==null),u;return t==="oauth_2"?u=!a.includes("client_id")&&!a.includes("client_secret"):u=a.length===0,{configured:u,missingFields:a}}async function yi(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await fi(e,n);return{id:e.id,authType:t,configured:o,missingFields:i,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function rt(){return{ok:!0}}async function Ye(e){return Promise.all(e.plugins.map(n=>yi(n,e)))}async function ot(e,n){let t=gi(e,n);return yi(t,e)}async function La(e,n){return e.database?(await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.id as accountId","a.dek as dek","i.name as integrationName"]).where("a.tenant_id","=",n).execute()).map(r=>({integrationName:r.integrationName,hasCredentials:!!r.dek})):[]}async function mi(e,n){let t=await La(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Qe(e){let n=new Map;if(n.set("default",{id:"default",accounts:[],connectedPlugins:[]}),e.database){let t=await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id","a.dek as dek","i.name as integrationName"]).execute();for(let r of t){let o=r.tenant_id;if(!o)continue;let i=n.get(o);i||(i={id:o,accounts:[],connectedPlugins:[]},n.set(o,i));let s=!!r.dek;i.accounts.push({integrationName:r.integrationName,hasCredentials:s}),s&&i.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function it(e,n){if(!n)throw ge("Tenant id must be a non-empty string");return mi(e,n)}async function st(e,n){let t=n?.id?.trim();if(!t)throw ge("Tenant id is required",{missingFields:["id"]});return mi(e,t)}async function at(e,n){let t=n?.trim()||"default",r={},o=await mn(e,t);for(let i of o)r[i.plugin]=Kn(i);for(let i of e.plugins)i.id in r||(!i.options?.authType||!e.database||!e.kek?r[i.id]="missing_credentials":r[i.id]="not_connected");return r}async function ar(e,n){if(!e.database)throw Te(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw Te(`Permission '${n}' not found`);return nt(e,t)}function Na(e){if(!e.oauthConfig)throw ge(`Plugin '${e.id}' has no oauthConfig`)}function $a(e){if(!e.manual)throw new E(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function ur(e){let n=$a(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new E(500,"connect_not_configured","Manual connect requires manual.baseUrl and manual.redirectUri. Use hub for hosted connect, or set both URLs for manual OAuth.");return n}function Wa(e){let n=!!e.hub,t=Je(e.manual);if(!n&&!t)throw new E(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function hi(e){if(!e.database||!e.kek)throw new E(500,"database_not_configured","A database and kek are required to issue connect links.")}async function ja(e,n){let t=n?.plugin?.trim();if(!t)throw ge("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=gi(e,t);Na(o);let i=ur(e);hi(e);let s=await fi(o,e);if(!s.configured)throw new E(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=Ke(Pe(t,r),e.kek),u;try{u=new URL(i.baseUrl)}catch{throw new E(500,"connect_misconfigured","manual.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return u.searchParams.set("state",a),{connectUrl:u.toString(),expiresAt:new Date(Date.now()+zt).toISOString()}}async function Ka(e,n,t){hi(n);let o={tenantId:t.tenantId?.trim()||"default",oauthMode:t.oauthMode},i=t.plugin?.trim();i&&(o.plugin=i);let s=t.providerName?.trim();s&&(o.providerName=s);let a=await Yn(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt}}async function ut(e,n,t){return Wa(n),n.hub?Ka(e,n,t):ja(n,t)}async function ct(e,n,t){if(n.hub&&!Je(n.manual))throw new E(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw ge("state is required",{missingFields:["state"]});ur(n);try{return await Qt(e,r)}catch(o){if(o instanceof J)switch(o.code){case"invalid_state":throw ge("Invalid or expired state");case"client_id_not_configured":throw new E(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new E(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function lt(e,n,t){if(n.hub&&!Je(n.manual))throw new E(400,"hub_mode","oauthCallback is not used with hub config. Hub delivers tokens to your deliveryUrl.");let r=t?.code?.trim(),o=t?.state?.trim(),i=[];if(r||i.push("code"),o||i.push("state"),i.length)throw ge("Missing required fields",{missingFields:i});let s=ur(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:o,redirectUri:s.redirectUri,callbackParams:t.callbackParams})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw ge("Invalid or expired state");case"credentials_not_configured":throw new E(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new E(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function cr(e,n){if(!e.database)throw Te("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw Te("Permission not found");return nt(e,t)}async function bi(e,n){return"id"in n?ar(e,n.id):cr(e,n.token)}import{createCipheriv as Ya,createDecipheriv as pg,randomBytes as vi,scryptSync as Qa}from"crypto";import{createHmac as lr,randomUUID as qa,timingSafeEqual as wi}from"crypto";function dr(e){return e.run??null}function pr(e){return e.probe??null}function Ci(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function dt(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=lr("sha256",e.signingSecret.trim()).update(n).digest("hex");return{body:n,headers:{"content-type":"application/json","x-corsair-signature":`sha256=${r}`,"x-corsair-timestamp":t,"x-corsair-project":e.projectId,"x-corsair-nonce":qa()}}}function gr(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Ci(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Se)return!1;let i=lr("sha256",n).update(e.body).digest("hex");try{return wi(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function Xe(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=Ci(e.signatureHeader);if(!t)return{ok:!1,error:"Invalid tunnel signature"};let r=Number(e.timestampHeader);if(!Number.isFinite(r))return{ok:!1,error:"Invalid or missing tunnel timestamp"};if(Math.abs(Date.now()-r*1e3)>Se)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=lr("sha256",n).update(e.body).digest("hex");try{if(!wi(Buffer.from(i,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}function en(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function pt(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function gt(e){let n=e.sync?.encrypted;return typeof n!="string"||!n.trim()?null:{encrypted:n.trim()}}function wn(e){let n=e.connectUrl?.trim();return n?{connectUrl:n,expiresAt:e.expiresAt}:null}function fr(e){return wn(en(e))}async function yr(e){let n=await mt({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=en(n.body),r=pt({httpOk:n.ok,status:n.status,body:t}),o=wn(t);if(!r||!o)throw new Error(yt({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function ft(e){return gt(en(e))}function Za(e){let n=e;for(;n;){if(n instanceof Error){let t=n.code;if(typeof t=="string")return t;n=n.cause;continue}if(typeof n=="object"&&n!==null&&"code"in n){let t=n.code;if(typeof t=="string")return t}break}}function ki(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var Ga="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",za="Check the delivery URL configured for this environment.";function Ja(e){return`${e.ack.error?`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`:`App rejected the signed delivery (HTTP ${e.status} from ${e.deliveryUrl})`}. ${Ga}`}function Va(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${za}`}function Cn(e,n){let t=Za(n),r=n instanceof Error?n.message:"Delivery request failed",o;switch(t){case"ECONNREFUSED":o="connection refused \u2014 nothing accepted a TCP connection on that host and port";break;case"ENOTFOUND":o="host not found \u2014 DNS could not resolve the hostname";break;case"ETIMEDOUT":case"UND_ERR_CONNECT_TIMEOUT":o="connection timed out before the app responded";break;case"ECONNRESET":o="connection reset while talking to the app";break;case"CERT_HAS_EXPIRED":case"UNABLE_TO_VERIFY_LEAF_SIGNATURE":case"DEPTH_ZERO_SELF_SIGNED_CERT":o=`TLS certificate error (${t})`;break;default:o=r==="fetch failed"&&t?`${r} (${t})`:r}return[`Could not reach ${e}`,o].join(". ")}function yt(e){if(e.status===0)return e.ack.error?e.ack.error:e.body.startsWith("Could not reach")?e.body:Cn(e.deliveryUrl,new Error(e.body||"Delivery request failed"));if(e.status===401||e.status===403)return Ja(e);if(e.status===404)return Va(e);if(e.ack.error)return`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`;if(e.status>=500){let t=e.body.trim();return t?`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl}): ${ki(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${ki(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}async function mt(e){let{body:n,headers:t}=dt(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),o=await r.text();return{ok:r.ok,status:r.status,body:o}}catch(r){return{ok:!1,status:0,body:Cn(e.deliveryUrl,r)}}}var Xa="aes-256-gcm",eu=12,nu=16,tu=16,ru=32;function ou(e,n){return Qa(e.trim(),n,ru)}function mr(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=vi(tu),o=ou(t,r),i=vi(eu),s=Ya(Xa,o,i,{authTagLength:nu}),a=JSON.stringify(e),u=Buffer.concat([s.update(a,"utf8"),s.final()]),l=s.getAuthTag();return[r.toString("base64"),i.toString("base64"),l.toString("base64"),u.toString("base64")].join(":")}var iu=["invalid corsair instance","a database must be configured to sync connections from the app","a database must be configured on the corsair instance","signing secret is required to encrypt sync manifest"];function hr(e){if(e instanceof yo)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!iu.some(t=>n.includes(t))}function su(e){if(!e)return[];let n=R(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!ve(r)):[]}async function vn(e,n){let t=v(e);if(!t.database)throw new Error("A database must be configured to sync connections from the app");await Jn(e,{silent:!0});let[r,o]=await Promise.all([Qe(t),Ye(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=su(t.plugins.find(u=>u.id===s.id));return{id:s.id,authType:s.authType,configured:s.configured,missingFields:s.missingFields,...a.length>0?{integrationCredentialFields:a}:{}}}),syncedAt:new Date().toISOString()};return mr(i,n)}var re=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function ht(e,n){let t=v(e,()=>new re("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new re("no_database","Database not configured");let r=$(t,n.plugin,c=>new re("plugin_not_found",c)),o=R(r);if(!o)throw new re("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new re("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await ze(e,n.tenantId);let i=new Set(En(r,o)),a=r.authConfig?.[o]?.account??[],u=M({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),l=0;for(let[c,d]of Object.entries(n.credentials)){if(!d.trim())continue;if(!i.has(c))throw new re("invalid_credentials",`Unknown credential field '${c}' for plugin '${n.plugin}'`);let p=K(u,`set_${c}`);if(!p)throw new re("invalid_credentials",`Cannot set credential field '${c}' for plugin '${n.plugin}'`);await p(d.trim()),l+=1}if(l===0)throw new re("invalid_credentials","Provide at least one credential field to save");return await pe(e,{plugin:r,tenantId:n.tenantId}).catch(()=>{}),{plugin:n.plugin,tenantId:n.tenantId}}var oe=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function br(e,n){let t=v(e,()=>new oe("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new oe("no_database","Database not configured");let r=$(t,n.plugin,c=>new oe("plugin_not_found",c)),o=R(r);if(!o)throw new oe("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await ni(e);let i=new Set(bo(r,o)),a=r.authConfig?.[o]?.integration??[],u=U({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:a}),l=0;for(let[c,d]of Object.entries(n.credentials)){if(!d.trim())continue;if(!i.has(c))throw new oe("invalid_credentials",`Unknown integration credential field '${c}' for plugin '${n.plugin}'`);let p=K(u,`set_${c}`);if(!p)throw new oe("invalid_credentials",`Cannot set integration field '${c}' for plugin '${n.plugin}'`);await p(d.trim()),l+=1}if(l===0)throw new oe("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var bt=new Map;function au(e){for(let[n,t]of bt)t<=e&&bt.delete(n)}function kt(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};if(!Number.isFinite(n)||n<=0)return{ok:!1,error:"Delivery replay TTL must be a positive number"};let r=Date.now();au(r);let o=bt.get(t);return o!==void 0&&o>r?{ok:!1,error:"Delivery request already consumed"}:(bt.set(t,r+n),{ok:!0})}var Ae=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function nn(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a,authType:u="managed",providerData:l}=n;if(!o.trim())throw new Ae("no_access_token","Managed OAuth delivery missing access_token");let c=v(e,()=>new Ae("invalid_corsair_instance","Invalid corsair instance"));if(!c.database)throw new Ae("no_database","No database configured on corsair instance");let d=$(c,t,g=>new Ae("plugin_not_found",g));await ze(e,r);let p=M({authType:u,integrationName:t,tenantId:r,kek:c.kek,database:c.database});await p.set_access_token(o),i&&await p.set_refresh_token(i),s&&await p.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await p.set_scope(a),await pe(e,{plugin:d,tenantId:r}).catch(()=>{});try{let g=await Zn(c.plugins,t,{access_token:o,refresh_token:i,scope:a,...l});if(g){try{let f=d.authConfig?.[u]?.account??[];await Ze({database:c.database,kek:c.kek,pluginId:t,tenantId:r,link:g,authType:u,extraAccountFields:f})}catch(f){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,f)}c.hub&&qe(c.hub,{plugin:t,tenantId:r,link:g,authType:u})}}catch(g){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,g)}return await Ge(e,d,r,p).catch(g=>{console.warn(`[corsair:managed-oauth] subscribe failed for '${t}' tenant '${r}':`,g)}),{plugin:t,tenantId:r}}function uu(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Pi(e,n,t=[]){for(let[r,o]of Object.entries(e))if(uu(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=Pi(o,n,[...t,r]);if(i)return i}return null}function cu(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function lu(e){let n=e["x-goog-resource-uri"],t=e["x-goog-channel-id"];if(!n||!t)return null;let r={resourceId:e["x-goog-resource-id"]||"",resourceState:e["x-goog-resource-state"]||"",resourceUri:n,channelId:t,channelExpiration:e["x-goog-channel-expiration"]||""};return n.includes("/drive/")&&(r.kind="drive#change"),{message:{data:Buffer.from(JSON.stringify(r)).toString("base64"),messageId:e["x-goog-message-number"]||""}}}async function Ti(e,n,t,r,o){let i=cu(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=lu(i)||s);let u={headers:i,body:s,...r?{query:r}:{}},l=r?.tenantId||"default",c=e.withTenant?e.withTenant(l):e,d=o?.plugin,p=d?[d]:Dn;for(let g of p){let f=c[g];if(!f||!f.webhooks||!d&&f.pluginWebhookMatcher&&!f.pluginWebhookMatcher(u))continue;let h=Pi(f.webhooks,u);if(!h)continue;let k=h.path.join("."),b={payload:s,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{},...o?.hubVerified?{hubVerified:!0}:{}};try{let C=await h.webhook.handler(b),P=!!Object.keys(C.returnToSender||{})?.length;return{plugin:g,action:k,body:s,response:P?{...C?.returnToSender,success:!0}:{success:!0},...C.responseHeaders&&{responseHeaders:C.responseHeaders}}}catch(C){return console.error(`Error executing webhook handler for ${g}.${k}:`,C),{plugin:g,action:k,body:s,response:{success:!1,error:C instanceof Error?C.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHash as du}from"crypto";import*as Oe from"vm";var Ai="__corsairFailedStep",pu=3e4,kr=class{constructor(n,t){this.wakeAt=n;this.stepName=t}__corsairSleep=!0};function xi(e){return typeof e=="object"&&e!==null&&e.__corsairSleep===!0}function Ri(e,n){return`st_${du("sha256").update(`${n} ${e}`).digest("hex").slice(0,16)}`}function wt(e){if(e instanceof Error)return e.message;if(e!==null&&typeof e=="object"&&"message"in e){let n=e.message;if(typeof n=="string")return n}return String(e)}var Ii=new Set(["constructor","prototype","__proto__"]);function fe(e,n){if(e===null)return null;let t=typeof e;return t==="function"?fu(e,n):t==="object"?gu(e):e}function gu(e){return new Proxy(e,{get(n,t){if(!Ii.has(t))return fe(Reflect.get(n,t,n),n)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function fu(e,n){return new Proxy(e,{apply:(t,r,o)=>yu(Reflect.apply(t,n,o)),construct(){throw new Error("Workflow code may not construct host objects")},get(t,r){if(!Ii.has(r))return fe(Reflect.get(t,r,t),t)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function yu(e){return e!==null&&typeof e=="object"&&typeof e.then=="function"?Promise.resolve(e).then(n=>fe(n,void 0),n=>{throw fe(n,void 0)}):fe(e,void 0)}function mu(e){let n=Object.create(null),t=Oe.createContext(n,{name:"corsair-workflow",codeGeneration:{strings:!1,wasm:!1}}),o=Oe.runInContext("(s) => JSON.parse(s)",t,{filename:"corsair:sandbox:json"})(JSON.stringify(e.payload??null)),s=Oe.runInContext(`(function (hostRun, hostSleep) {
|
|
20
|
+
const step = function step(name, fn) { return hostRun(name, fn); };
|
|
21
|
+
step.sleep = function sleep(name, ms) { return hostSleep(name, ms); };
|
|
22
|
+
return step;
|
|
23
|
+
})`,t,{filename:"corsair:sandbox:step"})((p,g)=>e.step(p,g),(p,g)=>e.step.sleep(p,g)),u=Oe.runInContext(`(function (sink) {
|
|
24
|
+
const fwd = (level) => function () {
|
|
25
|
+
try { sink(level, Array.prototype.slice.call(arguments)); } catch (_e) {}
|
|
26
|
+
};
|
|
27
|
+
return { log: fwd('log'), info: fwd('info'), warn: fwd('warn'), error: fwd('error'), debug: fwd('debug') };
|
|
28
|
+
})`,t,{filename:"corsair:sandbox:console"})((p,g)=>{let f=console[p]??console.log;try{f(...g)}catch{}});n.__corsair=fe(e.corsair,void 0),n.__payload=o,n.__step=s,n.__console=u;let l=Oe.runInContext(`(function () {
|
|
29
|
+
'use strict';
|
|
30
|
+
const module = { exports: {} };
|
|
31
|
+
const require = function (id) {
|
|
32
|
+
throw new Error('Workflow code may not import modules (attempted to require "' + id + '")');
|
|
33
|
+
};
|
|
34
|
+
(function (exports, module, require, console) {
|
|
35
|
+
${e.code}
|
|
36
|
+
})(module.exports, module, require, __console);
|
|
37
|
+
const main = module.exports.main;
|
|
38
|
+
if (typeof main !== 'function') {
|
|
39
|
+
throw new Error('Workflow code must export a \`main\` function');
|
|
40
|
+
}
|
|
41
|
+
return main(__corsair, __payload, __step);
|
|
42
|
+
})()`,t,{filename:"corsair:workflow",timeout:e.timeoutMs});l.catch(()=>{});let c,d=new Promise((p,g)=>{c=setTimeout(()=>g(new Error(`Workflow exceeded ${e.timeoutMs}ms time limit`)),e.timeoutMs)});return Promise.race([l,d]).finally(()=>clearTimeout(c))}async function wr(e){let n=e.memoizedSteps??{},t=[],r=0,o=null,i=(async(s,a)=>{if(o)throw o;let u=r++,l=Ri(s,u);if(Object.hasOwn(n,l))return fe(n[l].output,void 0);try{let c=await a();return t.push({stepId:l,name:s,seq:u,status:"completed",output:c}),c}catch(c){if(xi(c))throw c;let d=wt(c);t.push({stepId:l,name:s,seq:u,status:"failed",error:d});let p=new Error(d);throw p[Ai]=s,p}});i.sleep=async(s,a)=>{if(o)throw o;let u=r++,l=Ri(s,u);if(Object.hasOwn(n,l))return;t.push({stepId:l,name:s,seq:u,status:"completed",output:null});let c=Number.isFinite(a)?Math.max(0,a):0;throw o=new kr(Date.now()+c,s),o};try{await mu({code:e.code,corsair:e.corsair,payload:e.payload,step:i,timeoutMs:e.timeoutMs??pu});let s=o;return s?{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()}:{status:"completed",steps:t}}catch(s){if(xi(s))return{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()};let a=wt(s),u=s!==null&&typeof s=="object"?s[Ai]:void 0;return{status:"failed",steps:t,error:{message:a,...u?{failedStep:u}:{}}}}}import*as Ct from"vm";var Si=1e4;async function Cr(e){let n=Object.create(null),t=Ct.createContext(n,{name:"corsair-probe",codeGeneration:{strings:!1,wasm:!1}});n.corsair=fe(e.corsair,void 0);let r=bu(e.timeoutMs),o=`(async () => {
|
|
43
|
+
const __result = await (async () => {
|
|
44
|
+
${e.code}
|
|
45
|
+
})();
|
|
46
|
+
return JSON.stringify(__result) ?? 'null';
|
|
47
|
+
})()`;try{let i=await or(()=>{let s=Ct.runInContext(o,t,{filename:"corsair:probe",timeout:r});s.catch(()=>{});let a,u=new Promise((l,c)=>{a=setTimeout(()=>c(new Error(`Probe exceeded ${r}ms time limit`)),r)});return Promise.race([s,u]).finally(()=>clearTimeout(a))});return{status:"ok",value:hu(i)}}catch(i){return{status:"error",error:wt(i)}}}function hu(e){if(typeof e!="string")throw new Error(`Probe returned a non-string result (${typeof e})`);return JSON.parse(e)}function bu(e){return typeof e!="number"||!Number.isFinite(e)||e<=0?Si:Math.min(e,Si)}function Me(e){return e.deliveryMode==="auth.credentials"}function Pn(e){return e.deliveryMode==="connections.sync"}function vt(e){return e.deliveryMode==="connect.create_link"}function Tn(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function An(e){return e.deliveryMode==="oauth.tokens"}function Pt(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!Me(e)&&!Pn(e)&&!vt(e)&&!Tn(e)&&!An(e)}function ku(e){return{status:"ok",connectLink:{connectUrl:e.connectUrl,expiresAt:e.expiresAt},webhookResponse:{status:200,body:{status:"ok",connectUrl:e.connectUrl,expiresAt:e.expiresAt}}}}async function wu(e,n){try{return{status:"ok",webhookResponse:{status:200,body:{status:"ok",sync:{encrypted:await vn(e,n)}}}}}catch(t){return{status:"failed",retryable:hr(t),error:t instanceof Error?t.message:"Connections sync delivery failed"}}}async function Cu(e,n){try{let t=await Qn(e,n);return ku(t)}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Connect link delivery failed"}}}function vr(e,n){if(e instanceof Headers)return e.get(n)??void 0;let t=e[n]??e[n.toLowerCase()];return Array.isArray(t)?t[0]:typeof t=="string"?t:void 0}async function vu(e,n,t){let r=typeof t.tenantId=="string"?t.tenantId:typeof t.query?.tenantId=="string"?t.query.tenantId:void 0;return r||(!n.database||!t.plugin||!t.linkType||!t.externalId?void 0:await Gn({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Pu(e,n,t,r){let o=await vu(e,n,t),i={...t.query??{},...o?{tenantId:o}:{}},s=await Ti(e,t.headers,t.body,i,{plugin:t.plugin,hubVerified:r&&t.hubVerified===!0});if(!s.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(s.response&&s.response.success===!1)return{status:"failed",retryable:!1,error:typeof s.response.error=="string"?s.response.error:"Webhook handler failed"};let a=s.response?.returnToSender,u=a&&typeof a=="object"&&typeof a.validationToken=="string"&&Object.keys(a).length===1?a.validationToken:a||(s.response?.data??s.response);return{status:"ok",webhookResponse:{status:s.response?.statusCode??200,body:u,headers:s.responseHeaders}}}async function Tu(e,n){return await kn(e,{code:n.code,state:n.state,redirectUri:n.redirectUri,callbackParams:n.callbackParams,...n.plugin&&n.tenantId?{trusted:!0,plugin:n.plugin,tenantId:n.tenantId}:{}}),{status:"ok"}}async function Au(e,n){return await nn(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope,authType:n.authType,providerData:n.providerData}),{status:"ok"}}async function Tr(e,n,t){let r=await Pr(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function Pr(e,n,t){let r=v(e),o=n.token?.trim();if(!o)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let i=new Date().toISOString(),s=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",o).executeTakeFirst();return s?s.status!=="pending"?{status:"ok"}:s.expires_at<i?(await r.database.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",s.id).execute(),{status:"failed",retryable:!1,error:"Permission has expired"}):(await r.database.db.updateTable("corsair_permissions").set({status:t,updated_at:new Date}).where("id","=",s.id).execute(),{status:"ok"}):{status:"failed",retryable:!1,error:"Permission not found"}}async function xu(e,n){try{return await ht(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function Ru(e,n){try{return await br(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}function _i(e,n){let t=e;return n&&typeof t?.withTenant=="function"?t.withTenant(n):e}async function Iu(e,n){try{let t=_i(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",run:await wr({corsair:t,code:n.code,payload:n.trigger?.payload??null,memoizedSteps:n.memoizedSteps})}}}}catch(t){return{status:"failed",retryable:!0,error:t instanceof Error?t.message:"Workflow run failed"}}}async function Su(e,n){try{let t=_i(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",probe:await Cr({corsair:t,code:n.code,timeoutMs:n.timeoutMs})}}}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Probe failed"}}}async function xn(e,n,t={}){let r=v(e),o=vr(n.headers,"x-corsair-signature"),i=vr(n.headers,"x-corsair-timestamp"),s=vr(n.headers,"x-corsair-nonce"),a=!1;if(t.signingSecret?.trim()){let l=Xe({body:n.body,signatureHeader:o,timestampHeader:i,signingSecret:t.signingSecret});if(!l.ok)return{status:"failed",retryable:!1,error:l.error};if(!s?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let c=kt(`nonce:${s.trim()}`,Se);if(!c.ok)return{status:"failed",retryable:!1,error:c.error};a=!0}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let u;try{u=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}if(u.type==="connect.status")return{status:"failed",retryable:!1,error:"connect.status is deprecated; use connections.sync signed delivery instead"};switch(u.type){case"webhook":return Pu(e,r,u.payload,a);case"oauth.callback":return Tu(e,u.payload);case"oauth.tokens":return Au(e,u.payload);case"permission.approve":return Pr(e,u.payload,"approved");case"permission.deny":return Pr(e,u.payload,"denied");case"auth.credentials":return xu(e,u.payload);case"integration.credentials":return Ru(e,u.payload);case"connect.create_link":return Cu(e,u.payload);case"connections.sync":{let l=t.signingSecret?.trim();return l?wu(e,l):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}case"run":return t.allowWorkflowExecution?Iu(e,u.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};case"probe":return t.allowWorkflowExecution?Su(e,u.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${String(u.type)}`}}}function _u(e){let n=e.webhookResponse;return e.status==="ok"?{status:n?.status??200,body:n?.body??{status:"ok"}}:{status:n?.status??502,body:n?.body??{status:"error",error:e.error??"delivery failed"}}}var Ar=3,Eu=250;function Du(e){return e?.name==="AbortError"}async function Ou(e){try{return(await e.json())?.ok!==!1}catch{return!0}}async function Mu(e,n,t,r,o){for(let i=1;i<=Ar;i++){try{let s=await n.fetch(`${e.apiUrl}/api/dev/ack`,{method:"POST",headers:{...t,"content-type":"application/json"},body:JSON.stringify(r),signal:o});if(s.ok)return await Ou(s)||console.warn(`[corsair] hub did not record delivery ${r.deliveryId} (already timed out); the run may be retried`),!0}catch(s){if(Du(s))throw s}i<Ar&&await Di(Eu)}return console.warn(`[corsair] failed to acknowledge delivery ${r.deliveryId} after ${Ar} attempts; the run may be retried`),!1}async function Hu(e,n,t,r){let o={authorization:`Bearer ${n.projectApiKey}`},i=await t.fetch(`${n.apiUrl}/api/dev/pull`,{headers:o,signal:r});if(i.status===204)return"idle";if(!i.ok)return"error";let{deliveryId:s,body:a,headers:u}=await i.json(),l=await t.process(e,{headers:u,body:a},{signingSecret:n.signingSecret,allowWorkflowExecution:n.allowWorkflowExecution}),{status:c,body:d}=_u(l);return await Mu(n,t,o,{deliveryId:s,status:c,body:d},r)?"handled":"error"}var Ei=1e3,Fu=5e3,Uu=3e4;function Di(e){return new Promise(n=>setTimeout(n,e))}var Tt=globalThis.__corsairConnectLoops??=new Map;function Bu(e,n={fetch,process:xn}){let t;try{t=F(e)}catch{return{stop:()=>{}}}if(!t.projectApiKey.startsWith("ck_dev_"))return{stop:()=>{}};if(!t.allowWorkflowExecution)return console.warn("[corsair] workflow executions not enabled. Please set hub: { ..., allowWorkflowExecution: true }"),{stop:()=>{}};let r=t.projectApiKey;if(Tt.has(r))return{stop:()=>{}};let o=Symbol("corsair-connect-loop");Tt.set(r,o);let i=()=>{Tt.get(r)===o&&Tt.delete(r)},s=!1,a=null;return(async()=>{let l=Ei,c=!1,d=async p=>{c||(console.warn("[corsair] connect loop error; retrying",p),c=!0),s||await Di(l),l=Math.min(l*2,Fu)};try{for(;!s;){a=new AbortController;let p=setTimeout(()=>a?.abort(),Uu);try{await Hu(e,t,n,a.signal)==="error"?await d("pull or ack failed"):(c=!1,l=Ei)}catch(g){if(s)break;await d(g instanceof Error?g.message:g)}finally{clearTimeout(p)}}}finally{i()}})(),{stop:()=>{s=!0,a?.abort(),i()}}}function Oi(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Lu(e,n){return n&&!n.has(e.id)?!1:R(e)!==null}async function Mi(e,n,t={}){let r=v(e),o=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,s=await mn(r,o,{pluginIds:t.pluginIds}),a=new Map(s.map(l=>[l.plugin,l])),u=r.plugins.filter(l=>Lu(l,i)).map(l=>{let c=R(l),d=a.get(l.id);return d?{plugin:l.id,providerName:be(l.id),authKind:Oi(c),status:d.status,connected:d.connected,fields:d.fields.map(p=>({name:p.name,level:p.level,required:p.required,configured:p.configured})),missingRequiredFields:d.missingRequiredFields}:{plugin:l.id,providerName:be(l.id),authKind:Oi(c),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:u}}async function Hi(e,n){let t=F(e);return N({hub:t,path:`/projects/${encodeURIComponent(n.projectId)}/connections`,notFoundMessage:"Hub REST API not found at /projects/:id/connections. Check HUB_API_URL and ensure the Hub API is deployed.",parseResponse:Mn})}var xr=new Map;function Fi(e){let n;try{n=F(e)}catch{return}let t=Ft(n);t&&xr.get(n.projectApiKey)!==t&&(xr.set(n.projectApiKey,t),x({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{xr.delete(n.projectApiKey)}))}var Nu=[".corsair.dev"];function $u(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Wu(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:$u(n)?!0:Nu.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Ui(e){return!e||!Wu(e)?null:{"Access-Control-Allow-Origin":e,"Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"content-type, x-corsair-signature, x-corsair-timestamp, x-corsair-project, x-corsair-nonce, access-control-request-private-network","Access-Control-Allow-Private-Network":"true","Access-Control-Max-Age":"0",Vary:"Origin"}}function Bi(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,o]of Object.entries(n))t.set(r,o);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function Rr(e,n){let t=new URL(e);return n.error?(t.searchParams.set("error",n.error),t.toString()):n.connectedPlugin?(t.searchParams.set("connected",n.connectedPlugin),t.toString()):(n.status!==void 0&&t.searchParams.set("status",Buffer.from(JSON.stringify(n.status)).toString("base64url")),t.toString())}async function Ir(e,n){let t=F(e),o=new URL(n).searchParams.get("d");if(!o)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let i=we(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=kt(`browser:${i.jti}`,ke);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(Pn(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connections sync delivery requires hubOrigin and requestId for client bridge"}};let a=await vn(e,t.signingSecret);return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Le({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(vt(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connect link delivery requires hubOrigin and requestId for client bridge"}};let a=i.connectLinkPlugins?.filter(Boolean)??[];if(a.length===0)return{type:"json",status:400,body:{error:"Connect link delivery requires at least one plugin in connectLinkPlugins"}};let u=await Qn(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Le({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:u.connectUrl,expiresAt:u.expiresAt}})}}if(Me(i))return i.hubSuccessUrl?i.credentials?(await ht(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:Rr(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:Rr(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(Tn(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await Tr(e,i.permissionToken,i.deliveryMode==="permission.approve"?"approved":"denied")}else if(An(i)){if(!i.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await nn(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope,authType:i.authType,providerData:i.providerData})}else{if(!Pt(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await kn(e,{code:i.code,state:i.state,redirectUri:i.redirectUri,trusted:!0,plugin:i.plugin,tenantId:i.tenantId})}}catch(a){let u=a instanceof Error?a.message:"Hub delivery failed";return Pn(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Le({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:vt(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Le({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:Me(i)&&i.hubSuccessUrl?{type:"redirect",url:Rr(i.hubSuccessUrl,{error:u})}:Me(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Le({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:i.hubSuccessUrl}}async function Sr(e,n){let t=F(e),r=await xn(e,n,{signingSecret:t.signingSecret,allowWorkflowExecution:t.allowWorkflowExecution});if(r.status!=="ok")return{type:"json",status:r.retryable===!1?400:502,body:{error:r.error??"Tunnel processing failed"}};let o=r.webhookResponse;if(!o)return{type:"json",status:200,body:{status:"ok"}};let i=o.status??200,s=o.headers;return o.body&&typeof o.body=="object"&&!(o.body instanceof ArrayBuffer)?{type:"json",status:i,body:o.body,headers:s}:{type:"text",status:i,body:typeof o.body=="string"?o.body:o.body?JSON.stringify(o.body):null,headers:s}}function _r(e){if(e.type==="redirect")return Response.redirect(e.url,302);let n=new Headers;for(let[t,r]of Object.entries(e.headers??{}))typeof r=="string"&&n.set(t,r);return e.type==="json"?Response.json(e.body,{status:e.status,headers:n}):new Response(e.body,{status:e.status,headers:n})}async function Er(e,n){return n.method==="GET"?Ir(e,n.url):Sr(e,{headers:n.headers,body:n.body??""})}async function Dr(e,n){try{let t=await Er(e,n);return _r(t)}catch(t){if(t instanceof ue)return Response.json({error:t.message},{status:503});throw t}}async function He(e,n){Fi(e);let t=n.method.toUpperCase(),r=Ui(n.headers.get("origin"));if(t==="OPTIONS")return r?new Response(null,{status:204,headers:r}):Response.json({error:"Method not allowed"},{status:405});if(t!=="GET"&&t!=="POST")return Response.json({error:"Method not allowed"},{status:405});let o=await Dr(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return Bi(o,r)}var H=class extends Error{pluginId;authType;constructor(n,t,r){super(r??`[auth-missing:${n}:${t}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n,this.authType=t}};function tn(e){if(e.forceRefresh||!e.accessToken||!e.expiresAt)return!1;let n=e.now??Math.floor(Date.now()/1e3);return Number(e.expiresAt)>n+300}async function rn(e,n,t){let r=Math.floor(Date.now()/1e3),o=t?Number(t):Number.NaN,i=typeof n.expires_in=="number"?r+n.expires_in:Number.isFinite(o)&&o>r?o:r+3600;return await e.set_access_token(n.access_token),await e.set_expires_at(String(i)),n.refresh_token&&await e.set_refresh_token(n.refresh_token),n.scope&&await e.set_scope(n.scope),i}var Li=new WeakMap;function Rn(e,n,t){let r=Li.get(e);r||(r=new Map,Li.set(e,r));let o=r.get(n);if(o!==void 0)return o;let i=t().finally(()=>{r.delete(n)});return r.set(n,i),i}var Ni=300;async function Or(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,s=n?.forceRefresh??!1,a=`managed:${o}:${i}`;return Rn(t,a,async()=>{let[u,l,c]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!u&&!c)throw new H(o,"managed");let d=Math.floor(Date.now()/1e3);if(!s&&u&&l&&Number(l)>d+Ni)return{accessToken:u,expiresAt:Number(l),refreshed:!1};if(!c&&u&&!s){let f=l?Number(l):null;if(f===null||f>d+Ni)return{accessToken:u,expiresAt:f??d+3600,refreshed:!1}}if(!c)throw new H(o,"managed");let p=await Ku(r,o,i,c),g=await rn(t,p,l);return{accessToken:p.access_token,expiresAt:g,refreshed:!0}})}function ju(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function Ku(e,n,t,r){try{return await x({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t,refresh_token:r},parseResponse:Be})}catch(o){let i=o instanceof Error?o.message:"";throw ju(i)?new H(n,"managed"):o}}async function $i(e,n){e._refreshAuth=async()=>(await Or(n,{forceRefresh:!0})).accessToken}function Wi(e){return{delivery:n=>He(e,n),deliveryOptions:n=>He(e,n)}}var ji=1200*1e3;function Mr(){return ae()}function Hr(){return ji}function Fr(e,n){return dn(e,n,ji)}function Ur(e,n){return te(e,n)}function Br(e){return _e(e)}var Ki=600*1e3;function Lr(){return ae()}function Nr(){return Ki}function $r(e,n){return dn(e,n,Ki)}function Wr(e,n){return te(e,n)}function jr(e){return jt(e)}function Kr(e){return _e(e)}function qr(){return ae()}function Zr(e,n,t){return Bn(e,n,Math.floor(t.getTime()/1e3))}function Gr(e,n){return te(e,n)}function zr(e){return _e(e)}function At(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(o,i){let s=t.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${t.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
|
|
48
|
+
|
|
49
|
+
To generate a KEK, run: openssl rand -base64 ${gn}`)}})}async function qu(e){let n=!1;for(;;){let t=await e.database.db.selectFrom("corsair_integrations").selectAll().where("name","=",e.integrationName).executeTakeFirst();if(!t){if(!n&&e.ensureProvisioned){n=!0,await e.ensureProvisioned();continue}throw new Error(`Integration "${e.integrationName}" not found. Make sure to create the integration first.`)}let r=await e.database.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",e.tenantId).where("integration_id","=",t.id).executeTakeFirst();if(!r){if(!n&&e.ensureProvisioned){n=!0,await e.ensureProvisioned();continue}throw new Error(`Account not found for tenant "${e.tenantId}" and integration "${e.integrationName}". Make sure to create the account first.`)}return{integrationId:t.id,accountId:r.id,integration:{id:t.id,config:t.config,dek:t.dek??null},account:{id:r.id,config:r.config,dek:r.dek??null}}}}async function qi(e){let{integrationId:n,accountId:t}=await qu(e);return{integrationId:n,accountId:t}}function Zi(e,n){let t=()=>{if(!e)throw new Error("corsair.chats requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e};return{create:r=>Ut(t(),{tenantId:n,message:r}),list:()=>Lt(t(),{tenantId:n}),get:r=>({message:o=>Bt(t(),{chatId:r,tenantId:n,message:o}),listMessages:()=>Nt(t(),{chatId:r,tenantId:n})})}}function Jr(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function Zu(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await Yt(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins,multiTenancy:n.multiTenancy})).connectUrl}catch{return null}}async function Gu(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await Yt(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):Jr(e.pluginId,r.connectUrl)}catch{return`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`}let t=await Zu({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return t?Jr(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function zu(e,n,t){let r=Ke(Pe(e,n.tenantId??t??"default"),n.kek),o=new URL(n.baseUrl);o.searchParams.set("state",r);let i=o.toString();return n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:i,state:r}):Jr(e,i)}async function Ju(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&Je(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?zu(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?Gu({manual:e.manual,hub:e.hub,plugin:e.plugin,pluginId:t,tenantId:n,authType:e.error.authType,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy}):e.error.message}async function Gi(e){let n=await Ju(e);throw new H(e.error.pluginId,e.error.authType,n)}var Vu=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function zi(e,n,t,r,o){let i={pluginId:n,operation:t,input:r,originalError:e},s=Object.keys(o).find(l=>o[l]?.match(e,i));return await(o[s||"DEFAULT"]?.handler||Vu)(e,i)}function Yu(e){return typeof e=="function"}function Vr({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:d,tenantId:p,manualConfig:g,hubConfig:f,plugin:h,kek:k,allPlugins:b,multiTenancy:C}){for(let[P,D]of Object.entries(e)){let _=n?.[P];if(Yu(D)){let O=_,w=[...s,P].join("."),T=async(A={})=>{let q=l?.[w];ir(w,q?.riskLevel??"write");let ie;if(u){let Z=q,{result:_n,reason:ee,onComplete:un,token:se,id:Ie,expiresAt:G}=await di({pluginId:o,endpointPath:w,args:A,mode:u.mode,override:u.overrides?.[w],riskLevel:Z?.riskLevel??"write",meta:Z,db:c,timeoutMs:d?sr(d.timeout):void 0,tenantId:p,approvalMode:d?.mode});if(_n==="blocked"){let ne;throw ee==="denied"?ne=`Action '${w}' was denied by the user. Await further instructions before proceeding.`:ee==="policy"?ne=`Action '${w}' is blocked by the permission policy. Update the corsair config to allow it.`:ee==="timeout"?ne=`Action '${w}' timed out waiting for approval.`:se&&Ie?ne=await rr({permissionsOptions:d,manual:g,hub:f,permissionId:Ie,permissionToken:se,plugin:o,endpoint:w,args:A,tenantId:p??"default",expiresAt:G??new Date(Date.now()+(d?sr(d.timeout):600*1e3)).toISOString(),operationPath:w}):ne=`Action '${w}' requires user approval before it can run.`,new Ve(ne)}ie=un}let I=async(Z,_n,ee)=>{try{return await D(_n,ee)}catch(un){if(un instanceof Error){let se=await zi(un,o,w,typeof ee=="object"&&ee!==null?ee:{args:ee},i);if(Z<(se.maxRetries||0)){let Ie=Z+1;console.log(`Retrying (${Ie} / ${se.maxRetries})...`);let G;if(se.headersRetryAfterMs)G=se.headersRetryAfterMs;else switch(se.retryStrategy){case"exponential_backoff":G=Math.pow(2,Ie-1)*1e3;break;case"exponential_backoff_jitter":let ne=Math.pow(2,Ie-1)*1e3,$s=(Math.random()-.5)*1e3;G=Math.max(0,ne+$s);break;case"linear_1s":G=1e3;break;case"linear_2s":G=2e3;break;case"linear_3s":G=3e3;break;case"linear_4s":G=4e3;break;default:G=1e3;break}await new Promise(ne=>setTimeout(ne,G)),await I(Ie,_n,ee),console.log(`[corsair:${o}:${w}] Retry strategy:`,se)}}throw un}},X;try{X=a?await a(t,"endpoint"):void 0}catch(Z){throw Z instanceof H&&(h&&f&&bn({hub:f,database:c,kek:k,plugins:b??[],plugin:h,tenantId:p,verified:!1}),await Gi({error:Z,manual:g,hub:f,plugin:h,tenantId:p,database:c,kek:k,plugins:b,multiTenancy:C})),Z}if(!O?.before&&!O?.after){let Z=await I(0,{...t,key:X},A);return await ie?.(),h&&f&&bn({hub:f,database:c,kek:k,plugins:b??[],plugin:h,tenantId:p,verified:!0}),Z}let an={...t,key:X},Re=O.before?await O.before(an,A):{ctx:an,args:A,continue:!0,passToAfter:void 0};if(Re.continue===!1)return;let go=await I(0,Re.ctx,Re.args);return await O.after?.(Re.ctx,go,Re.passToAfter),await ie?.(),h&&f&&bn({hub:f,database:c,kek:k,plugins:b??[],plugin:h,tenantId:p,verified:!0}),go};r[P]=T}else if(D&&typeof D=="object"){let O={};Vr({endpoints:D,hooks:_,ctx:t,tree:O,pluginId:o,errorHandlers:i,currentPath:[...s,P],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:d,tenantId:p,manualConfig:g,hubConfig:f,plugin:h,kek:k,allPlugins:b,multiTenancy:C}),r[P]=O}}}function Qu(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Yr({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(Qu(s)){let u=a,l=async c=>{let d=(g,f)=>s.handler(g,f),p=o&&c?.hubVerified!==!0?await o(t,"webhook"):void 0;return!u?.before&&!u?.after?d({...t,key:p},c):(async()=>{let g={...t,key:p},f=u.before?await u.before(g,c):{ctx:g,args:c,continue:!0,passToAfter:void 0};if(f.continue===!1)return;let h=await d(f.ctx,f.args);return h?.success===!0&&await u.after?.(f.ctx,h,f.passToAfter),h})()};r[i]={match:s.match,handler:l}}else if(s&&typeof s=="object"){let u={};Yr({webhooks:s,hooks:a,ctx:t,webhooksTree:u,keyBuilder:o}),r[i]=u}}}function Ji(e){return e&&typeof e=="object"?e:{}}async function Vi(e,n){return N({hub:e,path:`/workflows?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Ji(t).workflows;return Array.isArray(r)?r:[]}})}async function Yi(e,n){return N({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>Ji(t).workflow})}async function Qi(e,n){await x({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/status?tenantId=${encodeURIComponent(n.tenantId)}`,body:{status:n.status},notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>t})}async function Xi(e,n){await x({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/rename?tenantId=${encodeURIComponent(n.tenantId)}`,body:{name:n.name},notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>t})}async function es(e,n){return x({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/run?tenantId=${encodeURIComponent(n.tenantId)}`,body:{payload:n.payload,idempotencyKey:n.idempotencyKey},notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>t})}function Qr(e){return e&&typeof e=="object"?e:{}}async function ns(e,n){return N({hub:e,path:`/runs?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Qr(t).runs;return Array.isArray(r)?r:[]}})}async function ts(e,n){return N({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/runs?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>{let r=Qr(t).runs;return Array.isArray(r)?r:[]}})}async function rs(e,n){return N({hub:e,path:`/runs/${encodeURIComponent(n.runId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Run "${n.runId}" not found`,parseResponse:t=>Qr(t).run})}async function Xr(e,n,t){await x({hub:e,path:`/runs/${encodeURIComponent(t.runId)}/${n}?tenantId=${encodeURIComponent(t.tenantId)}`,body:{},notFoundMessage:`Run "${t.runId}" cannot be ${n==="cancel"?"canceled":`${n}d`} in its current state`,parseResponse:r=>r})}var os=(e,n)=>Xr(e,"approve",n),is=(e,n)=>Xr(e,"deny",n),ss=(e,n)=>Xr(e,"cancel",n);function as(e,n){let t=()=>{if(!e)throw new Error("corsair.workflows.runs requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e};return{list:r=>r?.workflowId?ts(t(),{workflowId:r.workflowId,tenantId:n}):ns(t(),{tenantId:n}),get:r=>rs(t(),{runId:r,tenantId:n}),approve:r=>os(t(),{runId:r,tenantId:n}),deny:r=>is(t(),{runId:r,tenantId:n}),cancel:r=>ss(t(),{runId:r,tenantId:n})}}function us(e,n){let t=()=>{if(!e)throw new Error("corsair.workflows requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o,i)=>Qi(t(),{workflowId:o,tenantId:n,status:i});return{list:()=>Vi(t(),{tenantId:n}),get:o=>Yi(t(),{workflowId:o,tenantId:n}),run:(o,i)=>es(t(),{workflowId:o,tenantId:n,payload:i?.payload,idempotencyKey:i?.idempotencyKey}),runs:as(e,n),disable:o=>r(o,"inactive"),enable:o=>r(o,"active"),archive:o=>r(o,"archived"),unarchive:o=>r(o,"inactive"),rename:(o,i)=>Xi(t(),{workflowId:o,tenantId:n,name:i})}}function Xu(e,n,t,r){let o=null;return async()=>{if(o)return o;if(!e)throw new Error("Database not configured");let{accountId:i}=await qi({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function ec(e,n,t,r,o){return e?Ot(e.db,n,t,r,o):{findByEntityId:async()=>null,existsByEntityId:async()=>!1,findIdByEntityId:async()=>null,findById:async()=>null,findManyByEntityIds:async()=>[],list:async()=>[],search:async()=>[],upsertByEntityId:async()=>{throw new Error("Database not configured")},deleteById:async()=>!1,deleteByEntityId:async()=>!1,count:async()=>0}}function eo(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:u,internalConfig:l}=n,c=r??"default",d=l&&t?()=>je(l,c):void 0,p={},g={};for(let f of e)p[f.id]={},g[f.id]={};for(let f of e){let h=f.schema,k=Xu(t,f.id,c,d);if(h?.entities){let I={};for(let[X,an]of Object.entries(h.entities)){let Re=t?Ot(t.db,k,X,h.version,an):ec(void 0,k,X,h.version,an);I[X]=Re}g[f.id].db=I,p[f.id].db=I}let b=f.options,C=f.authConfig,P;if(t&&o&&b?.authType){let I=C?.[b.authType]?.account??[];P=M({authType:b.authType,integrationName:f.id,tenantId:c,kek:o,database:t,extraAccountFields:I,ensureProvisioned:d}),p[f.id].keys=P}let D={database:t,db:g[f.id]?.db??{},$getAccountId:k,...f.options?{options:f.options}:{},...P?{keys:P,authType:b?.authType}:{},tenantId:c,...u?{hub:u}:{}},_=f.endpoints??{},O=f.hooks,w={...i,...f.errorHandlers},T={},A=f.options?.permissions;Vr({endpoints:_,hooks:O,ctx:D,tree:T,pluginId:f.id,errorHandlers:w,currentPath:[],keyBuilder:f.keyBuilder,permissionsConfig:A,endpointMeta:f.endpointMeta,database:t,permissionsOptions:s,tenantId:r,manualConfig:a?{...a,oauthConfig:f.oauthConfig,kek:o,tenantId:c}:void 0,hubConfig:u,plugin:f,kek:o,allPlugins:e,multiTenancy:l?.multiTenancy}),Object.keys(T).length>0&&(p[f.id].api=T),D.endpoints=T;let q=f.webhooks??{},ie=f.webhookHooks;if(Object.keys(q).length>0){let I={};Yr({webhooks:q,hooks:ie,ctx:D,webhooksTree:I,keyBuilder:f.keyBuilder}),p[f.id].webhooks=I,f.pluginWebhookMatcher&&(p[f.id].pluginWebhookMatcher=f.pluginWebhookMatcher),f.pluginTenantWebhookMatcher&&(p[f.id].pluginTenantWebhookMatcher=f.pluginTenantWebhookMatcher)}}return p.chats=Zi(u,c),p.workflows=us(u,c),p}function cs(e,n,t){let r={};for(let o of e){let i=o.options,s=o.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],u=U({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:a});r[o.id]=u}}return r}var nc="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function ls(e){let{permissions:n,approval:t}=e;if(n&&t)throw new Error("createCorsair was given both permissions and approval config. Use permissions only \u2014 approval is deprecated.");return t?(console.warn(`[corsair] ${nc}`),t):n}var ds=[{method:"GET",pattern:"/ok",handler:async()=>B(200,rt())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>B(200,await Qe(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>B(201,await st(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>B(200,await it(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>B(200,await Ye(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>B(200,await ot(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>B(200,await at(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>B(200,await ar(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?B(200,await cr(e,t)):B(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>B(200,await ut(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>B(200,await ct(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>B(200,await lt(e,n,t))}];(()=>{let e=new Set;for(let n of ds){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function tc(e,n){let t=e.split("/").filter(Boolean),r=n.split("/").filter(Boolean);if(t.length!==r.length)return null;let o={};for(let i=0;i<t.length;i++){let s=t[i],a=r[i];if(s.startsWith(":"))o[s.slice(1)]=decodeURIComponent(a);else if(s!==a)return null}return o}function rc(e,n){if(!n)return e;let t=n.endsWith("/")?n.slice(0,-1):n;return e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length):e}async function oc(e){if(!(e.method==="GET"||e.method==="HEAD"||!(e.headers.get("content-type")??"").includes("application/json")))try{let t=await e.text();return t?JSON.parse(t):void 0}catch{throw new E(400,"invalid_json","Request body is not valid JSON")}}var ic="/api/corsair";function Fe(e,n={}){let t=n.basePath??ic,r=v(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),s=rc(i.pathname,t),a=o.method.toUpperCase();if(a==="OPTIONS"||s==="/"||s==="")return await He(e,o);if(a!=="GET"&&a!=="POST")return B(405,{error:"method_not_allowed",message:`Method ${a} not allowed`});let u=Object.fromEntries(i.searchParams);for(let l of ds){if(l.method!==a)continue;let c=tc(l.pattern,s);if(!c)continue;let d=await oc(o);return await l.handler({corsair:e,internal:r,req:o,params:c,query:u,body:d})}throw Te(`No route for ${a} ${s}`)}catch(i){if(n.onError){let a=await n.onError(i,o);if(a)return a}if(i instanceof E)return pi(i);let s=i instanceof Error?i.message:"Internal server error";return B(500,{error:"internal_error",message:s})}}}function sc(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,o=`${t}://${n}${r}`,i=new Headers;for(let[u,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let c of l)i.append(u,c);else i.set(u,l);let s=e.method!=="GET"&&e.method!=="HEAD",a={method:e.method,headers:i};return s&&e.body!==void 0&&(a.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),i.has("content-type")||i.set("content-type","application/json")),new Request(o,a)}async function ac(e,n){e.status(n.status),n.headers.forEach((r,o)=>e.setHeader(o,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function ps(e,n){let t=Fe(e,n);return async(r,o,i)=>{try{let s=await t(sc(r));await ac(o,s)}catch(s){i(s)}}}function gs(e,n){let t=Fe(e,n);return r=>t(r.req.raw)}function fs(e,n){let t=Fe(e,n);return{GET:t,POST:t,OPTIONS:t}}function ys(e){let n={[In]:e};return{ok:rt,tenants:{list:()=>Qe(e),create:t=>st(e,t),get:t=>it(e,t)},plugins:{list:()=>Ye(e),get:t=>ot(e,t)},connectionStatus:{get:t=>at(e,t?.tenantId)},permissions:{get:t=>bi(e,t)},connect:{createLink:t=>ut(n,e,t),resolve:t=>ct(n,e,t),oauthCallback:t=>lt(n,e,t)}}}async function ms(e,n,t,r,o="pending"){if(!e)return null;try{let i=ko(),s=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:s,updated_at:s,account_id:n,event_type:t,payload:r,status:o}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function uc(e,n,t,r="pending"){try{let o=await e.$getAccountId();return ms(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as bs from"https";import*as xt from"querystring";var cc=["expires_in","refresh_token_expires_in"];function hs(e){let n={...e};for(let t of cc){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function lc(e){try{return hs(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=xt.parse(e);return!n.access_token&&!n.error?null:hs({...n})}function zn(e,n,t,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,u)=>{let l={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let c=xt.stringify(l),d={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json","Content-Length":Buffer.byteLength(c).toString()};s&&(d.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let p=bs.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:d},g=>{let f="";g.on("data",h=>{f+=h}),g.on("end",()=>{if(g.statusCode!==200){u(new Error(`Token exchange failed (${g.statusCode}): ${f}`));return}let h=lc(f);h?a(h):u(new Error(`Token endpoint returned non-JSON response: ${f}`))})});p.on("error",g=>u(new Error(`Request failed: ${g.message}`))),p.write(c),p.end()})}async function ks(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,[s,a,u]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(tn({accessToken:s,expiresAt:a,forceRefresh:n?.forceRefresh}))return{accessToken:s,expiresAt:Number(a),refreshed:!1};if(!u)throw new H(o,"oauth_2");let l=await x({hub:r,path:"/oauth/refresh",body:{plugin:o,tenantId:i,refresh_token:u},parseResponse:Be}),c=await rn(t,l,a);return{accessToken:l.access_token,expiresAt:c,refreshed:!0}}async function ws(e){let{tokenUrl:n,refreshToken:t,clientSecret:r,clientId:o,tokenAuthMethod:i="body",bodyFormat:s="form",extraParams:a}=e,u={grant_type:"refresh_token",refresh_token:t,...a},l={Accept:"application/json"};i==="basic"?l.Authorization=`Basic ${Buffer.from(`${o??""}:${r}`).toString("base64")}`:i==="basic_secret_only"?l.Authorization=`Basic ${Buffer.from(`${r}:`).toString("base64")}`:(o&&(u.client_id=o),u.client_secret=r),s==="json"?l["Content-Type"]="application/json":l["Content-Type"]="application/x-www-form-urlencoded";let c=await fetch(n,{method:"POST",headers:l,body:s==="json"?JSON.stringify(u):new URLSearchParams(u)});if(!c.ok)throw new Error(`OAuth token refresh failed (${c.status}): ${await c.text()}`);let d=JSON.parse(await c.text());if(typeof d.access_token!="string"||d.access_token.length===0)throw new Error("OAuth token refresh returned no access_token");return{access_token:d.access_token,...typeof d.refresh_token=="string"&&d.refresh_token.length>0?{refresh_token:d.refresh_token}:{},...typeof d.expires_in=="number"?{expires_in:d.expires_in}:{},...typeof d.scope=="string"&&d.scope.length>0?{scope:d.scope}:{}}}async function Cs(e,n){let t=await e.keys.get_integration_credentials(),r=`${n.plugin}:${e.tenantId}`;if(!t.client_secret){if(!e.hub)throw new H(n.plugin,"oauth_2");let l={keys:e.keys,hub:e.hub,plugin:n.plugin,tenantId:e.tenantId},c=g=>Rn(e.keys,r,async()=>(await ks(l,{forceRefresh:g})).accessToken);e._refreshAuth=()=>c(!0);let[d,p]=await Promise.all([e.keys.get_access_token(),e.keys.get_expires_at()]);return tn({accessToken:d,expiresAt:p})?d:c(!1)}let o=t.client_secret,i=t.client_id,s=l=>Rn(e.keys,r,async()=>{let[c,d,p]=await Promise.all([e.keys.get_access_token(),e.keys.get_expires_at(),e.keys.get_refresh_token()]);if(!l&&tn({accessToken:c,expiresAt:d}))return c;if(!p)throw new H(n.plugin,"oauth_2");let g=await ws({tokenUrl:n.tokenUrl,tokenAuthMethod:n.tokenAuthMethod,bodyFormat:n.bodyFormat,extraParams:n.extraParams,clientId:i,clientSecret:o,refreshToken:p});return await rn(e.keys,g,d),g.access_token});e._refreshAuth=()=>s(!0);let[a,u]=await Promise.all([e.keys.get_access_token(),e.keys.get_expires_at()]);return tn({accessToken:a,expiresAt:u})?a:s(!1)}var vs=" ";function Y(e){let n=e;return n._def??n.def??{}}function Q(e){let n=e.typeName;if(n)return n;let t=e.type;if(t)return`Zod${t.split("_").map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("")}`}function V(e){return e.innerType??e.schema??e.out??e.in}function Ts(e,n){switch(n){case"ZodPipe":return e.in??e.innerType;case"ZodEffects":return e.schema??e.innerType;case"ZodTransform":return e.schema??e.innerType??e.in;default:return V(e)}}function As(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function It(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function on(e){return Array.isArray(e.options)?e.options:Array.isArray(e.values)?e.values:e.entries!==null&&typeof e.entries=="object"&&!Array.isArray(e.entries)?Object.values(e.entries):[]}function xs(e,n){return e.description??n.description}function dc(e){let n=e;for(;n;){let t=Y(n),r=xs(n,t);if(r)return r;let o=Q(t);if(io(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=Ts(t,o);continue}break}}function io(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function j(e){let n=Y(e),t=Q(n);switch(t){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"Date";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(n.value??on(n)[0]??"unknown");case"ZodEnum":return on(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=V(n);return r?j(r):"unknown"}case"ZodNullable":{let r=V(n);return`${r?j(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=V(n);return r?j(r):"unknown"}case"ZodArray":{let r=As(n);if(!r)return"unknown[]";let o=Y(r),i=Q(o)==="ZodUnion",s=j(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=It(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let u=Q(Y(a));return`${u==="ZodOptional"||u==="ZodNullable"?s+"?":s}: ${j(a)}`}).join(", ")} }`}case"ZodUnion":return on(n).map(r=>j(r)).join(" | ");case"ZodIntersection":return`${j(n.left)} & ${j(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=Ts(n,t);return r?j(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ye(e){let n=Y(e),t=Q(n),r=xs(e,n);switch(t){case"ZodString":return{kind:"string",optional:!1,description:r};case"ZodNumber":return{kind:"number",optional:!1,description:r};case"ZodBoolean":return{kind:"boolean",optional:!1,description:r};case"ZodLiteral":{let o=n.value??on(n)[0],i=typeof o=="string"||typeof o=="number"||typeof o=="boolean"?o:String(o??"");return{kind:"literal",optional:!1,description:r,value:i}}case"ZodEnum":{let o=on(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=V(n),i=o?ye(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=V(n),i=o?ye(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=V(n);return o?{...ye(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=As(n);return{kind:"array",optional:!1,description:r,items:o?ye(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=It(e,n),i={};for(let[s,a]of Object.entries(o))i[s]=ye(a);return{kind:"object",optional:!1,description:r,fields:i}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let o=on(n);for(let i of o){let s=Y(i);if(Q(s)==="ZodObject")return{...ye(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=V(n);return o?{...ye(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Mb(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let o=t.slice(0,r),i=t.slice(r+1),s=e.find(c=>c.id===o);if(!s)return null;let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=xe(s.endpointMeta,a),l=xe(s.endpointSchemas,a);return!u&&!l?null:{input:l?.input?ye(l.input):null,output:l?.output?ye(l.output):null,description:u?.description}}var so=["equals","contains","startsWith","endsWith","in"],pc=["equals","gt","gte","lt","lte","in"],gc=["equals"],fc=["equals","before","after","between"];function Rs(e){let n=Y(e);switch(Q(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=V(n);return r?Rs(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function ao(e){let n=Y(e),t=Q(n);if(io(t)){let i=V(n);return i?ao(i):{}}if(t!=="ZodObject")return{};let r=It(e,n),o={};for(let[i,s]of Object.entries(r)){let a=Rs(s);a==="string"?o[i]={type:"string",operators:so}:a==="number"?o[i]={type:"number",operators:pc}:a==="boolean"?o[i]={type:"boolean",operators:gc}:a==="date"&&(o[i]={type:"date",operators:fc})}return o}function Is(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function to(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];typeof o=="function"?t.push(i.join(".")):o!==null&&typeof o=="object"&&to(o,i,t)}}function ro(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function oo(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];ro(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&oo(o,i,t)}}function uo(e,n){if(n.length===0)return null;let[t,...r]=n,o=Object.entries(e).find(([a])=>a.toLowerCase()===t);if(!o)return null;let[i,s]=o;if(r.length===0)return ro(s)?[i]:null;if(s!==null&&typeof s=="object"&&!ro(s)){let a=uo(s,r);if(a!==null)return[i,...a]}return null}function Ss(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let i=0;i<n.length;i++){let s=" ".repeat(i+2);t.push(`${s}${n[i]}: {`)}let r=" ".repeat(n.length+2),o=r+" ";t.push(`${r}before(ctx, args) {`),t.push(`${o}return { ctx, args };`),t.push(`${r}},`),t.push(`${r}after(ctx, response) {`),t.push(`${r}},`);for(let i=n.length-1;i>=0;i--){let s=" ".repeat(i+2);t.push(`${s}},`)}return t.push(" },"),t.push("})"),t.join(`
|
|
50
|
+
`)}var yc=new Set(Dn);function Ue(e,n){let t=n?.type??"api",r=n?.plugin;if(r!==void 0){let i=e.find(a=>a.id===r);if(!i)return yc.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:Ue(e);if(t==="webhooks"){if(!i.webhooks)return[];let a=[];return oo(i.webhooks,[],a),a.map(u=>`${i.id}.webhooks.${u}`)}if(t==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(u=>`${i.id}.db.${u}.search`):[]}if(!i.endpoints)return[];let s=[];return to(i.endpoints,[],s),s.map(a=>`${i.id}.api.${a}`)}let o={};if(t==="webhooks")for(let i of e){if(!i.webhooks)continue;let s=[];oo(i.webhooks,[],s),o[i.id]=s.map(a=>`${i.id}.webhooks.${a}`)}else if(t==="db")for(let i of e){let s=i.schema?.entities;s&&(o[i.id]=Object.keys(s).map(a=>`${i.id}.db.${a}.search`))}else for(let i of e){if(!i.endpoints)continue;let s=[];to(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function xe(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function mc(e,n){let t=e.toLowerCase(),r=n.toLowerCase();if(!t.startsWith(`${r}.`)){let i=t.slice(n.length+1),s=i.startsWith(".")?i.slice(1):i;return s.startsWith("api.")&&(s=s.slice(4)),{shortPath:s,lookupKey:s}}let o=e.slice(n.length+1);return o.toLowerCase().startsWith("api.")&&(o=o.slice(4)),{shortPath:o,lookupKey:o.toLowerCase()}}function no(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
|
|
51
|
+
${e.join(", ")}`:`${n}:
|
|
52
|
+
`+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
|
|
53
|
+
`)}function Hb(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let o=t.slice(0,r),i=t.slice(r+1),s=e.find(a=>a.id===o);if(s){if(i.startsWith("db.")){let c=i.slice(3),d=c.lastIndexOf(".");if(d!==-1){let p=c.slice(0,d),g=c.slice(d+1),f=s.schema?.entities;if(g==="search"&&f){let h=Is(f,p);if(h){let[k,b]=h,C=ao(b),P=[`Search ${o} ${k} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${so.join(", ")}]`];for(let[D,_]of Object.entries(C))P.push(` ${D}?: ${_.type} [${_.operators.join(", ")}]`);return P.push("}"),P.join(`
|
|
54
|
+
`)}}}return no(Ue(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let c=i.slice(9);if(s.webhooks){let d=uo(s.webhooks,c.split("."));if(d!==null){let p=d.join("."),g=xe(s.webhookSchemas,p.toLowerCase()),f=g?.response?j(g.response):null,h=[];return g?.description&&h.push(g.description),g?.payload&&h.push(`payload ${Rt(sn(g.payload))}`),f&&h.push(`response: ${f}`),h.push(`usage:
|
|
55
|
+
${Ss(o,d)}`),h.join(`
|
|
56
|
+
|
|
57
|
+
`)}}return no(Ue(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=xe(s.endpointMeta,a),l=xe(s.endpointSchemas,a);if(u||l){let c=[],d=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),p=[u?.description,d].filter(Boolean).join(" ");return p&&c.push(p),l?.input&&c.push(`input ${Rt(sn(l.input))}`),l?.output&&c.push(`output ${Rt(sn(l.output))}`),c.join(`
|
|
58
|
+
|
|
59
|
+
`)}}}return no(Ue(e),"Path not found. Available operations")}function Ps(e){let n=e;for(;;){let t=Y(n),r=Q(t);if(io(r)){let o=V(t);if(!o)return n;n=o;continue}return n}}function sn(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=Ps(e),t=Y(n);if(Q(t)==="ZodObject"){let o=It(n,t),i=[];for(let[s,a]of Object.entries(o)){let u=Y(a),l=Q(u),c=l==="ZodOptional"||l==="ZodNullable",d=Ps(a),p=dc(a);i.push({key:s,optional:c,type:j(d),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:j(n)}}function Rt(e,n=0){if(e===void 0)return"{}";if(e.kind==="inline")return e.type;if(e.kind==="object"){if(e.fields.length===0)return"{}";let t=vs.repeat(n+1),r=vs.repeat(n);return`{
|
|
60
|
+
${e.fields.map(i=>{let s=i.optional?`${i.key}?`:i.key,a=i.description?` // ${i.description}`:"";return`${t}${s}: ${i.type}${a}`}).join(`
|
|
61
|
+
`)}
|
|
62
|
+
${r}}`}return"unknown"}function hc(e,n){let t=Ue(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(c=>c.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let c of t){let{shortPath:d,lookupKey:p}=mc(c,n),g=xe(r.endpointMeta,p),f=xe(r.endpointSchemas,p);!g&&!f||o.push({path:c,shortPath:d,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:sn(f?.input),output:sn(f?.output)})}o.sort((c,d)=>c.path.localeCompare(d.path));let i=[],s=Ue(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let c of s){let p=c.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),h=uo(r.webhooks,f.split("."));if(h===null)continue;let k=h.join("."),b=xe(r.webhookSchemas,k.toLowerCase()),C=b?.response?j(b.response):void 0;i.push({path:c,description:b?.description,payload:sn(b?.payload),responseType:C,usageExample:Ss(n,h)})}i.sort((c,d)=>c.path.localeCompare(d.path));let a=[],u=Ue(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(u)&&l)for(let c of u){let p=c.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("db."))continue;let f=g.slice(3),h=f.lastIndexOf(".");if(h===-1)continue;let k=f.slice(0,h);if(f.slice(h+1)!=="search")continue;let C=Is(l,k);if(!C)continue;let[P,D]=C,_=ao(D),O=Object.entries(_).map(([w,T])=>({field:w,type:T.type,operators:T.operators}));a.push({path:c,entityName:P,filters:[{field:"entity_id",type:"string",operators:so},...O]})}return a.sort((c,d)=>c.path.localeCompare(d.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as _s}from"crypto";async function bc(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=_s(),o=_s(),i=await fetch(n.watchUrl,{method:"POST",signal:AbortSignal.timeout(2e4),headers:{authorization:`Bearer ${t}`,"content-type":"application/json"},body:JSON.stringify({id:r,type:"web_hook",address:n.webhookUrl,token:o,...n.body})});if(!i.ok)throw new Error(`Google channel watch failed (${i.status}): ${await i.text()}`);return{webhookLink:{linkType:"channel_id",externalId:r},webhookSecret:o}}import{randomUUID as kc}from"crypto";var St="https://graph.microsoft.com/v1.0",co=2e4,wc=60;async function Cc(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let u=await fetch(`${St}/subscriptions`,{headers:r,signal:AbortSignal.timeout(co)});if(u.ok){let{value:l}=await u.json(),c=(l??[]).filter(d=>d.notificationUrl===n.webhookUrl);await Promise.all(c.map(d=>fetch(`${St}/subscriptions/${d.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(co)}).catch(()=>{})))}}catch{}let o=kc(),i=new Date(Date.now()+wc*6e4).toISOString(),s=await fetch(`${St}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(co),body:JSON.stringify({changeType:n.changeType,notificationUrl:n.webhookUrl,resource:n.resource,expirationDateTime:i,clientState:o})});if(!s.ok)throw new Error(`MS Graph subscribe failed (${s.status}): ${await s.text()}`);let a=await s.json();return a.id?(await e.keys.set_webhook_signature(o),{webhookLink:{linkType:"subscription_id",externalId:a.id},webhookSecret:o}):null}function Es(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function vc(e,n){let t=Es(e,n);if(!t)return null;let r=e[t];if(!r?.pluginTenantWebhookMatcher)return null;let o=r.pluginTenantWebhookMatcher(n);return o?{plugin:t,tenantMatch:o}:null}function Pc(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function Ds(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Os(e){if(typeof e=="string"){let n=e.trim();return n.length>0?n:void 0}if(typeof e=="number"&&Number.isFinite(e))return String(e)}function Sn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function Tc(e){return Sn(e.body)}function Ms(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return _t(Array.isArray(r)?r:[r])}function Hs(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let l=_t(Array.isArray(u)?u:[u]);if(l)return decodeURIComponent(l)}let r=Ms({query:e.query},"validationToken");if(r)return r;let o=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let u of o){let l=n[u],c=Array.isArray(l)?l[0]:l;if(!(!c||typeof c!="string"))try{let p=(c.startsWith("http")?new URL(c):new URL(`https://example.invalid${c.startsWith("/")?c:`/${c}`}`)).searchParams.get("validationToken");if(p?.trim())return p.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=Sn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return _t([s?.validationToken])??null}function Ac(e){if(Hs(e))return!0;let n=Sn(e.body??e.payload);return Ds(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function _t(e){for(let n of e){let t=Os(n);if(t)return t}}function xc(e){let t=Sn(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var In=Symbol.for("corsair:internal");function Bs(e){let n=e.database?fo(e.database):void 0,t=n&&e.kek?cs(e.plugins,n,e.kek):At(!!n,!!e.kek),r=ls(e),o={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?Ln(e.hub):void 0},i=li(n),s=ys(o);if(e.multiTenancy){let l=Object.assign({withTenant:c=>{if(!c)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let d=eo(e.plugins,{database:n,tenantId:c,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o});return Object.assign(d,{[In]:o})},keys:t,permissions:i,manage:s},{[In]:o});return Fs(l,o.hub),Us(l,o.hub),l}let a=eo(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o}),u=Object.assign({},a,{keys:t,permissions:i,manage:s,[In]:o});return Fs(u,o.hub),Us(u,o.hub),u}function Fs(e,n){n?.projectApiKey?.startsWith("ck_dev_")&&import("./loop-EV4V7YYV.js").then(t=>t.startConnectLoop(e)).catch(()=>{})}function Rc(e){return e?.projectApiKey?.startsWith("ck_dev_")?e.tunnel!==!1&&process.env.CORSAIR_TUNNEL!=="0":!1}var Et=globalThis.__corsairTunnels??=new Set;function Us(e,n){if(!Rc(n))return;let t=n.projectApiKey;if(Et.has(t))return;let r=Number(process.env.PORT);if(!Number.isInteger(r)||r<1||r>65535){console.error("[corsair] PORT is not set \u2014 dev tunnel skipped. Set PORT to your app port, or run `corsair http <port>`.");return}Et.add(t);let o=typeof n.tunnel=="object"?n.tunnel:{},i=process.env.CORSAIR_FRP_HOST??o.shareHost??Mt;import("./hub/tunnel/run-tunnel.js").then(s=>s.runTunnel({port:r,apiUrl:n.apiUrl,apiKey:t,shareHost:i,onClose:()=>Et.delete(t)})).then(({url:s})=>{console.log(`[corsair] tunnel active: ${s}${Ht}`)}).catch(s=>{Et.delete(t),console.warn(`[corsair] tunnel failed to start: ${s instanceof Error?s.message:String(s)}. Run \`corsair setup\` to enable your dev tunnel.`)})}var Ic={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},repositories:{list:{}}},discord:{guilds:{list:{}},channels:{list:{}}},hubspot:{contacts:{getMany:{}},companies:{getMany:{}},deals:{getMany:{}}},gmail:{messages:{list:{}},labels:{list:{}},drafts:{list:{}},threads:{list:{}}},googlecalendar:{events:{getMany:{}}},googlemeet:{conferenceRecords:{list:{}}},googledrive:{files:{list:{}},folders:{list:{}},sharedDrives:{list:{}}},notion:{databases:{getManyDatabases:{}},databasePages:{getManyDatabasePages:{}},users:{getManyUsers:{}}},airtable:{bases:{getMany:{}}},todoist:{projects:{getMany:{}},tasks:{getMany:{}}},cal:{bookings:{list:{}}},zohomail:{folders:{list:{}},messages:{list:{}}}},lo=Ic;async function Jn(e,n){let t=[],r=n?.silent??!1,o=g=>{t.push(g),r||console.log(g)},i=g=>{t.push(g),r||console.warn(g)},s=n?.caller??"script",a=mo(e);if(!a)throw new Error("setupCorsair: invalid corsair instance");if(!a.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u=Nc(e,a.plugins,n),l={...a,database:a.database},c=l.database.db;await jc(c,i);let d=await Kc(c,l,u.tenantId,u.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await Gc(e,u,n.credentials,l,o,i);let p=await Jc(d,u,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let g=Bs({plugins:a.plugins,database:c,kek:a.kek,multiTenancy:!0}).withTenant(u.tenantId);await Vc(g,a.plugins,p,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
|
|
63
|
+
`)}function po(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...L[n][t],...r])}function Lc(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let o=n.find(a=>a.id===t);if(!o)continue;let i=R(o);if(!i)continue;let s=po(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function Nc(e,n,t){let r=ho(e),o=t?.tenantId?.trim(),i=o!==void 0&&o.length>0;if(r&&t?.backfill&&!i)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(r&&Lc(t?.credentials,n)&&!i)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(i&&!o)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:r,tenantIdProvided:i,tenantId:i?o:"default",provisionAccounts:!r||i}}function Ns(e,n){return he(e)?n===0?!0:Object.values(e).every(t=>Ns(t,n-1)):!1}function $c(e){return Ns(e,4)}var Wc={...wo};function Dt(e){if(e instanceof Mc){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Bc?Dt(r):"unknown";return n}return e instanceof Dc?`${Dt(e.unwrap())} | null`:e instanceof Hc?`${Dt(e.unwrap())} | undefined`:e instanceof Ec?e.options.join(" | "):e instanceof Uc?"string":e instanceof Oc?"number":e instanceof Sc?"boolean":e instanceof _c?"date":e instanceof Fc?"jsonb":"unknown"}async function jc(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(Wc))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
|
|
64
|
+
Schema: ${JSON.stringify(Dt(i),null,2)}`)}async function Kc(e,n,t,r,o){let i=new Date,s=new Map;for(let a of n.plugins){let u=a.id,l=R(a),c=await e.selectFrom("corsair_integrations").selectAll().where("name","=",u).executeTakeFirst();if(!c){let h=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:h,name:u,config:{},created_at:i,updated_at:i}).execute(),c=await e.selectFrom("corsair_integrations").selectAll().where("id","=",h).executeTakeFirst(),o(`[corsair:setup] Created integration: ${u}`)}let d=l?a.authConfig?.[l]?.integration??[]:[],p=l?a.authConfig?.[l]?.account??[]:[],g=l&&c?U({authType:l,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:d}):void 0;if(c&&!c.dek&&g&&(await g.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${u}`)),!c||!l||!g)continue;let f;if(r){let h=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",c.id).executeTakeFirst();if(!h){let k=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:k,tenant_id:t,integration_id:c.id,config:{},created_at:i,updated_at:i}).execute(),h=await e.selectFrom("corsair_accounts").selectAll().where("id","=",k).executeTakeFirst(),o(`[corsair:setup] Created account: ${u}`)}f=h&&M({authType:l,integrationName:u,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:p}),h&&f&&!h.dek&&(await f.issue_new_dek(),o(`[corsair:setup] Issued account DEK: ${u}`))}s.set(u,{pluginId:u,authType:l,integration:g,account:f,integrationFields:[...L[l].integration,...d],accountFields:r?[...L[l].account,...p]:[]})}return s}function qc(e){if(!he(e))return;let n=e.keys;return he(n)?n:void 0}function Zc(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function Gc(e,n,t,r,o,i){let s=qc(e),a=n.provisionAccounts?Zc(e,n.tenantId):void 0;for(let[u,l]of Object.entries(t)){let c=r.plugins.find(b=>b.id===u);if(!c){i(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let d=R(c);if(!d){i(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let p=po(c,d,"integration"),g=po(c,d,"account"),f=s?.[u],h=a?.[u],k=he(h)?h.keys:void 0;for(let[b,C]of Object.entries(l))if(C){if(p.has(b)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${u}.${b}' is an integration-level credential shared across all tenants. You passed tenantId="${n.tenantId}", which only scopes account-level credentials. Run setup without --tenant if you intend to change this credential globally.`);let P=K(f,`set_${b}`);if(!P){i(`[corsair:setup] Cannot set integration field '${b}' for '${u}'.`);continue}await P(C),o(`[corsair:setup] Set ${u} integration.${b}`);continue}if(g.has(b)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${u}.${b}' on a multi-tenant instance`);let P=K(k,`set_${b}`);if(!P){i(`[corsair:setup] Cannot set account field '${b}' for '${u}'.`);continue}await P(C),o(`[corsair:setup] Set ${u} account.${b} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${b}' for plugin '${u}'.`)}}}var Ls=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function zc(e,n,t,r,o,i,s,a,u){let l=[],c=[];for(let p of o){if(Ls.has(p))continue;let g=K(t,`get_${p}`);if(!g)continue;let f=null;try{let h=await g();f=typeof h=="string"?h:null}catch{}f||l.push(p)}if(r&&i.length>0)for(let p of i){if(Ls.has(p))continue;let g=K(r,`get_${p}`);if(!g)continue;let f=null;try{let h=await g();f=typeof h=="string"?h:null}catch{}f||c.push(p)}let d=l.length===0&&c.length===0;if(d)a(`[corsair:setup] '${e}' (${n}) is configured \u2713`);else if(n==="managed")a(`[corsair:setup] '${e}' (managed) is not connected yet. Use Connect in your app \u2014 Corsair Hub delivers OAuth tokens after authorization.`);else{let p=[...l,...c];if(u==="cli"){let g=p.map(f=>`${f}=VALUE`).join(" ");a(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
|
|
65
|
+
corsair setup --${e} ${g}`)}else{let g=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let f of l)g.push(` await corsair.keys.${e}.set_${f}(value)`);for(let f of c){let h=s.provisionAccounts?s.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(s.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;g.push(` await ${h}.keys.set_${f}(value)`)}a(g.join(`
|
|
66
|
+
`))}}return d}async function Jc(e,n,t,r){let o=new Set;for(let i of e.values())await zc(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function Vc(e,n,t,r,o){if(!$c(lo)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=lo,s=new Set(n.map(a=>a.id));for(let[a,u]of Object.entries(i)){if(!s.has(a))continue;if(!t.has(a)){r(`[corsair:setup] Skipping backfill for '${a}' \u2014 auth not configured.`);continue}let l=he(e)?e[a]:void 0,c=he(l)?l.api:void 0;if(c)for(let[d,p]of Object.entries(u))for(let[g,f]of Object.entries(p)){r(`[corsair:setup] Backfilling ${a} \u203A ${d}.${g}...`);try{let h=he(c)?c[d]:void 0;await K(h,g)?.(f)}catch(h){o(`[corsair:setup] ${a} \u203A ${d}.${g} failed: `+(h instanceof Error?h.message:String(h)))}}}}export{vo as a,be as b,On as c,Mn as d,Hn as e,Be as f,Po as g,Fn as h,Wt as i,cn as j,So as k,_o as l,ke as m,Se as n,ae as o,Ne as p,$e as q,we as r,Kt as s,Do as t,pn as u,ue as v,Ln as w,F as x,Nn as y,We as z,ce as A,le as B,z as C,qt as D,fn as E,Ce as F,de as G,yn as H,U as I,M as J,Lo as K,No as L,Jn as M,Gc as N,Pe as O,Gt as P,qe as Q,Ze as R,Jt as S,Gn as T,Vo as U,De as V,W,Vt as X,kn as Y,ei as Z,Ta as _,Vn as $,ap as aa,ri as ba,oi as ca,ii as da,Yt as ea,Yn as fa,Qt as ga,Xn as ha,et as ia,Ve as ja,tt as ka,or as la,ci as ma,ir as na,dr as oa,pr as pa,dt as qa,gr as ra,Xe as sa,en as ta,pt as ua,gt as va,wn as wa,fr as xa,yr as ya,ft as za,Cn as Aa,yt as Ba,mt as Ca,Ae as Da,nn as Ea,Ti as Fa,wr as Ga,Cr as Ha,Me as Ia,Tn as Ja,An as Ka,Pt as La,Tr as Ma,xn as Na,_u as Oa,Hu as Pa,Bu as Qa,Mi as Ra,Hi as Sa,Ir as Ta,Sr as Ua,_r as Va,Er as Wa,Dr as Xa,He as Ya,H as Za,Or as _a,$i as $a,Wi as ab,Mr as bb,Hr as cb,Fr as db,Ur as eb,Br as fb,Lr as gb,Nr as hb,$r as ib,Wr as jb,jr as kb,Kr as lb,qr as mb,Zr as nb,Gr as ob,zr as pb,Fe as qb,ps as rb,gs as sb,fs as tb,ms as ub,uc as vb,zn as wb,Cs as xb,Mb as yb,Ue as zb,Hb as Ab,Rt as Bb,hc as Cb,bc as Db,St as Eb,Cc as Fb,Es as Gb,vc as Hb,Pc as Ib,Ds as Jb,Os as Kb,Sn as Lb,Tc as Mb,Ms as Nb,Hs as Ob,Ac as Pb,_t as Qb,xc as Rb,In as Sb,Bs as Tb,Rc as Ub};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-
|
|
2
|
-
export { f as PermissionLookupInput } from '../../types-
|
|
3
|
-
import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-
|
|
1
|
+
import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-D-yPWPrk.js';
|
|
2
|
+
export { f as PermissionLookupInput } from '../../types-D-yPWPrk.js';
|
|
3
|
+
import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-BMqVYze1.js';
|
|
4
4
|
import '../../index-eydqYIn0.js';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{da as a,ea as b,fa as c}from"./chunk-
|
|
1
|
+
import{da as a,ea as b,fa as c}from"./chunk-A7MHZJ3T.js";import"./chunk-3TC2WIUS.js";import"./chunk-VOH7OVWP.js";import"./chunk-F2EV3CHK.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{c as createHubConnectSession,b as createHubConnectSessionForPlugin,a as postHubConnectSession};
|
package/dist/core.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair, s as shouldStartTunnel } from './index-
|
|
1
|
+
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair, s as shouldStartTunnel } from './index-Dzgq6g_o.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
|
-
import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor,
|
|
4
|
-
export {
|
|
5
|
-
export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, g as PermissionRequiredError, P as PluginDocsIntrospection, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, o as extractMicrosoftGraphValidationToken, p as firstString, f as formatDocSchemaShape, q as getHeader, i as introspectPluginForDocs, s as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, u as readQueryParam, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-
|
|
6
|
-
import { A as AuthTypes } from './types-
|
|
7
|
-
export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-
|
|
3
|
+
import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, H as HubConfig, h as CorsairPluginSubscribeResult } from './index-rSDS0vTc.js';
|
|
4
|
+
export { i as AccountFieldNames, o as AgentMessageRole, p as AgentReply, m as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, j as BaseKeyManager, a0 as BeforeHookResult, w as BindEndpoints, am as BindWebhooks, ak as Bivariant, x as BoundEndpointFn, y as BoundEndpointTree, an as BoundWebhook, ao as BoundWebhookTree, q as ChatHandle, r as ChatMessage, s as ChatSummary, t as CorsairChatsNamespace, v as CorsairClient, z as CorsairContext, D as CorsairEndpoint, J as CorsairErrorHandler, c as CorsairIntegration, a1 as CorsairKeyBuilder, a2 as CorsairKeyBuilderBase, ap as CorsairOAuthWebhookTenantLinkResolver, U as CorsairPermissionsNamespace, C as CorsairPlugin, a3 as CorsairPluginContext, a4 as CorsairPluginSubscribe, ag as CorsairRunsNamespace, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, aq as CorsairWebhook, ar as CorsairWebhookHandler, f as CorsairWebhookMatcher, g as CorsairWebhookTenantMatcher, aw as CorsairWorkflowsNamespace, u as CreateChatResult, a5 as EndpointHooks, a6 as EndpointMetaEntry, F as EndpointPathsOf, E as EndpointRiskLevel, G as EndpointTree, V as EnforcePermissionOptions, X as EnforcePermissionResult, K as ErrorContext, L as ErrorHandler, M as ErrorHandlerAndMatchFunction, N as ErrorMatcher, k as IntegrationFieldNames, a7 as KeyBuilderContext, l as OAuth2IntegrationCredentials, O as OAuthConfig, a8 as PermissionMode, a9 as PermissionPolicy, P as PluginAuthConfig, aa as PluginEndpointMeta, ab as PluginPermissionsConfig, R as RawWebhookRequest, _ as ReadonlyForbiddenError, ac as RequiredPluginEndpointMeta, ad as RequiredPluginEndpointSchemas, ae as RequiredPluginWebhookSchemas, Q as RetryStrategies, S as RetryStrategy, T as TokenResponse, ax as TriggerRunResult, al as UnionToIntersection, af as WebhookHooks, as as WebhookPathsOf, at as WebhookRequest, au as WebhookResponse, W as WebhookTenantMatch, av as WebhookTree, ah as WorkflowRun, ai as WorkflowRunStatus, aj as WorkflowRunStep, ay as WorkflowStatus, az as WorkflowSummary, Y as assertReadonlyAllowed, n as exchangeCodeForTokens, Z as isReadonlyScopeActive, $ as runReadonly } from './index-rSDS0vTc.js';
|
|
5
|
+
export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, g as PermissionRequiredError, P as PluginDocsIntrospection, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, o as extractMicrosoftGraphValidationToken, p as firstString, f as formatDocSchemaShape, q as getHeader, i as introspectPluginForDocs, s as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, u as readQueryParam, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-dY__baGV.js';
|
|
6
|
+
import { A as AuthTypes } from './types-D-yPWPrk.js';
|
|
7
|
+
export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-D-yPWPrk.js';
|
|
8
8
|
import 'kysely';
|
|
9
9
|
import './index-eydqYIn0.js';
|
|
10
10
|
import 'zod';
|
|
@@ -154,6 +154,23 @@ declare function initializeIntegrationDEK(database: CorsairDatabase, integration
|
|
|
154
154
|
*/
|
|
155
155
|
declare function initializeAccountDEK(database: CorsairDatabase, integrationName: string, tenantId: string, kek: string): Promise<string>;
|
|
156
156
|
|
|
157
|
+
type OAuthTokenAuthMethod = 'body' | 'basic' | 'basic_secret_only';
|
|
158
|
+
type OAuthBodyFormat = 'form' | 'json';
|
|
159
|
+
|
|
160
|
+
type OAuthAccessContext = {
|
|
161
|
+
keys: AccountKeyManagerFor<'oauth_2'>;
|
|
162
|
+
hub?: HubConfig | null;
|
|
163
|
+
tenantId: string;
|
|
164
|
+
};
|
|
165
|
+
type OAuthAccessOptions = {
|
|
166
|
+
plugin: string;
|
|
167
|
+
tokenUrl: string;
|
|
168
|
+
tokenAuthMethod?: OAuthTokenAuthMethod;
|
|
169
|
+
bodyFormat?: OAuthBodyFormat;
|
|
170
|
+
extraParams?: Record<string, string>;
|
|
171
|
+
};
|
|
172
|
+
declare function getOAuthAccessToken(ctx: OAuthAccessContext, opts: OAuthAccessOptions): Promise<string>;
|
|
173
|
+
|
|
157
174
|
/** Minimal shape we need from the account key manager (ctx.keys). */
|
|
158
175
|
type SubscribeCtx$1 = {
|
|
159
176
|
keys: {
|
|
@@ -199,4 +216,4 @@ declare function msGraphSubscribe(ctx: SubscribeCtx, input: {
|
|
|
199
216
|
changeType: string;
|
|
200
217
|
}): Promise<CorsairPluginSubscribeResult | null>;
|
|
201
218
|
|
|
202
|
-
export { AccountKeyManagerFor, AuthTypes, CorsairPluginSubscribeResult, type EventLoggingContext, IntegrationKeyManagerFor, MS_GRAPH_API_BASE, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, generateDEK, googleChannelSubscribe, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, msGraphSubscribe, reEncryptConfig };
|
|
219
|
+
export { AccountKeyManagerFor, AuthTypes, CorsairPluginSubscribeResult, type EventLoggingContext, IntegrationKeyManagerFor, MS_GRAPH_API_BASE, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, generateDEK, getOAuthAccessToken, googleChannelSubscribe, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, msGraphSubscribe, reEncryptConfig };
|
package/dist/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as d,
|
|
1
|
+
import{A as d,B as e,Bb as A,C as f,Cb as B,D as g,Db as C,E as h,Eb as D,F as i,Fb as E,G as j,Gb as F,H as k,Hb as G,I as l,Ib as H,J as m,Jb as I,K as n,Kb as J,L as o,Lb as K,Mb as L,Nb as M,Ob as N,Pb as O,Qb as P,Rb as Q,Sb as R,Tb as S,Ub as T,Za as v,a,b,ga as p,ja as q,ka as r,la as s,ma as t,na as u,ub as w,vb as x,wb as y,xb as z}from"./chunk-A7MHZJ3T.js";import"./chunk-3TC2WIUS.js";import{h as c}from"./chunk-VOH7OVWP.js";import"./chunk-F2EV3CHK.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{v as AuthMissingError,c as BASE_AUTH_FIELDS,R as CORSAIR_INTERNAL,D as MS_GRAPH_API_BASE,q as PermissionRequiredError,a as ProviderDisplayNames,r as ReadonlyForbiddenError,K as asRecord,u as assertReadonlyAllowed,H as collectPluginWebhookMatchers,m as createAccountKeyManager,S as createCorsair,l as createIntegrationKeyManager,Q as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,y as exchangeCodeForTokens,N as extractMicrosoftGraphValidationToken,P as firstString,A as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,I as getHeader,z as getOAuthAccessToken,C as googleChannelSubscribe,o as initializeAccountDEK,n as initializeIntegrationDEK,B as introspectPluginForDocs,O as isMicrosoftGraphValidationHandshake,t as isReadonlyScopeActive,w as logEvent,x as logEventFromContext,F as matchWebhookPlugin,G as matchWebhookPluginAndTenant,E as msGraphSubscribe,k as reEncryptConfig,L as readBodyRecord,M as readQueryParam,p as resolveConnectLink,s as runReadonly,T as shouldStartTunnel,J as toExternalId};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as x,b as L,c as w,f as O}from"../../chunk-
|
|
1
|
+
import{a as x,b as L,c as w,f as O}from"../../chunk-3TC2WIUS.js";import"../../chunk-SOY77BN4.js";import{spawn as X}from"child_process";import{mkdtempSync as rr,rmSync as er,writeFileSync as G}from"fs";import{tmpdir as tr}from"os";import{join as S}from"path";var Q=/^(?:\/[A-Za-z0-9._~-]+)+$/;function F(r){if(!/^[\x20-\x21\x23-\x7E]+$/.test(r.apiKey))throw new Error("apiKey contains invalid characters (quotes, newlines, or control chars)");if(r.deliveryPath&&!Q.test(r.deliveryPath))throw new Error("deliveryPath must be an absolute URL path (e.g. /api/corsair)");let o=[`serverAddr = "${r.serverAddr}"`,`serverPort = ${r.serverPort}`,"loginFailExit = true",`metadatas.token = "${r.apiKey}"`];return r.deliveryPath&&o.push(`metadatas.path = "${r.deliveryPath}"`),r.caCertPath&&o.push("transport.tls.enable = true",`transport.tls.serverName = "${r.serverName??r.serverAddr}"`,`transport.tls.trustedCaFile = "${r.caCertPath}"`),o.push("","[[proxies]]",`name = "corsair-${r.slug}"`,'type = "http"','localIP = "127.0.0.1"',`localPort = ${r.localPort}`,`subdomain = "${r.slug}"`,""),o.join(`
|
|
2
2
|
`)}import K from"http";var Z=3e4,J=new Set(["host","forwarded","x-real-ip"]);function V(r){return J.has(r)||r.startsWith("x-forwarded-")}function M(r,o=w){let n=K.createServer((e,t)=>{let c=e.url??"/",i;try{i=new URL(c,"http://127.0.0.1")}catch{t.statusCode=400,t.end("Bad request");return}if(/%2f|%5c/i.test(i.pathname)){t.statusCode=400,t.end("Bad request");return}if(!(i.pathname===o||i.pathname.startsWith(`${o}/`))){t.statusCode=404,t.end("Not found");return}let P={host:`127.0.0.1:${r}`};for(let[l,u]of Object.entries(e.headers))u!==void 0&&!V(l)&&(P[l]=u);let a=K.request({host:"127.0.0.1",port:r,method:e.method,path:i.pathname+i.search,headers:P,timeout:Z},l=>{let u={};for(let[y,m]of Object.entries(l.headers))m!==void 0&&y!=="set-cookie"&&(u[y]=m);t.writeHead(l.statusCode??502,u),l.pipe(t)});a.on("timeout",()=>a.destroy()),a.on("error",()=>{if(!t.writableEnded){if(t.headersSent){t.destroy();return}t.statusCode=502,t.end("Bad gateway")}}),e.on("error",()=>a.destroy()),t.on("close",()=>{a.destroyed||a.destroy()}),e.pipe(a)});return new Promise((e,t)=>{n.once("error",t),n.listen(0,"127.0.0.1",()=>{let c=n.address(),i=typeof c=="object"&&c?c.port:0;e({port:i,close:()=>new Promise(E=>{n.close(()=>E())})})})})}var D=15e3,nr=/start proxy success/i,z=/start error/i,j=/^[a-z0-9.-]+$/i;async function or(r){let o=r.apiUrl.replace(/\/$/,""),n=await fetch(`${o}/api/dev/tunnel-config`,{headers:{authorization:`Bearer ${r.apiKey}`},signal:AbortSignal.timeout(D)});if(!n.ok)throw new Error(`Hub tunnel-config failed (HTTP ${n.status})`);let e=await n.json();if(!e.slug||!/^[a-z0-9-]+$/.test(e.slug))throw new Error("Hub tunnel-config returned an invalid slug");if(!e.serverAddr||!j.test(e.serverAddr))throw new Error("Hub tunnel-config returned an invalid server address");if(!Number.isInteger(e.serverPort)||e.serverPort<1||e.serverPort>65535)throw new Error("Hub tunnel-config returned an invalid server port");if(e.serverName!==void 0&&!j.test(e.serverName))throw new Error("Hub tunnel-config returned an invalid serverName");let t=e.caCert??null;if(t&&!t.startsWith("-----BEGIN CERTIFICATE-----"))throw new Error('Hub tunnel-config returned a caCert that does not begin with "-----BEGIN CERTIFICATE-----"');return{serverAddr:e.serverAddr,serverPort:e.serverPort,slug:e.slug,caCert:t,serverName:e.serverName}}async function $r(r){let{port:o,apiUrl:n,apiKey:e,shareHost:t=L,timeoutMs:c=2e4,onClose:i}=r,{serverAddr:E,serverPort:P,slug:a,caCert:l,serverName:u}=await or({apiUrl:n,apiKey:e}),y=O(),m=sr(),$=await M(o,m),b,A;try{b=rr(S(tr(),"corsair-frpc-")),A=S(b,"frpc.toml");let f=l?S(b,"ca.crt"):void 0;f&&l&&G(f,l,{mode:384}),G(A,F({serverAddr:E,serverPort:P,apiKey:e,slug:a,localPort:$.port,caCertPath:f,serverName:u,deliveryPath:m}),{mode:384})}catch(f){throw await $.close(),f}let W=`https://${a}.${t}`;return new Promise((f,Y)=>{let h=!1,N=!1,v="",d=X(y,["-c",A],{stdio:["ignore","pipe","pipe"]}),C=()=>{$.close(),er(b,{recursive:!0,force:!0})},_=!1,H=()=>{d.killed||d.kill(),C()};process.once("exit",H);let R=()=>{_||(_=!0,process.removeListener("exit",H),process.removeListener("SIGINT",T),process.removeListener("SIGTERM",T),d.stdout.removeAllListeners("data"),d.stderr.removeAllListeners("data"),d.killed||d.kill(),C())},T=s=>{R(),process.kill(process.pid,s)};process.once("SIGINT",T),process.once("SIGTERM",T);let g=s=>{h||(h=!0,clearTimeout(I),R(),Y(s))},U=async s=>{if(!N){if(v+=s.toString(),z.test(v)){g(new Error(`frpc rejected the tunnel: ${ir(v)}`));return}if(nr.test(v)){N=!0,clearTimeout(I);try{await lr({apiUrl:n,apiKey:e})}catch(p){g(p instanceof Error?p:new Error(String(p)));return}h||(h=!0,f({url:W,stop:R}))}}};d.stdout.on("data",s=>{U(s)}),d.stderr.on("data",s=>{U(s)}),d.on("error",s=>{g(new Error(`Failed to spawn frpc: ${s.message}`))}),d.on("exit",s=>{if(!h){let p=ar(v),q=p?` \u2014 ${p}`:"";g(new Error(`frpc exited early (code ${s??"null"}) before the tunnel came up${q}`));return}process.removeListener("exit",H),C(),i?.()});let I=setTimeout(()=>{g(new Error(`Timed out after ${c}ms waiting for frpc to establish the tunnel`))},c)})}function sr(){try{let r=new URL(x()).pathname.replace(/\/$/,"");return r&&r!=="/"?r:w}catch{return w}}function ir(r){return(r.split(`
|
|
3
3
|
`).find(n=>z.test(n))??"start error").trim()}function ar(r){return r.split(`
|
|
4
4
|
`).filter(n=>n.trim()!=="").at(-1)?.trim()??""}async function lr(r){let o=r.apiUrl.replace(/\/$/,""),n=await fetch(`${o}/api/dev/register`,{method:"POST",headers:{authorization:`Bearer ${r.apiKey}`},signal:AbortSignal.timeout(D)});if(!n.ok)throw new Error(`Hub tunnel-live ping failed (HTTP ${n.status})`)}export{or as fetchTunnelConfig,lr as pingTunnelLive,$r as runTunnel};
|