corsair 0.1.136 → 0.1.137
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-5Lt0P6ay.d.ts → browser-delivery-CuosfbGl.d.ts} +1 -1
- package/dist/chunk-CDHXC7TY.js +66 -0
- package/dist/chunk-QAK6BJXE.js +1 -0
- package/dist/client/react/index.d.ts +20 -1
- package/dist/client/react/index.js +3 -3
- package/dist/connect-UZW2X4RS.js +1 -0
- package/dist/connect.d.ts +51 -0
- package/dist/connect.js +1 -0
- package/dist/core.d.ts +4 -4
- package/dist/core.js +1 -1
- package/dist/hub.d.ts +5 -5
- package/dist/hub.js +1 -1
- package/dist/{index-CjQxK4YA.d.ts → index-DkasBCao.d.ts} +1 -1
- package/dist/{index-CkaSwl1Q.d.ts → index-IKVoCn09.d.ts} +1 -1
- package/dist/{index-Ba71z8av.d.ts → index-ryBhZJCc.d.ts} +3 -2
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -3
- package/dist/loop-ZYFJTNGJ.js +1 -0
- package/dist/oauth.d.ts +1 -1
- package/dist/oauth.js +1 -1
- package/dist/setup-KMADSAGQ.js +1 -0
- package/dist/setup-introspect-PNESATVT.js +1 -0
- package/dist/setup.d.ts +2 -2
- package/dist/setup.js +1 -1
- package/dist/{tenant-match-utils-B9Xc7dNa.d.ts → tenant-match-utils-DcEjUYmt.d.ts} +8 -7
- package/dist/tunnel.d.ts +4 -4
- package/dist/tunnel.js +1 -1
- package/package.json +9 -4
- package/dist/chunk-IKQU6YIZ.js +0 -66
- package/dist/connect-JKEAFJMP.js +0 -1
- package/dist/loop-SWONOQNY.js +0 -1
- package/dist/setup-G23JJ5MM.js +0 -1
- package/dist/setup-introspect-MRN3CJR3.js +0 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import{a as Ae,b as tr,c as rr}from"./chunk-6IURNA4L.js";import{a as jo,b as er}from"./chunk-QAK6BJXE.js";import{a as Ko,b as xe,c as Zo,d as T,e as K,f as Go,g as Q,h as j,i as S,j as Gn,k as zo,l as Xe,m as nr,n as Jo}from"./chunk-7AYINDN2.js";import{a as qo}from"./chunk-N66TLOH2.js";import{ZodBoolean as fd,ZodDate as yd,ZodEnum as md,ZodNullable as hd,ZodNumber as bd,ZodObject as kd,ZodOptional as wd,ZodRecord as Cd,ZodString as vd,ZodType as Td}from"zod";var zn=["ably","abstract","abuseipdb","abyssale","accrediblecertificates","activecampaign","activetrail","addresszen","aeroleads","affinda","agencyzoom","agentmail","agentql","agenty","agiled","agilitycms","ahrefs","aimlapi","airtable","aivoov","alchemy","algolia","allimagesai","alphavantage","altoviz","alttextai","amara","ambee","ambientweather","amcards","amplitude","anchorbrowser","anonyflow","anthropicadministrator","apaleo","api2pdf","apibible","apify","apilabz","apininjas","apipie","apisports","appointo","asana","ascora","ashby","asindataapi","asticaai","asyncinterview","attio","autom","ayrshare","backendless","bannerbear","bart","basecamp","baselinker","basin","beaconstac","beeminder","benchmarkemail","bestbuy","bettercontact","betterproposals","betterstack","bigdatacloud","bigmailer","bigml","bitbucket","bitwarden","blazemeter","blocknative","bluesky","boldsign","boloforms","boltiot","bonsai","bookingmood","borneo","botbaba","botpress","botsonic","bouncer","box","boxhero","brandfetch","breathehr","brevo","brex","brightdata","browseai","browserless","browsertool","bubble","bugsnag","buildkite","bunnycdn","cal","calendly","campayn","canva","canvas","capsulecrm","castingwords","cdrplatform","certifier","chatbotkit","chatfai","chmeetings","circleci","clickhouse","clientary","clockify","cloudflare","cloudinary","collegefootballdata","confluence","connecteam","contentfulgraphql","contextsevenmcp","convoloai","cosmic","countdownapi","crowterminal","cursor","customgpt","dadataru","databricks","datadog","datarobot","deepseek","devinmcp","diffbot","digitalocean","discord","dockerhub","dodopayments","doppler","dreamstudio","dripcel","dropbox","dropboxsign","dynapictures","emelia","epicgames","exa","exist","facebook","faraday","figma","filloutforms","firecrawl","fireflies","flexisign","formbricks","gemini","github","gitlab","gladia","gmail","googleaddressvalidation","googleanalytics","googlebigquery","googlecalendar","googlecloudvision","googledocs","googledrive","googlemaps","googlemeet","googlesheets","grafana","griptape","groqcloud","habitica","hackernews","harvest","hashnode","here","heygen","htmltoimage","hubspot","huggingface","imgbb","insightoai","instagram","intercom","jigsawstack","jira","kaggle","kibana","linear","linkedin","loyverse","mailboxlayer","mailchimp","mailtrap","marketstack","merriamwebsterdict","monday","neon","nextdns","notion","ocrspace","ocrwebservice","ollama","onedrive","onepassword","openai","openrouter","openweathermap","oura","outlook","pagerduty","parseur","pdfmonkey","perplexityai","pinecone","posthog","razorpay","reddit","removebg","resend","retailed","runpod","salesforce","sapsuccessfactors","scaleai","scrapegraphai","securitytrails","sendgrid","sentry","serpapi","sharepoint","slack","sourcegraph","spotify","strava","streamtime","stripe","studiobyai21labs","supabase","synthflowai","tally","tavily","tavilymcp","teams","telegram","textrazor","ticktick","timecamp","timelink","tinyurl","tisane","todoist","toggl","trello","twentyonerisk","twilio","twitter","twitterapiio","twochat","typeform","unione","uniswapapi","uploadcare","vapi","vercel","veriphone","vestaboard","wakatime","webflow","webvizio","whatsapp","witai","wix","wiza","workday","workiom","worldnewsapi","xquik","youcom","youtube","zendesk","zohoinventory","zohomail","zoom","zoominfo"],Vo={ably:"Ably",abstract:"Abstract",abuseipdb:"AbuseIPDB",abyssale:"Abyssale",accrediblecertificates:"Accredible Certificates",activecampaign:"ActiveCampaign",activetrail:"Active Trail",addresszen:"Addresszen",aeroleads:"Aeroleads",affinda:"Affinda",agencyzoom:"AgencyZoom",agentmail:"AgentMail",agentql:"AgentQL",agenty:"Agenty",agiled:"Agiled",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",anonyflow:"Anonyflow",anthropicadministrator:"Anthropic Administrator",apaleo:"Apaleo",api2pdf:"API2PDF",apibible:"API.Bible",apify:"Apify",apilabz:"API Labz",apininjas:"API Ninjas",apipie:"APIpie AI",apisports:"API-Sports",appointo:"Appointo",asana:"Asana",ascora:"Ascora",ashby:"Ashby",asindataapi:"ASIN Data API",asticaai:"Astica AI",asyncinterview:"Async Interview",attio:"Attio",autom:"Autom",ayrshare:"Ayrshare",backendless:"Backendless",bannerbear:"Bannerbear",bart:"BART",basecamp:"Basecamp",baselinker:"BaseLinker",basin:"Basin",beaconstac:"Beaconstac",beeminder:"Beeminder",benchmarkemail:"BenchmarkEmail",bestbuy:"Best Buy",bettercontact:"BetterContact",betterproposals:"Better Proposals",betterstack:"Better Stack",bigdatacloud:"BigDataCloud",bigmailer:"BigMailer",bigml:"BigML",bitbucket:"Bitbucket",bitwarden:"Bitwarden",blazemeter:"BlazeMeter",blocknative:"Blocknative",bluesky:"Bluesky",boldsign:"Boldsign",boloforms:"Boloforms",boltiot:"Bolt IoT",bonsai:"Bonsai",bookingmood:"Bookingmood",borneo:"Borneo",botbaba:"Botbaba",botpress:"Botpress",botsonic:"Botsonic",bouncer:"Bouncer",box:"Box",boxhero:"BoxHero",brandfetch:"Brandfetch",breathehr:"Breathe HR",brevo:"Brevo",brex:"Brex",brightdata:"Bright Data",browseai:"Browse AI",browserless:"Browserless",browsertool:"Browser Tool",bubble:"Bubble",bugsnag:"BugSnag",buildkite:"Buildkite",bunnycdn:"Bunnycdn",cal:"Cal",calendly:"Calendly",campayn:"Campayn",canva:"Canva",canvas:"Canvas LMS",capsulecrm:"Capsule CRM",castingwords:"CastingWords",cdrplatform:"CDR Platform",certifier:"Certifier",chatbotkit:"ChatBotKit",chatfai:"ChatFAI",chmeetings:"ChMeetings",circleci:"CircleCI",clickhouse:"Clickhouse",clientary:"Clientary",clockify:"Clockify",cloudflare:"Cloudflare",cloudinary:"Cloudinary",collegefootballdata:"College Football Data",confluence:"Confluence",connecteam:"Connecteam",contentfulgraphql:"Contentful GraphQL",contextsevenmcp:"Context7",convoloai:"ConvoloAi",cosmic:"Cosmic",countdownapi:"Countdown API",crowterminal:"CrowTerminal",cursor:"Cursor",customgpt:"CustomGPT",dadataru:"Dadataru",databricks:"Databricks",datadog:"Datadog",datarobot:"DataRobot",deepseek:"DeepSeek",devinmcp:"Devin MCP",diffbot:"Diffbot",digitalocean:"DigitalOcean",discord:"Discord",dockerhub:"Docker Hub",dodopayments:"Dodo Payments",doppler:"Doppler",dreamstudio:"DreamStudio",dripcel:"Dripcel",dropbox:"Dropbox",dropboxsign:"Dropbox Sign",dynapictures:"Dynapictures",emelia:"Emelia",epicgames:"Epic Games",exa:"Exa",exist:"Exist",facebook:"Facebook",faraday:"Faraday",figma:"Figma",filloutforms:"FilloutForms",firecrawl:"Firecrawl",fireflies:"Fireflies",flexisign:"Flexisign",formbricks:"Formbricks",gemini:"Gemini",github:"GitHub",gitlab:"GitLab",gladia:"Gladia",gmail:"Gmail",googleaddressvalidation:"Google Address Validation",googleanalytics:"Google Analytics",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",griptape:"Griptape",groqcloud:"GroqCloud",habitica:"Habitica",hackernews:"Hacker News",harvest:"Harvest",hashnode:"Hashnode",here:"HERE",heygen:"HeyGen",htmltoimage:"HtmlToImage",hubspot:"HubSpot",huggingface:"Hugging Face",imgbb:"ImgBB",insightoai:"Insighto.ai",instagram:"Instagram",intercom:"Intercom",jigsawstack:"JigsawStack",jira:"Jira",kaggle:"Kaggle",kibana:"Kibana",linear:"Linear",linkedin:"LinkedIn",loyverse:"Loyverse",mailboxlayer:"MailboxLayer",mailchimp:"Mailchimp",mailtrap:"Mailtrap",marketstack:"Marketstack",merriamwebsterdict:"Merriam-Webster Dictionary",monday:"Monday",neon:"Neon",nextdns:"NextDNS",notion:"Notion",ocrspace:"OCR.space",ocrwebservice:"OcrWebService",ollama:"Ollama",onedrive:"OneDrive",onepassword:"1Password",openai:"OpenAI",openrouter:"OpenRouter",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",parseur:"Parseur",pdfmonkey:"PDFMonkey",perplexityai:"Perplexity AI",pinecone:"Pinecone",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",removebg:"remove.bg",resend:"Resend",retailed:"Retailed",runpod:"RunPod",salesforce:"Salesforce",sapsuccessfactors:"SAP SuccessFactors",scaleai:"Scale AI",scrapegraphai:"ScrapeGraphAI",securitytrails:"SecurityTrails",sendgrid:"SendGrid",sentry:"Sentry",serpapi:"Serpapi",sharepoint:"SharePoint",slack:"Slack",sourcegraph:"Sourcegraph",spotify:"Spotify",strava:"Strava",streamtime:"Streamtime",stripe:"Stripe",studiobyai21labs:"StudioByAI21Labs",supabase:"Supabase",synthflowai:"Synthflow AI",tally:"Tally",tavily:"Tavily",tavilymcp:"Tavily MCP",teams:"Teams",telegram:"Telegram",textrazor:"TextRazor",ticktick:"TickTick",timecamp:"TimeCamp",timelink:"Timelink",tinyurl:"TinyURL",tisane:"Tisane",todoist:"Todoist",toggl:"Toggl",trello:"Trello",twentyonerisk:"TwentyOneRisk",twilio:"Twilio",twitter:"Twitter",twitterapiio:"Twitter API IO",twochat:"TwoChat",typeform:"Typeform",unione:"Unione",uniswapapi:"Uniswap",uploadcare:"Uploadcare",vapi:"Vapi",vercel:"Vercel",veriphone:"Veriphone",vestaboard:"Vestaboard",wakatime:"WakaTime",webflow:"Webflow",webvizio:"Webvizio",whatsapp:"WhatsApp",witai:"WitAi",wix:"Wix",wiza:"Wiza",workday:"Workday",workiom:"Workiom",worldnewsapi:"World News API",xquik:"XQuik",youcom:"You.com",youtube:"YouTube",zendesk:"Zendesk",zohoinventory:"Zoho Inventory",zohomail:"Zoho Mail",zoom:"Zoom",zoominfo:"ZoomInfo"};function Ie(e){let n=Vo[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var ye=class extends Error{connectUrl;plugin;tenantId;reason;constructor(n){super(n.message??"Reconnect required"),Object.setPrototypeOf(this,new.target.prototype),this.name="ReconnectRequiredError",this.connectUrl=n.connectUrl,this.plugin=n.plugin,this.tenantId=n.tenantId,this.reason=n.reason}};function _(e){return typeof e=="string"&&e.length>0}function qa(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function Ka(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function Jn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!_(n.connectUrl)||!_(n.token)||!_(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:_(n.environmentId)?n.environmentId:n.projectId};return _(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Vn(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(!_(r.tenantId)||!_(r.plugin)||!qa(r.status)||!Ka(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:_(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function Yn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!_(n.approvalUrl)||!_(n.token)||!_(n.projectId)||!_(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 en(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(_(n.access_token))return{access_token:n.access_token,refresh_token:_(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:_(n.scope)?n.scope:void 0};throw new Error(_(n.error)?_(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Za(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function Ga(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;_(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 za(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 Yo(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!_(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(!_(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=Ga(o.fields),a=Za(o.missingRequiredFields),c=za(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:_(o.providerName)?o.providerName:o.plugin,authKind:i,status:c,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function Qn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function Qo(e){if(!e||typeof e!="object")return null;let n=e;if(n.errorType!=="reconnect_required")return null;let t=r=>typeof r=="string"&&r.length>0?r:null;return{message:t(n.error),connectUrl:t(n.connectUrl),plugin:t(n.plugin),tenantId:t(n.tenantId),reason:t(n.reason)}}function Xo(e){return e.replace(/\/$/,"")}function or(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return Ae()}catch{return null}}function ei(e){let n=or(e);return n?{"x-corsair-delivery-url":n}:{}}async function ni(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 Ja(e,n,t){if(n===404&&t)return t;let r=Qn(e);return r||`Hub API returned HTTP ${n}`}function ti(e,n,t){let r=Qo(e);throw r?new ye({message:r.message??void 0,connectUrl:r.connectUrl,plugin:r.plugin,tenantId:r.tenantId,reason:r.reason??void 0}):new Error(Ja(e,n,t))}async function I(e){let n=Xo(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...ei(e.hub)},body:JSON.stringify(e.body)}),r=await ni(t);return t.ok||ti(r,t.status,e.notFoundMessage),e.parseResponse(r)}async function q(e){let n=Xo(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...ei(e.hub)}}),r=await ni(t);return t.ok||ti(r,t.status,e.notFoundMessage),e.parseResponse(r)}function Xn(e){return e&&typeof e=="object"?e:{}}function ri(e){let n=Xn(e);return{chatId:n.threadId,message:n.message,workflowId:n.workflowId??null,action:n.action}}async function ir(e,n){return I({hub:e,path:"/threads",body:{tenantId:n.tenantId,message:n.message},parseResponse:t=>{let r=Xn(t);return{chat:r.thread,reply:ri(r.reply)}}})}async function sr(e,n){return I({hub:e,path:`/threads/${encodeURIComponent(n.chatId)}/messages`,body:{tenantId:n.tenantId,message:n.message},notFoundMessage:`Chat "${n.chatId}" not found`,parseResponse:ri})}async function ar(e,n){return q({hub:e,path:`/threads?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Xn(t).threads;return Array.isArray(r)?r:[]}})}async function cr(e,n){return q({hub:e,path:`/threads/${encodeURIComponent(n.chatId)}/messages?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Chat "${n.chatId}" not found`,parseResponse:t=>{let r=Xn(t).messages;return Array.isArray(r)?r:[]}})}import{randomUUID as tc}from"crypto";var Va="corsair:client-bridge";function ur(e){return new URL(e).origin}function nn(e){let n=JSON.stringify({type:Va,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(ur(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 Ya=new Set(["localhost","127.0.0.1","[::1]","::1"]);function lr(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Ya.has(n)}catch{return!1}}function xn(e){return e==="development"?"browser":"server"}function oi(e){return xn(e)==="browser"}function ii(e){return lr(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as nc}from"crypto";var Se=60*1e3,$e=300*1e3;import{createHmac as Qa,randomBytes as Xa,timingSafeEqual as ec}from"crypto";function me(){return Xa(16).toString("base64url")}function In(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Qa("sha256",t).update(e).digest("base64url")}function le(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=In(o,t);try{if(!ec(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 et(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=In(i,n);return`${i}.${s}`}function Sn(e,n,t){let r=Math.floor(Date.now()/1e3);return et(e,n,r+Math.floor(t/1e3))}function We(e){return decodeURIComponent(e)}function dr(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function si(e){let n=e.trim();return n.length>0?n:null}function tn(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function rn(e,n){if(!si(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??nc(16).toString("base64url"),iat:t,exp:t+Math.floor(Se/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=In(o,n);return`${o}.${i}`}function _e(e,n){return si(n)?le(e,n):null}function rc(e){let n=ur(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 pr(e){let n=rn(rc(e),e.signingSecret);return tn(e.deliveryUrl,n)}function ai(e){if(xn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=tc(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:pr(r)}}var _n="https://auth.corsair.dev";var he=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}},En=class extends Error{constructor(){super("Hub credentials are missing. Pass hub: { projectApiKey, signingSecret } to createCorsair() with non-empty values, or omit `hub` entirely if you are not using Corsair Hub."),this.name="HubCredentialsMissingError"}};function gr(e){let n=(e.apiUrl?.trim()||_n).replace(/\/$/,""),t=e.projectApiKey?.trim()??"",r=e.signingSecret?.trim()??"",o=t.startsWith("ck_cloud_");if(!t||!r&&!o)throw new En;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 nt(e){return gr(e)}function oc(e){let n=e.projectApiKey.startsWith("ck_cloud_");return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&(n||e.signingSecret.trim().length>0)}function U(e){let n=T(e).hub;if(!n||!oc(n))throw new he;return n}function ci(e){return e.replace(/\/$/,"")}function tt(e){return e.oauthCallbackUrl?ci(e.oauthCallbackUrl.trim()):`${ci(e.apiUrl)}/oauth/callback`}function on(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";if(e.startsWith("ck_cloud_"))return"cloud";throw new Error("Hub API key must start with ck_dev_ (development), ck_prod_ (production), or ck_cloud_ (cloud)")}import{createCipheriv as ui,createDecipheriv as li,randomBytes as rt,scrypt as ic}from"crypto";import{promisify as sc}from"util";var di=sc(ic),ot="aes-256-gcm",pi=12,it=16,ac=16,je=32;function be(){return rt(je).toString("base64")}async function ke(e,n){let t=rt(ac),r=await di(n,t,je),o=rt(pi),i=ui(ot,r,o,{authTagLength:it}),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 X(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"),c=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),u=await di(n,s,je),d=li(ot,u,a,{authTagLength:it});return d.setAuthTag(c),Buffer.concat([d.update(l),d.final()]).toString("utf8")}function fr(e,n){let t=Buffer.from(n,"base64"),r=rt(pi),o=ui(ot,t,r,{authTagLength:it}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function Dn(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"),c=Buffer.from(o,"base64"),l=li(ot,i,s,{authTagLength:it});return l.setAuthTag(a),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function Ee(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=fr(o,n);return t}function de(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Dn(o,n);return t}function On(e,n,t){let r=de(e,n);return Ee(r,t)}function gi(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 yr=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function F(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...j[n].integration,...i],a=null,c={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let b=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!b)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:b.id,config:yr(b.config),dek:b.dek??null},a},updateIntegration:async b=>{let k=await c.getIntegration();await o.db.updateTable("corsair_integrations").set({...b.config!==void 0?{config:b.config}:{},...b.dek!==void 0?{dek:b.dek}:{},updated_at:new Date}).where("id","=",k.id).execute(),a=null}},l=null,u=async()=>{if(l)return l;let b=await c.getIntegration();if(!b.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await X(b.dek,r),l},d=async()=>{let b=await c.getIntegration(),k=await u(),v=b.config;return!v||Object.keys(v).length===0?{}:de(v,k)},p=Promise.resolve(),g=b=>{let k=p.then(()=>f(b));return p=k.catch(()=>{}),k},f=async b=>{let k=await u(),v;try{v=await d()}catch(D){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,D),v={}}let P={...v};for(let[D,M]of Object.entries(b))M===null?delete P[D]:P[D]=M;let O=Ee(P,k);await c.updateIntegration({config:O})};return{get_dek:u,issue_new_dek:async()=>{let b=await c.getIntegration(),k=be(),v={};if(b.dek){let O=await X(b.dek,r),D=b.config;D&&Object.keys(D).length>0&&(v=On(D,O,k))}let P=await ke(k,r);return await c.updateIntegration({config:v,dek:P}),l=k,k},...gi(d,g,s)}}function B(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,c=[...j[n].account,...s],l=null,u=async()=>{if(l)return l;let w=!1;for(;;){let R=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!R){if(!w&&a){w=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return l={id:R.id,config:yr(R.config),dek:R.dek??null},l}},d={kek:o,integrationName:t,tenantId:r,getIntegration:u,getAccount:async()=>{let w=!1;for(;;){let R=await u(),A=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",R.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{id:A.id,config:yr(A.config),dek:A.dek??null}}},updateAccount:async w=>{let R=await d.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","=",R.id).execute()}},p=null,g=null,f=null,h=async()=>{let w=await d.getAccount();if(!w.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return p&&g===w.dek||(p=await X(w.dek,o),g=w.dek),p},b=async()=>{if(f)return f;let w=await d.getIntegration();if(!w.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await X(w.dek,o),f},k=async()=>{let w=await d.getAccount(),R=await h(),A=w.config;return!A||Object.keys(A).length===0?{}:de(A,R)},v=async()=>{let w=await d.getIntegration(),R=await b(),A=w.config;return!A||Object.keys(A).length===0?{}:de(A,R)},P=Promise.resolve(),O=w=>{let R=P.then(()=>D(w));return P=R.catch(()=>{}),R},D=async w=>{let R=await d.getAccount();if(!R.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);let A=await X(R.dek,o),Y;try{let L=R.config;Y=!L||Object.keys(L).length===0?{}:de(L,A)}catch(L){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,L),Y={}}let ee={...Y};for(let[L,Pe]of Object.entries(w))Pe===null?delete ee[L]:ee[L]=Pe;let H=Ee(ee,A);await d.updateAccount({config:H})},M={get_dek:h,issue_new_dek:async()=>{let w=await d.getAccount(),R=be(),A={};if(w.dek){let ee=await X(w.dek,o),H=w.config;H&&Object.keys(H).length>0&&(A=On(H,ee,R))}let Y=await ke(R,o);return await d.updateAccount({config:A,dek:Y}),p=R,g=Y,R},...gi(k,O,c)};return n==="oauth_2"&&(M.get_integration_credentials=async()=>{let w=await v();return{...w,client_id:w.client_id||null,client_secret:w.client_secret||null,redirect_url:w.redirect_url??null}}),M}async function fi(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=be(),i=await ke(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function yi(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=be(),a=await ke(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var cc=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function De(e){return cc.has(e)}function uc(e,n){return De(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function lc(e){return!De(e)}function dc(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function pc(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function gc(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!dc(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function mi(e,n){if(!e)return!1;let t=Q(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function fc(e,n){let r=e.authConfig?.[n]?.integration??[];return[...j[n].integration,...r]}function yc(e,n){let r=e.authConfig?.[n]?.account??[];return[...j[n].account,...r]}function mc(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:gc(n,t),fields:t,missingRequiredFields:r}}async function qe(e,n,t){let r=S(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??[],c=F({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=B({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),u=fc(n,r),d=yc(n,r),p=[];for(let g of u)p.push({name:g,level:"integration",required:uc(r,g),configured:await mi(c,g)});for(let g of d)p.push({name:g,level:"account",required:lc(g),configured:await mi(l,g)});if(pc(r,p)){let g=p.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return mc(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 qe(e,s,r);a&&i.push(a)}return i}function st(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var hi=Symbol.for("corsair:internal"),bi=new WeakMap,ki=new WeakMap;function hc(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function bc(e){if(e.database){let t=bi.get(e.database);return t||(t=new Map,bi.set(e.database,t)),t}let n=ki.get(e);return n||(n=new Map,ki.set(e,n)),n}function kc(e){return e.multiTenancy?{withTenant:()=>({}),[hi]:e}:{[hi]:e}}async function sn(e,n){if(!e.database)return;let t=n.trim()||"default",r=bc(e),o=hc(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-KMADSAGQ.js");await a(kc(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 Oe(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function mr(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 an(e,n){if(!n)throw new Error("OAuth state signing requires a configured kek. Pass kek to createCorsair().");let t=Hn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var hr=600*1e3;function at(e,n){if(!n)return null;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:mr(r,{maxAgeMs:hr})}function wi(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function Ci(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 cn(e,n){await I({hub:e,path:"/connections/report",body:wi(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function wc(e,n){try{let t=U(e);I({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof he)return}}async function Cc(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!S(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await qe(n,e.plugin,r);o&&Ti(e.hub,Ci({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function vi(e,n){wc(e,n)}function Ti(e,n){I({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function un(e){Cc(e).catch(()=>{})}async function we(e,n){let t=T(e);if(!S(n.plugin))return;let o=await qe(t,n.plugin,n.tenantId);o&&vi(e,Ci({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 ct(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 Pi=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function vc(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 Tc(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 X(n.dek,e.kek),r=Pi(n.config),o={};Object.keys(r).length>0&&(o=de(r,t)),o[e.link.linkType]=e.link.externalId;let i=Ee(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function ln(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await vc({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let u=B({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),d=`set_${i.linkType}`,p=u[d];typeof p=="function"&&(await p(i.externalId),l=!0)}l||await Tc({database:n,kek:t,accountId:c,link:i})}async function br(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 c=await X(a.dek,t),u=Pi(a.config)[o];if(!u)continue;if(Dn(u,c)===i)return a}catch{continue}return null}async function ut(e){return(await br(e))?.tenant_id??null}async function Ri(e){return ut({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as Ai from"querystring";function Ke(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}?${Ai.stringify(i)}`}async function xi(e,n){try{return await q({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function dn(e,n,t,r){if(!n.subscribe)return;let o=U(e),i=await xi(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await we(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var Z=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Ii(e){let n=e.oauthConfig;if(!n)throw new Z("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Pc(e,n,t,r){await e.db.transaction().execute(async o=>{let i=o.selectFrom("corsair_integrations").select(["id"]).where("name","=",n);e.isPg===!0&&(i=i.forUpdate());let s=await i.executeTakeFirst();if(!s)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).where("integration_id","=",s.id).executeTakeFirst())return;let c=be(),l=await ke(c,r),u=new Date;await o.insertInto("corsair_accounts").values({id:Xe(),created_at:u,updated_at:u,tenant_id:t,integration_id:s.id,config:{},dek:l}).execute()})}async function kr(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=T(e,()=>new Z("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=K(s,n,p=>new Z("plugin_not_found",p)),c=Ii(a),u=await F({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!u)throw new Error(`client_id not configured for '${n}'`);if(i){let p=new URL(Ke({oauthConfig:c,clientId:u,redirectUri:o,state:""}));return p.searchParams.delete("state"),{url:p.toString(),state:""}}let d=an(Oe(n,r),s.kek);return{url:Ke({oauthConfig:c,clientId:u,redirectUri:o,state:d}),state:d}}function Rc(e,n){return{...n??{},...e}}async function Bn(e,n){let{code:t,state:r,redirectUri:o}=n,i=T(e,()=>new Z("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new Z("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let h=at(r,i.kek);if(!h)throw new Z("invalid_state","Invalid or tampered state parameter");s=h.plugin,a=h.tenantId}if(!i.database)throw new Z("no_database","No database configured on corsair instance");let c=K(i,s,h=>new Z("plugin_not_found",h)),l=Ii(c),u=F({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),d=await u.get_client_id(),p=await u.get_client_secret();if(!d||!p)throw new Z("credentials_not_configured",`Credentials not configured for '${s}'`);await Pc(i.database,s,a,i.kek);let g=await lt(t,d,p,l,o);if(!g.access_token)throw new Z("no_access_token",`No access_token returned from ${l.providerName}`);let f=B({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...c.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 we(e,{plugin:c,tenantId:a}).catch(()=>{});try{let h=Rc(g,n.callbackParams),b=await ct(i.plugins,s,h);if(b){try{let k=c.authConfig?.oauth_2?.account??[];await ln({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:b,authType:"oauth_2",extraAccountFields:k})}catch(k){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,k)}i.hub&&cn(i.hub,{plugin:s,tenantId:a,link:b,authType:"oauth_2"})}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,h)}if(c.subscribe)try{await dn(e,c,a,f)}catch(h){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,h)}return{plugin:s,tenantId:a}}async function Ac(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??dn,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let c=t.plugins.find(u=>u.id===a.integrationName);if(!c?.subscribe)continue;let l=`${c.id}/${a.tenantId}`;try{let u=S(c)??"oauth_2",d=B({authType:u,integrationName:c.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...c.authConfig?.[u]?.account??[]]}),p=c.keyBuilder;if(p){let g=Object.create(d,{get_expires_at:{value:async()=>"0"}});await p({authType:u,keys:g,hub:t.hub},"endpoint")}await o(n,c,a.tenantId,d),i.push(l)}catch(u){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,u),s.push(l)}}return{renewed:i,failed:s}}async function Si(e){let n=T(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 Ac({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function xc(e,n={}){let t=!1,r=()=>{t||(t=!0,Si(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 _i(e){if(!T(e).database)throw new Error("A database must be configured to provision Corsair integrations");await dt(e,{silent:!0})}async function pn(e,n){let t=T(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await sn(t,n)}var Ic=Symbol.for("corsair:internal"),Sc=new Set(["access_token","refresh_token","expires_at","scope"]);function _c(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Ec(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!De(t)&&!Sc.has(t)):n.filter(t=>!De(t))}function Ei(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function Dc(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function Oc(e){return{[Ic]:Ei(e)}}async function pt(e,n,t={}){let r=tt(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Ei(e),a=Oc(e);for(let c of e.plugins){if(i&&!i.has(c.id))continue;let l=S(c);if(!l)continue;let u=_c(l),d=t.providerNameOverrides?.[c.id]??Ie(c.id),p=await qe(s,c,n),g=Gn(c,l),f=Ec(l,g),h={plugin:c.id,providerName:d,authKind:u,alreadyConfigured:p?.connected??!1};if(f.length>0&&(h.credentialFields=f),u==="oauth"){let k=t.oauthModeOverrides?.[c.id]??(l==="managed"?"managed":"byo");if(h.oauthMode=k,!t.skipOAuthUrlGeneration&&k!=="managed")try{let v=await kr(a,c.id,{tenantId:n,redirectUri:r,hubConnect:!0});h.oauthUrl=v.url}catch(v){v instanceof Error&&/client_id not configured/i.test(v.message)||(h.setupError=v instanceof Error?v.message:`Could not prepare OAuth for ${c.id}`)}}o.push(h)}return o}async function Jg(e,n,t={}){let r=T(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return pt({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function Di(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await sn(e.internalConfig??Dc(e),n)}async function Oi(e,n){await pn(e,n)}async function Mi(e,n){let t=on(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=Ae({deliveryUrl:n.deliveryUrl})),I({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:Jn})}async function Hi(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await Di(t,n.tenantId);let r=await pt(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 Mi(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function gt(e,n){let t=T(e),r=U(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,c=await pt(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(c.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 Mi(r,{tenantId:n.tenantId,plugins:c,deliveryUrl:n.deliveryUrl})}async function ft(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=T(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 Mc(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 Mc(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-PNESATVT.js"),{postHubConnectSession:i}=await import("./connect-UZW2X4RS.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 c=a.find(l=>l.setupError);if(c)throw new Error(c.setupError??`Could not prepare connect link for ${c.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}function gn(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var te=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Hc(e){let n=e.oauthConfig;if(!n)throw new te("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function wr(e,n){let t=T(e,()=>new te("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new te("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new te("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=at(n,t.kek);if(!o)throw new te("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=K(t,i,p=>new te("plugin_not_found",p)),c=Hc(a),u=await F({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!u)throw new te("client_id_not_configured",`client_id not configured for '${i}'`);let d=Ke({oauthConfig:c,clientId:u,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:c.providerName,oauthUrl:d,state:n}}import{AsyncLocalStorage as Uc}from"async_hooks";import{randomBytes as Fc}from"crypto";import{v4 as Lc}from"uuid";async function yt(e,n){let t=on(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=Ae({deliveryUrl:n.deliveryUrl})),I({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:Yn})}function mt(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Cr="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 Tr(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Bi(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function vr(e){return mt(e)}async function Pr(e,n){if(Tr(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Bi(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await yt(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:Bc(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function Bc(e){try{return JSON.parse(e)}catch{return e}}async function ht(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Pr(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:c,tenantId:l,expiresAt:u,operationPath:d}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:c});let g=await Pr({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(c),tenant_id:l,expires_at:u});return Tr(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):vr(g):Cr:r?g?vr(g):`Action '${d}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Cr}var Me=class extends Error{reason;constructor(n,t="pending"){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError",this.reason=t}};var Fi=new Uc,fn=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 Ar(e){return Fi.run(!0,e)}function Li(){return Fi.getStore()===!0}function xr(e,n){if(Li()&&n!=="read")throw new fn(e,n)}var Nc={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 $c(e,n,t){return t!==void 0?t:Nc[n][e]}function Ir(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 Ni(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 Ui(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 $i(e){let n=$c(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"?Ui(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let c=Lc(),l=Fc(32).toString("hex"),u=e.timeoutMs??600*1e3,d=new Date(Date.now()+u).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:c,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: ${c}`,`
|
|
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"?Ui(e.db,c,u):{result:"blocked",reason:"pending",id:c,token:l,expiresAt:d}}var C=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 x(e,n,t){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json",...t}})}function pe(e){let n={error:e.code,message:e.message,...e.extra};return x(e.status,n)}function He(e){return new C(404,"not_found",e)}function G(e,n={}){return new C(400,"bad_request",e,n)}function Sr(e,n){return K(e,n,t=>He(t))}async function Wi(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=F({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),o=j[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,u)=>s[u]==null),c;return t==="oauth_2"?c=!a.includes("client_id")&&!a.includes("client_secret"):c=a.length===0,{configured:c,missingFields:a}}async function ji(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await Wi(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 bt(){return{ok:!0}}async function yn(e){return Promise.all(e.plugins.map(n=>ji(n,e)))}async function kt(e,n){let t=Sr(e,n);return ji(t,e)}async function Wc(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 qi(e,n){let t=await Wc(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function mn(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 wt(e,n){if(!n)throw G("Tenant id must be a non-empty string");return qi(e,n)}async function Ct(e,n){let t=n?.id?.trim();if(!t)throw G("Tenant id is required",{missingFields:["id"]});return qi(e,t)}async function vt(e,n){let t=n?.trim()||"default",r={},o=await Mn(e,t);for(let i of o)r[i.plugin]=st(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 Tt(e,n){let t=n?.plugin;if(typeof t!="string"||!t.trim())throw G("plugin is required",{missingFields:["plugin"]});let r=t.trim();Sr(e,r);let o=n?.tenantId;if(o!=null&&typeof o!="string")throw G("tenantId must be a string");let i=o?.trim()||"default";if(!e.database)return{ok:!0,disconnected:!1};let s=e.database.db,a=await s.selectFrom("corsair_integrations").select(["id"]).where("name","=",r).executeTakeFirst();if(!a)return{ok:!0,disconnected:!1};let c=!1;return await s.transaction().execute(async l=>{e.database?.isPg===!0&&await l.selectFrom("corsair_integrations").select("id").where("name","=",r).forUpdate().execute();let u=l.selectFrom("corsair_accounts").select("id").where("tenant_id","=",i).where("integration_id","=",a.id);await l.deleteFrom("corsair_events").where("account_id","in",u).execute(),await l.deleteFrom("corsair_entities").where("account_id","in",u).execute(),c=((await l.deleteFrom("corsair_accounts").where("tenant_id","=",i).where("integration_id","=",a.id).executeTakeFirst()).numDeletedRows??0n)>0n}),{ok:!0,disconnected:c}}async function _r(e,n){if(!e.database)throw He(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw He(`Permission '${n}' not found`);return ht(e,t)}function jc(e){if(!e.oauthConfig)throw G(`Plugin '${e.id}' has no oauthConfig`)}function qc(e){if(!e.manual)throw new C(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Er(e){let n=qc(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new C(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 Kc(e){let n=!!e.hub,t=gn(e.manual);if(!n&&!t)throw new C(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function Ki(e){if(!e.database||!e.kek)throw new C(500,"database_not_configured","A database and kek are required to issue connect links.")}async function Zc(e,n){let t=n?.plugin?.trim();if(!t)throw G("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=Sr(e,t);jc(o);let i=Er(e);Ki(e);let s=await Wi(o,e);if(!s.configured)throw new C(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=an(Oe(t,r),e.kek),c;try{c=new URL(i.baseUrl)}catch{throw new C(500,"connect_misconfigured","manual.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return c.searchParams.set("state",a),{connectUrl:c.toString(),expiresAt:new Date(Date.now()+hr).toISOString(),tenantId:r}}async function Gc(e,n,t){Ki(n);let r=t.tenantId?.trim()||"default",o={tenantId:r,oauthMode:t.oauthMode},i=t.plugin?.trim();i&&(o.plugin=i);let s=t.providerName?.trim();s&&(o.providerName=s);let a=await gt(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt,tenantId:r}}async function Pt(e,n,t){return Kc(n),n.hub?Gc(e,n,t):Zc(n,t)}async function Rt(e,n,t){if(n.hub&&!gn(n.manual))throw new C(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw G("state is required",{missingFields:["state"]});Er(n);try{return await wr(e,r)}catch(o){if(o instanceof te)switch(o.code){case"invalid_state":throw G("Invalid or expired state");case"client_id_not_configured":throw new C(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new C(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function At(e,n,t){if(n.hub&&!gn(n.manual))throw new C(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 G("Missing required fields",{missingFields:i});let s=Er(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:o,redirectUri:s.redirectUri,callbackParams:t.callbackParams})}catch(c){if(c instanceof Error&&c.name==="OAuthCallbackError")switch(c.code){case"invalid_state":throw G("Invalid or expired state");case"credentials_not_configured":throw new C(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new C(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function Dr(e,n){if(!e.database)throw He("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw He("Permission not found");return ht(e,t)}async function Zi(e,n){return"id"in n?_r(e,n.id):Dr(e,n.token)}import{createCipheriv as nu,createDecipheriv as ny,randomBytes as Vi,scryptSync as tu}from"crypto";import{createHmac as Or,randomUUID as zc,timingSafeEqual as zi}from"crypto";function Mr(e){return e.run??null}function Hr(e){return e.probe??null}function Ji(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function xt(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=Or("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":zc()}}}function Br(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Ji(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>$e)return!1;let i=Or("sha256",n).update(e.body).digest("hex");try{return zi(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function hn(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=Ji(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)>$e)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=Or("sha256",n).update(e.body).digest("hex");try{if(!zi(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 bn(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function It(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function St(e){let n=e.sync?.encrypted;return typeof n!="string"||!n.trim()?null:{encrypted:n.trim()}}function Un(e){let n=e.connectUrl?.trim();return n?{connectUrl:n,expiresAt:e.expiresAt}:null}function Ur(e){return Un(bn(e))}async function Fr(e){let n=await Dt({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=bn(n.body),r=It({httpOk:n.ok,status:n.status,body:t}),o=Un(t);if(!r||!o)throw new Error(Et({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function _t(e){return St(bn(e))}function Jc(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 Gi(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var Vc="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",Yc="Check the delivery URL configured for this environment.";function Qc(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})`}. ${Vc}`}function Xc(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${Yc}`}function Fn(e,n){let t=Jc(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 Et(e){if(e.status===0)return e.ack.error?e.ack.error:e.body.startsWith("Could not reach")?e.body:Fn(e.deliveryUrl,new Error(e.body||"Delivery request failed"));if(e.status===401||e.status===403)return Qc(e);if(e.status===404)return Xc(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}): ${Gi(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${Gi(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}var eu=15e3;async function Dt(e){let{body:n,headers:t}=xt(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n,signal:AbortSignal.timeout(eu)}),o=await r.text();return{ok:r.ok,status:r.status,body:o}}catch(r){return{ok:!1,status:0,body:Fn(e.deliveryUrl,r)}}}var ru="aes-256-gcm",ou=12,iu=16,su=16,au=32;function cu(e,n){return tu(e.trim(),n,au)}function Lr(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=Vi(su),o=cu(t,r),i=Vi(ou),s=nu(ru,o,i,{authTagLength:iu}),a=JSON.stringify(e),c=Buffer.concat([s.update(a,"utf8"),s.final()]),l=s.getAuthTag();return[r.toString("base64"),i.toString("base64"),l.toString("base64"),c.toString("base64")].join(":")}var uu=["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 Nr(e){if(e instanceof Ko)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!uu.some(t=>n.includes(t))}function lu(e){if(!e)return[];let n=S(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!De(r)):[]}async function Ln(e,n){let t=T(e);if(!t.database)throw new Error("A database must be configured to sync connections from the app");await dt(e,{silent:!0});let[r,o]=await Promise.all([mn(t),yn(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=lu(t.plugins.find(c=>c.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 Lr(i,n)}var ge=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function Ot(e,n){let t=T(e,()=>new ge("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ge("no_database","Database not configured");let r=K(t,n.plugin,u=>new ge("plugin_not_found",u)),o=S(r);if(!o)throw new ge("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new ge("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await pn(e,n.tenantId);let i=new Set(Gn(r,o)),a=r.authConfig?.[o]?.account??[],c=B({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),l=0;for(let[u,d]of Object.entries(n.credentials)){if(!d.trim())continue;if(!i.has(u))throw new ge("invalid_credentials",`Unknown credential field '${u}' for plugin '${n.plugin}'`);let p=Q(c,`set_${u}`);if(!p)throw new ge("invalid_credentials",`Cannot set credential field '${u}' for plugin '${n.plugin}'`);await p(d.trim()),l+=1}if(l===0)throw new ge("invalid_credentials","Provide at least one credential field to save");return await we(e,{plugin:r,tenantId:n.tenantId}).catch(()=>{}),{plugin:n.plugin,tenantId:n.tenantId}}var fe=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function $r(e,n){let t=T(e,()=>new fe("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new fe("no_database","Database not configured");let r=K(t,n.plugin,u=>new fe("plugin_not_found",u)),o=S(r);if(!o)throw new fe("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await _i(e);let i=new Set(zo(r,o)),a=r.authConfig?.[o]?.integration??[],c=F({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:a}),l=0;for(let[u,d]of Object.entries(n.credentials)){if(!d.trim())continue;if(!i.has(u))throw new fe("invalid_credentials",`Unknown integration credential field '${u}' for plugin '${n.plugin}'`);let p=Q(c,`set_${u}`);if(!p)throw new fe("invalid_credentials",`Cannot set integration field '${u}' for plugin '${n.plugin}'`);await p(d.trim()),l+=1}if(l===0)throw new fe("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var Mt=new Map;function du(e){for(let[n,t]of Mt)t<=e&&Mt.delete(n)}function Ht(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();du(r);let o=Mt.get(t);return o!==void 0&&o>r?{ok:!1,error:"Delivery request already consumed"}:(Mt.set(t,r+n),{ok:!0})}var Be=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function kn(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a,authType:c="managed",providerData:l}=n;if(!o.trim())throw new Be("no_access_token","Managed OAuth delivery missing access_token");let u=T(e,()=>new Be("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new Be("no_database","No database configured on corsair instance");let d=K(u,t,g=>new Be("plugin_not_found",g));await pn(e,r);let p=B({authType:c,integrationName:t,tenantId:r,kek:u.kek,database:u.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 we(e,{plugin:d,tenantId:r}).catch(()=>{});try{let g=await ct(u.plugins,t,{access_token:o,refresh_token:i,scope:a,...l});if(g){try{let f=d.authConfig?.[c]?.account??[];await ln({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:g,authType:c,extraAccountFields:f})}catch(f){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,f)}u.hub&&cn(u.hub,{plugin:t,tenantId:r,link:g,authType:c})}}catch(g){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,g)}return await dn(e,d,r,p).catch(g=>{console.warn(`[corsair:managed-oauth] subscribe failed for '${t}' tenant '${r}':`,g)}),{plugin:t,tenantId:r}}function pu(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Yi(e,n,t=[]){for(let[r,o]of Object.entries(e))if(pu(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=Yi(o,n,[...t,r]);if(i)return i}return null}function gu(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function fu(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 Qi(e,n,t,r,o){let i=gu(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=fu(i)||s);let c={headers:i,body:s,...r?{query:r}:{}},l=r?.tenantId||"default",u=e.withTenant?e.withTenant(l):e,d=o?.plugin,p=d?[d]:zn;for(let g of p){let f=u[g];if(!f||!f.webhooks||!d&&f.pluginWebhookMatcher&&!f.pluginWebhookMatcher(c))continue;let h=Yi(f.webhooks,c);if(!h)continue;let b=h.path.join("."),k={payload:s,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{},...o?.hubVerified?{hubVerified:!0}:{}};try{let v=await h.webhook.handler(k),P=!!Object.keys(v.returnToSender||{})?.length;return{plugin:g,action:b,body:s,response:P?{...v?.returnToSender,success:!0}:{success:!0},...v.responseHeaders&&{responseHeaders:v.responseHeaders}}}catch(v){return console.error(`Error executing webhook handler for ${g}.${b}:`,v),{plugin:g,action:b,body:s,response:{success:!1,error:v instanceof Error?v.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHash as yu}from"crypto";import*as Ze from"vm";var Xi="__corsairFailedStep",mu=3e4,Wr=class{constructor(n,t){this.wakeAt=n;this.stepName=t}__corsairSleep=!0};function es(e){return typeof e=="object"&&e!==null&&e.__corsairSleep===!0}function ns(e,n){return`st_${yu("sha256").update(`${n} ${e}`).digest("hex").slice(0,16)}`}function Bt(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 ts=new Set(["constructor","prototype","__proto__"]);function Ce(e,n){if(e===null)return null;let t=typeof e;return t==="function"?bu(e,n):t==="object"?hu(e):e}function hu(e){return new Proxy(e,{get(n,t){if(!ts.has(t))return Ce(Reflect.get(n,t,n),n)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function bu(e,n){return new Proxy(e,{apply:(t,r,o)=>ku(Reflect.apply(t,n,o)),construct(){throw new Error("Workflow code may not construct host objects")},get(t,r){if(!ts.has(r))return Ce(Reflect.get(t,r,t),t)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function ku(e){return e!==null&&typeof e=="object"&&typeof e.then=="function"?Promise.resolve(e).then(n=>Ce(n,void 0),n=>{throw Ce(n,void 0)}):Ce(e,void 0)}function wu(e){let n=Object.create(null),t=Ze.createContext(n,{name:"corsair-workflow",codeGeneration:{strings:!1,wasm:!1}}),o=Ze.runInContext("(s) => JSON.parse(s)",t,{filename:"corsair:sandbox:json"})(JSON.stringify(e.payload??null)),s=Ze.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)),c=Ze.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=Ce(e.corsair,void 0),n.__payload=o,n.__step=s,n.__console=c;let l=Ze.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 u,d=new Promise((p,g)=>{u=setTimeout(()=>g(new Error(`Workflow exceeded ${e.timeoutMs}ms time limit`)),e.timeoutMs)});return Promise.race([l,d]).finally(()=>clearTimeout(u))}async function jr(e){let n=e.memoizedSteps??{},t=[],r=0,o=null,i=(async(s,a)=>{if(o)throw o;let c=r++,l=ns(s,c);if(Object.hasOwn(n,l))return Ce(n[l].output,void 0);try{let u=await a();return t.push({stepId:l,name:s,seq:c,status:"completed",output:u}),u}catch(u){if(es(u))throw u;let d=Bt(u);t.push({stepId:l,name:s,seq:c,status:"failed",error:d});let p=new Error(d);throw p[Xi]=s,p}});i.sleep=async(s,a)=>{if(o)throw o;let c=r++,l=ns(s,c);if(Object.hasOwn(n,l))return;t.push({stepId:l,name:s,seq:c,status:"completed",output:null});let u=Number.isFinite(a)?Math.max(0,a):0;throw o=new Wr(Date.now()+u,s),o};try{await wu({code:e.code,corsair:e.corsair,payload:e.payload,step:i,timeoutMs:e.timeoutMs??mu});let s=o;return s?{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()}:{status:"completed",steps:t}}catch(s){if(es(s))return{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()};let a=Bt(s),c=s!==null&&typeof s=="object"?s[Xi]:void 0;return{status:"failed",steps:t,error:{message:a,...c?{failedStep:c}:{}}}}}import*as Ut from"vm";var rs=1e4;async function qr(e){let n=Object.create(null),t=Ut.createContext(n,{name:"corsair-probe",codeGeneration:{strings:!1,wasm:!1}});n.corsair=Ce(e.corsair,void 0);let r=vu(e.timeoutMs),o=`(async () => {
|
|
43
|
+
const __result = await (async () => {
|
|
44
|
+
${e.code}
|
|
45
|
+
})();
|
|
46
|
+
return JSON.stringify(__result) ?? 'null';
|
|
47
|
+
})()`;try{let i=await Ar(()=>{let s=Ut.runInContext(o,t,{filename:"corsair:probe",timeout:r});s.catch(()=>{});let a,c=new Promise((l,u)=>{a=setTimeout(()=>u(new Error(`Probe exceeded ${r}ms time limit`)),r)});return Promise.race([s,c]).finally(()=>clearTimeout(a))});return{status:"ok",value:Cu(i)}}catch(i){return{status:"error",error:Bt(i)}}}function Cu(e){if(typeof e!="string")throw new Error(`Probe returned a non-string result (${typeof e})`);return JSON.parse(e)}function vu(e){return typeof e!="number"||!Number.isFinite(e)||e<=0?rs:Math.min(e,rs)}function Ge(e){return e.deliveryMode==="auth.credentials"}function Nn(e){return e.deliveryMode==="connections.sync"}function Ft(e){return e.deliveryMode==="connect.create_link"}function $n(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function Wn(e){return e.deliveryMode==="oauth.tokens"}function Lt(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!Ge(e)&&!Nn(e)&&!Ft(e)&&!$n(e)&&!Wn(e)}function Tu(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 Pu(e,n){try{return{status:"ok",webhookResponse:{status:200,body:{status:"ok",sync:{encrypted:await Ln(e,n)}}}}}catch(t){return{status:"failed",retryable:Nr(t),error:t instanceof Error?t.message:"Connections sync delivery failed"}}}async function Ru(e,n){try{let t=await ft(e,n);return Tu(t)}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Connect link delivery failed"}}}function Kr(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 Au(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 ut({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function xu(e,n,t,r){let o=await Au(e,n,t),i={...t.query??{},...o?{tenantId:o}:{}},s=await Qi(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,c=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:c,headers:s.responseHeaders}}}async function Iu(e,n){return await Bn(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 Su(e,n){return await kn(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 Gr(e,n,t){let r=await Zr(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function Zr(e,n,t){let r=T(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 _u(e,n){try{return await Ot(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function Eu(e,n){try{return await $r(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}function os(e,n){let t=e;return n&&typeof t?.withTenant=="function"?t.withTenant(n):e}async function Du(e,n){try{let t=os(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",run:await jr({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 Ou(e,n){try{let t=os(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",probe:await qr({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 jn(e,n,t={}){let r=T(e),o=Kr(n.headers,"x-corsair-signature"),i=Kr(n.headers,"x-corsair-timestamp"),s=Kr(n.headers,"x-corsair-nonce"),a=!1;if(t.signingSecret?.trim()){let l=hn({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 u=Ht(`nonce:${s.trim()}`,$e);if(!u.ok)return{status:"failed",retryable:!1,error:u.error};a=!0}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let c;try{c=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}if(c.type==="connect.status")return{status:"failed",retryable:!1,error:"connect.status is deprecated; use connections.sync signed delivery instead"};switch(c.type){case"webhook":return xu(e,r,c.payload,a);case"oauth.callback":return Iu(e,c.payload);case"oauth.tokens":return Su(e,c.payload);case"permission.approve":return Zr(e,c.payload,"approved");case"permission.deny":return Zr(e,c.payload,"denied");case"auth.credentials":return _u(e,c.payload);case"integration.credentials":return Eu(e,c.payload);case"connect.create_link":return Ru(e,c.payload);case"connections.sync":{let l=t.signingSecret?.trim();return l?Pu(e,l):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}case"run":return t.allowWorkflowExecution?Du(e,c.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};case"probe":return t.allowWorkflowExecution?Ou(e,c.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(c.type)}`}}}function Mu(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 zr=3,Hu=250;function Bu(e){return e?.name==="AbortError"}async function Uu(e){try{return(await e.json())?.ok!==!1}catch{return!0}}async function Fu(e,n,t,r,o){for(let i=1;i<=zr;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 Uu(s)||console.warn(`[corsair] hub did not record delivery ${r.deliveryId} (already timed out); the run may be retried`),!0}catch(s){if(Bu(s))throw s}i<zr&&await ss(Hu)}return console.warn(`[corsair] failed to acknowledge delivery ${r.deliveryId} after ${zr} attempts; the run may be retried`),!1}async function Lu(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:c}=await i.json(),l=await t.process(e,{headers:c,body:a},{signingSecret:n.signingSecret,allowWorkflowExecution:n.allowWorkflowExecution}),{status:u,body:d}=Mu(l);return await Fu(n,t,o,{deliveryId:s,status:u,body:d},r)?"handled":"error"}var is=1e3,Nu=5e3,$u=3e4;function ss(e){return new Promise(n=>setTimeout(n,e))}var Nt=globalThis.__corsairConnectLoops??=new Map;function Wu(e,n={fetch,process:jn}){let t;try{t=U(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(Nt.has(r))return{stop:()=>{}};let o=Symbol("corsair-connect-loop");Nt.set(r,o);let i=()=>{Nt.get(r)===o&&Nt.delete(r)},s=!1,a=null;return(async()=>{let l=is,u=!1,d=async p=>{u||(console.warn("[corsair] connect loop error; retrying",p),u=!0),s||await ss(l),l=Math.min(l*2,Nu)};try{for(;!s;){a=new AbortController;let p=setTimeout(()=>a?.abort(),$u);try{await Lu(e,t,n,a.signal)==="error"?await d("pull or ack failed"):(u=!1,l=is)}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 as(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function ju(e,n){return n&&!n.has(e.id)?!1:S(e)!==null}async function cs(e,n,t={}){let r=T(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])),c=r.plugins.filter(l=>ju(l,i)).map(l=>{let u=S(l),d=a.get(l.id);return d?{plugin:l.id,providerName:Ie(l.id),authKind:as(u),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:Ie(l.id),authKind:as(u),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:c}}async function us(e,n){let t=U(e);return q({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:Vn})}var ls=1024*1024,ds=3e4;function ze(e){return e!==void 0&&Number.isFinite(e)&&e>0?e:ls}function Je(e){return e!==void 0&&Number.isFinite(e)&&e>=0?e:ds}function wn(e){return new C(413,"payload_too_large",`Request body exceeds the ${e}-byte limit`)}function qu(e){return new C(408,"request_timeout",`Request body stalled: no bytes received for ${e}ms`)}async function $t(e,n){if(!(n>0))return e();let t;try{return await Promise.race([e(),new Promise((r,o)=>{t=setTimeout(()=>o(qu(n)),n)})])}finally{clearTimeout(t)}}async function Wt(e,n){if(e.body===null)return"";let t=e.body.getReader();try{let r=[],o=0;for(;;){let{done:a,value:c}=await $t(()=>t.read(),n.bodyStallTimeoutMs);if(a)break;if(o+=c.byteLength,o>n.maxBodyBytes)throw wn(n.maxBodyBytes);r.push(c)}let i=new Uint8Array(o),s=0;for(let a of r)i.set(a,s),s+=a.byteLength;return new TextDecoder().decode(i)}catch(r){throw t.cancel().catch(()=>{}),r}}var Jr=new Map;function ps(e){let n;try{n=U(e)}catch{return}let t=or(n);t&&Jr.get(n.projectApiKey)!==t&&(Jr.set(n.projectApiKey,t),I({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{Jr.delete(n.projectApiKey)}))}var Ku=[".corsair.dev"];function Zu(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Gu(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Zu(n)?!0:Ku.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function gs(e){return!e||!Gu(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 fs(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 Vr(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 Yr(e,n){let t=U(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=_e(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=Ht(`browser:${i.jti}`,Se);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(Nn(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 Ln(e,t.signingSecret);return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:nn({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(Ft(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 c=await ft(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:nn({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:c.connectUrl,expiresAt:c.expiresAt}})}}if(Ge(i))return i.hubSuccessUrl?i.credentials?(await Ot(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:Vr(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:Vr(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if($n(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await Gr(e,i.permissionToken,i.deliveryMode==="permission.approve"?"approved":"denied")}else if(Wn(i)){if(!i.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await kn(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(!Lt(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await Bn(e,{code:i.code,state:i.state,redirectUri:i.redirectUri,trusted:!0,plugin:i.plugin,tenantId:i.tenantId})}}catch(a){let c=a instanceof Error?a.message:"Hub delivery failed";return Nn(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:nn({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:Ft(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:nn({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:Ge(i)&&i.hubSuccessUrl?{type:"redirect",url:Vr(i.hubSuccessUrl,{error:c})}:Ge(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:nn({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:{type:"json",status:400,body:{error:c}}}return{type:"redirect",url:i.hubSuccessUrl}}async function Qr(e,n){let t=U(e),r=await jn(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 Xr(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 eo(e,n){return n.method==="GET"?Yr(e,n.url):Qr(e,{headers:n.headers,body:n.body??""})}async function no(e,n){try{let t=await eo(e,n);return Xr(t)}catch(t){if(t instanceof he)return Response.json({error:t.message},{status:503});throw t}}async function Ve(e,n,t){ps(e);let r=n.method.toUpperCase(),o=gs(n.headers.get("origin"));if(r==="OPTIONS")return o?new Response(null,{status:204,headers:o}):Response.json({error:"Method not allowed"},{status:405});if(r!=="GET"&&r!=="POST")return Response.json({error:"Method not allowed"},{status:405});let i=await no(e,{method:r,url:n.url,headers:n.headers,body:r==="POST"?await Wt(n,{maxBodyBytes:ze(t?.maxBodyBytes),bodyStallTimeoutMs:Je(t?.bodyStallTimeoutMs)}):void 0});return fs(i,o)}var E=class extends Error{pluginId;authType;connectUrl;tenantId;constructor(n,t,r,o){super(r??`[auth-missing:${n}:${t}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n,this.authType=t,this.connectUrl=o?.connectUrl??null,this.tenantId=o?.tenantId??null}};function Cn(e){if(e.forceRefresh||!e.accessToken)return!1;if(!e.expiresAt)return!0;let n=e.now??Math.floor(Date.now()/1e3);return Number(e.expiresAt)>n+300}async function vn(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 ys=new WeakMap;function qn(e,n,t){let r=ys.get(e);r||(r=new Map,ys.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 ms=300;async function to(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,s=n?.forceRefresh??!1,a=`managed:${o}:${i}`;return qn(t,a,async()=>{let[c,l,u]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!c&&!u)throw new E(o,"managed");let d=Math.floor(Date.now()/1e3);if(!s&&c&&l&&Number(l)>d+ms)return{accessToken:c,expiresAt:Number(l),refreshed:!1};if(!u&&c&&!s){let f=l?Number(l):null;if(f===null||f>d+ms)return{accessToken:c,expiresAt:f??d+3600,refreshed:!1}}if(!u)throw new E(o,"managed");let p=await Ju(r,o,i,u),g=await vn(t,p,l);return{accessToken:p.access_token,expiresAt:g,refreshed:!0}})}function zu(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function Ju(e,n,t,r){try{return await I({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t,refresh_token:r},parseResponse:en})}catch(o){let i=o instanceof Error?o.message:"";throw zu(i)?new E(n,"managed"):o}}async function hs(e,n){e._refreshAuth=async()=>(await to(n,{forceRefresh:!0})).accessToken}function bs(e){return{delivery:n=>Ve(e,n),deliveryOptions:n=>Ve(e,n)}}var ks=1200*1e3;function ro(){return me()}function oo(){return ks}function io(e,n){return Sn(e,n,ks)}function so(e,n){return le(e,n)}function ao(e){return We(e)}var ws=600*1e3;function co(){return me()}function uo(){return ws}function lo(e,n){return Sn(e,n,ws)}function po(e,n){return le(e,n)}function go(e){return dr(e)}function fo(e){return We(e)}function yo(){return me()}function mo(e,n,t){return et(e,n,Math.floor(t.getTime()/1e3))}function ho(e,n){return le(e,n)}function bo(e){return We(e)}var Ye=class extends Error{constructor(){super(`Corsair KEK is missing. Pass \`kek\` to createCorsair() or set CORSAIR_KEK in your environment. Generate one with: openssl rand -base64 ${je}`),this.name="CorsairKekMissingError"}};function jt(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(o,i){if(e&&!n)throw new Ye;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 ${je}`)}})}async function Vu(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 Cs(e){let{integrationId:n,accountId:t}=await Vu(e);return{integrationId:n,accountId:t}}function vs(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=>ir(t(),{tenantId:n,message:r}),list:()=>ar(t(),{tenantId:n}),get:r=>({message:o=>sr(t(),{chatId:r,tenantId:n,message:o}),listMessages:()=>cr(t(),{chatId:r,tenantId:n})})}}function Ts(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function Yu(e){let n=e.hub;if(n&&e.database&&e.kek)try{let t=await Hi(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return{message:e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:t.connectUrl,state:t.token}):Ts(e.pluginId,t.connectUrl),connectUrl:t.connectUrl}}catch{return{message:`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`,connectUrl:null}}return{message:`[auth-missing:${e.pluginId}:${e.authType}]`,connectUrl:null}}function Qu(e,n,t){let r=an(Oe(e,n.tenantId??t??"default"),n.kek),o=new URL(n.baseUrl);o.searchParams.set("state",r);let i=o.toString();return{message:n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:i,state:r}):Ts(e,i),connectUrl:i}}async function Xu(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&gn(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?Qu(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?Yu({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}):{message:e.error.message,connectUrl:null}}async function Ps(e){let{message:n,connectUrl:t}=await Xu(e);throw new E(e.error.pluginId,e.error.authType,n,{connectUrl:t,tenantId:e.tenantId??"default"})}var qt="connect.request",wo="connect.cleared",el=600*1e3;async function ko(e,n,t){let r=await e.db.selectFrom("corsair_integrations").select("id").where("name","=",t).executeTakeFirst();return r?(await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).where("integration_id","=",r.id).executeTakeFirst())?.id??null:null}async function nl(e,n){return(await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute()).map(r=>r.id)}async function tl(e,n,t){let r=await e.db.selectFrom("corsair_events").select("created_at").where("account_id","=",n).where("event_type","in",[qt,wo]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(!r)return t;let o=r.created_at instanceof Date?r.created_at.getTime():Date.parse(String(r.created_at));return Math.max(t,o+1)}async function Rs(e,n,t,r,o){let i=await tl(e,n,o),s=new Date(i);await e.db.insertInto("corsair_events").values({id:Xe(),created_at:s,updated_at:s,account_id:n,event_type:t,payload:r}).execute()}async function rl(e,n,t=Date.now()){let r=await ko(e,n.tenantId,n.plugin);r&&await Rs(e,r,qt,{plugin:n.plugin,connectUrl:n.connectUrl},t)}async function ol(e,n,t,r,o){let i=await e.db.selectFrom("corsair_events").select(["event_type","payload","created_at"]).where("account_id","=",n).where("event_type","in",[qt,wo]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(!i||i.event_type!==qt)return null;let s=i.created_at instanceof Date?i.created_at.getTime():Date.parse(String(i.created_at));if(r-s>o)return null;let a=typeof i.payload=="string"?JSON.parse(i.payload):i.payload??{},c=a.plugin,l=a.connectUrl;return typeof c!="string"||typeof l!="string"?null:{plugin:c,connectUrl:l,requestedAt:new Date(s).toISOString(),tenantId:t,requestedAtMs:s,accountId:n}}async function Co(e,n,t=Date.now(),r=el){let o=await nl(e,n);if(o.length===0)return null;let i=(await Promise.all(o.map(l=>ol(e,l,n,t,r)))).filter(l=>l!==null);if(i.length===0)return null;i.sort((l,u)=>l.requestedAtMs-u.requestedAtMs||l.accountId.localeCompare(u.accountId));let{requestedAtMs:s,accountId:a,...c}=i[0];return c}async function As(e,n,t=Date.now(),r){let o;if(r)o=await ko(e,n,r);else{let i=await Co(e,n,t);o=i?await ko(e,n,i.plugin):null}o&&await Rs(e,o,wo,{},t)}async function vo(e,n){if(!(!e||!n.plugin||!n.connectUrl))try{await rl(e,{tenantId:n.tenantId??"default",plugin:n.plugin,connectUrl:n.connectUrl})}catch{}}var il=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function xs(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||il)(e,i)}function sl(e){return typeof e=="function"}function To({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:c,endpointMeta:l,database:u,permissionsOptions:d,tenantId:p,manualConfig:g,hubConfig:f,plugin:h,kek:b,allPlugins:k,multiTenancy:v}){for(let[P,O]of Object.entries(e)){let D=n?.[P];if(sl(O)){let M=D,w=[...s,P].join("."),R=async(A={})=>{let Y=l?.[w];xr(w,Y?.riskLevel??"write");let ee;if(c){let N=Y,{result:ce,reason:W,onComplete:An,token:Re,id:Ne,expiresAt:ne}=await $i({pluginId:o,endpointPath:w,args:A,mode:c.mode,override:c.overrides?.[w],riskLevel:N?.riskLevel??"write",meta:N,db:u,timeoutMs:d?Ir(d.timeout):void 0,tenantId:p,approvalMode:d?.mode});if(ce==="blocked"){let ue;W==="denied"?ue=`Action '${w}' was denied by the user. Await further instructions before proceeding.`:W==="policy"?ue=`Action '${w}' is blocked by the permission policy. Update the corsair config to allow it.`:W==="timeout"?ue=`Action '${w}' timed out waiting for approval.`:Re&&Ne?ue=await Rr({permissionsOptions:d,manual:g,hub:f,permissionId:Ne,permissionToken:Re,plugin:o,endpoint:w,args:A,tenantId:p??"default",expiresAt:ne??new Date(Date.now()+(d?Ir(d.timeout):600*1e3)).toISOString(),operationPath:w}):ue=`Action '${w}' requires user approval before it can run.`;let Xt=W==="denied"||W==="policy"||W==="timeout"?W:"pending";throw new Me(ue,Xt)}ee=An}let H=async(N,ce,W)=>{try{return await O(ce,W)}catch(An){if(An instanceof Error){let Re=await xs(An,o,w,typeof W=="object"&&W!==null?W:{args:W},i);if(N<(Re.maxRetries||0)){let Ne=N+1;console.log(`Retrying (${Ne} / ${Re.maxRetries})...`);let ne;if(Re.headersRetryAfterMs)ne=Re.headersRetryAfterMs;else switch(Re.retryStrategy){case"exponential_backoff":ne=Math.pow(2,Ne-1)*1e3;break;case"exponential_backoff_jitter":let ue=Math.pow(2,Ne-1)*1e3,Xt=(Math.random()-.5)*1e3;ne=Math.max(0,ue+Xt);break;case"linear_1s":ne=1e3;break;case"linear_2s":ne=2e3;break;case"linear_3s":ne=3e3;break;case"linear_4s":ne=4e3;break;default:ne=1e3;break}return await new Promise(ue=>setTimeout(ue,ne)),await H(Ne,ce,W)}}throw An}},L;try{L=a?await a(t,"endpoint"):void 0}catch(N){if(N instanceof ye)throw h&&f&&un({hub:f,database:u,kek:b,plugins:k??[],plugin:h,tenantId:p,verified:!1}),await vo(u,{tenantId:N.tenantId??p,plugin:N.plugin,connectUrl:N.connectUrl}),N;if(N instanceof E){h&&f&&un({hub:f,database:u,kek:b,plugins:k??[],plugin:h,tenantId:p,verified:!1});try{await Ps({error:N,manual:g,hub:f,plugin:h,tenantId:p,database:u,kek:b,plugins:k,multiTenancy:v})}catch(ce){throw ce instanceof E&&await vo(u,{tenantId:ce.tenantId??p,plugin:ce.pluginId,connectUrl:ce.connectUrl}),ce}}throw N}if(!M?.before&&!M?.after){let N=await H(0,{...t,key:L},A);return await ee?.(),h&&f&&un({hub:f,database:u,kek:b,plugins:k??[],plugin:h,tenantId:p,verified:!0}),N}let Pe={...t,key:L},Le=M.before?await M.before(Pe,A):{ctx:Pe,args:A,continue:!0,passToAfter:void 0};if(Le.continue===!1)return;let Wo=await H(0,Le.ctx,Le.args);return await M.after?.(Le.ctx,Wo,Le.passToAfter),await ee?.(),h&&f&&un({hub:f,database:u,kek:b,plugins:k??[],plugin:h,tenantId:p,verified:!0}),Wo};r[P]=R}else if(O&&typeof O=="object"){let M={};To({endpoints:O,hooks:D,ctx:t,tree:M,pluginId:o,errorHandlers:i,currentPath:[...s,P],keyBuilder:a,permissionsConfig:c,endpointMeta:l,database:u,permissionsOptions:d,tenantId:p,manualConfig:g,hubConfig:f,plugin:h,kek:b,allPlugins:k,multiTenancy:v}),r[P]=M}}}function al(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Po({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(al(s)){let c=a,l=async u=>{let d=(g,f)=>s.handler(g,f),p=o&&u?.hubVerified!==!0?await o(t,"webhook"):void 0;return!c?.before&&!c?.after?d({...t,key:p},u):(async()=>{let g={...t,key:p},f=c.before?await c.before(g,u):{ctx:g,args:u,continue:!0,passToAfter:void 0};if(f.continue===!1)return;let h=await d(f.ctx,f.args);return h?.success===!0&&await c.after?.(f.ctx,h,f.passToAfter),h})()};r[i]={match:s.match,handler:l}}else if(s&&typeof s=="object"){let c={};Po({webhooks:s,hooks:a,ctx:t,webhooksTree:c,keyBuilder:o}),r[i]=c}}}function Is(e){return e&&typeof e=="object"?e:{}}async function Ss(e,n){return q({hub:e,path:`/workflows?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Is(t).workflows;return Array.isArray(r)?r:[]}})}async function _s(e,n){return q({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>Is(t).workflow})}async function Es(e,n){await I({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 Ds(e,n){await I({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 Os(e,n){return I({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 Ro(e){return e&&typeof e=="object"?e:{}}async function Ms(e,n){return q({hub:e,path:`/runs?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Ro(t).runs;return Array.isArray(r)?r:[]}})}async function Hs(e,n){return q({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/runs?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>{let r=Ro(t).runs;return Array.isArray(r)?r:[]}})}async function Bs(e,n){return q({hub:e,path:`/runs/${encodeURIComponent(n.runId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Run "${n.runId}" not found`,parseResponse:t=>Ro(t).run})}async function Ao(e,n,t){await I({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 Us=(e,n)=>Ao(e,"approve",n),Fs=(e,n)=>Ao(e,"deny",n),Ls=(e,n)=>Ao(e,"cancel",n);function Ns(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?Hs(t(),{workflowId:r.workflowId,tenantId:n}):Ms(t(),{tenantId:n}),get:r=>Bs(t(),{runId:r,tenantId:n}),approve:r=>Us(t(),{runId:r,tenantId:n}),deny:r=>Fs(t(),{runId:r,tenantId:n}),cancel:r=>Ls(t(),{runId:r,tenantId:n})}}function $s(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)=>Es(t(),{workflowId:o,tenantId:n,status:i});return{list:()=>Ss(t(),{tenantId:n}),get:o=>_s(t(),{workflowId:o,tenantId:n}),run:(o,i)=>Os(t(),{workflowId:o,tenantId:n,payload:i?.payload,idempotencyKey:i?.idempotencyKey}),runs:Ns(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)=>Ds(t(),{workflowId:o,tenantId:n,name:i})}}function cl(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 Cs({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function ul(e,n,t,r,o){return e?nr(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 xo(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:c,internalConfig:l}=n,u=r??"default",d=l&&t?()=>sn(l,u):void 0,p={},g={};for(let f of e)p[f.id]={},g[f.id]={};for(let f of e){let h=f.schema,b=cl(t,f.id,u,d);if(h?.entities){let H={};for(let[L,Pe]of Object.entries(h.entities)){let Le=t?nr(t.db,b,L,h.version,Pe):ul(void 0,b,L,h.version,Pe);H[L]=Le}g[f.id].db=H,p[f.id].db=H}let k=f.options,v=f.authConfig,P;if(t&&o&&k?.authType){let H=v?.[k.authType]?.account??[];P=B({authType:k.authType,integrationName:f.id,tenantId:u,kek:o,database:t,extraAccountFields:H,ensureProvisioned:d}),p[f.id].keys=P}let O={database:t,db:g[f.id]?.db??{},$getAccountId:b,...f.options?{options:f.options}:{},...P?{keys:P,authType:k?.authType}:{},tenantId:u,...c?{hub:c}:{}},D=f.endpoints??{},M=f.hooks,w={...i,...f.errorHandlers},R={},A=f.options?.permissions;To({endpoints:D,hooks:M,ctx:O,tree:R,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:u}:void 0,hubConfig:c,plugin:f,kek:o,allPlugins:e,multiTenancy:l?.multiTenancy}),Object.keys(R).length>0&&(p[f.id].api=R),O.endpoints=R;let Y=f.webhooks??{},ee=f.webhookHooks;if(Object.keys(Y).length>0){let H={};Po({webhooks:Y,hooks:ee,ctx:O,webhooksTree:H,keyBuilder:f.keyBuilder}),p[f.id].webhooks=H,f.pluginWebhookMatcher&&(p[f.id].pluginWebhookMatcher=f.pluginWebhookMatcher),f.pluginTenantWebhookMatcher&&(p[f.id].pluginTenantWebhookMatcher=f.pluginTenantWebhookMatcher)}}return p.chats=vs(c,u),p.workflows=$s(c,u),p}function Ws(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??[],c=F({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:a});r[o.id]=c}}return r}var ll=3e4;function dl(e){let n=e.length;for(;n>0&&e[n-1]==="/";)n--;return e.slice(0,n)}function pl(e){let n=0;for(;n<e.length&&e[n]==="/";)n++;return e.slice(n)}function gl(e,n){return`${dl(e)}/${pl(n)}`}function fl(e,n){let t=n??{},{error:r,message:o,...i}=t;return typeof r!="string"?new C(e,"internal_error","Internal error"):new C(e,r,o,i)}var Io=Symbol("cloudRequestTimeout");async function re(e,n,t,r){let o=e.fetch??globalThis.fetch,i=e.timeoutMs??ll,s=new AbortController,a,c=new Promise(p=>{a=setTimeout(()=>{s.abort(),p(Io)},i)}),l;try{let p=o(gl(e.baseUrl,t),{method:n,headers:{authorization:`Bearer ${e.apiKey}`,"content-type":"application/json"},body:r===void 0?void 0:JSON.stringify(r),signal:s.signal}).catch(f=>{if(s.signal.aborted)return Io;throw f}),g=await Promise.race([p,c]);if(g===Io)throw new C(0,"internal_error","Cloud request timed out");l=g}finally{clearTimeout(a)}let u=await l.text(),d;try{d=u?JSON.parse(u):void 0}catch{d=void 0}if(!l.ok)throw fl(l.status,d);if(d===void 0)throw new C(l.status,"internal_error","Invalid or empty response body from runtime");return d}var oe={invoke:"/:tenant/:plugin/call/:op",connectLinks:"/connect/links",tenants:"/tenants",tenant:"/tenants/:id",connectionStatus:"/connection-status",disconnect:"/disconnect",permission:"/permissions/:id",permissionLookup:"/permissions/lookup-by-token"};var yl=new Set(["db","keys","webhooks"]),ml=new Set(["chats","workflows"]),js=new Set(["then","catch","finally"]);function qs(e,n,t,r){let o=(...i)=>re(e,"POST",oe.invoke.replace(":tenant",encodeURIComponent(n)).replace(":plugin",encodeURIComponent(t)).replace(":op",r.map(encodeURIComponent).join(".")),{args:i[0]}).then(s=>s.data);return new Proxy(o,{get(i,s){if(!(typeof s!="string"||js.has(s)))return qs(e,n,t,[...r,s])}})}function So(e,n){let t=e?new Set(e.map(r=>r.id)):null;return new Proxy({},{get(r,o){if(!(typeof o!="string"||js.has(o))){if(ml.has(o))throw new Error(`"${o}" is not available in cloud mode (deferred)`);if(t&&!t.has(o))throw new Error(`Unknown plugin "${o}"`);return new Proxy({},{get(i,s){if(s==="api")return qs(n.transport,n.tenantId,o,[]);if(typeof s=="string"&&yl.has(s))throw new Error(`"${s}" is not available in cloud mode (deferred)`)}})}}})}function Ks(e){return{connect:{createLink:n=>{if(!n.plugin||!n.tenantId)throw new Error('connect.createLink requires both "plugin" and "tenantId" in cloud mode');return re(e,"POST",oe.connectLinks,n)}},tenants:{create:n=>re(e,"POST",oe.tenants,n),list:()=>re(e,"GET",oe.tenants),get:n=>re(e,"GET",oe.tenant.replace(":id",encodeURIComponent(n)))},connectionStatus:{get:n=>re(e,"GET",`${oe.connectionStatus}?tenantId=${encodeURIComponent(n.tenantId)}`)},disconnect:n=>re(e,"POST",oe.disconnect,n),permissions:{get:n=>"id"in n?re(e,"GET",oe.permission.replace(":id",encodeURIComponent(n.id))):re(e,"POST",oe.permissionLookup,{token:n.token})}}}var Zs="default";function ve(e){throw new Error(`"${e}" is not available in cloud mode (deferred)`)}function hl(e){let n=e?.baseUrl?.trim()||process.env.CORSAIR_CLOUD_URL?.trim();if(!n)throw new Error("Cloud mode (ck_cloud_ key) requires a base URL \u2014 set hub.baseUrl or CORSAIR_CLOUD_URL.");return er(n),n}function Gs(e){return!!(e?.baseUrl?.trim()||process.env.CORSAIR_CLOUD_URL?.trim())}function bl(e,n){let t=Ks(e);return{ok:()=>ve("manage.ok"),tenants:t.tenants,plugins:{list:()=>ve("manage.plugins.list"),get:()=>ve("manage.plugins.get")},connectionStatus:{get:r=>{let o=r?.tenantId||void 0;if(!o&&n)throw new Error("connectionStatus.get requires a tenantId in multi-tenant mode");return t.connectionStatus.get({tenantId:o??Zs})}},permissions:t.permissions,connect:{createLink:t.connect.createLink,resolve:()=>ve("manage.connect.resolve"),oauthCallback:()=>ve("manage.connect.oauthCallback")},disconnect:t.disconnect}}function zs(e,n){let t=bl(e,n.multiTenancy);if(n.multiTenancy)return{withTenant:s=>{if(!s)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");return So(n.plugins,{transport:e,tenantId:s})},get keys(){return ve("keys")},get permissions(){return ve("permissions")},manage:t};let r=So(n.plugins,{transport:e,tenantId:Zs}),o={manage:t,get keys(){return ve("keys")},get permissions(){return ve("permissions")}};return new Proxy(r,{get(s,a,c){return typeof a=="string"&&a in o?Reflect.get(o,a,c):Reflect.get(s,a,c)}})}function Js(e){return zs({baseUrl:hl(e.hub),apiKey:e.hub.projectApiKey},{multiTenancy:!!e.multiTenancy,plugins:e.plugins})}function kl(e){let n=e.apiKey?.trim();if(!n)throw new Error("corsairCloud: apiKey is required");let t=e.url?.trim()||jo(n);if(!t)throw new Error("corsairCloud: could not resolve a URL from apiKey \u2014 pass a ck_cloud_<slug>.<secret> key, or set `url` explicitly.");return er(t),zs({baseUrl:t,apiKey:n},{multiTenancy:!0})}var wl="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function Vs(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] ${wl}`),t):n}var Cl=e=>new C(404,"unknown_plugin",`Plugin '${e}' is not registered.`),vl=(e,n)=>new C(404,"unknown_op",`Operation '${n}' not found on plugin '${e}'.`),_o=()=>new C(403,"call_disabled","The /call route is disabled. Construct managementHandler with { unsafeAllowUnauthenticated: true } to enable it \u2014 only when your own backend fronts the handler."),Tl=e=>new C(401,"not_connected",`Tenant is not connected for plugin '${e}'. Reconnect and retry.`),Ys=e=>new C(403,"permission_denied",`The call was blocked (${e}).`,{reason:e}),Pl=()=>new C(403,"approval_required","This action needs human approval before it can run. Approval is not resumable over HTTP in this version.",{reason:"pending"}),Rl=(e,n)=>new C(502,"provider_error","The provider returned an error.",{providerStatus:e,body:n});function Al(e,n){if(e instanceof C)return e;if(e instanceof E)return Tl(e.pluginId||n);if(e instanceof fn)return Ys("readonly");if(e instanceof Me)return e.reason==="pending"?Pl():Ys(e.reason);if(e instanceof Error&&e.name==="ApiError"){let t=e;return Rl(typeof t.status=="number"?t.status:502,t.body)}return console.error("[corsair] unhandled error in call operation",e),new C(500,"internal_error","Internal error")}var xl=new WeakMap,Qs=new WeakMap,Il=512;function Xs(e,n){let t=e.get(n);return t||(t=new Map,e.set(n,t)),t}function Sl(e,n,t){if(n.size<=Il)return;let r=Qs.get(e);for(let o of n.keys())if(o!==t&&(r?.get(o)??0)===0){n.delete(o);return}}function _l(e,n,t){if(!n.multiTenancy)return{client:e};let r=typeof t=="string"?t.trim():"";if(!r)throw G("tenant is required for a multi-tenant runtime",{missingFields:["tenant"]});let o=Xs(xl,e),i=o.get(r);if(i)return o.delete(r),o.set(r,i),{client:i,tenantId:r};let s=e.withTenant(r);return o.set(r,s),Sl(e,o,r),{client:s,tenantId:r}}function El(e,n){let t=e;for(let r of n.split(".")){if(t==null||typeof t!="object"||!Object.prototype.hasOwnProperty.call(t,r))return null;t=t[r]}return typeof t=="function"?t:null}function ea(e,n=[]){let t=[];for(let[r,o]of Object.entries(e??{}))typeof o=="function"?t.push([...n,r].join(".")):o&&typeof o=="object"&&t.push(...ea(o,[...n,r]));return t}function na(e){let n={};for(let t of e.plugins)n[t.id]=ea(t.endpoints??{});return n}async function ta(e,n,{plugin:t,op:r,tenant:o,args:i}){if(!n.plugins.some(d=>d.id===t))throw Cl(t);let{client:s,tenantId:a}=_l(e,n,o),c=s[t],l=El(c?.api,r);if(!l)throw vl(t,r);let u=a?Xs(Qs,e):null;u&&a&&u.set(a,(u.get(a)??0)+1);try{return await l(i??{})}catch(d){throw Al(d,t)}finally{if(u&&a){let d=(u.get(a)??1)-1;d<=0?u.delete(a):u.set(a,d)}}}function Tn(e,n){if(e===void 0)return n;if(e===null)throw new C(401,"unauthenticated","Could not determine the tenant for this request. Sign in and retry.");return e}function Kt(e){if(e!==void 0)throw new C(403,"forbidden","This route is disabled when resolveTenant is configured (end-user mode). Use a handler without resolveTenant, behind your own admin auth.")}var ra=[{method:"GET",pattern:"/ok",public:!0,handler:async()=>x(200,bt())},{method:"GET",pattern:"/tenants",handler:async({internal:e,scopedTenant:n})=>(Kt(n),x(200,await mn(e)))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n,scopedTenant:t})=>(Kt(t),x(201,await Ct(e,n)))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n,scopedTenant:t})=>(Kt(t),x(200,await wt(e,n.id)))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>x(200,await yn(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>x(200,await kt(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n,scopedTenant:t})=>x(200,await vt(e,Tn(t,n.tenantId)))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n,scopedTenant:t})=>(Kt(t),x(200,await _r(e,n.id)))},{method:"POST",pattern:"/permissions/lookup-by-token",public:!0,handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?x(200,await Dr(e,t)):x(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t,scopedTenant:r})=>{let o=t,i=Tn(r,o.tenantId);return x(200,await Pt(e,n,{...o,tenantId:i}))}},{method:"GET",pattern:"/connect/resolve",public:!0,handler:async({corsair:e,internal:n,query:t})=>x(200,await Rt(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",public:!0,handler:async({corsair:e,internal:n,body:t})=>x(200,await At(e,n,t))},{method:"GET",pattern:"/connect/request",handler:async({internal:e,query:n,scopedTenant:t})=>{let r=Tn(t,n.tenantId)??"default",o=e.database?await Co(e.database,r):null;return x(200,{request:o},{"cache-control":"no-store"})}},{method:"POST",pattern:"/connect/request/clear",handler:async({internal:e,body:n,scopedTenant:t})=>{let r=n,o=Tn(t,r?.tenantId)??"default";return e.database&&await As(e.database,o,void 0,r?.plugin),x(200,{ok:!0})}},{method:"POST",pattern:"/disconnect",handler:async({internal:e,body:n,scopedTenant:t})=>{let r=n??{},o=Tn(t,r.tenantId);return x(200,await Tt(e,{...r,tenantId:o}))}},{method:"GET",pattern:"/call",handler:async({internal:e,allowCall:n})=>{if(!n)throw _o();return x(200,{plugins:na(e)})}},{method:"POST",pattern:"/:tenant/:plugin/call/:op",handler:async({corsair:e,internal:n,params:t,body:r,scopedTenant:o,allowCall:i})=>{if(!i)throw _o();let s=r??{},a=Tn(o,t.tenant),c=await ta(e,n,{plugin:t.plugin,op:t.op,tenant:a,args:s.args});return x(200,{data:c})}}];(()=>{let e=new Set;for(let n of ra){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Dl(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 Ol(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 Ml(e,n){if(e.method==="GET"||e.method==="HEAD"||!(e.headers.get("content-type")??"").includes("application/json"))return;let r=await Wt(e,n).catch(o=>{throw o instanceof C?o:new C(400,"invalid_json","Request body is not valid JSON")});if(r)try{return JSON.parse(r)}catch{throw new C(400,"invalid_json","Request body is not valid JSON")}}var Hl="/api/corsair";function $(e,n={}){let t=n.basePath??Hl,r=ze(n.maxBodyBytes),o=Je(n.bodyStallTimeoutMs),i={maxBodyBytes:r,bodyStallTimeoutMs:o},s=T(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async a=>{try{let c=a.headers.get("content-length");if(c!==null&&Number(c)>r)throw wn(r);let l=new URL(a.url),u=Ol(l.pathname,t),d=a.method.toUpperCase();if(d==="OPTIONS"||u==="/"||u==="")return await Ve(e,a,{maxBodyBytes:r,bodyStallTimeoutMs:o});if(d!=="GET"&&d!=="POST")return x(405,{error:"method_not_allowed",message:`Method ${d} not allowed`});let p=Object.fromEntries(l.searchParams);for(let g of ra){if(g.method!==d)continue;let f=Dl(g.pattern,u);if(!f)continue;if(!g.public&&n.authenticate&&!await n.authenticate(a))return x(401,{error:"unauthorized",message:"invalid or missing credentials"});let h=await Ml(a,i),b=n.resolveTenant?await n.resolveTenant(a):void 0;return await g.handler({corsair:e,internal:s,req:a,params:f,query:p,body:h,scopedTenant:b,allowCall:(n.unsafeAllowUnauthenticated??!1)||!!n.authenticate})}throw He(`No route for ${d} ${u}`)}catch(c){if(n.onError){let u=await n.onError(c,a);if(u)return u}if(c instanceof C)return pe(c);let l=c instanceof Error?c.message:"Internal server error";return x(500,{error:"internal_error",message:l})}}}function Bl(e,n){if(e.get)return e.get(n);let t=e.headers[n]??e.headers[n.toLowerCase()];return Array.isArray(t)?t[0]:t}function Ul(e){if(Buffer.isBuffer(e))return e;if(e instanceof Uint8Array)return Buffer.from(e);if(typeof e=="string")return Buffer.from(e,"utf8");throw new TypeError(`corsair adapter: unsupported stream chunk type ${typeof e}`)}async function Fl(e,n,t){let r=[],o=0,i=e();try{let s=await $t(()=>i.next(),t);for(;s.done!==!0;){let a=Ul(s.value);if(o+=a.byteLength,o>n)throw wn(n);r.push(a),s=await $t(()=>i.next(),t)}return Buffer.concat(r)}catch(s){try{Promise.resolve(i.return?.()).catch(()=>{})}catch{}throw s}}var oa=!1;function Ll(){oa||(oa=!0,console.warn("[corsair] A JSON body parser consumed this request before the corsair adapter.","Re-serializing the parsed object is lossy and will likely fail Hub signature",'verification ("Invalid tunnel signature"). Fix on the corsair route only:',"Express \u2192 mount express.raw({ type: 'application/json' }) before the handler,","or capture raw bytes via express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } }).","Fastify \u2192 call registerCorsairRawBodyParser(app) before listen()."))}async function Nl(e,n){let t=(e.method??"GET").toUpperCase();if(t==="GET"||t==="HEAD")return;let r=ze(n.maxBodyBytes),o=Je(n.bodyStallTimeoutMs),i;if(typeof e.rawBody=="string")i=e.rawBody;else if(e.rawBody instanceof Uint8Array)i=e.rawBody;else if(e.body!==void 0&&e.body!==null)typeof e.body=="string"||e.body instanceof Uint8Array?i=e.body:(Ll(),i=JSON.stringify(e.body));else{let a=e[Symbol.asyncIterator];if(typeof a!="function")return;let c=await Fl(a.bind(e),r,o);c.length>0&&(i=c)}if(i===void 0)return;if((typeof i=="string"?Buffer.byteLength(i,"utf8"):i.byteLength)>r)throw wn(r);return typeof i=="string"?i:i}function z(e){e.resume?.()}async function Ue(e,n={}){let t=Bl(e,"host")??"localhost",r=e.protocol??"http",o=e.originalUrl??e.url??"/",i=`${r}://${t}${o}`,s=new Headers;for(let[l,u]of Object.entries(e.headers))if(u!=null&&!$l.has(l.toLowerCase()))if(Array.isArray(u))for(let d of u)s.append(l,d);else s.set(l,u);let a={method:(e.method??"GET").toUpperCase(),headers:s},c=await Nl(e,n);return c!==void 0&&(a.body=c,s.has("content-type")||s.set("content-type","application/json")),new Request(i,a)}async function J(e,n){typeof e.status=="function"?e.status(n.status):e.statusCode=n.status;let t=n.headers.getSetCookie();n.headers.forEach((o,i)=>{i!=="set-cookie"&&e.setHeader(i,o)}),t.length>0&&e.setHeader("set-cookie",t);let r=Buffer.from(await n.arrayBuffer());e.send?e.send(r):e.end?.(r)}var $l=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailer","transfer-encoding","upgrade","content-length"]);function ia(e,n){let t=$(e,n);return async(r,o,i)=>{try{let s=await t(await Ue(r,{maxBodyBytes:n?.maxBodyBytes,bodyStallTimeoutMs:n?.bodyStallTimeoutMs}));await J(o,s)}catch(s){if(s instanceof C&&o.headersSent!==!0){await J(o,pe(s)),z(r);return}z(r),i(s)}}}function Wl(e,n){let t=e[n];return Array.isArray(t)?t[0]:t}function jl(e){let n=(e.method??"GET").toUpperCase();if(n==="GET"||n==="HEAD"||e.body!==void 0||e.rawBody!==void 0)return;let t=Wl(e.headers,"content-type");if(!(!t||!t.includes("application/json"))&&!(e.raw.readableEnded!==!0&&e.raw.complete!==!0))throw new Error("corsair: Fastify consumed this JSON body before the corsair adapter could read it. Call registerCorsairRawBodyParser(app) before listen() so the original bytes reach the adapter verbatim (Hub signs deliveries over the exact bytes it sent).")}function sa(e){e.addContentTypeParser("application/json",{parseAs:"buffer"},(n,t,r)=>{n.rawBody=t;try{r(null,JSON.parse(t.toString("utf8")))}catch{r(Object.assign(new Error("Invalid JSON body"),{statusCode:400}))}})}function aa(e,n){let t=$(e,n);return async(r,o)=>{jl(r);let i={method:r.method??r.raw.method,url:r.url??r.raw.url,headers:r.headers,protocol:r.protocol,body:r.body,rawBody:r.rawBody,resume:r.raw.resume?.bind(r.raw),[Symbol.asyncIterator]:r.raw[Symbol.asyncIterator]?.bind(r.raw)};try{let s=await t(await Ue(i,{maxBodyBytes:n?.maxBodyBytes,bodyStallTimeoutMs:n?.bodyStallTimeoutMs}));o.hijack?.(),await J(o.raw,s)}catch(s){if(s instanceof C&&o.raw.headersSent!==!0&&o.hijack){o.hijack(),await J(o.raw,pe(s)),z(i);return}throw z(i),s}}}function ca(e,n){let t=$(e,n);return r=>t(r.req.raw)}function ua(e,n){let t=$(e,n);return{GET:t,POST:t,OPTIONS:t}}function la(e,n){let t=$(e,n);return async(r,o)=>{try{let i=await t(await Ue(r,{maxBodyBytes:n?.maxBodyBytes,bodyStallTimeoutMs:n?.bodyStallTimeoutMs}));await J(o,i)}catch(i){if(o.headersSent===!0){console.error("[corsair] management response failed after headers were sent:",i),o.end?.(),z(r);return}if(i instanceof C){await J(o,pe(i)),z(r);return}console.error("[corsair] management handler failed:",i),await J(o,x(500,{error:"internal_error"})),z(r)}}}function Zt(e,n){let t=$(e,n);return r=>t(r.request)}function da(e,n){let t=Zt(e,n);return{GET:t,POST:t,OPTIONS:t}}function pa(e,n){let t=Zt(e,n);return{loader:t,action:t}}function ga(e,n){let t=Zt(e,n);return{GET:t,POST:t,OPTIONS:t}}function fa(e,n){let t=Zt(e,n);return{GET:t,POST:t,OPTIONS:t}}function ya(e,n){let t=$(e,n);return async r=>{let o={method:r.node.req.method,url:r.node.req.url,headers:r.node.req.headers,protocol:r.node.req.protocol,body:r._body,rawBody:r.node.req.rawBody??r._rawBody,resume:r.node.req.resume?.bind(r.node.req),[Symbol.asyncIterator]:r.node.req[Symbol.asyncIterator]?.bind(r.node.req)};try{let i=await t(await Ue(o,{maxBodyBytes:n?.maxBodyBytes,bodyStallTimeoutMs:n?.bodyStallTimeoutMs}));await J(r.node.res,i)}catch(i){if(i instanceof C&&r.node.res.headersSent!==!0){await J(r.node.res,pe(i)),z(o);return}throw z(o),i}}}function ma(e,n){return $(e,n)}function ha(e){let n={[Kn]:e};return{ok:bt,tenants:{list:()=>mn(e),create:t=>Ct(e,t),get:t=>wt(e,t)},plugins:{list:()=>yn(e),get:t=>kt(e,t)},connectionStatus:{get:t=>vt(e,t?.tenantId)},permissions:{get:t=>Zi(e,t)},connect:{createLink:t=>Pt(n,e,t),resolve:t=>Rt(n,e,t),oauthCallback:t=>At(n,e,t)},disconnect:t=>Tt(e,t)}}async function ba(e,n,t,r,o="pending"){if(!e)return null;try{let i=Xe(),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 ql(e,n,t,r="pending"){try{let o=await e.$getAccountId();return ba(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as wa from"https";import*as Gt from"querystring";var Kl=["expires_in","refresh_token_expires_in"];function ka(e){let n={...e};for(let t of Kl){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function Zl(e){try{return ka(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=Gt.parse(e);return!n.access_token&&!n.error?null:ka({...n})}function lt(e,n,t,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,c)=>{let l={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let u=Gt.stringify(l),d={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json","Content-Length":Buffer.byteLength(u).toString()};s&&(d.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let p=wa.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){c(new Error(`Token exchange failed (${g.statusCode}): ${f}`));return}let h=Zl(f);h?a(h):c(new Error(`Token endpoint returned non-JSON response: ${f}`))})});p.on("error",g=>c(new Error(`Request failed: ${g.message}`))),p.write(u),p.end()})}async function Ca(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,[s,a,c]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(Cn({accessToken:s,expiresAt:a,forceRefresh:n?.forceRefresh}))return{accessToken:s,expiresAt:Number(a),refreshed:!1};if(!c)throw new E(o,"oauth_2");let l=await I({hub:r,path:"/oauth/refresh",body:{plugin:o,tenantId:i,refresh_token:c},parseResponse:en}),u=await vn(t,l,a);return{accessToken:l.access_token,expiresAt:u,refreshed:!0}}async function va(e){let{tokenUrl:n,refreshToken:t,clientSecret:r,clientId:o,tokenAuthMethod:i="body",bodyFormat:s="form",extraParams:a}=e,c={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&&(c.client_id=o),c.client_secret=r),s==="json"?l["Content-Type"]="application/json":l["Content-Type"]="application/x-www-form-urlencoded";let u=await fetch(n,{method:"POST",headers:l,body:s==="json"?JSON.stringify(c):new URLSearchParams(c)});if(!u.ok)throw new Error(`OAuth token refresh failed (${u.status}): ${await u.text()}`);let d=JSON.parse(await u.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 Ta(e,n){let t=await e.keys.get_integration_credentials(),r=`${n.plugin}:${e.tenantId}`;if(!t.client_secret){if(!e.hub)throw new E(n.plugin,"oauth_2");let l={keys:e.keys,hub:e.hub,plugin:n.plugin,tenantId:e.tenantId},u=g=>qn(e.keys,r,async()=>(await Ca(l,{forceRefresh:g})).accessToken);e._refreshAuth=()=>u(!0);let[d,p]=await Promise.all([e.keys.get_access_token(),e.keys.get_expires_at()]);return Cn({accessToken:d,expiresAt:p})?d:u(!1)}let o=t.client_secret,i=t.client_id,s=l=>qn(e.keys,r,async()=>{let[u,d,p]=await Promise.all([e.keys.get_access_token(),e.keys.get_expires_at(),e.keys.get_refresh_token()]);if(!l&&Cn({accessToken:u,expiresAt:d}))return u;if(!p)throw new E(n.plugin,"oauth_2");let g=await va({tokenUrl:n.tokenUrl,tokenAuthMethod:n.tokenAuthMethod,bodyFormat:n.bodyFormat,extraParams:n.extraParams,clientId:i,clientSecret:o,refreshToken:p});return await vn(e.keys,g,d),g.access_token});e._refreshAuth=()=>s(!0);let[a,c]=await Promise.all([e.keys.get_access_token(),e.keys.get_expires_at()]);return Cn({accessToken:a,expiresAt:c})?a:s(!1)}var Pa=" ";function se(e){let n=e;return n._def??n.def??{}}function ae(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 ie(e){return e.innerType??e.schema??e.out??e.in}function Aa(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 ie(e)}}function xa(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Jt(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Pn(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 Ia(e,n){return e.description??n.description}function Gl(e){let n=e;for(;n;){let t=se(n),r=Ia(n,t);if(r)return r;let o=ae(t);if(Ho(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=Aa(t,o);continue}break}}function Ho(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function V(e){let n=se(e),t=ae(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??Pn(n)[0]??"unknown");case"ZodEnum":return Pn(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=ie(n);return r?V(r):"unknown"}case"ZodNullable":{let r=ie(n);return`${r?V(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=ie(n);return r?V(r):"unknown"}case"ZodArray":{let r=xa(n);if(!r)return"unknown[]";let o=se(r),i=ae(o)==="ZodUnion",s=V(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Jt(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let c=ae(se(a));return`${c==="ZodOptional"||c==="ZodNullable"?s+"?":s}: ${V(a)}`}).join(", ")} }`}case"ZodUnion":return Pn(n).map(r=>V(r)).join(" | ");case"ZodIntersection":return`${V(n.left)} & ${V(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=Aa(n,t);return r?V(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function Te(e){let n=se(e),t=ae(n),r=Ia(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??Pn(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=Pn(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=ie(n),i=o?Te(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=ie(n),i=o?Te(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=ie(n);return o?{...Te(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=xa(n);return{kind:"array",optional:!1,description:r,items:o?Te(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=Jt(e,n),i={};for(let[s,a]of Object.entries(o))i[s]=Te(a);return{kind:"object",optional:!1,description:r,fields:i}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let o=Pn(n);for(let i of o){let s=se(i);if(ae(s)==="ZodObject")return{...Te(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=ie(n);return o?{...Te(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function OC(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(u=>u.id===o);if(!s)return null;let a=i;a.startsWith("api.")&&(a=a.slice(4));let c=Fe(s.endpointMeta,a),l=Fe(s.endpointSchemas,a);return!c&&!l?null:{input:l?.input?Te(l.input):null,output:l?.output?Te(l.output):null,description:c?.description}}var Bo=["equals","contains","startsWith","endsWith","in"],zl=["equals","gt","gte","lt","lte","in"],Jl=["equals"],Vl=["equals","before","after","between"];function Sa(e){let n=se(e);switch(ae(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=ie(n);return r?Sa(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Uo(e){let n=se(e),t=ae(n);if(Ho(t)){let i=ie(n);return i?Uo(i):{}}if(t!=="ZodObject")return{};let r=Jt(e,n),o={};for(let[i,s]of Object.entries(r)){let a=Sa(s);a==="string"?o[i]={type:"string",operators:Bo}:a==="number"?o[i]={type:"number",operators:zl}:a==="boolean"?o[i]={type:"boolean",operators:Jl}:a==="date"&&(o[i]={type:"date",operators:Vl})}return o}function _a(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Do(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"&&Do(o,i,t)}}function Oo(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Mo(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];Oo(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&Mo(o,i,t)}}function Fo(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 Oo(s)?[i]:null;if(s!==null&&typeof s=="object"&&!Oo(s)){let a=Fo(s,r);if(a!==null)return[i,...a]}return null}function Ea(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 Yl=new Set(zn);function Qe(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 Yl.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:Qe(e);if(t==="webhooks"){if(!i.webhooks)return[];let a=[];return Mo(i.webhooks,[],a),a.map(c=>`${i.id}.webhooks.${c}`)}if(t==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(c=>`${i.id}.db.${c}.search`):[]}if(!i.endpoints)return[];let s=[];return Do(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=[];Mo(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=[];Do(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function Fe(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function Ql(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 Eo(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 MC(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 u=i.slice(3),d=u.lastIndexOf(".");if(d!==-1){let p=u.slice(0,d),g=u.slice(d+1),f=s.schema?.entities;if(g==="search"&&f){let h=_a(f,p);if(h){let[b,k]=h,v=Uo(k),P=[`Search ${o} ${b} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${Bo.join(", ")}]`];for(let[O,D]of Object.entries(v))P.push(` ${O}?: ${D.type} [${D.operators.join(", ")}]`);return P.push("}"),P.join(`
|
|
54
|
+
`)}}}return Eo(Qe(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let u=i.slice(9);if(s.webhooks){let d=Fo(s.webhooks,u.split("."));if(d!==null){let p=d.join("."),g=Fe(s.webhookSchemas,p.toLowerCase()),f=g?.response?V(g.response):null,h=[];return g?.description&&h.push(g.description),g?.payload&&h.push(`payload ${zt(Rn(g.payload))}`),f&&h.push(`response: ${f}`),h.push(`usage:
|
|
55
|
+
${Ea(o,d)}`),h.join(`
|
|
56
|
+
|
|
57
|
+
`)}}return Eo(Qe(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let c=Fe(s.endpointMeta,a),l=Fe(s.endpointSchemas,a);if(c||l){let u=[],d=[c?.riskLevel?`[${c.riskLevel}]`:"",c?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),p=[c?.description,d].filter(Boolean).join(" ");return p&&u.push(p),l?.input&&u.push(`input ${zt(Rn(l.input))}`),l?.output&&u.push(`output ${zt(Rn(l.output))}`),u.join(`
|
|
58
|
+
|
|
59
|
+
`)}}}return Eo(Qe(e),"Path not found. Available operations")}function Ra(e){let n=e;for(;;){let t=se(n),r=ae(t);if(Ho(r)){let o=ie(t);if(!o)return n;n=o;continue}return n}}function Rn(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=Ra(e),t=se(n);if(ae(t)==="ZodObject"){let o=Jt(n,t),i=[];for(let[s,a]of Object.entries(o)){let c=se(a),l=ae(c),u=l==="ZodOptional"||l==="ZodNullable",d=Ra(a),p=Gl(a);i.push({key:s,optional:u,type:V(d),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:V(n)}}function zt(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=Pa.repeat(n+1),r=Pa.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 Xl(e,n){let t=Qe(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(u=>u.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let u of t){let{shortPath:d,lookupKey:p}=Ql(u,n),g=Fe(r.endpointMeta,p),f=Fe(r.endpointSchemas,p);!g&&!f||o.push({path:u,shortPath:d,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:Rn(f?.input),output:Rn(f?.output)})}o.sort((u,d)=>u.path.localeCompare(d.path));let i=[],s=Qe(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let u of s){let p=u.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),h=Fo(r.webhooks,f.split("."));if(h===null)continue;let b=h.join("."),k=Fe(r.webhookSchemas,b.toLowerCase()),v=k?.response?V(k.response):void 0;i.push({path:u,description:k?.description,payload:Rn(k?.payload),responseType:v,usageExample:Ea(n,h)})}i.sort((u,d)=>u.path.localeCompare(d.path));let a=[],c=Qe(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(c)&&l)for(let u of c){let p=u.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 b=f.slice(0,h);if(f.slice(h+1)!=="search")continue;let v=_a(l,b);if(!v)continue;let[P,O]=v,D=Uo(O),M=Object.entries(D).map(([w,R])=>({field:w,type:R.type,operators:R.operators}));a.push({path:u,entityName:P,filters:[{field:"entity_id",type:"string",operators:Bo},...M]})}return a.sort((u,d)=>u.path.localeCompare(d.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as Da}from"crypto";async function ed(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=Da(),o=Da(),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 nd}from"crypto";var Vt="https://graph.microsoft.com/v1.0",Lo=2e4,td=60;async function rd(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let c=await fetch(`${Vt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(Lo)});if(c.ok){let{value:l}=await c.json(),u=(l??[]).filter(d=>d.notificationUrl===n.webhookUrl);await Promise.all(u.map(d=>fetch(`${Vt}/subscriptions/${d.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(Lo)}).catch(()=>{})))}}catch{}let o=nd(),i=new Date(Date.now()+td*6e4).toISOString(),s=await fetch(`${Vt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(Lo),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 Oa(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function od(e,n){let t=Oa(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 id(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function Ma(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Ha(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 Zn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function sd(e){return Zn(e.body)}function Ba(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return Yt(Array.isArray(r)?r:[r])}function Ua(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let l=Yt(Array.isArray(c)?c:[c]);if(l)return decodeURIComponent(l)}let r=Ba({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 c of o){let l=n[c],u=Array.isArray(l)?l[0]:l;if(!(!u||typeof u!="string"))try{let p=(u.startsWith("http")?new URL(u):new URL(`https://example.invalid${u.startsWith("/")?u:`/${u}`}`)).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=Zn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return Yt([s?.validationToken])??null}function ad(e){if(Ua(e))return!0;let n=Zn(e.body??e.payload);return Ma(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function Yt(e){for(let n of e){let t=Ha(n);if(t)return t}}function cd(e){let t=Zn(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Kn=Symbol.for("corsair:internal");function $a(e){if(e.hub?.projectApiKey?.startsWith("ck_cloud_")&&Gs(e.hub))return Js(e);let n=e.database?qo(e.database):void 0,t=e.kek??"",r=n&&t?Ws(e.plugins,n,t):jt(!!n,!!t),o=Vs(e),i={plugins:e.plugins,database:n,kek:t,multiTenancy:!!e.multiTenancy,permissions:o,manual:e.manual,hub:e.hub?nt(e.hub):void 0},s=Ni(n),a=ha(i);if(e.multiTenancy){let u=Object.assign({withTenant:d=>{if(!d)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let p=xo(e.plugins,{database:n,tenantId:d,kek:t,rootErrorHandlers:e.errorHandlers,permissionsOptions:o,manualConfig:e.manual,hubConfig:i.hub,internalConfig:i});return Object.assign(p,{[Kn]:i})},keys:r,permissions:s,manage:a},{[Kn]:i});return Fa(u,i.hub),Na(u,i.hub),u}let c=xo(e.plugins,{database:n,tenantId:void 0,kek:t,rootErrorHandlers:e.errorHandlers,permissionsOptions:o,manualConfig:e.manual,hubConfig:i.hub,internalConfig:i}),l=Object.assign({},c,{keys:r,permissions:s,manage:a,[Kn]:i});return Fa(l,i.hub),Na(l,i.hub),l}function Fa(e,n){n?.projectApiKey?.startsWith("ck_dev_")&&import("./loop-ZYFJTNGJ.js").then(t=>t.startConnectLoop(e)).catch(()=>{})}function ud(e){return e?.projectApiKey?.startsWith("ck_dev_")?e.tunnel!==!1&&process.env.CORSAIR_TUNNEL!=="0":!1}var La=globalThis.__corsairTunnels??=new Set,ld=1e3,dd=3e4;function pd(e){let n=e.schedule??((s,a)=>void setTimeout(s,a).unref?.()),t=e.minDelayMs??ld,r=e.maxDelayMs??dd,o=t,i=()=>{let s=!1,a=()=>{s||(s=!0,n(i,o),o=Math.min(o*2,r))};e.start(a).then(()=>{o=t}).catch(a)};i()}function Na(e,n){if(!ud(n))return;let t=n.projectApiKey;if(La.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}La.add(t);let o=typeof n.tunnel=="object"?n.tunnel:{},i=process.env.CORSAIR_FRP_HOST??o.shareHost??tr;pd({start:s=>import("./hub/tunnel/run-tunnel.js").then(a=>a.runTunnel({port:r,apiUrl:n.apiUrl,apiKey:t,shareHost:i,onClose:s})).then(({url:a})=>{console.log(`[corsair] tunnel active: ${a}${rr}`)}).catch(a=>{throw console.warn(`[corsair] tunnel down: ${a instanceof Error?a.message:String(a)}. Retrying \u2014 run \`corsair setup\` if it doesn't recover.`),a})})}var gd={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:{}}}},No=gd;async function dt(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=Zo(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 c=Rd(e,a.plugins,n),l={...a,database:a.database},u=l.database.db;await Id(u,i);let d=await Sd(u,l,c.tenantId,c.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await Dd(e,c,n.credentials,l,o,i);let p=await Md(d,c,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let g=$a({plugins:a.plugins,database:u,kek:a.kek,multiTenancy:!0}).withTenant(c.tenantId);await Hd(g,a.plugins,p,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
|
|
63
|
+
`)}function $o(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...j[n][t],...r])}function Pd(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=S(o);if(!i)continue;let s=$o(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function Rd(e,n,t){let r=Go(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&&Pd(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 ja(e,n){return xe(e)?n===0?!0:Object.values(e).every(t=>ja(t,n-1)):!1}function Ad(e){return ja(e,4)}var xd=Jo;function Qt(e){if(e instanceof kd){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Td?Qt(r):"unknown";return n}return e instanceof hd?`${Qt(e.unwrap())} | null`:e instanceof wd?`${Qt(e.unwrap())} | undefined`:e instanceof md?e.options.join(" | "):e instanceof vd?"string":e instanceof bd?"number":e instanceof fd?"boolean":e instanceof yd?"date":e instanceof Cd?"jsonb":"unknown"}async function Id(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(xd))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
|
|
64
|
+
Schema: ${JSON.stringify(Qt(i),null,2)}`)}async function Sd(e,n,t,r,o){let i=new Date,s=new Map;for(let a of n.plugins){let c=a.id,l=S(a),u=await e.selectFrom("corsair_integrations").selectAll().where("name","=",c).executeTakeFirst();if(!u){let h=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:h,name:c,config:{},created_at:i,updated_at:i}).execute(),u=await e.selectFrom("corsair_integrations").selectAll().where("id","=",h).executeTakeFirst(),o(`[corsair:setup] Created integration: ${c}`)}let d=l?a.authConfig?.[l]?.integration??[]:[],p=l?a.authConfig?.[l]?.account??[]:[],g=l&&u?F({authType:l,integrationName:c,kek:n.kek,database:n.database,extraIntegrationFields:d}):void 0;if(u&&!u.dek&&g&&(await g.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${c}`)),!u||!l||!g)continue;let f;if(r){let h=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",u.id).executeTakeFirst();if(!h){let b=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:b,tenant_id:t,integration_id:u.id,config:{},created_at:i,updated_at:i}).execute(),h=await e.selectFrom("corsair_accounts").selectAll().where("id","=",b).executeTakeFirst(),o(`[corsair:setup] Created account: ${c}`)}f=h&&B({authType:l,integrationName:c,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: ${c}`))}s.set(c,{pluginId:c,authType:l,integration:g,account:f,integrationFields:[...j[l].integration,...d],accountFields:r?[...j[l].account,...p]:[]})}return s}function _d(e){if(!xe(e))return;let n=e.keys;return xe(n)?n:void 0}function Ed(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function Dd(e,n,t,r,o,i){let s=_d(e),a=n.provisionAccounts?Ed(e,n.tenantId):void 0;for(let[c,l]of Object.entries(t)){let u=r.plugins.find(k=>k.id===c);if(!u){i(`[corsair:setup] Unknown plugin '${c}' \u2014 skipping credentials.`);continue}let d=S(u);if(!d){i(`[corsair:setup] Plugin '${c}' has no auth type \u2014 skipping credentials.`);continue}let p=$o(u,d,"integration"),g=$o(u,d,"account"),f=s?.[c],h=a?.[c],b=xe(h)?h.keys:void 0;for(let[k,v]of Object.entries(l))if(v){if(p.has(k)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${c}.${k}' 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=Q(f,`set_${k}`);if(!P){i(`[corsair:setup] Cannot set integration field '${k}' for '${c}'.`);continue}await P(v),o(`[corsair:setup] Set ${c} integration.${k}`);continue}if(g.has(k)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${c}.${k}' on a multi-tenant instance`);let P=Q(b,`set_${k}`);if(!P){i(`[corsair:setup] Cannot set account field '${k}' for '${c}'.`);continue}await P(v),o(`[corsair:setup] Set ${c} account.${k} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${k}' for plugin '${c}'.`)}}}var Wa=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Od(e,n,t,r,o,i,s,a,c){let l=[],u=[];for(let p of o){if(Wa.has(p))continue;let g=Q(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(Wa.has(p))continue;let g=Q(r,`get_${p}`);if(!g)continue;let f=null;try{let h=await g();f=typeof h=="string"?h:null}catch{}f||u.push(p)}let d=l.length===0&&u.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,...u];if(c==="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 u){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 Md(e,n,t,r){let o=new Set;for(let i of e.values())await Od(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function Hd(e,n,t,r,o){if(!Ad(No)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=No,s=new Set(n.map(a=>a.id));for(let[a,c]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=xe(e)?e[a]:void 0,u=xe(l)?l.api:void 0;if(u)for(let[d,p]of Object.entries(c))for(let[g,f]of Object.entries(p)){r(`[corsair:setup] Backfilling ${a} \u203A ${d}.${g}...`);try{let h=xe(u)?u[d]:void 0;await Q(h,g)?.(f)}catch(h){o(`[corsair:setup] ${a} \u203A ${d}.${g} failed: `+(h instanceof Error?h.message:String(h)))}}}}export{Vo as a,Ie as b,ye as c,Jn as d,Vn as e,Yn as f,en as g,Yo as h,Qn as i,lr as j,xn as k,oi as l,ii as m,Se as n,$e as o,me as p,tn as q,rn as r,_e as s,pr as t,ai as u,_n as v,he as w,En as x,gr as y,nt as z,U as A,tt as B,on as C,be as D,ke as E,X as F,fr as G,Dn as H,Ee as I,de as J,On as K,F as L,B as M,fi as N,yi as O,dt as P,Dd as Q,Oe as R,mr as S,cn as T,ln as U,br as V,ut as W,Ri as X,Ke as Y,Z,kr as _,Bn as $,Si as aa,xc as ba,pt as ca,Jg as da,Di as ea,Oi as fa,Mi as ga,Hi as ha,gt as ia,wr as ja,yt as ka,mt as la,Me as ma,fn as na,Ar as oa,Li as pa,xr as qa,Mr as ra,Hr as sa,xt as ta,Br as ua,hn as va,bn as wa,It as xa,St as ya,Un as za,Ur as Aa,Fr as Ba,_t as Ca,Fn as Da,Et as Ea,Dt as Fa,Be as Ga,kn as Ha,Qi as Ia,jr as Ja,qr as Ka,Ge as La,$n as Ma,Wn as Na,Lt as Oa,Gr as Pa,jn as Qa,Mu as Ra,Lu as Sa,Wu as Ta,cs as Ua,us as Va,ls as Wa,ds as Xa,ze as Ya,Je as Za,Yr as _a,Qr as $a,Xr as ab,eo as bb,no as cb,Ve as db,E as eb,to as fb,hs as gb,bs as hb,ro as ib,oo as jb,io as kb,so as lb,ao as mb,co as nb,uo as ob,lo as pb,po as qb,go as rb,fo as sb,yo as tb,mo as ub,ho as vb,bo as wb,Ye as xb,kl as yb,$ as zb,ia as Ab,sa as Bb,aa as Cb,ca as Db,ua as Eb,la as Fb,da as Gb,pa as Hb,ga as Ib,fa as Jb,ya as Kb,ma as Lb,ba as Mb,ql as Nb,lt as Ob,Ta as Pb,OC as Qb,Qe as Rb,MC as Sb,zt as Tb,Xl as Ub,ed as Vb,Vt as Wb,rd as Xb,Oa as Yb,od as Zb,id as _b,Ma as $b,Ha as ac,Zn as bc,sd as cc,Ba as dc,Ua as ec,ad as fc,Yt as gc,cd as hc,Kn as ic,$a as jc,ud as kc,pd as lc};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s="api.corsair.cloud",n=new Set(["localhost","127.0.0.1","[::1]","::1"]);function a(r){if(!r.startsWith("ck_cloud_"))return null;let o=r.slice(9),t=o.indexOf(".");if(t<=0)return null;let e=o.slice(0,t);return/^[a-z0-9]+$/.test(e)?`https://${s}/${e}/api/corsair`:null}function l(r,o="Cloud base URL"){let t;try{t=new URL(r)}catch{throw new Error(`${o} is not a valid URL: "${r}"`)}if(t.search||t.hash)throw new Error(`${o} must not contain a query or fragment (got "${r}") \u2014 path segments are appended to it.`);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&n.has(t.hostname)))throw new Error(`${o} must use https:// (got "${r}") \u2014 http:// is only allowed for localhost/127.0.0.1, since the project key is sent as a bearer token.`)}export{a,l as b};
|
|
@@ -154,6 +154,8 @@ type CorsairManagementClient = {
|
|
|
154
154
|
ok: true;
|
|
155
155
|
}>;
|
|
156
156
|
};
|
|
157
|
+
/** Invoke a plugin op via `POST /:tenant/:plugin/call/:op`. Returns the op's result. */
|
|
158
|
+
call: <T = unknown>(plugin: string, op: string, tenantId: string, args?: unknown) => Promise<T>;
|
|
157
159
|
};
|
|
158
160
|
|
|
159
161
|
/** Props for {@link CorsairProvider}. */
|
|
@@ -332,4 +334,21 @@ declare function createCorsairReactClient(opts: CorsairReactClientOptions): {
|
|
|
332
334
|
};
|
|
333
335
|
};
|
|
334
336
|
|
|
335
|
-
|
|
337
|
+
type ApiResult<T> = AsyncState<T> & {
|
|
338
|
+
refetch: () => void;
|
|
339
|
+
};
|
|
340
|
+
type UseCorsairResult = {
|
|
341
|
+
/**
|
|
342
|
+
* `pluginOp` splits on the first `.`: plugin is the segment before it, op is
|
|
343
|
+
* everything after (e.g. `"notion.pages.searchPage"` → plugin `notion`, op
|
|
344
|
+
* `pages.searchPage`). Tenant defaults to `'default'`.
|
|
345
|
+
*/
|
|
346
|
+
useApi: <T = unknown>(pluginOp: string, args?: unknown, opts?: {
|
|
347
|
+
tenantId?: string;
|
|
348
|
+
}) => ApiResult<T>;
|
|
349
|
+
/** Reserved for a future typed query layer — no `/db` route exists yet. */
|
|
350
|
+
db: undefined;
|
|
351
|
+
};
|
|
352
|
+
declare function useCorsair(): UseCorsairResult;
|
|
353
|
+
|
|
354
|
+
export { type ApiResult, type AsyncState, type ConnectAppearance, type ConnectLink, type ConnectTheme, type ConnectionStatus, CorsairErrorBoundary, type CorsairErrorBoundaryProps, CorsairProvider, type CorsairProviderProps, type CorsairReactClientOptions, type CreateConnectLinkInput, type CreateTenantInput, type OAuthCallbackInput, type OAuthCallbackResult, type PermissionLookupInput, type PermissionRecord, type PluginConnectionState, type PluginInfo, type Tenant, type UseConnectionsResult, type UseCorsairResult, createCorsairReactClient, useConnections, useCorsair };
|