corsair 0.1.113 → 0.1.115

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.
Files changed (35) hide show
  1. package/dist/{browser-delivery-BJtn0HMO.d.ts → browser-delivery-DzIPy41I.d.ts} +1 -1
  2. package/dist/chunk-3EPM4FJ3.js +1 -0
  3. package/dist/chunk-YDI4KN5B.js +66 -0
  4. package/dist/client/react/index.d.ts +3 -3
  5. package/dist/connect-LFLJCALJ.js +1 -0
  6. package/dist/core.d.ts +6 -6
  7. package/dist/core.js +1 -1
  8. package/dist/http.js +1 -1
  9. package/dist/hub/tunnel/run-tunnel.d.ts +39 -0
  10. package/dist/hub/tunnel/run-tunnel.js +4 -0
  11. package/dist/hub.d.ts +32 -14
  12. package/dist/hub.js +1 -1
  13. package/dist/{index-CsNw9hYU.d.ts → index--jxBUCjh.d.ts} +2 -2
  14. package/dist/{index-B_P6rcu8.d.ts → index-BjzfHSPn.d.ts} +3 -2
  15. package/dist/{index-DcJhvFt7.d.ts → index-By4SUsQO.d.ts} +17 -1
  16. package/dist/index.d.ts +10 -10
  17. package/dist/index.js +1 -1
  18. package/dist/loop-I2YLSQ54.js +1 -0
  19. package/dist/oauth.d.ts +2 -2
  20. package/dist/oauth.js +1 -1
  21. package/dist/setup-HUAVSMIY.js +1 -0
  22. package/dist/setup-introspect-46SQYJEX.js +1 -0
  23. package/dist/setup.d.ts +3 -3
  24. package/dist/setup.js +1 -1
  25. package/dist/{tenant-match-utils-Dq3dd_Zs.d.ts → tenant-match-utils-B-L5MHWg.d.ts} +2 -2
  26. package/dist/tunnel.d.ts +5 -5
  27. package/dist/tunnel.js +1 -1
  28. package/dist/{types-C24LhkXl.d.ts → types-3hs1SH6L.d.ts} +32 -2
  29. package/dist/{types-Dt339hBs.d.ts → types-Ca25_1ZL.d.ts} +1 -1
  30. package/package.json +9 -2
  31. package/scripts/postinstall-frpc.mjs +113 -0
  32. package/dist/chunk-VOB4G3KC.js +0 -66
  33. package/dist/connect-ZMHBC56U.js +0 -1
  34. package/dist/setup-H43JR2HU.js +0 -1
  35. package/dist/setup-introspect-SO3DTCV6.js +0 -1
@@ -1,4 +1,4 @@
1
- import { B as BrowserDeliveryPayload } from './index-CsNw9hYU.js';
1
+ import { B as BrowserDeliveryPayload } from './index--jxBUCjh.js';
2
2
 
3
3
  /**
4
4
  * Browser (client) delivery — hub redirects the user's browser to the app with `?d=<token>`.
@@ -0,0 +1 @@
1
+ var i="3000",s="/api/corsair";function c(r){return r.replace(/\/$/,"")}function m(r){let t=r?.deliveryUrl?.trim()||process.env.CORSAIR_DELIVERY_URL?.trim();if(t){let n=/^https?:\/\//i.test(t)?t:`https://${t}`;return c(n)}return`http://localhost:${process.env.PORT?.trim()||i}${s}`}var _="corsair.cloud",d="/api/corsair";import{existsSync as o}from"fs";import{homedir as p}from"os";import{join as a}from"path";var f="0.71.0";function e(){return`${process.platform}-${process.arch}`}function l(){return process.platform==="win32"?"frpc.exe":"frpc"}function u(){return a(p(),".cache","corsair","frpc",f,e(),l())}function E(){let r=process.env.CORSAIR_FRP_BIN;if(r&&o(r))return r;let t=u();if(o(t))return t;throw new Error(`frpc binary not found for ${e()}. If you use pnpm, run \`pnpm approve-builds corsair\` (or add corsair to onlyBuiltDependencies) and reinstall; otherwise reinstall corsair, or set CORSAIR_FRP_BIN to an frpc path (https://github.com/fatedier/frp/releases).`)}export{m as a,_ as b,d as c,f as d,e,E as f};
@@ -0,0 +1,66 @@
1
+ import{a as ye,b as St,c as _t}from"./chunk-3EPM4FJ3.js";import{a as uo,b as fe,c as co,d as w,e as U,f as lo,g as N,h as F,i as P,j as An,k as po,l as go,m as It,n as fo,o as yo}from"./chunk-WDF3YE27.js";import{a as ao}from"./chunk-IGGCNGU2.js";import{ZodBoolean as yc,ZodDate as mc,ZodEnum as hc,ZodNullable as bc,ZodNumber as kc,ZodObject as wc,ZodOptional as Cc,ZodRecord as vc,ZodString as Tc,ZodType as Pc}from"zod";var xn=["abstract","activetrail","addresszen","affinda","agencyzoom","agentmail","agenty","agentql","ahrefs","aimlapi","airtable","alchemy","algolia","alphavantage","alttextai","amara","ambientweather","ambee","amcards","amplitude","apibible","apify","apilabz","apisports","asana","ayrshare","bitwarden","bluesky","boloforms","box","canvas","cal","calendly","canva","cloudflare","cloudinary","confluence","cursor","databricks","datadog","deepseek","digitalocean","discord","dockerhub","dodopayments","dropbox","epicgames","exa","facebook","figma","firecrawl","fireflies","gemini","github","gitlab","gmail","googlebigquery","googlecalendar","googledocs","googledrive","googlemaps","googlemeet","googlesheets","grafana","hackernews","harvest","hashnode","heygen","hubspot","huggingface","insightoai","instagram","intercom","jira","linear","linkedin","loyverse","mailchimp","monday","neon","notion","ocrspace","ollama","onedrive","onepassword","openai","openweathermap","oura","outlook","pagerduty","perplexityai","posthog","razorpay","reddit","resend","retailed","salesforce","sentry","sharepoint","slack","spotify","strava","stripe","supabase","tally","tavily","teams","telegram","todoist","toggl","trello","twilio","twitter","twitterapiio","twochat","typeform","vapi","vercel","whatsapp","wiza","workday","xquik","youcom","youtube","zendesk","zohomail","zoom"],mo={abstract:"Abstract",activetrail:"Active Trail",addresszen:"Addresszen",affinda:"Affinda",agencyzoom:"AgencyZoom",agentmail:"AgentMail",agenty:"Agenty",agentql:"AgentQL",ahrefs:"Ahrefs",aimlapi:"AI/ML API",airtable:"Airtable",alchemy:"Alchemy",algolia:"Algolia",alphavantage:"Alpha Vantage",alttextai:"AltText.ai",amara:"Amara",ambientweather:"Ambient Weather",ambee:"Ambee",amcards:"AMcards",amplitude:"Amplitude",apibible:"API.Bible",apify:"Apify",apilabz:"API Labz",apisports:"API-Sports",asana:"Asana",ayrshare:"Ayrshare",bitwarden:"Bitwarden",bluesky:"Bluesky",boloforms:"Boloforms",box:"Box",canvas:"Canvas LMS",cal:"Cal",calendly:"Calendly",canva:"Canva",cloudflare:"Cloudflare",cloudinary:"Cloudinary",confluence:"Confluence",cursor:"Cursor",databricks:"Databricks",datadog:"Datadog",deepseek:"DeepSeek",digitalocean:"DigitalOcean",discord:"Discord",dockerhub:"Docker Hub",dodopayments:"Dodo Payments",dropbox:"Dropbox",epicgames:"Epic Games",exa:"Exa",facebook:"Facebook",figma:"Figma",firecrawl:"Firecrawl",fireflies:"Fireflies",gemini:"Gemini",github:"GitHub",gitlab:"GitLab",gmail:"Gmail",googlebigquery:"Google BigQuery",googlecalendar:"Google Calendar",googledocs:"Google Docs",googledrive:"Google Drive",googlemaps:"Google Maps",googlemeet:"Google Meet",googlesheets:"Google Sheets",grafana:"Grafana",hackernews:"Hacker News",harvest:"Harvest",hashnode:"Hashnode",heygen:"HeyGen",hubspot:"HubSpot",huggingface:"Hugging Face",insightoai:"Insighto.ai",instagram:"Instagram",intercom:"Intercom",jira:"Jira",linear:"Linear",linkedin:"LinkedIn",loyverse:"Loyverse",mailchimp:"Mailchimp",monday:"Monday",neon:"Neon",notion:"Notion",ocrspace:"OCR.space",ollama:"Ollama",onedrive:"OneDrive",onepassword:"1Password",openai:"OpenAI",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",perplexityai:"Perplexity AI",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",resend:"Resend",retailed:"Retailed",salesforce:"Salesforce",sentry:"Sentry",sharepoint:"SharePoint",slack:"Slack",spotify:"Spotify",strava:"Strava",stripe:"Stripe",supabase:"Supabase",tally:"Tally",tavily:"Tavily",teams:"Teams",telegram:"Telegram",todoist:"Todoist",toggl:"Toggl",trello:"Trello",twilio:"Twilio",twitter:"Twitter",twitterapiio:"Twitter API IO",twochat:"TwoChat",typeform:"Typeform",vapi:"Vapi",vercel:"Vercel",whatsapp:"WhatsApp",wiza:"Wiza",workday:"Workday",xquik:"XQuik",youcom:"You.com",youtube:"YouTube",zendesk:"Zendesk",zohomail:"Zoho Mail",zoom:"Zoom"};function me(e){let n=mo[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}import{randomUUID as Os}from"crypto";var Rs="corsair:client-bridge";function Et(e){return new URL(e).origin}function Fe(e){let n=JSON.stringify({type:Rs,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(Et(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 Is=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Dt(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Is.has(n)}catch{return!1}}function rn(e){return e==="development"?"browser":"server"}function ho(e){return rn(e)==="browser"}function bo(e){return Dt(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as Ds}from"crypto";var he=60*1e3,Re=300*1e3;import{createHmac as Ss,randomBytes as _s,timingSafeEqual as Es}from"crypto";function ie(){return _s(16).toString("base64url")}function on(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Ss("sha256",t).update(e).digest("base64url")}function ee(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=on(o,t);try{if(!Es(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 Rn(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=on(i,n);return`${i}.${s}`}function sn(e,n,t){let r=Math.floor(Date.now()/1e3);return Rn(e,n,r+Math.floor(t/1e3))}function Ie(e){return decodeURIComponent(e)}function Ot(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function ko(e){let n=e.trim();return n.length>0?n:null}function Ue(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function Be(e,n){if(!ko(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??Ds(16).toString("base64url"),iat:t,exp:t+Math.floor(he/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=on(o,n);return`${o}.${i}`}function be(e,n){return ko(n)?ee(e,n):null}function Ms(e){let n=Et(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 Mt(e){let n=Be(Ms(e),e.signingSecret);return Ue(e.deliveryUrl,n)}function wo(e){if(rn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=Os(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:Mt(r)}}var an="https://auth.corsair.dev";var se=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function In(e){let n=(e.apiUrl?.trim()||an).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim();if(!t||!r)throw new Error("Hub config requires non-empty projectApiKey and signingSecret");return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,""),redirectURL:e.redirectURL?.trim()||void 0,allowWorkflowExecution:e.allowWorkflowExecution??!1,tunnel:e.tunnel}}function Hs(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function O(e){let n=w(e).hub;if(!n||!Hs(n))throw new se;return n}function Co(e){return e.replace(/\/$/,"")}function Sn(e){return e.oauthCallbackUrl?Co(e.oauthCallbackUrl.trim()):`${Co(e.apiUrl)}/oauth/callback`}function Le(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";throw new Error("Hub API key must start with ck_dev_ (development) or ck_prod_ (production)")}function x(e){return typeof e=="string"&&e.length>0}function Fs(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function Us(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function _n(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!x(n.connectUrl)||!x(n.token)||!x(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:x(n.environmentId)?n.environmentId:n.projectId};return x(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function En(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(!x(r.tenantId)||!x(r.plugin)||!Fs(r.status)||!Us(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:x(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function Dn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!x(n.approvalUrl)||!x(n.token)||!x(n.projectId)||!x(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 On(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(x(n.access_token))return{access_token:n.access_token,refresh_token:x(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:x(n.scope)?n.scope:void 0};throw new Error(x(n.error)?x(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Bs(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function Ls(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;x(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 Ns(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 vo(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!x(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(!x(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=Ls(o.fields),a=Bs(o.missingRequiredFields),u=Ns(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:x(o.providerName)?o.providerName:o.plugin,authKind:i,status:u,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function Mn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function To(e){return e.replace(/\/$/,"")}function Ht(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return ye()}catch{return null}}function Po(e){let n=Ht(e);return n?{"x-corsair-delivery-url":n}:{}}async function Ao(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 xo(e,n,t){if(n===404&&t)return t;let r=Mn(e);return r||`Hub API returned HTTP ${n}`}async function _(e){let n=To(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...Po(e.hub)},body:JSON.stringify(e.body)}),r=await Ao(t);if(!t.ok)throw new Error(xo(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function $(e){let n=To(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...Po(e.hub)}}),r=await Ao(t);if(!t.ok)throw new Error(xo(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as Ro,createDecipheriv as Io,randomBytes as Hn,scrypt as $s}from"crypto";import{promisify as Ws}from"util";var So=Ws($s),Fn="aes-256-gcm",_o=12,Un=16,js=16,un=32;function ae(){return Hn(un).toString("base64")}async function ue(e,n){let t=Hn(js),r=await So(n,t,un),o=Hn(_o),i=Ro(Fn,r,o,{authTagLength:Un}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[t.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function Z(e,n){let[t,r,o,i]=e.split(":");if(!t||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),u=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),c=await So(n,s,un),p=Io(Fn,c,a,{authTagLength:Un});return p.setAuthTag(u),Buffer.concat([p.update(l),p.final()]).toString("utf8")}function Ft(e,n){let t=Buffer.from(n,"base64"),r=Hn(_o),o=Ro(Fn,t,r,{authTagLength:Un}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function cn(e,n){let[t,r,o]=e.split(":");if(!t||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),u=Buffer.from(o,"base64"),l=Io(Fn,i,s,{authTagLength:Un});return l.setAuthTag(a),Buffer.concat([l.update(u),l.final()]).toString("utf8")}function ke(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Ft(o,n);return t}function ce(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=cn(o,n);return t}function ln(e,n,t){let r=ce(e,n);return ke(r,t)}function Eo(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 Ut=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function M(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...F[n].integration,...i],a=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let h=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!h)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:h.id,config:Ut(h.config),dek:h.dek??null},a},updateIntegration:async h=>{let m=await u.getIntegration();await o.db.updateTable("corsair_integrations").set({...h.config!==void 0?{config:h.config}:{},...h.dek!==void 0?{dek:h.dek}:{},updated_at:new Date}).where("id","=",m.id).execute(),a=null}},l=null,c=async()=>{if(l)return l;let h=await u.getIntegration();if(!h.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await Z(h.dek,r),l},p=async()=>{let h=await u.getIntegration(),m=await c(),k=h.config;return!k||Object.keys(k).length===0?{}:ce(k,m)},d=Promise.resolve(),g=h=>{let m=d.then(()=>f(h));return d=m.catch(()=>{}),m},f=async h=>{let m=await c(),k;try{k=await p()}catch(R){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,R),k={}}let C={...k};for(let[R,E]of Object.entries(h))E===null?delete C[R]:C[R]=E;let S=ke(C,m);await u.updateIntegration({config:S})};return{get_dek:c,issue_new_dek:async()=>{let h=await u.getIntegration(),m=ae(),k={};if(h.dek){let S=await Z(h.dek,r),R=h.config;R&&Object.keys(R).length>0&&(k=ln(R,S,m))}let C=await ue(m,r);return await u.updateIntegration({config:k,dek:C}),l=m,m},...Eo(p,g,s)}}function D(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,u=[...F[n].account,...s],l=null,c=null,p=async()=>{if(c)return c;let b=!1;for(;;){let v=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!v){if(!b&&a){b=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return c={id:v.id,config:Ut(v.config),dek:v.dek??null},c}},d={kek:o,integrationName:t,tenantId:r,getIntegration:p,getAccount:async()=>{if(l)return l;let b=!1;for(;;){let v=await p(),T=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",v.id).executeTakeFirst();if(!T){if(!b&&a){b=!0,await a();continue}throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`)}return l={id:T.id,config:Ut(T.config),dek:T.dek??null},l}},updateAccount:async b=>{let v=await d.getAccount();await i.db.updateTable("corsair_accounts").set({...b.config!==void 0?{config:b.config}:{},...b.dek!==void 0?{dek:b.dek}:{},updated_at:new Date}).where("id","=",v.id).execute(),l=null}},g=null,f=null,y=async()=>{if(g)return g;let b=await d.getAccount();if(!b.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await Z(b.dek,o),g},h=async()=>{if(f)return f;let b=await d.getIntegration();if(!b.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await Z(b.dek,o),f},m=async()=>{let b=await d.getAccount(),v=await y(),T=b.config;return!T||Object.keys(T).length===0?{}:ce(T,v)},k=async()=>{let b=await d.getIntegration(),v=await h(),T=b.config;return!T||Object.keys(T).length===0?{}:ce(T,v)},C=Promise.resolve(),S=b=>{let v=C.then(()=>R(b));return C=v.catch(()=>{}),v},R=async b=>{let v=await y(),T;try{T=await m()}catch(A){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,A),T={}}let j={...T};for(let[A,Y]of Object.entries(b))Y===null?delete j[A]:j[A]=Y;let re=ke(j,v);await d.updateAccount({config:re})},E={get_dek:y,issue_new_dek:async()=>{let b=await d.getAccount(),v=ae(),T={};if(b.dek){let re=await Z(b.dek,o),A=b.config;A&&Object.keys(A).length>0&&(T=ln(A,re,v))}let j=await ue(v,o);return await d.updateAccount({config:T,dek:j}),g=v,v},...Eo(m,S,u)};return n==="oauth_2"&&(E.get_integration_credentials=async()=>{let b=await k();return{...b,client_id:b.client_id||null,client_secret:b.client_secret||null,redirect_url:b.redirect_url??null}}),E}async function Do(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=ae(),i=await ue(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function Oo(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=ae(),a=await ue(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var Ks=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function we(e){return Ks.has(e)}function qs(e,n){return we(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Zs(e){return!we(e)}function Gs(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function zs(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function Js(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!Gs(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function Mo(e,n){if(!e)return!1;let t=N(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function Vs(e,n){let r=e.authConfig?.[n]?.integration??[];return[...F[n].integration,...r]}function Ys(e,n){let r=e.authConfig?.[n]?.account??[];return[...F[n].account,...r]}function Qs(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:Js(n,t),fields:t,missingRequiredFields:r}}async function Se(e,n,t){let r=P(n);if(!r||!e.database||!e.kek)return null;let o=t.trim()||"default",i=n.authConfig,s=i?.[r]?.integration??[],a=i?.[r]?.account??[],u=M({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=D({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),c=Vs(n,r),p=Ys(n,r),d=[];for(let g of c)d.push({name:g,level:"integration",required:qs(r,g),configured:await Mo(u,g)});for(let g of p)d.push({name:g,level:"account",required:Zs(g),configured:await Mo(l,g)});if(zs(r,d)){let g=d.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return Qs(n.id,r,d)}async function dn(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 Se(e,s,r);a&&i.push(a)}return i}function Bn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var Ho=Symbol.for("corsair:internal"),Fo=new WeakMap,Uo=new WeakMap;function Xs(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function ea(e){if(e.database){let t=Fo.get(e.database);return t||(t=new Map,Fo.set(e.database,t)),t}let n=Uo.get(e);return n||(n=new Map,Uo.set(e,n)),n}function na(e){return e.multiTenancy?{withTenant:()=>({}),[Ho]:e}:{[Ho]:e}}async function Ne(e,n){if(!e.database)return;let t=n.trim()||"default",r=ea(e),o=Xs(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-HUAVSMIY.js");await a(na(e),{tenantId:e.multiTenancy?t:void 0,silent:!0})})().finally(()=>{r.delete(o)});r.set(o,s),await s}import*as pn from"crypto";function Ce(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Bt(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 $e(e,n){let t=pn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Lt=600*1e3;function Ln(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=pn.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(o,"base64url"),a=Buffer.from(i,"base64url");return s.length!==a.length||!pn.timingSafeEqual(s,a)?null:Bt(r,{maxAgeMs:Lt})}function Bo(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function Lo(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 We(e,n){await _({hub:e,path:"/connections/report",body:Bo(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function ta(e,n){try{let t=O(e);_({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof se)return}}async function ra(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!P(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Se(n,e.plugin,r);o&&$o(e.hub,Lo({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function No(e,n){ta(e,n)}function $o(e,n){_({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function gn(e){ra(e).catch(()=>{})}async function le(e,n){let t=w(e);if(!P(n.plugin))return;let o=await Se(t,n.plugin,n.tenantId);o&&No(e,Lo({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 Nn(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 Wo=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function oa(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 ia(e){let n=await e.database.db.selectFrom("corsair_accounts").selectAll().where("id","=",e.accountId).executeTakeFirst();if(!n?.dek)throw new Error(`Account '${e.accountId}' has no DEK.`);let t=await Z(n.dek,e.kek),r=Wo(n.config),o={};Object.keys(r).length>0&&(o=ce(r,t)),o[e.link.linkType]=e.link.externalId;let i=ke(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function je(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:u}=await oa({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let c=D({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),p=`set_${i.linkType}`,d=c[p];typeof d=="function"&&(await d(i.externalId),l=!0)}l||await ia({database:n,kek:t,accountId:u,link:i})}async function Nt(e){let{database:n,kek:t,pluginId:r,linkType:o,externalId:i}=e,s=await n.db.selectFrom("corsair_accounts as accounts").innerJoin("corsair_integrations as integrations","integrations.id","accounts.integration_id").selectAll("accounts").where("integrations.name","=",r).execute();for(let a of s)if(a.dek)try{let u=await Z(a.dek,t),c=Wo(a.config)[o];if(!c)continue;if(cn(c,u)===i)return a}catch{continue}return null}async function $n(e){return(await Nt(e))?.tenant_id??null}async function jo(e){return $n({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as Ko from"querystring";function _e(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}?${Ko.stringify(i)}`}async function qo(e,n){try{return await $({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function Ke(e,n,t,r){if(!n.subscribe)return;let o=O(e),i=await qo(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await le(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var B=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Zo(e){let n=e.oauthConfig;if(!n)throw new B("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function sa(e,n,t,r){let o=yo(e),i=await o.integrations.findByName(n);if(!i)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.accounts.findOne({tenant_id:t,integration_id:i.id}))return;let a=ae(),u=await ue(a,r);await o.accounts.create({tenant_id:t,integration_id:i.id,config:{},dek:u})}async function $t(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=U(s,n,d=>new B("plugin_not_found",d)),u=Zo(a),c=await M({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!c)throw new Error(`client_id not configured for '${n}'`);if(i){let d=new URL(_e({oauthConfig:u,clientId:c,redirectUri:o,state:""}));return d.searchParams.delete("state"),{url:d.toString(),state:""}}let p=$e(Ce(n,r),s.kek);return{url:_e({oauthConfig:u,clientId:c,redirectUri:o,state:p}),state:p}}function aa(e,n){return{...n??{},...e}}async function fn(e,n){let{code:t,state:r,redirectUri:o}=n,i=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new B("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let y=Ln(r,i.kek);if(!y)throw new B("invalid_state","Invalid or tampered state parameter");s=y.plugin,a=y.tenantId}if(!i.database)throw new B("no_database","No database configured on corsair instance");let u=U(i,s,y=>new B("plugin_not_found",y)),l=Zo(u),c=M({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),p=await c.get_client_id(),d=await c.get_client_secret();if(!p||!d)throw new B("credentials_not_configured",`Credentials not configured for '${s}'`);await sa(i.database,s,a,i.kek);let g=await Wn(t,p,d,l,o);if(!g.access_token)throw new B("no_access_token",`No access_token returned from ${l.providerName}`);let f=D({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...u.authConfig?.oauth_2?.account??[]]});await f.set_access_token(g.access_token),g.refresh_token&&await f.set_refresh_token(g.refresh_token),g.expires_in&&await f.set_expires_at(String(Math.floor(Date.now()/1e3)+g.expires_in)),await le(e,{plugin:u,tenantId:a}).catch(()=>{});try{let y=aa(g,n.callbackParams),h=await Nn(i.plugins,s,y);if(h){try{let m=u.authConfig?.oauth_2?.account??[];await je({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:h,authType:"oauth_2",extraAccountFields:m})}catch(m){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,m)}i.hub&&We(i.hub,{plugin:s,tenantId:a,link:h,authType:"oauth_2"})}}catch(y){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,y)}if(u.subscribe)try{await Ke(e,u,a,f)}catch(y){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,y)}return{plugin:s,tenantId:a}}async function ua(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??Ke,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let u=t.plugins.find(c=>c.id===a.integrationName);if(!u?.subscribe)continue;let l=`${u.id}/${a.tenantId}`;try{let c=P(u)??"oauth_2",p=D({authType:c,integrationName:u.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...u.authConfig?.[c]?.account??[]]}),d=u.keyBuilder;if(d){let g=Object.create(p,{get_expires_at:{value:async()=>"0"}});await d({authType:c,keys:g,hub:t.hub},"endpoint")}await o(n,u,a.tenantId,p),i.push(l)}catch(c){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,c),s.push(l)}}return{renewed:i,failed:s}}async function Go(e){let n=w(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 ua({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function ca(e,n={}){let t=!1,r=()=>{t||(t=!0,Go(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 zo(e){if(!w(e).database)throw new Error("A database must be configured to provision Corsair integrations");await jn(e,{silent:!0})}async function qe(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await Ne(t,n)}var la=Symbol.for("corsair:internal"),da=new Set(["access_token","refresh_token","expires_at","scope"]);function pa(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function ga(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!we(t)&&!da.has(t)):n.filter(t=>!we(t))}function Jo(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function fa(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function ya(e){return{[la]:Jo(e)}}async function Kn(e,n,t={}){let r=Sn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Jo(e),a=ya(e);for(let u of e.plugins){if(i&&!i.has(u.id))continue;let l=P(u);if(!l)continue;let c=pa(l),p=t.providerNameOverrides?.[u.id]??me(u.id),d=await Se(s,u,n),g=An(u,l),f=ga(l,g),y={plugin:u.id,providerName:p,authKind:c,alreadyConfigured:d?.connected??!1};if(f.length>0&&(y.credentialFields=f),c==="oauth"){let m=t.oauthModeOverrides?.[u.id]??(l==="managed"?"managed":"byo");if(y.oauthMode=m,!t.skipOAuthUrlGeneration&&m!=="managed")try{let k=await $t(a,u.id,{tenantId:n,redirectUri:r,hubConnect:!0});y.oauthUrl=k.url}catch(k){y.setupError=k instanceof Error?k.message:`Could not prepare OAuth for ${u.id}`}}o.push(y)}return o}async function hd(e,n,t={}){let r=w(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return Kn({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function Vo(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await Ne(e.internalConfig??fa(e),n)}async function Yo(e,n){await qe(e,n)}async function Qo(e,n){let t=Le(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ye({deliveryUrl:n.deliveryUrl})),_({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:_n})}async function Wt(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await Vo(t,n.tenantId);let r=await Kn(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 Qo(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function qn(e,n){let t=w(e),r=O(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r,multiTenancy:t.multiTenancy,internalConfig:t};await Yo(e,n.tenantId);let i=n.plugin?[n.plugin]:void 0,s=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,a=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,u=await Kn(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(u.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return Qo(r,{tenantId:n.tenantId,plugins:u,deliveryUrl:n.deliveryUrl})}async function Zn(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=w(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 ma(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 ma(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-46SQYJEX.js"),{postHubConnectSession:i}=await import("./connect-LFLJCALJ.js"),s={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await o(s,t.tenantId);let a=await r(s,t.tenantId,{pluginIds:t.pluginIds});if(a.length===0)throw new Error("No connectable plugins found for this tenant");let u=a.find(l=>l.setupError);if(u)throw new Error(u.setupError??`Could not prepare connect link for ${u.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}function Ze(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var G=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function ha(e){let n=e.oauthConfig;if(!n)throw new G("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function jt(e,n){let t=w(e,()=>new G("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new G("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new G("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=Ln(n,t.kek);if(!o)throw new G("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=U(t,i,d=>new G("plugin_not_found",d)),u=ha(a),c=await M({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!c)throw new G("client_id_not_configured",`client_id not configured for '${i}'`);let p=_e({oauthConfig:u,clientId:c,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:u.providerName,oauthUrl:p,state:n}}import{AsyncLocalStorage as ka}from"async_hooks";import{randomBytes as wa}from"crypto";import{v4 as Ca}from"uuid";async function Gn(e,n){let t=Le(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=ye({deliveryUrl:n.deliveryUrl})),_({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:Dn})}function zn(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Kt="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 Zt(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Xo(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function qt(e){return zn(e)}async function Gt(e,n){if(Zt(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Xo(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await Gn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:ba(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function ba(e){try{return JSON.parse(e)}catch{return e}}async function Jn(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Gt(e,n);return{...n,approvalUrl:r}}async function zt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:u,tenantId:l,expiresAt:c,operationPath:p}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:u});let g=await Gt({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(u),tenant_id:l,expires_at:c});return Zt(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):qt(g):Kt:r?g?qt(g):`Action '${p}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Kt}var Ge=class extends Error{constructor(n){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError"}};var ni=new ka,Vn=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 Jt(e){return ni.run(!0,e)}function ti(){return ni.getStore()===!0}function Vt(e,n){if(ti()&&n!=="read")throw new Vn(e,n)}var va={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 Ta(e,n,t){return t!==void 0?t:va[n][e]}function Yt(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 ri(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 ei(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 oi(e){let n=Ta(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,y=a.id;return{result:"allow",onComplete:async()=>{await f.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",y).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"?ei(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let u=Ca(),l=wa(32).toString("hex"),c=e.timeoutMs??600*1e3,p=new Date(Date.now()+c).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:u,created_at:new Date,updated_at:new Date,token:l,plugin:e.pluginId,endpoint:e.endpointPath,args:o,tenant_id:s,status:"pending",expires_at:p}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
15
+ Action: ${r}`,`
16
+ Permission ID: ${u}`,`
17
+ Permission token: ${l}`,`
18
+ Expires at: ${p}`,`
19
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?ei(e.db,u,c):{result:"blocked",reason:"pending",id:u,token:l,expiresAt:p}}var I=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 H(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function ii(e){let n={error:e.code,message:e.message,...e.extra};return H(e.status,n)}function ve(e){return new I(404,"not_found",e)}function de(e,n={}){return new I(400,"bad_request",e,n)}function si(e,n){return U(e,n,t=>ve(t))}async function ai(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=M({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),o=F[t].integration,i=r,s;try{s=await Promise.all(o.map(l=>i[`get_${l}`]()))}catch{s=o.map(()=>null)}let a=o.filter((l,c)=>s[c]==null),u;return t==="oauth_2"?u=!a.includes("client_id")&&!a.includes("client_secret"):u=a.length===0,{configured:u,missingFields:a}}async function ui(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await ai(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 Yn(){return{ok:!0}}async function ze(e){return Promise.all(e.plugins.map(n=>ui(n,e)))}async function Qn(e,n){let t=si(e,n);return ui(t,e)}async function Pa(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 ci(e,n){let t=await Pa(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Je(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 Xn(e,n){if(!n)throw de("Tenant id must be a non-empty string");return ci(e,n)}async function et(e,n){let t=n?.id?.trim();if(!t)throw de("Tenant id is required",{missingFields:["id"]});return ci(e,t)}async function nt(e,n){let t=n?.trim()||"default",r={},o=await dn(e,t);for(let i of o)r[i.plugin]=Bn(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 Qt(e,n){if(!e.database)throw ve(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw ve(`Permission '${n}' not found`);return Jn(e,t)}function Aa(e){if(!e.oauthConfig)throw de(`Plugin '${e.id}' has no oauthConfig`)}function xa(e){if(!e.manual)throw new I(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Xt(e){let n=xa(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new I(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 Ra(e){let n=!!e.hub,t=Ze(e.manual);if(!n&&!t)throw new I(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function li(e){if(!e.database||!e.kek)throw new I(500,"database_not_configured","A database and kek are required to issue connect links.")}async function Ia(e,n){let t=n?.plugin?.trim();if(!t)throw de("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=si(e,t);Aa(o);let i=Xt(e);li(e);let s=await ai(o,e);if(!s.configured)throw new I(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=$e(Ce(t,r),e.kek),u;try{u=new URL(i.baseUrl)}catch{throw new I(500,"connect_misconfigured","manual.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return u.searchParams.set("state",a),{connectUrl:u.toString(),expiresAt:new Date(Date.now()+Lt).toISOString()}}async function Sa(e,n,t){li(n);let o={tenantId:t.tenantId?.trim()||"default",oauthMode:t.oauthMode},i=t.plugin?.trim();i&&(o.plugin=i);let s=t.providerName?.trim();s&&(o.providerName=s);let a=await qn(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt}}async function tt(e,n,t){return Ra(n),n.hub?Sa(e,n,t):Ia(n,t)}async function rt(e,n,t){if(n.hub&&!Ze(n.manual))throw new I(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw de("state is required",{missingFields:["state"]});Xt(n);try{return await jt(e,r)}catch(o){if(o instanceof G)switch(o.code){case"invalid_state":throw de("Invalid or expired state");case"client_id_not_configured":throw new I(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new I(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function ot(e,n,t){if(n.hub&&!Ze(n.manual))throw new I(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 de("Missing required fields",{missingFields:i});let s=Xt(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:o,redirectUri:s.redirectUri,callbackParams:t.callbackParams})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw de("Invalid or expired state");case"credentials_not_configured":throw new I(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new I(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function er(e,n){if(!e.database)throw ve("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw ve("Permission not found");return Jn(e,t)}async function di(e,n){return"id"in n?Qt(e,n.id):er(e,n.token)}import{createCipheriv as Fa,createDecipheriv as lp,randomBytes as yi,scryptSync as Ua}from"crypto";import{createHmac as nr,randomUUID as _a,timingSafeEqual as gi}from"crypto";function tr(e){return e.run??null}function rr(e){return e.probe??null}function fi(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function it(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=nr("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":_a()}}}function or(e){let n=e.signingSecret.trim();if(!n)return!1;let t=fi(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Re)return!1;let i=nr("sha256",n).update(e.body).digest("hex");try{return gi(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function Ve(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=fi(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)>Re)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=nr("sha256",n).update(e.body).digest("hex");try{if(!gi(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 Ye(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function st(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function at(e){let n=e.sync?.encrypted;return typeof n!="string"||!n.trim()?null:{encrypted:n.trim()}}function yn(e){let n=e.connectUrl?.trim();return n?{connectUrl:n,expiresAt:e.expiresAt}:null}function ir(e){return yn(Ye(e))}async function sr(e){let n=await lt({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=Ye(n.body),r=st({httpOk:n.ok,status:n.status,body:t}),o=yn(t);if(!r||!o)throw new Error(ct({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function ut(e){return at(Ye(e))}function Ea(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 pi(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var Da="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",Oa="Check the delivery URL configured for this environment.";function Ma(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})`}. ${Da}`}function Ha(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${Oa}`}function mn(e,n){let t=Ea(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 ct(e){if(e.status===0)return e.ack.error?e.ack.error:e.body.startsWith("Could not reach")?e.body:mn(e.deliveryUrl,new Error(e.body||"Delivery request failed"));if(e.status===401||e.status===403)return Ma(e);if(e.status===404)return Ha(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}): ${pi(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${pi(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}async function lt(e){let{body:n,headers:t}=it(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),o=await r.text();return{ok:r.ok,status:r.status,body:o}}catch(r){return{ok:!1,status:0,body:mn(e.deliveryUrl,r)}}}var Ba="aes-256-gcm",La=12,Na=16,$a=16,Wa=32;function ja(e,n){return Ua(e.trim(),n,Wa)}function ar(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=yi($a),o=ja(t,r),i=yi(La),s=Fa(Ba,o,i,{authTagLength:Na}),a=JSON.stringify(e),u=Buffer.concat([s.update(a,"utf8"),s.final()]),l=s.getAuthTag();return[r.toString("base64"),i.toString("base64"),l.toString("base64"),u.toString("base64")].join(":")}var Ka=["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 ur(e){if(e instanceof uo)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!Ka.some(t=>n.includes(t))}function qa(e){if(!e)return[];let n=P(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!we(r)):[]}async function hn(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to sync connections from the app");await jn(e,{silent:!0});let[r,o]=await Promise.all([Je(t),ze(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=qa(t.plugins.find(u=>u.id===s.id));return{id:s.id,authType:s.authType,configured:s.configured,missingFields:s.missingFields,...a.length>0?{integrationCredentialFields:a}:{}}}),syncedAt:new Date().toISOString()};return ar(i,n)}var ne=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function dt(e,n){let t=w(e,()=>new ne("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ne("no_database","Database not configured");let r=U(t,n.plugin,c=>new ne("plugin_not_found",c)),o=P(r);if(!o)throw new ne("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new ne("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await qe(e,n.tenantId);let i=new Set(An(r,o)),a=r.authConfig?.[o]?.account??[],u=D({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),l=0;for(let[c,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(c))throw new ne("invalid_credentials",`Unknown credential field '${c}' for plugin '${n.plugin}'`);let d=N(u,`set_${c}`);if(!d)throw new ne("invalid_credentials",`Cannot set credential field '${c}' for plugin '${n.plugin}'`);await d(p.trim()),l+=1}if(l===0)throw new ne("invalid_credentials","Provide at least one credential field to save");return await le(e,{plugin:r,tenantId:n.tenantId}).catch(()=>{}),{plugin:n.plugin,tenantId:n.tenantId}}var te=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function cr(e,n){let t=w(e,()=>new te("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new te("no_database","Database not configured");let r=U(t,n.plugin,c=>new te("plugin_not_found",c)),o=P(r);if(!o)throw new te("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await zo(e);let i=new Set(po(r,o)),a=r.authConfig?.[o]?.integration??[],u=M({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:a}),l=0;for(let[c,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(c))throw new te("invalid_credentials",`Unknown integration credential field '${c}' for plugin '${n.plugin}'`);let d=N(u,`set_${c}`);if(!d)throw new te("invalid_credentials",`Cannot set integration field '${c}' for plugin '${n.plugin}'`);await d(p.trim()),l+=1}if(l===0)throw new te("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var pt=new Map;function Za(e){for(let[n,t]of pt)t<=e&&pt.delete(n)}function gt(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();Za(r);let o=pt.get(t);return o!==void 0&&o>r?{ok:!1,error:"Delivery request already consumed"}:(pt.set(t,r+n),{ok:!0})}var Te=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Qe(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a}=n;if(!o.trim())throw new Te("no_access_token","Managed OAuth delivery missing access_token");let u=w(e,()=>new Te("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new Te("no_database","No database configured on corsair instance");let l=U(u,t,p=>new Te("plugin_not_found",p));await qe(e,r);let c=D({authType:"managed",integrationName:t,tenantId:r,kek:u.kek,database:u.database});await c.set_access_token(o),i&&await c.set_refresh_token(i),s&&await c.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await c.set_scope(a),await le(e,{plugin:l,tenantId:r}).catch(()=>{});try{let p=await Nn(u.plugins,t,{access_token:o,refresh_token:i,scope:a});if(p){try{let d=l.authConfig?.managed?.account??[];await je({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:p,authType:"managed",extraAccountFields:d})}catch(d){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,d)}u.hub&&We(u.hub,{plugin:t,tenantId:r,link:p,authType:"managed"})}}catch(p){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,p)}return await Ke(e,l,r,c).catch(p=>{console.warn(`[corsair:managed-oauth] subscribe failed for '${t}' tenant '${r}':`,p)}),{plugin:t,tenantId:r}}function Ga(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function mi(e,n,t=[]){for(let[r,o]of Object.entries(e))if(Ga(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=mi(o,n,[...t,r]);if(i)return i}return null}function za(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Ja(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 hi(e,n,t,r,o){let i=za(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=Ja(i)||s);let u={headers:i,body:s,...r?{query:r}:{}},l=r?.tenantId||"default",c=e.withTenant?e.withTenant(l):e,p=o?.plugin,d=p?[p]:xn;for(let g of d){let f=c[g];if(!f||!f.webhooks||!p&&f.pluginWebhookMatcher&&!f.pluginWebhookMatcher(u))continue;let y=mi(f.webhooks,u);if(!y)continue;let h=y.path.join("."),m={payload:s,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let k=await y.webhook.handler(m),C=!!Object.keys(k.returnToSender||{})?.length;return{plugin:g,action:h,body:s,response:C?{...k?.returnToSender,success:!0}:{success:!0},...k.responseHeaders&&{responseHeaders:k.responseHeaders}}}catch(k){return console.error(`Error executing webhook handler for ${g}.${h}:`,k),{plugin:g,action:h,body:s,response:{success:!1,error:k instanceof Error?k.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHash as Va}from"crypto";import*as Ee from"vm";var bi="__corsairFailedStep",Ya=3e4,lr=class{constructor(n,t){this.wakeAt=n;this.stepName=t}__corsairSleep=!0};function ki(e){return typeof e=="object"&&e!==null&&e.__corsairSleep===!0}function wi(e,n){return`st_${Va("sha256").update(`${n} ${e}`).digest("hex").slice(0,16)}`}function ft(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 Ci=new Set(["constructor","prototype","__proto__"]);function pe(e,n){if(e===null)return null;let t=typeof e;return t==="function"?Xa(e,n):t==="object"?Qa(e):e}function Qa(e){return new Proxy(e,{get(n,t){if(!Ci.has(t))return pe(Reflect.get(n,t,n),n)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function Xa(e,n){return new Proxy(e,{apply:(t,r,o)=>eu(Reflect.apply(t,n,o)),construct(){throw new Error("Workflow code may not construct host objects")},get(t,r){if(!Ci.has(r))return pe(Reflect.get(t,r,t),t)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function eu(e){return e!==null&&typeof e=="object"&&typeof e.then=="function"?Promise.resolve(e).then(n=>pe(n,void 0),n=>{throw pe(n,void 0)}):pe(e,void 0)}function nu(e){let n=Object.create(null),t=Ee.createContext(n,{name:"corsair-workflow",codeGeneration:{strings:!1,wasm:!1}}),o=Ee.runInContext("(s) => JSON.parse(s)",t,{filename:"corsair:sandbox:json"})(JSON.stringify(e.payload??null)),s=Ee.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"})((d,g)=>e.step(d,g),(d,g)=>e.step.sleep(d,g)),u=Ee.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"})((d,g)=>{let f=console[d]??console.log;try{f(...g)}catch{}});n.__corsair=pe(e.corsair,void 0),n.__payload=o,n.__step=s,n.__console=u;let l=Ee.runInContext(`(function () {
29
+ 'use strict';
30
+ const module = { exports: {} };
31
+ const require = function (id) {
32
+ throw new Error('Workflow code may not import modules (attempted to require "' + id + '")');
33
+ };
34
+ (function (exports, module, require, console) {
35
+ ${e.code}
36
+ })(module.exports, module, require, __console);
37
+ const main = module.exports.main;
38
+ if (typeof main !== 'function') {
39
+ throw new Error('Workflow code must export a \`main\` function');
40
+ }
41
+ return main(__corsair, __payload, __step);
42
+ })()`,t,{filename:"corsair:workflow",timeout:e.timeoutMs});l.catch(()=>{});let c,p=new Promise((d,g)=>{c=setTimeout(()=>g(new Error(`Workflow exceeded ${e.timeoutMs}ms time limit`)),e.timeoutMs)});return Promise.race([l,p]).finally(()=>clearTimeout(c))}async function dr(e){let n=e.memoizedSteps??{},t=[],r=0,o=null,i=(async(s,a)=>{if(o)throw o;let u=r++,l=wi(s,u);if(Object.hasOwn(n,l))return pe(n[l].output,void 0);try{let c=await a();return t.push({stepId:l,name:s,seq:u,status:"completed",output:c}),c}catch(c){if(ki(c))throw c;let p=ft(c);t.push({stepId:l,name:s,seq:u,status:"failed",error:p});let d=new Error(p);throw d[bi]=s,d}});i.sleep=async(s,a)=>{if(o)throw o;let u=r++,l=wi(s,u);if(Object.hasOwn(n,l))return;t.push({stepId:l,name:s,seq:u,status:"completed",output:null});let c=Number.isFinite(a)?Math.max(0,a):0;throw o=new lr(Date.now()+c,s),o};try{await nu({code:e.code,corsair:e.corsair,payload:e.payload,step:i,timeoutMs:e.timeoutMs??Ya});let s=o;return s?{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()}:{status:"completed",steps:t}}catch(s){if(ki(s))return{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()};let a=ft(s),u=s!==null&&typeof s=="object"?s[bi]:void 0;return{status:"failed",steps:t,error:{message:a,...u?{failedStep:u}:{}}}}}import*as yt from"vm";var vi=1e4;async function pr(e){let n=Object.create(null),t=yt.createContext(n,{name:"corsair-probe",codeGeneration:{strings:!1,wasm:!1}});n.corsair=pe(e.corsair,void 0);let r=ru(e.timeoutMs),o=`(async () => {
43
+ const __result = await (async () => {
44
+ ${e.code}
45
+ })();
46
+ return JSON.stringify(__result) ?? 'null';
47
+ })()`;try{let i=await Jt(()=>{let s=yt.runInContext(o,t,{filename:"corsair:probe",timeout:r});s.catch(()=>{});let a,u=new Promise((l,c)=>{a=setTimeout(()=>c(new Error(`Probe exceeded ${r}ms time limit`)),r)});return Promise.race([s,u]).finally(()=>clearTimeout(a))});return{status:"ok",value:tu(i)}}catch(i){return{status:"error",error:ft(i)}}}function tu(e){if(typeof e!="string")throw new Error(`Probe returned a non-string result (${typeof e})`);return JSON.parse(e)}function ru(e){return typeof e!="number"||!Number.isFinite(e)||e<=0?vi:Math.min(e,vi)}function De(e){return e.deliveryMode==="auth.credentials"}function bn(e){return e.deliveryMode==="connections.sync"}function mt(e){return e.deliveryMode==="connect.create_link"}function kn(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function wn(e){return e.deliveryMode==="oauth.tokens"}function ht(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!De(e)&&!bn(e)&&!mt(e)&&!kn(e)&&!wn(e)}function ou(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 iu(e,n){try{return{status:"ok",webhookResponse:{status:200,body:{status:"ok",sync:{encrypted:await hn(e,n)}}}}}catch(t){return{status:"failed",retryable:ur(t),error:t instanceof Error?t.message:"Connections sync delivery failed"}}}async function su(e,n){try{let t=await Zn(e,n);return ou(t)}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Connect link delivery failed"}}}function gr(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 $n({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function uu(e,n,t){let r=await au(e,n,t),o={...t.query??{},...r?{tenantId:r}:{}},i=await hi(e,t.headers,t.body,o,t.plugin?{plugin:t.plugin}:void 0);if(!i.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(i.response&&i.response.success===!1)return{status:"failed",retryable:!1,error:typeof i.response.error=="string"?i.response.error:"Webhook handler failed"};let s=i.response?.returnToSender,a=s&&typeof s=="object"&&typeof s.validationToken=="string"&&Object.keys(s).length===1?s.validationToken:s||(i.response?.data??i.response);return{status:"ok",webhookResponse:{status:i.response?.statusCode??200,body:a,headers:i.responseHeaders}}}async function cu(e,n){return await fn(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 lu(e,n){return await Qe(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function yr(e,n,t){let r=await fr(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function fr(e,n,t){let r=w(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 du(e,n){try{return await dt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function pu(e,n){try{return await cr(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}function Ti(e,n){let t=e;return n&&typeof t?.withTenant=="function"?t.withTenant(n):e}async function gu(e,n){try{let t=Ti(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",run:await dr({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 fu(e,n){try{let t=Ti(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",probe:await pr({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 Cn(e,n,t={}){let r=w(e),o=gr(n.headers,"x-corsair-signature"),i=gr(n.headers,"x-corsair-timestamp"),s=gr(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let u=Ve({body:n.body,signatureHeader:o,timestampHeader:i,signingSecret:t.signingSecret});if(!u.ok)return{status:"failed",retryable:!1,error:u.error};if(!s?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let l=gt(`nonce:${s.trim()}`,Re);if(!l.ok)return{status:"failed",retryable:!1,error:l.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let a;try{a=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}if(a.type==="connect.status")return{status:"failed",retryable:!1,error:"connect.status is deprecated; use connections.sync signed delivery instead"};switch(a.type){case"webhook":return uu(e,r,a.payload);case"oauth.callback":return cu(e,a.payload);case"oauth.tokens":return lu(e,a.payload);case"permission.approve":return fr(e,a.payload,"approved");case"permission.deny":return fr(e,a.payload,"denied");case"auth.credentials":return du(e,a.payload);case"integration.credentials":return pu(e,a.payload);case"connect.create_link":return su(e,a.payload);case"connections.sync":{let u=t.signingSecret?.trim();return u?iu(e,u):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}case"run":return t.allowWorkflowExecution?gu(e,a.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};case"probe":return t.allowWorkflowExecution?fu(e,a.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(a.type)}`}}}function yu(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 mr=3,mu=250;function hu(e){return e?.name==="AbortError"}async function bu(e){try{return(await e.json())?.ok!==!1}catch{return!0}}async function ku(e,n,t,r,o){for(let i=1;i<=mr;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 bu(s)||console.warn(`[corsair] hub did not record delivery ${r.deliveryId} (already timed out); the run may be retried`),!0}catch(s){if(hu(s))throw s}i<mr&&await Ai(mu)}return console.warn(`[corsair] failed to acknowledge delivery ${r.deliveryId} after ${mr} attempts; the run may be retried`),!1}async function wu(e,n,t,r){let o={authorization:`Bearer ${n.projectApiKey}`},i=await t.fetch(`${n.apiUrl}/api/dev/pull`,{headers:o,signal:r});if(i.status===204)return"idle";if(!i.ok)return"error";let{deliveryId:s,body:a,headers:u}=await i.json(),l=await t.process(e,{headers:u,body:a},{signingSecret:n.signingSecret,allowWorkflowExecution:n.allowWorkflowExecution}),{status:c,body:p}=yu(l);return await ku(n,t,o,{deliveryId:s,status:c,body:p},r)?"handled":"error"}var Pi=1e3,Cu=5e3,vu=3e4;function Ai(e){return new Promise(n=>setTimeout(n,e))}var bt=globalThis.__corsairConnectLoops??=new Map;function Tu(e,n={fetch,process:Cn}){let t;try{t=O(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(bt.has(r))return{stop:()=>{}};let o=Symbol("corsair-connect-loop");bt.set(r,o);let i=()=>{bt.get(r)===o&&bt.delete(r)},s=!1,a=null;return(async()=>{let l=Pi,c=!1,p=async d=>{c||(console.warn("[corsair] connect loop error; retrying",d),c=!0),s||await Ai(l),l=Math.min(l*2,Cu)};try{for(;!s;){a=new AbortController;let d=setTimeout(()=>a?.abort(),vu);try{await wu(e,t,n,a.signal)==="error"?await p("pull or ack failed"):(c=!1,l=Pi)}catch(g){if(s)break;await p(g instanceof Error?g.message:g)}finally{clearTimeout(d)}}}finally{i()}})(),{stop:()=>{s=!0,a?.abort(),i()}}}function xi(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Pu(e,n){return n&&!n.has(e.id)?!1:P(e)!==null}async function Ri(e,n,t={}){let r=w(e),o=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,s=await dn(r,o,{pluginIds:t.pluginIds}),a=new Map(s.map(l=>[l.plugin,l])),u=r.plugins.filter(l=>Pu(l,i)).map(l=>{let c=P(l),p=a.get(l.id);return p?{plugin:l.id,providerName:me(l.id),authKind:xi(c),status:p.status,connected:p.connected,fields:p.fields.map(d=>({name:d.name,level:d.level,required:d.required,configured:d.configured})),missingRequiredFields:p.missingRequiredFields}:{plugin:l.id,providerName:me(l.id),authKind:xi(c),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:u}}async function Ii(e,n){let t=O(e);return $({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:En})}var hr=new Map;function Si(e){let n;try{n=O(e)}catch{return}let t=Ht(n);t&&hr.get(n.projectApiKey)!==t&&(hr.set(n.projectApiKey,t),_({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{hr.delete(n.projectApiKey)}))}var Au=[".corsair.dev"];function xu(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Ru(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:xu(n)?!0:Au.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function _i(e){return!e||!Ru(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 Ei(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 br(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 kr(e,n){let t=O(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=be(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=gt(`browser:${i.jti}`,he);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(bn(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 hn(e,t.signingSecret);return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(mt(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connect link delivery requires hubOrigin and requestId for client bridge"}};let a=i.connectLinkPlugins?.filter(Boolean)??[];if(a.length===0)return{type:"json",status:400,body:{error:"Connect link delivery requires at least one plugin in connectLinkPlugins"}};let u=await Zn(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:u.connectUrl,expiresAt:u.expiresAt}})}}if(De(i))return i.hubSuccessUrl?i.credentials?(await dt(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:br(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:br(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(kn(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await yr(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 Qe(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope})}else{if(!ht(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await fn(e,{code:i.code,state:i.state,redirectUri:i.redirectUri,trusted:!0,plugin:i.plugin,tenantId:i.tenantId})}}catch(a){let u=a instanceof Error?a.message:"Hub delivery failed";return bn(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:mt(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:De(i)&&i.hubSuccessUrl?{type:"redirect",url:br(i.hubSuccessUrl,{error:u})}:De(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:i.hubSuccessUrl}}async function wr(e,n){let t=O(e),r=await Cn(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 Cr(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 vr(e,n){return n.method==="GET"?kr(e,n.url):wr(e,{headers:n.headers,body:n.body??""})}async function Tr(e,n){try{let t=await vr(e,n);return Cr(t)}catch(t){if(t instanceof se)return Response.json({error:t.message},{status:503});throw t}}async function Oe(e,n){Si(e);let t=n.method.toUpperCase(),r=_i(n.headers.get("origin"));if(t==="OPTIONS")return r?new Response(null,{status:204,headers:r}):Response.json({error:"Method not allowed"},{status:405});if(t!=="GET"&&t!=="POST")return Response.json({error:"Method not allowed"},{status:405});let o=await Tr(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return Ei(o,r)}var W=class extends Error{pluginId;authType;constructor(n,t,r){super(r??`[auth-missing:${n}:${t}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n,this.authType=t}};var Di=300;async function Pr(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,s=n?.forceRefresh??!1,[a,u,l]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!l)throw new W(o,"managed");let c=Math.floor(Date.now()/1e3);if(!s&&a&&u&&Number(u)>c+Di)return{accessToken:a,expiresAt:Number(u),refreshed:!1};if(!l&&a&&!s){let g=u?Number(u):null;if(g===null||g>c+Di)return{accessToken:a,expiresAt:g??c+3600,refreshed:!1}}let p=await Su(r,o,i),d=p.expires_in?c+p.expires_in:u?Number(u):c+3600;return await t.set_access_token(p.access_token),await t.set_expires_at(String(d)),p.refresh_token&&await t.set_refresh_token(p.refresh_token),p.scope&&await t.set_scope(p.scope),{accessToken:p.access_token,expiresAt:d,refreshed:!0}}function Iu(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function Su(e,n,t){try{return await _({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t},parseResponse:On})}catch(r){let o=r instanceof Error?r.message:"";throw Iu(o)?new W(n,"managed"):r}}async function Oi(e,n){e._refreshAuth=async()=>(await Pr(n,{forceRefresh:!0})).accessToken}function Mi(e){return{delivery:n=>Oe(e,n),deliveryOptions:n=>Oe(e,n)}}var Hi=1200*1e3;function Ar(){return ie()}function xr(){return Hi}function Rr(e,n){return sn(e,n,Hi)}function Ir(e,n){return ee(e,n)}function Sr(e){return Ie(e)}var Fi=600*1e3;function _r(){return ie()}function Er(){return Fi}function Dr(e,n){return sn(e,n,Fi)}function Or(e,n){return ee(e,n)}function Mr(e){return Ot(e)}function Hr(e){return Ie(e)}function Fr(){return ie()}function Ur(e,n,t){return Rn(e,n,Math.floor(t.getTime()/1e3))}function Br(e,n){return ee(e,n)}function Lr(e){return Ie(e)}function Ui(e){return e&&typeof e=="object"?e:{}}async function Nr(e,n){return _({hub:e,path:"/threads",body:{tenantId:n.tenantId,message:n.message},parseResponse:t=>t})}async function $r(e,n){return _({hub:e,path:`/threads/${encodeURIComponent(n.threadId)}/messages`,body:{tenantId:n.tenantId,message:n.message},notFoundMessage:`Thread "${n.threadId}" not found`,parseResponse:t=>t})}async function Wr(e,n){return $({hub:e,path:`/threads?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Ui(t).threads;return Array.isArray(r)?r:[]}})}async function kt(e,n){return $({hub:e,path:`/threads/${encodeURIComponent(n.threadId)}/messages?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Thread "${n.threadId}" not found`,parseResponse:t=>{let r=Ui(t).messages;return Array.isArray(r)?r:[]}})}function wt(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(o,i){let s=t.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${t.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
48
+
49
+ To generate a KEK, run: openssl rand -base64 ${un}`)}})}async function _u(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 Bi(e){let{integrationId:n,accountId:t}=await _u(e);return{integrationId:n,accountId:t}}function jr(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function Eu(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await Wt(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins,multiTenancy:n.multiTenancy})).connectUrl}catch{return null}}async function Du(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await Wt(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):jr(e.pluginId,r.connectUrl)}catch{return`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`}let t=await Eu({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return t?jr(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function Ou(e,n,t){let r=$e(Ce(e,n.tenantId??t??"default"),n.kek),o=new URL(n.baseUrl);o.searchParams.set("state",r);let i=o.toString();return n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:i,state:r}):jr(e,i)}async function Mu(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&Ze(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?Ou(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?Du({manual:e.manual,hub:e.hub,plugin:e.plugin,pluginId:t,tenantId:n,authType:e.error.authType,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy}):e.error.message}async function Li(e){let n=await Mu(e);throw new W(e.error.pluginId,e.error.authType,n)}var Hu=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Ni(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||Hu)(e,i)}function Fu(e){return typeof e=="function"}function Kr({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:p,tenantId:d,manualConfig:g,hubConfig:f,plugin:y,kek:h,allPlugins:m,multiTenancy:k}){for(let[C,S]of Object.entries(e)){let R=n?.[C];if(Fu(S)){let E=R,b=[...s,C].join("."),v=async(T={})=>{let j=l?.[b];Vt(b,j?.riskLevel??"write");let re;if(u){let K=j,{result:Pn,reason:Q,onComplete:tn,token:oe,id:xe,expiresAt:q}=await oi({pluginId:o,endpointPath:b,args:T,mode:u.mode,override:u.overrides?.[b],riskLevel:K?.riskLevel??"write",meta:K,db:c,timeoutMs:p?Yt(p.timeout):void 0,tenantId:d,approvalMode:p?.mode});if(Pn==="blocked"){let X;throw Q==="denied"?X=`Action '${b}' was denied by the user. Await further instructions before proceeding.`:Q==="policy"?X=`Action '${b}' is blocked by the permission policy. Update the corsair config to allow it.`:Q==="timeout"?X=`Action '${b}' timed out waiting for approval.`:oe&&xe?X=await zt({permissionsOptions:p,manual:g,hub:f,permissionId:xe,permissionToken:oe,plugin:o,endpoint:b,args:T,tenantId:d??"default",expiresAt:q??new Date(Date.now()+(p?Yt(p.timeout):600*1e3)).toISOString(),operationPath:b}):X=`Action '${b}' requires user approval before it can run.`,new Ge(X)}re=tn}let A=async(K,Pn,Q)=>{try{return await S(Pn,Q)}catch(tn){if(tn instanceof Error){let oe=await Ni(tn,o,b,typeof Q=="object"&&Q!==null?Q:{args:Q},i);if(K<(oe.maxRetries||0)){let xe=K+1;console.log(`Retrying (${xe} / ${oe.maxRetries})...`);let q;if(oe.headersRetryAfterMs)q=oe.headersRetryAfterMs;else switch(oe.retryStrategy){case"exponential_backoff":q=Math.pow(2,xe-1)*1e3;break;case"exponential_backoff_jitter":let X=Math.pow(2,xe-1)*1e3,xs=(Math.random()-.5)*1e3;q=Math.max(0,X+xs);break;case"linear_1s":q=1e3;break;case"linear_2s":q=2e3;break;case"linear_3s":q=3e3;break;case"linear_4s":q=4e3;break;default:q=1e3;break}await new Promise(X=>setTimeout(X,q)),await A(xe,Pn,Q),console.log(`[corsair:${o}:${b}] Retry strategy:`,oe)}}throw tn}},Y;try{Y=a?await a(t,"endpoint"):void 0}catch(K){throw K instanceof W&&(y&&f&&gn({hub:f,database:c,kek:h,plugins:m??[],plugin:y,tenantId:d,verified:!1}),await Li({error:K,manual:g,hub:f,plugin:y,tenantId:d,database:c,kek:h,plugins:m,multiTenancy:k})),K}if(!E?.before&&!E?.after){let K=await A(0,{...t,key:Y},T);return await re?.(),y&&f&&gn({hub:f,database:c,kek:h,plugins:m??[],plugin:y,tenantId:d,verified:!0}),K}let nn={...t,key:Y},Ae=E.before?await E.before(nn,T):{ctx:nn,args:T,continue:!0,passToAfter:void 0};if(Ae.continue===!1)return;let so=await A(0,Ae.ctx,Ae.args);return await E.after?.(Ae.ctx,so,Ae.passToAfter),await re?.(),y&&f&&gn({hub:f,database:c,kek:h,plugins:m??[],plugin:y,tenantId:d,verified:!0}),so};r[C]=v}else if(S&&typeof S=="object"){let E={};Kr({endpoints:S,hooks:R,ctx:t,tree:E,pluginId:o,errorHandlers:i,currentPath:[...s,C],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:p,tenantId:d,manualConfig:g,hubConfig:f,plugin:y,kek:h,allPlugins:m,multiTenancy:k}),r[C]=E}}}function $i(e){return e&&typeof e=="object"?e:{}}async function Wi(e,n){let t=new URLSearchParams({tenantId:n.tenantId});return n.limit!=null&&t.set("limit",String(n.limit)),$({hub:e,path:`/runs?${t.toString()}`,parseResponse:r=>{let o=$i(r).runs;return Array.isArray(o)?o:[]}})}async function qr(e,n){return $({hub:e,path:`/runs/${encodeURIComponent(n.runId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Run "${n.runId}" not found`,parseResponse:t=>$i(t).run})}async function Zr(e,n,t){await _({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 ji=(e,n)=>Zr(e,"approve",n),Ki=(e,n)=>Zr(e,"deny",n),qi=(e,n)=>Zr(e,"cancel",n);function Zi(e,n){let t=()=>{if(!e)throw new Error("corsair.runs requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({get:()=>qr(t(),{runId:o,tenantId:n}),approve:()=>ji(t(),{runId:o,tenantId:n}),deny:()=>Ki(t(),{runId:o,tenantId:n}),cancel:()=>qi(t(),{runId:o,tenantId:n})}));return r.list=o=>Wi(t(),{tenantId:n,limit:o?.limit}),r.get=o=>qr(t(),{runId:o,tenantId:n}),r}function Gi(e,n){let t=()=>{if(!e)throw new Error("corsair.threads requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({message:i=>$r(t(),{threadId:o,tenantId:n,message:i}),listMessages:()=>kt(t(),{threadId:o,tenantId:n})}));return r.create=o=>Nr(t(),{tenantId:n,message:o}),r.list=()=>Wr(t(),{tenantId:n}),r.listMessages=o=>kt(t(),{threadId:o,tenantId:n}),r}function Uu(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Gr({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(Uu(s)){let u=a,l=async c=>{let p=(g,f)=>s.handler(g,f),d=o?await o(t,"webhook"):void 0;return!u?.before&&!u?.after?p({...t,key:d},c):(async()=>{let g={...t,key:d},f=u.before?await u.before(g,c):{ctx:g,args:c,continue:!0,passToAfter:void 0};if(f.continue===!1)return;let y=await p(f.ctx,f.args);return y?.success===!0&&await u.after?.(f.ctx,y,f.passToAfter),y})()};r[i]={match:s.match,handler:l}}else if(s&&typeof s=="object"){let u={};Gr({webhooks:s,hooks:a,ctx:t,webhooksTree:u,keyBuilder:o}),r[i]=u}}}function Bu(e){return e&&typeof e=="object"?e:{}}async function zi(e,n){return $({hub:e,path:`/workflows?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Bu(t).workflows;return Array.isArray(r)?r:[]}})}async function Ji(e,n){return _({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 Vi(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=>({run:i=>Ji(t(),{workflowId:o,tenantId:n,payload:i?.payload,idempotencyKey:i?.idempotencyKey})}));return r.list=()=>zi(t(),{tenantId:n}),r}function Lu(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 Bi({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function Nu(e,n,t,r,o){return e?It(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 zr(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:u,internalConfig:l}=n,c=r??"default",p=l&&t?()=>Ne(l,c):void 0,d={},g={};for(let f of e)d[f.id]={},g[f.id]={};for(let f of e){let y=f.schema,h=Lu(t,f.id,c,p);if(y?.entities){let A={};for(let[Y,nn]of Object.entries(y.entities)){let Ae=t?It(t.db,h,Y,y.version,nn):Nu(void 0,h,Y,y.version,nn);A[Y]=Ae}g[f.id].db=A,d[f.id].db=A}let m=f.options,k=f.authConfig,C;if(t&&o&&m?.authType){let A=k?.[m.authType]?.account??[];C=D({authType:m.authType,integrationName:f.id,tenantId:c,kek:o,database:t,extraAccountFields:A,ensureProvisioned:p}),d[f.id].keys=C}let S={database:t,db:g[f.id]?.db??{},$getAccountId:h,...f.options?{options:f.options}:{},...C?{keys:C,authType:m?.authType}:{},tenantId:c,...u?{hub:u}:{}},R=f.endpoints??{},E=f.hooks,b={...i,...f.errorHandlers},v={},T=f.options?.permissions;Kr({endpoints:R,hooks:E,ctx:S,tree:v,pluginId:f.id,errorHandlers:b,currentPath:[],keyBuilder:f.keyBuilder,permissionsConfig:T,endpointMeta:f.endpointMeta,database:t,permissionsOptions:s,tenantId:r,manualConfig:a?{...a,oauthConfig:f.oauthConfig,kek:o,tenantId:c}:void 0,hubConfig:u,plugin:f,kek:o,allPlugins:e,multiTenancy:l?.multiTenancy}),Object.keys(v).length>0&&(d[f.id].api=v),S.endpoints=v;let j=f.webhooks??{},re=f.webhookHooks;if(Object.keys(j).length>0){let A={};Gr({webhooks:j,hooks:re,ctx:S,webhooksTree:A,keyBuilder:f.keyBuilder}),d[f.id].webhooks=A,f.pluginWebhookMatcher&&(d[f.id].pluginWebhookMatcher=f.pluginWebhookMatcher),f.pluginTenantWebhookMatcher&&(d[f.id].pluginTenantWebhookMatcher=f.pluginTenantWebhookMatcher)}}return d.threads=Gi(u,c),d.runs=Zi(u,c),d.workflows=Vi(u,c),d}function Yi(e,n,t){let r={};for(let o of e){let i=o.options,s=o.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],u=M({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:a});r[o.id]=u}}return r}var $u="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function Qi(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] ${$u}`),t):n}var Xi=[{method:"GET",pattern:"/ok",handler:async()=>H(200,Yn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>H(200,await Je(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>H(201,await et(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>H(200,await Xn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>H(200,await ze(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>H(200,await Qn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>H(200,await nt(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>H(200,await Qt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?H(200,await er(e,t)):H(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>H(200,await tt(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>H(200,await rt(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>H(200,await ot(e,n,t))}];(()=>{let e=new Set;for(let n of Xi){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Wu(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 ju(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 Ku(e){if(!(e.method==="GET"||e.method==="HEAD"||!(e.headers.get("content-type")??"").includes("application/json")))try{let t=await e.text();return t?JSON.parse(t):void 0}catch{throw new I(400,"invalid_json","Request body is not valid JSON")}}var qu="/api/corsair";function Me(e,n={}){let t=n.basePath??qu,r=w(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),s=ju(i.pathname,t),a=o.method.toUpperCase();if(a==="OPTIONS"||s==="/"||s==="")return await Oe(e,o);if(a!=="GET"&&a!=="POST")return H(405,{error:"method_not_allowed",message:`Method ${a} not allowed`});let u=Object.fromEntries(i.searchParams);for(let l of Xi){if(l.method!==a)continue;let c=Wu(l.pattern,s);if(!c)continue;let p=await Ku(o);return await l.handler({corsair:e,internal:r,req:o,params:c,query:u,body:p})}throw ve(`No route for ${a} ${s}`)}catch(i){if(n.onError){let a=await n.onError(i,o);if(a)return a}if(i instanceof I)return ii(i);let s=i instanceof Error?i.message:"Internal server error";return H(500,{error:"internal_error",message:s})}}}function Zu(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,o=`${t}://${n}${r}`,i=new Headers;for(let[u,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let c of l)i.append(u,c);else i.set(u,l);let s=e.method!=="GET"&&e.method!=="HEAD",a={method:e.method,headers:i};return s&&e.body!==void 0&&(a.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),i.has("content-type")||i.set("content-type","application/json")),new Request(o,a)}async function Gu(e,n){e.status(n.status),n.headers.forEach((r,o)=>e.setHeader(o,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function es(e,n){let t=Me(e,n);return async(r,o,i)=>{try{let s=await t(Zu(r));await Gu(o,s)}catch(s){i(s)}}}function ns(e,n){let t=Me(e,n);return r=>t(r.req.raw)}function ts(e,n){let t=Me(e,n);return{GET:t,POST:t,OPTIONS:t}}function rs(e){let n={[vn]:e};return{ok:Yn,tenants:{list:()=>Je(e),create:t=>et(e,t),get:t=>Xn(e,t)},plugins:{list:()=>ze(e),get:t=>Qn(e,t)},connectionStatus:{get:t=>nt(e,t?.tenantId)},permissions:{get:t=>di(e,t)},connect:{createLink:t=>tt(n,e,t),resolve:t=>rt(n,e,t),oauthCallback:t=>ot(n,e,t)}}}async function os(e,n,t,r,o="pending"){if(!e)return null;try{let i=go(),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 zu(e,n,t,r="pending"){try{let o=await e.$getAccountId();return os(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as ss from"https";import*as Ct from"querystring";var Ju=["expires_in","refresh_token_expires_in"];function is(e){let n={...e};for(let t of Ju){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function Vu(e){try{return is(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=Ct.parse(e);return!n.access_token&&!n.error?null:is({...n})}function Wn(e,n,t,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,u)=>{let l={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let c=Ct.stringify(l),p={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json","Content-Length":Buffer.byteLength(c).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let d=ss.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},g=>{let f="";g.on("data",y=>{f+=y}),g.on("end",()=>{if(g.statusCode!==200){u(new Error(`Token exchange failed (${g.statusCode}): ${f}`));return}let y=Vu(f);y?a(y):u(new Error(`Token endpoint returned non-JSON response: ${f}`))})});d.on("error",g=>u(new Error(`Request failed: ${g.message}`))),d.write(c),d.end()})}var as=" ";function J(e){let n=e;return n._def??n.def??{}}function V(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 z(e){return e.innerType??e.schema??e.out??e.in}function cs(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 z(e)}}function ls(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Tt(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Xe(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 ds(e,n){return e.description??n.description}function Yu(e){let n=e;for(;n;){let t=J(n),r=ds(n,t);if(r)return r;let o=V(t);if(Xr(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=cs(t,o);continue}break}}function Xr(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function L(e){let n=J(e),t=V(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??Xe(n)[0]??"unknown");case"ZodEnum":return Xe(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=z(n);return r?L(r):"unknown"}case"ZodNullable":{let r=z(n);return`${r?L(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=z(n);return r?L(r):"unknown"}case"ZodArray":{let r=ls(n);if(!r)return"unknown[]";let o=J(r),i=V(o)==="ZodUnion",s=L(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Tt(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let u=V(J(a));return`${u==="ZodOptional"||u==="ZodNullable"?s+"?":s}: ${L(a)}`}).join(", ")} }`}case"ZodUnion":return Xe(n).map(r=>L(r)).join(" | ");case"ZodIntersection":return`${L(n.left)} & ${L(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=cs(n,t);return r?L(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ge(e){let n=J(e),t=V(n),r=ds(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??Xe(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=Xe(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=z(n),i=o?ge(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=z(n),i=o?ge(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=z(n);return o?{...ge(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=ls(n);return{kind:"array",optional:!1,description:r,items:o?ge(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=Tt(e,n),i={};for(let[s,a]of Object.entries(o))i[s]=ge(a);return{kind:"object",optional:!1,description:r,fields:i}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let o=Xe(n);for(let i of o){let s=J(i);if(V(s)==="ZodObject")return{...ge(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=z(n);return o?{...ge(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function mm(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let o=t.slice(0,r),i=t.slice(r+1),s=e.find(c=>c.id===o);if(!s)return null;let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=Pe(s.endpointMeta,a),l=Pe(s.endpointSchemas,a);return!u&&!l?null:{input:l?.input?ge(l.input):null,output:l?.output?ge(l.output):null,description:u?.description}}var eo=["equals","contains","startsWith","endsWith","in"],Qu=["equals","gt","gte","lt","lte","in"],Xu=["equals"],ec=["equals","before","after","between"];function ps(e){let n=J(e);switch(V(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=z(n);return r?ps(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function no(e){let n=J(e),t=V(n);if(Xr(t)){let i=z(n);return i?no(i):{}}if(t!=="ZodObject")return{};let r=Tt(e,n),o={};for(let[i,s]of Object.entries(r)){let a=ps(s);a==="string"?o[i]={type:"string",operators:eo}:a==="number"?o[i]={type:"number",operators:Qu}:a==="boolean"?o[i]={type:"boolean",operators:Xu}:a==="date"&&(o[i]={type:"date",operators:ec})}return o}function gs(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Vr(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"&&Vr(o,i,t)}}function Yr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Qr(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];Yr(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&Qr(o,i,t)}}function to(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 Yr(s)?[i]:null;if(s!==null&&typeof s=="object"&&!Yr(s)){let a=to(s,r);if(a!==null)return[i,...a]}return null}function fs(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 nc=new Set(xn);function He(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 nc.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:He(e);if(t==="webhooks"){if(!i.webhooks)return[];let a=[];return Qr(i.webhooks,[],a),a.map(u=>`${i.id}.webhooks.${u}`)}if(t==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(u=>`${i.id}.db.${u}.search`):[]}if(!i.endpoints)return[];let s=[];return Vr(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=[];Qr(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=[];Vr(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function Pe(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function tc(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 Jr(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 hm(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let o=t.slice(0,r),i=t.slice(r+1),s=e.find(a=>a.id===o);if(s){if(i.startsWith("db.")){let c=i.slice(3),p=c.lastIndexOf(".");if(p!==-1){let d=c.slice(0,p),g=c.slice(p+1),f=s.schema?.entities;if(g==="search"&&f){let y=gs(f,d);if(y){let[h,m]=y,k=no(m),C=[`Search ${o} ${h} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${eo.join(", ")}]`];for(let[S,R]of Object.entries(k))C.push(` ${S}?: ${R.type} [${R.operators.join(", ")}]`);return C.push("}"),C.join(`
54
+ `)}}}return Jr(He(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let c=i.slice(9);if(s.webhooks){let p=to(s.webhooks,c.split("."));if(p!==null){let d=p.join("."),g=Pe(s.webhookSchemas,d.toLowerCase()),f=g?.response?L(g.response):null,y=[];return g?.description&&y.push(g.description),g?.payload&&y.push(`payload ${vt(en(g.payload))}`),f&&y.push(`response: ${f}`),y.push(`usage:
55
+ ${fs(o,p)}`),y.join(`
56
+
57
+ `)}}return Jr(He(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=Pe(s.endpointMeta,a),l=Pe(s.endpointSchemas,a);if(u||l){let c=[],p=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),d=[u?.description,p].filter(Boolean).join(" ");return d&&c.push(d),l?.input&&c.push(`input ${vt(en(l.input))}`),l?.output&&c.push(`output ${vt(en(l.output))}`),c.join(`
58
+
59
+ `)}}}return Jr(He(e),"Path not found. Available operations")}function us(e){let n=e;for(;;){let t=J(n),r=V(t);if(Xr(r)){let o=z(t);if(!o)return n;n=o;continue}return n}}function en(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=us(e),t=J(n);if(V(t)==="ZodObject"){let o=Tt(n,t),i=[];for(let[s,a]of Object.entries(o)){let u=J(a),l=V(u),c=l==="ZodOptional"||l==="ZodNullable",p=us(a),d=Yu(a);i.push({key:s,optional:c,type:L(p),...d!==void 0?{description:d}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:L(n)}}function vt(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=as.repeat(n+1),r=as.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 rc(e,n){let t=He(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(c=>c.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let c of t){let{shortPath:p,lookupKey:d}=tc(c,n),g=Pe(r.endpointMeta,d),f=Pe(r.endpointSchemas,d);!g&&!f||o.push({path:c,shortPath:p,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:en(f?.input),output:en(f?.output)})}o.sort((c,p)=>c.path.localeCompare(p.path));let i=[],s=He(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let c of s){let d=c.toLowerCase().slice(n.length+1),g=d.startsWith(".")?d.slice(1):d;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),y=to(r.webhooks,f.split("."));if(y===null)continue;let h=y.join("."),m=Pe(r.webhookSchemas,h.toLowerCase()),k=m?.response?L(m.response):void 0;i.push({path:c,description:m?.description,payload:en(m?.payload),responseType:k,usageExample:fs(n,y)})}i.sort((c,p)=>c.path.localeCompare(p.path));let a=[],u=He(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(u)&&l)for(let c of u){let d=c.toLowerCase().slice(n.length+1),g=d.startsWith(".")?d.slice(1):d;if(!g.startsWith("db."))continue;let f=g.slice(3),y=f.lastIndexOf(".");if(y===-1)continue;let h=f.slice(0,y);if(f.slice(y+1)!=="search")continue;let k=gs(l,h);if(!k)continue;let[C,S]=k,R=no(S),E=Object.entries(R).map(([b,v])=>({field:b,type:v.type,operators:v.operators}));a.push({path:c,entityName:C,filters:[{field:"entity_id",type:"string",operators:eo},...E]})}return a.sort((c,p)=>c.path.localeCompare(p.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as ys}from"crypto";async function oc(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=ys(),o=ys(),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 ic}from"crypto";var Pt="https://graph.microsoft.com/v1.0",ro=2e4,sc=60;async function ac(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let u=await fetch(`${Pt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(ro)});if(u.ok){let{value:l}=await u.json(),c=(l??[]).filter(p=>p.notificationUrl===n.webhookUrl);await Promise.all(c.map(p=>fetch(`${Pt}/subscriptions/${p.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(ro)}).catch(()=>{})))}}catch{}let o=ic(),i=new Date(Date.now()+sc*6e4).toISOString(),s=await fetch(`${Pt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(ro),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 ms(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function uc(e,n){let t=ms(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 cc(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function hs(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function bs(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 Tn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function lc(e){return Tn(e.body)}function ks(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return At(Array.isArray(r)?r:[r])}function ws(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let l=At(Array.isArray(u)?u:[u]);if(l)return decodeURIComponent(l)}let r=ks({query:e.query},"validationToken");if(r)return r;let o=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let u of o){let l=n[u],c=Array.isArray(l)?l[0]:l;if(!(!c||typeof c!="string"))try{let d=(c.startsWith("http")?new URL(c):new URL(`https://example.invalid${c.startsWith("/")?c:`/${c}`}`)).searchParams.get("validationToken");if(d?.trim())return d.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=Tn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return At([s?.validationToken])??null}function dc(e){if(ws(e))return!0;let n=Tn(e.body??e.payload);return hs(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function At(e){for(let n of e){let t=bs(n);if(t)return t}}function pc(e){let t=Tn(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var vn=Symbol.for("corsair:internal");function Ts(e){let n=e.database?ao(e.database):void 0,t=n&&e.kek?Yi(e.plugins,n,e.kek):wt(!!n,!!e.kek),r=Qi(e),o={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?In(e.hub):void 0},i=ri(n),s=rs(o);if(e.multiTenancy){let l=Object.assign({withTenant:c=>{if(!c)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let p=zr(e.plugins,{database:n,tenantId:c,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o});return Object.assign(p,{[vn]:o})},keys:t,permissions:i,manage:s},{[vn]:o});return Cs(l,o.hub),vs(l,o.hub),l}let a=zr(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o}),u=Object.assign({},a,{keys:t,permissions:i,manage:s,[vn]:o});return Cs(u,o.hub),vs(u,o.hub),u}function Cs(e,n){n?.projectApiKey?.startsWith("ck_dev_")&&import("./loop-I2YLSQ54.js").then(t=>t.startConnectLoop(e)).catch(()=>{})}function gc(e){return e?.projectApiKey?.startsWith("ck_dev_")?e.tunnel!==!1&&process.env.CORSAIR_TUNNEL!=="0":!1}var xt=globalThis.__corsairTunnels??=new Set;function vs(e,n){if(!gc(n))return;let t=n.projectApiKey;if(xt.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}xt.add(t);let o=typeof n.tunnel=="object"?n.tunnel:{},i=process.env.CORSAIR_FRP_HOST??o.shareHost??St;import("./hub/tunnel/run-tunnel.js").then(s=>s.runTunnel({port:r,apiUrl:n.apiUrl,apiKey:t,shareHost:i,onClose:()=>xt.delete(t)})).then(({url:s})=>{console.log(`[corsair] tunnel active: ${s}${_t}`)}).catch(s=>{xt.delete(t),console.warn(`[corsair] tunnel failed to start: ${s instanceof Error?s.message:String(s)}. Run \`corsair setup\` to enable your dev tunnel.`)})}var fc={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:{}}}},oo=fc;async function jn(e,n){let t=[],r=n?.silent??!1,o=g=>{t.push(g),r||console.log(g)},i=g=>{t.push(g),r||console.warn(g)},s=n?.caller??"script",a=co(e);if(!a)throw new Error("setupCorsair: invalid corsair instance");if(!a.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u=xc(e,a.plugins,n),l={...a,database:a.database},c=l.database.db;await Sc(c,i);let p=await _c(c,l,u.tenantId,u.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await Oc(e,u,n.credentials,l,o,i);let d=await Hc(p,u,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let g=Ts({plugins:a.plugins,database:c,kek:a.kek,multiTenancy:!0}).withTenant(u.tenantId);await Fc(g,a.plugins,d,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
63
+ `)}function io(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...F[n][t],...r])}function Ac(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=P(o);if(!i)continue;let s=io(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function xc(e,n,t){let r=lo(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&&Ac(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 As(e,n){return fe(e)?n===0?!0:Object.values(e).every(t=>As(t,n-1)):!1}function Rc(e){return As(e,4)}var Ic={...fo};function Rt(e){if(e instanceof wc){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Pc?Rt(r):"unknown";return n}return e instanceof bc?`${Rt(e.unwrap())} | null`:e instanceof Cc?`${Rt(e.unwrap())} | undefined`:e instanceof hc?e.options.join(" | "):e instanceof Tc?"string":e instanceof kc?"number":e instanceof yc?"boolean":e instanceof mc?"date":e instanceof vc?"jsonb":"unknown"}async function Sc(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(Ic))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
64
+ Schema: ${JSON.stringify(Rt(i),null,2)}`)}async function _c(e,n,t,r,o){let i=new Date,s=new Map;for(let a of n.plugins){let u=a.id,l=P(a),c=await e.selectFrom("corsair_integrations").selectAll().where("name","=",u).executeTakeFirst();if(!c){let y=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:y,name:u,config:{},created_at:i,updated_at:i}).execute(),c=await e.selectFrom("corsair_integrations").selectAll().where("id","=",y).executeTakeFirst(),o(`[corsair:setup] Created integration: ${u}`)}let p=l?a.authConfig?.[l]?.integration??[]:[],d=l?a.authConfig?.[l]?.account??[]:[],g=l&&c?M({authType:l,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:p}):void 0;if(c&&!c.dek&&g&&(await g.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${u}`)),!c||!l||!g)continue;let f;if(r){let y=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",c.id).executeTakeFirst();if(!y){let h=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:h,tenant_id:t,integration_id:c.id,config:{},created_at:i,updated_at:i}).execute(),y=await e.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),o(`[corsair:setup] Created account: ${u}`)}f=y&&D({authType:l,integrationName:u,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:d}),y&&f&&!y.dek&&(await f.issue_new_dek(),o(`[corsair:setup] Issued account DEK: ${u}`))}s.set(u,{pluginId:u,authType:l,integration:g,account:f,integrationFields:[...F[l].integration,...p],accountFields:r?[...F[l].account,...d]:[]})}return s}function Ec(e){if(!fe(e))return;let n=e.keys;return fe(n)?n:void 0}function Dc(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function Oc(e,n,t,r,o,i){let s=Ec(e),a=n.provisionAccounts?Dc(e,n.tenantId):void 0;for(let[u,l]of Object.entries(t)){let c=r.plugins.find(m=>m.id===u);if(!c){i(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let p=P(c);if(!p){i(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let d=io(c,p,"integration"),g=io(c,p,"account"),f=s?.[u],y=a?.[u],h=fe(y)?y.keys:void 0;for(let[m,k]of Object.entries(l))if(k){if(d.has(m)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${u}.${m}' 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 C=N(f,`set_${m}`);if(!C){i(`[corsair:setup] Cannot set integration field '${m}' for '${u}'.`);continue}await C(k),o(`[corsair:setup] Set ${u} integration.${m}`);continue}if(g.has(m)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${u}.${m}' on a multi-tenant instance`);let C=N(h,`set_${m}`);if(!C){i(`[corsair:setup] Cannot set account field '${m}' for '${u}'.`);continue}await C(k),o(`[corsair:setup] Set ${u} account.${m} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${m}' for plugin '${u}'.`)}}}var Ps=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Mc(e,n,t,r,o,i,s,a,u){let l=[],c=[];for(let d of o){if(Ps.has(d))continue;let g=N(t,`get_${d}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||l.push(d)}if(r&&i.length>0)for(let d of i){if(Ps.has(d))continue;let g=N(r,`get_${d}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||c.push(d)}let p=l.length===0&&c.length===0;if(p)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 d=[...l,...c];if(u==="cli"){let g=d.map(f=>`${f}=VALUE`).join(" ");a(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
65
+ corsair setup --${e} ${g}`)}else{let g=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let f of l)g.push(` await corsair.keys.${e}.set_${f}(value)`);for(let f of c){let y=s.provisionAccounts?s.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(s.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;g.push(` await ${y}.keys.set_${f}(value)`)}a(g.join(`
66
+ `))}}return p}async function Hc(e,n,t,r){let o=new Set;for(let i of e.values())await Mc(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function Fc(e,n,t,r,o){if(!Rc(oo)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=oo,s=new Set(n.map(a=>a.id));for(let[a,u]of Object.entries(i)){if(!s.has(a))continue;if(!t.has(a)){r(`[corsair:setup] Skipping backfill for '${a}' \u2014 auth not configured.`);continue}let l=fe(e)?e[a]:void 0,c=fe(l)?l.api:void 0;if(c)for(let[p,d]of Object.entries(u))for(let[g,f]of Object.entries(d)){r(`[corsair:setup] Backfilling ${a} \u203A ${p}.${g}...`);try{let y=fe(c)?c[p]:void 0;await N(y,g)?.(f)}catch(y){o(`[corsair:setup] ${a} \u203A ${p}.${g} failed: `+(y instanceof Error?y.message:String(y)))}}}}export{mo as a,me as b,Dt as c,rn as d,ho as e,bo as f,he as g,Re as h,ie as i,Ue as j,Be as k,be as l,Mt as m,wo as n,an as o,se as p,In as q,O as r,Sn as s,Le as t,_n as u,En as v,Dn as w,On as x,vo as y,Mn as z,ae as A,ue as B,Z as C,Ft as D,cn as E,ke as F,ce as G,ln as H,M as I,D as J,Do as K,Oo as L,jn as M,Oc as N,Ce as O,Bt as P,We as Q,je as R,Nt as S,$n as T,jo as U,_e as V,B as W,$t as X,fn as Y,Go as Z,ca as _,Kn as $,hd as aa,Vo as ba,Yo as ca,Qo as da,Wt as ea,qn as fa,jt as ga,Gn as ha,zn as ia,Ge as ja,Vn as ka,Jt as la,ti as ma,Vt as na,tr as oa,rr as pa,it as qa,or as ra,Ve as sa,Ye as ta,st as ua,at as va,yn as wa,ir as xa,sr as ya,ut as za,mn as Aa,ct as Ba,lt as Ca,Te as Da,Qe as Ea,hi as Fa,dr as Ga,pr as Ha,De as Ia,kn as Ja,wn as Ka,ht as La,yr as Ma,Cn as Na,yu as Oa,wu as Pa,Tu as Qa,Ri as Ra,Ii as Sa,kr as Ta,wr as Ua,Cr as Va,vr as Wa,Tr as Xa,Oe as Ya,W as Za,Pr as _a,Oi as $a,Mi as ab,Ar as bb,xr as cb,Rr as db,Ir as eb,Sr as fb,_r as gb,Er as hb,Dr as ib,Or as jb,Mr as kb,Hr as lb,Fr as mb,Ur as nb,Br as ob,Lr as pb,Me as qb,es as rb,ns as sb,ts as tb,os as ub,zu as vb,Wn as wb,mm as xb,He as yb,hm as zb,vt as Ab,rc as Bb,oc as Cb,Pt as Db,ac as Eb,ms as Fb,uc as Gb,cc as Hb,hs as Ib,bs as Jb,Tn as Kb,lc as Lb,ks as Mb,ws as Nb,dc as Ob,At as Pb,pc as Qb,vn as Rb,Ts as Sb,gc as Tb};
@@ -1,6 +1,6 @@
1
- import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-C24LhkXl.js';
2
- export { f as PermissionLookupInput } from '../../types-C24LhkXl.js';
3
- import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-Dt339hBs.js';
1
+ import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-3hs1SH6L.js';
2
+ export { f as PermissionLookupInput } from '../../types-3hs1SH6L.js';
3
+ import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-Ca25_1ZL.js';
4
4
  import '../../index-eydqYIn0.js';
5
5
  import 'zod';
6
6
 
@@ -0,0 +1 @@
1
+ import{da as a,ea as b,fa as c}from"./chunk-YDI4KN5B.js";import"./chunk-3EPM4FJ3.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{c as createHubConnectSession,b as createHubConnectSessionForPlugin,a as postHubConnectSession};
package/dist/core.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-B_P6rcu8.js';
1
+ export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair, s as shouldStartTunnel } from './index-BjzfHSPn.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, f as CorsairPluginSubscribeResult } from './index-DcJhvFt7.js';
4
- export { g as AccountFieldNames, a6 as AgentReply, k as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, h as BaseKeyManager, M as BeforeHookResult, n as BindEndpoints, ae as BindWebhooks, ac as Bivariant, o as BoundEndpointFn, p as BoundEndpointTree, af as BoundWebhook, ag as BoundWebhookTree, m as CorsairClient, q as CorsairContext, r as CorsairEndpoint, t as CorsairErrorHandler, c as CorsairIntegration, N as CorsairKeyBuilder, Q as CorsairKeyBuilderBase, ah as CorsairOAuthWebhookTenantLinkResolver, z as CorsairPermissionsNamespace, C as CorsairPlugin, S as CorsairPluginContext, U as CorsairPluginSubscribe, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, a7 as CorsairThreadsNamespace, ai as CorsairWebhook, aj as CorsairWebhookHandler, ak as CorsairWebhookMatcher, al as CorsairWebhookTenantMatcher, a8 as CreateThreadResult, V as EndpointHooks, X as EndpointMetaEntry, E as EndpointPathsOf, Y as EndpointRiskLevel, s as EndpointTree, D as EnforcePermissionOptions, F as EnforcePermissionResult, u as ErrorContext, v as ErrorHandler, w as ErrorHandlerAndMatchFunction, x as ErrorMatcher, i as IntegrationFieldNames, Z as KeyBuilderContext, j as OAuth2IntegrationCredentials, O as OAuthConfig, _ as PermissionMode, $ as PermissionPolicy, P as PluginAuthConfig, a0 as PluginEndpointMeta, a1 as PluginPermissionsConfig, am as RawWebhookRequest, K as ReadonlyForbiddenError, a2 as RequiredPluginEndpointMeta, a3 as RequiredPluginEndpointSchemas, a4 as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, a9 as ThreadHandle, aa as ThreadMessage, ab as ThreadSummary, T as TokenResponse, ad as UnionToIntersection, a5 as WebhookHooks, an as WebhookPathsOf, ao as WebhookRequest, ap as WebhookResponse, W as WebhookTenantMatch, aq as WebhookTree, G as assertReadonlyAllowed, l as exchangeCodeForTokens, J as isReadonlyScopeActive, L as runReadonly } from './index-DcJhvFt7.js';
5
- export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, g as PermissionRequiredError, P as PluginDocsIntrospection, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, o as extractMicrosoftGraphValidationToken, p as firstString, f as formatDocSchemaShape, q as getHeader, i as introspectPluginForDocs, s as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, u as readQueryParam, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-Dq3dd_Zs.js';
6
- import { A as AuthTypes } from './types-C24LhkXl.js';
7
- export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-C24LhkXl.js';
3
+ import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, f as CorsairPluginSubscribeResult } from './index-By4SUsQO.js';
4
+ export { g as AccountFieldNames, a6 as AgentReply, k as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, h as BaseKeyManager, M as BeforeHookResult, n as BindEndpoints, ae as BindWebhooks, ac as Bivariant, o as BoundEndpointFn, p as BoundEndpointTree, af as BoundWebhook, ag as BoundWebhookTree, m as CorsairClient, q as CorsairContext, r as CorsairEndpoint, t as CorsairErrorHandler, c as CorsairIntegration, N as CorsairKeyBuilder, Q as CorsairKeyBuilderBase, ah as CorsairOAuthWebhookTenantLinkResolver, z as CorsairPermissionsNamespace, C as CorsairPlugin, S as CorsairPluginContext, U as CorsairPluginSubscribe, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, a7 as CorsairThreadsNamespace, ai as CorsairWebhook, aj as CorsairWebhookHandler, ak as CorsairWebhookMatcher, al as CorsairWebhookTenantMatcher, a8 as CreateThreadResult, V as EndpointHooks, X as EndpointMetaEntry, E as EndpointPathsOf, Y as EndpointRiskLevel, s as EndpointTree, D as EnforcePermissionOptions, F as EnforcePermissionResult, u as ErrorContext, v as ErrorHandler, w as ErrorHandlerAndMatchFunction, x as ErrorMatcher, i as IntegrationFieldNames, Z as KeyBuilderContext, j as OAuth2IntegrationCredentials, O as OAuthConfig, _ as PermissionMode, $ as PermissionPolicy, P as PluginAuthConfig, a0 as PluginEndpointMeta, a1 as PluginPermissionsConfig, am as RawWebhookRequest, K as ReadonlyForbiddenError, a2 as RequiredPluginEndpointMeta, a3 as RequiredPluginEndpointSchemas, a4 as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, a9 as ThreadHandle, aa as ThreadMessage, ab as ThreadSummary, T as TokenResponse, ad as UnionToIntersection, a5 as WebhookHooks, an as WebhookPathsOf, ao as WebhookRequest, ap as WebhookResponse, W as WebhookTenantMatch, aq as WebhookTree, G as assertReadonlyAllowed, l as exchangeCodeForTokens, J as isReadonlyScopeActive, L as runReadonly } from './index-By4SUsQO.js';
5
+ export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, g as PermissionRequiredError, P as PluginDocsIntrospection, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, o as extractMicrosoftGraphValidationToken, p as firstString, f as formatDocSchemaShape, q as getHeader, i as introspectPluginForDocs, s as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, u as readQueryParam, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-B-L5MHWg.js';
6
+ import { A as AuthTypes } from './types-3hs1SH6L.js';
7
+ export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-3hs1SH6L.js';
8
8
  import 'kysely';
9
9
  import './index-eydqYIn0.js';
10
10
  import 'zod';
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{Ab as B,B as d,Bb as C,C as e,Cb as D,D as f,Db as E,E as g,Eb as F,F as h,Fb as G,G as i,Gb as H,H as j,Hb as I,I as k,Ib as J,J as l,Jb as K,K as m,Kb as L,L as n,Lb as M,M as o,Mb as N,Nb as O,Ob as P,Pb as Q,Qb as R,Xa as v,a,b,ja as p,ma as q,na as r,oa as s,pa as t,qa as u,sb as w,tb as x,ub as y,yb as z,zb as A}from"./chunk-VOB4G3KC.js";import{h as c}from"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{v as AuthMissingError,c as BASE_AUTH_FIELDS,Q as CORSAIR_INTERNAL,C as MS_GRAPH_API_BASE,q as PermissionRequiredError,a as ProviderDisplayNames,r as ReadonlyForbiddenError,J as asRecord,u as assertReadonlyAllowed,G as collectPluginWebhookMatchers,m as createAccountKeyManager,R as createCorsair,l as createIntegrationKeyManager,P as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,y as exchangeCodeForTokens,M as extractMicrosoftGraphValidationToken,O as firstString,z as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,H as getHeader,B as googleChannelSubscribe,o as initializeAccountDEK,n as initializeIntegrationDEK,A as introspectPluginForDocs,N as isMicrosoftGraphValidationHandshake,t as isReadonlyScopeActive,w as logEvent,x as logEventFromContext,E as matchWebhookPlugin,F as matchWebhookPluginAndTenant,D as msGraphSubscribe,k as reEncryptConfig,K as readBodyRecord,L as readQueryParam,p as resolveConnectLink,s as runReadonly,I as toExternalId};
1
+ import{A as d,Ab as z,B as e,Bb as A,C as f,Cb as B,D as g,Db as C,E as h,Eb as D,F as i,Fb as E,G as j,Gb as F,H as k,Hb as G,I as l,Ib as H,J as m,Jb as I,K as n,Kb as J,L as o,Lb as K,Mb as L,Nb as M,Ob as N,Pb as O,Qb as P,Rb as Q,Sb as R,Tb as S,Za as v,a,b,ga as p,ja as q,ka as r,la as s,ma as t,na as u,ub as w,vb as x,wb as y}from"./chunk-YDI4KN5B.js";import"./chunk-3EPM4FJ3.js";import{h as c}from"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{v as AuthMissingError,c as BASE_AUTH_FIELDS,Q as CORSAIR_INTERNAL,C as MS_GRAPH_API_BASE,q as PermissionRequiredError,a as ProviderDisplayNames,r as ReadonlyForbiddenError,J as asRecord,u as assertReadonlyAllowed,G as collectPluginWebhookMatchers,m as createAccountKeyManager,R as createCorsair,l as createIntegrationKeyManager,P as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,y as exchangeCodeForTokens,M as extractMicrosoftGraphValidationToken,O as firstString,z as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,H as getHeader,B as googleChannelSubscribe,o as initializeAccountDEK,n as initializeIntegrationDEK,A as introspectPluginForDocs,N as isMicrosoftGraphValidationHandshake,t as isReadonlyScopeActive,w as logEvent,x as logEventFromContext,E as matchWebhookPlugin,F as matchWebhookPluginAndTenant,D as msGraphSubscribe,k as reEncryptConfig,K as readBodyRecord,L as readQueryParam,p as resolveConnectLink,s as runReadonly,S as shouldStartTunnel,I as toExternalId};
package/dist/http.js CHANGED
@@ -1 +1 @@
1
- var c=class extends Error{url;status;statusText;body;request;retryAfter;rateLimitReset;rateLimitRemaining;rateLimitLimit;constructor(e,i,n,r){super(n),this.name="ApiError",this.url=i.url,this.status=i.status,this.statusText=i.statusText,this.body=i.body,this.request=e,this.retryAfter=r?.retryAfter,this.rateLimitReset=r?.rateLimitReset,this.rateLimitRemaining=r?.rateLimitRemaining,this.rateLimitLimit=r?.rateLimitLimit}isRateLimitError(){return this.status===429}};var g=class extends Error{constructor(e){super(e),this.name="CancelError"}get isCancelled(){return!0}},p=class{#t;#r;#e;#i;#s;#a;#n;constructor(e){this.#t=!1,this.#r=!1,this.#e=!1,this.#i=[],this.#s=new Promise((i,n)=>{this.#a=i,this.#n=n;let r=o=>{this.#t||this.#r||this.#e||(this.#t=!0,this.#a&&this.#a(o))},a=o=>{this.#t||this.#r||this.#e||(this.#r=!0,this.#n&&this.#n(o))},s=o=>{this.#t||this.#r||this.#e||this.#i.push(o)};return Object.defineProperty(s,"isResolved",{get:()=>this.#t}),Object.defineProperty(s,"isRejected",{get:()=>this.#r}),Object.defineProperty(s,"isCancelled",{get:()=>this.#e}),e(r,a,s)})}get[Symbol.toStringTag](){return"Cancellable Promise"}then(e,i){return this.#s.then(e,i)}catch(e){return this.#s.catch(e)}finally(e){return this.#s.finally(e)}cancel(){if(!(this.#t||this.#r||this.#e)){if(this.#e=!0,this.#i.length)try{for(let e of this.#i)e()}catch(e){console.warn("Cancellation threw an error",e);return}this.#i.length=0,this.#n&&this.#n(new g("Request aborted"))}}get isCancelled(){return this.#e}};var v={enabled:!0,maxRetries:3,initialRetryDelay:1e3,backoffMultiplier:2,headerNames:{retryAfter:"retry-after",resetTime:"x-ratelimit-reset",remaining:"x-ratelimit-remaining",limit:"x-ratelimit-limit"}};function S(t,e){let i={};if(e.headerNames.retryAfter){let n=t.headers.get(e.headerNames.retryAfter);if(n){let r=parseInt(n,10);isNaN(r)||(i.retryAfter=r*1e3)}}if(e.headerNames.resetTime){let n=t.headers.get(e.headerNames.resetTime);if(n){let r=parseInt(n,10);if(!isNaN(r)){let a=Date.now(),s=r>1e12?r:r*1e3;i.rateLimitReset=s,s>a&&(i.retryAfter=s-a)}}}if(e.headerNames.remaining){let n=t.headers.get(e.headerNames.remaining);if(n){let r=parseInt(n,10);isNaN(r)||(i.rateLimitRemaining=r)}}if(e.headerNames.limit){let n=t.headers.get(e.headerNames.limit);if(n){let r=parseInt(n,10);isNaN(r)||(i.rateLimitLimit=r)}}return i}function C(t,e,i){return i.enabled?t===429?!0:i.isRateLimitError?i.isRateLimitError(t,e):!1:!1}function R(t,e,i){if(e.retryAfter)return e.retryAfter;let n=i.initialRetryDelay*Math.pow(i.backoffMultiplier,t-1);return Math.min(n,6e4)}async function T(t){return new Promise(e=>setTimeout(e,t))}var x=t=>t!=null,d=t=>typeof t=="string",A=t=>d(t)&&t!=="",E=t=>typeof t=="object"&&typeof t.type=="string"&&typeof t.stream=="function"&&typeof t.arrayBuffer=="function"&&typeof t.constructor=="function"&&typeof t.constructor.name=="string"&&/^(Blob|File)$/.test(t.constructor.name)&&/^(Blob|File)$/.test(t[Symbol.toStringTag]),N=t=>t instanceof FormData,j=t=>{try{return btoa(t)}catch{return Buffer.from(t).toString("base64")}},k=t=>{let e=[],i=(r,a)=>{e.push(`${encodeURIComponent(r)}=${encodeURIComponent(String(a))}`)},n=(r,a)=>{x(a)&&(Array.isArray(a)?a.forEach(s=>{n(r,s)}):typeof a=="object"?Object.entries(a).forEach(([s,o])=>{n(`${r}[${s}]`,o)}):i(r,a))};return Object.entries(t).forEach(([r,a])=>{n(r,a)}),e.length>0?`?${e.join("&")}`:""},$=(t,e)=>{let i=t.ENCODE_PATH||encodeURI,n=e.url.replace("{api-version}",t.VERSION).replace(/{(.*?)}/g,(o,l)=>e.path?.hasOwnProperty(l)?i(String(e.path[l])):o),r=t.BASE.endsWith("/")?t.BASE.slice(0,-1):t.BASE,a=n.startsWith("/")?n.slice(1):n,s=`${r}/${a}`;return e.query?`${s}${k(e.query)}`:s},W=t=>{if(t.formData){let e=new FormData,i=(n,r)=>{d(r)||E(r)?e.append(n,r):e.append(n,JSON.stringify(r))};return Object.entries(t.formData).filter(([n,r])=>x(r)).forEach(([n,r])=>{Array.isArray(r)?r.forEach(a=>i(n,a)):i(n,r)}),e}},h=async(t,e)=>typeof e=="function"?e(t):e,M=async(t,e)=>{let[i,n,r,a]=await Promise.all([h(e,t.TOKEN),h(e,t.USERNAME),h(e,t.PASSWORD),h(e,t.HEADERS)]),s=Object.entries({Accept:"application/json",...a,...e.headers}).filter(([o,l])=>x(l)).reduce((o,[l,u])=>({...o,[l]:String(u)}),{});if(A(i)&&(s.Authorization=`Bearer ${i}`),A(n)&&A(r)){let o=j(`${n}:${r}`);s.Authorization=`Basic ${o}`}return e.body!==void 0&&(e.mediaType?s["Content-Type"]=e.mediaType:E(e.body)?s["Content-Type"]=e.body.type||"application/octet-stream":d(e.body)?s["Content-Type"]="text/plain":N(e.body)||(s["Content-Type"]="application/json")),new Headers(s)},F=t=>{if(t.body!==void 0)return t.mediaType?.includes("/json")?JSON.stringify(t.body):d(t.body)||E(t.body)||N(t.body)?t.body:JSON.stringify(t.body)},U=async(t,e,i,n,r,a,s)=>{let o=new AbortController,l=t.TIMEOUT??2e4,u={headers:a,body:n??r,method:e.method,signal:AbortSignal.any([o.signal,AbortSignal.timeout(l)])};return t.WITH_CREDENTIALS&&(u.credentials=t.CREDENTIALS),s(()=>o.abort()),await fetch(i,u)},_=(t,e)=>{if(e){let i=t.headers.get(e);if(d(i))return i}},J=async t=>{if(t.status!==204)try{let e=t.headers.get("Content-Type");if(e)return["application/json","application/problem+json"].some(r=>e.toLowerCase().startsWith(r))?await t.json():await t.text()}catch(e){console.error(e)}},P=(t,e,i)=>{let r={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",...t.errors}[e.status];if(r)throw new c(t,e,r,i);if(!e.ok){let a=e.status??"unknown",s=e.statusText??"unknown",o=(()=>{try{return JSON.stringify(e.body,null,2)}catch{return}})(),l=e.body?.message||e.body?.error||e.body?.detail||`Generic Error: status: ${a}; status text: ${s}; body: ${o}`;throw new c(t,e,l,i)}},G=(t,e,i)=>{let n=i?.rateLimitConfig||v;return new p(async(r,a,s)=>{let o=0,l=n.maxRetries+1;for(;o<l;){o++;try{let u=$(t,e),b=W(e),w=F(e),H=await M(t,e);if(s.isCancelled)return;let f=await U(t,e,u,w,b,H,s),I=await J(f),B=_(f,e.responseHeader),y={url:u,ok:f.ok,status:f.status,statusText:f.statusText,body:B??I};if(n.enabled&&C(f.status,y.body,n)){let O=S(f,n);if(o<l){let D=R(o,O,n);await T(D);continue}P(e,y,O)}P(e,y),r(y.body);return}catch(u){if(u instanceof c&&u.isRateLimitError()&&o<l){let b=u.retryAfter?u.retryAfter:R(o,{retryAfter:u.retryAfter,rateLimitReset:u.rateLimitReset},n);await T(b);continue}if(o>=l){a(u);return}if(u instanceof c&&u.isRateLimitError())continue;a(u);return}}})};var L=class{handlers=new Map;on(e,i){let n=this.handlers.get(e)||[];return n.push(i),this.handlers.set(e,n),this}off(e,i){let n=this.handlers.get(e)||[],r=n.indexOf(i);return r!==-1&&(n.splice(r,1),this.handlers.set(e,n)),this}getRegisteredEvents(){return Array.from(this.handlers.keys())}hasHandlers(e){let i=this.handlers.get(e);return!!i&&i.length>0}clearHandlers(e){return e?this.handlers.delete(e):this.handlers.clear(),this}async executeHandlers(e,i){let n=this.handlers.get(e)||[];for(let r of n)await r(i)}};import*as m from"crypto";function z(t,e,i,n="sha256"){if(!i||!e)return!1;let r=m.createHmac(n,e).update(t).digest("hex");try{return m.timingSafeEqual(Buffer.from(i),Buffer.from(r))}catch{return!1}}function V(t,e,i,n,r="sha256"){if(!i||!e||!i.startsWith(n))return!1;let a=i.slice(n.length),s=m.createHmac(r,e).update(t).digest("hex");try{return m.timingSafeEqual(Buffer.from(a),Buffer.from(s))}catch{return!1}}function q(t,e,i,n,r=300){if(!e||!n||!i)return!1;let a=Math.floor(Date.now()/1e3),s=parseInt(i,10);if(Math.abs(a-s)>r)return!1;let o=`v0:${i}:${t}`,l="v0="+m.createHmac("sha256",e).update(o).digest("hex");try{return m.timingSafeEqual(Buffer.from(n),Buffer.from(l))}catch{return!1}}function K(t,e,i,n,r=300){return q(t,e,i,n,r)}export{c as ApiError,L as BaseWebhookHandler,G as request,q as verifyHmacSha256Signature,z as verifyHmacSignature,V as verifyHmacSignatureWithPrefix,K as verifySlackSignature};
1
+ var $=new Set(["api_key","key","token","appid"]);function g(t){let e=t;try{e=decodeURIComponent(t)}catch{e=t}return $.has(e.toLowerCase())}function W(t){let e=t.indexOf("?");if(e===-1)return t;let n=t.indexOf("#",e),r=t.slice(0,e+1),i=n===-1?t.slice(e+1):t.slice(e+1,n),s=n===-1?"":t.slice(n),a=!1,o=i.split("&").map(c=>{if(!c)return c;let u=c.indexOf("="),d=u===-1?c:c.slice(0,u);return g(d)?(a=!0,`${d}=[REDACTED]`):c}).join("&");return a?r+o+s:t}function C(t){if(!t)return t;try{let e=/^[a-z]+:\/\//i.test(t),n=e?void 0:"http://localhost",r=new URL(t,n),i=!1;for(let s of[...r.searchParams.keys()])g(s)&&(r.searchParams.set(s,"[REDACTED]"),i=!0);return i?e?r.toString():r.pathname+r.search+r.hash:t}catch{return W(t)}}function M(t){let e=C(t.url),n=!1,r=t.query;if(t.query){r={...t.query};for(let i of Object.keys(r))g(i)&&(r[i]="[REDACTED]",n=!0)}return!n&&e===t.url?t:{...t,url:e,...n?{query:r}:{}}}var l=class extends Error{url;status;statusText;body;request;retryAfter;rateLimitReset;rateLimitRemaining;rateLimitLimit;constructor(e,n,r,i){super(r),this.name="ApiError",this.url=C(n.url),this.status=n.status,this.statusText=n.statusText,this.body=n.body,this.request=M(e),this.retryAfter=i?.retryAfter,this.rateLimitReset=i?.rateLimitReset,this.rateLimitRemaining=i?.rateLimitRemaining,this.rateLimitLimit=i?.rateLimitLimit}isRateLimitError(){return this.status===429}};var R=class extends Error{constructor(e){super(e),this.name="CancelError"}get isCancelled(){return!0}},h=class{#t;#r;#e;#n;#s;#a;#i;constructor(e){this.#t=!1,this.#r=!1,this.#e=!1,this.#n=[],this.#s=new Promise((n,r)=>{this.#a=n,this.#i=r;let i=o=>{this.#t||this.#r||this.#e||(this.#t=!0,this.#a&&this.#a(o))},s=o=>{this.#t||this.#r||this.#e||(this.#r=!0,this.#i&&this.#i(o))},a=o=>{this.#t||this.#r||this.#e||this.#n.push(o)};return Object.defineProperty(a,"isResolved",{get:()=>this.#t}),Object.defineProperty(a,"isRejected",{get:()=>this.#r}),Object.defineProperty(a,"isCancelled",{get:()=>this.#e}),e(i,s,a)})}get[Symbol.toStringTag](){return"Cancellable Promise"}then(e,n){return this.#s.then(e,n)}catch(e){return this.#s.catch(e)}finally(e){return this.#s.finally(e)}cancel(){if(!(this.#t||this.#r||this.#e)){if(this.#e=!0,this.#n.length)try{for(let e of this.#n)e()}catch(e){console.warn("Cancellation threw an error",e);return}this.#n.length=0,this.#i&&this.#i(new R("Request aborted"))}}get isCancelled(){return this.#e}};var P={enabled:!0,maxRetries:3,initialRetryDelay:1e3,backoffMultiplier:2,headerNames:{retryAfter:"retry-after",resetTime:"x-ratelimit-reset",remaining:"x-ratelimit-remaining",limit:"x-ratelimit-limit"}};function S(t,e){let n={};if(e.headerNames.retryAfter){let r=t.headers.get(e.headerNames.retryAfter);if(r){let i=parseInt(r,10);isNaN(i)||(n.retryAfter=i*1e3)}}if(e.headerNames.resetTime){let r=t.headers.get(e.headerNames.resetTime);if(r){let i=parseInt(r,10);if(!isNaN(i)){let s=Date.now(),a=i>1e12?i:i*1e3;n.rateLimitReset=a,a>s&&(n.retryAfter=a-s)}}}if(e.headerNames.remaining){let r=t.headers.get(e.headerNames.remaining);if(r){let i=parseInt(r,10);isNaN(i)||(n.rateLimitRemaining=i)}}if(e.headerNames.limit){let r=t.headers.get(e.headerNames.limit);if(r){let i=parseInt(r,10);isNaN(i)||(n.rateLimitLimit=i)}}return n}function q(t,e,n){return n.enabled?t===429?!0:n.isRateLimitError?n.isRateLimitError(t,e):!1:!1}function T(t,e,n){if(e.retryAfter)return e.retryAfter;let r=n.initialRetryDelay*Math.pow(n.backoffMultiplier,t-1);return Math.min(r,6e4)}async function A(t){return new Promise(e=>setTimeout(e,t))}var x=t=>t!=null,y=t=>typeof t=="string",E=t=>y(t)&&t!=="",L=t=>typeof t=="object"&&typeof t.type=="string"&&typeof t.stream=="function"&&typeof t.arrayBuffer=="function"&&typeof t.constructor=="function"&&typeof t.constructor.name=="string"&&/^(Blob|File)$/.test(t.constructor.name)&&/^(Blob|File)$/.test(t[Symbol.toStringTag]),N=t=>t instanceof FormData,F=t=>{try{return btoa(t)}catch{return Buffer.from(t).toString("base64")}},U=t=>{let e=[],n=(i,s)=>{e.push(`${encodeURIComponent(i)}=${encodeURIComponent(String(s))}`)},r=(i,s)=>{x(s)&&(Array.isArray(s)?s.forEach(a=>{r(i,a)}):typeof s=="object"?Object.entries(s).forEach(([a,o])=>{r(`${i}[${a}]`,o)}):n(i,s))};return Object.entries(t).forEach(([i,s])=>{r(i,s)}),e.length>0?`?${e.join("&")}`:""},_=(t,e)=>{let n=t.ENCODE_PATH||encodeURI,r=e.url.replace("{api-version}",t.VERSION).replace(/{(.*?)}/g,(o,c)=>e.path?.hasOwnProperty(c)?n(String(e.path[c])):o),i=t.BASE.endsWith("/")?t.BASE.slice(0,-1):t.BASE,s=r.startsWith("/")?r.slice(1):r,a=`${i}/${s}`;return e.query?`${a}${U(e.query)}`:a},J=t=>{if(t.formData){let e=new FormData,n=(r,i)=>{y(i)||L(i)?e.append(r,i):e.append(r,JSON.stringify(i))};return Object.entries(t.formData).filter(([r,i])=>x(i)).forEach(([r,i])=>{Array.isArray(i)?i.forEach(s=>n(r,s)):n(r,i)}),e}},b=async(t,e)=>typeof e=="function"?e(t):e,z=async(t,e)=>{let[n,r,i,s]=await Promise.all([b(e,t.TOKEN),b(e,t.USERNAME),b(e,t.PASSWORD),b(e,t.HEADERS)]),a=Object.entries({Accept:"application/json",...s,...e.headers}).filter(([o,c])=>x(c)).reduce((o,[c,u])=>({...o,[c]:String(u)}),{});if(E(n)&&(a.Authorization=`Bearer ${n}`),E(r)&&E(i)){let o=F(`${r}:${i}`);a.Authorization=`Basic ${o}`}return e.body!==void 0&&(e.mediaType?a["Content-Type"]=e.mediaType:L(e.body)?a["Content-Type"]=e.body.type||"application/octet-stream":y(e.body)?a["Content-Type"]="text/plain":N(e.body)||(a["Content-Type"]="application/json")),new Headers(a)},Q=t=>{if(t.body!==void 0)return t.mediaType?.includes("/json")?JSON.stringify(t.body):y(t.body)||L(t.body)||N(t.body)?t.body:JSON.stringify(t.body)},G=async(t,e,n,r,i,s,a)=>{let o=new AbortController,c=t.TIMEOUT??2e4,u={headers:s,body:r??i,method:e.method,signal:AbortSignal.any([o.signal,AbortSignal.timeout(c)])};return t.WITH_CREDENTIALS&&(u.credentials=t.CREDENTIALS),a(()=>o.abort()),await fetch(n,u)},V=(t,e)=>{if(e){let n=t.headers.get(e);if(y(n))return n}},K=async t=>{if(t.status!==204)try{let e=t.headers.get("Content-Type");if(e)return["application/json","application/problem+json"].some(i=>e.toLowerCase().startsWith(i))?await t.json():await t.text()}catch(e){console.error(e)}},w=(t,e,n)=>{let i={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",...t.errors}[e.status];if(i)throw new l(t,e,i,n);if(!e.ok){let s=e.status??"unknown",a=e.statusText??"unknown",o=(()=>{try{return JSON.stringify(e.body,null,2)}catch{return}})(),c=e.body?.message||e.body?.error||e.body?.detail||`Generic Error: status: ${s}; status text: ${a}; body: ${o}`;throw new l(t,e,c,n)}},Y=(t,e,n)=>{let r=n?.rateLimitConfig||P;return new h(async(i,s,a)=>{let o=0,c=r.maxRetries+1;for(;o<c;){o++;try{let u=_(t,e),d=J(e),D=Q(e),H=await z(t,e);if(a.isCancelled)return;let m=await G(t,e,u,D,d,H,a),k=await K(m),B=V(m,e.responseHeader),p={url:u,ok:m.ok,status:m.status,statusText:m.statusText,body:B??k};if(r.enabled&&q(m.status,p.body,r)){let v=S(m,r);if(o<c){let j=T(o,v,r);await A(j);continue}w(e,p,v)}w(e,p),i(p.body);return}catch(u){if(u instanceof l&&u.isRateLimitError()&&o<c){let d=u.retryAfter?u.retryAfter:T(o,{retryAfter:u.retryAfter,rateLimitReset:u.rateLimitReset},r);await A(d);continue}if(o>=c){s(u);return}if(u instanceof l&&u.isRateLimitError())continue;s(u);return}}})};var O=class{handlers=new Map;on(e,n){let r=this.handlers.get(e)||[];return r.push(n),this.handlers.set(e,r),this}off(e,n){let r=this.handlers.get(e)||[],i=r.indexOf(n);return i!==-1&&(r.splice(i,1),this.handlers.set(e,r)),this}getRegisteredEvents(){return Array.from(this.handlers.keys())}hasHandlers(e){let n=this.handlers.get(e);return!!n&&n.length>0}clearHandlers(e){return e?this.handlers.delete(e):this.handlers.clear(),this}async executeHandlers(e,n){let r=this.handlers.get(e)||[];for(let i of r)await i(n)}};import*as f from"crypto";function X(t,e,n,r="sha256"){if(!n||!e)return!1;let i=f.createHmac(r,e).update(t).digest("hex");try{return f.timingSafeEqual(Buffer.from(n),Buffer.from(i))}catch{return!1}}function Z(t,e,n,r,i="sha256"){if(!n||!e||!n.startsWith(r))return!1;let s=n.slice(r.length),a=f.createHmac(i,e).update(t).digest("hex");try{return f.timingSafeEqual(Buffer.from(s),Buffer.from(a))}catch{return!1}}function I(t,e,n,r,i=300){if(!e||!r||!n)return!1;let s=Math.floor(Date.now()/1e3),a=parseInt(n,10);if(Math.abs(s-a)>i)return!1;let o=`v0:${n}:${t}`,c="v0="+f.createHmac("sha256",e).update(o).digest("hex");try{return f.timingSafeEqual(Buffer.from(r),Buffer.from(c))}catch{return!1}}function ee(t,e,n,r,i=300){return I(t,e,n,r,i)}export{l as ApiError,O as BaseWebhookHandler,Y as request,I as verifyHmacSha256Signature,X as verifyHmacSignature,Z as verifyHmacSignatureWithPrefix,ee as verifySlackSignature};
@@ -0,0 +1,39 @@
1
+ /** Fetches this dev environment's frp connection details from the Hub. */
2
+ declare function fetchTunnelConfig(opts: {
3
+ apiUrl: string;
4
+ apiKey: string;
5
+ }): Promise<{
6
+ serverAddr: string;
7
+ serverPort: number;
8
+ slug: string;
9
+ caCert: string | null;
10
+ serverName: string | undefined;
11
+ }>;
12
+ /**
13
+ * Spawns `frpc -c <tmp toml>` under the Hub-assigned slug, waits for the proxy
14
+ * to register, then pings the Hub that the tunnel is live. The frpc binary is
15
+ * resolved from the SDK's own install (no `brew install`); `shareHost` is only
16
+ * used to derive the public URL — the Hub owns the slug.
17
+ */
18
+ declare function runTunnel(opts: {
19
+ port: number;
20
+ apiUrl: string;
21
+ apiKey: string;
22
+ shareHost?: string;
23
+ timeoutMs?: number;
24
+ /** Called if the frpc child exits *after* the tunnel came up. */
25
+ onClose?: () => void;
26
+ }): Promise<{
27
+ url: string;
28
+ stop: () => void;
29
+ }>;
30
+ /**
31
+ * Tells the Hub the tunnel is live. No URL is sent — the Hub derives the
32
+ * delivery URL from its own slug, so a dev can't point Hub delivery elsewhere.
33
+ */
34
+ declare function pingTunnelLive(opts: {
35
+ apiUrl: string;
36
+ apiKey: string;
37
+ }): Promise<void>;
38
+
39
+ export { fetchTunnelConfig, pingTunnelLive, runTunnel };