corsair 0.1.90 → 0.1.92

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.
@@ -0,0 +1 @@
1
+ import{b as F,c as D,d as P,e as B}from"./chunk-IGGCNGU2.js";var R={oauth_2:{integration:["client_id","client_secret","redirect_url"],account:["access_token","refresh_token","expires_at","scope","webhook_signature"]},api_key:{integration:[],account:["api_key","webhook_signature"]},bot_token:{integration:[],account:["bot_token","webhook_signature"]},managed:{integration:[],account:["access_token","refresh_token","expires_at","scope","webhook_signature"]}};function L(e,t){if(!e||typeof e!="object")return;let r=e[t];return typeof r=="function"?(...n)=>Reflect.apply(r,e,n):void 0}import{Kysely as J}from"kysely";var H=Symbol.for("corsair:internal"),x=class extends Error{constructor(t="Invalid corsair instance"){super(t),this.name="InvalidCorsairInstanceError"}};function _(e){return typeof e=="object"&&e!==null}function S(e){return!_(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:_(e.database)?e.database.db instanceof J:!1}function O(e){if(!e||typeof e!="object")return;let r=Object.getOwnPropertyDescriptor(e,H)?.value;return S(r)?r:void 0}function G(e,t){let r=O(e);if(!r)throw t?.()??new x;return r}function v(e,t){return e.plugins.find(r=>r.id===t)}function X(e,t,r){let n=v(e,t);if(!n)throw r(`Plugin '${t}' not found`);return n}function Y(e){return"withTenant"in e&&typeof e.withTenant=="function"}import{v7 as q}from"uuid";function T(){return q()}function N(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function V(e){let t=e.options?.authType;return N(t)?t:void 0}function ee(e,t){let r=e.authConfig,n=R[t].account,i=r?.[t]?.account??[];return[...n,...i]}import{z as C}from"zod";import{sql as w}from"kysely";function k(e){return e.replace(/'/g,"''")}function W(e){let t=k(e);return w`data->>'${w.raw(t)}'`}function j(e){let t=k(e);return w`(data->>'${w.raw(t)}')::numeric`}function K(e){let t=k(e);return w`(data->>'${w.raw(t)}')::boolean`}function U(e){let t=k(e);return w`(data->>'${w.raw(t)}')::timestamptz`}function te(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function Z(e){let t=e;for(;t;){if(t instanceof C.ZodOptional||t instanceof C.ZodNullable){t=t._def.innerType;continue}if(t instanceof C.ZodDefault){t=t._def.innerType;continue}break}return t}function ne(e){let t=Z(e);if(t instanceof C.ZodString)return"string";if(t instanceof C.ZodNumber)return"number";if(t instanceof C.ZodBoolean)return"boolean";if(t instanceof C.ZodDate)return"date"}function re(e){let t=Z(e);if(!(t instanceof C.ZodObject))return{};let r=t.shape,n={};for(let[i,a]of Object.entries(r)){let u=ne(a);u&&(n[i]=u)}return n}function ie(e,t,r){if(typeof r=="string")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;"equals"in n&&typeof n.equals=="string"&&(e=e.where(t,"=",n.equals)),"contains"in n&&typeof n.contains=="string"&&(e=e.where(t,"like",`%${n.contains}%`)),"startsWith"in n&&typeof n.startsWith=="string"&&(e=e.where(t,"like",`${n.startsWith}%`)),"endsWith"in n&&typeof n.endsWith=="string"&&(e=e.where(t,"like",`%${n.endsWith}`)),"in"in n&&Array.isArray(n.in)&&(e=e.where(t,"in",n.in))}return e}function oe(e,t,r){if(typeof r=="number")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;typeof n.equals=="number"&&(e=e.where(t,"=",n.equals)),typeof n.gt=="number"&&(e=e.where(t,">",n.gt)),typeof n.gte=="number"&&(e=e.where(t,">=",n.gte)),typeof n.lt=="number"&&(e=e.where(t,"<",n.lt)),typeof n.lte=="number"&&(e=e.where(t,"<=",n.lte)),Array.isArray(n.in)&&(e=e.where(t,"in",n.in))}return e}function se(e,t,r){if(typeof r=="boolean")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;typeof n.equals=="boolean"&&(e=e.where(t,"=",n.equals))}return e}function ae(e,t,r){if(r instanceof Date)return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;if(n.equals instanceof Date&&(e=e.where(t,"=",n.equals)),n.before instanceof Date&&(e=e.where(t,"<",n.before)),n.after instanceof Date&&(e=e.where(t,">",n.after)),Array.isArray(n.between)&&n.between.length===2){let[i,a]=n.between;i instanceof Date&&(e=e.where(t,">=",i)),a instanceof Date&&(e=e.where(t,"<=",a))}}return e}function ue(e,t,r,n){return r==="number"?oe(e,j(t),n):r==="boolean"?se(e,K(t),n):r==="date"?ae(e,U(t),n):ie(e,W(t),n)}function ce(e,t,r){if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;return"equals"in n&&(e=e.where(t,"=",n.equals)),"contains"in n&&typeof n.contains=="string"&&(e=e.where(t,"like",`%${n.contains}%`)),"startsWith"in n&&typeof n.startsWith=="string"&&(e=e.where(t,"like",`${n.startsWith}%`)),"endsWith"in n&&typeof n.endsWith=="string"&&(e=e.where(t,"like",`%${n.endsWith}`)),"in"in n&&Array.isArray(n.in)&&(e=e.where(t,"in",n.in)),e}return e.where(t,"=",r)}function de(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function h(e,t,r){return e.selectFrom("corsair_entities").selectAll().where("account_id","=",t).where("entity_type","=",r)}function $(e,t,r,n,i){let a=re(i);function u(o){let l=te(o.data);return{...o,data:i.parse(l)}}return{findByEntityId:async o=>{let l=await t(),c=await h(e,l,r).where("entity_id","=",o).executeTakeFirst();return c?u(c):null},existsByEntityId:async o=>{let l=await t();return await h(e,l,r).select("id").where("entity_id","=",o).executeTakeFirst()!==void 0},findIdByEntityId:async o=>{let l=await t();return(await h(e,l,r).select("id").where("entity_id","=",o).executeTakeFirst())?.id??null},findById:async o=>{let l=await t(),c=await h(e,l,r).where("id","=",o).executeTakeFirst();return c?u(c):null},findManyByEntityIds:async o=>{if(o.length===0)return[];let l=await t();return(await h(e,l,r).where("entity_id","in",o).execute()).map(u)},list:async o=>{let l=await t(),c=h(e,l,r);return typeof o?.limit=="number"&&(c=c.limit(o.limit)),typeof o?.offset=="number"&&(c=c.offset(o.offset)),(await c.execute()).map(u)},search:async o=>{let l=await t(),c=h(e,l,r),d=new Set(["data","limit","offset"]);for(let[y,f]of Object.entries(o))d.has(y)||f===void 0||(c=ce(c,y,f));if(o.data&&typeof o.data=="object")for(let[y,f]of Object.entries(o.data)){if(f===void 0)continue;let g=a[y]??"string";c=ue(c,y,g,f)}return typeof o.limit=="number"&&(c=c.limit(o.limit)),typeof o.offset=="number"&&(c=c.offset(o.offset)),(await c.execute()).map(u)},upsertByEntityId:async(o,l)=>{let c=await t(),d=i.parse(l),s=new Date,y=await h(e,c,r).select("id").where("entity_id","=",o).executeTakeFirst();if(y?.id){await e.updateTable("corsair_entities").set({version:n,data:d,updated_at:s}).where("id","=",y.id).execute();let I=await e.selectFrom("corsair_entities").selectAll().where("id","=",y.id).executeTakeFirst();return u(I)}let f=T();await e.insertInto("corsair_entities").values({id:f,created_at:s,updated_at:s,account_id:c,entity_id:o,entity_type:r,version:n,data:d}).execute();let g=await e.selectFrom("corsair_entities").selectAll().where("id","=",f).executeTakeFirst();return u(g)},deleteById:async o=>{let l=await t(),c=await e.deleteFrom("corsair_entities").where("account_id","=",l).where("entity_type","=",r).where("id","=",o).executeTakeFirst();return Number(c.numDeletedRows)>0},deleteByEntityId:async o=>{let l=await t(),c=await e.deleteFrom("corsair_entities").where("account_id","=",l).where("entity_type","=",r).where("entity_id","=",o).executeTakeFirst();return Number(c.numDeletedRows)>0},count:async()=>{let o=await t(),l=await e.selectFrom("corsair_entities").select(c=>c.fn.countAll().as("count")).where("account_id","=",o).where("entity_type","=",r).executeTakeFirst();return de(l?.count)}}}var le={corsair_integrations:F,corsair_accounts:D,corsair_entities:P,corsair_events:B};function ye(e){return le[e]}function M(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function p(e){if(!e)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function b(e){if(!e)return[];let t=[];for(let r in e){let n=r,i=e[n];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let a=i;"in"in a&&Array.isArray(a.in)?t.push({field:n,operator:"in",value:a.in}):"like"in a&&typeof a.like=="string"&&t.push({field:n,operator:"like",value:a.like})}else t.push({field:n,value:i})}return t}function m(e,t){if(!t?.length)return e;let r=e;for(let n of t){let i=n.operator??"=";r=r.where(n.field,i,n.value)}return r}function fe(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function A(e,t){let r=ye(t),n=()=>(p(e),e),i=()=>n().db.selectFrom(t),a=()=>n().db.insertInto(t),u=()=>n().db.updateTable(t),o=()=>n().db.deleteFrom(t);function l(d){let s={};for(let[y,f]of Object.entries(d))s[y]=M(f);return r.parse(s)}function c(d){let s={};for(let[y,f]of Object.entries(d))s[y]=M(f);return r.parse(s)}return{findById:async d=>{p(e);let s=i().selectAll();s=m(s,[{field:"id",value:d}]);let y=await s.executeTakeFirst();return y?l(y):null},findOne:async d=>{p(e);let s=i().selectAll();s=m(s,b(d));let y=await s.executeTakeFirst();return y?l(y):null},findMany:async d=>{p(e);let s=i().selectAll();return s=m(s,b(d?.where)),typeof d?.limit=="number"&&(s=s.limit(d.limit)),typeof d?.offset=="number"&&(s=s.offset(d.offset)),(await s.execute()).map(f=>l(f))},create:async d=>{p(e);let s=new Date,y={id:d.id??T(),created_at:s,updated_at:s,...d},f=await a().values(y).returningAll().executeTakeFirst();return f?l(f):c(y)},update:async(d,s)=>{p(e);let y={...s,updated_at:new Date},f=u().set(y).returningAll();f=m(f,[{field:"id",value:d}]);let g=await f.executeTakeFirst();return g?l(g):null},updateMany:async(d,s)=>{p(e);let y={...s,updated_at:new Date},f=i().select("id");f=m(f,b(d));let g=await f.execute();for(let I of g){let E=u().set(y);E=m(E,[{field:"id",value:I.id}]),await E.execute()}return g.length},delete:async d=>{p(e);let s=o();s=m(s,[{field:"id",value:d}]);let y=await s.executeTakeFirst();return Number(y?.numDeletedRows??0)>0},deleteMany:async d=>{p(e);let s=o();s=m(s,b(d));let y=await s.executeTakeFirst();return Number(y?.numDeletedRows??0)},count:async d=>{p(e);let s=i().select(f=>f.fn.countAll().as("count"));s=m(s,b(d));let y=await s.executeTakeFirst();return fe(y?.count)}}}function pe(e){let t=A(e,"corsair_integrations");return{...t,findByName:r=>t.findOne({name:r}),upsertByName:async(r,n)=>{let i=await t.findOne({name:r});return i?await t.update(i.id,n):t.create({...n,name:r})}}}function ge(e){let t=A(e,"corsair_accounts");return{...t,findByTenantAndIntegration:async(r,n)=>{p(e);let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();return i?t.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,n)=>t.findMany({where:{tenant_id:r},limit:n?.limit,offset:n?.offset}),upsertByTenantAndIntegration:async(r,n,i)=>{let a=await t.findOne({tenant_id:r,integration_id:n});return a?await t.update(a.id,i):t.create({...i,tenant_id:r,integration_id:n})}}}function me(e){let t=A(e,"corsair_entities");return{...t,findByEntityId:({accountId:r,entityType:n,entityId:i})=>t.findOne({account_id:r,entity_type:n,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:n,entityIds:i})=>i.length===0?[]:(p(e),await e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",n).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:n,limit:i,offset:a})=>t.findMany({where:{account_id:r,entity_type:n},limit:i,offset:a}),searchByEntityId:async({accountId:r,entityType:n,query:i,limit:a,offset:u})=>{p(e);let o=e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",n).where("entity_id","like",`%${i}%`);return typeof a=="number"&&(o=o.limit(a)),typeof u=="number"&&(o=o.offset(u)),await o.execute()},upsertByEntityId:async({accountId:r,entityType:n,entityId:i,version:a,data:u})=>{let o=await t.findOne({account_id:r,entity_type:n,entity_id:i});return o?await t.update(o.id,{version:a,data:u}):t.create({account_id:r,entity_type:n,entity_id:i,version:a,data:u})},deleteByEntityId:async({accountId:r,entityType:n,entityId:i})=>{p(e);let a=await e.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",n).where("entity_id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0}}}function we(e){let t=A(e,"corsair_events");return{...t,listByAccount:(r,n)=>t.findMany({where:{account_id:r},limit:n?.limit,offset:n?.offset}),listByStatus:(r,n)=>{let i={status:r};return n?.accountId&&(i.account_id=n.accountId),t.findMany({where:i,limit:n?.limit,offset:n?.offset})},listPending:r=>{let n={status:"pending"};return r?.accountId&&(n.account_id=r.accountId),t.findMany({where:n,limit:r?.limit??100})},updateStatus:(r,n)=>t.update(r,{status:n})}}function Q(e){return{integrations:pe(e),accounts:ge(e),entities:me(e),events:we(e)}}function he(e,t,r,n,i){let a=null;async function u(){if(a!==null)return a;p(e);let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t.integrationName).executeTakeFirst();if(!o)throw new Error(`Integration "${t.integrationName}" not found. Make sure to create the integration first.`);let l=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t.tenantId).where("integration_id","=",o.id).executeTakeFirst();if(!l)throw new Error(`Account not found for tenant "${t.tenantId}" and integration "${t.integrationName}". Make sure to create the account first.`);return a=l.id,a}return p(e),$(e.db,u,r,n,i)}function z(e){let{database:t,integrationName:r,schema:n,tenantId:i}=e,a=Q(t),u={tenantId:i,integrationName:r},o=null;async function l(){if(o!==null)return o;p(t);let d=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!d)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);let s=await t.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",i).where("integration_id","=",d.id).executeTakeFirst();if(!s)throw new Error(`Account not found for tenant "${i}" and integration "${r}". Make sure to create the account first.`);return o=s.id,o}let c={};for(let[d,s]of Object.entries(n.entities))c[d]=he(t,u,d,n.version,s);return{...c,$orm:a,$integrationName:r,$tenantId:i,$getAccountId:l}}function $e(e,t){let r=Q(e);return{$tenantId:t,$orm:r,listAccounts:n=>r.accounts.listByTenant(t,n),findAccountByIntegration:n=>r.accounts.findByTenantAndIntegration(t,n),listEntities:async n=>{p(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).execute();if(i.length===0)return[];let a=i.map(o=>o.id),u=e.db.selectFrom("corsair_entities").selectAll().where("account_id","in",a);return n?.entityType&&(u=u.where("entity_type","=",n.entityType)),typeof n?.limit=="number"&&(u=u.limit(n.limit)),typeof n?.offset=="number"&&(u=u.offset(n.offset)),await u.execute()},listEvents:async n=>{p(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).execute();if(i.length===0)return[];let a=i.map(o=>o.id),u=e.db.selectFrom("corsair_events").selectAll().where("account_id","in",a);return n?.status&&(u=u.where("status","=",n.status)),typeof n?.limit=="number"&&(u=u.limit(n.limit)),typeof n?.offset=="number"&&(u=u.offset(n.offset)),await u.execute()},forIntegration:n=>z({database:e,integrationName:n.integrationName,schema:n.schema,tenantId:t})}}function Me(e,t){return{forTenant:r=>z({database:e,integrationName:t.integrationName,schema:t.schema,tenantId:r})}}export{_ as a,O as b,G as c,X as d,Y as e,L as f,R as g,V as h,ee as i,T as j,$ as k,le as l,Q as m,z as n,$e as o,Me as p};
@@ -0,0 +1,38 @@
1
+ import{a as se,b as nr,c as P,d as $,e as tr,f as J,g as E,h as H,i as en,j as rr,k as Zn,l as or,m as ir}from"./chunk-FLNFC4KL.js";import{a as er}from"./chunk-IGGCNGU2.js";var nn=["agentql","ahrefs","airtable","amplitude","asana","bitwarden","bluesky","box","cal","calendly","cloudflare","cursor","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","github","gitlab","gmail","googlecalendar","googledrive","googlesheets","grafana","hackernews","hubspot","intercom","jira","linear","monday","notion","onedrive","openweathermap","oura","outlook","pagerduty","posthog","razorpay","reddit","resend","sentry","sharepoint","slack","spotify","strava","stripe","tally","tavily","teams","telegram","todoist","trello","twilio","twitter","twitterapiio","typeform","vapi","xquik","youtube","zendesk","zohomail","zoom"],sr={agentql:"AgentQL",ahrefs:"Ahrefs",airtable:"Airtable",amplitude:"Amplitude",asana:"Asana",bitwarden:"Bitwarden",bluesky:"Bluesky",box:"Box",cal:"Cal",calendly:"Calendly",cloudflare:"Cloudflare",cursor:"Cursor",discord:"Discord",dodopayments:"Dodo Payments",dropbox:"Dropbox",exa:"Exa",figma:"Figma",firecrawl:"Firecrawl",fireflies:"Fireflies",github:"GitHub",gitlab:"GitLab",gmail:"Gmail",googlecalendar:"Google Calendar",googledrive:"Google Drive",googlesheets:"Google Sheets",grafana:"Grafana",hackernews:"Hacker News",hubspot:"HubSpot",intercom:"Intercom",jira:"Jira",linear:"Linear",monday:"Monday",notion:"Notion",onedrive:"OneDrive",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",resend:"Resend",sentry:"Sentry",sharepoint:"SharePoint",slack:"Slack",spotify:"Spotify",strava:"Strava",stripe:"Stripe",tally:"Tally",tavily:"Tavily",teams:"Teams",telegram:"Telegram",todoist:"Todoist",trello:"Trello",twilio:"Twilio",twitter:"Twitter",twitterapiio:"Twitter API IO",typeform:"Typeform",vapi:"Vapi",xquik:"XQuik",youtube:"YouTube",zendesk:"Zendesk",zohomail:"Zoho Mail",zoom:"Zoom"};function ae(e){let n=sr[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var $e="https://auth.corsair.dev";var he=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret, deliveryUrl } to createCorsair()."),this.name="HubNotConfiguredError"}};function tn(e){let n=(e.apiUrl?.trim()||$e).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim(),i=e.deliveryUrl.trim();if(!t||!r||!i)throw new Error("Hub config requires non-empty projectApiKey, signingSecret, and deliveryUrl");return{apiUrl:n,projectApiKey:t,signingSecret:r,deliveryUrl:i,oauthCallbackUrl:e.oauthCallbackUrl?.trim()}}function Ao(e){return e.apiUrl.trim().length>0&&e.deliveryUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function B(e){let n=P(e).hub;if(!n||!Ao(n))throw new he;return n}function rn(e){return e.oauthCallbackUrl?e.oauthCallbackUrl:`${e.apiUrl.replace(/\/$/,"")}/oauth/callback`}function x(e){return typeof e=="string"&&e.length>0}function on(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};return x(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function sn(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 an(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 xo(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function So(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 Ro(e,n,t,r){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"?e:n?"ready":t.some(o=>o.level==="integration"&&o.required&&!o.configured)?"missing_integration":t.some(o=>o.level==="account"&&o.required&&o.configured)?"partial":(r.length>0,"not_started")}function ar(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 i=r;if(!x(i.plugin)||typeof i.connected!="boolean")continue;let o=i.authKind==="oauth"||i.authKind==="api_key"||i.authKind==="bot_token"?i.authKind:"api_key",a=So(i.fields),s=xo(i.missingRequiredFields),u=Ro(i.status,i.connected,a,s);t.push({plugin:i.plugin,providerName:x(i.providerName)?i.providerName:i.plugin,authKind:o,status:u,connected:i.connected,fields:a,missingRequiredFields:s})}return{tenantId:n.tenantId,plugins:t}}function un(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function Io(e){return e.replace(/\/$/,"")}async function _o(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 Eo(e,n,t){if(n===404&&t)return t;let r=un(e);return r||`Hub API returned HTTP ${n}`}async function xe(e){let n=Io(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`},body:JSON.stringify(e.body)}),r=await _o(t);if(!t.ok)throw new Error(Eo(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as ur,createDecipheriv as cr,randomBytes as cn,scrypt as Do}from"crypto";import{promisify as Oo}from"util";var lr=Oo(Do),ln="aes-256-gcm",dr=12,dn=16,Mo=16,Le=32;function ee(){return cn(Le).toString("base64")}async function ne(e,n){let t=cn(Mo),r=await lr(n,t,Le),i=cn(dr),o=ur(ln,r,i,{authTagLength:dn}),a=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[t.toString("base64"),i.toString("base64"),s.toString("base64"),a.toString("base64")].join(":")}async function L(e,n){let[t,r,i,o]=e.split(":");if(!t||!r||!i||!o)throw new Error("Invalid encrypted DEK format");let a=Buffer.from(t,"base64"),s=Buffer.from(r,"base64"),u=Buffer.from(i,"base64"),c=Buffer.from(o,"base64"),d=await lr(n,a,Le),l=cr(ln,d,s,{authTagLength:dn});return l.setAuthTag(u),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function Gn(e,n){let t=Buffer.from(n,"base64"),r=cn(dr),i=ur(ln,t,r,{authTagLength:dn}),o=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[r.toString("base64"),a.toString("base64"),o.toString("base64")].join(":")}function We(e,n){let[t,r,i]=e.split(":");if(!t||!r||!i)throw new Error("Invalid encrypted data format");let o=Buffer.from(n,"base64"),a=Buffer.from(t,"base64"),s=Buffer.from(r,"base64"),u=Buffer.from(i,"base64"),c=cr(ln,o,a,{authTagLength:dn});return c.setAuthTag(s),Buffer.concat([c.update(u),c.final()]).toString("utf8")}function ue(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=Gn(i,n);return t}function te(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=We(i,n);return t}function je(e,n,t){let r=te(e,n);return ue(r,t)}function pr(e,n,t){let r={};for(let i of t)r[`get_${i}`]=async()=>(await e())[i]??null,r[`set_${i}`]=async o=>{let a=[null,void 0,""].includes(o)?null:o;await n({[i]:a})};return r}var Jn=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function I(e){let{authType:n,integrationName:t,kek:r,database:i,extraIntegrationFields:o=[]}=e,a=[...E[n].integration,...o],s=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(s)return s;let f=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!f)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return s={id:f.id,config:Jn(f.config),dek:f.dek??null},s},updateIntegration:async f=>{let y=await u.getIntegration();await i.db.updateTable("corsair_integrations").set({...f.config!==void 0?{config:f.config}:{},...f.dek!==void 0?{dek:f.dek}:{},updated_at:new Date}).where("id","=",y.id).execute(),s=null}},c=null,d=async()=>{if(c)return c;let f=await u.getIntegration();if(!f.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return c=await L(f.dek,r),c},l=async()=>{let f=await u.getIntegration(),y=await d(),h=f.config;return!h||Object.keys(h).length===0?{}:te(h,y)};return{get_dek:d,issue_new_dek:async()=>{let f=await u.getIntegration(),y=ee(),h={};if(f.dek){let C=await L(f.dek,r),b=f.config;b&&Object.keys(b).length>0&&(h=je(b,C,y))}let m=await ne(y,r);return await u.updateIntegration({config:h,dek:m}),c=y,y},...pr(l,async f=>{let y=await d(),h;try{h=await l()}catch(b){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,b),h={}}let m={...h};for(let[b,k]of Object.entries(f))k===null?delete m[b]:m[b]=k;let C=ue(m,y);await u.updateIntegration({config:C})},a)}}function R(e){let{authType:n,integrationName:t,tenantId:r,kek:i,database:o,extraAccountFields:a=[]}=e,s=[...E[n].account,...a],u=null,c=null,d=async()=>{if(c)return c;let k=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!k)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return c={id:k.id,config:Jn(k.config),dek:k.dek??null},c},l={kek:i,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(u)return u;let k=await d(),w=await o.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",k.id).executeTakeFirst();if(!w)throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`);return u={id:w.id,config:Jn(w.config),dek:w.dek??null},u},updateAccount:async k=>{let w=await l.getAccount();await o.db.updateTable("corsair_accounts").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",w.id).execute(),u=null}},p=null,g=null,f=async()=>{if(p)return p;let k=await l.getAccount();if(!k.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return p=await L(k.dek,i),p},y=async()=>{if(g)return g;let k=await l.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return g=await L(k.dek,i),g},h=async()=>{let k=await l.getAccount(),w=await f(),T=k.config;return!T||Object.keys(T).length===0?{}:te(T,w)},m=async()=>{let k=await l.getIntegration(),w=await y(),T=k.config;return!T||Object.keys(T).length===0?{}:te(T,w)},b={get_dek:f,issue_new_dek:async()=>{let k=await l.getAccount(),w=ee(),T={};if(k.dek){let O=await L(k.dek,i),M=k.config;M&&Object.keys(M).length>0&&(T=je(M,O,w))}let D=await ne(w,i);return await l.updateAccount({config:T,dek:D}),p=w,w},...pr(h,async k=>{let w=await f(),T;try{T=await h()}catch(M){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,M),T={}}let D={...T};for(let[M,A]of Object.entries(k))A===null?delete D[M]:D[M]=A;let O=ue(D,w);await l.updateAccount({config:O})},s)};return n==="oauth_2"&&(b.get_integration_credentials=async()=>{let k=await m();return{client_id:k.client_id||null,client_secret:k.client_secret||null,redirect_url:k.redirect_url??null}}),b}async function gr(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 i=ee(),o=await ne(i,t);return await e.db.updateTable("corsair_integrations").set({dek:o,updated_at:new Date}).where("id","=",r.id).execute(),i}async function fr(e,n,t,r){let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!i)throw new Error(`Integration "${n}" not found.`);let o=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",i.id).executeTakeFirst();if(!o)throw new Error(`Account not found for tenant "${t}" and integration "${n}".`);let a=ee(),s=await ne(a,r);return await e.db.updateTable("corsair_accounts").set({dek:s,updated_at:new Date}).where("id","=",o.id).execute(),a}var Ho=new Set(["webhook_signature","expires_at","scope","redirect_url"]);function Se(e){return Ho.has(e)}function Fo(e,n){return Se(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Bo(e){return!Se(e)}function Uo(e){switch(e){case"oauth_2":case"managed":return["access_token","refresh_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function No(e,n){return Uo(e).every(r=>n.find(o=>o.level==="account"&&o.name===r)?.configured??!1)}async function yr(e,n){if(!e)return!1;let t=J(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function $o(e,n){let r=e.authConfig?.[n]?.integration??[];return[...E[n].integration,...r]}function Lo(e,n){let r=e.authConfig?.[n]?.account??[];return[...E[n].account,...r]}function Wo(e,n,t){let r=t.filter(s=>s.required&&!s.configured).map(s=>s.name),i=t.filter(s=>s.level==="integration"&&s.required&&!s.configured).map(s=>s.name),o=t.filter(s=>s.level==="account"&&s.required&&s.configured),a;return i.length>0?a="missing_integration":r.length===0?a="ready":o.length>0?a="partial":a="not_started",{plugin:e,authType:n,status:a,connected:No(n,t),fields:t,missingRequiredFields:r}}async function pn(e,n,t){let r=H(n);if(!r||!e.database||!e.kek)return null;let i=t.trim()||"default",o=n.authConfig,a=o?.[r]?.integration??[],s=o?.[r]?.account??[],u=I({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:a}),c=R({authType:r,integrationName:n.id,tenantId:i,kek:e.kek,database:e.database,extraAccountFields:s}),d=$o(n,r),l=Lo(n,r),p=[];for(let g of d)p.push({name:g,level:"integration",required:Fo(r,g),configured:await yr(u,g)});for(let g of l)p.push({name:g,level:"account",required:Bo(g),configured:await yr(c,g)});return Wo(n.id,r,p)}async function Ke(e,n,t={}){let r=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,o=[];for(let a of e.plugins){if(i&&!i.has(a.id))continue;let s=await pn(e,a,r);s&&o.push(s)}return o}function gn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}import*as qe from"crypto";function z(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function zn(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 i=r;return n!==void 0&&typeof i.iat=="number"&&Date.now()-i.iat>n?null:i}return null}catch{return null}}function ce(e,n){let t=qe.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Vn=600*1e3;function fn(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),i=e.slice(t+1),o=qe.createHmac("sha256",n).update(r).digest("base64url"),a=Buffer.from(i,"base64url"),s=Buffer.from(o,"base64url");return a.length!==s.length||!qe.timingSafeEqual(a,s)?null:zn(r,{maxAgeMs:Vn})}var jo=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Ze(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:jo.has(n)}catch{return!1}}function Re(e){return Ze(e)?"client":"server"}function hr(e,n){return e==="client"||Ze(n)}function Ie(e){if(!e.source)return null;let n=Ze(e.deliveryUrl);return e.source==="server"&&n?{error:'source "server" cannot be used with a loopback delivery URL \u2014 omit source to auto-detect or use "client"',status:400}:e.oauthMode==="managed"&&e.source==="client"&&!n?{error:'managed OAuth with source "client" requires a loopback delivery URL \u2014 omit source for production server delivery',status:400}:null}import{ZodBoolean as qo,ZodDate as Zo,ZodEnum as Go,ZodNullable as Jo,ZodNumber as zo,ZodObject as Vo,ZodOptional as Yo,ZodRecord as Qo,ZodString as Xo,ZodType as ei}from"zod";var Ko={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:{}}},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:{}}}},Yn=Ko;async function kr(e,n){let t=[],r=p=>{t.push(p),console.log(p)},i=p=>{t.push(p),console.warn(p)},o=n?.caller??"script",a=nr(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 s=ti(e,a.plugins,n),u={...a,database:a.database},c=u.database.db;await ii(c,i);let d=await si(c,u,s.tenantId,s.provisionAccounts,r);n?.credentials&&Object.keys(n.credentials).length>0&&await ci(e,s,n.credentials,u,r,i);let l=await di(d,s,r,o);if(n?.backfill){r("[corsair:setup] Starting backfill...");let p=Cr({plugins:a.plugins,database:c,kek:a.kek,multiTenancy:!0}).withTenant(s.tenantId);await pi(p,a.plugins,l,r,i),r("[corsair:setup] Backfill complete.")}return t.join(`
2
+ `)}function Qn(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...E[n][t],...r])}function ni(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let i=n.find(s=>s.id===t);if(!i)continue;let o=H(i);if(!o)continue;let a=Qn(i,o,"account");for(let s of Object.keys(r))if(a.has(s))return!0}return!1}function ti(e,n,t){let r=tr(e),i=t?.tenantId?.trim(),o=i!==void 0&&i.length>0;if(r&&t?.backfill&&!o)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(r&&ni(t?.credentials,n)&&!o)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(o&&!i)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:r,tenantIdProvided:o,tenantId:o?i:"default",provisionAccounts:!r||o}}function br(e,n){return se(e)?n===0?!0:Object.values(e).every(t=>br(t,n-1)):!1}function ri(e){return br(e,4)}var oi={...or};function yn(e){if(e instanceof Vo){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof ei?yn(r):"unknown";return n}return e instanceof Jo?`${yn(e.unwrap())} | null`:e instanceof Yo?`${yn(e.unwrap())} | undefined`:e instanceof Go?e.options.join(" | "):e instanceof Xo?"string":e instanceof zo?"number":e instanceof qo?"boolean":e instanceof Zo?"date":e instanceof Qo?"jsonb":"unknown"}async function ii(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(i=>i.name));for(let[i,o]of Object.entries(oi))r.has(i)||n(`[corsair:setup] Table "${i}" does not exist. Run your database migrations before calling setupCorsair.
3
+ Schema: ${JSON.stringify(yn(o),null,2)}`)}async function si(e,n,t,r,i){let o=new Date,a=new Map;for(let s of n.plugins){let u=s.id,c=H(s),d=await e.selectFrom("corsair_integrations").selectAll().where("name","=",u).executeTakeFirst();if(!d){let y=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:y,name:u,config:{},created_at:o,updated_at:o}).execute(),d=await e.selectFrom("corsair_integrations").selectAll().where("id","=",y).executeTakeFirst(),i(`[corsair:setup] Created integration: ${u}`)}let l=c?s.authConfig?.[c]?.integration??[]:[],p=c?s.authConfig?.[c]?.account??[]:[],g=c&&d?I({authType:c,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:l}):void 0;if(d&&!d.dek&&g&&(await g.issue_new_dek(),i(`[corsair:setup] Issued integration DEK: ${u}`)),!d||!c||!g)continue;let f;if(r){let y=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",d.id).executeTakeFirst();if(!y){let h=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:h,tenant_id:t,integration_id:d.id,config:{},created_at:o,updated_at:o}).execute(),y=await e.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),i(`[corsair:setup] Created account: ${u}`)}f=y&&R({authType:c,integrationName:u,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:p}),y&&f&&!y.dek&&(await f.issue_new_dek(),i(`[corsair:setup] Issued account DEK: ${u}`))}a.set(u,{pluginId:u,authType:c,integration:g,account:f,integrationFields:[...E[c].integration,...l],accountFields:r?[...E[c].account,...p]:[]})}return a}function ai(e){if(!se(e))return;let n=e.keys;return se(n)?n:void 0}function ui(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function ci(e,n,t,r,i,o){let a=ai(e),s=n.provisionAccounts?ui(e,n.tenantId):void 0;for(let[u,c]of Object.entries(t)){let d=r.plugins.find(m=>m.id===u);if(!d){o(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let l=H(d);if(!l){o(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let p=Qn(d,l,"integration"),g=Qn(d,l,"account"),f=a?.[u],y=s?.[u],h=se(y)?y.keys:void 0;for(let[m,C]of Object.entries(c))if(C){if(p.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 b=J(f,`set_${m}`);if(!b){o(`[corsair:setup] Cannot set integration field '${m}' for '${u}'.`);continue}await b(C),i(`[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 b=J(h,`set_${m}`);if(!b){o(`[corsair:setup] Cannot set account field '${m}' for '${u}'.`);continue}await b(C),i(`[corsair:setup] Set ${u} account.${m} (tenant=${n.tenantId})`);continue}o(`[corsair:setup] Unknown credential field '${m}' for plugin '${u}'.`)}}}var mr=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function li(e,n,t,r,i,o,a,s,u){let c=[],d=[];for(let p of i){if(mr.has(p))continue;let g=J(t,`get_${p}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||c.push(p)}if(r&&o.length>0)for(let p of o){if(mr.has(p))continue;let g=J(r,`get_${p}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||d.push(p)}let l=c.length===0&&d.length===0;if(l)s(`[corsair:setup] '${e}' (${n}) is configured \u2713`);else if(n==="managed")s(`[corsair:setup] '${e}' (managed) is not connected yet. Use Connect in your app \u2014 Corsair Hub delivers OAuth tokens after authorization.`);else{let p=[...c,...d];if(u==="cli"){let g=p.map(f=>`${f}=VALUE`).join(" ");s(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
4
+ corsair setup --${e} ${g}`)}else{let g=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let f of c)g.push(` await corsair.keys.${e}.set_${f}(value)`);for(let f of d){let y=a.provisionAccounts?a.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(a.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;g.push(` await ${y}.keys.set_${f}(value)`)}s(g.join(`
5
+ `))}}return l}async function di(e,n,t,r){let i=new Set;for(let o of e.values())await li(o.pluginId,o.authType,o.integration,o.account,o.integrationFields,o.accountFields,n,t,r)&&i.add(o.pluginId);return i}async function pi(e,n,t,r,i){if(!ri(Yn)){i("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let o=Yn,a=new Set(n.map(s=>s.id));for(let[s,u]of Object.entries(o)){if(!a.has(s))continue;if(!t.has(s)){r(`[corsair:setup] Skipping backfill for '${s}' \u2014 auth not configured.`);continue}let c=se(e)?e[s]:void 0,d=se(c)?c.api:void 0;if(d)for(let[l,p]of Object.entries(u))for(let[g,f]of Object.entries(p)){r(`[corsair:setup] Backfilling ${s} \u203A ${l}.${g}...`);try{let y=se(d)?d[l]:void 0;await J(y,g)?.(f)}catch(y){i(`[corsair:setup] ${s} \u203A ${l}.${g} failed: `+(y instanceof Error?y.message:String(y)))}}}}async function _e(e,n){if(!P(e).database)throw new Error("A database must be configured to provision Corsair for connect");await kr(e,{tenantId:n})}var gi=new Set(["access_token","refresh_token","expires_at","scope"]);function fi(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function yi(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!Se(t)&&!gi.has(t)):n.filter(t=>!Se(t))}async function wr(e,n,t={}){let r=P(e),i=B(e),o=rn(i),a=[],s=t.pluginIds?new Set(t.pluginIds):null;for(let u of r.plugins){if(s&&!s.has(u.id))continue;let c=H(u);if(!c)continue;let d=fi(c),l=t.providerNameOverrides?.[u.id]??ae(u.id),p=await pn(r,u,n),g=en(u,c),f=yi(c,g),y={plugin:u.id,providerName:l,authKind:d,alreadyConfigured:p?.connected??!1};if(f.length>0&&(y.credentialFields=f),d==="oauth"){let m=t.oauthModeOverrides?.[u.id]??(c==="managed"?"managed":"byo");if(y.oauthMode=m,!t.skipOAuthUrlGeneration)if(m==="managed")y.state=ce(z(u.id,n),r.kek);else try{let C=await Xn(e,u.id,{tenantId:n,redirectUri:o});y.oauthUrl=C.url,y.state=C.state}catch(C){y.setupError=C instanceof Error?C.message:`Could not prepare OAuth for ${u.id}`}}a.push(y)}return a}function Tr(e,n){let t=B(e);if(n){let r=Ie({source:n,deliveryUrl:t.deliveryUrl});if(r)throw new Error(r.error);return n}return Re(t.deliveryUrl)}async function Pr(e,n){await _e(e,n)}async function hn(e,n){let t=B(e);await Pr(e,n.tenantId);let r=n.plugin?[n.plugin]:void 0,i=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,o=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,a=await wr(e,n.tenantId,{pluginIds:r,oauthModeOverrides:i,providerNameOverrides:o});if(a.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");let s=Tr(e,n.source);return xe({hub:t,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:{tenantId:n.tenantId,deliveryUrl:t.deliveryUrl,source:s,plugins:a},parseResponse:on})}function vr(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function hi(e,n){return n&&!n.has(e.id)?!1:H(e)!==null}async function Ee(e,n,t={}){let r=P(e),i=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,a=await Ke(r,i,{pluginIds:t.pluginIds}),s=new Map(a.map(c=>[c.plugin,c])),u=r.plugins.filter(c=>hi(c,o)).map(c=>{let d=H(c),l=s.get(c.id);return l?{plugin:c.id,providerName:ae(c.id),authKind:vr(d),status:l.status,connected:l.connected,fields:l.fields.map(p=>({name:p.name,level:p.level,required:p.required,configured:p.configured})),missingRequiredFields:l.missingRequiredFields}:{plugin:c.id,providerName:ae(c.id),authKind:vr(d),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:i,plugins:u}}var le=6e4,me=3e5;var V=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function mn(e,n){let t=P(e,()=>new V("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new V("no_database","Database not configured");let r=$(t,n.plugin,d=>new V("plugin_not_found",d)),i=H(r);if(!i)throw new V("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(i==="oauth_2"||i==="managed")throw new V("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await _e(e,n.tenantId);let o=new Set(en(r,i)),s=r.authConfig?.[i]?.account??[],u=R({authType:i,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:s}),c=0;for(let[d,l]of Object.entries(n.credentials)){if(!l.trim())continue;if(!o.has(d))throw new V("invalid_credentials",`Unknown credential field '${d}' for plugin '${n.plugin}'`);let p=J(u,`set_${d}`);if(!p)throw new V("invalid_credentials",`Cannot set credential field '${d}' for plugin '${n.plugin}'`);await p(l.trim()),c+=1}if(c===0)throw new V("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var kn=new Map;function mi(e){for(let[n,t]of kn)t<=e&&kn.delete(n)}function bn(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return mi(r),kn.has(t)?{ok:!1,error:"Delivery request already consumed"}:(kn.set(t,r+n),{ok:!0})}async function Cn(e,n,t){for(let r of e){if(r.id!==n)continue;let i=r.oauthWebhookTenantLinkResolver;return i?i(t):null}return null}var Ar=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function ki(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 bi(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 L(n.dek,e.kek),r=Ar(n.config),i={};Object.keys(r).length>0&&(i=te(r,t)),i[e.link.linkType]=e.link.externalId;let o=ue(i,t);await e.database.db.updateTable("corsair_accounts").set({config:o,updated_at:new Date}).where("id","=",n.id).execute()}async function De(e){let{database:n,kek:t,pluginId:r,tenantId:i,link:o,authType:a,extraAccountFields:s=[]}=e,{accountId:u}=await ki({database:n,pluginId:r,tenantId:i}),c=!1;if(a){let d=R({authType:a,integrationName:r,tenantId:i,kek:t,database:n,extraAccountFields:s}),l=`set_${o.linkType}`,p=d[l];typeof p=="function"&&(await p(o.externalId),c=!0)}c||await bi({database:n,kek:t,accountId:u,link:o})}async function et(e){let{database:n,kek:t,pluginId:r,linkType:i,externalId:o}=e,a=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 s of a)if(s.dek)try{let u=await L(s.dek,t),d=Ar(s.config)[i];if(!d)continue;if(We(d,u)===o)return s}catch{continue}return null}async function wn(e){return(await et(e))?.tenant_id??null}async function xr(e){return wn({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var de=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Oe(e,n){let{plugin:t,tenantId:r,accessToken:i,refreshToken:o,expiresIn:a,scope:s}=n;if(!i.trim())throw new de("no_access_token","Managed OAuth delivery missing access_token");let u=P(e,()=>new de("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new de("no_database","No database configured on corsair instance");let c=$(u,t,l=>new de("plugin_not_found",l));await _e(e,r);let d=R({authType:"managed",integrationName:t,tenantId:r,kek:u.kek,database:u.database});await d.set_access_token(i),o&&await d.set_refresh_token(o),a&&await d.set_expires_at(String(Math.floor(Date.now()/1e3)+a)),s&&await d.set_scope(s);try{let l=await Cn(u.plugins,t,{access_token:i,refresh_token:o,scope:s});if(l)try{let p=c.authConfig?.managed?.account??[];await De({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:l,authType:"managed",extraAccountFields:p})}catch(p){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,p)}}catch(l){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,l)}return{plugin:t,tenantId:r}}import{createHmac as nt,randomUUID as Ci,timingSafeEqual as Sr}from"crypto";function Rr(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function Tn(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=nt("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":Ci()}}}function tt(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Rr(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>3e5)return!1;let o=nt("sha256",n).update(e.body).digest("hex");try{return Sr(Buffer.from(o,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function Me(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=Rr(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)>3e5)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let o=nt("sha256",n).update(e.body).digest("hex");try{if(!Sr(Buffer.from(o,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}function rt(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function ot(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function it(e){return e.status===0?`Could not reach delivery URL (${e.deliveryUrl}): ${e.ack.error??e.body}`:e.ack.error??e.body??`HTTP ${e.status}`}async function st(e){let{body:n,headers:t}=Tn(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),i=await r.text();return{ok:r.ok,status:r.status,body:i}}catch(r){return{ok:!1,status:0,body:r instanceof Error?r.message:"Delivery request failed"}}}function wi(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Ir(e,n,t=[]){for(let[r,i]of Object.entries(e))if(wi(i)){if(i.match(n))return{webhook:i,path:[...t,r]}}else if(i&&typeof i=="object"){let o=Ir(i,n,[...t,r]);if(o)return o}return null}function Ti(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Pi(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 _r(e,n,t,r){let i=Ti(n),o=typeof t=="string"?JSON.parse(t):t;(!o||typeof o=="object"&&Object.keys(o).length===0)&&i["x-goog-resource-uri"]&&(o=Pi(i)||o);let s={headers:i,body:o,...r?{query:r}:{}},u=r?.tenantId||"default",c=e.withTenant?e.withTenant(u):e,d=nn;for(let l of d){let p=c[l];if(!p||!p.webhooks||p.pluginWebhookMatcher&&!p.pluginWebhookMatcher(s))continue;let g=Ir(p.webhooks,s);if(!g)continue;let f=g.path.join("."),y={payload:o,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let h=await g.webhook.handler(y),m=!!Object.keys(h.returnToSender||{})?.length;return{plugin:l,action:f,body:o,response:m?{...h?.returnToSender,success:!0}:{success:!0},...h.responseHeaders&&{responseHeaders:h.responseHeaders}}}catch(h){return console.error(`Error executing webhook handler for ${l}.${f}:`,h),{plugin:l,action:f,body:o,response:{success:!1,error:h instanceof Error?h.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{randomBytes as Si}from"crypto";import{createHmac as vi,randomBytes as Ai,timingSafeEqual as xi}from"crypto";function re(){return Ai(16).toString("base64url")}function Ge(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return vi("sha256",t).update(e).digest("base64url")}function Y(e,n){let t=n.trim();if(!t)return null;let r=e.split(".");if(r.length!==2)return null;let[i,o]=r;if(!i||!o)return null;let a=Ge(i,t);try{if(!xi(Buffer.from(o,"utf8"),Buffer.from(a,"utf8")))return null}catch{return null}let s;try{s=JSON.parse(Buffer.from(i,"base64url").toString("utf8"))}catch{return null}return s.exp*1e3<Date.now()?null:s}function Pn(e,n,t){let r=Math.floor(Date.now()/1e3),i={...e,iat:r,exp:t},o=Buffer.from(JSON.stringify(i)).toString("base64url"),a=Ge(o,n);return`${o}.${a}`}function Je(e,n,t){let r=Math.floor(Date.now()/1e3);return Pn(e,n,r+Math.floor(t/1e3))}function ke(e){return decodeURIComponent(e)}function at(e){return encodeURIComponent(e)}function Er(e){let n=e.trim();return n.length>0?n:null}function vn(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function An(e,n){if(!Er(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??Si(16).toString("base64url"),iat:t,exp:t+Math.floor(6e4/1e3)},i=Buffer.from(JSON.stringify(r)).toString("base64url"),o=Ge(i,n);return`${i}.${o}`}function pe(e,n){return Er(n)?Y(e,n):null}function be(e){return e.deliveryMode==="connect.status"}function Ce(e){return e.deliveryMode==="auth.credentials"}function ze(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function Ve(e){return e.deliveryMode==="oauth.tokens"}function xn(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!be(e)&&!Ce(e)&&!ze(e)&&!Ve(e)}function ut(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 Ri(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 wn({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Ii(e,n,t){let r=await Ri(e,n,t),i={...t.query??{},...r?{tenantId:r}:{}},o=await _r(e,t.headers,t.body,i);if(!o.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(o.response&&o.response.success===!1)return{status:"failed",retryable:!1,error:typeof o.response.error=="string"?o.response.error:"Webhook handler failed"};let a=o.response?.returnToSender,s=a&&typeof a=="object"&&typeof a.validationToken=="string"&&Object.keys(a).length===1?a.validationToken:a||(o.response?.data??o.response);return{status:"ok",webhookResponse:{status:o.response?.statusCode??200,body:s,headers:o.responseHeaders}}}async function _i(e,n){return await Ye(e,n),{status:"ok"}}async function Ei(e,n){return await Oe(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function lt(e,n,t){let r=await ct(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function ct(e,n,t){let r=P(e),i=n.token?.trim();if(!i)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let o=new Date().toISOString(),a=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",i).executeTakeFirst();return a?a.status!=="pending"?{status:"ok"}:a.expires_at<o?(await r.database.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",a.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","=",a.id).execute(),{status:"ok"}):{status:"failed",retryable:!1,error:"Permission not found"}}async function Di(e,n){try{return await mn(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function Oi(e,n){let t=n.tenantId?.trim()||"default";try{return{status:"ok",webhookResponse:{status:200,body:await Ee(e,t,{pluginIds:n.plugins})}}}catch(r){return{status:"failed",retryable:!1,error:r instanceof Error?r.message:"Connect status introspection failed"}}}async function dt(e,n,t={}){let r=P(e),i=ut(n.headers,"x-corsair-signature"),o=ut(n.headers,"x-corsair-timestamp"),a=ut(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let u=Me({body:n.body,signatureHeader:i,timestampHeader:o,signingSecret:t.signingSecret});if(!u.ok)return{status:"failed",retryable:!1,error:u.error};if(!a?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let c=bn(`nonce:${a.trim()}`,3e5);if(!c.ok)return{status:"failed",retryable:!1,error:c.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let s;try{s=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}switch(s.type){case"webhook":return Ii(e,r,s.payload);case"oauth.callback":return _i(e,s.payload);case"oauth.tokens":return Ei(e,s.payload);case"permission.approve":return ct(e,s.payload,"approved");case"permission.deny":return ct(e,s.payload,"denied");case"auth.credentials":return Di(e,s.payload);case"connect.status":return Oi(e,s.payload);default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${s.type}`}}}var Mi="corsair:client-bridge";function Dr(e){let n=JSON.stringify({type:Mi,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(e.hubOrigin);return`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><script>
6
+ (function () {
7
+ var message = ${n};
8
+ var targetOrigin = ${t};
9
+ if (window.parent && window.parent !== window) {
10
+ window.parent.postMessage(message, targetOrigin);
11
+ }
12
+ })();
13
+ </script></body></html>`}var Hi=[".corsair.dev"];function Fi(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Bi(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Fi(n)?!0:Hi.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Or(e){return!e||!Bi(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 Mr(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,i]of Object.entries(n))t.set(r,i);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function Sn(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 pt(e,n){let t=B(e),i=new URL(n).searchParams.get("d");if(!i)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let o=pe(i,t.signingSecret);if(!o)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let a=bn(`browser:${o.jti}`,6e4);if(!a.ok)return{type:"json",status:400,body:{error:a.error}};try{if(be(o)){if(!o.hubSuccessUrl)return{type:"json",status:400,body:{error:"Connect status delivery missing hubSuccessUrl"}};let s=o.tenantId?.trim()||"default",u=await Ee(e,s,{pluginIds:o.statusPlugins});return{type:"redirect",url:Sn(o.hubSuccessUrl,{status:u})}}if(Ce(o))return o.hubSuccessUrl?o.credentials?(await mn(e,{plugin:o.plugin,tenantId:o.tenantId,credentials:o.credentials}),{type:"redirect",url:Sn(o.hubSuccessUrl,{connectedPlugin:o.plugin})}):{type:"redirect",url:Sn(o.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(ze(o)){if(!o.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await lt(e,o.permissionToken,o.deliveryMode==="permission.approve"?"approved":"denied")}else if(Ve(o)){if(!o.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Oe(e,{plugin:o.plugin,tenantId:o.tenantId,accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn,scope:o.scope})}else{if(!xn(o)||!o.code||!o.state||!o.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await Ye(e,{code:o.code,state:o.state,redirectUri:o.redirectUri})}}catch(s){let u=s instanceof Error?s.message:"Hub delivery failed";return(be(o)||Ce(o))&&o.hubSuccessUrl?{type:"redirect",url:Sn(o.hubSuccessUrl,{error:u})}:(be(o)||Ce(o))&&o.hubOrigin&&o.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Dr({hubOrigin:o.hubOrigin,requestId:o.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:o.hubSuccessUrl}}async function gt(e,n){let t=B(e),r=await dt(e,n,{signingSecret:t.signingSecret});if(r.status!=="ok")return{type:"json",status:r.retryable===!1?400:502,body:{error:r.error??"Tunnel processing failed"}};let i=r.webhookResponse;if(!i)return{type:"json",status:200,body:{status:"ok"}};let o=i.status??200,a=i.headers;return i.body&&typeof i.body=="object"&&!(i.body instanceof ArrayBuffer)?{type:"json",status:o,body:i.body,headers:a}:{type:"text",status:o,body:typeof i.body=="string"?i.body:i.body?JSON.stringify(i.body):null,headers:a}}function ft(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 yt(e,n){return n.method==="GET"?pt(e,n.url):gt(e,{headers:n.headers,body:n.body??""})}async function ht(e,n){try{let t=await yt(e,n);return ft(t)}catch(t){if(t instanceof he)return Response.json({error:t.message},{status:503});throw t}}async function we(e,n){let t=n.method.toUpperCase(),r=Or(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 i=await ht(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return Mr(i,r)}var oe=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 Hr=300;async function mt(e,n){let{keys:t,hub:r,plugin:i,tenantId:o}=e,a=n?.forceRefresh??!1,[s,u,c]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!s&&!c)throw new oe(i,"managed");let d=Math.floor(Date.now()/1e3);if(!a&&s&&u&&Number(u)>d+Hr)return{accessToken:s,expiresAt:Number(u),refreshed:!1};if(!c&&s&&!a){let g=u?Number(u):null;if(g===null||g>d+Hr)return{accessToken:s,expiresAt:g??d+3600,refreshed:!1}}let l=await xe({hub:r,path:"/oauth/refresh",body:{plugin:i,tenantId:o},parseResponse:an}),p=l.expires_in?d+l.expires_in:u?Number(u):d+3600;return await t.set_access_token(l.access_token),await t.set_expires_at(String(p)),l.refresh_token&&await t.set_refresh_token(l.refresh_token),l.scope&&await t.set_scope(l.scope),{accessToken:l.access_token,expiresAt:p,refreshed:!0}}async function Fr(e,n){e._refreshAuth=async()=>(await mt(n,{forceRefresh:!0})).accessToken}async function Rn(e,n){return xe({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:{permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,deliveryUrl:e.deliveryUrl,expiresAt:n.expiresAt},parseResponse:sn})}function In(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}function Br(e){return{delivery:n=>we(e,n),deliveryOptions:n=>we(e,n)}}var Ur=1200*1e3;function kt(){return re()}function bt(){return Ur}function Ct(e,n){return Je(e,n,Ur)}function wt(e,n){return Y(e,n)}function Tt(e){return ke(e)}var Nr=600*1e3;function Pt(){return re()}function vt(){return Nr}function At(e,n){return Je(e,n,Nr)}function xt(e,n){return Y(e,n)}function St(e){return at(e)}function Rt(e){return ke(e)}function It(){return re()}function _t(e,n,t){return Pn(e,n,Math.floor(t.getTime()/1e3))}function Et(e,n){return Y(e,n)}function Dt(e){return ke(e)}function _n(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(i,o){let a=t.length>1;throw new Error(`corsair.keys.${String(o)}: Cannot access keys because ${t.join(" and ")} ${a?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
14
+
15
+ To generate a KEK, run: openssl rand -base64 ${Le}`)}})}function He(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var Ui=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function $r(e,n,t,r,i){let o={pluginId:n,operation:t,input:r,originalError:e},a=Object.keys(i).find(c=>i[c]?.match(e,o));return await(i[a||"DEFAULT"]?.handler||Ui)(e,o)}import{randomBytes as $i}from"crypto";import{v4 as Li}from"uuid";var Ot="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 Ht(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Lr(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function Mt(e){return In(e)}async function Ft(e,n){if(Ht(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Lr(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await Rn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:Ni(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function Ni(e){try{return JSON.parse(e)}catch{return e}}async function En(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Ft(e,n);return{...n,approvalUrl:r}}async function Bt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:i,permissionToken:o,plugin:a,endpoint:s,args:u,tenantId:c,expiresAt:d,operationPath:l}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:o,id:i,plugin:a,endpoint:s,args:u});let g=await Ft({manual:t,hub:r},{id:i,token:o,plugin:a,endpoint:s,args:JSON.stringify(u),tenant_id:c,expires_at:d});return Ht(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):Mt(g):Ot:r?g?Mt(g):`Action '${l}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Ot}var Wi={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 ji(e,n,t){return t!==void 0?t:Wi[n][e]}function Ut(e){let n=/(\d+)(d|h|m|s)/g,t=0,r;for(;(r=n.exec(e))!==null;){let i=parseInt(r[1],10);switch(r[2]){case"d":t+=i*864e5;break;case"h":t+=i*36e5;break;case"m":t+=i*6e4;break;case"s":t+=i*1e3;break}}return t>0?t:600*1e3}function jr(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 Wr(e,n,t){let r=Date.now()+t;for(;Date.now()<r;){let i=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).executeTakeFirst();if(!i)return{result:"blocked",reason:"pending"};if(i.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(i.status==="denied")return{result:"blocked",reason:"denied"};if(i.status==="expired"||i.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(o=>setTimeout(o,500))}return{result:"blocked",reason:"timeout"}}async function Kr(e){let n=ji(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}'.`,`
16
+ Action: ${r}`,`
17
+ To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let i=JSON.stringify(e.args),o=new Date().toISOString(),a=e.tenantId??"default",s=await e.db.db.selectFrom("corsair_permissions").selectAll().where("plugin","=",e.pluginId).where("endpoint","=",e.endpointPath).where("args","=",i).where("tenant_id","=",a).where("expires_at",">",o).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(s){if(s.status==="approved"){let f=e.db,y=s.id;return{result:"allow",onComplete:async()=>{await f.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",y).execute()}}}return s.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
18
+ Action: ${r}`,`
19
+ Permission ID: ${s.id}`,`
20
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Wr(e.db,s.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:s.id,token:s.token,expiresAt:s.expires_at})}let u=Li(),c=$i(32).toString("hex"),d=e.timeoutMs??600*1e3,l=new Date(Date.now()+d).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:u,created_at:new Date,updated_at:new Date,token:c,plugin:e.pluginId,endpoint:e.endpointPath,args:i,tenant_id:a,status:"pending",expires_at:l}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
21
+ Action: ${r}`,`
22
+ Permission ID: ${u}`,`
23
+ Permission token: ${c}`,`
24
+ Expires at: ${l}`,`
25
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Wr(e.db,u,d):{result:"blocked",reason:"pending",id:u,token:c,expiresAt:l}}function Ki(e){return typeof e=="function"}function qi(e,n,t){let r=ce(z(e,n.tenantId??t??"default"),n.kek),i=new URL(n.baseUrl);i.searchParams.set("state",r);let o=i.toString(),a=n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:o,state:r}):`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${o}`;return new Error(a)}function Nt({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:i,errorHandlers:o,currentPath:a=[],keyBuilder:s,permissionsConfig:u,endpointMeta:c,database:d,permissionsOptions:l,tenantId:p,manualConfig:g,hubConfig:f}){for(let[y,h]of Object.entries(e)){let m=n?.[y];if(Ki(h)){let C=m,b=[...a,y].join("."),k=async(w={})=>{let T;if(u){let _=c?.[b],{result:Ae,reason:Z,onComplete:Ne,token:X,id:ye,expiresAt:N}=await Kr({pluginId:i,endpointPath:b,args:w,mode:u.mode,override:u.overrides?.[b],riskLevel:_?.riskLevel??"write",meta:_,db:d,timeoutMs:l?Ut(l.timeout):void 0,tenantId:p,approvalMode:l?.mode});if(Ae==="blocked"){let G;throw Z==="denied"?G=`Action '${b}' was denied by the user. Await further instructions before proceeding.`:Z==="policy"?G=`Action '${b}' is blocked by the permission policy. Update the corsair config to allow it.`:Z==="timeout"?G=`Action '${b}' timed out waiting for approval.`:X&&ye?G=await Bt({permissionsOptions:l,manual:g,hub:f,permissionId:ye,permissionToken:X,plugin:i,endpoint:b,args:w,tenantId:p??"default",expiresAt:N??new Date(Date.now()+(l?Ut(l.timeout):600*1e3)).toISOString(),operationPath:b}):G=`Action '${b}' requires user approval before it can run.`,new Error(G)}T=Ne}let D=async(_,Ae,Z)=>{try{return await h(Ae,Z)}catch(Ne){if(Ne instanceof Error){let X=await $r(Ne,i,b,typeof Z=="object"&&Z!==null?Z:{args:Z},o);if(_<(X.maxRetries||0)){let ye=_+1;console.log(`Retrying (${ye} / ${X.maxRetries})...`);let N;if(X.headersRetryAfterMs)N=X.headersRetryAfterMs;else switch(X.retryStrategy){case"exponential_backoff":N=Math.pow(2,ye-1)*1e3;break;case"exponential_backoff_jitter":let G=Math.pow(2,ye-1)*1e3,vo=(Math.random()-.5)*1e3;N=Math.max(0,G+vo);break;case"linear_1s":N=1e3;break;case"linear_2s":N=2e3;break;case"linear_3s":N=3e3;break;case"linear_4s":N=4e3;break;default:N=1e3;break}await new Promise(G=>setTimeout(G,N)),await D(ye,Ae,Z),console.log(`[corsair:${i}:${b}] Retry strategy:`,X)}}throw Ne}},O;try{O=s?await s(t,"endpoint"):void 0}catch(_){throw g&&He(g)&&g.oauthConfig&&g.kek&&_ instanceof oe&&_.authType==="oauth_2"?qi(i,g,p):_}if(!C?.before&&!C?.after){let _=await D(0,{...t,key:O},w);return await T?.(),_}let M={...t,key:O},A=C.before?await C.before(M,w):{ctx:M,args:w,continue:!0,passToAfter:void 0};if(A.continue===!1)return;let ve=await D(0,A.ctx,A.args);return await C.after?.(A.ctx,ve,A.passToAfter),await T?.(),ve};r[y]=k}else if(h&&typeof h=="object"){let C={};Nt({endpoints:h,hooks:m,ctx:t,tree:C,pluginId:i,errorHandlers:o,currentPath:[...a,y],keyBuilder:s,permissionsConfig:u,endpointMeta:c,database:d,permissionsOptions:l,tenantId:p,manualConfig:g,hubConfig:f}),r[y]=C}}}function Zi(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function $t({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:i}){for(let[o,a]of Object.entries(e)){let s=n?.[o];if(Zi(a)){let u=s,c=async d=>{let l=(g,f)=>a.handler(g,f),p=i?await i(t,"webhook"):void 0;return!u?.before&&!u?.after?l({...t,key:p},d):(async()=>{let g={...t,key:p},f=u.before?await u.before(g,d):{ctx:g,args:d,continue:!0,passToAfter:void 0};if(f.continue===!1)return;let y=await l(f.ctx,f.args);return y?.success===!0&&await u.after?.(f.ctx,y,f.passToAfter),y})()};r[o]={match:a.match,handler:c}}else if(a&&typeof a=="object"){let u={};$t({webhooks:a,hooks:s,ctx:t,webhooksTree:u,keyBuilder:i}),r[o]=u}}}function Gi(e,n,t){let r=null;return async()=>{if(r)return r;if(!e)throw new Error("Database not configured");let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!i)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);let o=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",i.id).executeTakeFirst();if(!o)throw new Error(`Account not found for tenant "${t}" and integration "${n}". Make sure to create the account first.`);return r=o.id,r}}function Ji(e,n,t,r,i){return e?Zn(e.db,n,t,r,i):{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 Lt(e,n){let{database:t,tenantId:r,kek:i,rootErrorHandlers:o,permissionsOptions:a,manualConfig:s,hubConfig:u}=n,c={},d={};for(let l of e)c[l.id]={},d[l.id]={};for(let l of e){let p=l.schema,g=r??"default",f=Gi(t,l.id,g);if(p?.entities){let A={};for(let[ve,_]of Object.entries(p.entities)){let Ae=t?Zn(t.db,f,ve,p.version,_):Ji(void 0,f,ve,p.version,_);A[ve]=Ae}d[l.id].db=A,c[l.id].db=A}let y=l.options,h=l.authConfig,m;if(t&&i&&y?.authType){let A=h?.[y.authType]?.account??[];m=R({authType:y.authType,integrationName:l.id,tenantId:g,kek:i,database:t,extraAccountFields:A}),c[l.id].keys=m}let C={database:t,db:d[l.id]?.db??{},$getAccountId:f,...l.options?{options:l.options}:{},...m?{keys:m,authType:y?.authType}:{},tenantId:g,...u?{hub:u}:{}},b=l.endpoints??{},k=l.hooks,w={...o,...l.errorHandlers},T={},D=l.options?.permissions;Nt({endpoints:b,hooks:k,ctx:C,tree:T,pluginId:l.id,errorHandlers:w,currentPath:[],keyBuilder:l.keyBuilder,permissionsConfig:D,endpointMeta:l.endpointMeta,database:t,permissionsOptions:a,tenantId:r,manualConfig:s?{...s,oauthConfig:l.oauthConfig,kek:i,tenantId:g}:void 0,hubConfig:u}),Object.keys(T).length>0&&(c[l.id].api=T),C.endpoints=T;let O=l.webhooks??{},M=l.webhookHooks;if(Object.keys(O).length>0){let A={};$t({webhooks:O,hooks:M,ctx:C,webhooksTree:A,keyBuilder:l.keyBuilder}),c[l.id].webhooks=A,l.pluginWebhookMatcher&&(c[l.id].pluginWebhookMatcher=l.pluginWebhookMatcher),l.pluginTenantWebhookMatcher&&(c[l.id].pluginTenantWebhookMatcher=l.pluginTenantWebhookMatcher)}}return c}function qr(e,n,t){let r={};for(let i of e){let o=i.options,a=i.authConfig;if(o?.authType){let s=a?.[o.authType]?.integration??[],u=I({authType:o.authType,integrationName:i.id,kek:t,database:n,extraIntegrationFields:s});r[i.id]=u}}return r}var zi="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function Zr(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] ${zi}`),t):n}import*as Gr from"querystring";function Fe(e){let{oauthConfig:n,clientId:t,redirectUri:r,state:i}=e,o={...n.authParams,client_id:t,redirect_uri:r,response_type:"code",scope:n.scopes.join(" "),state:i};return`${n.authUrl}?${Gr.stringify(o)}`}var W=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Vi(e){let n=e.oauthConfig;if(!n)throw new W("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Wt(e,n){let t=P(e,()=>new W("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new W("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new W("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let i=fn(n,t.kek);if(!i)throw new W("invalid_state","Invalid or tampered state parameter");let{plugin:o,tenantId:a}=i,s=$(t,o,p=>new W("plugin_not_found",p)),u=Vi(s),d=await I({authType:"oauth_2",integrationName:o,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new W("client_id_not_configured",`client_id not configured for '${o}'`);let l=Fe({oauthConfig:u,clientId:d,redirectUri:r,state:n});return{plugin:o,tenantId:a,providerName:u.providerName,oauthUrl:l,state:n}}var v=class extends Error{status;code;extra;constructor(n,t,r,i={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=i}};function S(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function Jr(e){let n={error:e.code,message:e.message,...e.extra};return S(e.status,n)}function ge(e){return new v(404,"not_found",e)}function Q(e,n={}){return new v(400,"bad_request",e,n)}function zr(e,n){return $(e,n,t=>ge(t))}async function Vr(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=I({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),i=E[t].integration,o=r,a;try{a=await Promise.all(i.map(c=>o[`get_${c}`]()))}catch{a=i.map(()=>null)}let s=i.filter((c,d)=>a[d]==null),u;return t==="oauth_2"?u=!s.includes("client_id")&&!s.includes("client_secret"):u=s.length===0,{configured:u,missingFields:s}}async function Yr(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:i,missingFields:o}=await Vr(e,n);return{id:e.id,authType:t,configured:i,missingFields:o,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function Dn(){return{ok:!0}}async function On(e){return Promise.all(e.plugins.map(n=>Yr(n,e)))}async function Mn(e,n){let t=zr(e,n);return Yr(t,e)}async function Yi(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 Qr(e,n){let t=await Yi(e,n),r=t.filter(i=>i.hasCredentials).map(i=>i.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Hn(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 i=r.tenant_id;if(!i)continue;let o=n.get(i);o||(o={id:i,accounts:[],connectedPlugins:[]},n.set(i,o));let a=!!r.dek;o.accounts.push({integrationName:r.integrationName,hasCredentials:a}),a&&o.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function Fn(e,n){if(!n)throw Q("Tenant id must be a non-empty string");return Qr(e,n)}async function Bn(e,n){let t=n?.id?.trim();if(!t)throw Q("Tenant id is required",{missingFields:["id"]});return Qr(e,t)}async function Un(e,n){let t=n?.trim()||"default",r={},i=await Ke(e,t);for(let o of i)r[o.plugin]=gn(o);for(let o of e.plugins)o.id in r||(!o.options?.authType||!e.database||!e.kek?r[o.id]="missing_credentials":r[o.id]="not_connected");return r}async function jt(e,n){if(!e.database)throw ge(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw ge(`Permission '${n}' not found`);return En(e,t)}function Qi(e){if(!e.oauthConfig)throw Q(`Plugin '${e.id}' has no oauthConfig`)}function Xi(e){if(!e.manual)throw new v(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Kt(e){let n=Xi(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new v(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 es(e){let n=!!e.hub,t=He(e.manual);if(!n&&!t)throw new v(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function Xr(e){if(!e.database||!e.kek)throw new v(500,"database_not_configured","A database and kek are required to issue connect links.")}async function ns(e,n){let t=n?.plugin?.trim();if(!t)throw Q("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",i=zr(e,t);Qi(i);let o=Kt(e);Xr(e);let a=await Vr(i,e);if(!a.configured)throw new v(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:a.missingFields});let s=ce(z(t,r),e.kek),u;try{u=new URL(o.baseUrl)}catch{throw new v(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",s),{connectUrl:u.toString(),expiresAt:new Date(Date.now()+Vn).toISOString()}}async function ts(e,n,t){Xr(n);let r=t.tenantId?.trim()||"default",i=B(e);if(t.source){let c=Ie({source:t.source,deliveryUrl:i.deliveryUrl,oauthMode:t.oauthMode});if(c)throw Q(c.error)}let o={tenantId:r,source:t.source??Re(i.deliveryUrl),oauthMode:t.oauthMode},a=t.plugin?.trim();a&&(o.plugin=a);let s=t.providerName?.trim();s&&(o.providerName=s);let u=await hn(e,o);return{connectUrl:u.connectUrl,expiresAt:u.expiresAt}}async function Nn(e,n,t){return es(n),n.hub?ts(e,n,t):ns(n,t)}async function $n(e,n,t){if(n.hub&&!He(n.manual))throw new v(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw Q("state is required",{missingFields:["state"]});Kt(n);try{return await Wt(e,r)}catch(i){if(i instanceof W)switch(i.code){case"invalid_state":throw Q("Invalid or expired state");case"client_id_not_configured":throw new v(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new v(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function Ln(e,n,t){if(n.hub&&!He(n.manual))throw new v(400,"hub_mode","oauthCallback is not used with hub config. Hub delivers tokens to your deliveryUrl.");let r=t?.code?.trim(),i=t?.state?.trim(),o=[];if(r||o.push("code"),i||o.push("state"),o.length)throw Q("Missing required fields",{missingFields:o});let a=Kt(n),{processOAuthCallback:s}=await import("./oauth.js");try{return await s(e,{code:r,state:i,redirectUri:a.redirectUri})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw Q("Invalid or expired state");case"credentials_not_configured":throw new v(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new v(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function qt(e,n){if(!e.database)throw ge("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw ge("Permission not found");return En(e,t)}async function eo(e,n){return"id"in n?jt(e,n.id):qt(e,n.token)}var no=[{method:"GET",pattern:"/ok",handler:async()=>S(200,Dn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>S(200,await Hn(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>S(201,await Bn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>S(200,await Fn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>S(200,await On(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>S(200,await Mn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>S(200,await Un(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>S(200,await jt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?S(200,await qt(e,t)):S(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>S(200,await Nn(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>S(200,await $n(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>S(200,await Ln(e,n,t))}];(()=>{let e=new Set;for(let n of no){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function rs(e,n){let t=e.split("/").filter(Boolean),r=n.split("/").filter(Boolean);if(t.length!==r.length)return null;let i={};for(let o=0;o<t.length;o++){let a=t[o],s=r[o];if(a.startsWith(":"))i[a.slice(1)]=decodeURIComponent(s);else if(a!==s)return null}return i}function os(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 is(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 v(400,"invalid_json","Request body is not valid JSON")}}var ss="/api/corsair";function Te(e,n={}){let t=n.basePath??ss,r=P(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async i=>{try{let o=new URL(i.url),a=os(o.pathname,t),s=i.method.toUpperCase();if(s==="OPTIONS"||a==="/"||a==="")return await we(e,i);if(s!=="GET"&&s!=="POST")return S(405,{error:"method_not_allowed",message:`Method ${s} not allowed`});let u=Object.fromEntries(o.searchParams);for(let c of no){if(c.method!==s)continue;let d=rs(c.pattern,a);if(!d)continue;let l=await is(i);return await c.handler({corsair:e,internal:r,req:i,params:d,query:u,body:l})}throw ge(`No route for ${s} ${a}`)}catch(o){if(n.onError){let s=await n.onError(o,i);if(s)return s}if(o instanceof v)return Jr(o);let a=o instanceof Error?o.message:"Internal server error";return S(500,{error:"internal_error",message:a})}}}function as(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,i=`${t}://${n}${r}`,o=new Headers;for(let[u,c]of Object.entries(e.headers))if(c!=null)if(Array.isArray(c))for(let d of c)o.append(u,d);else o.set(u,c);let a=e.method!=="GET"&&e.method!=="HEAD",s={method:e.method,headers:o};return a&&e.body!==void 0&&(s.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),o.has("content-type")||o.set("content-type","application/json")),new Request(i,s)}async function us(e,n){e.status(n.status),n.headers.forEach((r,i)=>e.setHeader(i,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function to(e,n){let t=Te(e,n);return async(r,i,o)=>{try{let a=await t(as(r));await us(i,a)}catch(a){o(a)}}}function ro(e,n){let t=Te(e,n);return r=>t(r.req.raw)}function oo(e,n){let t=Te(e,n);return{GET:t,POST:t,OPTIONS:t}}function io(e){let n={[Qe]:e};return{ok:Dn,tenants:{list:()=>Hn(e),create:t=>Bn(e,t),get:t=>Fn(e,t)},plugins:{list:()=>On(e),get:t=>Mn(e,t)},connectionStatus:{get:t=>Un(e,t?.tenantId)},permissions:{get:t=>eo(e,t)},connect:{createLink:t=>Nn(n,e,t),resolve:t=>$n(n,e,t),oauthCallback:t=>Ln(n,e,t)}}}async function so(e,n,t,r,i="pending"){if(!e)return null;try{let o=rr(),a=new Date;return await e.db.insertInto("corsair_events").values({id:o,created_at:a,updated_at:a,account_id:n,event_type:t,payload:r,status:i}).execute(),o}catch(o){return console.warn("Failed to log event:",o),null}}async function cs(e,n,t,r="pending"){try{let i=await e.$getAccountId();return so(e.database,i,n,t,r)}catch(i){return console.warn("Failed to log event:",i),null}}import*as ao from"https";import*as uo from"querystring";function Wn(e,n,t,r,i){let o=new URL(r.tokenUrl),a=r.tokenAuthMethod==="basic";return new Promise((s,u)=>{let c={code:e.trim(),redirect_uri:i,grant_type:"authorization_code"};a||(c.client_id=n,c.client_secret=t);let d=uo.stringify(c),l={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(d).toString()};a&&(l.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let p=ao.request({hostname:o.hostname,...o.port?{port:Number(o.port)}:{},path:o.pathname+o.search,method:"POST",headers:l},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}try{s(JSON.parse(f))}catch{u(new Error(`Token endpoint returned non-JSON response: ${f}`))}})});p.on("error",g=>u(new Error(`Request failed: ${g.message}`))),p.write(d),p.end()})}var co=" ";function K(e){let n=e;return n._def??n.def??{}}function q(e){let n=e.typeName;if(n)return n;let t=e.type;if(t)return`Zod${t.split("_").map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("")}`}function j(e){return e.innerType??e.schema??e.out??e.in}function po(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 j(e)}}function go(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Kn(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Be(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 fo(e,n){return e.description??n.description}function ls(e){let n=e;for(;n;){let t=K(n),r=fo(n,t);if(r)return r;let i=q(t);if(Vt(i)||i==="ZodPipe"||i==="ZodEffects"||i==="ZodTransform"){n=po(t,i);continue}break}}function Vt(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function F(e){let n=K(e),t=q(n);switch(t){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"Date";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(n.value??Be(n)[0]??"unknown");case"ZodEnum":return Be(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=j(n);return r?F(r):"unknown"}case"ZodNullable":{let r=j(n);return`${r?F(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=j(n);return r?F(r):"unknown"}case"ZodArray":{let r=go(n);if(!r)return"unknown[]";let i=K(r),o=q(i)==="ZodUnion",a=F(r);return`${o?`(${a})`:a}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Kn(e,n),i=Object.entries(r);return i.length===0?"{}":`{ ${i.map(([a,s])=>{let u=q(K(s));return`${u==="ZodOptional"||u==="ZodNullable"?a+"?":a}: ${F(s)}`}).join(", ")} }`}case"ZodUnion":return Be(n).map(r=>F(r)).join(" | ");case"ZodIntersection":return`${F(n.left)} & ${F(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=po(n,t);return r?F(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ie(e){let n=K(e),t=q(n),r=fo(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 i=n.value??Be(n)[0],o=typeof i=="string"||typeof i=="number"||typeof i=="boolean"?i:String(i??"");return{kind:"literal",optional:!1,description:r,value:o}}case"ZodEnum":{let i=Be(n).map(o=>String(o));return{kind:"string",optional:!1,description:r,enum:i}}case"ZodOptional":{let i=j(n),o=i?ie(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodNullable":{let i=j(n),o=i?ie(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodDefault":case"ZodCatch":{let i=j(n);return i?{...ie(i),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let i=go(n);return{kind:"array",optional:!1,description:r,items:i?ie(i):{kind:"unknown",optional:!1}}}case"ZodObject":{let i=Kn(e,n),o={};for(let[a,s]of Object.entries(i))o[a]=ie(s);return{kind:"object",optional:!1,description:r,fields:o}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let i=Be(n);for(let o of i){let a=K(o);if(q(a)==="ZodObject")return{...ie(o),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let i=j(n);return i?{...ie(i),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Ul(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let i=t.slice(0,r),o=t.slice(r+1),a=e.find(d=>d.id===i);if(!a)return null;let s=o;s.startsWith("api.")&&(s=s.slice(4));let u=fe(a.endpointMeta,s),c=fe(a.endpointSchemas,s);return!u&&!c?null:{input:c?.input?ie(c.input):null,output:c?.output?ie(c.output):null,description:u?.description}}var Yt=["equals","contains","startsWith","endsWith","in"],ds=["equals","gt","gte","lt","lte","in"],ps=["equals"],gs=["equals","before","after","between"];function yo(e){let n=K(e);switch(q(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=j(n);return r?yo(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Qt(e){let n=K(e),t=q(n);if(Vt(t)){let o=j(n);return o?Qt(o):{}}if(t!=="ZodObject")return{};let r=Kn(e,n),i={};for(let[o,a]of Object.entries(r)){let s=yo(a);s==="string"?i[o]={type:"string",operators:Yt}:s==="number"?i[o]={type:"number",operators:ds}:s==="boolean"?i[o]={type:"boolean",operators:ps}:s==="date"&&(i[o]={type:"date",operators:gs})}return i}function ho(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Gt(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];typeof i=="function"?t.push(o.join(".")):i!==null&&typeof i=="object"&&Gt(i,o,t)}}function Jt(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function zt(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];Jt(i)?t.push(o.join(".")):i!==null&&typeof i=="object"&&zt(i,o,t)}}function Xt(e,n){if(n.length===0)return null;let[t,...r]=n,i=Object.entries(e).find(([s])=>s.toLowerCase()===t);if(!i)return null;let[o,a]=i;if(r.length===0)return Jt(a)?[o]:null;if(a!==null&&typeof a=="object"&&!Jt(a)){let s=Xt(a,r);if(s!==null)return[o,...s]}return null}function mo(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let o=0;o<n.length;o++){let a=" ".repeat(o+2);t.push(`${a}${n[o]}: {`)}let r=" ".repeat(n.length+2),i=r+" ";t.push(`${r}before(ctx, args) {`),t.push(`${i}return { ctx, args };`),t.push(`${r}},`),t.push(`${r}after(ctx, response) {`),t.push(`${r}},`);for(let o=n.length-1;o>=0;o--){let a=" ".repeat(o+2);t.push(`${a}},`)}return t.push(" },"),t.push("})"),t.join(`
26
+ `)}var fs=new Set(nn);function Pe(e,n){let t=n?.type??"api",r=n?.plugin;if(r!==void 0){let o=e.find(s=>s.id===r);if(!o)return fs.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:Pe(e);if(t==="webhooks"){if(!o.webhooks)return[];let s=[];return zt(o.webhooks,[],s),s.map(u=>`${o.id}.webhooks.${u}`)}if(t==="db"){let s=o.schema?.entities;return s?Object.keys(s).map(u=>`${o.id}.db.${u}.search`):[]}if(!o.endpoints)return[];let a=[];return Gt(o.endpoints,[],a),a.map(s=>`${o.id}.api.${s}`)}let i={};if(t==="webhooks")for(let o of e){if(!o.webhooks)continue;let a=[];zt(o.webhooks,[],a),i[o.id]=a.map(s=>`${o.id}.webhooks.${s}`)}else if(t==="db")for(let o of e){let a=o.schema?.entities;a&&(i[o.id]=Object.keys(a).map(s=>`${o.id}.db.${s}.search`))}else for(let o of e){if(!o.endpoints)continue;let a=[];Gt(o.endpoints,[],a),i[o.id]=a.map(s=>`${o.id}.api.${s}`)}return i}function fe(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function ys(e,n){let t=e.toLowerCase(),r=n.toLowerCase();if(!t.startsWith(`${r}.`)){let o=t.slice(n.length+1),a=o.startsWith(".")?o.slice(1):o;return a.startsWith("api.")&&(a=a.slice(4)),{shortPath:a,lookupKey:a}}let i=e.slice(n.length+1);return i.toLowerCase().startsWith("api.")&&(i=i.slice(4)),{shortPath:i,lookupKey:i.toLowerCase()}}function Zt(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
27
+ ${e.join(", ")}`:`${n}:
28
+ `+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
29
+ `)}function Nl(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let i=t.slice(0,r),o=t.slice(r+1),a=e.find(s=>s.id===i);if(a){if(o.startsWith("db.")){let d=o.slice(3),l=d.lastIndexOf(".");if(l!==-1){let p=d.slice(0,l),g=d.slice(l+1),f=a.schema?.entities;if(g==="search"&&f){let y=ho(f,p);if(y){let[h,m]=y,C=Qt(m),b=[`Search ${i} ${h} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${Yt.join(", ")}]`];for(let[k,w]of Object.entries(C))b.push(` ${k}?: ${w.type} [${w.operators.join(", ")}]`);return b.push("}"),b.join(`
30
+ `)}}}return Zt(Pe(e,{type:"db"}),"Path not found. Available db operations")}if(o.startsWith("webhooks.")){let d=o.slice(9);if(a.webhooks){let l=Xt(a.webhooks,d.split("."));if(l!==null){let p=l.join("."),g=fe(a.webhookSchemas,p.toLowerCase()),f=g?.response?F(g.response):null,y=[];return g?.description&&y.push(g.description),g?.payload&&y.push(`payload ${jn(Ue(g.payload))}`),f&&y.push(`response: ${f}`),y.push(`usage:
31
+ ${mo(i,l)}`),y.join(`
32
+
33
+ `)}}return Zt(Pe(e,{type:"webhooks"}),"Path not found. Available webhooks")}let s=o;s.startsWith("api.")&&(s=s.slice(4));let u=fe(a.endpointMeta,s),c=fe(a.endpointSchemas,s);if(u||c){let d=[],l=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),p=[u?.description,l].filter(Boolean).join(" ");return p&&d.push(p),c?.input&&d.push(`input ${jn(Ue(c.input))}`),c?.output&&d.push(`output ${jn(Ue(c.output))}`),d.join(`
34
+
35
+ `)}}}return Zt(Pe(e),"Path not found. Available operations")}function lo(e){let n=e;for(;;){let t=K(n),r=q(t);if(Vt(r)){let i=j(t);if(!i)return n;n=i;continue}return n}}function Ue(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=lo(e),t=K(n);if(q(t)==="ZodObject"){let i=Kn(n,t),o=[];for(let[a,s]of Object.entries(i)){let u=K(s),c=q(u),d=c==="ZodOptional"||c==="ZodNullable",l=lo(s),p=ls(s);o.push({key:a,optional:d,type:F(l),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:o}}return{kind:"inline",type:F(n)}}function jn(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=co.repeat(n+1),r=co.repeat(n);return`{
36
+ ${e.fields.map(o=>{let a=o.optional?`${o.key}?`:o.key,s=o.description?` // ${o.description}`:"";return`${t}${a}: ${o.type}${s}`}).join(`
37
+ `)}
38
+ ${r}}`}return"unknown"}function hs(e,n){let t=Pe(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(d=>d.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let i=[];for(let d of t){let{shortPath:l,lookupKey:p}=ys(d,n),g=fe(r.endpointMeta,p),f=fe(r.endpointSchemas,p);!g&&!f||i.push({path:d,shortPath:l,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:Ue(f?.input),output:Ue(f?.output)})}i.sort((d,l)=>d.path.localeCompare(l.path));let o=[],a=Pe(e,{plugin:n,type:"webhooks"});if(Array.isArray(a)&&r.webhooks)for(let d of a){let p=d.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),y=Xt(r.webhooks,f.split("."));if(y===null)continue;let h=y.join("."),m=fe(r.webhookSchemas,h.toLowerCase()),C=m?.response?F(m.response):void 0;o.push({path:d,description:m?.description,payload:Ue(m?.payload),responseType:C,usageExample:mo(n,y)})}o.sort((d,l)=>d.path.localeCompare(l.path));let s=[],u=Pe(e,{plugin:n,type:"db"}),c=r.schema?.entities;if(Array.isArray(u)&&c)for(let d of u){let p=d.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;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 C=ho(c,h);if(!C)continue;let[b,k]=C,w=Qt(k),T=Object.entries(w).map(([D,O])=>({field:D,type:O.type,operators:O.operators}));s.push({path:d,entityName:b,filters:[{field:"entity_id",type:"string",operators:Yt},...T]})}return s.sort((d,l)=>d.path.localeCompare(l.path)),{ok:!0,data:{pluginId:n,api:i,webhooks:o,db:s}}}function ko(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function ms(e,n){let t=ko(e,n);if(!t)return null;let r=e[t];if(!r?.pluginTenantWebhookMatcher)return null;let i=r.pluginTenantWebhookMatcher(n);return i?{plugin:t,tenantMatch:i}:null}function ks(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function bo(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Co(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 Xe(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function bs(e){return Xe(e.body)}function wo(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return qn(Array.isArray(r)?r:[r])}function To(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let c=qn(Array.isArray(u)?u:[u]);if(c)return decodeURIComponent(c)}let r=wo({query:e.query},"validationToken");if(r)return r;let i=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let u of i){let c=n[u],d=Array.isArray(c)?c[0]:c;if(!(!d||typeof d!="string"))try{let p=(d.startsWith("http")?new URL(d):new URL(`https://example.invalid${d.startsWith("/")?d:`/${d}`}`)).searchParams.get("validationToken");if(p?.trim())return p.trim()}catch{continue}}let o=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,a=Xe(typeof o=="string"?(()=>{try{return JSON.parse(o)}catch{return o}})():o);return qn([a?.validationToken])??null}function Cs(e){if(To(e))return!0;let n=Xe(e.body??e.payload);return bo(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function qn(e){for(let n of e){let t=Co(n);if(t)return t}}function ws(e){let t=Xe(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Qe=Symbol.for("corsair:internal");function Cr(e){let n=e.database?er(e.database):void 0,t=n&&e.kek?qr(e.plugins,n,e.kek):_n(!!n,!!e.kek),r=Zr(e),i={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?tn(e.hub):void 0},o=jr(n),a=io(i);if(e.multiTenancy)return Object.assign({withTenant:u=>{if(!u)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let c=Lt(e.plugins,{database:n,tenantId:u,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:i.hub});return Object.assign(c,{[Qe]:i})},keys:t,permissions:o,manage:a},{[Qe]:i});let s=Lt(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:i.hub});return Object.assign({},s,{keys:t,permissions:o,manage:a,[Qe]:i})}var U=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Po(e){let n=e.oauthConfig;if(!n)throw new U("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Ts(e,n,t,r){let i=ir(e),o=await i.integrations.findByName(n);if(!o)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:t,integration_id:o.id}))return;let s=ee(),u=await ne(s,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:u})}async function Xn(e,n,t){let{tenantId:r,redirectUri:i}=t,o=P(e,()=>new U("invalid_corsair_instance","Invalid corsair instance"));if(!o.database)throw new Error("No database configured on corsair instance");let a=$(o,n,l=>new U("plugin_not_found",l)),s=Po(a),c=await I({authType:"oauth_2",integrationName:n,kek:o.kek,database:o.database}).get_client_id();if(!c)throw new Error(`client_id not configured for '${n}'`);let d=ce(z(n,r),o.kek);return{url:Fe({oauthConfig:s,clientId:c,redirectUri:i,state:d}),state:d}}async function Ye(e,n){let{code:t,state:r,redirectUri:i}=n,o=P(e,()=>new U("invalid_corsair_instance","Invalid corsair instance")),a=fn(r,o.kek);if(!a)throw new U("invalid_state","Invalid or tampered state parameter");let{plugin:s,tenantId:u}=a;if(!o.database)throw new U("no_database","No database configured on corsair instance");let c=$(o,s,h=>new U("plugin_not_found",h)),d=Po(c),l=I({authType:"oauth_2",integrationName:s,kek:o.kek,database:o.database}),p=await l.get_client_id(),g=await l.get_client_secret();if(!p||!g)throw new U("credentials_not_configured",`Credentials not configured for '${s}'`);await Ts(o.database,s,u,o.kek);let f=await Wn(t,p,g,d,i);if(!f.access_token)throw new U("no_access_token",`No access_token returned from ${d.providerName}`);let y=R({authType:"oauth_2",integrationName:s,tenantId:u,kek:o.kek,database:o.database});await y.set_access_token(f.access_token),f.refresh_token&&await y.set_refresh_token(f.refresh_token),f.expires_in&&await y.set_expires_at(String(Math.floor(Date.now()/1e3)+f.expires_in));try{let h=await Cn(o.plugins,s,f);if(h)try{let m=c.authConfig?.oauth_2?.account??[];await De({database:o.database,kek:o.kek,pluginId:s,tenantId:u,link:h,authType:"oauth_2",extraAccountFields:m})}catch(m){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${u}':`,m)}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${u}':`,h)}return{plugin:s,tenantId:u}}export{sr as a,ae as b,$e as c,he as d,tn as e,B as f,rn as g,on as h,sn as i,an as j,ar as k,un as l,ee as m,ne as n,L as o,Gn as p,We as q,ue as r,te as s,je as t,I as u,R as v,gr as w,fr as x,z as y,zn as z,De as A,et as B,wn as C,xr as D,Fe as E,U as F,Xn as G,Ye as H,Ze as I,Re as J,hr as K,Ie as L,kr as M,ci as N,hn as O,Ee as P,le as Q,me as R,de as S,Oe as T,Tn as U,tt as V,Me as W,rt as X,ot as Y,it as Z,st as _,_r as $,re as aa,vn as ba,An as ca,pe as da,be as ea,Ce as fa,ze as ga,Ve as ha,xn as ia,lt as ja,dt as ka,pt as la,gt as ma,ft as na,yt as oa,ht as pa,we as qa,oe as ra,mt as sa,Fr as ta,Rn as ua,In as va,Br as wa,kt as xa,bt as ya,Ct as za,wt as Aa,Tt as Ba,Pt as Ca,vt as Da,At as Ea,xt as Fa,St as Ga,Rt as Ha,It as Ia,_t as Ja,Et as Ka,Dt as La,Wt as Ma,Te as Na,to as Oa,ro as Pa,oo as Qa,so as Ra,cs as Sa,Wn as Ta,Ul as Ua,Pe as Va,Nl as Wa,jn as Xa,hs as Ya,ko as Za,ms as _a,ks as $a,bo as ab,Co as bb,Xe as cb,bs as db,wo as eb,To as fb,Cs as gb,qn as hb,ws as ib,Qe as jb,Cr as kb};
@@ -1,9 +1,9 @@
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-BswoTGV5.js';
2
- export { f as PermissionLookupInput } from '../../types-BswoTGV5.js';
3
- import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-DoUHxHNl.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-CNagdEGY.js';
2
+ export { f as PermissionLookupInput } from '../../types-CNagdEGY.js';
3
+ import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-DGS4LASW.js';
4
4
  import '../../index-ggMa1Rj6.js';
5
5
  import 'zod';
6
- import '../../constants-CE0V2QbI.js';
6
+ import '../../constants-DnSLjl7e.js';
7
7
 
8
8
  type AsyncState<T> = {
9
9
  status: 'idle';
@@ -1,6 +1,7 @@
1
1
  type AllErrors = 'RATE_LIMIT_ERROR' | 'AUTH_ERROR' | 'PERMISSION_ERROR' | 'NETWORK_ERROR' | 'TIMEOUT_ERROR' | 'SERVER_ERROR' | 'VALIDATION_ERROR' | 'NOT_FOUND_ERROR' | 'BAD_REQUEST_ERROR' | 'PARSING_ERROR' | 'DEFAULT' | (string & {});
2
- declare const BaseProviders: readonly ["ahrefs", "airtable", "amplitude", "asana", "bitwarden", "bluesky", "box", "cal", "calendly", "cloudflare", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "grafana", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tally", "tavily", "teams", "telegram", "todoist", "trello", "twilio", "twitter", "twitterapiio", "typeform", "vapi", "xquik", "youtube", "zendesk", "zohomail", "zoom"];
2
+ declare const BaseProviders: readonly ["agentql", "ahrefs", "airtable", "amplitude", "asana", "bitwarden", "bluesky", "box", "cal", "calendly", "cloudflare", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "grafana", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tally", "tavily", "teams", "telegram", "todoist", "trello", "twilio", "twitter", "twitterapiio", "typeform", "vapi", "xquik", "youtube", "zendesk", "zohomail", "zoom"];
3
3
  declare const ProviderDisplayNames: {
4
+ readonly agentql: "AgentQL";
4
5
  readonly ahrefs: "Ahrefs";
5
6
  readonly airtable: "Airtable";
6
7
  readonly amplitude: "Amplitude";
@@ -66,7 +67,7 @@ declare const ProviderDisplayNames: {
66
67
  readonly zoom: "Zoom";
67
68
  };
68
69
  declare function formatProviderDisplayName(plugin: string): string;
69
- type AllProviders = 'ahrefs' | 'airtable' | 'amplitude' | 'asana' | 'bitwarden' | 'bluesky' | 'box' | 'cal' | 'calendly' | 'cloudflare' | 'cursor' | 'discord' | 'dodopayments' | 'dropbox' | 'exa' | 'figma' | 'firecrawl' | 'fireflies' | 'github' | 'gitlab' | 'gmail' | 'googlecalendar' | 'googledrive' | 'googlesheets' | 'grafana' | 'hackernews' | 'hubspot' | 'intercom' | 'jira' | 'linear' | 'monday' | 'notion' | 'onedrive' | 'openweathermap' | 'oura' | 'outlook' | 'pagerduty' | 'posthog' | 'razorpay' | 'reddit' | 'resend' | 'sentry' | 'sharepoint' | 'slack' | 'spotify' | 'strava' | 'stripe' | 'tally' | 'tavily' | 'teams' | 'telegram' | 'todoist' | 'trello' | 'twilio' | 'twitter' | 'twitterapiio' | 'typeform' | 'vapi' | 'xquik' | 'youtube' | 'zendesk' | 'zohomail' | 'zoom' | (string & {});
70
+ type AllProviders = 'agentql' | 'ahrefs' | 'airtable' | 'amplitude' | 'asana' | 'bitwarden' | 'bluesky' | 'box' | 'cal' | 'calendly' | 'cloudflare' | 'cursor' | 'discord' | 'dodopayments' | 'dropbox' | 'exa' | 'figma' | 'firecrawl' | 'fireflies' | 'github' | 'gitlab' | 'gmail' | 'googlecalendar' | 'googledrive' | 'googlesheets' | 'grafana' | 'hackernews' | 'hubspot' | 'intercom' | 'jira' | 'linear' | 'monday' | 'notion' | 'onedrive' | 'openweathermap' | 'oura' | 'outlook' | 'pagerduty' | 'posthog' | 'razorpay' | 'reddit' | 'resend' | 'sentry' | 'sharepoint' | 'slack' | 'spotify' | 'strava' | 'stripe' | 'tally' | 'tavily' | 'teams' | 'telegram' | 'todoist' | 'trello' | 'twilio' | 'twitter' | 'twitterapiio' | 'typeform' | 'vapi' | 'xquik' | 'youtube' | 'zendesk' | 'zohomail' | 'zoom' | (string & {});
70
71
  type AuthTypes = 'oauth_2' | 'api_key' | 'bot_token' | 'managed';
71
72
  type PickAuth<T extends AuthTypes> = T;
72
73
 
package/dist/core.d.ts CHANGED
@@ -1,18 +1,18 @@
1
- export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-dta3YWl8.js';
1
+ export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-4xQX76fp.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './types-BY2SDx3_.js';
4
- export { a as AccountFieldNames, d as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, b as BaseKeyManager, e as Bivariant, c as IntegrationFieldNames, O as OAuth2IntegrationCredentials, P as PluginAuthConfig, U as UnionToIntersection } from './types-BY2SDx3_.js';
5
- export { v as BeforeHookResult, B as BindEndpoints, N as BindWebhooks, h as BoundEndpointFn, i as BoundEndpointTree, Q as BoundWebhook, S as BoundWebhookTree, g as CorsairClient, j as CorsairContext, k as CorsairEndpoint, m as CorsairErrorHandler, c as CorsairIntegration, w as CorsairKeyBuilder, x as CorsairKeyBuilderBase, U as CorsairOAuthWebhookTenantLinkResolver, s as CorsairPermissionsNamespace, C as CorsairPlugin, y as CorsairPluginContext, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, V as CorsairWebhook, X as CorsairWebhookHandler, Y as CorsairWebhookMatcher, Z as CorsairWebhookTenantMatcher, z as EndpointHooks, A as EndpointMetaEntry, E as EndpointPathsOf, D as EndpointRiskLevel, l as EndpointTree, t as EnforcePermissionOptions, u as EnforcePermissionResult, n as ErrorContext, o as ErrorHandler, p as ErrorHandlerAndMatchFunction, q as ErrorMatcher, K as KeyBuilderContext, O as OAuthConfig, P as PermissionMode, F as PermissionPolicy, G as PluginEndpointMeta, H as PluginPermissionsConfig, _ as RawWebhookRequest, I as RequiredPluginEndpointMeta, J as RequiredPluginEndpointSchemas, L as RequiredPluginWebhookSchemas, R as RetryStrategies, r as RetryStrategy, T as TokenResponse, M as WebhookHooks, $ as WebhookPathsOf, a0 as WebhookRequest, a1 as WebhookResponse, W as WebhookTenantMatch, a2 as WebhookTree, f as exchangeCodeForTokens } from './index-x-RG0TdQ.js';
6
- 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, P as PluginDocsIntrospection, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, n as extractMicrosoftGraphValidationToken, o as firstString, f as formatDocSchemaShape, p as getHeader, i as introspectPluginForDocs, q as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, t as readQueryParam, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-DhF58Vo8.js';
7
- import { A as AuthTypes } from './constants-CE0V2QbI.js';
8
- export { a as AllProviders, B as BaseProviders, P as PickAuth, b as ProviderDisplayNames, f as formatProviderDisplayName } from './constants-CE0V2QbI.js';
3
+ import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './types-B9vj3Bq8.js';
4
+ export { a as AccountFieldNames, d as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, b as BaseKeyManager, e as Bivariant, c as IntegrationFieldNames, O as OAuth2IntegrationCredentials, P as PluginAuthConfig, U as UnionToIntersection } from './types-B9vj3Bq8.js';
5
+ export { v as BeforeHookResult, B as BindEndpoints, N as BindWebhooks, h as BoundEndpointFn, i as BoundEndpointTree, Q as BoundWebhook, S as BoundWebhookTree, g as CorsairClient, j as CorsairContext, k as CorsairEndpoint, m as CorsairErrorHandler, c as CorsairIntegration, w as CorsairKeyBuilder, x as CorsairKeyBuilderBase, U as CorsairOAuthWebhookTenantLinkResolver, s as CorsairPermissionsNamespace, C as CorsairPlugin, y as CorsairPluginContext, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, V as CorsairWebhook, X as CorsairWebhookHandler, Y as CorsairWebhookMatcher, Z as CorsairWebhookTenantMatcher, z as EndpointHooks, A as EndpointMetaEntry, E as EndpointPathsOf, D as EndpointRiskLevel, l as EndpointTree, t as EnforcePermissionOptions, u as EnforcePermissionResult, n as ErrorContext, o as ErrorHandler, p as ErrorHandlerAndMatchFunction, q as ErrorMatcher, K as KeyBuilderContext, O as OAuthConfig, P as PermissionMode, F as PermissionPolicy, G as PluginEndpointMeta, H as PluginPermissionsConfig, _ as RawWebhookRequest, I as RequiredPluginEndpointMeta, J as RequiredPluginEndpointSchemas, L as RequiredPluginWebhookSchemas, R as RetryStrategies, r as RetryStrategy, T as TokenResponse, M as WebhookHooks, $ as WebhookPathsOf, a0 as WebhookRequest, a1 as WebhookResponse, W as WebhookTenantMatch, a2 as WebhookTree, f as exchangeCodeForTokens } from './index-DBW1TceJ.js';
6
+ 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, P as PluginDocsIntrospection, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, n as extractMicrosoftGraphValidationToken, o as firstString, f as formatDocSchemaShape, p as getHeader, i as introspectPluginForDocs, q as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, t as readQueryParam, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-BTdQekAg.js';
7
+ import { A as AuthTypes } from './constants-DnSLjl7e.js';
8
+ export { a as AllProviders, B as BaseProviders, P as PickAuth, b as ProviderDisplayNames, f as formatProviderDisplayName } from './constants-DnSLjl7e.js';
9
9
  import 'kysely';
10
10
  import './index-ggMa1Rj6.js';
11
11
  import 'zod';
12
12
  import 'pg';
13
13
  import 'postgres';
14
14
  import './orm.js';
15
- import './types-BswoTGV5.js';
15
+ import './types-CNagdEGY.js';
16
16
 
17
17
  /**
18
18
  * Context interface with account ID resolver for logging events.
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{$a as y,Ma as q,Ra as r,Sa as s,Ta as t,Xa as u,Ya as v,Za as w,_a as x,a,ab as z,b,bb as A,cb as B,db as C,eb as D,fb as E,gb as F,hb as G,ib as H,jb as I,kb as J,m as d,n as e,o as f,p as g,q as h,r as i,ra as p,s as j,t as k,u as l,v as m,w as n,x as o}from"./chunk-N6K7UBCS.js";import{g as c}from"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{p as AuthMissingError,c as BASE_AUTH_FIELDS,I as CORSAIR_INTERNAL,a as ProviderDisplayNames,B as asRecord,y as collectPluginWebhookMatchers,m as createAccountKeyManager,J as createCorsair,l as createIntegrationKeyManager,H as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,t as exchangeCodeForTokens,E as extractMicrosoftGraphValidationToken,G as firstString,u as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,z as getHeader,o as initializeAccountDEK,n as initializeIntegrationDEK,v as introspectPluginForDocs,F as isMicrosoftGraphValidationHandshake,r as logEvent,s as logEventFromContext,w as matchWebhookPlugin,x as matchWebhookPluginAndTenant,k as reEncryptConfig,C as readBodyRecord,D as readQueryParam,q as resolveConnectLink,A as toExternalId};
1
+ import{$a as y,Ma as q,Ra as r,Sa as s,Ta as t,Xa as u,Ya as v,Za as w,_a as x,a,ab as z,b,bb as A,cb as B,db as C,eb as D,fb as E,gb as F,hb as G,ib as H,jb as I,kb as J,m as d,n as e,o as f,p as g,q as h,r as i,ra as p,s as j,t as k,u as l,v as m,w as n,x as o}from"./chunk-LSONNUVF.js";import{g as c}from"./chunk-FLNFC4KL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{p as AuthMissingError,c as BASE_AUTH_FIELDS,I as CORSAIR_INTERNAL,a as ProviderDisplayNames,B as asRecord,y as collectPluginWebhookMatchers,m as createAccountKeyManager,J as createCorsair,l as createIntegrationKeyManager,H as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,t as exchangeCodeForTokens,E as extractMicrosoftGraphValidationToken,G as firstString,u as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,z as getHeader,o as initializeAccountDEK,n as initializeIntegrationDEK,v as introspectPluginForDocs,F as isMicrosoftGraphValidationHandshake,r as logEvent,s as logEventFromContext,w as matchWebhookPlugin,x as matchWebhookPluginAndTenant,k as reEncryptConfig,C as readBodyRecord,D as readQueryParam,q as resolveConnectLink,A as toExternalId};
package/dist/hub.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { f as formatProviderDisplayName } from './constants-CE0V2QbI.js';
2
- import { g as HubOAuthMode, h as HubConnectSessionResult, i as HubPermissionSessionResult, j as HubConnectSource, H as HubConfig, f as HubConfigInput, k as HubConnectSessionInput, A as AccountKeyManagerFor, l as HubPermissionSessionInput } from './types-BY2SDx3_.js';
3
- export { D as DEFAULT_HUB_API_URL } from './types-BY2SDx3_.js';
1
+ export { f as formatProviderDisplayName } from './constants-DnSLjl7e.js';
2
+ import { g as HubOAuthMode, h as HubConnectSessionResult, i as HubPermissionSessionResult, j as HubConnectSource, H as HubConfig, f as HubConfigInput, k as HubConnectSessionInput, A as AccountKeyManagerFor, l as HubPermissionSessionInput } from './types-B9vj3Bq8.js';
3
+ export { D as DEFAULT_HUB_API_URL } from './types-B9vj3Bq8.js';
4
4
  import { e as TunnelType, c as ProcessCorsairRequest } from './index-LpuBJQ1m.js';
5
5
  export { f as BROWSER_DELIVERY_TTL_MS, g as BrowserDeliveryMode, B as BrowserDeliveryPayload, S as SIGNED_TUNNEL_REPLAY_WINDOW_MS, d as TunnelEnvelope } from './index-LpuBJQ1m.js';
6
6
  export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-CvBUoA96.js';
package/dist/hub.js CHANGED
@@ -1 +1 @@
1
- import{Aa as U,Ba as V,Ca as W,Da as X,Ea as Y,Fa as Z,Ga as _,Ha as $,I as l,Ia as aa,J as m,Ja as ba,K as n,Ka as ca,L as o,La as da,O as p,P as q,Q as r,R as s,S as t,T as u,U as v,V as w,W as x,X as y,Y as z,Z as A,_ as B,aa as C,b as a,ba as D,c as b,ca as E,d as c,da as F,e as d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,la as G,ma as H,na as I,oa as J,pa as K,qa as L,sa as M,ta as N,ua as O,va as P,wa as Q,xa as R,ya as S,za as T}from"./chunk-N6K7UBCS.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{r as BROWSER_DELIVERY_TTL_MS,b as DEFAULT_HUB_API_URL,c as HubNotConfiguredError,t as ManagedOAuthDeliveryError,s as SIGNED_TUNNEL_REPLAY_WINDOW_MS,N as attachManagedRefreshAuth,D as buildBrowserDeliveryRedirectUrl,R as createConnectSessionJti,W as createConnectTokenJti,p as createHubConnectSession,O as createHubPermissionSession,Q as createHubRouteHandlers,aa as createPermissionSessionJti,C as createSignedTokenJti,V as decodeConnectSessionTokenFromPath,$ as decodeConnectTokenFromPath,da as decodePermissionTokenFromPath,B as deliverSignedEnvelope,_ as encodeConnectTokenForPath,P as formatHubApprovalMessage,a as formatProviderDisplayName,A as formatServerDeliveryError,S as getConnectSessionExpiryMs,q as getConnectStatusForTenant,X as getConnectTokenExpiryMs,e as getHubConfig,M as getManagedAccessToken,G as handleHubDeliveryGet,H as handleHubDeliveryPost,J as handleHubDeliveryRequest,I as hubDeliveryToResponse,l as isLoopbackDeliveryUrl,z as isServerDeliveryAckSuccessful,d as normalizeHubConfig,g as parseConnectSessionResponse,j as parseConnectStatusResponse,k as parseHubApiErrorBody,i as parseOAuthRefreshResponse,h as parsePermissionSessionResponse,y as parseServerDeliveryAckBody,u as processManagedOAuthDelivery,m as resolveConnectSourceFromDeliveryUrl,f as resolveHubOAuthCallbackUrl,K as respondToHubDelivery,L as respondToHubDeliveryFromRequest,n as shouldUseBrowserDelivery,E as signBrowserDeliveryToken,T as signConnectSessionToken,Y as signConnectToken,v as signDeliveryEnvelope,ba as signPermissionToken,o as validateExplicitConnectSource,F as verifyBrowserDeliveryToken,U as verifyConnectSessionToken,Z as verifyConnectToken,w as verifyDeliveryEnvelope,ca as verifyPermissionToken,x as verifySignedTunnelDelivery};
1
+ import{Aa as U,Ba as V,Ca as W,Da as X,Ea as Y,Fa as Z,Ga as _,Ha as $,I as l,Ia as aa,J as m,Ja as ba,K as n,Ka as ca,L as o,La as da,O as p,P as q,Q as r,R as s,S as t,T as u,U as v,V as w,W as x,X as y,Y as z,Z as A,_ as B,aa as C,b as a,ba as D,c as b,ca as E,d as c,da as F,e as d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,la as G,ma as H,na as I,oa as J,pa as K,qa as L,sa as M,ta as N,ua as O,va as P,wa as Q,xa as R,ya as S,za as T}from"./chunk-LSONNUVF.js";import"./chunk-FLNFC4KL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{r as BROWSER_DELIVERY_TTL_MS,b as DEFAULT_HUB_API_URL,c as HubNotConfiguredError,t as ManagedOAuthDeliveryError,s as SIGNED_TUNNEL_REPLAY_WINDOW_MS,N as attachManagedRefreshAuth,D as buildBrowserDeliveryRedirectUrl,R as createConnectSessionJti,W as createConnectTokenJti,p as createHubConnectSession,O as createHubPermissionSession,Q as createHubRouteHandlers,aa as createPermissionSessionJti,C as createSignedTokenJti,V as decodeConnectSessionTokenFromPath,$ as decodeConnectTokenFromPath,da as decodePermissionTokenFromPath,B as deliverSignedEnvelope,_ as encodeConnectTokenForPath,P as formatHubApprovalMessage,a as formatProviderDisplayName,A as formatServerDeliveryError,S as getConnectSessionExpiryMs,q as getConnectStatusForTenant,X as getConnectTokenExpiryMs,e as getHubConfig,M as getManagedAccessToken,G as handleHubDeliveryGet,H as handleHubDeliveryPost,J as handleHubDeliveryRequest,I as hubDeliveryToResponse,l as isLoopbackDeliveryUrl,z as isServerDeliveryAckSuccessful,d as normalizeHubConfig,g as parseConnectSessionResponse,j as parseConnectStatusResponse,k as parseHubApiErrorBody,i as parseOAuthRefreshResponse,h as parsePermissionSessionResponse,y as parseServerDeliveryAckBody,u as processManagedOAuthDelivery,m as resolveConnectSourceFromDeliveryUrl,f as resolveHubOAuthCallbackUrl,K as respondToHubDelivery,L as respondToHubDeliveryFromRequest,n as shouldUseBrowserDelivery,E as signBrowserDeliveryToken,T as signConnectSessionToken,Y as signConnectToken,v as signDeliveryEnvelope,ba as signPermissionToken,o as validateExplicitConnectSource,F as verifyBrowserDeliveryToken,U as verifyConnectSessionToken,Z as verifyConnectToken,w as verifyDeliveryEnvelope,ca as verifyPermissionToken,x as verifySignedTunnelDelivery};
@@ -1,6 +1,6 @@
1
1
  import { CorsairDatabase } from './db.js';
2
- import { H as HubConfig } from './types-BY2SDx3_.js';
3
- import { C as CorsairPlugin, a as CorsairPermissionsOptions, b as CorsairManualConfig, c as CorsairIntegration, d as CorsairTenantWrapper, e as CorsairSingleTenantClient } from './index-x-RG0TdQ.js';
2
+ import { H as HubConfig } from './types-B9vj3Bq8.js';
3
+ import { C as CorsairPlugin, a as CorsairPermissionsOptions, b as CorsairManualConfig, c as CorsairIntegration, d as CorsairTenantWrapper, e as CorsairSingleTenantClient } from './index-DBW1TceJ.js';
4
4
 
5
5
  declare const CORSAIR_INTERNAL: unique symbol;
6
6
  type CorsairInternalConfig = {
@@ -1,9 +1,9 @@
1
1
  import { ZodTypeAny } from 'zod';
2
2
  import { CorsairDatabase, CorsairDatabaseInput } from './db.js';
3
3
  import { CorsairPluginSchema, PluginEntityClients } from './orm.js';
4
- import { c as AllErrors, A as AuthTypes, a as AllProviders } from './constants-CE0V2QbI.js';
5
- import { A as AccountKeyManagerFor, P as PluginAuthConfig, I as IntegrationKeyManagerFor, H as HubConfig, f as HubConfigInput } from './types-BY2SDx3_.js';
6
- import { M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult } from './types-BswoTGV5.js';
4
+ import { c as AllErrors, A as AuthTypes, a as AllProviders } from './constants-DnSLjl7e.js';
5
+ import { A as AccountKeyManagerFor, P as PluginAuthConfig, I as IntegrationKeyManagerFor, H as HubConfig, f as HubConfigInput } from './types-B9vj3Bq8.js';
6
+ import { M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult } from './types-CNagdEGY.js';
7
7
  import { a as CorsairPermission } from './index-ggMa1Rj6.js';
8
8
 
9
9
  /**
package/dist/index.d.ts CHANGED
@@ -1,22 +1,22 @@
1
- import { C as CorsairClientOptions, a as CorsairManagementClient } from './types-DoUHxHNl.js';
2
- export { b as CorsairClientError } from './types-DoUHxHNl.js';
3
- export { c as createCorsair } from './index-dta3YWl8.js';
4
- import { e as CorsairSingleTenantClient, C as CorsairPlugin, d as CorsairTenantWrapper, g as CorsairClient, s as CorsairPermissionsNamespace, S as BoundWebhookTree, _ as RawWebhookRequest, Z as CorsairWebhookTenantMatcher, a1 as WebhookResponse } from './index-x-RG0TdQ.js';
5
- export { a3 as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPermissionsOptions } from './index-x-RG0TdQ.js';
6
- import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-DhF58Vo8.js';
7
- export { A as AuthMissingError, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, o as firstString, f as formatDocSchemaShape, p as getHeader, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-DhF58Vo8.js';
1
+ import { C as CorsairClientOptions, a as CorsairManagementClient } from './types-DGS4LASW.js';
2
+ export { b as CorsairClientError } from './types-DGS4LASW.js';
3
+ export { c as createCorsair } from './index-4xQX76fp.js';
4
+ import { e as CorsairSingleTenantClient, C as CorsairPlugin, d as CorsairTenantWrapper, g as CorsairClient, s as CorsairPermissionsNamespace, S as BoundWebhookTree, _ as RawWebhookRequest, Z as CorsairWebhookTenantMatcher, a1 as WebhookResponse } from './index-DBW1TceJ.js';
5
+ export { a3 as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPermissionsOptions } from './index-DBW1TceJ.js';
6
+ import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-BTdQekAg.js';
7
+ export { A as AuthMissingError, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, o as firstString, f as formatDocSchemaShape, p as getHeader, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-BTdQekAg.js';
8
8
  export { SetupCorsairOptions, setupCorsair } from './setup.js';
9
9
  export { O as OAuthCallbackTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, p as processCorsair } from './index-LpuBJQ1m.js';
10
- import { B as BaseProviders } from './constants-CE0V2QbI.js';
11
- export { R as ResolveAccountFromWebhookLinkInput, W as WebhookTenantLink, r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-B7k-eaef.js';
12
- export { c as ConnectLink, a as ConnectionStatus, d as CreateConnectLinkInput, C as CreateTenantInput, M as ManagementOk, e as OAuthCallbackInput, O as OAuthCallbackResult, f as PermissionLookupInput, b as PermissionRecord, g as PluginConnectionState, P as PluginInfo, R as ResolvedConnectLink, T as Tenant } from './types-BswoTGV5.js';
10
+ import { B as BaseProviders } from './constants-DnSLjl7e.js';
11
+ export { R as ResolveAccountFromWebhookLinkInput, W as WebhookTenantLink, r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-WXEw8ztX.js';
12
+ export { c as ConnectLink, a as ConnectionStatus, d as CreateConnectLinkInput, C as CreateTenantInput, M as ManagementOk, e as OAuthCallbackInput, O as OAuthCallbackResult, f as PermissionLookupInput, b as PermissionRecord, g as PluginConnectionState, P as PluginInfo, R as ResolvedConnectLink, T as Tenant } from './types-CNagdEGY.js';
13
13
  import './db.js';
14
14
  import 'kysely';
15
15
  import './index-ggMa1Rj6.js';
16
16
  import 'zod';
17
17
  import 'pg';
18
18
  import 'postgres';
19
- import './types-BY2SDx3_.js';
19
+ import './types-B9vj3Bq8.js';
20
20
  import './orm.js';
21
21
 
22
22
  type ManagementHandlerOptions = {
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import{a as N,b as j}from"./chunk-XLNT2UI2.js";import{$ as b,$a as F,A as y,B as h,C as k,D as x,M as P,Ma as I,Na as O,Oa as R,Pa as T,Qa as A,Ua as l,Va as c,Wa as d,Xa as m,Za as L,_a as W,ab as v,bb as E,cb as _,db as $,hb as M,ib as D,jb as g,ka as S,kb as H,ra as w}from"./chunk-N6K7UBCS.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";function s(n){let t=n[g];if(!t)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return t.plugins}function B(n,t){let r=c(s(n),t);return typeof r=="string"?r:Array.isArray(r)?r.join(`
1
+ import{a as N,b as j}from"./chunk-XLNT2UI2.js";import{$ as b,$a as F,A as y,B as h,C as k,D as x,M as P,Ma as I,Na as O,Oa as R,Pa as T,Qa as A,Ua as l,Va as c,Wa as d,Xa as m,Za as L,_a as W,ab as v,bb as E,cb as _,db as $,hb as M,ib as D,jb as g,ka as S,kb as H,ra as w}from"./chunk-LSONNUVF.js";import"./chunk-FLNFC4KL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";function s(n){let t=n[g];if(!t)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return t.plugins}function B(n,t){let r=c(s(n),t);return typeof r=="string"?r:Array.isArray(r)?r.join(`
2
2
  `):Object.values(r).flat().join(`
3
3
  `)}function J(n,t){return d(s(n),t)}function q(n,t){return l(s(n),t)}var Y=Symbol.for("corsair:internal");function z(n,t){let r=n;for(let e of t){if(!r||typeof r!="object")return null;r=r[e]}return typeof r=="function"?r:null}function C(n){return n[Y]?.database}async function G(n,t){let r=new Date().toISOString(),e=await n.permissions.find_by_token(t);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<r){let o=C(n);return o&&await o.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let f=e.tenant_id??"default",a=(n.withTenant?n.withTenant(f):n)[e.plugin];if(!a?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let p=z(a.api,e.endpoint.split("."));if(!p)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let o=typeof e.args=="string"?JSON.parse(e.args):e.args,i=await p(o);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:i}}catch(o){let i=o instanceof Error?o.message:String(o),u=C(n);return u&&await u.db.updateTable("corsair_permissions").set({status:"failed",error:i,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:i}}}export{w as AuthMissingError,N as CorsairClientError,_ as asRecord,F as collectPluginWebhookMatchers,H as createCorsair,j as createCorsairClient,D as decodePubSubData,G as executePermission,M as firstString,m as formatDocSchemaShape,v as getHeader,J as getSchema,q as getStructuredSchema,B as listOperations,O as managementHandler,L as matchWebhookPlugin,W as matchWebhookPluginAndTenant,S as processCorsair,b as processWebhook,$ as readBodyRecord,h as resolveAccountFromWebhookLink,I as resolveConnectLink,x as resolveTenantFromWebhookLink,k as resolveTenantIdFromWebhookLink,y as setWebhookTenantLink,P as setupCorsair,R as toExpressHandler,E as toExternalId,T as toHonoHandler,A as toNextJsHandler};
package/dist/oauth.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as OAuthConfig } from './index-x-RG0TdQ.js';
1
+ import { O as OAuthConfig } from './index-DBW1TceJ.js';
2
2
  import 'zod';
3
3
  import './db.js';
4
4
  import 'kysely';
@@ -6,9 +6,9 @@ import './index-ggMa1Rj6.js';
6
6
  import 'pg';
7
7
  import 'postgres';
8
8
  import './orm.js';
9
- import './constants-CE0V2QbI.js';
10
- import './types-BY2SDx3_.js';
11
- import './types-BswoTGV5.js';
9
+ import './constants-DnSLjl7e.js';
10
+ import './types-B9vj3Bq8.js';
11
+ import './types-CNagdEGY.js';
12
12
 
13
13
  type OAuthState = {
14
14
  plugin: string;
package/dist/oauth.js CHANGED
@@ -1 +1 @@
1
- import{E as c,F as d,G as e,H as f,y as a,z as b}from"./chunk-N6K7UBCS.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{d as OAuthCallbackError,c as buildOAuthAuthorizeUrl,b as decodeOAuthState,a as encodeOAuthState,e as generateOAuthUrl,f as processOAuthCallback};
1
+ import{E as c,F as d,G as e,H as f,y as a,z as b}from"./chunk-LSONNUVF.js";import"./chunk-FLNFC4KL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{d as OAuthCallbackError,c as buildOAuthAuthorizeUrl,b as decodeOAuthState,a as encodeOAuthState,e as generateOAuthUrl,f as processOAuthCallback};
package/dist/orm.d.ts CHANGED
@@ -505,6 +505,10 @@ type EntitySearchOptions<DataSchema extends ZodTypeAny> = EntityFieldsFilter & {
505
505
  type PluginEntityClient<DataSchema extends ZodTypeAny> = {
506
506
  /** Find by external entity ID (e.g., Slack message ts). */
507
507
  findByEntityId: (entityId: string) => Promise<TypedEntity<DataSchema> | null>;
508
+ /** Check if an entity exists by external entity ID without loading payload data. */
509
+ existsByEntityId: (entityId: string) => Promise<boolean>;
510
+ /** Find internal UUID by external entity ID without loading payload data. */
511
+ findIdByEntityId: (entityId: string) => Promise<string | null>;
508
512
  /** Find by internal UUID. */
509
513
  findById: (id: string) => Promise<TypedEntity<DataSchema> | null>;
510
514
  /** Find multiple by external entity IDs. */
package/dist/orm.js CHANGED
@@ -1 +1 @@
1
- import"./chunk-N2XRSSRL.js";import{m as o,n as e,o as n,p as s}from"./chunk-NZS35HPL.js";import{b as r,c as t,d as i,e as a}from"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{t as CorsairAccountsSchema,i as CorsairEntitiesSchema,a as CorsairEventsSchema,r as CorsairIntegrationsSchema,o as createCorsairOrm,e as createPluginOrm,s as createPluginOrmFactory,n as createTenantScopedOrm};
1
+ import"./chunk-N2XRSSRL.js";import{m as o,n as e,o as n,p as s}from"./chunk-FLNFC4KL.js";import{b as r,c as t,d as i,e as a}from"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{t as CorsairAccountsSchema,i as CorsairEntitiesSchema,a as CorsairEventsSchema,r as CorsairIntegrationsSchema,o as createCorsairOrm,e as createPluginOrm,s as createPluginOrmFactory,n as createTenantScopedOrm};
package/dist/setup.d.ts CHANGED
@@ -1,15 +1,15 @@
1
- import { a as CorsairInternalConfig } from './index-dta3YWl8.js';
1
+ import { a as CorsairInternalConfig } from './index-4xQX76fp.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { C as CorsairPlugin, e as CorsairSingleTenantClient, d as CorsairTenantWrapper } from './index-x-RG0TdQ.js';
4
- import './types-BY2SDx3_.js';
5
- import './constants-CE0V2QbI.js';
3
+ import { C as CorsairPlugin, e as CorsairSingleTenantClient, d as CorsairTenantWrapper } from './index-DBW1TceJ.js';
4
+ import './types-B9vj3Bq8.js';
5
+ import './constants-DnSLjl7e.js';
6
6
  import 'kysely';
7
7
  import './index-ggMa1Rj6.js';
8
8
  import 'zod';
9
9
  import 'pg';
10
10
  import 'postgres';
11
11
  import './orm.js';
12
- import './types-BswoTGV5.js';
12
+ import './types-CNagdEGY.js';
13
13
 
14
14
  /** Plugin id → credential field → value (from CLI `field=value` pairs). */
15
15
  type SetupCredentials = Record<string, Record<string, string>>;
package/dist/setup.js CHANGED
@@ -1 +1 @@
1
- import{M as a,N as b}from"./chunk-N6K7UBCS.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as applySetupCredentials,a as setupCorsair};
1
+ import{M as a,N as b}from"./chunk-LSONNUVF.js";import"./chunk-FLNFC4KL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as applySetupCredentials,a as setupCorsair};
@@ -1,5 +1,5 @@
1
- import { A as AuthTypes } from './constants-CE0V2QbI.js';
2
- import { W as WebhookTenantMatch } from './index-x-RG0TdQ.js';
1
+ import { A as AuthTypes } from './constants-DnSLjl7e.js';
2
+ import { W as WebhookTenantMatch } from './index-DBW1TceJ.js';
3
3
  import { C as CorsairAccount } from './index-ggMa1Rj6.js';
4
4
  import { CorsairDatabase } from './db.js';
5
5
 
@@ -1,5 +1,5 @@
1
- import { D as EndpointRiskLevel, C as CorsairPlugin, Y as CorsairWebhookMatcher, Z as CorsairWebhookTenantMatcher, _ as RawWebhookRequest, W as WebhookTenantMatch } from './index-x-RG0TdQ.js';
2
- import { a as AllProviders } from './constants-CE0V2QbI.js';
1
+ import { D as EndpointRiskLevel, C as CorsairPlugin, Y as CorsairWebhookMatcher, Z as CorsairWebhookTenantMatcher, _ as RawWebhookRequest, W as WebhookTenantMatch } from './index-DBW1TceJ.js';
2
+ import { a as AllProviders } from './constants-DnSLjl7e.js';
3
3
 
4
4
  /**
5
5
  * Error thrown when a plugin endpoint is called but the required auth credentials
package/dist/tunnel.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { B as BrowserDeliveryPayload } from './index-LpuBJQ1m.js';
2
2
  export { O as OAuthCallbackTunnelPayload, b as OAuthTokensTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, a as applyPermissionDecision, p as processCorsair } from './index-LpuBJQ1m.js';
3
- export { r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-B7k-eaef.js';
3
+ export { r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-WXEw8ztX.js';
4
4
  export { v as verifyBrowserDeliveryToken } from './browser-delivery-CvBUoA96.js';
5
- import './constants-CE0V2QbI.js';
6
- import './index-x-RG0TdQ.js';
5
+ import './constants-DnSLjl7e.js';
6
+ import './index-DBW1TceJ.js';
7
7
  import 'zod';
8
8
  import './db.js';
9
9
  import 'kysely';
@@ -11,8 +11,8 @@ import './index-ggMa1Rj6.js';
11
11
  import 'pg';
12
12
  import 'postgres';
13
13
  import './orm.js';
14
- import './types-BY2SDx3_.js';
15
- import './types-BswoTGV5.js';
14
+ import './types-B9vj3Bq8.js';
15
+ import './types-CNagdEGY.js';
16
16
 
17
17
  declare function isConnectStatusBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
18
18
  declare function isAuthCredentialsBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
package/dist/tunnel.js CHANGED
@@ -1 +1 @@
1
- import{A as a,B as b,C as c,D as d,da as e,ea as f,fa as g,ga as h,ha as i,ia as j,ja as k,ka as l}from"./chunk-N6K7UBCS.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{k as applyPermissionDecision,g as isAuthCredentialsBrowserDelivery,j as isByoOAuthBrowserDelivery,f as isConnectStatusBrowserDelivery,i as isManagedBrowserDelivery,h as isPermissionBrowserDelivery,l as processCorsair,b as resolveAccountFromWebhookLink,d as resolveTenantFromWebhookLink,c as resolveTenantIdFromWebhookLink,a as setWebhookTenantLink,e as verifyBrowserDeliveryToken};
1
+ import{A as a,B as b,C as c,D as d,da as e,ea as f,fa as g,ga as h,ha as i,ia as j,ja as k,ka as l}from"./chunk-LSONNUVF.js";import"./chunk-FLNFC4KL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{k as applyPermissionDecision,g as isAuthCredentialsBrowserDelivery,j as isByoOAuthBrowserDelivery,f as isConnectStatusBrowserDelivery,i as isManagedBrowserDelivery,h as isPermissionBrowserDelivery,l as processCorsair,b as resolveAccountFromWebhookLink,d as resolveTenantFromWebhookLink,c as resolveTenantIdFromWebhookLink,a as setWebhookTenantLink,e as verifyBrowserDeliveryToken};
@@ -1,4 +1,4 @@
1
- import { A as AuthTypes } from './constants-CE0V2QbI.js';
1
+ import { A as AuthTypes } from './constants-DnSLjl7e.js';
2
2
 
3
3
  type HubConnectSource = 'client' | 'server';
4
4
  type HubOAuthMode = 'byo' | 'managed';
@@ -1,5 +1,5 @@
1
1
  import { a as CorsairPermission } from './index-ggMa1Rj6.js';
2
- import { A as AuthTypes } from './constants-CE0V2QbI.js';
2
+ import { A as AuthTypes } from './constants-DnSLjl7e.js';
3
3
 
4
4
  type Tenant = {
5
5
  id: string;
@@ -1,4 +1,4 @@
1
- import { M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult } from './types-BswoTGV5.js';
1
+ import { M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult } from './types-CNagdEGY.js';
2
2
 
3
3
  type CorsairClientOptions = {
4
4
  /** Origin + base path of the mounted handler, e.g. 'https://api.example.com/api/corsair'. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsair",
3
- "version": "0.1.90",
3
+ "version": "0.1.92",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,38 +0,0 @@
1
- import{a as se,b as nr,c as P,d as $,e as tr,f as J,g as E,h as H,i as en,j as rr,k as qn,l as or,m as ir}from"./chunk-NZS35HPL.js";import{a as er}from"./chunk-IGGCNGU2.js";var nn=["ahrefs","airtable","amplitude","asana","bitwarden","bluesky","box","cal","calendly","cloudflare","cursor","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","github","gitlab","gmail","googlecalendar","googledrive","googlesheets","grafana","hackernews","hubspot","intercom","jira","linear","monday","notion","onedrive","openweathermap","oura","outlook","pagerduty","posthog","razorpay","reddit","resend","sentry","sharepoint","slack","spotify","strava","stripe","tally","tavily","teams","telegram","todoist","trello","twilio","twitter","twitterapiio","typeform","vapi","xquik","youtube","zendesk","zohomail","zoom"],sr={ahrefs:"Ahrefs",airtable:"Airtable",amplitude:"Amplitude",asana:"Asana",bitwarden:"Bitwarden",bluesky:"Bluesky",box:"Box",cal:"Cal",calendly:"Calendly",cloudflare:"Cloudflare",cursor:"Cursor",discord:"Discord",dodopayments:"Dodo Payments",dropbox:"Dropbox",exa:"Exa",figma:"Figma",firecrawl:"Firecrawl",fireflies:"Fireflies",github:"GitHub",gitlab:"GitLab",gmail:"Gmail",googlecalendar:"Google Calendar",googledrive:"Google Drive",googlesheets:"Google Sheets",grafana:"Grafana",hackernews:"Hacker News",hubspot:"HubSpot",intercom:"Intercom",jira:"Jira",linear:"Linear",monday:"Monday",notion:"Notion",onedrive:"OneDrive",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",resend:"Resend",sentry:"Sentry",sharepoint:"SharePoint",slack:"Slack",spotify:"Spotify",strava:"Strava",stripe:"Stripe",tally:"Tally",tavily:"Tavily",teams:"Teams",telegram:"Telegram",todoist:"Todoist",trello:"Trello",twilio:"Twilio",twitter:"Twitter",twitterapiio:"Twitter API IO",typeform:"Typeform",vapi:"Vapi",xquik:"XQuik",youtube:"YouTube",zendesk:"Zendesk",zohomail:"Zoho Mail",zoom:"Zoom"};function ae(e){let n=sr[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var $e="https://auth.corsair.dev";var he=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret, deliveryUrl } to createCorsair()."),this.name="HubNotConfiguredError"}};function tn(e){let n=(e.apiUrl?.trim()||$e).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim(),i=e.deliveryUrl.trim();if(!t||!r||!i)throw new Error("Hub config requires non-empty projectApiKey, signingSecret, and deliveryUrl");return{apiUrl:n,projectApiKey:t,signingSecret:r,deliveryUrl:i,oauthCallbackUrl:e.oauthCallbackUrl?.trim()}}function vo(e){return e.apiUrl.trim().length>0&&e.deliveryUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function B(e){let n=P(e).hub;if(!n||!vo(n))throw new he;return n}function rn(e){return e.oauthCallbackUrl?e.oauthCallbackUrl:`${e.apiUrl.replace(/\/$/,"")}/oauth/callback`}function R(e){return typeof e=="string"&&e.length>0}function on(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!R(n.connectUrl)||!R(n.token)||!R(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};return R(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function sn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!R(n.approvalUrl)||!R(n.token)||!R(n.projectId)||!R(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 an(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(!R(n.access_token))throw new Error("Hub token refresh returned no access_token");return{access_token:n.access_token,refresh_token:R(n.refresh_token)?n.refresh_token:void 0,expires_in:typeof n.expires_in=="number"?n.expires_in:void 0,scope:R(n.scope)?n.scope:void 0}}function Ao(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function xo(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;R(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 So(e,n,t,r){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"?e:n?"ready":t.some(o=>o.level==="integration"&&o.required&&!o.configured)?"missing_integration":t.some(o=>o.level==="account"&&o.required&&o.configured)?"partial":(r.length>0,"not_started")}function ar(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!R(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 i=r;if(!R(i.plugin)||typeof i.connected!="boolean")continue;let o=i.authKind==="oauth"||i.authKind==="api_key"||i.authKind==="bot_token"?i.authKind:"api_key",a=xo(i.fields),s=Ao(i.missingRequiredFields),u=So(i.status,i.connected,a,s);t.push({plugin:i.plugin,providerName:R(i.providerName)?i.providerName:i.plugin,authKind:o,status:u,connected:i.connected,fields:a,missingRequiredFields:s})}return{tenantId:n.tenantId,plugins:t}}function un(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function Ro(e){return e.replace(/\/$/,"")}async function Io(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 _o(e,n,t){if(n===404&&t)return t;let r=un(e);return r||`Hub API returned HTTP ${n}`}async function xe(e){let n=Ro(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`},body:JSON.stringify(e.body)}),r=await Io(t);if(!t.ok)throw new Error(_o(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as ur,createDecipheriv as cr,randomBytes as cn,scrypt as Eo}from"crypto";import{promisify as Do}from"util";var lr=Do(Eo),ln="aes-256-gcm",dr=12,dn=16,Oo=16,Le=32;function ee(){return cn(Le).toString("base64")}async function ne(e,n){let t=cn(Oo),r=await lr(n,t,Le),i=cn(dr),o=ur(ln,r,i,{authTagLength:dn}),a=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[t.toString("base64"),i.toString("base64"),s.toString("base64"),a.toString("base64")].join(":")}async function L(e,n){let[t,r,i,o]=e.split(":");if(!t||!r||!i||!o)throw new Error("Invalid encrypted DEK format");let a=Buffer.from(t,"base64"),s=Buffer.from(r,"base64"),u=Buffer.from(i,"base64"),c=Buffer.from(o,"base64"),d=await lr(n,a,Le),l=cr(ln,d,s,{authTagLength:dn});return l.setAuthTag(u),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function Gn(e,n){let t=Buffer.from(n,"base64"),r=cn(dr),i=ur(ln,t,r,{authTagLength:dn}),o=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[r.toString("base64"),a.toString("base64"),o.toString("base64")].join(":")}function We(e,n){let[t,r,i]=e.split(":");if(!t||!r||!i)throw new Error("Invalid encrypted data format");let o=Buffer.from(n,"base64"),a=Buffer.from(t,"base64"),s=Buffer.from(r,"base64"),u=Buffer.from(i,"base64"),c=cr(ln,o,a,{authTagLength:dn});return c.setAuthTag(s),Buffer.concat([c.update(u),c.final()]).toString("utf8")}function ue(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=Gn(i,n);return t}function te(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=We(i,n);return t}function je(e,n,t){let r=te(e,n);return ue(r,t)}function pr(e,n,t){let r={};for(let i of t)r[`get_${i}`]=async()=>(await e())[i]??null,r[`set_${i}`]=async o=>{let a=[null,void 0,""].includes(o)?null:o;await n({[i]:a})};return r}var Jn=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function I(e){let{authType:n,integrationName:t,kek:r,database:i,extraIntegrationFields:o=[]}=e,a=[...E[n].integration,...o],s=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(s)return s;let g=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!g)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return s={id:g.id,config:Jn(g.config),dek:g.dek??null},s},updateIntegration:async g=>{let y=await u.getIntegration();await i.db.updateTable("corsair_integrations").set({...g.config!==void 0?{config:g.config}:{},...g.dek!==void 0?{dek:g.dek}:{},updated_at:new Date}).where("id","=",y.id).execute(),s=null}},c=null,d=async()=>{if(c)return c;let g=await u.getIntegration();if(!g.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return c=await L(g.dek,r),c},l=async()=>{let g=await u.getIntegration(),y=await d(),h=g.config;return!h||Object.keys(h).length===0?{}:te(h,y)};return{get_dek:d,issue_new_dek:async()=>{let g=await u.getIntegration(),y=ee(),h={};if(g.dek){let C=await L(g.dek,r),b=g.config;b&&Object.keys(b).length>0&&(h=je(b,C,y))}let m=await ne(y,r);return await u.updateIntegration({config:h,dek:m}),c=y,y},...pr(l,async g=>{let y=await d(),h;try{h=await l()}catch(b){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,b),h={}}let m={...h};for(let[b,k]of Object.entries(g))k===null?delete m[b]:m[b]=k;let C=ue(m,y);await u.updateIntegration({config:C})},a)}}function S(e){let{authType:n,integrationName:t,tenantId:r,kek:i,database:o,extraAccountFields:a=[]}=e,s=[...E[n].account,...a],u=null,c=null,d=async()=>{if(c)return c;let k=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!k)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return c={id:k.id,config:Jn(k.config),dek:k.dek??null},c},l={kek:i,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(u)return u;let k=await d(),w=await o.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",k.id).executeTakeFirst();if(!w)throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`);return u={id:w.id,config:Jn(w.config),dek:w.dek??null},u},updateAccount:async k=>{let w=await l.getAccount();await o.db.updateTable("corsair_accounts").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",w.id).execute(),u=null}},p=null,f=null,g=async()=>{if(p)return p;let k=await l.getAccount();if(!k.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return p=await L(k.dek,i),p},y=async()=>{if(f)return f;let k=await l.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await L(k.dek,i),f},h=async()=>{let k=await l.getAccount(),w=await g(),T=k.config;return!T||Object.keys(T).length===0?{}:te(T,w)},m=async()=>{let k=await l.getIntegration(),w=await y(),T=k.config;return!T||Object.keys(T).length===0?{}:te(T,w)},b={get_dek:g,issue_new_dek:async()=>{let k=await l.getAccount(),w=ee(),T={};if(k.dek){let O=await L(k.dek,i),M=k.config;M&&Object.keys(M).length>0&&(T=je(M,O,w))}let D=await ne(w,i);return await l.updateAccount({config:T,dek:D}),p=w,w},...pr(h,async k=>{let w=await g(),T;try{T=await h()}catch(M){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,M),T={}}let D={...T};for(let[M,A]of Object.entries(k))A===null?delete D[M]:D[M]=A;let O=ue(D,w);await l.updateAccount({config:O})},s)};return n==="oauth_2"&&(b.get_integration_credentials=async()=>{let k=await m();return{client_id:k.client_id||null,client_secret:k.client_secret||null,redirect_url:k.redirect_url??null}}),b}async function gr(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 i=ee(),o=await ne(i,t);return await e.db.updateTable("corsair_integrations").set({dek:o,updated_at:new Date}).where("id","=",r.id).execute(),i}async function fr(e,n,t,r){let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!i)throw new Error(`Integration "${n}" not found.`);let o=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",i.id).executeTakeFirst();if(!o)throw new Error(`Account not found for tenant "${t}" and integration "${n}".`);let a=ee(),s=await ne(a,r);return await e.db.updateTable("corsair_accounts").set({dek:s,updated_at:new Date}).where("id","=",o.id).execute(),a}var Mo=new Set(["webhook_signature","expires_at","scope","redirect_url"]);function Se(e){return Mo.has(e)}function Ho(e,n){return Se(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Fo(e){return!Se(e)}function Bo(e){switch(e){case"oauth_2":case"managed":return["access_token","refresh_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function Uo(e,n){return Bo(e).every(r=>n.find(o=>o.level==="account"&&o.name===r)?.configured??!1)}async function yr(e,n){if(!e)return!1;let t=J(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function No(e,n){let r=e.authConfig?.[n]?.integration??[];return[...E[n].integration,...r]}function $o(e,n){let r=e.authConfig?.[n]?.account??[];return[...E[n].account,...r]}function Lo(e,n,t){let r=t.filter(s=>s.required&&!s.configured).map(s=>s.name),i=t.filter(s=>s.level==="integration"&&s.required&&!s.configured).map(s=>s.name),o=t.filter(s=>s.level==="account"&&s.required&&s.configured),a;return i.length>0?a="missing_integration":r.length===0?a="ready":o.length>0?a="partial":a="not_started",{plugin:e,authType:n,status:a,connected:Uo(n,t),fields:t,missingRequiredFields:r}}async function pn(e,n,t){let r=H(n);if(!r||!e.database||!e.kek)return null;let i=t.trim()||"default",o=n.authConfig,a=o?.[r]?.integration??[],s=o?.[r]?.account??[],u=I({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:a}),c=S({authType:r,integrationName:n.id,tenantId:i,kek:e.kek,database:e.database,extraAccountFields:s}),d=No(n,r),l=$o(n,r),p=[];for(let f of d)p.push({name:f,level:"integration",required:Ho(r,f),configured:await yr(u,f)});for(let f of l)p.push({name:f,level:"account",required:Fo(f),configured:await yr(c,f)});return Lo(n.id,r,p)}async function Ke(e,n,t={}){let r=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,o=[];for(let a of e.plugins){if(i&&!i.has(a.id))continue;let s=await pn(e,a,r);s&&o.push(s)}return o}function gn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}import*as Ze from"crypto";function z(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function zn(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 i=r;return n!==void 0&&typeof i.iat=="number"&&Date.now()-i.iat>n?null:i}return null}catch{return null}}function ce(e,n){let t=Ze.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Vn=600*1e3;function fn(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),i=e.slice(t+1),o=Ze.createHmac("sha256",n).update(r).digest("base64url"),a=Buffer.from(i,"base64url"),s=Buffer.from(o,"base64url");return a.length!==s.length||!Ze.timingSafeEqual(a,s)?null:zn(r,{maxAgeMs:Vn})}var Wo=new Set(["localhost","127.0.0.1","[::1]","::1"]);function qe(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Wo.has(n)}catch{return!1}}function Re(e){return qe(e)?"client":"server"}function hr(e,n){return e==="client"||qe(n)}function Ie(e){if(!e.source)return null;let n=qe(e.deliveryUrl);return e.source==="server"&&n?{error:'source "server" cannot be used with a loopback delivery URL \u2014 omit source to auto-detect or use "client"',status:400}:e.oauthMode==="managed"&&e.source==="client"&&!n?{error:'managed OAuth with source "client" requires a loopback delivery URL \u2014 omit source for production server delivery',status:400}:null}import{ZodBoolean as Ko,ZodDate as Zo,ZodEnum as qo,ZodNullable as Go,ZodNumber as Jo,ZodObject as zo,ZodOptional as Vo,ZodRecord as Yo,ZodString as Qo,ZodType as Xo}from"zod";var jo={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:{}}},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:{}}}},Yn=jo;async function kr(e,n){let t=[],r=p=>{t.push(p),console.log(p)},i=p=>{t.push(p),console.warn(p)},o=n?.caller??"script",a=nr(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 s=ni(e,a.plugins,n),u={...a,database:a.database},c=u.database.db;await oi(c,i);let d=await ii(c,u,s.tenantId,s.provisionAccounts,r);n?.credentials&&Object.keys(n.credentials).length>0&&await ui(e,s,n.credentials,u,r,i);let l=await li(d,s,r,o);if(n?.backfill){r("[corsair:setup] Starting backfill...");let p=Cr({plugins:a.plugins,database:c,kek:a.kek,multiTenancy:!0}).withTenant(s.tenantId);await di(p,a.plugins,l,r,i),r("[corsair:setup] Backfill complete.")}return t.join(`
2
- `)}function Qn(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...E[n][t],...r])}function ei(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let i=n.find(s=>s.id===t);if(!i)continue;let o=H(i);if(!o)continue;let a=Qn(i,o,"account");for(let s of Object.keys(r))if(a.has(s))return!0}return!1}function ni(e,n,t){let r=tr(e),i=t?.tenantId?.trim(),o=i!==void 0&&i.length>0;if(r&&t?.backfill&&!o)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(r&&ei(t?.credentials,n)&&!o)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(o&&!i)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:r,tenantIdProvided:o,tenantId:o?i:"default",provisionAccounts:!r||o}}function br(e,n){return se(e)?n===0?!0:Object.values(e).every(t=>br(t,n-1)):!1}function ti(e){return br(e,4)}var ri={...or};function yn(e){if(e instanceof zo){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Xo?yn(r):"unknown";return n}return e instanceof Go?`${yn(e.unwrap())} | null`:e instanceof Vo?`${yn(e.unwrap())} | undefined`:e instanceof qo?e.options.join(" | "):e instanceof Qo?"string":e instanceof Jo?"number":e instanceof Ko?"boolean":e instanceof Zo?"date":e instanceof Yo?"jsonb":"unknown"}async function oi(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(i=>i.name));for(let[i,o]of Object.entries(ri))r.has(i)||n(`[corsair:setup] Table "${i}" does not exist. Run your database migrations before calling setupCorsair.
3
- Schema: ${JSON.stringify(yn(o),null,2)}`)}async function ii(e,n,t,r,i){let o=new Date,a=new Map;for(let s of n.plugins){let u=s.id,c=H(s),d=await e.selectFrom("corsair_integrations").selectAll().where("name","=",u).executeTakeFirst();if(!d){let y=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:y,name:u,config:{},created_at:o,updated_at:o}).execute(),d=await e.selectFrom("corsair_integrations").selectAll().where("id","=",y).executeTakeFirst(),i(`[corsair:setup] Created integration: ${u}`)}let l=c?s.authConfig?.[c]?.integration??[]:[],p=c?s.authConfig?.[c]?.account??[]:[],f=c&&d?I({authType:c,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:l}):void 0;if(d&&!d.dek&&f&&(await f.issue_new_dek(),i(`[corsair:setup] Issued integration DEK: ${u}`)),!d||!c||!f)continue;let g;if(r){let y=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",d.id).executeTakeFirst();if(!y){let h=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:h,tenant_id:t,integration_id:d.id,config:{},created_at:o,updated_at:o}).execute(),y=await e.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),i(`[corsair:setup] Created account: ${u}`)}g=y&&S({authType:c,integrationName:u,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:p}),y&&g&&!y.dek&&(await g.issue_new_dek(),i(`[corsair:setup] Issued account DEK: ${u}`))}a.set(u,{pluginId:u,authType:c,integration:f,account:g,integrationFields:[...E[c].integration,...l],accountFields:r?[...E[c].account,...p]:[]})}return a}function si(e){if(!se(e))return;let n=e.keys;return se(n)?n:void 0}function ai(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function ui(e,n,t,r,i,o){let a=si(e),s=n.provisionAccounts?ai(e,n.tenantId):void 0;for(let[u,c]of Object.entries(t)){let d=r.plugins.find(m=>m.id===u);if(!d){o(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let l=H(d);if(!l){o(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let p=Qn(d,l,"integration"),f=Qn(d,l,"account"),g=a?.[u],y=s?.[u],h=se(y)?y.keys:void 0;for(let[m,C]of Object.entries(c))if(C){if(p.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 b=J(g,`set_${m}`);if(!b){o(`[corsair:setup] Cannot set integration field '${m}' for '${u}'.`);continue}await b(C),i(`[corsair:setup] Set ${u} integration.${m}`);continue}if(f.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 b=J(h,`set_${m}`);if(!b){o(`[corsair:setup] Cannot set account field '${m}' for '${u}'.`);continue}await b(C),i(`[corsair:setup] Set ${u} account.${m} (tenant=${n.tenantId})`);continue}o(`[corsair:setup] Unknown credential field '${m}' for plugin '${u}'.`)}}}var mr=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function ci(e,n,t,r,i,o,a,s,u){let c=[],d=[];for(let p of i){if(mr.has(p))continue;let f=J(t,`get_${p}`);if(!f)continue;let g=null;try{let y=await f();g=typeof y=="string"?y:null}catch{}g||c.push(p)}if(r&&o.length>0)for(let p of o){if(mr.has(p))continue;let f=J(r,`get_${p}`);if(!f)continue;let g=null;try{let y=await f();g=typeof y=="string"?y:null}catch{}g||d.push(p)}let l=c.length===0&&d.length===0;if(l)s(`[corsair:setup] '${e}' (${n}) is configured \u2713`);else if(n==="managed")s(`[corsair:setup] '${e}' (managed) is not connected yet. Use Connect in your app \u2014 Corsair Hub delivers OAuth tokens after authorization.`);else{let p=[...c,...d];if(u==="cli"){let f=p.map(g=>`${g}=VALUE`).join(" ");s(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
4
- corsair setup --${e} ${f}`)}else{let f=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let g of c)f.push(` await corsair.keys.${e}.set_${g}(value)`);for(let g of d){let y=a.provisionAccounts?a.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(a.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;f.push(` await ${y}.keys.set_${g}(value)`)}s(f.join(`
5
- `))}}return l}async function li(e,n,t,r){let i=new Set;for(let o of e.values())await ci(o.pluginId,o.authType,o.integration,o.account,o.integrationFields,o.accountFields,n,t,r)&&i.add(o.pluginId);return i}async function di(e,n,t,r,i){if(!ti(Yn)){i("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let o=Yn,a=new Set(n.map(s=>s.id));for(let[s,u]of Object.entries(o)){if(!a.has(s))continue;if(!t.has(s)){r(`[corsair:setup] Skipping backfill for '${s}' \u2014 auth not configured.`);continue}let c=se(e)?e[s]:void 0,d=se(c)?c.api:void 0;if(d)for(let[l,p]of Object.entries(u))for(let[f,g]of Object.entries(p)){r(`[corsair:setup] Backfilling ${s} \u203A ${l}.${f}...`);try{let y=se(d)?d[l]:void 0;await J(y,f)?.(g)}catch(y){i(`[corsair:setup] ${s} \u203A ${l}.${f} failed: `+(y instanceof Error?y.message:String(y)))}}}}async function _e(e,n){if(!P(e).database)throw new Error("A database must be configured to provision Corsair for connect");await kr(e,{tenantId:n})}var pi=new Set(["access_token","refresh_token","expires_at","scope"]);function gi(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function fi(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!Se(t)&&!pi.has(t)):n.filter(t=>!Se(t))}async function wr(e,n,t={}){let r=P(e),i=B(e),o=rn(i),a=[],s=t.pluginIds?new Set(t.pluginIds):null;for(let u of r.plugins){if(s&&!s.has(u.id))continue;let c=H(u);if(!c)continue;let d=gi(c),l=t.providerNameOverrides?.[u.id]??ae(u.id),p=await pn(r,u,n),f=en(u,c),g=fi(c,f),y={plugin:u.id,providerName:l,authKind:d,alreadyConfigured:p?.connected??!1};if(g.length>0&&(y.credentialFields=g),d==="oauth"){let m=t.oauthModeOverrides?.[u.id]??(c==="managed"?"managed":"byo");if(y.oauthMode=m,!t.skipOAuthUrlGeneration)if(m==="managed")y.state=ce(z(u.id,n),r.kek);else try{let C=await Xn(e,u.id,{tenantId:n,redirectUri:o});y.oauthUrl=C.url,y.state=C.state}catch(C){y.setupError=C instanceof Error?C.message:`Could not prepare OAuth for ${u.id}`}}a.push(y)}return a}function Tr(e,n){let t=B(e);if(n){let r=Ie({source:n,deliveryUrl:t.deliveryUrl});if(r)throw new Error(r.error);return n}return Re(t.deliveryUrl)}async function Pr(e,n){await _e(e,n)}async function hn(e,n){let t=B(e);await Pr(e,n.tenantId);let r=n.plugin?[n.plugin]:void 0,i=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,o=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,a=await wr(e,n.tenantId,{pluginIds:r,oauthModeOverrides:i,providerNameOverrides:o});if(a.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");let s=Tr(e,n.source);return xe({hub:t,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:{tenantId:n.tenantId,deliveryUrl:t.deliveryUrl,source:s,plugins:a},parseResponse:on})}function vr(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function yi(e,n){return n&&!n.has(e.id)?!1:H(e)!==null}async function Ee(e,n,t={}){let r=P(e),i=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,a=await Ke(r,i,{pluginIds:t.pluginIds}),s=new Map(a.map(c=>[c.plugin,c])),u=r.plugins.filter(c=>yi(c,o)).map(c=>{let d=H(c),l=s.get(c.id);return l?{plugin:c.id,providerName:ae(c.id),authKind:vr(d),status:l.status,connected:l.connected,fields:l.fields.map(p=>({name:p.name,level:p.level,required:p.required,configured:p.configured})),missingRequiredFields:l.missingRequiredFields}:{plugin:c.id,providerName:ae(c.id),authKind:vr(d),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:i,plugins:u}}var le=6e4,me=3e5;var V=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function mn(e,n){let t=P(e,()=>new V("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new V("no_database","Database not configured");let r=$(t,n.plugin,d=>new V("plugin_not_found",d)),i=H(r);if(!i)throw new V("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(i==="oauth_2"||i==="managed")throw new V("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await _e(e,n.tenantId);let o=new Set(en(r,i)),s=r.authConfig?.[i]?.account??[],u=S({authType:i,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:s}),c=0;for(let[d,l]of Object.entries(n.credentials)){if(!l.trim())continue;if(!o.has(d))throw new V("invalid_credentials",`Unknown credential field '${d}' for plugin '${n.plugin}'`);let p=J(u,`set_${d}`);if(!p)throw new V("invalid_credentials",`Cannot set credential field '${d}' for plugin '${n.plugin}'`);await p(l.trim()),c+=1}if(c===0)throw new V("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var kn=new Map;function hi(e){for(let[n,t]of kn)t<=e&&kn.delete(n)}function bn(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return hi(r),kn.has(t)?{ok:!1,error:"Delivery request already consumed"}:(kn.set(t,r+n),{ok:!0})}async function Cn(e,n,t){for(let r of e){if(r.id!==n)continue;let i=r.oauthWebhookTenantLinkResolver;return i?i(t):null}return null}var Ar=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function mi(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 ki(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 L(n.dek,e.kek),r=Ar(n.config),i={};Object.keys(r).length>0&&(i=te(r,t)),i[e.link.linkType]=e.link.externalId;let o=ue(i,t);await e.database.db.updateTable("corsair_accounts").set({config:o,updated_at:new Date}).where("id","=",n.id).execute()}async function De(e){let{database:n,kek:t,pluginId:r,tenantId:i,link:o,authType:a,extraAccountFields:s=[]}=e,{accountId:u}=await mi({database:n,pluginId:r,tenantId:i}),c=!1;if(a){let d=S({authType:a,integrationName:r,tenantId:i,kek:t,database:n,extraAccountFields:s}),l=`set_${o.linkType}`,p=d[l];typeof p=="function"&&(await p(o.externalId),c=!0)}c||await ki({database:n,kek:t,accountId:u,link:o})}async function et(e){let{database:n,kek:t,pluginId:r,linkType:i,externalId:o}=e,a=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 s of a)if(s.dek)try{let u=await L(s.dek,t),d=Ar(s.config)[i];if(!d)continue;if(We(d,u)===o)return s}catch{continue}return null}async function wn(e){return(await et(e))?.tenant_id??null}async function xr(e){return wn({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var de=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Oe(e,n){let{plugin:t,tenantId:r,accessToken:i,refreshToken:o,expiresIn:a,scope:s}=n;if(!i.trim())throw new de("no_access_token","Managed OAuth delivery missing access_token");let u=P(e,()=>new de("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new de("no_database","No database configured on corsair instance");let c=$(u,t,l=>new de("plugin_not_found",l));await _e(e,r);let d=S({authType:"managed",integrationName:t,tenantId:r,kek:u.kek,database:u.database});await d.set_access_token(i),o&&await d.set_refresh_token(o),a&&await d.set_expires_at(String(Math.floor(Date.now()/1e3)+a)),s&&await d.set_scope(s);try{let l=await Cn(u.plugins,t,{access_token:i,refresh_token:o,scope:s});if(l)try{let p=c.authConfig?.managed?.account??[];await De({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:l,authType:"managed",extraAccountFields:p})}catch(p){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,p)}}catch(l){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,l)}return{plugin:t,tenantId:r}}import{createHmac as nt,randomUUID as bi,timingSafeEqual as Sr}from"crypto";function Rr(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function Tn(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=nt("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":bi()}}}function tt(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Rr(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>3e5)return!1;let o=nt("sha256",n).update(e.body).digest("hex");try{return Sr(Buffer.from(o,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function Me(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=Rr(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)>3e5)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let o=nt("sha256",n).update(e.body).digest("hex");try{if(!Sr(Buffer.from(o,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}function rt(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function ot(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function it(e){return e.status===0?`Could not reach delivery URL (${e.deliveryUrl}): ${e.ack.error??e.body}`:e.ack.error??e.body??`HTTP ${e.status}`}async function st(e){let{body:n,headers:t}=Tn(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),i=await r.text();return{ok:r.ok,status:r.status,body:i}}catch(r){return{ok:!1,status:0,body:r instanceof Error?r.message:"Delivery request failed"}}}function Ci(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Ir(e,n,t=[]){for(let[r,i]of Object.entries(e))if(Ci(i)){if(i.match(n))return{webhook:i,path:[...t,r]}}else if(i&&typeof i=="object"){let o=Ir(i,n,[...t,r]);if(o)return o}return null}function wi(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Ti(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 _r(e,n,t,r){let i=wi(n),o=typeof t=="string"?JSON.parse(t):t;(!o||typeof o=="object"&&Object.keys(o).length===0)&&i["x-goog-resource-uri"]&&(o=Ti(i)||o);let s={headers:i,body:o,...r?{query:r}:{}},u=r?.tenantId||"default",c=e.withTenant?e.withTenant(u):e,d=nn;for(let l of d){let p=c[l];if(!p||!p.webhooks||p.pluginWebhookMatcher&&!p.pluginWebhookMatcher(s))continue;let f=Ir(p.webhooks,s);if(!f)continue;let g=f.path.join("."),y={payload:o,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let h=await f.webhook.handler(y),m=!!Object.keys(h.returnToSender||{})?.length;return{plugin:l,action:g,body:o,response:m?{...h?.returnToSender,success:!0}:{success:!0},...h.responseHeaders&&{responseHeaders:h.responseHeaders}}}catch(h){return console.error(`Error executing webhook handler for ${l}.${g}:`,h),{plugin:l,action:g,body:o,response:{success:!1,error:h instanceof Error?h.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{randomBytes as xi}from"crypto";import{createHmac as Pi,randomBytes as vi,timingSafeEqual as Ai}from"crypto";function re(){return vi(16).toString("base64url")}function Ge(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Pi("sha256",t).update(e).digest("base64url")}function Y(e,n){let t=n.trim();if(!t)return null;let r=e.split(".");if(r.length!==2)return null;let[i,o]=r;if(!i||!o)return null;let a=Ge(i,t);try{if(!Ai(Buffer.from(o,"utf8"),Buffer.from(a,"utf8")))return null}catch{return null}let s;try{s=JSON.parse(Buffer.from(i,"base64url").toString("utf8"))}catch{return null}return s.exp*1e3<Date.now()?null:s}function Pn(e,n,t){let r=Math.floor(Date.now()/1e3),i={...e,iat:r,exp:t},o=Buffer.from(JSON.stringify(i)).toString("base64url"),a=Ge(o,n);return`${o}.${a}`}function Je(e,n,t){let r=Math.floor(Date.now()/1e3);return Pn(e,n,r+Math.floor(t/1e3))}function ke(e){return decodeURIComponent(e)}function at(e){return encodeURIComponent(e)}function Er(e){let n=e.trim();return n.length>0?n:null}function vn(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function An(e,n){if(!Er(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??xi(16).toString("base64url"),iat:t,exp:t+Math.floor(6e4/1e3)},i=Buffer.from(JSON.stringify(r)).toString("base64url"),o=Ge(i,n);return`${i}.${o}`}function pe(e,n){return Er(n)?Y(e,n):null}function be(e){return e.deliveryMode==="connect.status"}function Ce(e){return e.deliveryMode==="auth.credentials"}function ze(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function Ve(e){return e.deliveryMode==="oauth.tokens"}function xn(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!be(e)&&!Ce(e)&&!ze(e)&&!Ve(e)}function ut(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 Si(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 wn({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Ri(e,n,t){let r=await Si(e,n,t),i={...t.query??{},...r?{tenantId:r}:{}},o=await _r(e,t.headers,t.body,i);if(!o.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(o.response&&o.response.success===!1)return{status:"failed",retryable:!1,error:typeof o.response.error=="string"?o.response.error:"Webhook handler failed"};let a=o.response?.returnToSender,s=a&&typeof a=="object"&&typeof a.validationToken=="string"&&Object.keys(a).length===1?a.validationToken:a||(o.response?.data??o.response);return{status:"ok",webhookResponse:{status:o.response?.statusCode??200,body:s,headers:o.responseHeaders}}}async function Ii(e,n){return await Ye(e,n),{status:"ok"}}async function _i(e,n){return await Oe(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function lt(e,n,t){let r=await ct(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function ct(e,n,t){let r=P(e),i=n.token?.trim();if(!i)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let o=new Date().toISOString(),a=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",i).executeTakeFirst();return a?a.status!=="pending"?{status:"ok"}:a.expires_at<o?(await r.database.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",a.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","=",a.id).execute(),{status:"ok"}):{status:"failed",retryable:!1,error:"Permission not found"}}async function Ei(e,n){try{return await mn(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function Di(e,n){let t=n.tenantId?.trim()||"default";try{return{status:"ok",webhookResponse:{status:200,body:await Ee(e,t,{pluginIds:n.plugins})}}}catch(r){return{status:"failed",retryable:!1,error:r instanceof Error?r.message:"Connect status introspection failed"}}}async function dt(e,n,t={}){let r=P(e),i=ut(n.headers,"x-corsair-signature"),o=ut(n.headers,"x-corsair-timestamp"),a=ut(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let u=Me({body:n.body,signatureHeader:i,timestampHeader:o,signingSecret:t.signingSecret});if(!u.ok)return{status:"failed",retryable:!1,error:u.error};if(!a?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let c=bn(`nonce:${a.trim()}`,3e5);if(!c.ok)return{status:"failed",retryable:!1,error:c.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let s;try{s=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}switch(s.type){case"webhook":return Ri(e,r,s.payload);case"oauth.callback":return Ii(e,s.payload);case"oauth.tokens":return _i(e,s.payload);case"permission.approve":return ct(e,s.payload,"approved");case"permission.deny":return ct(e,s.payload,"denied");case"auth.credentials":return Ei(e,s.payload);case"connect.status":return Di(e,s.payload);default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${s.type}`}}}var Oi="corsair:client-bridge";function Dr(e){let n=JSON.stringify({type:Oi,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(e.hubOrigin);return`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><script>
6
- (function () {
7
- var message = ${n};
8
- var targetOrigin = ${t};
9
- if (window.parent && window.parent !== window) {
10
- window.parent.postMessage(message, targetOrigin);
11
- }
12
- })();
13
- </script></body></html>`}var Mi=[".corsair.dev"];function Hi(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Fi(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Hi(n)?!0:Mi.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Or(e){return!e||!Fi(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 Mr(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,i]of Object.entries(n))t.set(r,i);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function Sn(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 pt(e,n){let t=B(e),i=new URL(n).searchParams.get("d");if(!i)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let o=pe(i,t.signingSecret);if(!o)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let a=bn(`browser:${o.jti}`,6e4);if(!a.ok)return{type:"json",status:400,body:{error:a.error}};try{if(be(o)){if(!o.hubSuccessUrl)return{type:"json",status:400,body:{error:"Connect status delivery missing hubSuccessUrl"}};let s=o.tenantId?.trim()||"default",u=await Ee(e,s,{pluginIds:o.statusPlugins});return{type:"redirect",url:Sn(o.hubSuccessUrl,{status:u})}}if(Ce(o))return o.hubSuccessUrl?o.credentials?(await mn(e,{plugin:o.plugin,tenantId:o.tenantId,credentials:o.credentials}),{type:"redirect",url:Sn(o.hubSuccessUrl,{connectedPlugin:o.plugin})}):{type:"redirect",url:Sn(o.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(ze(o)){if(!o.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await lt(e,o.permissionToken,o.deliveryMode==="permission.approve"?"approved":"denied")}else if(Ve(o)){if(!o.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Oe(e,{plugin:o.plugin,tenantId:o.tenantId,accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn,scope:o.scope})}else{if(!xn(o)||!o.code||!o.state||!o.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await Ye(e,{code:o.code,state:o.state,redirectUri:o.redirectUri})}}catch(s){let u=s instanceof Error?s.message:"Hub delivery failed";return(be(o)||Ce(o))&&o.hubSuccessUrl?{type:"redirect",url:Sn(o.hubSuccessUrl,{error:u})}:(be(o)||Ce(o))&&o.hubOrigin&&o.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Dr({hubOrigin:o.hubOrigin,requestId:o.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:o.hubSuccessUrl}}async function gt(e,n){let t=B(e),r=await dt(e,n,{signingSecret:t.signingSecret});if(r.status!=="ok")return{type:"json",status:r.retryable===!1?400:502,body:{error:r.error??"Tunnel processing failed"}};let i=r.webhookResponse;if(!i)return{type:"json",status:200,body:{status:"ok"}};let o=i.status??200,a=i.headers;return i.body&&typeof i.body=="object"&&!(i.body instanceof ArrayBuffer)?{type:"json",status:o,body:i.body,headers:a}:{type:"text",status:o,body:typeof i.body=="string"?i.body:i.body?JSON.stringify(i.body):null,headers:a}}function ft(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 yt(e,n){return n.method==="GET"?pt(e,n.url):gt(e,{headers:n.headers,body:n.body??""})}async function ht(e,n){try{let t=await yt(e,n);return ft(t)}catch(t){if(t instanceof he)return Response.json({error:t.message},{status:503});throw t}}async function we(e,n){let t=n.method.toUpperCase(),r=Or(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 i=await ht(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return Mr(i,r)}var oe=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 Bi=300;async function mt(e,n){let{keys:t,hub:r,plugin:i,tenantId:o}=e,a=n?.forceRefresh??!1,[s,u,c]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!s&&!c)throw new oe(i,"managed");let d=Math.floor(Date.now()/1e3);if(!a&&s&&u&&Number(u)>d+Bi)return{accessToken:s,expiresAt:Number(u),refreshed:!1};if(!c&&s&&!a)return{accessToken:s,expiresAt:u?Number(u):d+3600,refreshed:!1};let l=await xe({hub:r,path:"/oauth/refresh",body:{plugin:i,tenantId:o},parseResponse:an}),p=l.expires_in?d+l.expires_in:u?Number(u):d+3600;return await t.set_access_token(l.access_token),await t.set_expires_at(String(p)),l.refresh_token&&await t.set_refresh_token(l.refresh_token),l.scope&&await t.set_scope(l.scope),{accessToken:l.access_token,expiresAt:p,refreshed:!0}}async function Hr(e,n){e._refreshAuth=async()=>(await mt(n,{forceRefresh:!0})).accessToken}async function Rn(e,n){return xe({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:{permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,deliveryUrl:e.deliveryUrl,expiresAt:n.expiresAt},parseResponse:sn})}function In(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}function Fr(e){return{delivery:n=>we(e,n),deliveryOptions:n=>we(e,n)}}var Br=1200*1e3;function kt(){return re()}function bt(){return Br}function Ct(e,n){return Je(e,n,Br)}function wt(e,n){return Y(e,n)}function Tt(e){return ke(e)}var Ur=600*1e3;function Pt(){return re()}function vt(){return Ur}function At(e,n){return Je(e,n,Ur)}function xt(e,n){return Y(e,n)}function St(e){return at(e)}function Rt(e){return ke(e)}function It(){return re()}function _t(e,n,t){return Pn(e,n,Math.floor(t.getTime()/1e3))}function Et(e,n){return Y(e,n)}function Dt(e){return ke(e)}function _n(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(i,o){let a=t.length>1;throw new Error(`corsair.keys.${String(o)}: Cannot access keys because ${t.join(" and ")} ${a?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
14
-
15
- To generate a KEK, run: openssl rand -base64 ${Le}`)}})}function He(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var Ui=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Nr(e,n,t,r,i){let o={pluginId:n,operation:t,input:r,originalError:e},a=Object.keys(i).find(c=>i[c]?.match(e,o));return await(i[a||"DEFAULT"]?.handler||Ui)(e,o)}import{randomBytes as $i}from"crypto";import{v4 as Li}from"uuid";var Ot="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 Ht(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function $r(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function Mt(e){return In(e)}async function Ft(e,n){if(Ht(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?$r(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await Rn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:Ni(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function Ni(e){try{return JSON.parse(e)}catch{return e}}async function En(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Ft(e,n);return{...n,approvalUrl:r}}async function Bt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:i,permissionToken:o,plugin:a,endpoint:s,args:u,tenantId:c,expiresAt:d,operationPath:l}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:o,id:i,plugin:a,endpoint:s,args:u});let f=await Ft({manual:t,hub:r},{id:i,token:o,plugin:a,endpoint:s,args:JSON.stringify(u),tenant_id:c,expires_at:d});return Ht(t)?f?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:f}):Mt(f):Ot:r?f?Mt(f):`Action '${l}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Ot}var Wi={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 ji(e,n,t){return t!==void 0?t:Wi[n][e]}function Ut(e){let n=/(\d+)(d|h|m|s)/g,t=0,r;for(;(r=n.exec(e))!==null;){let i=parseInt(r[1],10);switch(r[2]){case"d":t+=i*864e5;break;case"h":t+=i*36e5;break;case"m":t+=i*6e4;break;case"s":t+=i*1e3;break}}return t>0?t:600*1e3}function Wr(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 Lr(e,n,t){let r=Date.now()+t;for(;Date.now()<r;){let i=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).executeTakeFirst();if(!i)return{result:"blocked",reason:"pending"};if(i.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(i.status==="denied")return{result:"blocked",reason:"denied"};if(i.status==="expired"||i.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(o=>setTimeout(o,500))}return{result:"blocked",reason:"timeout"}}async function jr(e){let n=ji(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}'.`,`
16
- Action: ${r}`,`
17
- To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let i=JSON.stringify(e.args),o=new Date().toISOString(),a=e.tenantId??"default",s=await e.db.db.selectFrom("corsair_permissions").selectAll().where("plugin","=",e.pluginId).where("endpoint","=",e.endpointPath).where("args","=",i).where("tenant_id","=",a).where("expires_at",">",o).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(s){if(s.status==="approved"){let g=e.db,y=s.id;return{result:"allow",onComplete:async()=>{await g.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",y).execute()}}}return s.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
18
- Action: ${r}`,`
19
- Permission ID: ${s.id}`,`
20
- Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Lr(e.db,s.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:s.id,token:s.token,expiresAt:s.expires_at})}let u=Li(),c=$i(32).toString("hex"),d=e.timeoutMs??600*1e3,l=new Date(Date.now()+d).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:u,created_at:new Date,updated_at:new Date,token:c,plugin:e.pluginId,endpoint:e.endpointPath,args:i,tenant_id:a,status:"pending",expires_at:l}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
21
- Action: ${r}`,`
22
- Permission ID: ${u}`,`
23
- Permission token: ${c}`,`
24
- Expires at: ${l}`,`
25
- Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Lr(e.db,u,d):{result:"blocked",reason:"pending",id:u,token:c,expiresAt:l}}function Ki(e){return typeof e=="function"}function Zi(e,n,t){let r=ce(z(e,n.tenantId??t??"default"),n.kek),i=new URL(n.baseUrl);i.searchParams.set("state",r);let o=i.toString(),a=n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:o,state:r}):`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${o}`;return new Error(a)}function Nt({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:i,errorHandlers:o,currentPath:a=[],keyBuilder:s,permissionsConfig:u,endpointMeta:c,database:d,permissionsOptions:l,tenantId:p,manualConfig:f,hubConfig:g}){for(let[y,h]of Object.entries(e)){let m=n?.[y];if(Ki(h)){let C=m,b=[...a,y].join("."),k=async(w={})=>{let T;if(u){let _=c?.[b],{result:Ae,reason:q,onComplete:Ne,token:X,id:ye,expiresAt:N}=await jr({pluginId:i,endpointPath:b,args:w,mode:u.mode,override:u.overrides?.[b],riskLevel:_?.riskLevel??"write",meta:_,db:d,timeoutMs:l?Ut(l.timeout):void 0,tenantId:p,approvalMode:l?.mode});if(Ae==="blocked"){let G;throw q==="denied"?G=`Action '${b}' was denied by the user. Await further instructions before proceeding.`:q==="policy"?G=`Action '${b}' is blocked by the permission policy. Update the corsair config to allow it.`:q==="timeout"?G=`Action '${b}' timed out waiting for approval.`:X&&ye?G=await Bt({permissionsOptions:l,manual:f,hub:g,permissionId:ye,permissionToken:X,plugin:i,endpoint:b,args:w,tenantId:p??"default",expiresAt:N??new Date(Date.now()+(l?Ut(l.timeout):600*1e3)).toISOString(),operationPath:b}):G=`Action '${b}' requires user approval before it can run.`,new Error(G)}T=Ne}let D=async(_,Ae,q)=>{try{return await h(Ae,q)}catch(Ne){if(Ne instanceof Error){let X=await Nr(Ne,i,b,typeof q=="object"&&q!==null?q:{args:q},o);if(_<(X.maxRetries||0)){let ye=_+1;console.log(`Retrying (${ye} / ${X.maxRetries})...`);let N;if(X.headersRetryAfterMs)N=X.headersRetryAfterMs;else switch(X.retryStrategy){case"exponential_backoff":N=Math.pow(2,ye-1)*1e3;break;case"exponential_backoff_jitter":let G=Math.pow(2,ye-1)*1e3,Po=(Math.random()-.5)*1e3;N=Math.max(0,G+Po);break;case"linear_1s":N=1e3;break;case"linear_2s":N=2e3;break;case"linear_3s":N=3e3;break;case"linear_4s":N=4e3;break;default:N=1e3;break}await new Promise(G=>setTimeout(G,N)),await D(ye,Ae,q),console.log(`[corsair:${i}:${b}] Retry strategy:`,X)}}throw Ne}},O;try{O=s?await s(t,"endpoint"):void 0}catch(_){throw f&&He(f)&&f.oauthConfig&&f.kek&&_ instanceof oe&&_.authType==="oauth_2"?Zi(i,f,p):_}if(!C?.before&&!C?.after){let _=await D(0,{...t,key:O},w);return await T?.(),_}let M={...t,key:O},A=C.before?await C.before(M,w):{ctx:M,args:w,continue:!0,passToAfter:void 0};if(A.continue===!1)return;let ve=await D(0,A.ctx,A.args);return await C.after?.(A.ctx,ve,A.passToAfter),await T?.(),ve};r[y]=k}else if(h&&typeof h=="object"){let C={};Nt({endpoints:h,hooks:m,ctx:t,tree:C,pluginId:i,errorHandlers:o,currentPath:[...a,y],keyBuilder:s,permissionsConfig:u,endpointMeta:c,database:d,permissionsOptions:l,tenantId:p,manualConfig:f,hubConfig:g}),r[y]=C}}}function qi(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function $t({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:i}){for(let[o,a]of Object.entries(e)){let s=n?.[o];if(qi(a)){let u=s,c=async d=>{let l=(f,g)=>a.handler(f,g),p=i?await i(t,"webhook"):void 0;return!u?.before&&!u?.after?l({...t,key:p},d):(async()=>{let f={...t,key:p},g=u.before?await u.before(f,d):{ctx:f,args:d,continue:!0,passToAfter:void 0};if(g.continue===!1)return;let y=await l(g.ctx,g.args);return y?.success===!0&&await u.after?.(g.ctx,y,g.passToAfter),y})()};r[o]={match:a.match,handler:c}}else if(a&&typeof a=="object"){let u={};$t({webhooks:a,hooks:s,ctx:t,webhooksTree:u,keyBuilder:i}),r[o]=u}}}function Gi(e,n,t){let r=null;return async()=>{if(r)return r;if(!e)throw new Error("Database not configured");let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!i)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);let o=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",i.id).executeTakeFirst();if(!o)throw new Error(`Account not found for tenant "${t}" and integration "${n}". Make sure to create the account first.`);return r=o.id,r}}function Ji(e,n,t,r,i){return e?qn(e.db,n,t,r,i):{findByEntityId: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 Lt(e,n){let{database:t,tenantId:r,kek:i,rootErrorHandlers:o,permissionsOptions:a,manualConfig:s,hubConfig:u}=n,c={},d={};for(let l of e)c[l.id]={},d[l.id]={};for(let l of e){let p=l.schema,f=r??"default",g=Gi(t,l.id,f);if(p?.entities){let A={};for(let[ve,_]of Object.entries(p.entities)){let Ae=t?qn(t.db,g,ve,p.version,_):Ji(void 0,g,ve,p.version,_);A[ve]=Ae}d[l.id].db=A,c[l.id].db=A}let y=l.options,h=l.authConfig,m;if(t&&i&&y?.authType){let A=h?.[y.authType]?.account??[];m=S({authType:y.authType,integrationName:l.id,tenantId:f,kek:i,database:t,extraAccountFields:A}),c[l.id].keys=m}let C={database:t,db:d[l.id]?.db??{},$getAccountId:g,...l.options?{options:l.options}:{},...m?{keys:m,authType:y?.authType}:{},tenantId:f,...u?{hub:u}:{}},b=l.endpoints??{},k=l.hooks,w={...o,...l.errorHandlers},T={},D=l.options?.permissions;Nt({endpoints:b,hooks:k,ctx:C,tree:T,pluginId:l.id,errorHandlers:w,currentPath:[],keyBuilder:l.keyBuilder,permissionsConfig:D,endpointMeta:l.endpointMeta,database:t,permissionsOptions:a,tenantId:r,manualConfig:s?{...s,oauthConfig:l.oauthConfig,kek:i,tenantId:f}:void 0,hubConfig:u}),Object.keys(T).length>0&&(c[l.id].api=T),C.endpoints=T;let O=l.webhooks??{},M=l.webhookHooks;if(Object.keys(O).length>0){let A={};$t({webhooks:O,hooks:M,ctx:C,webhooksTree:A,keyBuilder:l.keyBuilder}),c[l.id].webhooks=A,l.pluginWebhookMatcher&&(c[l.id].pluginWebhookMatcher=l.pluginWebhookMatcher),l.pluginTenantWebhookMatcher&&(c[l.id].pluginTenantWebhookMatcher=l.pluginTenantWebhookMatcher)}}return c}function Kr(e,n,t){let r={};for(let i of e){let o=i.options,a=i.authConfig;if(o?.authType){let s=a?.[o.authType]?.integration??[],u=I({authType:o.authType,integrationName:i.id,kek:t,database:n,extraIntegrationFields:s});r[i.id]=u}}return r}var zi="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function Zr(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] ${zi}`),t):n}import*as qr from"querystring";function Fe(e){let{oauthConfig:n,clientId:t,redirectUri:r,state:i}=e,o={...n.authParams,client_id:t,redirect_uri:r,response_type:"code",scope:n.scopes.join(" "),state:i};return`${n.authUrl}?${qr.stringify(o)}`}var W=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Vi(e){let n=e.oauthConfig;if(!n)throw new W("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Wt(e,n){let t=P(e,()=>new W("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new W("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new W("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let i=fn(n,t.kek);if(!i)throw new W("invalid_state","Invalid or tampered state parameter");let{plugin:o,tenantId:a}=i,s=$(t,o,p=>new W("plugin_not_found",p)),u=Vi(s),d=await I({authType:"oauth_2",integrationName:o,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new W("client_id_not_configured",`client_id not configured for '${o}'`);let l=Fe({oauthConfig:u,clientId:d,redirectUri:r,state:n});return{plugin:o,tenantId:a,providerName:u.providerName,oauthUrl:l,state:n}}var v=class extends Error{status;code;extra;constructor(n,t,r,i={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=i}};function x(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function Gr(e){let n={error:e.code,message:e.message,...e.extra};return x(e.status,n)}function ge(e){return new v(404,"not_found",e)}function Q(e,n={}){return new v(400,"bad_request",e,n)}function Jr(e,n){return $(e,n,t=>ge(t))}async function zr(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=I({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),i=E[t].integration,o=r,a;try{a=await Promise.all(i.map(c=>o[`get_${c}`]()))}catch{a=i.map(()=>null)}let s=i.filter((c,d)=>a[d]==null),u;return t==="oauth_2"?u=!s.includes("client_id")&&!s.includes("client_secret"):u=s.length===0,{configured:u,missingFields:s}}async function Vr(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:i,missingFields:o}=await zr(e,n);return{id:e.id,authType:t,configured:i,missingFields:o,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function Dn(){return{ok:!0}}async function On(e){return Promise.all(e.plugins.map(n=>Vr(n,e)))}async function Mn(e,n){let t=Jr(e,n);return Vr(t,e)}async function Yi(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 Yr(e,n){let t=await Yi(e,n),r=t.filter(i=>i.hasCredentials).map(i=>i.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Hn(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 i=r.tenant_id;if(!i)continue;let o=n.get(i);o||(o={id:i,accounts:[],connectedPlugins:[]},n.set(i,o));let a=!!r.dek;o.accounts.push({integrationName:r.integrationName,hasCredentials:a}),a&&o.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function Fn(e,n){if(!n)throw Q("Tenant id must be a non-empty string");return Yr(e,n)}async function Bn(e,n){let t=n?.id?.trim();if(!t)throw Q("Tenant id is required",{missingFields:["id"]});return Yr(e,t)}async function Un(e,n){let t=n?.trim()||"default",r={},i=await Ke(e,t);for(let o of i)r[o.plugin]=gn(o);for(let o of e.plugins)o.id in r||(!o.options?.authType||!e.database||!e.kek?r[o.id]="missing_credentials":r[o.id]="not_connected");return r}async function jt(e,n){if(!e.database)throw ge(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw ge(`Permission '${n}' not found`);return En(e,t)}function Qi(e){if(!e.oauthConfig)throw Q(`Plugin '${e.id}' has no oauthConfig`)}function Xi(e){if(!e.manual)throw new v(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Kt(e){let n=Xi(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new v(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 es(e){let n=!!e.hub,t=He(e.manual);if(!n&&!t)throw new v(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function Qr(e){if(!e.database||!e.kek)throw new v(500,"database_not_configured","A database and kek are required to issue connect links.")}async function ns(e,n){let t=n?.plugin?.trim();if(!t)throw Q("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",i=Jr(e,t);Qi(i);let o=Kt(e);Qr(e);let a=await zr(i,e);if(!a.configured)throw new v(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:a.missingFields});let s=ce(z(t,r),e.kek),u;try{u=new URL(o.baseUrl)}catch{throw new v(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",s),{connectUrl:u.toString(),expiresAt:new Date(Date.now()+Vn).toISOString()}}async function ts(e,n,t){Qr(n);let r=t.tenantId?.trim()||"default",i=B(e);if(t.source){let c=Ie({source:t.source,deliveryUrl:i.deliveryUrl,oauthMode:t.oauthMode});if(c)throw Q(c.error)}let o={tenantId:r,source:t.source??Re(i.deliveryUrl),oauthMode:t.oauthMode},a=t.plugin?.trim();a&&(o.plugin=a);let s=t.providerName?.trim();s&&(o.providerName=s);let u=await hn(e,o);return{connectUrl:u.connectUrl,expiresAt:u.expiresAt}}async function Nn(e,n,t){return es(n),n.hub?ts(e,n,t):ns(n,t)}async function $n(e,n,t){if(n.hub&&!He(n.manual))throw new v(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw Q("state is required",{missingFields:["state"]});Kt(n);try{return await Wt(e,r)}catch(i){if(i instanceof W)switch(i.code){case"invalid_state":throw Q("Invalid or expired state");case"client_id_not_configured":throw new v(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new v(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function Ln(e,n,t){if(n.hub&&!He(n.manual))throw new v(400,"hub_mode","oauthCallback is not used with hub config. Hub delivers tokens to your deliveryUrl.");let r=t?.code?.trim(),i=t?.state?.trim(),o=[];if(r||o.push("code"),i||o.push("state"),o.length)throw Q("Missing required fields",{missingFields:o});let a=Kt(n),{processOAuthCallback:s}=await import("./oauth.js");try{return await s(e,{code:r,state:i,redirectUri:a.redirectUri})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw Q("Invalid or expired state");case"credentials_not_configured":throw new v(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new v(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function Zt(e,n){if(!e.database)throw ge("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw ge("Permission not found");return En(e,t)}async function Xr(e,n){return"id"in n?jt(e,n.id):Zt(e,n.token)}var eo=[{method:"GET",pattern:"/ok",handler:async()=>x(200,Dn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>x(200,await Hn(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>x(201,await Bn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>x(200,await Fn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>x(200,await On(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>x(200,await Mn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>x(200,await Un(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>x(200,await jt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?x(200,await Zt(e,t)):x(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>x(200,await Nn(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>x(200,await $n(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>x(200,await Ln(e,n,t))}];(()=>{let e=new Set;for(let n of eo){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function rs(e,n){let t=e.split("/").filter(Boolean),r=n.split("/").filter(Boolean);if(t.length!==r.length)return null;let i={};for(let o=0;o<t.length;o++){let a=t[o],s=r[o];if(a.startsWith(":"))i[a.slice(1)]=decodeURIComponent(s);else if(a!==s)return null}return i}function os(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 is(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 v(400,"invalid_json","Request body is not valid JSON")}}var ss="/api/corsair";function Te(e,n={}){let t=n.basePath??ss,r=P(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async i=>{try{let o=new URL(i.url),a=os(o.pathname,t),s=i.method.toUpperCase();if(s==="OPTIONS"||a==="/"||a==="")return await we(e,i);if(s!=="GET"&&s!=="POST")return x(405,{error:"method_not_allowed",message:`Method ${s} not allowed`});let u=Object.fromEntries(o.searchParams);for(let c of eo){if(c.method!==s)continue;let d=rs(c.pattern,a);if(!d)continue;let l=await is(i);return await c.handler({corsair:e,internal:r,req:i,params:d,query:u,body:l})}throw ge(`No route for ${s} ${a}`)}catch(o){if(n.onError){let s=await n.onError(o,i);if(s)return s}if(o instanceof v)return Gr(o);let a=o instanceof Error?o.message:"Internal server error";return x(500,{error:"internal_error",message:a})}}}function as(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,i=`${t}://${n}${r}`,o=new Headers;for(let[u,c]of Object.entries(e.headers))if(c!=null)if(Array.isArray(c))for(let d of c)o.append(u,d);else o.set(u,c);let a=e.method!=="GET"&&e.method!=="HEAD",s={method:e.method,headers:o};return a&&e.body!==void 0&&(s.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),o.has("content-type")||o.set("content-type","application/json")),new Request(i,s)}async function us(e,n){e.status(n.status),n.headers.forEach((r,i)=>e.setHeader(i,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function no(e,n){let t=Te(e,n);return async(r,i,o)=>{try{let a=await t(as(r));await us(i,a)}catch(a){o(a)}}}function to(e,n){let t=Te(e,n);return r=>t(r.req.raw)}function ro(e,n){let t=Te(e,n);return{GET:t,POST:t,OPTIONS:t}}function oo(e){let n={[Qe]:e};return{ok:Dn,tenants:{list:()=>Hn(e),create:t=>Bn(e,t),get:t=>Fn(e,t)},plugins:{list:()=>On(e),get:t=>Mn(e,t)},connectionStatus:{get:t=>Un(e,t?.tenantId)},permissions:{get:t=>Xr(e,t)},connect:{createLink:t=>Nn(n,e,t),resolve:t=>$n(n,e,t),oauthCallback:t=>Ln(n,e,t)}}}async function io(e,n,t,r,i="pending"){if(!e)return null;try{let o=rr(),a=new Date;return await e.db.insertInto("corsair_events").values({id:o,created_at:a,updated_at:a,account_id:n,event_type:t,payload:r,status:i}).execute(),o}catch(o){return console.warn("Failed to log event:",o),null}}async function cs(e,n,t,r="pending"){try{let i=await e.$getAccountId();return io(e.database,i,n,t,r)}catch(i){return console.warn("Failed to log event:",i),null}}import*as so from"https";import*as ao from"querystring";function Wn(e,n,t,r,i){let o=new URL(r.tokenUrl),a=r.tokenAuthMethod==="basic";return new Promise((s,u)=>{let c={code:e.trim(),redirect_uri:i,grant_type:"authorization_code"};a||(c.client_id=n,c.client_secret=t);let d=ao.stringify(c),l={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(d).toString()};a&&(l.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let p=so.request({hostname:o.hostname,...o.port?{port:Number(o.port)}:{},path:o.pathname+o.search,method:"POST",headers:l},f=>{let g="";f.on("data",y=>{g+=y}),f.on("end",()=>{if(f.statusCode!==200){u(new Error(`Token exchange failed (${f.statusCode}): ${g}`));return}try{s(JSON.parse(g))}catch{u(new Error(`Token endpoint returned non-JSON response: ${g}`))}})});p.on("error",f=>u(new Error(`Request failed: ${f.message}`))),p.write(d),p.end()})}var uo=" ";function K(e){let n=e;return n._def??n.def??{}}function Z(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 j(e){return e.innerType??e.schema??e.out??e.in}function lo(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 j(e)}}function po(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Kn(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Be(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 go(e,n){return e.description??n.description}function ls(e){let n=e;for(;n;){let t=K(n),r=go(n,t);if(r)return r;let i=Z(t);if(Vt(i)||i==="ZodPipe"||i==="ZodEffects"||i==="ZodTransform"){n=lo(t,i);continue}break}}function Vt(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function F(e){let n=K(e),t=Z(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??Be(n)[0]??"unknown");case"ZodEnum":return Be(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=j(n);return r?F(r):"unknown"}case"ZodNullable":{let r=j(n);return`${r?F(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=j(n);return r?F(r):"unknown"}case"ZodArray":{let r=po(n);if(!r)return"unknown[]";let i=K(r),o=Z(i)==="ZodUnion",a=F(r);return`${o?`(${a})`:a}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Kn(e,n),i=Object.entries(r);return i.length===0?"{}":`{ ${i.map(([a,s])=>{let u=Z(K(s));return`${u==="ZodOptional"||u==="ZodNullable"?a+"?":a}: ${F(s)}`}).join(", ")} }`}case"ZodUnion":return Be(n).map(r=>F(r)).join(" | ");case"ZodIntersection":return`${F(n.left)} & ${F(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=lo(n,t);return r?F(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ie(e){let n=K(e),t=Z(n),r=go(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 i=n.value??Be(n)[0],o=typeof i=="string"||typeof i=="number"||typeof i=="boolean"?i:String(i??"");return{kind:"literal",optional:!1,description:r,value:o}}case"ZodEnum":{let i=Be(n).map(o=>String(o));return{kind:"string",optional:!1,description:r,enum:i}}case"ZodOptional":{let i=j(n),o=i?ie(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodNullable":{let i=j(n),o=i?ie(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodDefault":case"ZodCatch":{let i=j(n);return i?{...ie(i),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let i=po(n);return{kind:"array",optional:!1,description:r,items:i?ie(i):{kind:"unknown",optional:!1}}}case"ZodObject":{let i=Kn(e,n),o={};for(let[a,s]of Object.entries(i))o[a]=ie(s);return{kind:"object",optional:!1,description:r,fields:o}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let i=Be(n);for(let o of i){let a=K(o);if(Z(a)==="ZodObject")return{...ie(o),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let i=j(n);return i?{...ie(i),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Ul(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let i=t.slice(0,r),o=t.slice(r+1),a=e.find(d=>d.id===i);if(!a)return null;let s=o;s.startsWith("api.")&&(s=s.slice(4));let u=fe(a.endpointMeta,s),c=fe(a.endpointSchemas,s);return!u&&!c?null:{input:c?.input?ie(c.input):null,output:c?.output?ie(c.output):null,description:u?.description}}var Yt=["equals","contains","startsWith","endsWith","in"],ds=["equals","gt","gte","lt","lte","in"],ps=["equals"],gs=["equals","before","after","between"];function fo(e){let n=K(e);switch(Z(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=j(n);return r?fo(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Qt(e){let n=K(e),t=Z(n);if(Vt(t)){let o=j(n);return o?Qt(o):{}}if(t!=="ZodObject")return{};let r=Kn(e,n),i={};for(let[o,a]of Object.entries(r)){let s=fo(a);s==="string"?i[o]={type:"string",operators:Yt}:s==="number"?i[o]={type:"number",operators:ds}:s==="boolean"?i[o]={type:"boolean",operators:ps}:s==="date"&&(i[o]={type:"date",operators:gs})}return i}function yo(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Gt(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];typeof i=="function"?t.push(o.join(".")):i!==null&&typeof i=="object"&&Gt(i,o,t)}}function Jt(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function zt(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];Jt(i)?t.push(o.join(".")):i!==null&&typeof i=="object"&&zt(i,o,t)}}function Xt(e,n){if(n.length===0)return null;let[t,...r]=n,i=Object.entries(e).find(([s])=>s.toLowerCase()===t);if(!i)return null;let[o,a]=i;if(r.length===0)return Jt(a)?[o]:null;if(a!==null&&typeof a=="object"&&!Jt(a)){let s=Xt(a,r);if(s!==null)return[o,...s]}return null}function ho(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let o=0;o<n.length;o++){let a=" ".repeat(o+2);t.push(`${a}${n[o]}: {`)}let r=" ".repeat(n.length+2),i=r+" ";t.push(`${r}before(ctx, args) {`),t.push(`${i}return { ctx, args };`),t.push(`${r}},`),t.push(`${r}after(ctx, response) {`),t.push(`${r}},`);for(let o=n.length-1;o>=0;o--){let a=" ".repeat(o+2);t.push(`${a}},`)}return t.push(" },"),t.push("})"),t.join(`
26
- `)}var fs=new Set(nn);function Pe(e,n){let t=n?.type??"api",r=n?.plugin;if(r!==void 0){let o=e.find(s=>s.id===r);if(!o)return fs.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:Pe(e);if(t==="webhooks"){if(!o.webhooks)return[];let s=[];return zt(o.webhooks,[],s),s.map(u=>`${o.id}.webhooks.${u}`)}if(t==="db"){let s=o.schema?.entities;return s?Object.keys(s).map(u=>`${o.id}.db.${u}.search`):[]}if(!o.endpoints)return[];let a=[];return Gt(o.endpoints,[],a),a.map(s=>`${o.id}.api.${s}`)}let i={};if(t==="webhooks")for(let o of e){if(!o.webhooks)continue;let a=[];zt(o.webhooks,[],a),i[o.id]=a.map(s=>`${o.id}.webhooks.${s}`)}else if(t==="db")for(let o of e){let a=o.schema?.entities;a&&(i[o.id]=Object.keys(a).map(s=>`${o.id}.db.${s}.search`))}else for(let o of e){if(!o.endpoints)continue;let a=[];Gt(o.endpoints,[],a),i[o.id]=a.map(s=>`${o.id}.api.${s}`)}return i}function fe(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function ys(e,n){let t=e.toLowerCase(),r=n.toLowerCase();if(!t.startsWith(`${r}.`)){let o=t.slice(n.length+1),a=o.startsWith(".")?o.slice(1):o;return a.startsWith("api.")&&(a=a.slice(4)),{shortPath:a,lookupKey:a}}let i=e.slice(n.length+1);return i.toLowerCase().startsWith("api.")&&(i=i.slice(4)),{shortPath:i,lookupKey:i.toLowerCase()}}function qt(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
27
- ${e.join(", ")}`:`${n}:
28
- `+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
29
- `)}function Nl(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let i=t.slice(0,r),o=t.slice(r+1),a=e.find(s=>s.id===i);if(a){if(o.startsWith("db.")){let d=o.slice(3),l=d.lastIndexOf(".");if(l!==-1){let p=d.slice(0,l),f=d.slice(l+1),g=a.schema?.entities;if(f==="search"&&g){let y=yo(g,p);if(y){let[h,m]=y,C=Qt(m),b=[`Search ${i} ${h} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${Yt.join(", ")}]`];for(let[k,w]of Object.entries(C))b.push(` ${k}?: ${w.type} [${w.operators.join(", ")}]`);return b.push("}"),b.join(`
30
- `)}}}return qt(Pe(e,{type:"db"}),"Path not found. Available db operations")}if(o.startsWith("webhooks.")){let d=o.slice(9);if(a.webhooks){let l=Xt(a.webhooks,d.split("."));if(l!==null){let p=l.join("."),f=fe(a.webhookSchemas,p.toLowerCase()),g=f?.response?F(f.response):null,y=[];return f?.description&&y.push(f.description),f?.payload&&y.push(`payload ${jn(Ue(f.payload))}`),g&&y.push(`response: ${g}`),y.push(`usage:
31
- ${ho(i,l)}`),y.join(`
32
-
33
- `)}}return qt(Pe(e,{type:"webhooks"}),"Path not found. Available webhooks")}let s=o;s.startsWith("api.")&&(s=s.slice(4));let u=fe(a.endpointMeta,s),c=fe(a.endpointSchemas,s);if(u||c){let d=[],l=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),p=[u?.description,l].filter(Boolean).join(" ");return p&&d.push(p),c?.input&&d.push(`input ${jn(Ue(c.input))}`),c?.output&&d.push(`output ${jn(Ue(c.output))}`),d.join(`
34
-
35
- `)}}}return qt(Pe(e),"Path not found. Available operations")}function co(e){let n=e;for(;;){let t=K(n),r=Z(t);if(Vt(r)){let i=j(t);if(!i)return n;n=i;continue}return n}}function Ue(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=co(e),t=K(n);if(Z(t)==="ZodObject"){let i=Kn(n,t),o=[];for(let[a,s]of Object.entries(i)){let u=K(s),c=Z(u),d=c==="ZodOptional"||c==="ZodNullable",l=co(s),p=ls(s);o.push({key:a,optional:d,type:F(l),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:o}}return{kind:"inline",type:F(n)}}function jn(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=uo.repeat(n+1),r=uo.repeat(n);return`{
36
- ${e.fields.map(o=>{let a=o.optional?`${o.key}?`:o.key,s=o.description?` // ${o.description}`:"";return`${t}${a}: ${o.type}${s}`}).join(`
37
- `)}
38
- ${r}}`}return"unknown"}function hs(e,n){let t=Pe(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(d=>d.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let i=[];for(let d of t){let{shortPath:l,lookupKey:p}=ys(d,n),f=fe(r.endpointMeta,p),g=fe(r.endpointSchemas,p);!f&&!g||i.push({path:d,shortPath:l,description:f?.description,riskLevel:f?.riskLevel,irreversible:f?.irreversible,input:Ue(g?.input),output:Ue(g?.output)})}i.sort((d,l)=>d.path.localeCompare(l.path));let o=[],a=Pe(e,{plugin:n,type:"webhooks"});if(Array.isArray(a)&&r.webhooks)for(let d of a){let p=d.toLowerCase().slice(n.length+1),f=p.startsWith(".")?p.slice(1):p;if(!f.startsWith("webhooks."))continue;let g=f.slice(9),y=Xt(r.webhooks,g.split("."));if(y===null)continue;let h=y.join("."),m=fe(r.webhookSchemas,h.toLowerCase()),C=m?.response?F(m.response):void 0;o.push({path:d,description:m?.description,payload:Ue(m?.payload),responseType:C,usageExample:ho(n,y)})}o.sort((d,l)=>d.path.localeCompare(l.path));let s=[],u=Pe(e,{plugin:n,type:"db"}),c=r.schema?.entities;if(Array.isArray(u)&&c)for(let d of u){let p=d.toLowerCase().slice(n.length+1),f=p.startsWith(".")?p.slice(1):p;if(!f.startsWith("db."))continue;let g=f.slice(3),y=g.lastIndexOf(".");if(y===-1)continue;let h=g.slice(0,y);if(g.slice(y+1)!=="search")continue;let C=yo(c,h);if(!C)continue;let[b,k]=C,w=Qt(k),T=Object.entries(w).map(([D,O])=>({field:D,type:O.type,operators:O.operators}));s.push({path:d,entityName:b,filters:[{field:"entity_id",type:"string",operators:Yt},...T]})}return s.sort((d,l)=>d.path.localeCompare(l.path)),{ok:!0,data:{pluginId:n,api:i,webhooks:o,db:s}}}function mo(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function ms(e,n){let t=mo(e,n);if(!t)return null;let r=e[t];if(!r?.pluginTenantWebhookMatcher)return null;let i=r.pluginTenantWebhookMatcher(n);return i?{plugin:t,tenantMatch:i}:null}function ks(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function ko(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function bo(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 Xe(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function bs(e){return Xe(e.body)}function Co(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return Zn(Array.isArray(r)?r:[r])}function wo(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let c=Zn(Array.isArray(u)?u:[u]);if(c)return decodeURIComponent(c)}let r=Co({query:e.query},"validationToken");if(r)return r;let i=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let u of i){let c=n[u],d=Array.isArray(c)?c[0]:c;if(!(!d||typeof d!="string"))try{let p=(d.startsWith("http")?new URL(d):new URL(`https://example.invalid${d.startsWith("/")?d:`/${d}`}`)).searchParams.get("validationToken");if(p?.trim())return p.trim()}catch{continue}}let o=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,a=Xe(typeof o=="string"?(()=>{try{return JSON.parse(o)}catch{return o}})():o);return Zn([a?.validationToken])??null}function Cs(e){if(wo(e))return!0;let n=Xe(e.body??e.payload);return ko(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function Zn(e){for(let n of e){let t=bo(n);if(t)return t}}function ws(e){let t=Xe(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Qe=Symbol.for("corsair:internal");function Cr(e){let n=e.database?er(e.database):void 0,t=n&&e.kek?Kr(e.plugins,n,e.kek):_n(!!n,!!e.kek),r=Zr(e),i={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?tn(e.hub):void 0},o=Wr(n),a=oo(i);if(e.multiTenancy)return Object.assign({withTenant:u=>{if(!u)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let c=Lt(e.plugins,{database:n,tenantId:u,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:i.hub});return Object.assign(c,{[Qe]:i})},keys:t,permissions:o,manage:a},{[Qe]:i});let s=Lt(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:i.hub});return Object.assign({},s,{keys:t,permissions:o,manage:a,[Qe]:i})}var U=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function To(e){let n=e.oauthConfig;if(!n)throw new U("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Ts(e,n,t,r){let i=ir(e),o=await i.integrations.findByName(n);if(!o)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:t,integration_id:o.id}))return;let s=ee(),u=await ne(s,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:u})}async function Xn(e,n,t){let{tenantId:r,redirectUri:i}=t,o=P(e,()=>new U("invalid_corsair_instance","Invalid corsair instance"));if(!o.database)throw new Error("No database configured on corsair instance");let a=$(o,n,l=>new U("plugin_not_found",l)),s=To(a),c=await I({authType:"oauth_2",integrationName:n,kek:o.kek,database:o.database}).get_client_id();if(!c)throw new Error(`client_id not configured for '${n}'`);let d=ce(z(n,r),o.kek);return{url:Fe({oauthConfig:s,clientId:c,redirectUri:i,state:d}),state:d}}async function Ye(e,n){let{code:t,state:r,redirectUri:i}=n,o=P(e,()=>new U("invalid_corsair_instance","Invalid corsair instance")),a=fn(r,o.kek);if(!a)throw new U("invalid_state","Invalid or tampered state parameter");let{plugin:s,tenantId:u}=a;if(!o.database)throw new U("no_database","No database configured on corsair instance");let c=$(o,s,h=>new U("plugin_not_found",h)),d=To(c),l=I({authType:"oauth_2",integrationName:s,kek:o.kek,database:o.database}),p=await l.get_client_id(),f=await l.get_client_secret();if(!p||!f)throw new U("credentials_not_configured",`Credentials not configured for '${s}'`);await Ts(o.database,s,u,o.kek);let g=await Wn(t,p,f,d,i);if(!g.access_token)throw new U("no_access_token",`No access_token returned from ${d.providerName}`);let y=S({authType:"oauth_2",integrationName:s,tenantId:u,kek:o.kek,database:o.database});await y.set_access_token(g.access_token),g.refresh_token&&await y.set_refresh_token(g.refresh_token),g.expires_in&&await y.set_expires_at(String(Math.floor(Date.now()/1e3)+g.expires_in));try{let h=await Cn(o.plugins,s,g);if(h)try{let m=c.authConfig?.oauth_2?.account??[];await De({database:o.database,kek:o.kek,pluginId:s,tenantId:u,link:h,authType:"oauth_2",extraAccountFields:m})}catch(m){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${u}':`,m)}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${u}':`,h)}return{plugin:s,tenantId:u}}export{sr as a,ae as b,$e as c,he as d,tn as e,B as f,rn as g,on as h,sn as i,an as j,ar as k,un as l,ee as m,ne as n,L as o,Gn as p,We as q,ue as r,te as s,je as t,I as u,S as v,gr as w,fr as x,z as y,zn as z,De as A,et as B,wn as C,xr as D,Fe as E,U as F,Xn as G,Ye as H,qe as I,Re as J,hr as K,Ie as L,kr as M,ui as N,hn as O,Ee as P,le as Q,me as R,de as S,Oe as T,Tn as U,tt as V,Me as W,rt as X,ot as Y,it as Z,st as _,_r as $,re as aa,vn as ba,An as ca,pe as da,be as ea,Ce as fa,ze as ga,Ve as ha,xn as ia,lt as ja,dt as ka,pt as la,gt as ma,ft as na,yt as oa,ht as pa,we as qa,oe as ra,mt as sa,Hr as ta,Rn as ua,In as va,Fr as wa,kt as xa,bt as ya,Ct as za,wt as Aa,Tt as Ba,Pt as Ca,vt as Da,At as Ea,xt as Fa,St as Ga,Rt as Ha,It as Ia,_t as Ja,Et as Ka,Dt as La,Wt as Ma,Te as Na,no as Oa,to as Pa,ro as Qa,io as Ra,cs as Sa,Wn as Ta,Ul as Ua,Pe as Va,Nl as Wa,jn as Xa,hs as Ya,mo as Za,ms as _a,ks as $a,ko as ab,bo as bb,Xe as cb,bs as db,Co as eb,wo as fb,Cs as gb,Zn as hb,ws as ib,Qe as jb,Cr as kb};
@@ -1 +0,0 @@
1
- import{b as F,c as D,d as P,e as B}from"./chunk-IGGCNGU2.js";var R={oauth_2:{integration:["client_id","client_secret","redirect_url"],account:["access_token","refresh_token","expires_at","scope","webhook_signature"]},api_key:{integration:[],account:["api_key","webhook_signature"]},bot_token:{integration:[],account:["bot_token","webhook_signature"]},managed:{integration:[],account:["access_token","refresh_token","expires_at","scope","webhook_signature"]}};function L(e,t){if(!e||typeof e!="object")return;let r=e[t];return typeof r=="function"?(...n)=>Reflect.apply(r,e,n):void 0}import{Kysely as J}from"kysely";var H=Symbol.for("corsair:internal"),x=class extends Error{constructor(t="Invalid corsair instance"){super(t),this.name="InvalidCorsairInstanceError"}};function I(e){return typeof e=="object"&&e!==null}function S(e){return!I(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:I(e.database)?e.database.db instanceof J:!1}function O(e){if(!e||typeof e!="object")return;let r=Object.getOwnPropertyDescriptor(e,H)?.value;return S(r)?r:void 0}function G(e,t){let r=O(e);if(!r)throw t?.()??new x;return r}function N(e,t){return e.plugins.find(r=>r.id===t)}function X(e,t,r){let n=N(e,t);if(!n)throw r(`Plugin '${t}' not found`);return n}function Y(e){return"withTenant"in e&&typeof e.withTenant=="function"}import{v7 as q}from"uuid";function T(){return q()}function v(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function V(e){let t=e.options?.authType;return v(t)?t:void 0}function ee(e,t){let r=e.authConfig,n=R[t].account,i=r?.[t]?.account??[];return[...n,...i]}import{z as h}from"zod";import{sql as w}from"kysely";function A(e){return e.replace(/'/g,"''")}function W(e){let t=A(e);return w`data->>'${w.raw(t)}'`}function j(e){let t=A(e);return w`(data->>'${w.raw(t)}')::numeric`}function K(e){let t=A(e);return w`(data->>'${w.raw(t)}')::boolean`}function U(e){let t=A(e);return w`(data->>'${w.raw(t)}')::timestamptz`}function te(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function Z(e){let t=e;for(;t;){if(t instanceof h.ZodOptional||t instanceof h.ZodNullable){t=t._def.innerType;continue}if(t instanceof h.ZodDefault){t=t._def.innerType;continue}break}return t}function ne(e){let t=Z(e);if(t instanceof h.ZodString)return"string";if(t instanceof h.ZodNumber)return"number";if(t instanceof h.ZodBoolean)return"boolean";if(t instanceof h.ZodDate)return"date"}function re(e){let t=Z(e);if(!(t instanceof h.ZodObject))return{};let r=t.shape,n={};for(let[i,a]of Object.entries(r)){let u=ne(a);u&&(n[i]=u)}return n}function ie(e,t,r){if(typeof r=="string")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;"equals"in n&&typeof n.equals=="string"&&(e=e.where(t,"=",n.equals)),"contains"in n&&typeof n.contains=="string"&&(e=e.where(t,"like",`%${n.contains}%`)),"startsWith"in n&&typeof n.startsWith=="string"&&(e=e.where(t,"like",`${n.startsWith}%`)),"endsWith"in n&&typeof n.endsWith=="string"&&(e=e.where(t,"like",`%${n.endsWith}`)),"in"in n&&Array.isArray(n.in)&&(e=e.where(t,"in",n.in))}return e}function oe(e,t,r){if(typeof r=="number")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;typeof n.equals=="number"&&(e=e.where(t,"=",n.equals)),typeof n.gt=="number"&&(e=e.where(t,">",n.gt)),typeof n.gte=="number"&&(e=e.where(t,">=",n.gte)),typeof n.lt=="number"&&(e=e.where(t,"<",n.lt)),typeof n.lte=="number"&&(e=e.where(t,"<=",n.lte)),Array.isArray(n.in)&&(e=e.where(t,"in",n.in))}return e}function se(e,t,r){if(typeof r=="boolean")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;typeof n.equals=="boolean"&&(e=e.where(t,"=",n.equals))}return e}function ae(e,t,r){if(r instanceof Date)return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;if(n.equals instanceof Date&&(e=e.where(t,"=",n.equals)),n.before instanceof Date&&(e=e.where(t,"<",n.before)),n.after instanceof Date&&(e=e.where(t,">",n.after)),Array.isArray(n.between)&&n.between.length===2){let[i,a]=n.between;i instanceof Date&&(e=e.where(t,">=",i)),a instanceof Date&&(e=e.where(t,"<=",a))}}return e}function ue(e,t,r,n){return r==="number"?oe(e,j(t),n):r==="boolean"?se(e,K(t),n):r==="date"?ae(e,U(t),n):ie(e,W(t),n)}function ce(e,t,r){if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;return"equals"in n&&(e=e.where(t,"=",n.equals)),"contains"in n&&typeof n.contains=="string"&&(e=e.where(t,"like",`%${n.contains}%`)),"startsWith"in n&&typeof n.startsWith=="string"&&(e=e.where(t,"like",`${n.startsWith}%`)),"endsWith"in n&&typeof n.endsWith=="string"&&(e=e.where(t,"like",`%${n.endsWith}`)),"in"in n&&Array.isArray(n.in)&&(e=e.where(t,"in",n.in)),e}return e.where(t,"=",r)}function de(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function C(e,t,r){return e.selectFrom("corsair_entities").selectAll().where("account_id","=",t).where("entity_type","=",r)}function $(e,t,r,n,i){let a=re(i);function u(o){let y=te(o.data);return{...o,data:i.parse(y)}}return{findByEntityId:async o=>{let y=await t(),d=await C(e,y,r).where("entity_id","=",o).executeTakeFirst();return d?u(d):null},findById:async o=>{let y=await t(),d=await C(e,y,r).where("id","=",o).executeTakeFirst();return d?u(d):null},findManyByEntityIds:async o=>{if(o.length===0)return[];let y=await t();return(await C(e,y,r).where("entity_id","in",o).execute()).map(u)},list:async o=>{let y=await t(),d=C(e,y,r);return typeof o?.limit=="number"&&(d=d.limit(o.limit)),typeof o?.offset=="number"&&(d=d.offset(o.offset)),(await d.execute()).map(u)},search:async o=>{let y=await t(),d=C(e,y,r),c=new Set(["data","limit","offset"]);for(let[l,f]of Object.entries(o))c.has(l)||f===void 0||(d=ce(d,l,f));if(o.data&&typeof o.data=="object")for(let[l,f]of Object.entries(o.data)){if(f===void 0)continue;let g=a[l]??"string";d=ue(d,l,g,f)}return typeof o.limit=="number"&&(d=d.limit(o.limit)),typeof o.offset=="number"&&(d=d.offset(o.offset)),(await d.execute()).map(u)},upsertByEntityId:async(o,y)=>{let d=await t(),c=i.parse(y),s=new Date,l=await C(e,d,r).select("id").where("entity_id","=",o).executeTakeFirst();if(l?.id){await e.updateTable("corsair_entities").set({version:n,data:c,updated_at:s}).where("id","=",l.id).execute();let E=await e.selectFrom("corsair_entities").selectAll().where("id","=",l.id).executeTakeFirst();return u(E)}let f=T();await e.insertInto("corsair_entities").values({id:f,created_at:s,updated_at:s,account_id:d,entity_id:o,entity_type:r,version:n,data:c}).execute();let g=await e.selectFrom("corsair_entities").selectAll().where("id","=",f).executeTakeFirst();return u(g)},deleteById:async o=>{let y=await t(),d=await e.deleteFrom("corsair_entities").where("account_id","=",y).where("entity_type","=",r).where("id","=",o).executeTakeFirst();return Number(d.numDeletedRows)>0},deleteByEntityId:async o=>{let y=await t(),d=await e.deleteFrom("corsair_entities").where("account_id","=",y).where("entity_type","=",r).where("entity_id","=",o).executeTakeFirst();return Number(d.numDeletedRows)>0},count:async()=>{let o=await t(),y=await e.selectFrom("corsair_entities").select(d=>d.fn.countAll().as("count")).where("account_id","=",o).where("entity_type","=",r).executeTakeFirst();return de(y?.count)}}}var le={corsair_integrations:F,corsair_accounts:D,corsair_entities:P,corsair_events:B};function ye(e){return le[e]}function M(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function p(e){if(!e)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function b(e){if(!e)return[];let t=[];for(let r in e){let n=r,i=e[n];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let a=i;"in"in a&&Array.isArray(a.in)?t.push({field:n,operator:"in",value:a.in}):"like"in a&&typeof a.like=="string"&&t.push({field:n,operator:"like",value:a.like})}else t.push({field:n,value:i})}return t}function m(e,t){if(!t?.length)return e;let r=e;for(let n of t){let i=n.operator??"=";r=r.where(n.field,i,n.value)}return r}function fe(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function k(e,t){let r=ye(t),n=()=>(p(e),e),i=()=>n().db.selectFrom(t),a=()=>n().db.insertInto(t),u=()=>n().db.updateTable(t),o=()=>n().db.deleteFrom(t);function y(c){let s={};for(let[l,f]of Object.entries(c))s[l]=M(f);return r.parse(s)}function d(c){let s={};for(let[l,f]of Object.entries(c))s[l]=M(f);return r.parse(s)}return{findById:async c=>{p(e);let s=i().selectAll();s=m(s,[{field:"id",value:c}]);let l=await s.executeTakeFirst();return l?y(l):null},findOne:async c=>{p(e);let s=i().selectAll();s=m(s,b(c));let l=await s.executeTakeFirst();return l?y(l):null},findMany:async c=>{p(e);let s=i().selectAll();return s=m(s,b(c?.where)),typeof c?.limit=="number"&&(s=s.limit(c.limit)),typeof c?.offset=="number"&&(s=s.offset(c.offset)),(await s.execute()).map(f=>y(f))},create:async c=>{p(e);let s=new Date,l={id:c.id??T(),created_at:s,updated_at:s,...c},f=await a().values(l).returningAll().executeTakeFirst();return f?y(f):d(l)},update:async(c,s)=>{p(e);let l={...s,updated_at:new Date},f=u().set(l).returningAll();f=m(f,[{field:"id",value:c}]);let g=await f.executeTakeFirst();return g?y(g):null},updateMany:async(c,s)=>{p(e);let l={...s,updated_at:new Date},f=i().select("id");f=m(f,b(c));let g=await f.execute();for(let E of g){let _=u().set(l);_=m(_,[{field:"id",value:E.id}]),await _.execute()}return g.length},delete:async c=>{p(e);let s=o();s=m(s,[{field:"id",value:c}]);let l=await s.executeTakeFirst();return Number(l?.numDeletedRows??0)>0},deleteMany:async c=>{p(e);let s=o();s=m(s,b(c));let l=await s.executeTakeFirst();return Number(l?.numDeletedRows??0)},count:async c=>{p(e);let s=i().select(f=>f.fn.countAll().as("count"));s=m(s,b(c));let l=await s.executeTakeFirst();return fe(l?.count)}}}function pe(e){let t=k(e,"corsair_integrations");return{...t,findByName:r=>t.findOne({name:r}),upsertByName:async(r,n)=>{let i=await t.findOne({name:r});return i?await t.update(i.id,n):t.create({...n,name:r})}}}function ge(e){let t=k(e,"corsair_accounts");return{...t,findByTenantAndIntegration:async(r,n)=>{p(e);let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();return i?t.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,n)=>t.findMany({where:{tenant_id:r},limit:n?.limit,offset:n?.offset}),upsertByTenantAndIntegration:async(r,n,i)=>{let a=await t.findOne({tenant_id:r,integration_id:n});return a?await t.update(a.id,i):t.create({...i,tenant_id:r,integration_id:n})}}}function me(e){let t=k(e,"corsair_entities");return{...t,findByEntityId:({accountId:r,entityType:n,entityId:i})=>t.findOne({account_id:r,entity_type:n,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:n,entityIds:i})=>i.length===0?[]:(p(e),await e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",n).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:n,limit:i,offset:a})=>t.findMany({where:{account_id:r,entity_type:n},limit:i,offset:a}),searchByEntityId:async({accountId:r,entityType:n,query:i,limit:a,offset:u})=>{p(e);let o=e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",n).where("entity_id","like",`%${i}%`);return typeof a=="number"&&(o=o.limit(a)),typeof u=="number"&&(o=o.offset(u)),await o.execute()},upsertByEntityId:async({accountId:r,entityType:n,entityId:i,version:a,data:u})=>{let o=await t.findOne({account_id:r,entity_type:n,entity_id:i});return o?await t.update(o.id,{version:a,data:u}):t.create({account_id:r,entity_type:n,entity_id:i,version:a,data:u})},deleteByEntityId:async({accountId:r,entityType:n,entityId:i})=>{p(e);let a=await e.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",n).where("entity_id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0}}}function we(e){let t=k(e,"corsair_events");return{...t,listByAccount:(r,n)=>t.findMany({where:{account_id:r},limit:n?.limit,offset:n?.offset}),listByStatus:(r,n)=>{let i={status:r};return n?.accountId&&(i.account_id=n.accountId),t.findMany({where:i,limit:n?.limit,offset:n?.offset})},listPending:r=>{let n={status:"pending"};return r?.accountId&&(n.account_id=r.accountId),t.findMany({where:n,limit:r?.limit??100})},updateStatus:(r,n)=>t.update(r,{status:n})}}function Q(e){return{integrations:pe(e),accounts:ge(e),entities:me(e),events:we(e)}}function he(e,t,r,n,i){let a=null;async function u(){if(a!==null)return a;p(e);let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t.integrationName).executeTakeFirst();if(!o)throw new Error(`Integration "${t.integrationName}" not found. Make sure to create the integration first.`);let y=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t.tenantId).where("integration_id","=",o.id).executeTakeFirst();if(!y)throw new Error(`Account not found for tenant "${t.tenantId}" and integration "${t.integrationName}". Make sure to create the account first.`);return a=y.id,a}return p(e),$(e.db,u,r,n,i)}function z(e){let{database:t,integrationName:r,schema:n,tenantId:i}=e,a=Q(t),u={tenantId:i,integrationName:r},o=null;async function y(){if(o!==null)return o;p(t);let c=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!c)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);let s=await t.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",i).where("integration_id","=",c.id).executeTakeFirst();if(!s)throw new Error(`Account not found for tenant "${i}" and integration "${r}". Make sure to create the account first.`);return o=s.id,o}let d={};for(let[c,s]of Object.entries(n.entities))d[c]=he(t,u,c,n.version,s);return{...d,$orm:a,$integrationName:r,$tenantId:i,$getAccountId:y}}function $e(e,t){let r=Q(e);return{$tenantId:t,$orm:r,listAccounts:n=>r.accounts.listByTenant(t,n),findAccountByIntegration:n=>r.accounts.findByTenantAndIntegration(t,n),listEntities:async n=>{p(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).execute();if(i.length===0)return[];let a=i.map(o=>o.id),u=e.db.selectFrom("corsair_entities").selectAll().where("account_id","in",a);return n?.entityType&&(u=u.where("entity_type","=",n.entityType)),typeof n?.limit=="number"&&(u=u.limit(n.limit)),typeof n?.offset=="number"&&(u=u.offset(n.offset)),await u.execute()},listEvents:async n=>{p(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).execute();if(i.length===0)return[];let a=i.map(o=>o.id),u=e.db.selectFrom("corsair_events").selectAll().where("account_id","in",a);return n?.status&&(u=u.where("status","=",n.status)),typeof n?.limit=="number"&&(u=u.limit(n.limit)),typeof n?.offset=="number"&&(u=u.offset(n.offset)),await u.execute()},forIntegration:n=>z({database:e,integrationName:n.integrationName,schema:n.schema,tenantId:t})}}function Me(e,t){return{forTenant:r=>z({database:e,integrationName:t.integrationName,schema:t.schema,tenantId:r})}}export{I as a,O as b,G as c,X as d,Y as e,L as f,R as g,V as h,ee as i,T as j,$ as k,le as l,Q as m,z as n,$e as o,Me as p};