corsair 0.1.95 → 0.1.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-delivery-CvBUoA96.d.ts → browser-delivery-DW81SP-j.d.ts} +1 -1
- package/dist/chunk-67EXGXPK.js +1 -0
- package/dist/chunk-FPKQA47O.js +38 -0
- package/dist/core.js +1 -1
- package/dist/hub.d.ts +13 -11
- package/dist/hub.js +1 -1
- package/dist/{index-LpuBJQ1m.d.ts → index-BHI3widx.d.ts} +2 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/oauth.js +1 -1
- package/dist/orm.js +1 -1
- package/dist/setup.js +1 -1
- package/dist/tunnel.d.ts +4 -5
- package/dist/tunnel.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-FLNFC4KL.js +0 -1
- package/dist/chunk-IGJCF7OM.js +0 -38
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as D,c as P,d as B,e as R}from"./chunk-IGGCNGU2.js";var _={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 F(e){return typeof e=="object"&&e!==null}function S(e){return!F(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:F(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=_[t].account,i=r?.[t]?.account??[];return[...n,...i]}function Ee(e,t){let r=e.authConfig,n=_[t].integration,i=r?.[t]?.integration??[];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:D,corsair_accounts:P,corsair_entities:B,corsair_events:R};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 Me(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 Qe(e,t){return{forTenant:r=>z({database:e,integrationName:t.integrationName,schema:t.schema,tenantId:r})}}export{F as a,O as b,G as c,X as d,Y as e,L as f,_ as g,V as h,ee as i,Ee as j,T as k,$ as l,le as m,Q as n,z as o,Me as p,Qe as q};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import{a as se,b as gr,c as T,d as M,e as fr,f as F,g as O,h as x,i as tn,j as yr,k as mr,l as Gn,m as hr,n as kr}from"./chunk-67EXGXPK.js";import{a as pr}from"./chunk-IGGCNGU2.js";var rn=["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"],br={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=br[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var Le="https://auth.corsair.dev";var ue=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function on(e){let n=(e.apiUrl?.trim()||Le).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim();if(!t||!r)throw new Error("Hub config requires non-empty projectApiKey and signingSecret");return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,"")}}function Vo(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function J(e){let n=T(e).hub;if(!n||!Vo(n))throw new ue;return n}function Cr(e){return e.replace(/\/$/,"")}function sn(e){return e.oauthCallbackUrl?Cr(e.oauthCallbackUrl.trim()):`${Cr(e.apiUrl)}/oauth/callback`}function Ie(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";throw new Error("Hub API key must start with ck_dev_ (development) or ck_prod_ (production)")}function v(e){return typeof e=="string"&&e.length>0}function Yo(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function Qo(e){return e==="oauth"||e==="api_key"||e==="bot_token"}function an(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!v(n.connectUrl)||!v(n.token)||!v(n.projectId))throw new Error("Hub API returned an incomplete connect session (expected connectUrl, token, and projectId)");let t={connectUrl:n.connectUrl,token:n.token,projectId:n.projectId,environmentId:v(n.environmentId)?n.environmentId:n.projectId};return v(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function un(e){if(!Array.isArray(e))throw new Error("Hub API returned an invalid connections response (expected array)");let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;if(!v(r.tenantId)||!v(r.plugin)||!Yo(r.status)||!Qo(r.authKind)||typeof r.connected!="boolean"||typeof r.verified!="boolean")continue;let o=Array.isArray(r.missingFields)?r.missingFields.filter(i=>typeof i=="string"):[];n.push({tenantId:r.tenantId,plugin:r.plugin,status:r.status,authKind:r.authKind,connected:r.connected,verified:r.verified,missingFields:o,reportedAt:v(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function cn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!v(n.approvalUrl)||!v(n.token)||!v(n.projectId)||!v(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 ln(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(v(n.access_token))return{access_token:n.access_token,refresh_token:v(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:v(n.scope)?n.scope:void 0};throw new Error(v(n.error)?v(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 ei(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;v(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 ni(e,n,t,r){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"?e:n?"ready":t.some(i=>i.level==="integration"&&i.required&&!i.configured)?"missing_integration":t.some(i=>i.level==="account"&&i.required&&i.configured)?"partial":(r.length>0,"not_started")}function wr(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!v(n.tenantId)||!Array.isArray(n.plugins))throw new Error("Connect status response was incomplete (expected tenantId and plugins)");let t=[];for(let r of n.plugins){if(!r||typeof r!="object")continue;let o=r;if(!v(o.plugin)||typeof o.connected!="boolean")continue;let i=o.authKind==="oauth"||o.authKind==="api_key"||o.authKind==="bot_token"?o.authKind:"api_key",a=ei(o.fields),s=Xo(o.missingRequiredFields),u=ni(o.status,o.connected,a,s);t.push({plugin:o.plugin,providerName:v(o.providerName)?o.providerName:o.plugin,authKind:i,status:u,connected:o.connected,fields:a,missingRequiredFields:s})}return{tenantId:n.tenantId,plugins:t}}function dn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function Pr(e){return e.replace(/\/$/,"")}async function Tr(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 vr(e,n,t){if(n===404&&t)return t;let r=dn(e);return r||`Hub API returned HTTP ${n}`}async function ce(e){let n=Pr(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 Tr(t);if(!t.ok)throw new Error(vr(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function Ar(e){let n=Pr(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`}}),r=await Tr(t);if(!t.ok)throw new Error(vr(r,t.status,e.notFoundMessage));return e.parseResponse(r)}var ti="3000",ri="/api/corsair";function Jn(e){return e.replace(/\/$/,"")}function oi(e,n){return`${Jn(e)}${n}`}function xr(e){return e.startsWith("http")?e:`https://${e}`}function Re(e){let n=e?.deliveryUrl?.trim();if(n)return Jn(n);let t=e?.deliveryPath?.trim()||ri,r=t.startsWith("/")?t:`/${t}`,o=process.env.CORSAIR_DELIVERY_URL?.trim();if(o)return Jn(xr(o));let i=process.env.APP_URL?.trim()||process.env.NEXT_PUBLIC_APP_URL?.trim()||process.env.VERCEL_URL?.trim();return i?oi(xr(i),r):`http://localhost:${process.env.PORT?.trim()||ti}${r}`}import{createCipheriv as Ir,createDecipheriv as Rr,randomBytes as pn,scrypt as ii}from"crypto";import{promisify as si}from"util";var Sr=si(ii),gn="aes-256-gcm",_r=12,fn=16,ai=16,We=32;function X(){return pn(We).toString("base64")}async function ee(e,n){let t=pn(ai),r=await Sr(n,t,We),o=pn(_r),i=Ir(gn,r,o,{authTagLength:fn}),a=Buffer.concat([i.update(e,"utf8"),i.final()]),s=i.getAuthTag();return[t.toString("base64"),o.toString("base64"),s.toString("base64"),a.toString("base64")].join(":")}async function L(e,n){let[t,r,o,i]=e.split(":");if(!t||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let a=Buffer.from(t,"base64"),s=Buffer.from(r,"base64"),u=Buffer.from(o,"base64"),d=Buffer.from(i,"base64"),l=await Sr(n,a,We),c=Rr(gn,l,s,{authTagLength:fn});return c.setAuthTag(u),Buffer.concat([c.update(d),c.final()]).toString("utf8")}function zn(e,n){let t=Buffer.from(n,"base64"),r=pn(_r),o=Ir(gn,t,r,{authTagLength:fn}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),a=o.getAuthTag();return[r.toString("base64"),a.toString("base64"),i.toString("base64")].join(":")}function je(e,n){let[t,r,o]=e.split(":");if(!t||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),a=Buffer.from(t,"base64"),s=Buffer.from(r,"base64"),u=Buffer.from(o,"base64"),d=Rr(gn,i,a,{authTagLength:fn});return d.setAuthTag(s),Buffer.concat([d.update(u),d.final()]).toString("utf8")}function le(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=zn(o,n);return t}function ne(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=je(o,n);return t}function Ke(e,n,t){let r=ne(e,n);return le(r,t)}function Er(e,n,t){let r={};for(let o of t)r[`get_${o}`]=async()=>(await e())[o]??null,r[`set_${o}`]=async i=>{let a=[null,void 0,""].includes(i)?null:i;await n({[o]:a})};return r}var Vn=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:o,extraIntegrationFields:i=[]}=e,a=[...O[n].integration,...i],s=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(s)return s;let g=await o.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:Vn(g.config),dek:g.dek??null},s},updateIntegration:async g=>{let y=await u.getIntegration();await o.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}},d=null,l=async()=>{if(d)return d;let g=await u.getIntegration();if(!g.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return d=await L(g.dek,r),d},c=async()=>{let g=await u.getIntegration(),y=await l(),m=g.config;return!m||Object.keys(m).length===0?{}:ne(m,y)};return{get_dek:l,issue_new_dek:async()=>{let g=await u.getIntegration(),y=X(),m={};if(g.dek){let P=await L(g.dek,r),w=g.config;w&&Object.keys(w).length>0&&(m=Ke(w,P,y))}let h=await ee(y,r);return await u.updateIntegration({config:m,dek:h}),d=y,y},...Er(c,async g=>{let y=await l(),m;try{m=await c()}catch(w){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,w),m={}}let h={...m};for(let[w,k]of Object.entries(g))k===null?delete h[w]:h[w]=k;let P=le(h,y);await u.updateIntegration({config:P})},a)}}function S(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:a=[]}=e,s=[...O[n].account,...a],u=null,d=null,l=async()=>{if(d)return d;let k=await i.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 d={id:k.id,config:Vn(k.config),dek:k.dek??null},d},c={kek:o,integrationName:t,tenantId:r,getIntegration:l,getAccount:async()=>{if(u)return u;let k=await l(),b=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",k.id).executeTakeFirst();if(!b)throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`);return u={id:b.id,config:Vn(b.config),dek:b.dek??null},u},updateAccount:async k=>{let b=await c.getAccount();await i.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","=",b.id).execute(),u=null}},p=null,f=null,g=async()=>{if(p)return p;let k=await c.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,o),p},y=async()=>{if(f)return f;let k=await c.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await L(k.dek,o),f},m=async()=>{let k=await c.getAccount(),b=await g(),C=k.config;return!C||Object.keys(C).length===0?{}:ne(C,b)},h=async()=>{let k=await c.getIntegration(),b=await y(),C=k.config;return!C||Object.keys(C).length===0?{}:ne(C,b)},w={get_dek:g,issue_new_dek:async()=>{let k=await c.getAccount(),b=X(),C={};if(k.dek){let _=await L(k.dek,o),D=k.config;D&&Object.keys(D).length>0&&(C=Ke(D,_,b))}let B=await ee(b,o);return await c.updateAccount({config:C,dek:B}),p=b,b},...Er(m,async k=>{let b=await g(),C;try{C=await m()}catch(D){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,D),C={}}let B={...C};for(let[D,E]of Object.entries(k))E===null?delete B[D]:B[D]=E;let _=le(B,b);await c.updateAccount({config:_})},s)};return n==="oauth_2"&&(w.get_integration_credentials=async()=>{let k=await h();return{client_id:k.client_id||null,client_secret:k.client_secret||null,redirect_url:k.redirect_url??null}}),w}async function Dr(e,n,t){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!r)throw new Error(`Integration "${n}" not found.`);let o=X(),i=await ee(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function Or(e,n,t,r){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!o)throw new Error(`Integration "${n}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${t}" and integration "${n}".`);let a=X(),s=await ee(a,r);return await e.db.updateTable("corsair_accounts").set({dek:s,updated_at:new Date}).where("id","=",i.id).execute(),a}var ui=new Set(["webhook_signature","expires_at","scope","redirect_url"]);function Se(e){return ui.has(e)}function ci(e,n){return Se(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function li(e){return!Se(e)}function di(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 pi(e,n){return di(e).every(r=>n.find(i=>i.level==="account"&&i.name===r)?.configured??!1)}async function Mr(e,n){if(!e)return!1;let t=F(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function gi(e,n){let r=e.authConfig?.[n]?.integration??[];return[...O[n].integration,...r]}function fi(e,n){let r=e.authConfig?.[n]?.account??[];return[...O[n].account,...r]}function yi(e,n,t){let r=t.filter(s=>s.required&&!s.configured).map(s=>s.name),o=t.filter(s=>s.level==="integration"&&s.required&&!s.configured).map(s=>s.name),i=t.filter(s=>s.level==="account"&&s.required&&s.configured),a;return o.length>0?a="missing_integration":r.length===0?a="ready":i.length>0?a="partial":a="not_started",{plugin:e,authType:n,status:a,connected:pi(n,t),fields:t,missingRequiredFields:r}}async function _e(e,n,t){let r=x(n);if(!r||!e.database||!e.kek)return null;let o=t.trim()||"default",i=n.authConfig,a=i?.[r]?.integration??[],s=i?.[r]?.account??[],u=I({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:a}),d=S({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:s}),l=gi(n,r),c=fi(n,r),p=[];for(let f of l)p.push({name:f,level:"integration",required:ci(r,f),configured:await Mr(u,f)});for(let f of c)p.push({name:f,level:"account",required:li(f),configured:await Mr(d,f)});return yi(n.id,r,p)}async function qe(e,n,t={}){let r=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,i=[];for(let a of e.plugins){if(o&&!o.has(a.id))continue;let s=await _e(e,a,r);s&&i.push(s)}return i}function yn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}import{ZodBoolean as hi,ZodDate as ki,ZodEnum as bi,ZodNullable as Ci,ZodNumber as wi,ZodObject as Pi,ZodOptional as Ti,ZodRecord as vi,ZodString as Ai,ZodType as xi}from"zod";var mi={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=mi;async function Xn(e,n){let t=[],r=n?.silent??!1,o=f=>{t.push(f),r||console.log(f)},i=f=>{t.push(f),r||console.warn(f)},a=n?.caller??"script",s=gr(e);if(!s)throw new Error("setupCorsair: invalid corsair instance");if(!s.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u=Ri(e,s.plugins,n),d={...s,database:s.database},l=d.database.db;await Ei(l,i);let c=await Di(l,d,u.tenantId,u.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await Hi(e,u,n.credentials,d,o,i);let p=await Ui(c,u,o,a);if(n?.backfill){o("[corsair:setup] Starting backfill...");let f=Ur({plugins:s.plugins,database:l,kek:s.kek,multiTenancy:!0}).withTenant(u.tenantId);await Bi(f,s.plugins,p,o,i),o("[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([...O[n][t],...r])}function Ii(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let o=n.find(s=>s.id===t);if(!o)continue;let i=x(o);if(!i)continue;let a=Qn(o,i,"account");for(let s of Object.keys(r))if(a.has(s))return!0}return!1}function Ri(e,n,t){let r=fr(e),o=t?.tenantId?.trim(),i=o!==void 0&&o.length>0;if(r&&t?.backfill&&!i)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(r&&Ii(t?.credentials,n)&&!i)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(i&&!o)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:r,tenantIdProvided:i,tenantId:i?o:"default",provisionAccounts:!r||i}}function Fr(e,n){return se(e)?n===0?!0:Object.values(e).every(t=>Fr(t,n-1)):!1}function Si(e){return Fr(e,4)}var _i={...hr};function mn(e){if(e instanceof Pi){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof xi?mn(r):"unknown";return n}return e instanceof Ci?`${mn(e.unwrap())} | null`:e instanceof Ti?`${mn(e.unwrap())} | undefined`:e instanceof bi?e.options.join(" | "):e instanceof Ai?"string":e instanceof wi?"number":e instanceof hi?"boolean":e instanceof ki?"date":e instanceof vi?"jsonb":"unknown"}async function Ei(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(_i))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
|
|
3
|
+
Schema: ${JSON.stringify(mn(i),null,2)}`)}async function Di(e,n,t,r,o){let i=new Date,a=new Map;for(let s of n.plugins){let u=s.id,d=x(s),l=await e.selectFrom("corsair_integrations").selectAll().where("name","=",u).executeTakeFirst();if(!l){let y=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:y,name:u,config:{},created_at:i,updated_at:i}).execute(),l=await e.selectFrom("corsair_integrations").selectAll().where("id","=",y).executeTakeFirst(),o(`[corsair:setup] Created integration: ${u}`)}let c=d?s.authConfig?.[d]?.integration??[]:[],p=d?s.authConfig?.[d]?.account??[]:[],f=d&&l?I({authType:d,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:c}):void 0;if(l&&!l.dek&&f&&(await f.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${u}`)),!l||!d||!f)continue;let g;if(r){let y=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",l.id).executeTakeFirst();if(!y){let m=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:m,tenant_id:t,integration_id:l.id,config:{},created_at:i,updated_at:i}).execute(),y=await e.selectFrom("corsair_accounts").selectAll().where("id","=",m).executeTakeFirst(),o(`[corsair:setup] Created account: ${u}`)}g=y&&S({authType:d,integrationName:u,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:p}),y&&g&&!y.dek&&(await g.issue_new_dek(),o(`[corsair:setup] Issued account DEK: ${u}`))}a.set(u,{pluginId:u,authType:d,integration:f,account:g,integrationFields:[...O[d].integration,...c],accountFields:r?[...O[d].account,...p]:[]})}return a}function Oi(e){if(!se(e))return;let n=e.keys;return se(n)?n:void 0}function Mi(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function Hi(e,n,t,r,o,i){let a=Oi(e),s=n.provisionAccounts?Mi(e,n.tenantId):void 0;for(let[u,d]of Object.entries(t)){let l=r.plugins.find(h=>h.id===u);if(!l){i(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let c=x(l);if(!c){i(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let p=Qn(l,c,"integration"),f=Qn(l,c,"account"),g=a?.[u],y=s?.[u],m=se(y)?y.keys:void 0;for(let[h,P]of Object.entries(d))if(P){if(p.has(h)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${u}.${h}' 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 w=F(g,`set_${h}`);if(!w){i(`[corsair:setup] Cannot set integration field '${h}' for '${u}'.`);continue}await w(P),o(`[corsair:setup] Set ${u} integration.${h}`);continue}if(f.has(h)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${u}.${h}' on a multi-tenant instance`);let w=F(m,`set_${h}`);if(!w){i(`[corsair:setup] Cannot set account field '${h}' for '${u}'.`);continue}await w(P),o(`[corsair:setup] Set ${u} account.${h} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${h}' for plugin '${u}'.`)}}}var Hr=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Fi(e,n,t,r,o,i,a,s,u){let d=[],l=[];for(let p of o){if(Hr.has(p))continue;let f=F(t,`get_${p}`);if(!f)continue;let g=null;try{let y=await f();g=typeof y=="string"?y:null}catch{}g||d.push(p)}if(r&&i.length>0)for(let p of i){if(Hr.has(p))continue;let f=F(r,`get_${p}`);if(!f)continue;let g=null;try{let y=await f();g=typeof y=="string"?y:null}catch{}g||l.push(p)}let c=d.length===0&&l.length===0;if(c)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=[...d,...l];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 d)f.push(` await corsair.keys.${e}.set_${g}(value)`);for(let g of l){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 c}async function Ui(e,n,t,r){let o=new Set;for(let i of e.values())await Fi(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function Bi(e,n,t,r,o){if(!Si(Yn)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=Yn,a=new Set(n.map(s=>s.id));for(let[s,u]of Object.entries(i)){if(!a.has(s))continue;if(!t.has(s)){r(`[corsair:setup] Skipping backfill for '${s}' \u2014 auth not configured.`);continue}let d=se(e)?e[s]:void 0,l=se(d)?d.api:void 0;if(l)for(let[c,p]of Object.entries(u))for(let[f,g]of Object.entries(p)){r(`[corsair:setup] Backfilling ${s} \u203A ${c}.${f}...`);try{let y=se(l)?l[c]:void 0;await F(y,f)?.(g)}catch(y){o(`[corsair:setup] ${s} \u203A ${c}.${f} failed: `+(y instanceof Error?y.message:String(y)))}}}}async function Br(e){if(!T(e).database)throw new Error("A database must be configured to provision Corsair integrations");await Xn(e,{silent:!0})}async function Ee(e,n){if(!T(e).database)throw new Error("A database must be configured to provision Corsair for connect");await Xn(e,{tenantId:n,silent:!0})}var Ni=Symbol.for("corsair:internal"),$i=new Set(["access_token","refresh_token","expires_at","scope"]);function Li(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Wi(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!Se(t)&&!$i.has(t)):n.filter(t=>!Se(t))}function Nr(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:!1}}function $r(e){return{[Ni]:Nr(e)}}async function nt(e,n,t={}){let r=sn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,a=Nr(e),s=$r(e);for(let u of e.plugins){if(i&&!i.has(u.id))continue;let d=x(u);if(!d)continue;let l=Li(d),c=t.providerNameOverrides?.[u.id]??ae(u.id),p=await _e(a,u,n),f=tn(u,d),g=Wi(d,f),y={plugin:u.id,providerName:c,authKind:l,alreadyConfigured:p?.connected??!1};if(g.length>0&&(y.credentialFields=g),l==="oauth"){let h=t.oauthModeOverrides?.[u.id]??(d==="managed"?"managed":"byo");if(y.oauthMode=h,!t.skipOAuthUrlGeneration&&h!=="managed")try{let P=await et(s,u.id,{tenantId:n,redirectUri:r,hubConnect:!0});y.oauthUrl=P.url}catch(P){y.setupError=P instanceof Error?P.message:`Could not prepare OAuth for ${u.id}`}}o.push(y)}return o}async function tt(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await Ee($r(e),n)}async function Lr(e,n){let t=Ie(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return t==="development"&&(r.deliveryUrl=Re({deliveryUrl:n.deliveryUrl})),ce({hub:e,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:an})}async function rt(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e};await tt(t,n.tenantId);let r=await nt(t,n.tenantId,{pluginIds:[n.plugin.id]});if(r.length===0)throw new Error(`Plugin '${n.plugin.id}' is not configured on this Corsair instance`);return Lr(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function hn(e,n){let t=T(e),r=J(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r};await tt(o,n.tenantId);let i=n.plugin?[n.plugin]:void 0,a=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,s=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,u=await nt(o,n.tenantId,{pluginIds:i,oauthModeOverrides:a,providerNameOverrides:s});if(u.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return Lr(r,{tenantId:n.tenantId,plugins:u,deliveryUrl:n.deliveryUrl})}function Wr(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function ji(e,n){return n&&!n.has(e.id)?!1:x(e)!==null}async function jr(e,n,t={}){let r=T(e),o=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,a=await qe(r,o,{pluginIds:t.pluginIds}),s=new Map(a.map(d=>[d.plugin,d])),u=r.plugins.filter(d=>ji(d,i)).map(d=>{let l=x(d),c=s.get(d.id);return c?{plugin:d.id,providerName:ae(d.id),authKind:Wr(l),status:c.status,connected:c.connected,fields:c.fields.map(p=>({name:p.name,level:p.level,required:p.required,configured:p.configured})),missingRequiredFields:c.missingRequiredFields}:{plugin:d.id,providerName:ae(d.id),authKind:Wr(l),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:u}}async function Kr(e,n){let t=J(e);return Ar({hub:t,path:`/projects/${encodeURIComponent(n.projectId)}/connections`,notFoundMessage:"Hub REST API not found at /projects/:id/connections. Check HUB_API_URL and ensure the Hub API is deployed.",parseResponse:un})}var Ki=new Set(["localhost","127.0.0.1","[::1]","::1"]);function ot(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Ki.has(n)}catch{return!1}}function it(e){return e==="development"?"browser":"server"}function qr(e){return it(e)==="browser"}function Zr(e){return ot(e)?"Production delivery URL must be a public URL, not localhost":null}var Gr=new Set(["oauth.callback","oauth.tokens","webhook","permission.approve","permission.deny","auth.credentials","integration.credentials"]),de=60*1e3,Ce=300*1e3;var z=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function kn(e,n){let t=T(e,()=>new z("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new z("no_database","Database not configured");let r=M(t,n.plugin,l=>new z("plugin_not_found",l)),o=x(r);if(!o)throw new z("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new z("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await Ee(e,n.tenantId);let i=new Set(tn(r,o)),s=r.authConfig?.[o]?.account??[],u=S({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:s}),d=0;for(let[l,c]of Object.entries(n.credentials)){if(!c.trim())continue;if(!i.has(l))throw new z("invalid_credentials",`Unknown credential field '${l}' for plugin '${n.plugin}'`);let p=F(u,`set_${l}`);if(!p)throw new z("invalid_credentials",`Cannot set credential field '${l}' for plugin '${n.plugin}'`);await p(c.trim()),d+=1}if(d===0)throw new z("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var V=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function st(e,n){let t=T(e,()=>new V("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new V("no_database","Database not configured");let r=M(t,n.plugin,l=>new V("plugin_not_found",l)),o=x(r);if(!o)throw new V("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await Br(e);let i=new Set(yr(r,o)),s=r.authConfig?.[o]?.integration??[],u=I({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:s}),d=0;for(let[l,c]of Object.entries(n.credentials)){if(!c.trim())continue;if(!i.has(l))throw new V("invalid_credentials",`Unknown integration credential field '${l}' for plugin '${n.plugin}'`);let p=F(u,`set_${l}`);if(!p)throw new V("invalid_credentials",`Cannot set integration field '${l}' for plugin '${n.plugin}'`);await p(c.trim()),d+=1}if(d===0)throw new V("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var bn=new Map;function qi(e){for(let[n,t]of bn)t<=e&&bn.delete(n)}function Cn(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return qi(r),bn.has(t)?{ok:!1,error:"Delivery request already consumed"}:(bn.set(t,r+n),{ok:!0})}async function wn(e,n,t){for(let r of e){if(r.id!==n)continue;let o=r.oauthWebhookTenantLinkResolver;return o?o(t):null}return null}var Jr=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function Zi(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 Gi(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=Jr(n.config),o={};Object.keys(r).length>0&&(o=ne(r,t)),o[e.link.linkType]=e.link.externalId;let i=le(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function De(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:a,extraAccountFields:s=[]}=e,{accountId:u}=await Zi({database:n,pluginId:r,tenantId:o}),d=!1;if(a){let l=S({authType:a,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:s}),c=`set_${i.linkType}`,p=l[c];typeof p=="function"&&(await p(i.externalId),d=!0)}d||await Gi({database:n,kek:t,accountId:u,link:i})}async function at(e){let{database:n,kek:t,pluginId:r,linkType:o,externalId:i}=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),l=Jr(s.config)[o];if(!l)continue;if(je(l,u)===i)return s}catch{continue}return null}async function Pn(e){return(await at(e))?.tenant_id??null}async function zr(e){return Pn({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var pe=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:o,refreshToken:i,expiresIn:a,scope:s}=n;if(!o.trim())throw new pe("no_access_token","Managed OAuth delivery missing access_token");let u=T(e,()=>new pe("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new pe("no_database","No database configured on corsair instance");let d=M(u,t,c=>new pe("plugin_not_found",c));await Ee(e,r);let l=S({authType:"managed",integrationName:t,tenantId:r,kek:u.kek,database:u.database});await l.set_access_token(o),i&&await l.set_refresh_token(i),a&&await l.set_expires_at(String(Math.floor(Date.now()/1e3)+a)),s&&await l.set_scope(s);try{let c=await wn(u.plugins,t,{access_token:o,refresh_token:i,scope:s});if(c)try{let p=d.authConfig?.managed?.account??[];await De({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:c,authType:"managed",extraAccountFields:p})}catch(p){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,p)}}catch(c){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,c)}return{plugin:t,tenantId:r}}import{createHmac as ut,randomUUID as Ji,timingSafeEqual as Vr}from"crypto";function Yr(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=ut("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":Ji()}}}function ct(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Yr(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Ce)return!1;let i=ut("sha256",n).update(e.body).digest("hex");try{return Vr(Buffer.from(i,"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=Yr(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)>Ce)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=ut("sha256",n).update(e.body).digest("hex");try{if(!Vr(Buffer.from(i,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}function lt(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function dt(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function pt(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 gt(e){let{body:n,headers:t}=Tn(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),o=await r.text();return{ok:r.ok,status:r.status,body:o}}catch(r){return{ok:!1,status:0,body:r instanceof Error?r.message:"Delivery request failed"}}}function zi(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Qr(e,n,t=[]){for(let[r,o]of Object.entries(e))if(zi(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=Qr(o,n,[...t,r]);if(i)return i}return null}function Vi(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Yi(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 Xr(e,n,t,r){let o=Vi(n),i=typeof t=="string"?JSON.parse(t):t;(!i||typeof i=="object"&&Object.keys(i).length===0)&&o["x-goog-resource-uri"]&&(i=Yi(o)||i);let s={headers:o,body:i,...r?{query:r}:{}},u=r?.tenantId||"default",d=e.withTenant?e.withTenant(u):e,l=rn;for(let c of l){let p=d[c];if(!p||!p.webhooks||p.pluginWebhookMatcher&&!p.pluginWebhookMatcher(s))continue;let f=Qr(p.webhooks,s);if(!f)continue;let g=f.path.join("."),y={payload:i,headers:o,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let m=await f.webhook.handler(y),h=!!Object.keys(m.returnToSender||{})?.length;return{plugin:c,action:g,body:i,response:h?{...m?.returnToSender,success:!0}:{success:!0},...m.responseHeaders&&{responseHeaders:m.responseHeaders}}}catch(m){return console.error(`Error executing webhook handler for ${c}.${g}:`,m),{plugin:c,action:g,body:i,response:{success:!1,error:m instanceof Error?m.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{randomBytes as ns}from"crypto";import{createHmac as Qi,randomBytes as Xi,timingSafeEqual as es}from"crypto";function te(){return Xi(16).toString("base64url")}function Ze(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Qi("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[o,i]=r;if(!o||!i)return null;let a=Ze(o,t);try{if(!es(Buffer.from(i,"utf8"),Buffer.from(a,"utf8")))return null}catch{return null}let s;try{s=JSON.parse(Buffer.from(o,"base64url").toString("utf8"))}catch{return null}return s.exp*1e3<Date.now()?null:s}function vn(e,n,t){let r=Math.floor(Date.now()/1e3),o={...e,iat:r,exp:t},i=Buffer.from(JSON.stringify(o)).toString("base64url"),a=Ze(i,n);return`${i}.${a}`}function Ge(e,n,t){let r=Math.floor(Date.now()/1e3);return vn(e,n,r+Math.floor(t/1e3))}function we(e){return decodeURIComponent(e)}function ft(e){return encodeURIComponent(e)}function eo(e){let n=e.trim();return n.length>0?n:null}function An(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function xn(e,n){if(!eo(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??ns(16).toString("base64url"),iat:t,exp:t+Math.floor(de/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=Ze(o,n);return`${o}.${i}`}function ge(e,n){return eo(n)?Y(e,n):null}function Pe(e){return e.deliveryMode==="auth.credentials"}function Je(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function ze(e){return e.deliveryMode==="oauth.tokens"}function In(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!Pe(e)&&!Je(e)&&!ze(e)}function yt(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 ts(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 Pn({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function rs(e,n,t){let r=await ts(e,n,t),o={...t.query??{},...r?{tenantId:r}:{}},i=await Xr(e,t.headers,t.body,o);if(!i.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(i.response&&i.response.success===!1)return{status:"failed",retryable:!1,error:typeof i.response.error=="string"?i.response.error:"Webhook handler failed"};let a=i.response?.returnToSender,s=a&&typeof a=="object"&&typeof a.validationToken=="string"&&Object.keys(a).length===1?a.validationToken:a||(i.response?.data??i.response);return{status:"ok",webhookResponse:{status:i.response?.statusCode??200,body:s,headers:i.responseHeaders}}}async function os(e,n){return await Ve(e,n),{status:"ok"}}async function is(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 ht(e,n,t){let r=await mt(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function mt(e,n,t){let r=T(e),o=n.token?.trim();if(!o)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let i=new Date().toISOString(),a=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",o).executeTakeFirst();return a?a.status!=="pending"?{status:"ok"}:a.expires_at<i?(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 ss(e,n){try{return await kn(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function as(e,n){try{return await st(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}async function kt(e,n,t={}){let r=T(e),o=yt(n.headers,"x-corsair-signature"),i=yt(n.headers,"x-corsair-timestamp"),a=yt(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let u=Me({body:n.body,signatureHeader:o,timestampHeader:i,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 d=Cn(`nonce:${a.trim()}`,Ce);if(!d.ok)return{status:"failed",retryable:!1,error:d.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"}}if(s.type==="connect.status")return{status:"failed",retryable:!1,error:"connect.status pull introspection is disabled; apps push status via POST /connections/report"};switch(s.type){case"webhook":return rs(e,r,s.payload);case"oauth.callback":return os(e,s.payload);case"oauth.tokens":return is(e,s.payload);case"permission.approve":return mt(e,s.payload,"approved");case"permission.deny":return mt(e,s.payload,"denied");case"auth.credentials":return ss(e,s.payload);case"integration.credentials":return as(e,s.payload);default:return us(String(s.type))}}function us(e){return Gr.has(e)?{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${e}`}:{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${e}`}}var cs="corsair:client-bridge";function no(e){let n=JSON.stringify({type:cs,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 ls=[".corsair.dev"];function ds(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function ps(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:ds(n)?!0:ls.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function to(e){return!e||!ps(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 ro(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,o]of Object.entries(n))t.set(r,o);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function bt(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 Ct(e,n){let t=J(e),o=new URL(n).searchParams.get("d");if(!o)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let i=ge(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let a=Cn(`browser:${i.jti}`,de);if(!a.ok)return{type:"json",status:400,body:{error:a.error}};try{if(Pe(i))return i.hubSuccessUrl?i.credentials?(await kn(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:bt(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:bt(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(Je(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await ht(e,i.permissionToken,i.deliveryMode==="permission.approve"?"approved":"denied")}else if(ze(i)){if(!i.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Oe(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope})}else{if(!In(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await Ve(e,{code:i.code,state:i.state,redirectUri:i.redirectUri})}}catch(s){let u=s instanceof Error?s.message:"Hub delivery failed";return Pe(i)&&i.hubSuccessUrl?{type:"redirect",url:bt(i.hubSuccessUrl,{error:u})}:Pe(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:no({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:i.hubSuccessUrl}}async function wt(e,n){let t=J(e),r=await kt(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 o=r.webhookResponse;if(!o)return{type:"json",status:200,body:{status:"ok"}};let i=o.status??200,a=o.headers;return o.body&&typeof o.body=="object"&&!(o.body instanceof ArrayBuffer)?{type:"json",status:i,body:o.body,headers:a}:{type:"text",status:i,body:typeof o.body=="string"?o.body:o.body?JSON.stringify(o.body):null,headers:a}}function Pt(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 Tt(e,n){return n.method==="GET"?Ct(e,n.url):wt(e,{headers:n.headers,body:n.body??""})}async function vt(e,n){try{let t=await Tt(e,n);return Pt(t)}catch(t){if(t instanceof ue)return Response.json({error:t.message},{status:503});throw t}}async function Te(e,n){let t=n.method.toUpperCase(),r=to(n.headers.get("origin"));if(t==="OPTIONS")return r?new Response(null,{status:204,headers:r}):Response.json({error:"Method not allowed"},{status:405});if(t!=="GET"&&t!=="POST")return Response.json({error:"Method not allowed"},{status:405});let o=await vt(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return ro(o,r)}var re=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 oo=300;async function At(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,a=n?.forceRefresh??!1,[s,u,d]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!s&&!d)throw new re(o,"managed");let l=Math.floor(Date.now()/1e3);if(!a&&s&&u&&Number(u)>l+oo)return{accessToken:s,expiresAt:Number(u),refreshed:!1};if(!d&&s&&!a){let f=u?Number(u):null;if(f===null||f>l+oo)return{accessToken:s,expiresAt:f??l+3600,refreshed:!1}}let c=await ce({hub:r,path:"/oauth/refresh",body:{plugin:o,tenantId:i},parseResponse:ln}),p=c.expires_in?l+c.expires_in:u?Number(u):l+3600;return await t.set_access_token(c.access_token),await t.set_expires_at(String(p)),c.refresh_token&&await t.set_refresh_token(c.refresh_token),c.scope&&await t.set_scope(c.scope),{accessToken:c.access_token,expiresAt:p,refreshed:!0}}async function io(e,n){e._refreshAuth=async()=>(await At(n,{forceRefresh:!0})).accessToken}async function Rn(e,n){let t=Ie(e.projectApiKey),r={permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,expiresAt:n.expiresAt};return t==="development"&&(r.deliveryUrl=Re({deliveryUrl:n.deliveryUrl})),ce({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:cn})}function Sn(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}function gs(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}async function fs(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins},t=x(e.plugin);if(!t)return;let r=e.tenantId?.trim()||"default",o=await _e(n,e.plugin,r);o&&so(e.hub,{tenantId:r,plugin:e.plugin.id,authKind:gs(t),status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields})}function so(e,n){ce({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function Ye(e){fs(e).catch(()=>{})}function ao(e){return{delivery:n=>Te(e,n),deliveryOptions:n=>Te(e,n)}}var uo=1200*1e3;function xt(){return te()}function It(){return uo}function Rt(e,n){return Ge(e,n,uo)}function St(e,n){return Y(e,n)}function _t(e){return we(e)}var co=600*1e3;function Et(){return te()}function Dt(){return co}function Ot(e,n){return Ge(e,n,co)}function Mt(e,n){return Y(e,n)}function Ht(e){return ft(e)}function Ft(e){return we(e)}function Ut(){return te()}function Bt(e,n,t){return vn(e,n,Math.floor(t.getTime()/1e3))}function Nt(e,n){return Y(e,n)}function $t(e){return we(e)}function _n(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(o,i){let a=t.length>1;throw new Error(`corsair.keys.${String(i)}: 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 ${We}`)}})}function He(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}import*as Qe from"crypto";function fe(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Lt(e,{maxAgeMs:n}={}){try{let t=e.includes(".")?e.split(".")[0]:e,r=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));if(r!==null&&typeof r=="object"&&"plugin"in r&&"tenantId"in r&&typeof r.plugin=="string"&&typeof r.tenantId=="string"){let o=r;return n!==void 0&&typeof o.iat=="number"&&Date.now()-o.iat>n?null:o}return null}catch{return null}}function Fe(e,n){let t=Qe.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Wt=600*1e3;function En(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=Qe.createHmac("sha256",n).update(r).digest("base64url"),a=Buffer.from(o,"base64url"),s=Buffer.from(i,"base64url");return a.length!==s.length||!Qe.timingSafeEqual(a,s)?null:Lt(r,{maxAgeMs:Wt})}function jt(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function ys(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await rt(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins})).connectUrl}catch{return null}}async function ms(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await rt(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):jt(e.pluginId,r.connectUrl)}catch{return`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`}let t=await ys({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins});return t?jt(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function hs(e,n,t){let r=Fe(fe(e,n.tenantId??t??"default"),n.kek),o=new URL(n.baseUrl);o.searchParams.set("state",r);let i=o.toString();return n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:i,state:r}):jt(e,i)}async function lo(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&He(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?hs(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?ms({manual:e.manual,hub:e.hub,plugin:e.plugin,pluginId:t,tenantId:n,authType:e.error.authType,database:e.database,kek:e.kek,plugins:e.plugins}):e.error.message}var ks=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function po(e,n,t,r,o){let i={pluginId:n,operation:t,input:r,originalError:e},a=Object.keys(o).find(d=>o[d]?.match(e,i));return await(o[a||"DEFAULT"]?.handler||ks)(e,i)}import{randomBytes as Cs}from"crypto";import{v4 as ws}from"uuid";var Kt="Permission approval required. Set manual.approvalBaseUrl (or use hub for hosted approval) so an approval URL can be generated. Optionally set manual.onApprovalRequired to customize the agent message.";function Zt(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function go(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function qt(e){return Sn(e)}async function Gt(e,n){if(Zt(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?go(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:bs(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function bs(e){try{return JSON.parse(e)}catch{return e}}async function Dn(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Gt(e,n);return{...n,approvalUrl:r}}async function Jt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:a,endpoint:s,args:u,tenantId:d,expiresAt:l,operationPath:c}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:a,endpoint:s,args:u});let f=await Gt({manual:t,hub:r},{id:o,token:i,plugin:a,endpoint:s,args:JSON.stringify(u),tenant_id:d,expires_at:l});return Zt(t)?f?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:f}):qt(f):Kt:r?f?qt(f):`Action '${c}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Kt}var Ps={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 Ts(e,n,t){return t!==void 0?t:Ps[n][e]}function zt(e){let n=/(\d+)(d|h|m|s)/g,t=0,r;for(;(r=n.exec(e))!==null;){let o=parseInt(r[1],10);switch(r[2]){case"d":t+=o*864e5;break;case"h":t+=o*36e5;break;case"m":t+=o*6e4;break;case"s":t+=o*1e3;break}}return t>0?t:600*1e3}function yo(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 fo(e,n,t){let r=Date.now()+t;for(;Date.now()<r;){let o=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).executeTakeFirst();if(!o)return{result:"blocked",reason:"pending"};if(o.status==="approved")return{result:"allow",onComplete:async()=>{await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}};if(o.status==="denied")return{result:"blocked",reason:"denied"};if(o.status==="expired"||o.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(i=>setTimeout(i,500))}return{result:"blocked",reason:"timeout"}}async function mo(e){let n=Ts(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 o=JSON.stringify(e.args),i=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","=",o).where("tenant_id","=",a).where("expires_at",">",i).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"?fo(e.db,s.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:s.id,token:s.token,expiresAt:s.expires_at})}let u=ws(),d=Cs(32).toString("hex"),l=e.timeoutMs??600*1e3,c=new Date(Date.now()+l).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:u,created_at:new Date,updated_at:new Date,token:d,plugin:e.pluginId,endpoint:e.endpointPath,args:o,tenant_id:a,status:"pending",expires_at:c}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
|
|
21
|
+
Action: ${r}`,`
|
|
22
|
+
Permission ID: ${u}`,`
|
|
23
|
+
Permission token: ${d}`,`
|
|
24
|
+
Expires at: ${c}`,`
|
|
25
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?fo(e.db,u,l):{result:"blocked",reason:"pending",id:u,token:d,expiresAt:c}}function vs(e){return typeof e=="function"}function Vt({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:a=[],keyBuilder:s,permissionsConfig:u,endpointMeta:d,database:l,permissionsOptions:c,tenantId:p,manualConfig:f,hubConfig:g,plugin:y,kek:m,allPlugins:h}){for(let[P,w]of Object.entries(e)){let k=n?.[P];if(vs(w)){let b=k,C=[...a,P].join("."),B=async(_={})=>{let D;if(u){let N=d?.[C],{result:nn,reason:Z,onComplete:$e,token:Q,id:be,expiresAt:$}=await mo({pluginId:o,endpointPath:C,args:_,mode:u.mode,override:u.overrides?.[C],riskLevel:N?.riskLevel??"write",meta:N,db:l,timeoutMs:c?zt(c.timeout):void 0,tenantId:p,approvalMode:c?.mode});if(nn==="blocked"){let G;throw Z==="denied"?G=`Action '${C}' was denied by the user. Await further instructions before proceeding.`:Z==="policy"?G=`Action '${C}' is blocked by the permission policy. Update the corsair config to allow it.`:Z==="timeout"?G=`Action '${C}' timed out waiting for approval.`:Q&&be?G=await Jt({permissionsOptions:c,manual:f,hub:g,permissionId:be,permissionToken:Q,plugin:o,endpoint:C,args:_,tenantId:p??"default",expiresAt:$??new Date(Date.now()+(c?zt(c.timeout):600*1e3)).toISOString(),operationPath:C}):G=`Action '${C}' requires user approval before it can run.`,new Error(G)}D=$e}let E=async(N,nn,Z)=>{try{return await w(nn,Z)}catch($e){if($e instanceof Error){let Q=await po($e,o,C,typeof Z=="object"&&Z!==null?Z:{args:Z},i);if(N<(Q.maxRetries||0)){let be=N+1;console.log(`Retrying (${be} / ${Q.maxRetries})...`);let $;if(Q.headersRetryAfterMs)$=Q.headersRetryAfterMs;else switch(Q.retryStrategy){case"exponential_backoff":$=Math.pow(2,be-1)*1e3;break;case"exponential_backoff_jitter":let G=Math.pow(2,be-1)*1e3,zo=(Math.random()-.5)*1e3;$=Math.max(0,G+zo);break;case"linear_1s":$=1e3;break;case"linear_2s":$=2e3;break;case"linear_3s":$=3e3;break;case"linear_4s":$=4e3;break;default:$=1e3;break}await new Promise(G=>setTimeout(G,$)),await E(be,nn,Z),console.log(`[corsair:${o}:${C}] Retry strategy:`,Q)}}throw $e}},he;try{he=s?await s(t,"endpoint"):void 0}catch(N){if(N instanceof re)return y&&g&&Ye({hub:g,database:l,kek:m,plugins:h??[],plugin:y,tenantId:p,verified:!1}),lo({error:N,manual:f,hub:g,plugin:y,tenantId:p,database:l,kek:m,plugins:h});throw N}if(!b?.before&&!b?.after){let N=await E(0,{...t,key:he},_);return await D?.(),y&&g&&Ye({hub:g,database:l,kek:m,plugins:h??[],plugin:y,tenantId:p,verified:!0}),N}let Ne={...t,key:he},ke=b.before?await b.before(Ne,_):{ctx:Ne,args:_,continue:!0,passToAfter:void 0};if(ke.continue===!1)return;let dr=await E(0,ke.ctx,ke.args);return await b.after?.(ke.ctx,dr,ke.passToAfter),await D?.(),y&&g&&Ye({hub:g,database:l,kek:m,plugins:h??[],plugin:y,tenantId:p,verified:!0}),dr};r[P]=B}else if(w&&typeof w=="object"){let b={};Vt({endpoints:w,hooks:k,ctx:t,tree:b,pluginId:o,errorHandlers:i,currentPath:[...a,P],keyBuilder:s,permissionsConfig:u,endpointMeta:d,database:l,permissionsOptions:c,tenantId:p,manualConfig:f,hubConfig:g,plugin:y,kek:m,allPlugins:h}),r[P]=b}}}function As(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Yt({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,a]of Object.entries(e)){let s=n?.[i];if(As(a)){let u=s,d=async l=>{let c=(f,g)=>a.handler(f,g),p=o?await o(t,"webhook"):void 0;return!u?.before&&!u?.after?c({...t,key:p},l):(async()=>{let f={...t,key:p},g=u.before?await u.before(f,l):{ctx:f,args:l,continue:!0,passToAfter:void 0};if(g.continue===!1)return;let y=await c(g.ctx,g.args);return y?.success===!0&&await u.after?.(g.ctx,y,g.passToAfter),y})()};r[i]={match:a.match,handler:d}}else if(a&&typeof a=="object"){let u={};Yt({webhooks:a,hooks:s,ctx:t,webhooksTree:u,keyBuilder:o}),r[i]=u}}}function xs(e,n,t){let r=null;return async()=>{if(r)return r;if(!e)throw new Error("Database not configured");let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!o)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${t}" and integration "${n}". Make sure to create the account first.`);return r=i.id,r}}function Is(e,n,t,r,o){return e?Gn(e.db,n,t,r,o):{findByEntityId:async()=>null,existsByEntityId:async()=>!1,findIdByEntityId:async()=>null,findById:async()=>null,findManyByEntityIds:async()=>[],list:async()=>[],search:async()=>[],upsertByEntityId:async()=>{throw new Error("Database not configured")},deleteById:async()=>!1,deleteByEntityId:async()=>!1,count:async()=>0}}function Qt(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:a,manualConfig:s,hubConfig:u}=n,d={},l={};for(let c of e)d[c.id]={},l[c.id]={};for(let c of e){let p=c.schema,f=r??"default",g=xs(t,c.id,f);if(p?.entities){let E={};for(let[he,Ne]of Object.entries(p.entities)){let ke=t?Gn(t.db,g,he,p.version,Ne):Is(void 0,g,he,p.version,Ne);E[he]=ke}l[c.id].db=E,d[c.id].db=E}let y=c.options,m=c.authConfig,h;if(t&&o&&y?.authType){let E=m?.[y.authType]?.account??[];h=S({authType:y.authType,integrationName:c.id,tenantId:f,kek:o,database:t,extraAccountFields:E}),d[c.id].keys=h}let P={database:t,db:l[c.id]?.db??{},$getAccountId:g,...c.options?{options:c.options}:{},...h?{keys:h,authType:y?.authType}:{},tenantId:f,...u?{hub:u}:{}},w=c.endpoints??{},k=c.hooks,b={...i,...c.errorHandlers},C={},B=c.options?.permissions;Vt({endpoints:w,hooks:k,ctx:P,tree:C,pluginId:c.id,errorHandlers:b,currentPath:[],keyBuilder:c.keyBuilder,permissionsConfig:B,endpointMeta:c.endpointMeta,database:t,permissionsOptions:a,tenantId:r,manualConfig:s?{...s,oauthConfig:c.oauthConfig,kek:o,tenantId:f}:void 0,hubConfig:u,plugin:c,kek:o,allPlugins:e}),Object.keys(C).length>0&&(d[c.id].api=C),P.endpoints=C;let _=c.webhooks??{},D=c.webhookHooks;if(Object.keys(_).length>0){let E={};Yt({webhooks:_,hooks:D,ctx:P,webhooksTree:E,keyBuilder:c.keyBuilder}),d[c.id].webhooks=E,c.pluginWebhookMatcher&&(d[c.id].pluginWebhookMatcher=c.pluginWebhookMatcher),c.pluginTenantWebhookMatcher&&(d[c.id].pluginTenantWebhookMatcher=c.pluginTenantWebhookMatcher)}}return d}function ho(e,n,t){let r={};for(let o of e){let i=o.options,a=o.authConfig;if(i?.authType){let s=a?.[i.authType]?.integration??[],u=I({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:s});r[o.id]=u}}return r}var Rs="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function ko(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] ${Rs}`),t):n}import*as bo from"querystring";function ve(e){let{oauthConfig:n,clientId:t,redirectUri:r,state:o}=e,i={...n.authParams,client_id:t,redirect_uri:r,response_type:"code",scope:n.scopes.join(" "),state:o};return`${n.authUrl}?${bo.stringify(i)}`}var W=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Ss(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 Xt(e,n){let t=T(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 o=En(n,t.kek);if(!o)throw new W("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:a}=o,s=M(t,i,p=>new W("plugin_not_found",p)),u=Ss(s),l=await I({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!l)throw new W("client_id_not_configured",`client_id not configured for '${i}'`);let c=ve({oauthConfig:u,clientId:l,redirectUri:r,state:n});return{plugin:i,tenantId:a,providerName:u.providerName,oauthUrl:c,state:n}}var A=class extends Error{status;code;extra;constructor(n,t,r,o={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=o}};function R(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function Co(e){let n={error:e.code,message:e.message,...e.extra};return R(e.status,n)}function ye(e){return new A(404,"not_found",e)}function oe(e,n={}){return new A(400,"bad_request",e,n)}function wo(e,n){return M(e,n,t=>ye(t))}async function Po(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}),o=O[t].integration,i=r,a;try{a=await Promise.all(o.map(d=>i[`get_${d}`]()))}catch{a=o.map(()=>null)}let s=o.filter((d,l)=>a[l]==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 To(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await Po(e,n);return{id:e.id,authType:t,configured:o,missingFields:i,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function On(){return{ok:!0}}async function Mn(e){return Promise.all(e.plugins.map(n=>To(n,e)))}async function Hn(e,n){let t=wo(e,n);return To(t,e)}async function _s(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 vo(e,n){let t=await _s(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Fn(e){let n=new Map;if(n.set("default",{id:"default",accounts:[],connectedPlugins:[]}),e.database){let t=await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id","a.dek as dek","i.name as integrationName"]).execute();for(let r of t){let o=r.tenant_id;if(!o)continue;let i=n.get(o);i||(i={id:o,accounts:[],connectedPlugins:[]},n.set(o,i));let a=!!r.dek;i.accounts.push({integrationName:r.integrationName,hasCredentials:a}),a&&i.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function Un(e,n){if(!n)throw oe("Tenant id must be a non-empty string");return vo(e,n)}async function Bn(e,n){let t=n?.id?.trim();if(!t)throw oe("Tenant id is required",{missingFields:["id"]});return vo(e,t)}async function Nn(e,n){let t=n?.trim()||"default",r={},o=await qe(e,t);for(let i of o)r[i.plugin]=yn(i);for(let i of e.plugins)i.id in r||(!i.options?.authType||!e.database||!e.kek?r[i.id]="missing_credentials":r[i.id]="not_connected");return r}async function er(e,n){if(!e.database)throw ye(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw ye(`Permission '${n}' not found`);return Dn(e,t)}function Es(e){if(!e.oauthConfig)throw oe(`Plugin '${e.id}' has no oauthConfig`)}function Ds(e){if(!e.manual)throw new A(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function nr(e){let n=Ds(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new A(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 Os(e){let n=!!e.hub,t=He(e.manual);if(!n&&!t)throw new A(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function Ao(e){if(!e.database||!e.kek)throw new A(500,"database_not_configured","A database and kek are required to issue connect links.")}async function Ms(e,n){let t=n?.plugin?.trim();if(!t)throw oe("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=wo(e,t);Es(o);let i=nr(e);Ao(e);let a=await Po(o,e);if(!a.configured)throw new A(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:a.missingFields});let s=Fe(fe(t,r),e.kek),u;try{u=new URL(i.baseUrl)}catch{throw new A(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()+Wt).toISOString()}}async function Hs(e,n,t){Ao(n);let o={tenantId:t.tenantId?.trim()||"default",oauthMode:t.oauthMode},i=t.plugin?.trim();i&&(o.plugin=i);let a=t.providerName?.trim();a&&(o.providerName=a);let s=await hn(e,o);return{connectUrl:s.connectUrl,expiresAt:s.expiresAt}}async function $n(e,n,t){return Os(n),n.hub?Hs(e,n,t):Ms(n,t)}async function Ln(e,n,t){if(n.hub&&!He(n.manual))throw new A(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw oe("state is required",{missingFields:["state"]});nr(n);try{return await Xt(e,r)}catch(o){if(o instanceof W)switch(o.code){case"invalid_state":throw oe("Invalid or expired state");case"client_id_not_configured":throw new A(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new A(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function Wn(e,n,t){if(n.hub&&!He(n.manual))throw new A(400,"hub_mode","oauthCallback is not used with hub config. Hub delivers tokens to your deliveryUrl.");let r=t?.code?.trim(),o=t?.state?.trim(),i=[];if(r||i.push("code"),o||i.push("state"),i.length)throw oe("Missing required fields",{missingFields:i});let a=nr(n),{processOAuthCallback:s}=await import("./oauth.js");try{return await s(e,{code:r,state:o,redirectUri:a.redirectUri})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw oe("Invalid or expired state");case"credentials_not_configured":throw new A(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new A(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function tr(e,n){if(!e.database)throw ye("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw ye("Permission not found");return Dn(e,t)}async function xo(e,n){return"id"in n?er(e,n.id):tr(e,n.token)}var Io=[{method:"GET",pattern:"/ok",handler:async()=>R(200,On())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>R(200,await Fn(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>R(201,await Bn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>R(200,await Un(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>R(200,await Mn(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>R(200,await Hn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>R(200,await Nn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>R(200,await er(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?R(200,await tr(e,t)):R(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>R(200,await $n(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>R(200,await Ln(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>R(200,await Wn(e,n,t))}];(()=>{let e=new Set;for(let n of Io){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Fs(e,n){let t=e.split("/").filter(Boolean),r=n.split("/").filter(Boolean);if(t.length!==r.length)return null;let o={};for(let i=0;i<t.length;i++){let a=t[i],s=r[i];if(a.startsWith(":"))o[a.slice(1)]=decodeURIComponent(s);else if(a!==s)return null}return o}function Us(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 Bs(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 A(400,"invalid_json","Request body is not valid JSON")}}var Ns="/api/corsair";function Ae(e,n={}){let t=n.basePath??Ns,r=T(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),a=Us(i.pathname,t),s=o.method.toUpperCase();if(s==="OPTIONS"||a==="/"||a==="")return await Te(e,o);if(s!=="GET"&&s!=="POST")return R(405,{error:"method_not_allowed",message:`Method ${s} not allowed`});let u=Object.fromEntries(i.searchParams);for(let d of Io){if(d.method!==s)continue;let l=Fs(d.pattern,a);if(!l)continue;let c=await Bs(o);return await d.handler({corsair:e,internal:r,req:o,params:l,query:u,body:c})}throw ye(`No route for ${s} ${a}`)}catch(i){if(n.onError){let s=await n.onError(i,o);if(s)return s}if(i instanceof A)return Co(i);let a=i instanceof Error?i.message:"Internal server error";return R(500,{error:"internal_error",message:a})}}}function $s(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,o=`${t}://${n}${r}`,i=new Headers;for(let[u,d]of Object.entries(e.headers))if(d!=null)if(Array.isArray(d))for(let l of d)i.append(u,l);else i.set(u,d);let a=e.method!=="GET"&&e.method!=="HEAD",s={method:e.method,headers:i};return a&&e.body!==void 0&&(s.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),i.has("content-type")||i.set("content-type","application/json")),new Request(o,s)}async function Ls(e,n){e.status(n.status),n.headers.forEach((r,o)=>e.setHeader(o,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function Ro(e,n){let t=Ae(e,n);return async(r,o,i)=>{try{let a=await t($s(r));await Ls(o,a)}catch(a){i(a)}}}function So(e,n){let t=Ae(e,n);return r=>t(r.req.raw)}function _o(e,n){let t=Ae(e,n);return{GET:t,POST:t,OPTIONS:t}}function Eo(e){let n={[Xe]:e};return{ok:On,tenants:{list:()=>Fn(e),create:t=>Bn(e,t),get:t=>Un(e,t)},plugins:{list:()=>Mn(e),get:t=>Hn(e,t)},connectionStatus:{get:t=>Nn(e,t?.tenantId)},permissions:{get:t=>xo(e,t)},connect:{createLink:t=>$n(n,e,t),resolve:t=>Ln(n,e,t),oauthCallback:t=>Wn(n,e,t)}}}async function Do(e,n,t,r,o="pending"){if(!e)return null;try{let i=mr(),a=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:a,updated_at:a,account_id:n,event_type:t,payload:r,status:o}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function Ws(e,n,t,r="pending"){try{let o=await e.$getAccountId();return Do(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as Oo from"https";import*as Mo from"querystring";function jn(e,n,t,r,o){let i=new URL(r.tokenUrl),a=r.tokenAuthMethod==="basic";return new Promise((s,u)=>{let d={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};a||(d.client_id=n,d.client_secret=t);let l=Mo.stringify(d),c={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(l).toString()};a&&(c.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let p=Oo.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:c},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(l),p.end()})}var Ho=" ";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 Uo(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 Bo(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function qn(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Ue(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 No(e,n){return e.description??n.description}function js(e){let n=e;for(;n;){let t=K(n),r=No(n,t);if(r)return r;let o=q(t);if(ar(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=Uo(t,o);continue}break}}function ar(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function H(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??Ue(n)[0]??"unknown");case"ZodEnum":return Ue(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=j(n);return r?H(r):"unknown"}case"ZodNullable":{let r=j(n);return`${r?H(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=j(n);return r?H(r):"unknown"}case"ZodArray":{let r=Bo(n);if(!r)return"unknown[]";let o=K(r),i=q(o)==="ZodUnion",a=H(r);return`${i?`(${a})`:a}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=qn(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([a,s])=>{let u=q(K(s));return`${u==="ZodOptional"||u==="ZodNullable"?a+"?":a}: ${H(s)}`}).join(", ")} }`}case"ZodUnion":return Ue(n).map(r=>H(r)).join(" | ");case"ZodIntersection":return`${H(n.left)} & ${H(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=Uo(n,t);return r?H(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ie(e){let n=K(e),t=q(n),r=No(e,n);switch(t){case"ZodString":return{kind:"string",optional:!1,description:r};case"ZodNumber":return{kind:"number",optional:!1,description:r};case"ZodBoolean":return{kind:"boolean",optional:!1,description:r};case"ZodLiteral":{let o=n.value??Ue(n)[0],i=typeof o=="string"||typeof o=="number"||typeof o=="boolean"?o:String(o??"");return{kind:"literal",optional:!1,description:r,value:i}}case"ZodEnum":{let o=Ue(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=j(n),i=o?ie(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=j(n),i=o?ie(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=j(n);return o?{...ie(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=Bo(n);return{kind:"array",optional:!1,description:r,items:o?ie(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=qn(e,n),i={};for(let[a,s]of Object.entries(o))i[a]=ie(s);return{kind:"object",optional:!1,description:r,fields:i}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let o=Ue(n);for(let i of o){let a=K(i);if(q(a)==="ZodObject")return{...ie(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=j(n);return o?{...ie(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function qd(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let o=t.slice(0,r),i=t.slice(r+1),a=e.find(l=>l.id===o);if(!a)return null;let s=i;s.startsWith("api.")&&(s=s.slice(4));let u=me(a.endpointMeta,s),d=me(a.endpointSchemas,s);return!u&&!d?null:{input:d?.input?ie(d.input):null,output:d?.output?ie(d.output):null,description:u?.description}}var ur=["equals","contains","startsWith","endsWith","in"],Ks=["equals","gt","gte","lt","lte","in"],qs=["equals"],Zs=["equals","before","after","between"];function $o(e){let n=K(e);switch(q(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=j(n);return r?$o(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function cr(e){let n=K(e),t=q(n);if(ar(t)){let i=j(n);return i?cr(i):{}}if(t!=="ZodObject")return{};let r=qn(e,n),o={};for(let[i,a]of Object.entries(r)){let s=$o(a);s==="string"?o[i]={type:"string",operators:ur}:s==="number"?o[i]={type:"number",operators:Ks}:s==="boolean"?o[i]={type:"boolean",operators:qs}:s==="date"&&(o[i]={type:"date",operators:Zs})}return o}function Lo(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function or(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];typeof o=="function"?t.push(i.join(".")):o!==null&&typeof o=="object"&&or(o,i,t)}}function ir(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function sr(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];ir(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&sr(o,i,t)}}function lr(e,n){if(n.length===0)return null;let[t,...r]=n,o=Object.entries(e).find(([s])=>s.toLowerCase()===t);if(!o)return null;let[i,a]=o;if(r.length===0)return ir(a)?[i]:null;if(a!==null&&typeof a=="object"&&!ir(a)){let s=lr(a,r);if(s!==null)return[i,...s]}return null}function Wo(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let i=0;i<n.length;i++){let a=" ".repeat(i+2);t.push(`${a}${n[i]}: {`)}let r=" ".repeat(n.length+2),o=r+" ";t.push(`${r}before(ctx, args) {`),t.push(`${o}return { ctx, args };`),t.push(`${r}},`),t.push(`${r}after(ctx, response) {`),t.push(`${r}},`);for(let i=n.length-1;i>=0;i--){let a=" ".repeat(i+2);t.push(`${a}},`)}return t.push(" },"),t.push("})"),t.join(`
|
|
26
|
+
`)}var Gs=new Set(rn);function xe(e,n){let t=n?.type??"api",r=n?.plugin;if(r!==void 0){let i=e.find(s=>s.id===r);if(!i)return Gs.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:xe(e);if(t==="webhooks"){if(!i.webhooks)return[];let s=[];return sr(i.webhooks,[],s),s.map(u=>`${i.id}.webhooks.${u}`)}if(t==="db"){let s=i.schema?.entities;return s?Object.keys(s).map(u=>`${i.id}.db.${u}.search`):[]}if(!i.endpoints)return[];let a=[];return or(i.endpoints,[],a),a.map(s=>`${i.id}.api.${s}`)}let o={};if(t==="webhooks")for(let i of e){if(!i.webhooks)continue;let a=[];sr(i.webhooks,[],a),o[i.id]=a.map(s=>`${i.id}.webhooks.${s}`)}else if(t==="db")for(let i of e){let a=i.schema?.entities;a&&(o[i.id]=Object.keys(a).map(s=>`${i.id}.db.${s}.search`))}else for(let i of e){if(!i.endpoints)continue;let a=[];or(i.endpoints,[],a),o[i.id]=a.map(s=>`${i.id}.api.${s}`)}return o}function me(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function Js(e,n){let t=e.toLowerCase(),r=n.toLowerCase();if(!t.startsWith(`${r}.`)){let i=t.slice(n.length+1),a=i.startsWith(".")?i.slice(1):i;return a.startsWith("api.")&&(a=a.slice(4)),{shortPath:a,lookupKey:a}}let o=e.slice(n.length+1);return o.toLowerCase().startsWith("api.")&&(o=o.slice(4)),{shortPath:o,lookupKey:o.toLowerCase()}}function rr(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 Zd(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let o=t.slice(0,r),i=t.slice(r+1),a=e.find(s=>s.id===o);if(a){if(i.startsWith("db.")){let l=i.slice(3),c=l.lastIndexOf(".");if(c!==-1){let p=l.slice(0,c),f=l.slice(c+1),g=a.schema?.entities;if(f==="search"&&g){let y=Lo(g,p);if(y){let[m,h]=y,P=cr(h),w=[`Search ${o} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${ur.join(", ")}]`];for(let[k,b]of Object.entries(P))w.push(` ${k}?: ${b.type} [${b.operators.join(", ")}]`);return w.push("}"),w.join(`
|
|
30
|
+
`)}}}return rr(xe(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let l=i.slice(9);if(a.webhooks){let c=lr(a.webhooks,l.split("."));if(c!==null){let p=c.join("."),f=me(a.webhookSchemas,p.toLowerCase()),g=f?.response?H(f.response):null,y=[];return f?.description&&y.push(f.description),f?.payload&&y.push(`payload ${Kn(Be(f.payload))}`),g&&y.push(`response: ${g}`),y.push(`usage:
|
|
31
|
+
${Wo(o,c)}`),y.join(`
|
|
32
|
+
|
|
33
|
+
`)}}return rr(xe(e,{type:"webhooks"}),"Path not found. Available webhooks")}let s=i;s.startsWith("api.")&&(s=s.slice(4));let u=me(a.endpointMeta,s),d=me(a.endpointSchemas,s);if(u||d){let l=[],c=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),p=[u?.description,c].filter(Boolean).join(" ");return p&&l.push(p),d?.input&&l.push(`input ${Kn(Be(d.input))}`),d?.output&&l.push(`output ${Kn(Be(d.output))}`),l.join(`
|
|
34
|
+
|
|
35
|
+
`)}}}return rr(xe(e),"Path not found. Available operations")}function Fo(e){let n=e;for(;;){let t=K(n),r=q(t);if(ar(r)){let o=j(t);if(!o)return n;n=o;continue}return n}}function Be(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=Fo(e),t=K(n);if(q(t)==="ZodObject"){let o=qn(n,t),i=[];for(let[a,s]of Object.entries(o)){let u=K(s),d=q(u),l=d==="ZodOptional"||d==="ZodNullable",c=Fo(s),p=js(s);i.push({key:a,optional:l,type:H(c),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:H(n)}}function Kn(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=Ho.repeat(n+1),r=Ho.repeat(n);return`{
|
|
36
|
+
${e.fields.map(i=>{let a=i.optional?`${i.key}?`:i.key,s=i.description?` // ${i.description}`:"";return`${t}${a}: ${i.type}${s}`}).join(`
|
|
37
|
+
`)}
|
|
38
|
+
${r}}`}return"unknown"}function zs(e,n){let t=xe(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(l=>l.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let l of t){let{shortPath:c,lookupKey:p}=Js(l,n),f=me(r.endpointMeta,p),g=me(r.endpointSchemas,p);!f&&!g||o.push({path:l,shortPath:c,description:f?.description,riskLevel:f?.riskLevel,irreversible:f?.irreversible,input:Be(g?.input),output:Be(g?.output)})}o.sort((l,c)=>l.path.localeCompare(c.path));let i=[],a=xe(e,{plugin:n,type:"webhooks"});if(Array.isArray(a)&&r.webhooks)for(let l of a){let p=l.toLowerCase().slice(n.length+1),f=p.startsWith(".")?p.slice(1):p;if(!f.startsWith("webhooks."))continue;let g=f.slice(9),y=lr(r.webhooks,g.split("."));if(y===null)continue;let m=y.join("."),h=me(r.webhookSchemas,m.toLowerCase()),P=h?.response?H(h.response):void 0;i.push({path:l,description:h?.description,payload:Be(h?.payload),responseType:P,usageExample:Wo(n,y)})}i.sort((l,c)=>l.path.localeCompare(c.path));let s=[],u=xe(e,{plugin:n,type:"db"}),d=r.schema?.entities;if(Array.isArray(u)&&d)for(let l of u){let p=l.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 m=g.slice(0,y);if(g.slice(y+1)!=="search")continue;let P=Lo(d,m);if(!P)continue;let[w,k]=P,b=cr(k),C=Object.entries(b).map(([B,_])=>({field:B,type:_.type,operators:_.operators}));s.push({path:l,entityName:w,filters:[{field:"entity_id",type:"string",operators:ur},...C]})}return s.sort((l,c)=>l.path.localeCompare(c.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:s}}}function jo(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function Vs(e,n){let t=jo(e,n);if(!t)return null;let r=e[t];if(!r?.pluginTenantWebhookMatcher)return null;let o=r.pluginTenantWebhookMatcher(n);return o?{plugin:t,tenantMatch:o}:null}function Ys(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 qo(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 en(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function Qs(e){return en(e.body)}function Zo(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return Zn(Array.isArray(r)?r:[r])}function Go(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let d=Zn(Array.isArray(u)?u:[u]);if(d)return decodeURIComponent(d)}let r=Zo({query:e.query},"validationToken");if(r)return r;let o=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let u of o){let d=n[u],l=Array.isArray(d)?d[0]:d;if(!(!l||typeof l!="string"))try{let p=(l.startsWith("http")?new URL(l):new URL(`https://example.invalid${l.startsWith("/")?l:`/${l}`}`)).searchParams.get("validationToken");if(p?.trim())return p.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,a=en(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return Zn([a?.validationToken])??null}function Xs(e){if(Go(e))return!0;let n=en(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=qo(n);if(t)return t}}function ea(e){let t=en(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Xe=Symbol.for("corsair:internal");function Ur(e){let n=e.database?pr(e.database):void 0,t=n&&e.kek?ho(e.plugins,n,e.kek):_n(!!n,!!e.kek),r=ko(e),o={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?on(e.hub):void 0},i=yo(n),a=Eo(o);if(e.multiTenancy)return Object.assign({withTenant:u=>{if(!u)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let d=Qt(e.plugins,{database:n,tenantId:u,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub});return Object.assign(d,{[Xe]:o})},keys:t,permissions:i,manage:a},{[Xe]:o});let s=Qt(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub});return Object.assign({},s,{keys:t,permissions:i,manage:a,[Xe]:o})}var U=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Jo(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 na(e,n,t,r){let o=kr(e),i=await o.integrations.findByName(n);if(!i)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.accounts.findOne({tenant_id:t,integration_id:i.id}))return;let s=X(),u=await ee(s,r);await o.accounts.create({tenant_id:t,integration_id:i.id,config:{},dek:u})}async function et(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,a=T(e,()=>new U("invalid_corsair_instance","Invalid corsair instance"));if(!a.database)throw new Error("No database configured on corsair instance");let s=M(a,n,p=>new U("plugin_not_found",p)),u=Jo(s),l=await I({authType:"oauth_2",integrationName:n,kek:a.kek,database:a.database}).get_client_id();if(!l)throw new Error(`client_id not configured for '${n}'`);if(i){let p=new URL(ve({oauthConfig:u,clientId:l,redirectUri:o,state:""}));return p.searchParams.delete("state"),{url:p.toString(),state:""}}let c=Fe(fe(n,r),a.kek);return{url:ve({oauthConfig:u,clientId:l,redirectUri:o,state:c}),state:c}}async function Ve(e,n){let{code:t,state:r,redirectUri:o}=n,i=T(e,()=>new U("invalid_corsair_instance","Invalid corsair instance")),a=En(r,i.kek);if(!a)throw new U("invalid_state","Invalid or tampered state parameter");let{plugin:s,tenantId:u}=a;if(!i.database)throw new U("no_database","No database configured on corsair instance");let d=M(i,s,m=>new U("plugin_not_found",m)),l=Jo(d),c=I({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),p=await c.get_client_id(),f=await c.get_client_secret();if(!p||!f)throw new U("credentials_not_configured",`Credentials not configured for '${s}'`);await na(i.database,s,u,i.kek);let g=await jn(t,p,f,l,o);if(!g.access_token)throw new U("no_access_token",`No access_token returned from ${l.providerName}`);let y=S({authType:"oauth_2",integrationName:s,tenantId:u,kek:i.kek,database:i.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 m=await wn(i.plugins,s,g);if(m)try{let h=d.authConfig?.oauth_2?.account??[];await De({database:i.database,kek:i.kek,pluginId:s,tenantId:u,link:m,authType:"oauth_2",extraAccountFields:h})}catch(h){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${u}':`,h)}}catch(m){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${u}':`,m)}return{plugin:s,tenantId:u}}export{br as a,ae as b,Le as c,ue as d,on as e,J as f,sn as g,Ie as h,an as i,un as j,cn as k,ln as l,wr as m,dn as n,Re as o,X as p,ee as q,L as r,zn as s,je as t,le as u,ne as v,Ke as w,I as x,S as y,Dr as z,Or as A,fe as B,Lt as C,De as D,at as E,Pn as F,zr as G,ve as H,U as I,et as J,Ve as K,Xn as L,Hi as M,hn as N,jr as O,Kr as P,ot as Q,it as R,qr as S,Zr as T,de as U,Ce as V,pe as W,Oe as X,Tn as Y,ct as Z,Me as _,lt as $,dt as aa,pt as ba,gt as ca,Xr as da,te as ea,An as fa,xn as ga,ge as ha,Pe as ia,Je as ja,ze as ka,In as la,ht as ma,kt as na,Ct as oa,wt as pa,Pt as qa,Tt as ra,vt as sa,Te as ta,re as ua,At as va,io as wa,Rn as xa,Sn as ya,ao as za,xt as Aa,It as Ba,Rt as Ca,St as Da,_t as Ea,Et as Fa,Dt as Ga,Ot as Ha,Mt as Ia,Ht as Ja,Ft as Ka,Ut as La,Bt as Ma,Nt as Na,$t as Oa,Xt as Pa,Ae as Qa,Ro as Ra,So as Sa,_o as Ta,Do as Ua,Ws as Va,jn as Wa,qd as Xa,xe as Ya,Zd as Za,Kn as _a,zs as $a,jo as ab,Vs as bb,Ys as cb,Ko as db,qo as eb,en as fb,Qs as gb,Zo as hb,Go as ib,Xs as jb,Zn as kb,ea as lb,Xe as mb,Ur as nb};
|
package/dist/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$a as
|
|
1
|
+
import{$a as v,A as o,Pa as q,Ua as r,Va as s,Wa as t,_a as u,a,ab as w,b,bb as x,cb as y,db as z,eb as A,fb as B,gb as C,hb as D,ib as E,jb as F,kb as G,lb as H,mb as I,nb as J,p as d,q as e,r as f,s as g,t as h,u as i,ua as p,v as j,w as k,x as l,y as m,z as n}from"./chunk-FPKQA47O.js";import{g as c}from"./chunk-67EXGXPK.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,9 +1,9 @@
|
|
|
1
1
|
export { f as formatProviderDisplayName } from './constants-DnSLjl7e.js';
|
|
2
2
|
import { g as HubOAuthMode, h as HubConnectSessionResult, i as HubPermissionSessionResult, H as HubConfig, f as HubConfigInput, j as HubConnectSessionInput, k as HubListProjectConnectionsInput, A as AccountKeyManagerFor, l as HubPermissionSessionInput } from './types-BZ-KI4kd.js';
|
|
3
3
|
export { D as DEFAULT_HUB_API_URL, m as HubEnvironmentSlug } from './types-BZ-KI4kd.js';
|
|
4
|
-
import { e as TunnelType, c as ProcessCorsairRequest } from './index-
|
|
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-
|
|
6
|
-
export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-
|
|
4
|
+
import { e as TunnelType, c as ProcessCorsairRequest } from './index-BHI3widx.js';
|
|
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-BHI3widx.js';
|
|
6
|
+
export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-DW81SP-j.js';
|
|
7
7
|
|
|
8
8
|
type ConnectAuthKind = 'oauth' | 'api_key' | 'bot_token';
|
|
9
9
|
type ConnectPluginManifestEntry = {
|
|
@@ -19,10 +19,12 @@ type ConnectPluginManifestEntry = {
|
|
|
19
19
|
type HubProjectConnection = {
|
|
20
20
|
tenantId: string;
|
|
21
21
|
plugin: string;
|
|
22
|
-
status: 'pending' | 'connected' | 'failed';
|
|
23
22
|
authKind: ConnectAuthKind;
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
status: ConnectAuthStatusLevel;
|
|
24
|
+
connected: boolean;
|
|
25
|
+
verified: boolean;
|
|
26
|
+
missingFields: string[];
|
|
27
|
+
reportedAt: string;
|
|
26
28
|
};
|
|
27
29
|
type ConnectAuthFieldStatus = {
|
|
28
30
|
name: string;
|
|
@@ -107,11 +109,6 @@ declare function getConnectStatusForTenant(corsair: unknown, tenantId: string, o
|
|
|
107
109
|
|
|
108
110
|
declare function listHubProjectConnections(corsair: unknown, input: HubListProjectConnectionsInput): Promise<HubProjectConnection[]>;
|
|
109
111
|
|
|
110
|
-
declare function resolveHubDeliveryUrl(input?: {
|
|
111
|
-
deliveryUrl?: string;
|
|
112
|
-
deliveryPath?: string;
|
|
113
|
-
}): string;
|
|
114
|
-
|
|
115
112
|
/**
|
|
116
113
|
* Server (production) delivery — hub POSTs a signed JSON envelope to the app's public delivery URL.
|
|
117
114
|
*
|
|
@@ -305,6 +302,11 @@ declare function processManagedOAuthDelivery(corsair: unknown, options: ProcessM
|
|
|
305
302
|
declare function createHubPermissionSession(hub: HubConfig, input: HubPermissionSessionInput): Promise<HubPermissionSessionResult>;
|
|
306
303
|
declare function formatHubApprovalMessage(approvalUrl: string): string;
|
|
307
304
|
|
|
305
|
+
declare function resolveHubDeliveryUrl(input?: {
|
|
306
|
+
deliveryUrl?: string;
|
|
307
|
+
deliveryPath?: string;
|
|
308
|
+
}): string;
|
|
309
|
+
|
|
308
310
|
declare function createHubRouteHandlers(corsair: unknown): {
|
|
309
311
|
delivery: (request: Request) => Promise<Response>;
|
|
310
312
|
deliveryOptions: (request: Request) => Promise<Response>;
|
package/dist/hub.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as C,Aa as
|
|
1
|
+
import{$ as C,Aa as V,Ba as W,Ca as X,Da as Y,Ea as Z,Fa as _,Ga as $,Ha as aa,Ia as ba,Ja as ca,Ka as da,La as ea,Ma as fa,N as o,Na as ga,O as p,Oa as ha,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 D,b as a,ba as E,c as b,ca as F,d as c,e as d,ea as G,f as e,fa as H,g as f,ga as I,h as g,ha as J,i as h,j as i,k as j,l as k,m as l,n as m,o as n,oa as K,pa as L,qa as M,ra as N,sa as O,ta as P,va as Q,wa as R,xa as S,ya as T,za as U}from"./chunk-FPKQA47O.js";import"./chunk-67EXGXPK.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{v as BROWSER_DELIVERY_TTL_MS,b as DEFAULT_HUB_API_URL,c as HubNotConfiguredError,x as ManagedOAuthDeliveryError,w as SIGNED_TUNNEL_REPLAY_WINDOW_MS,R as attachManagedRefreshAuth,H as buildBrowserDeliveryRedirectUrl,V as createConnectSessionJti,_ as createConnectTokenJti,o as createHubConnectSession,S as createHubPermissionSession,U as createHubRouteHandlers,ea as createPermissionSessionJti,G as createSignedTokenJti,Z as decodeConnectSessionTokenFromPath,da as decodeConnectTokenFromPath,ha as decodePermissionTokenFromPath,F as deliverSignedEnvelope,ca as encodeConnectTokenForPath,T as formatHubApprovalMessage,a as formatProviderDisplayName,E as formatServerDeliveryError,W as getConnectSessionExpiryMs,p as getConnectStatusForTenant,$ as getConnectTokenExpiryMs,e as getHubConfig,Q as getManagedAccessToken,K as handleHubDeliveryGet,L as handleHubDeliveryPost,N as handleHubDeliveryRequest,M as hubDeliveryToResponse,g as inferHubEnvironmentSlug,r as isLoopbackUrl,D as isServerDeliveryAckSuccessful,q as listHubProjectConnections,d as normalizeHubConfig,h as parseConnectSessionResponse,l as parseConnectStatusResponse,m as parseHubApiErrorBody,k as parseOAuthRefreshResponse,j as parsePermissionSessionResponse,i as parseProjectConnectionsResponse,C as parseServerDeliveryAckBody,y as processManagedOAuthDelivery,s as resolveDeliveryTransport,n as resolveHubDeliveryUrl,f as resolveHubOAuthCallbackUrl,O as respondToHubDelivery,P as respondToHubDeliveryFromRequest,I as signBrowserDeliveryToken,X as signConnectSessionToken,aa as signConnectToken,z as signDeliveryEnvelope,fa as signPermissionToken,t as usesBrowserDelivery,u as validateProductionDeliveryUrl,J as verifyBrowserDeliveryToken,Y as verifyConnectSessionToken,ba as verifyConnectToken,A as verifyDeliveryEnvelope,ga as verifyPermissionToken,B as verifySignedTunnelDelivery};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Each value maps to a handler in the app's tunnel/delivery endpoint.
|
|
8
8
|
*/
|
|
9
|
-
type TunnelType = 'oauth.callback' | 'oauth.tokens' | 'webhook' | 'permission.approve' | 'permission.deny' | 'auth.credentials' | '
|
|
9
|
+
type TunnelType = 'oauth.callback' | 'oauth.tokens' | 'webhook' | 'permission.approve' | 'permission.deny' | 'auth.credentials' | 'integration.credentials' | 'run';
|
|
10
10
|
/**
|
|
11
11
|
* JSON body of a server-side delivery POST from the hub.
|
|
12
12
|
*
|
|
@@ -23,7 +23,7 @@ type TunnelEnvelope<TPayload = unknown> = {
|
|
|
23
23
|
*
|
|
24
24
|
* Subset of {@link TunnelType} — values delivered via browser redirect rather than POST.
|
|
25
25
|
*/
|
|
26
|
-
type BrowserDeliveryMode = 'oauth.callback' | 'oauth.tokens' | 'permission.approve' | 'permission.deny' | '
|
|
26
|
+
type BrowserDeliveryMode = 'oauth.callback' | 'oauth.tokens' | 'permission.approve' | 'permission.deny' | 'auth.credentials';
|
|
27
27
|
/**
|
|
28
28
|
* Decoded payload inside a browser delivery token (`?d=` query param).
|
|
29
29
|
*
|
|
@@ -70,8 +70,6 @@ type BrowserDeliveryPayload = {
|
|
|
70
70
|
hubOrigin?: string;
|
|
71
71
|
/** Optional correlation id for debugging. */
|
|
72
72
|
requestId?: string;
|
|
73
|
-
/** Plugins to include in a connect status introspection response. */
|
|
74
|
-
statusPlugins?: string[];
|
|
75
73
|
/** API key / bot token fields (`deliveryMode: auth.credentials`). */
|
|
76
74
|
credentials?: Record<string, string>;
|
|
77
75
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { a3 as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPer
|
|
|
6
6
|
import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-DU4saqFg.js';
|
|
7
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-DU4saqFg.js';
|
|
8
8
|
export { SetupCorsairOptions, setupCorsair } from './setup.js';
|
|
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-
|
|
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-BHI3widx.js';
|
|
10
10
|
import { B as BaseProviders } from './constants-DnSLjl7e.js';
|
|
11
11
|
export { R as ResolveAccountFromWebhookLinkInput, W as WebhookTenantLink, r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-CZFbUeH1.js';
|
|
12
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-cJXSdmph.js';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as N,b as j}from"./chunk-XLNT2UI2.js";import{
|
|
1
|
+
import{a as N,b as j}from"./chunk-XLNT2UI2.js";import{D as y,E as h,F as k,G as x,L as P,Pa as I,Qa as O,Ra as R,Sa as T,Ta as A,Xa as l,Ya as c,Za as d,_a as m,ab as L,bb as W,cb as F,da as b,db as v,eb as E,fb as _,gb as $,kb as M,lb as D,mb as g,na as S,nb as H,ua as w}from"./chunk-FPKQA47O.js";import"./chunk-67EXGXPK.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.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{B as a,C as b,H as c,I as d,J as e,K as f}from"./chunk-FPKQA47O.js";import"./chunk-67EXGXPK.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.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./chunk-N2XRSSRL.js";import{
|
|
1
|
+
import"./chunk-N2XRSSRL.js";import{n as o,o as e,p as n,q as s}from"./chunk-67EXGXPK.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.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{L as a,M as b}from"./chunk-FPKQA47O.js";import"./chunk-67EXGXPK.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as applySetupCredentials,a as setupCorsair};
|
package/dist/tunnel.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { B as BrowserDeliveryPayload } from './index-
|
|
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-
|
|
1
|
+
import { B as BrowserDeliveryPayload } from './index-BHI3widx.js';
|
|
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-BHI3widx.js';
|
|
3
3
|
export { r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-CZFbUeH1.js';
|
|
4
|
-
export { v as verifyBrowserDeliveryToken } from './browser-delivery-
|
|
4
|
+
export { v as verifyBrowserDeliveryToken } from './browser-delivery-DW81SP-j.js';
|
|
5
5
|
import './constants-DnSLjl7e.js';
|
|
6
6
|
import './index-BjEnNYJD.js';
|
|
7
7
|
import 'zod';
|
|
@@ -14,10 +14,9 @@ import './orm.js';
|
|
|
14
14
|
import './types-BZ-KI4kd.js';
|
|
15
15
|
import './types-cJXSdmph.js';
|
|
16
16
|
|
|
17
|
-
declare function isConnectStatusBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
18
17
|
declare function isAuthCredentialsBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
19
18
|
declare function isPermissionBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
20
19
|
declare function isManagedBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
21
20
|
declare function isByoOAuthBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
22
21
|
|
|
23
|
-
export { BrowserDeliveryPayload, isAuthCredentialsBrowserDelivery, isByoOAuthBrowserDelivery,
|
|
22
|
+
export { BrowserDeliveryPayload, isAuthCredentialsBrowserDelivery, isByoOAuthBrowserDelivery, isManagedBrowserDelivery, isPermissionBrowserDelivery };
|
package/dist/tunnel.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as a,E as b,F as c,G as d,ha as e,ia as f,ja as g,ka as h,la as i,ma as j,na as k}from"./chunk-FPKQA47O.js";import"./chunk-67EXGXPK.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{j as applyPermissionDecision,f as isAuthCredentialsBrowserDelivery,i as isByoOAuthBrowserDelivery,h as isManagedBrowserDelivery,g as isPermissionBrowserDelivery,k as processCorsair,b as resolveAccountFromWebhookLink,d as resolveTenantFromWebhookLink,c as resolveTenantIdFromWebhookLink,a as setWebhookTenantLink,e as verifyBrowserDeliveryToken};
|
package/package.json
CHANGED
package/dist/chunk-FLNFC4KL.js
DELETED
|
@@ -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 _(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};
|
package/dist/chunk-IGJCF7OM.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import{a as ie,b as dr,c as T,d as $,e as pr,f as G,g as D,h as O,i as nn,j as gr,k as Jn,l as fr,m as yr}from"./chunk-FLNFC4KL.js";import{a as lr}from"./chunk-IGGCNGU2.js";var tn=["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"],mr={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 se(e){let n=mr[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var Le="https://auth.corsair.dev";var he=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function rn(e){let n=(e.apiUrl?.trim()||Le).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim();if(!t||!r)throw new Error("Hub config requires non-empty projectApiKey and signingSecret");return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,"")}}function Ko(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function Y(e){let n=T(e).hub;if(!n||!Ko(n))throw new he;return n}function hr(e){return e.replace(/\/$/,"")}function on(e){return e.oauthCallbackUrl?hr(e.oauthCallbackUrl.trim()):`${hr(e.apiUrl)}/oauth/callback`}function xe(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";throw new Error("Hub API key must start with ck_dev_ (development) or ck_prod_ (production)")}function v(e){return typeof e=="string"&&e.length>0}function qo(e){return e==="pending"||e==="connected"||e==="failed"}function Zo(e){return e==="oauth"||e==="api_key"||e==="bot_token"}function sn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!v(n.connectUrl)||!v(n.token)||!v(n.projectId))throw new Error("Hub API returned an incomplete connect session (expected connectUrl, token, and projectId)");let t={connectUrl:n.connectUrl,token:n.token,projectId:n.projectId,environmentId:v(n.environmentId)?n.environmentId:n.projectId};return v(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function an(e){if(!Array.isArray(e))throw new Error("Hub API returned an invalid connections response (expected array)");let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;!v(r.tenantId)||!v(r.plugin)||!qo(r.status)||!Zo(r.authKind)||n.push({tenantId:r.tenantId,plugin:r.plugin,status:r.status,authKind:r.authKind,connectedAt:v(r.connectedAt)?r.connectedAt:null,expiresAt:v(r.expiresAt)?r.expiresAt:null})}return n}function un(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!v(n.approvalUrl)||!v(n.token)||!v(n.projectId)||!v(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 cn(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(v(n.access_token))return{access_token:n.access_token,refresh_token:v(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:v(n.scope)?n.scope:void 0};throw new Error(v(n.error)?v(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Go(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function Jo(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;v(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 zo(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 kr(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!v(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(!v(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=Jo(i.fields),s=Go(i.missingRequiredFields),u=zo(i.status,i.connected,a,s);t.push({plugin:i.plugin,providerName:v(i.providerName)?i.providerName:i.plugin,authKind:o,status:u,connected:i.connected,fields:a,missingRequiredFields:s})}return{tenantId:n.tenantId,plugins:t}}function ln(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function br(e){return e.replace(/\/$/,"")}async function Cr(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 wr(e,n,t){if(n===404&&t)return t;let r=ln(e);return r||`Hub API returned HTTP ${n}`}async function Re(e){let n=br(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 Cr(t);if(!t.ok)throw new Error(wr(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function Pr(e){let n=br(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`}}),r=await Cr(t);if(!t.ok)throw new Error(wr(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as Tr,createDecipheriv as vr,randomBytes as dn,scrypt as Vo}from"crypto";import{promisify as Yo}from"util";var Ar=Yo(Vo),pn="aes-256-gcm",xr=12,gn=16,Qo=16,We=32;function Q(){return dn(We).toString("base64")}async function X(e,n){let t=dn(Qo),r=await Ar(n,t,We),i=dn(xr),o=Tr(pn,r,i,{authTagLength:gn}),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 N(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"),l=Buffer.from(o,"base64"),d=await Ar(n,a,We),c=vr(pn,d,s,{authTagLength:gn});return c.setAuthTag(u),Buffer.concat([c.update(l),c.final()]).toString("utf8")}function zn(e,n){let t=Buffer.from(n,"base64"),r=dn(xr),i=Tr(pn,t,r,{authTagLength:gn}),o=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[r.toString("base64"),a.toString("base64"),o.toString("base64")].join(":")}function je(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"),l=vr(pn,o,a,{authTagLength:gn});return l.setAuthTag(s),Buffer.concat([l.update(u),l.final()]).toString("utf8")}function ae(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=zn(i,n);return t}function ee(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=je(i,n);return t}function Ke(e,n,t){let r=ee(e,n);return ae(r,t)}function Rr(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 Vn=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function _(e){let{authType:n,integrationName:t,kek:r,database:i,extraIntegrationFields:o=[]}=e,a=[...D[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:Vn(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}},l=null,d=async()=>{if(l)return l;let f=await u.getIntegration();if(!f.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await N(f.dek,r),l},c=async()=>{let f=await u.getIntegration(),y=await d(),m=f.config;return!m||Object.keys(m).length===0?{}:ee(m,y)};return{get_dek:d,issue_new_dek:async()=>{let f=await u.getIntegration(),y=Q(),m={};if(f.dek){let P=await N(f.dek,r),w=f.config;w&&Object.keys(w).length>0&&(m=Ke(w,P,y))}let h=await X(y,r);return await u.updateIntegration({config:m,dek:h}),l=y,y},...Rr(c,async f=>{let y=await d(),m;try{m=await c()}catch(w){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,w),m={}}let h={...m};for(let[w,k]of Object.entries(f))k===null?delete h[w]:h[w]=k;let P=ae(h,y);await u.updateIntegration({config:P})},a)}}function R(e){let{authType:n,integrationName:t,tenantId:r,kek:i,database:o,extraAccountFields:a=[]}=e,s=[...D[n].account,...a],u=null,l=null,d=async()=>{if(l)return l;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 l={id:k.id,config:Vn(k.config),dek:k.dek??null},l},c={kek:i,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(u)return u;let k=await d(),b=await o.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",k.id).executeTakeFirst();if(!b)throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`);return u={id:b.id,config:Vn(b.config),dek:b.dek??null},u},updateAccount:async k=>{let b=await c.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","=",b.id).execute(),u=null}},p=null,g=null,f=async()=>{if(p)return p;let k=await c.getAccount();if(!k.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return p=await N(k.dek,i),p},y=async()=>{if(g)return g;let k=await c.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return g=await N(k.dek,i),g},m=async()=>{let k=await c.getAccount(),b=await f(),C=k.config;return!C||Object.keys(C).length===0?{}:ee(C,b)},h=async()=>{let k=await c.getIntegration(),b=await y(),C=k.config;return!C||Object.keys(C).length===0?{}:ee(C,b)},w={get_dek:f,issue_new_dek:async()=>{let k=await c.getAccount(),b=Q(),C={};if(k.dek){let S=await N(k.dek,i),E=k.config;E&&Object.keys(E).length>0&&(C=Ke(E,S,b))}let F=await X(b,i);return await c.updateAccount({config:C,dek:F}),p=b,b},...Rr(m,async k=>{let b=await f(),C;try{C=await m()}catch(E){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,E),C={}}let F={...C};for(let[E,I]of Object.entries(k))I===null?delete F[E]:F[E]=I;let S=ae(F,b);await c.updateAccount({config:S})},s)};return n==="oauth_2"&&(w.get_integration_credentials=async()=>{let k=await h();return{client_id:k.client_id||null,client_secret:k.client_secret||null,redirect_url:k.redirect_url??null}}),w}async function Sr(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=Q(),o=await X(i,t);return await e.db.updateTable("corsair_integrations").set({dek:o,updated_at:new Date}).where("id","=",r.id).execute(),i}async function Ir(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=Q(),s=await X(a,r);return await e.db.updateTable("corsair_accounts").set({dek:s,updated_at:new Date}).where("id","=",o.id).execute(),a}var Xo=new Set(["webhook_signature","expires_at","scope","redirect_url"]);function Se(e){return Xo.has(e)}function ei(e,n){return Se(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function ni(e){return!Se(e)}function ti(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 ri(e,n){return ti(e).every(r=>n.find(o=>o.level==="account"&&o.name===r)?.configured??!1)}async function _r(e,n){if(!e)return!1;let t=G(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function oi(e,n){let r=e.authConfig?.[n]?.integration??[];return[...D[n].integration,...r]}function ii(e,n){let r=e.authConfig?.[n]?.account??[];return[...D[n].account,...r]}function si(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:ri(n,t),fields:t,missingRequiredFields:r}}async function fn(e,n,t){let r=O(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=_({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:a}),l=R({authType:r,integrationName:n.id,tenantId:i,kek:e.kek,database:e.database,extraAccountFields:s}),d=oi(n,r),c=ii(n,r),p=[];for(let g of d)p.push({name:g,level:"integration",required:ei(r,g),configured:await _r(u,g)});for(let g of c)p.push({name:g,level:"account",required:ni(g),configured:await _r(l,g)});return si(n.id,r,p)}async function qe(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 fn(e,a,r);s&&o.push(s)}return o}function yn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}import{ZodBoolean as ui,ZodDate as ci,ZodEnum as li,ZodNullable as di,ZodNumber as pi,ZodObject as gi,ZodOptional as fi,ZodRecord as yi,ZodString as mi,ZodType as hi}from"zod";var ai={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=ai;async function Dr(e,n){let t=[],r=n?.silent??!1,i=g=>{t.push(g),r||console.log(g)},o=g=>{t.push(g),r||console.warn(g)},a=n?.caller??"script",s=dr(e);if(!s)throw new Error("setupCorsair: invalid corsair instance");if(!s.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u=bi(e,s.plugins,n),l={...s,database:s.database},d=l.database.db;await Pi(d,o);let c=await Ti(d,l,u.tenantId,u.provisionAccounts,i);n?.credentials&&Object.keys(n.credentials).length>0&&await xi(e,u,n.credentials,l,i,o);let p=await Si(c,u,i,a);if(n?.backfill){i("[corsair:setup] Starting backfill...");let g=Mr({plugins:s.plugins,database:d,kek:s.kek,multiTenancy:!0}).withTenant(u.tenantId);await Ii(g,s.plugins,p,i,o),i("[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([...D[n][t],...r])}function ki(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=O(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 bi(e,n,t){let r=pr(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&&ki(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 Or(e,n){return ie(e)?n===0?!0:Object.values(e).every(t=>Or(t,n-1)):!1}function Ci(e){return Or(e,4)}var wi={...fr};function mn(e){if(e instanceof gi){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof hi?mn(r):"unknown";return n}return e instanceof di?`${mn(e.unwrap())} | null`:e instanceof fi?`${mn(e.unwrap())} | undefined`:e instanceof li?e.options.join(" | "):e instanceof mi?"string":e instanceof pi?"number":e instanceof ui?"boolean":e instanceof ci?"date":e instanceof yi?"jsonb":"unknown"}async function Pi(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(i=>i.name));for(let[i,o]of Object.entries(wi))r.has(i)||n(`[corsair:setup] Table "${i}" does not exist. Run your database migrations before calling setupCorsair.
|
|
3
|
-
Schema: ${JSON.stringify(mn(o),null,2)}`)}async function Ti(e,n,t,r,i){let o=new Date,a=new Map;for(let s of n.plugins){let u=s.id,l=O(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 c=l?s.authConfig?.[l]?.integration??[]:[],p=l?s.authConfig?.[l]?.account??[]:[],g=l&&d?_({authType:l,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:c}):void 0;if(d&&!d.dek&&g&&(await g.issue_new_dek(),i(`[corsair:setup] Issued integration DEK: ${u}`)),!d||!l||!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 m=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:m,tenant_id:t,integration_id:d.id,config:{},created_at:o,updated_at:o}).execute(),y=await e.selectFrom("corsair_accounts").selectAll().where("id","=",m).executeTakeFirst(),i(`[corsair:setup] Created account: ${u}`)}f=y&&R({authType:l,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:l,integration:g,account:f,integrationFields:[...D[l].integration,...c],accountFields:r?[...D[l].account,...p]:[]})}return a}function vi(e){if(!ie(e))return;let n=e.keys;return ie(n)?n:void 0}function Ai(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function xi(e,n,t,r,i,o){let a=vi(e),s=n.provisionAccounts?Ai(e,n.tenantId):void 0;for(let[u,l]of Object.entries(t)){let d=r.plugins.find(h=>h.id===u);if(!d){o(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let c=O(d);if(!c){o(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let p=Qn(d,c,"integration"),g=Qn(d,c,"account"),f=a?.[u],y=s?.[u],m=ie(y)?y.keys:void 0;for(let[h,P]of Object.entries(l))if(P){if(p.has(h)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${u}.${h}' 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 w=G(f,`set_${h}`);if(!w){o(`[corsair:setup] Cannot set integration field '${h}' for '${u}'.`);continue}await w(P),i(`[corsair:setup] Set ${u} integration.${h}`);continue}if(g.has(h)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${u}.${h}' on a multi-tenant instance`);let w=G(m,`set_${h}`);if(!w){o(`[corsair:setup] Cannot set account field '${h}' for '${u}'.`);continue}await w(P),i(`[corsair:setup] Set ${u} account.${h} (tenant=${n.tenantId})`);continue}o(`[corsair:setup] Unknown credential field '${h}' for plugin '${u}'.`)}}}var Er=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Ri(e,n,t,r,i,o,a,s,u){let l=[],d=[];for(let p of i){if(Er.has(p))continue;let g=G(t,`get_${p}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||l.push(p)}if(r&&o.length>0)for(let p of o){if(Er.has(p))continue;let g=G(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 c=l.length===0&&d.length===0;if(c)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=[...l,...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 l)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 c}async function Si(e,n,t,r){let i=new Set;for(let o of e.values())await Ri(o.pluginId,o.authType,o.integration,o.account,o.integrationFields,o.accountFields,n,t,r)&&i.add(o.pluginId);return i}async function Ii(e,n,t,r,i){if(!Ci(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 l=ie(e)?e[s]:void 0,d=ie(l)?l.api:void 0;if(d)for(let[c,p]of Object.entries(u))for(let[g,f]of Object.entries(p)){r(`[corsair:setup] Backfilling ${s} \u203A ${c}.${g}...`);try{let y=ie(d)?d[c]:void 0;await G(y,g)?.(f)}catch(y){i(`[corsair:setup] ${s} \u203A ${c}.${g} failed: `+(y instanceof Error?y.message:String(y)))}}}}async function Ie(e,n){if(!T(e).database)throw new Error("A database must be configured to provision Corsair for connect");await Dr(e,{tenantId:n,silent:!0})}var _i=Symbol.for("corsair:internal"),Ei=new Set(["access_token","refresh_token","expires_at","scope"]);function Di(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Oi(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!Se(t)&&!Ei.has(t)):n.filter(t=>!Se(t))}function Hr(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:!1}}function Fr(e){return{[_i]:Hr(e)}}async function et(e,n,t={}){let r=on(e.hub),i=[],o=t.pluginIds?new Set(t.pluginIds):null,a=Hr(e),s=Fr(e);for(let u of e.plugins){if(o&&!o.has(u.id))continue;let l=O(u);if(!l)continue;let d=Di(l),c=t.providerNameOverrides?.[u.id]??se(u.id),p=await fn(a,u,n),g=nn(u,l),f=Oi(l,g),y={plugin:u.id,providerName:c,authKind:d,alreadyConfigured:p?.connected??!1};if(f.length>0&&(y.credentialFields=f),d==="oauth"){let h=t.oauthModeOverrides?.[u.id]??(l==="managed"?"managed":"byo");if(y.oauthMode=h,!t.skipOAuthUrlGeneration&&h!=="managed")try{let P=await Xn(s,u.id,{tenantId:n,redirectUri:r,hubConnect:!0});y.oauthUrl=P.url}catch(P){y.setupError=P instanceof Error?P.message:`Could not prepare OAuth for ${u.id}`}}i.push(y)}return i}async function nt(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await Ie(Fr(e),n)}var Mi="3000",Hi="/api/corsair";function tt(e){return e.replace(/\/$/,"")}function Fi(e,n){return`${tt(e)}${n}`}function Ur(e){return e.startsWith("http")?e:`https://${e}`}function _e(e){let n=e?.deliveryUrl?.trim();if(n)return tt(n);let t=e?.deliveryPath?.trim()||Hi,r=t.startsWith("/")?t:`/${t}`,i=process.env.CORSAIR_DELIVERY_URL?.trim();if(i)return tt(Ur(i));let o=process.env.APP_URL?.trim()||process.env.NEXT_PUBLIC_APP_URL?.trim()||process.env.VERCEL_URL?.trim();return o?Fi(Ur(o),r):`http://localhost:${process.env.PORT?.trim()||Mi}${r}`}async function Br(e,n){let t=xe(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return t==="development"&&(r.deliveryUrl=_e({deliveryUrl:n.deliveryUrl})),Re({hub:e,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:sn})}async function rt(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e};await nt(t,n.tenantId);let r=await et(t,n.tenantId,{pluginIds:[n.plugin.id]});if(r.length===0)throw new Error(`Plugin '${n.plugin.id}' is not configured on this Corsair instance`);return Br(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function hn(e,n){let t=T(e),r=Y(e),i={plugins:t.plugins,database:t.database,kek:t.kek,hub:r};await nt(i,n.tenantId);let o=n.plugin?[n.plugin]:void 0,a=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,s=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,u=await et(i,n.tenantId,{pluginIds:o,oauthModeOverrides:a,providerNameOverrides:s});if(u.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return Br(r,{tenantId:n.tenantId,plugins:u,deliveryUrl:n.deliveryUrl})}function $r(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Ui(e,n){return n&&!n.has(e.id)?!1:O(e)!==null}async function Ee(e,n,t={}){let r=T(e),i=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,a=await qe(r,i,{pluginIds:t.pluginIds}),s=new Map(a.map(l=>[l.plugin,l])),u=r.plugins.filter(l=>Ui(l,o)).map(l=>{let d=O(l),c=s.get(l.id);return c?{plugin:l.id,providerName:se(l.id),authKind:$r(d),status:c.status,connected:c.connected,fields:c.fields.map(p=>({name:p.name,level:p.level,required:p.required,configured:p.configured})),missingRequiredFields:c.missingRequiredFields}:{plugin:l.id,providerName:se(l.id),authKind:$r(d),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:i,plugins:u}}async function Nr(e,n){let t=Y(e);return Pr({hub:t,path:`/projects/${encodeURIComponent(n.projectId)}/connections`,notFoundMessage:"Hub REST API not found at /projects/:id/connections. Check HUB_API_URL and ensure the Hub API is deployed.",parseResponse:an})}var Bi=new Set(["localhost","127.0.0.1","[::1]","::1"]);function ot(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Bi.has(n)}catch{return!1}}function it(e){return e==="development"?"browser":"server"}function Lr(e){return it(e)==="browser"}function Wr(e){return ot(e)?"Production delivery URL must be a public URL, not localhost":null}var ue=6e4,ke=3e5;var J=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function kn(e,n){let t=T(e,()=>new J("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new J("no_database","Database not configured");let r=$(t,n.plugin,d=>new J("plugin_not_found",d)),i=O(r);if(!i)throw new J("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(i==="oauth_2"||i==="managed")throw new J("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await Ie(e,n.tenantId);let o=new Set(nn(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}),l=0;for(let[d,c]of Object.entries(n.credentials)){if(!c.trim())continue;if(!o.has(d))throw new J("invalid_credentials",`Unknown credential field '${d}' for plugin '${n.plugin}'`);let p=G(u,`set_${d}`);if(!p)throw new J("invalid_credentials",`Cannot set credential field '${d}' for plugin '${n.plugin}'`);await p(c.trim()),l+=1}if(l===0)throw new J("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var bn=new Map;function $i(e){for(let[n,t]of bn)t<=e&&bn.delete(n)}function Cn(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return $i(r),bn.has(t)?{ok:!1,error:"Delivery request already consumed"}:(bn.set(t,r+n),{ok:!0})}async function wn(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 jr=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function Ni(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 Li(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 N(n.dek,e.kek),r=jr(n.config),i={};Object.keys(r).length>0&&(i=ee(r,t)),i[e.link.linkType]=e.link.externalId;let o=ae(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 Ni({database:n,pluginId:r,tenantId:i}),l=!1;if(a){let d=R({authType:a,integrationName:r,tenantId:i,kek:t,database:n,extraAccountFields:s}),c=`set_${o.linkType}`,p=d[c];typeof p=="function"&&(await p(o.externalId),l=!0)}l||await Li({database:n,kek:t,accountId:u,link:o})}async function st(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 N(s.dek,t),d=jr(s.config)[i];if(!d)continue;if(je(d,u)===o)return s}catch{continue}return null}async function Pn(e){return(await st(e))?.tenant_id??null}async function Kr(e){return Pn({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var ce=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 ce("no_access_token","Managed OAuth delivery missing access_token");let u=T(e,()=>new ce("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new ce("no_database","No database configured on corsair instance");let l=$(u,t,c=>new ce("plugin_not_found",c));await Ie(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 c=await wn(u.plugins,t,{access_token:i,refresh_token:o,scope:s});if(c)try{let p=l.authConfig?.managed?.account??[];await De({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:c,authType:"managed",extraAccountFields:p})}catch(p){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,p)}}catch(c){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,c)}return{plugin:t,tenantId:r}}import{createHmac as at,randomUUID as Wi,timingSafeEqual as qr}from"crypto";function Zr(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=at("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":Wi()}}}function ut(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Zr(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=at("sha256",n).update(e.body).digest("hex");try{return qr(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=Zr(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=at("sha256",n).update(e.body).digest("hex");try{if(!qr(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 ct(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function lt(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function dt(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 pt(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 ji(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Gr(e,n,t=[]){for(let[r,i]of Object.entries(e))if(ji(i)){if(i.match(n))return{webhook:i,path:[...t,r]}}else if(i&&typeof i=="object"){let o=Gr(i,n,[...t,r]);if(o)return o}return null}function Ki(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function qi(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 Jr(e,n,t,r){let i=Ki(n),o=typeof t=="string"?JSON.parse(t):t;(!o||typeof o=="object"&&Object.keys(o).length===0)&&i["x-goog-resource-uri"]&&(o=qi(i)||o);let s={headers:i,body:o,...r?{query:r}:{}},u=r?.tenantId||"default",l=e.withTenant?e.withTenant(u):e,d=tn;for(let c of d){let p=l[c];if(!p||!p.webhooks||p.pluginWebhookMatcher&&!p.pluginWebhookMatcher(s))continue;let g=Gr(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 m=await g.webhook.handler(y),h=!!Object.keys(m.returnToSender||{})?.length;return{plugin:c,action:f,body:o,response:h?{...m?.returnToSender,success:!0}:{success:!0},...m.responseHeaders&&{responseHeaders:m.responseHeaders}}}catch(m){return console.error(`Error executing webhook handler for ${c}.${f}:`,m),{plugin:c,action:f,body:o,response:{success:!1,error:m instanceof Error?m.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{randomBytes as zi}from"crypto";import{createHmac as Zi,randomBytes as Gi,timingSafeEqual as Ji}from"crypto";function ne(){return Gi(16).toString("base64url")}function Ze(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Zi("sha256",t).update(e).digest("base64url")}function z(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=Ze(i,t);try{if(!Ji(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 vn(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=Ze(o,n);return`${o}.${a}`}function Ge(e,n,t){let r=Math.floor(Date.now()/1e3);return vn(e,n,r+Math.floor(t/1e3))}function be(e){return decodeURIComponent(e)}function gt(e){return encodeURIComponent(e)}function zr(e){let n=e.trim();return n.length>0?n:null}function An(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function xn(e,n){if(!zr(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??zi(16).toString("base64url"),iat:t,exp:t+Math.floor(6e4/1e3)},i=Buffer.from(JSON.stringify(r)).toString("base64url"),o=Ze(i,n);return`${i}.${o}`}function le(e,n){return zr(n)?z(e,n):null}function Ce(e){return e.deliveryMode==="connect.status"}function we(e){return e.deliveryMode==="auth.credentials"}function Je(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function ze(e){return e.deliveryMode==="oauth.tokens"}function Rn(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!Ce(e)&&!we(e)&&!Je(e)&&!ze(e)}function ft(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 Vi(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 Pn({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Yi(e,n,t){let r=await Vi(e,n,t),i={...t.query??{},...r?{tenantId:r}:{}},o=await Jr(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 Qi(e,n){return await Ve(e,n),{status:"ok"}}async function Xi(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 mt(e,n,t){let r=await yt(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function yt(e,n,t){let r=T(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 es(e,n){try{return await kn(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function ns(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 ht(e,n,t={}){let r=T(e),i=ft(n.headers,"x-corsair-signature"),o=ft(n.headers,"x-corsair-timestamp"),a=ft(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 l=Cn(`nonce:${a.trim()}`,3e5);if(!l.ok)return{status:"failed",retryable:!1,error:l.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let s;try{s=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}switch(s.type){case"webhook":return Yi(e,r,s.payload);case"oauth.callback":return Qi(e,s.payload);case"oauth.tokens":return Xi(e,s.payload);case"permission.approve":return yt(e,s.payload,"approved");case"permission.deny":return yt(e,s.payload,"denied");case"auth.credentials":return es(e,s.payload);case"connect.status":return ns(e,s.payload);default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${s.type}`}}}var ts="corsair:client-bridge";function Vr(e){let n=JSON.stringify({type:ts,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 rs=[".corsair.dev"];function os(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function is(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:os(n)?!0:rs.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Yr(e){return!e||!is(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 Qr(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 kt(e,n){let t=Y(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=le(i,t.signingSecret);if(!o)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let a=Cn(`browser:${o.jti}`,6e4);if(!a.ok)return{type:"json",status:400,body:{error:a.error}};try{if(Ce(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(we(o))return o.hubSuccessUrl?o.credentials?(await kn(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(Je(o)){if(!o.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await mt(e,o.permissionToken,o.deliveryMode==="permission.approve"?"approved":"denied")}else if(ze(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(!Rn(o)||!o.code||!o.state||!o.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await Ve(e,{code:o.code,state:o.state,redirectUri:o.redirectUri})}}catch(s){let u=s instanceof Error?s.message:"Hub delivery failed";return(Ce(o)||we(o))&&o.hubSuccessUrl?{type:"redirect",url:Sn(o.hubSuccessUrl,{error:u})}:(Ce(o)||we(o))&&o.hubOrigin&&o.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Vr({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 bt(e,n){let t=Y(e),r=await ht(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 Ct(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 wt(e,n){return n.method==="GET"?kt(e,n.url):bt(e,{headers:n.headers,body:n.body??""})}async function Pt(e,n){try{let t=await wt(e,n);return Ct(t)}catch(t){if(t instanceof he)return Response.json({error:t.message},{status:503});throw t}}async function Pe(e,n){let t=n.method.toUpperCase(),r=Yr(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 Pt(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return Qr(i,r)}var te=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 Xr=300;async function Tt(e,n){let{keys:t,hub:r,plugin:i,tenantId:o}=e,a=n?.forceRefresh??!1,[s,u,l]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!s&&!l)throw new te(i,"managed");let d=Math.floor(Date.now()/1e3);if(!a&&s&&u&&Number(u)>d+Xr)return{accessToken:s,expiresAt:Number(u),refreshed:!1};if(!l&&s&&!a){let g=u?Number(u):null;if(g===null||g>d+Xr)return{accessToken:s,expiresAt:g??d+3600,refreshed:!1}}let c=await Re({hub:r,path:"/oauth/refresh",body:{plugin:i,tenantId:o},parseResponse:cn}),p=c.expires_in?d+c.expires_in:u?Number(u):d+3600;return await t.set_access_token(c.access_token),await t.set_expires_at(String(p)),c.refresh_token&&await t.set_refresh_token(c.refresh_token),c.scope&&await t.set_scope(c.scope),{accessToken:c.access_token,expiresAt:p,refreshed:!0}}async function eo(e,n){e._refreshAuth=async()=>(await Tt(n,{forceRefresh:!0})).accessToken}async function In(e,n){let t=xe(e.projectApiKey),r={permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,expiresAt:n.expiresAt};return t==="development"&&(r.deliveryUrl=_e({deliveryUrl:n.deliveryUrl})),Re({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:un})}function _n(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}function no(e){return{delivery:n=>Pe(e,n),deliveryOptions:n=>Pe(e,n)}}var to=1200*1e3;function vt(){return ne()}function At(){return to}function xt(e,n){return Ge(e,n,to)}function Rt(e,n){return z(e,n)}function St(e){return be(e)}var ro=600*1e3;function It(){return ne()}function _t(){return ro}function Et(e,n){return Ge(e,n,ro)}function Dt(e,n){return z(e,n)}function Ot(e){return gt(e)}function Mt(e){return be(e)}function Ht(){return ne()}function Ft(e,n,t){return vn(e,n,Math.floor(t.getTime()/1e3))}function Ut(e,n){return z(e,n)}function Bt(e){return be(e)}function En(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 ${We}`)}})}function He(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}import*as Ye from"crypto";function de(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function $t(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 Fe(e,n){let t=Ye.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Nt=600*1e3;function Dn(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),i=e.slice(t+1),o=Ye.createHmac("sha256",n).update(r).digest("base64url"),a=Buffer.from(i,"base64url"),s=Buffer.from(o,"base64url");return a.length!==s.length||!Ye.timingSafeEqual(a,s)?null:$t(r,{maxAgeMs:Nt})}function Lt(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function ss(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await rt(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins})).connectUrl}catch{return null}}async function as(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await rt(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):Lt(e.pluginId,r.connectUrl)}catch{return`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`}let t=await ss({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins});return t?Lt(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function us(e,n,t){let r=Fe(de(e,n.tenantId??t??"default"),n.kek),i=new URL(n.baseUrl);i.searchParams.set("state",r);let o=i.toString();return n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:o,state:r}):Lt(e,o)}async function oo(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&He(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?us(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?as({manual:e.manual,hub:e.hub,plugin:e.plugin,pluginId:t,tenantId:n,authType:e.error.authType,database:e.database,kek:e.kek,plugins:e.plugins}):e.error.message}var cs=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function io(e,n,t,r,i){let o={pluginId:n,operation:t,input:r,originalError:e},a=Object.keys(i).find(l=>i[l]?.match(e,o));return await(i[a||"DEFAULT"]?.handler||cs)(e,o)}import{randomBytes as ds}from"crypto";import{v4 as ps}from"uuid";var Wt="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 Kt(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function so(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function jt(e){return _n(e)}async function qt(e,n){if(Kt(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?so(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await In(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:ls(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function ls(e){try{return JSON.parse(e)}catch{return e}}async function On(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await qt(e,n);return{...n,approvalUrl:r}}async function Zt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:i,permissionToken:o,plugin:a,endpoint:s,args:u,tenantId:l,expiresAt:d,operationPath:c}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:o,id:i,plugin:a,endpoint:s,args:u});let g=await qt({manual:t,hub:r},{id:i,token:o,plugin:a,endpoint:s,args:JSON.stringify(u),tenant_id:l,expires_at:d});return Kt(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):jt(g):Wt:r?g?jt(g):`Action '${c}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Wt}var gs={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 fs(e,n,t){return t!==void 0?t:gs[n][e]}function Gt(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 uo(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 ao(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 co(e){let n=fs(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"?ao(e.db,s.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:s.id,token:s.token,expiresAt:s.expires_at})}let u=ps(),l=ds(32).toString("hex"),d=e.timeoutMs??600*1e3,c=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:l,plugin:e.pluginId,endpoint:e.endpointPath,args:i,tenant_id:a,status:"pending",expires_at:c}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
|
|
21
|
-
Action: ${r}`,`
|
|
22
|
-
Permission ID: ${u}`,`
|
|
23
|
-
Permission token: ${l}`,`
|
|
24
|
-
Expires at: ${c}`,`
|
|
25
|
-
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?ao(e.db,u,d):{result:"blocked",reason:"pending",id:u,token:l,expiresAt:c}}function ys(e){return typeof e=="function"}function Jt({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:i,errorHandlers:o,currentPath:a=[],keyBuilder:s,permissionsConfig:u,endpointMeta:l,database:d,permissionsOptions:c,tenantId:p,manualConfig:g,hubConfig:f,plugin:y,kek:m,allPlugins:h}){for(let[P,w]of Object.entries(e)){let k=n?.[P];if(ys(w)){let b=k,C=[...a,P].join("."),F=async(S={})=>{let E;if(u){let U=l?.[C],{result:en,reason:q,onComplete:Ne,token:V,id:me,expiresAt:B}=await co({pluginId:i,endpointPath:C,args:S,mode:u.mode,override:u.overrides?.[C],riskLevel:U?.riskLevel??"write",meta:U,db:d,timeoutMs:c?Gt(c.timeout):void 0,tenantId:p,approvalMode:c?.mode});if(en==="blocked"){let Z;throw q==="denied"?Z=`Action '${C}' was denied by the user. Await further instructions before proceeding.`:q==="policy"?Z=`Action '${C}' is blocked by the permission policy. Update the corsair config to allow it.`:q==="timeout"?Z=`Action '${C}' timed out waiting for approval.`:V&&me?Z=await Zt({permissionsOptions:c,manual:g,hub:f,permissionId:me,permissionToken:V,plugin:i,endpoint:C,args:S,tenantId:p??"default",expiresAt:B??new Date(Date.now()+(c?Gt(c.timeout):600*1e3)).toISOString(),operationPath:C}):Z=`Action '${C}' requires user approval before it can run.`,new Error(Z)}E=Ne}let I=async(U,en,q)=>{try{return await w(en,q)}catch(Ne){if(Ne instanceof Error){let V=await io(Ne,i,C,typeof q=="object"&&q!==null?q:{args:q},o);if(U<(V.maxRetries||0)){let me=U+1;console.log(`Retrying (${me} / ${V.maxRetries})...`);let B;if(V.headersRetryAfterMs)B=V.headersRetryAfterMs;else switch(V.retryStrategy){case"exponential_backoff":B=Math.pow(2,me-1)*1e3;break;case"exponential_backoff_jitter":let Z=Math.pow(2,me-1)*1e3,jo=(Math.random()-.5)*1e3;B=Math.max(0,Z+jo);break;case"linear_1s":B=1e3;break;case"linear_2s":B=2e3;break;case"linear_3s":B=3e3;break;case"linear_4s":B=4e3;break;default:B=1e3;break}await new Promise(Z=>setTimeout(Z,B)),await I(me,en,q),console.log(`[corsair:${i}:${C}] Retry strategy:`,V)}}throw Ne}},fe;try{fe=s?await s(t,"endpoint"):void 0}catch(U){if(U instanceof te)return oo({error:U,manual:g,hub:f,plugin:y,tenantId:p,database:d,kek:m,plugins:h});throw U}if(!b?.before&&!b?.after){let U=await I(0,{...t,key:fe},S);return await E?.(),U}let $e={...t,key:fe},ye=b.before?await b.before($e,S):{ctx:$e,args:S,continue:!0,passToAfter:void 0};if(ye.continue===!1)return;let cr=await I(0,ye.ctx,ye.args);return await b.after?.(ye.ctx,cr,ye.passToAfter),await E?.(),cr};r[P]=F}else if(w&&typeof w=="object"){let b={};Jt({endpoints:w,hooks:k,ctx:t,tree:b,pluginId:i,errorHandlers:o,currentPath:[...a,P],keyBuilder:s,permissionsConfig:u,endpointMeta:l,database:d,permissionsOptions:c,tenantId:p,manualConfig:g,hubConfig:f,plugin:y,kek:m,allPlugins:h}),r[P]=b}}}function ms(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function zt({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:i}){for(let[o,a]of Object.entries(e)){let s=n?.[o];if(ms(a)){let u=s,l=async d=>{let c=(g,f)=>a.handler(g,f),p=i?await i(t,"webhook"):void 0;return!u?.before&&!u?.after?c({...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 c(f.ctx,f.args);return y?.success===!0&&await u.after?.(f.ctx,y,f.passToAfter),y})()};r[o]={match:a.match,handler:l}}else if(a&&typeof a=="object"){let u={};zt({webhooks:a,hooks:s,ctx:t,webhooksTree:u,keyBuilder:i}),r[o]=u}}}function hs(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 ks(e,n,t,r,i){return e?Jn(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 Vt(e,n){let{database:t,tenantId:r,kek:i,rootErrorHandlers:o,permissionsOptions:a,manualConfig:s,hubConfig:u}=n,l={},d={};for(let c of e)l[c.id]={},d[c.id]={};for(let c of e){let p=c.schema,g=r??"default",f=hs(t,c.id,g);if(p?.entities){let I={};for(let[fe,$e]of Object.entries(p.entities)){let ye=t?Jn(t.db,f,fe,p.version,$e):ks(void 0,f,fe,p.version,$e);I[fe]=ye}d[c.id].db=I,l[c.id].db=I}let y=c.options,m=c.authConfig,h;if(t&&i&&y?.authType){let I=m?.[y.authType]?.account??[];h=R({authType:y.authType,integrationName:c.id,tenantId:g,kek:i,database:t,extraAccountFields:I}),l[c.id].keys=h}let P={database:t,db:d[c.id]?.db??{},$getAccountId:f,...c.options?{options:c.options}:{},...h?{keys:h,authType:y?.authType}:{},tenantId:g,...u?{hub:u}:{}},w=c.endpoints??{},k=c.hooks,b={...o,...c.errorHandlers},C={},F=c.options?.permissions;Jt({endpoints:w,hooks:k,ctx:P,tree:C,pluginId:c.id,errorHandlers:b,currentPath:[],keyBuilder:c.keyBuilder,permissionsConfig:F,endpointMeta:c.endpointMeta,database:t,permissionsOptions:a,tenantId:r,manualConfig:s?{...s,oauthConfig:c.oauthConfig,kek:i,tenantId:g}:void 0,hubConfig:u,plugin:c,kek:i,allPlugins:e}),Object.keys(C).length>0&&(l[c.id].api=C),P.endpoints=C;let S=c.webhooks??{},E=c.webhookHooks;if(Object.keys(S).length>0){let I={};zt({webhooks:S,hooks:E,ctx:P,webhooksTree:I,keyBuilder:c.keyBuilder}),l[c.id].webhooks=I,c.pluginWebhookMatcher&&(l[c.id].pluginWebhookMatcher=c.pluginWebhookMatcher),c.pluginTenantWebhookMatcher&&(l[c.id].pluginTenantWebhookMatcher=c.pluginTenantWebhookMatcher)}}return l}function lo(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=_({authType:o.authType,integrationName:i.id,kek:t,database:n,extraIntegrationFields:s});r[i.id]=u}}return r}var bs="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function po(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] ${bs}`),t):n}import*as go from"querystring";function Te(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}?${go.stringify(o)}`}var L=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Cs(e){let n=e.oauthConfig;if(!n)throw new L("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Yt(e,n){let t=T(e,()=>new L("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new L("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new L("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let i=Dn(n,t.kek);if(!i)throw new L("invalid_state","Invalid or tampered state parameter");let{plugin:o,tenantId:a}=i,s=$(t,o,p=>new L("plugin_not_found",p)),u=Cs(s),d=await _({authType:"oauth_2",integrationName:o,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new L("client_id_not_configured",`client_id not configured for '${o}'`);let c=Te({oauthConfig:u,clientId:d,redirectUri:r,state:n});return{plugin:o,tenantId:a,providerName:u.providerName,oauthUrl:c,state:n}}var A=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 fo(e){let n={error:e.code,message:e.message,...e.extra};return x(e.status,n)}function pe(e){return new A(404,"not_found",e)}function re(e,n={}){return new A(400,"bad_request",e,n)}function yo(e,n){return $(e,n,t=>pe(t))}async function mo(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=_({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),i=D[t].integration,o=r,a;try{a=await Promise.all(i.map(l=>o[`get_${l}`]()))}catch{a=i.map(()=>null)}let s=i.filter((l,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 ho(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:i,missingFields:o}=await mo(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 Mn(){return{ok:!0}}async function Hn(e){return Promise.all(e.plugins.map(n=>ho(n,e)))}async function Fn(e,n){let t=yo(e,n);return ho(t,e)}async function ws(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 ko(e,n){let t=await ws(e,n),r=t.filter(i=>i.hasCredentials).map(i=>i.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Un(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 Bn(e,n){if(!n)throw re("Tenant id must be a non-empty string");return ko(e,n)}async function $n(e,n){let t=n?.id?.trim();if(!t)throw re("Tenant id is required",{missingFields:["id"]});return ko(e,t)}async function Nn(e,n){let t=n?.trim()||"default",r={},i=await qe(e,t);for(let o of i)r[o.plugin]=yn(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 Qt(e,n){if(!e.database)throw pe(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw pe(`Permission '${n}' not found`);return On(e,t)}function Ps(e){if(!e.oauthConfig)throw re(`Plugin '${e.id}' has no oauthConfig`)}function Ts(e){if(!e.manual)throw new A(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Xt(e){let n=Ts(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new A(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 vs(e){let n=!!e.hub,t=He(e.manual);if(!n&&!t)throw new A(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function bo(e){if(!e.database||!e.kek)throw new A(500,"database_not_configured","A database and kek are required to issue connect links.")}async function As(e,n){let t=n?.plugin?.trim();if(!t)throw re("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",i=yo(e,t);Ps(i);let o=Xt(e);bo(e);let a=await mo(i,e);if(!a.configured)throw new A(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:a.missingFields});let s=Fe(de(t,r),e.kek),u;try{u=new URL(o.baseUrl)}catch{throw new A(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()+Nt).toISOString()}}async function xs(e,n,t){bo(n);let i={tenantId:t.tenantId?.trim()||"default",oauthMode:t.oauthMode},o=t.plugin?.trim();o&&(i.plugin=o);let a=t.providerName?.trim();a&&(i.providerName=a);let s=await hn(e,i);return{connectUrl:s.connectUrl,expiresAt:s.expiresAt}}async function Ln(e,n,t){return vs(n),n.hub?xs(e,n,t):As(n,t)}async function Wn(e,n,t){if(n.hub&&!He(n.manual))throw new A(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw re("state is required",{missingFields:["state"]});Xt(n);try{return await Yt(e,r)}catch(i){if(i instanceof L)switch(i.code){case"invalid_state":throw re("Invalid or expired state");case"client_id_not_configured":throw new A(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new A(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function jn(e,n,t){if(n.hub&&!He(n.manual))throw new A(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 re("Missing required fields",{missingFields:o});let a=Xt(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 re("Invalid or expired state");case"credentials_not_configured":throw new A(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new A(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function er(e,n){if(!e.database)throw pe("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw pe("Permission not found");return On(e,t)}async function Co(e,n){return"id"in n?Qt(e,n.id):er(e,n.token)}var wo=[{method:"GET",pattern:"/ok",handler:async()=>x(200,Mn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>x(200,await Un(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>x(201,await $n(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>x(200,await Bn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>x(200,await Hn(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>x(200,await Fn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>x(200,await Nn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>x(200,await Qt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?x(200,await er(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 Ln(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>x(200,await Wn(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>x(200,await jn(e,n,t))}];(()=>{let e=new Set;for(let n of wo){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 Ss(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 A(400,"invalid_json","Request body is not valid JSON")}}var _s="/api/corsair";function ve(e,n={}){let t=n.basePath??_s,r=T(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async i=>{try{let o=new URL(i.url),a=Ss(o.pathname,t),s=i.method.toUpperCase();if(s==="OPTIONS"||a==="/"||a==="")return await Pe(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 l of wo){if(l.method!==s)continue;let d=Rs(l.pattern,a);if(!d)continue;let c=await Is(i);return await l.handler({corsair:e,internal:r,req:i,params:d,query:u,body:c})}throw pe(`No route for ${s} ${a}`)}catch(o){if(n.onError){let s=await n.onError(o,i);if(s)return s}if(o instanceof A)return fo(o);let a=o instanceof Error?o.message:"Internal server error";return x(500,{error:"internal_error",message:a})}}}function Es(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,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let d of l)o.append(u,d);else o.set(u,l);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 Ds(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 Po(e,n){let t=ve(e,n);return async(r,i,o)=>{try{let a=await t(Es(r));await Ds(i,a)}catch(a){o(a)}}}function To(e,n){let t=ve(e,n);return r=>t(r.req.raw)}function vo(e,n){let t=ve(e,n);return{GET:t,POST:t,OPTIONS:t}}function Ao(e){let n={[Qe]:e};return{ok:Mn,tenants:{list:()=>Un(e),create:t=>$n(e,t),get:t=>Bn(e,t)},plugins:{list:()=>Hn(e),get:t=>Fn(e,t)},connectionStatus:{get:t=>Nn(e,t?.tenantId)},permissions:{get:t=>Co(e,t)},connect:{createLink:t=>Ln(n,e,t),resolve:t=>Wn(n,e,t),oauthCallback:t=>jn(n,e,t)}}}async function xo(e,n,t,r,i="pending"){if(!e)return null;try{let o=gr(),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 Os(e,n,t,r="pending"){try{let i=await e.$getAccountId();return xo(e.database,i,n,t,r)}catch(i){return console.warn("Failed to log event:",i),null}}import*as Ro from"https";import*as So from"querystring";function Kn(e,n,t,r,i){let o=new URL(r.tokenUrl),a=r.tokenAuthMethod==="basic";return new Promise((s,u)=>{let l={code:e.trim(),redirect_uri:i,grant_type:"authorization_code"};a||(l.client_id=n,l.client_secret=t);let d=So.stringify(l),c={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(d).toString()};a&&(c.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let p=Ro.request({hostname:o.hostname,...o.port?{port:Number(o.port)}:{},path:o.pathname+o.search,method:"POST",headers:c},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 Io=" ";function j(e){let n=e;return n._def??n.def??{}}function K(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 W(e){return e.innerType??e.schema??e.out??e.in}function Eo(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 W(e)}}function Do(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Zn(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Ue(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 Oo(e,n){return e.description??n.description}function Ms(e){let n=e;for(;n;){let t=j(n),r=Oo(n,t);if(r)return r;let i=K(t);if(ir(i)||i==="ZodPipe"||i==="ZodEffects"||i==="ZodTransform"){n=Eo(t,i);continue}break}}function ir(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function M(e){let n=j(e),t=K(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??Ue(n)[0]??"unknown");case"ZodEnum":return Ue(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=W(n);return r?M(r):"unknown"}case"ZodNullable":{let r=W(n);return`${r?M(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=W(n);return r?M(r):"unknown"}case"ZodArray":{let r=Do(n);if(!r)return"unknown[]";let i=j(r),o=K(i)==="ZodUnion",a=M(r);return`${o?`(${a})`:a}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Zn(e,n),i=Object.entries(r);return i.length===0?"{}":`{ ${i.map(([a,s])=>{let u=K(j(s));return`${u==="ZodOptional"||u==="ZodNullable"?a+"?":a}: ${M(s)}`}).join(", ")} }`}case"ZodUnion":return Ue(n).map(r=>M(r)).join(" | ");case"ZodIntersection":return`${M(n.left)} & ${M(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=Eo(n,t);return r?M(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function oe(e){let n=j(e),t=K(n),r=Oo(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??Ue(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=Ue(n).map(o=>String(o));return{kind:"string",optional:!1,description:r,enum:i}}case"ZodOptional":{let i=W(n),o=i?oe(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodNullable":{let i=W(n),o=i?oe(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodDefault":case"ZodCatch":{let i=W(n);return i?{...oe(i),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let i=Do(n);return{kind:"array",optional:!1,description:r,items:i?oe(i):{kind:"unknown",optional:!1}}}case"ZodObject":{let i=Zn(e,n),o={};for(let[a,s]of Object.entries(i))o[a]=oe(s);return{kind:"object",optional:!1,description:r,fields:o}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let i=Ue(n);for(let o of i){let a=j(o);if(K(a)==="ZodObject")return{...oe(o),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let i=W(n);return i?{...oe(i),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Cd(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=ge(a.endpointMeta,s),l=ge(a.endpointSchemas,s);return!u&&!l?null:{input:l?.input?oe(l.input):null,output:l?.output?oe(l.output):null,description:u?.description}}var sr=["equals","contains","startsWith","endsWith","in"],Hs=["equals","gt","gte","lt","lte","in"],Fs=["equals"],Us=["equals","before","after","between"];function Mo(e){let n=j(e);switch(K(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=W(n);return r?Mo(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function ar(e){let n=j(e),t=K(n);if(ir(t)){let o=W(n);return o?ar(o):{}}if(t!=="ZodObject")return{};let r=Zn(e,n),i={};for(let[o,a]of Object.entries(r)){let s=Mo(a);s==="string"?i[o]={type:"string",operators:sr}:s==="number"?i[o]={type:"number",operators:Hs}:s==="boolean"?i[o]={type:"boolean",operators:Fs}:s==="date"&&(i[o]={type:"date",operators:Us})}return i}function Ho(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function tr(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"&&tr(i,o,t)}}function rr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function or(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];rr(i)?t.push(o.join(".")):i!==null&&typeof i=="object"&&or(i,o,t)}}function ur(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 rr(a)?[o]:null;if(a!==null&&typeof a=="object"&&!rr(a)){let s=ur(a,r);if(s!==null)return[o,...s]}return null}function Fo(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 Bs=new Set(tn);function Ae(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 Bs.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:Ae(e);if(t==="webhooks"){if(!o.webhooks)return[];let s=[];return or(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 tr(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=[];or(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=[];tr(o.endpoints,[],a),i[o.id]=a.map(s=>`${o.id}.api.${s}`)}return i}function ge(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function $s(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 nr(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 wd(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),c=d.lastIndexOf(".");if(c!==-1){let p=d.slice(0,c),g=d.slice(c+1),f=a.schema?.entities;if(g==="search"&&f){let y=Ho(f,p);if(y){let[m,h]=y,P=ar(h),w=[`Search ${i} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${sr.join(", ")}]`];for(let[k,b]of Object.entries(P))w.push(` ${k}?: ${b.type} [${b.operators.join(", ")}]`);return w.push("}"),w.join(`
|
|
30
|
-
`)}}}return nr(Ae(e,{type:"db"}),"Path not found. Available db operations")}if(o.startsWith("webhooks.")){let d=o.slice(9);if(a.webhooks){let c=ur(a.webhooks,d.split("."));if(c!==null){let p=c.join("."),g=ge(a.webhookSchemas,p.toLowerCase()),f=g?.response?M(g.response):null,y=[];return g?.description&&y.push(g.description),g?.payload&&y.push(`payload ${qn(Be(g.payload))}`),f&&y.push(`response: ${f}`),y.push(`usage:
|
|
31
|
-
${Fo(i,c)}`),y.join(`
|
|
32
|
-
|
|
33
|
-
`)}}return nr(Ae(e,{type:"webhooks"}),"Path not found. Available webhooks")}let s=o;s.startsWith("api.")&&(s=s.slice(4));let u=ge(a.endpointMeta,s),l=ge(a.endpointSchemas,s);if(u||l){let d=[],c=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),p=[u?.description,c].filter(Boolean).join(" ");return p&&d.push(p),l?.input&&d.push(`input ${qn(Be(l.input))}`),l?.output&&d.push(`output ${qn(Be(l.output))}`),d.join(`
|
|
34
|
-
|
|
35
|
-
`)}}}return nr(Ae(e),"Path not found. Available operations")}function _o(e){let n=e;for(;;){let t=j(n),r=K(t);if(ir(r)){let i=W(t);if(!i)return n;n=i;continue}return n}}function Be(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=_o(e),t=j(n);if(K(t)==="ZodObject"){let i=Zn(n,t),o=[];for(let[a,s]of Object.entries(i)){let u=j(s),l=K(u),d=l==="ZodOptional"||l==="ZodNullable",c=_o(s),p=Ms(s);o.push({key:a,optional:d,type:M(c),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:o}}return{kind:"inline",type:M(n)}}function qn(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=Io.repeat(n+1),r=Io.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 Ns(e,n){let t=Ae(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:c,lookupKey:p}=$s(d,n),g=ge(r.endpointMeta,p),f=ge(r.endpointSchemas,p);!g&&!f||i.push({path:d,shortPath:c,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:Be(f?.input),output:Be(f?.output)})}i.sort((d,c)=>d.path.localeCompare(c.path));let o=[],a=Ae(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=ur(r.webhooks,f.split("."));if(y===null)continue;let m=y.join("."),h=ge(r.webhookSchemas,m.toLowerCase()),P=h?.response?M(h.response):void 0;o.push({path:d,description:h?.description,payload:Be(h?.payload),responseType:P,usageExample:Fo(n,y)})}o.sort((d,c)=>d.path.localeCompare(c.path));let s=[],u=Ae(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(u)&&l)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 m=f.slice(0,y);if(f.slice(y+1)!=="search")continue;let P=Ho(l,m);if(!P)continue;let[w,k]=P,b=ar(k),C=Object.entries(b).map(([F,S])=>({field:F,type:S.type,operators:S.operators}));s.push({path:d,entityName:w,filters:[{field:"entity_id",type:"string",operators:sr},...C]})}return s.sort((d,c)=>d.path.localeCompare(c.path)),{ok:!0,data:{pluginId:n,api:i,webhooks:o,db:s}}}function Uo(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function Ls(e,n){let t=Uo(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 Ws(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 $o(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 js(e){return Xe(e.body)}function No(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return Gn(Array.isArray(r)?r:[r])}function Lo(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let l=Gn(Array.isArray(u)?u:[u]);if(l)return decodeURIComponent(l)}let r=No({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 l=n[u],d=Array.isArray(l)?l[0]:l;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 Gn([a?.validationToken])??null}function Ks(e){if(Lo(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 Gn(e){for(let n of e){let t=$o(n);if(t)return t}}function qs(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 Mr(e){let n=e.database?lr(e.database):void 0,t=n&&e.kek?lo(e.plugins,n,e.kek):En(!!n,!!e.kek),r=po(e),i={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?rn(e.hub):void 0},o=uo(n),a=Ao(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 l=Vt(e.plugins,{database:n,tenantId:u,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:i.hub});return Object.assign(l,{[Qe]:i})},keys:t,permissions:o,manage:a},{[Qe]:i});let s=Vt(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 H=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Wo(e){let n=e.oauthConfig;if(!n)throw new H("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Zs(e,n,t,r){let i=yr(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=Q(),u=await X(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,hubConnect:o=!1}=t,a=T(e,()=>new H("invalid_corsair_instance","Invalid corsair instance"));if(!a.database)throw new Error("No database configured on corsair instance");let s=$(a,n,p=>new H("plugin_not_found",p)),u=Wo(s),d=await _({authType:"oauth_2",integrationName:n,kek:a.kek,database:a.database}).get_client_id();if(!d)throw new Error(`client_id not configured for '${n}'`);if(o){let p=new URL(Te({oauthConfig:u,clientId:d,redirectUri:i,state:""}));return p.searchParams.delete("state"),{url:p.toString(),state:""}}let c=Fe(de(n,r),a.kek);return{url:Te({oauthConfig:u,clientId:d,redirectUri:i,state:c}),state:c}}async function Ve(e,n){let{code:t,state:r,redirectUri:i}=n,o=T(e,()=>new H("invalid_corsair_instance","Invalid corsair instance")),a=Dn(r,o.kek);if(!a)throw new H("invalid_state","Invalid or tampered state parameter");let{plugin:s,tenantId:u}=a;if(!o.database)throw new H("no_database","No database configured on corsair instance");let l=$(o,s,m=>new H("plugin_not_found",m)),d=Wo(l),c=_({authType:"oauth_2",integrationName:s,kek:o.kek,database:o.database}),p=await c.get_client_id(),g=await c.get_client_secret();if(!p||!g)throw new H("credentials_not_configured",`Credentials not configured for '${s}'`);await Zs(o.database,s,u,o.kek);let f=await Kn(t,p,g,d,i);if(!f.access_token)throw new H("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 m=await wn(o.plugins,s,f);if(m)try{let h=l.authConfig?.oauth_2?.account??[];await De({database:o.database,kek:o.kek,pluginId:s,tenantId:u,link:m,authType:"oauth_2",extraAccountFields:h})}catch(h){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${u}':`,h)}}catch(m){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${u}':`,m)}return{plugin:s,tenantId:u}}export{mr as a,se as b,Le as c,he as d,rn as e,Y as f,on as g,xe as h,sn as i,an as j,un as k,cn as l,kr as m,ln as n,Q as o,X as p,N as q,zn as r,je as s,ae as t,ee as u,Ke as v,_ as w,R as x,Sr as y,Ir as z,de as A,$t as B,De as C,st as D,Pn as E,Kr as F,Te as G,H,Xn as I,Ve as J,Dr as K,xi as L,_e as M,hn as N,Ee as O,Nr as P,ot as Q,it as R,Lr as S,Wr as T,ue as U,ke as V,ce as W,Oe as X,Tn as Y,ut as Z,Me as _,ct as $,lt as aa,dt as ba,pt as ca,Jr as da,ne as ea,An as fa,xn as ga,le as ha,Ce as ia,we as ja,Je as ka,ze as la,Rn as ma,mt as na,ht as oa,kt as pa,bt as qa,Ct as ra,wt as sa,Pt as ta,Pe as ua,te as va,Tt as wa,eo as xa,In as ya,_n as za,no as Aa,vt as Ba,At as Ca,xt as Da,Rt as Ea,St as Fa,It as Ga,_t as Ha,Et as Ia,Dt as Ja,Ot as Ka,Mt as La,Ht as Ma,Ft as Na,Ut as Oa,Bt as Pa,Yt as Qa,ve as Ra,Po as Sa,To as Ta,vo as Ua,xo as Va,Os as Wa,Kn as Xa,Cd as Ya,Ae as Za,wd as _a,qn as $a,Ns as ab,Uo as bb,Ls as cb,Ws as db,Bo as eb,$o as fb,Xe as gb,js as hb,No as ib,Lo as jb,Ks as kb,Gn as lb,qs as mb,Qe as nb,Mr as ob};
|