corsair 0.1.76 → 0.1.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ import{b as I,c as _,d as F,e as A}from"./chunk-IGGCNGU2.js";import{v7 as Z}from"uuid";function C(){return Z()}import{z as h}from"zod";import{sql as w}from"kysely";function E(e){return e.replace(/'/g,"''")}function B(e){let n=E(e);return w`data->>'${w.raw(n)}'`}function R(e){let n=E(e);return w`(data->>'${w.raw(n)}')::numeric`}function P(e){let n=E(e);return w`(data->>'${w.raw(n)}')::boolean`}function S(e){let n=E(e);return w`(data->>'${w.raw(n)}')::timestamptz`}function $(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function O(e){let n=e;for(;n;){if(n instanceof h.ZodOptional||n instanceof h.ZodNullable){n=n._def.innerType;continue}if(n instanceof h.ZodDefault){n=n._def.innerType;continue}break}return n}function U(e){let n=O(e);if(n instanceof h.ZodString)return"string";if(n instanceof h.ZodNumber)return"number";if(n instanceof h.ZodBoolean)return"boolean";if(n instanceof h.ZodDate)return"date"}function K(e){let n=O(e);if(!(n instanceof h.ZodObject))return{};let r=n.shape,t={};for(let[i,o]of Object.entries(r)){let u=U(o);u&&(t[i]=u)}return t}function M(e,n,r){if(typeof r=="string")return e.where(n,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let t=r;"equals"in t&&typeof t.equals=="string"&&(e=e.where(n,"=",t.equals)),"contains"in t&&typeof t.contains=="string"&&(e=e.where(n,"like",`%${t.contains}%`)),"startsWith"in t&&typeof t.startsWith=="string"&&(e=e.where(n,"like",`${t.startsWith}%`)),"endsWith"in t&&typeof t.endsWith=="string"&&(e=e.where(n,"like",`%${t.endsWith}`)),"in"in t&&Array.isArray(t.in)&&(e=e.where(n,"in",t.in))}return e}function Q(e,n,r){if(typeof r=="number")return e.where(n,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let t=r;typeof t.equals=="number"&&(e=e.where(n,"=",t.equals)),typeof t.gt=="number"&&(e=e.where(n,">",t.gt)),typeof t.gte=="number"&&(e=e.where(n,">=",t.gte)),typeof t.lt=="number"&&(e=e.where(n,"<",t.lt)),typeof t.lte=="number"&&(e=e.where(n,"<=",t.lte)),Array.isArray(t.in)&&(e=e.where(n,"in",t.in))}return e}function z(e,n,r){if(typeof r=="boolean")return e.where(n,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let t=r;typeof t.equals=="boolean"&&(e=e.where(n,"=",t.equals))}return e}function J(e,n,r){if(r instanceof Date)return e.where(n,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let t=r;if(t.equals instanceof Date&&(e=e.where(n,"=",t.equals)),t.before instanceof Date&&(e=e.where(n,"<",t.before)),t.after instanceof Date&&(e=e.where(n,">",t.after)),Array.isArray(t.between)&&t.between.length===2){let[i,o]=t.between;i instanceof Date&&(e=e.where(n,">=",i)),o instanceof Date&&(e=e.where(n,"<=",o))}}return e}function L(e,n,r,t){return r==="number"?Q(e,R(n),t):r==="boolean"?z(e,P(n),t):r==="date"?J(e,S(n),t):M(e,B(n),t)}function H(e,n,r){if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let t=r;return"equals"in t&&(e=e.where(n,"=",t.equals)),"contains"in t&&typeof t.contains=="string"&&(e=e.where(n,"like",`%${t.contains}%`)),"startsWith"in t&&typeof t.startsWith=="string"&&(e=e.where(n,"like",`${t.startsWith}%`)),"endsWith"in t&&typeof t.endsWith=="string"&&(e=e.where(n,"like",`%${t.endsWith}`)),"in"in t&&Array.isArray(t.in)&&(e=e.where(n,"in",t.in)),e}return e.where(n,"=",r)}function G(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function b(e,n,r){return e.selectFrom("corsair_entities").selectAll().where("account_id","=",n).where("entity_type","=",r)}function v(e,n,r,t,i){let o=K(i);function u(a){let y=$(a.data);return{...a,data:i.parse(y)}}return{findByEntityId:async a=>{let y=await n(),d=await b(e,y,r).where("entity_id","=",a).executeTakeFirst();return d?u(d):null},findById:async a=>{let y=await n(),d=await b(e,y,r).where("id","=",a).executeTakeFirst();return d?u(d):null},findManyByEntityIds:async a=>{if(a.length===0)return[];let y=await n();return(await b(e,y,r).where("entity_id","in",a).execute()).map(u)},list:async a=>{let y=await n(),d=b(e,y,r);return typeof a?.limit=="number"&&(d=d.limit(a.limit)),typeof a?.offset=="number"&&(d=d.offset(a.offset)),(await d.execute()).map(u)},search:async a=>{let y=await n(),d=b(e,y,r),c=new Set(["data","limit","offset"]);for(let[l,f]of Object.entries(a))c.has(l)||f===void 0||(d=H(d,l,f));if(a.data&&typeof a.data=="object")for(let[l,f]of Object.entries(a.data)){if(f===void 0)continue;let p=o[l]??"string";d=L(d,l,p,f)}return typeof a.limit=="number"&&(d=d.limit(a.limit)),typeof a.offset=="number"&&(d=d.offset(a.offset)),(await d.execute()).map(u)},upsertByEntityId:async(a,y)=>{let d=await n(),c=i.parse(y),s=new Date,l=await b(e,d,r).select("id").where("entity_id","=",a).executeTakeFirst();if(l?.id){await e.updateTable("corsair_entities").set({version:t,data:c,updated_at:s}).where("id","=",l.id).execute();let k=await e.selectFrom("corsair_entities").selectAll().where("id","=",l.id).executeTakeFirst();return u(k)}let f=C();await e.insertInto("corsair_entities").values({id:f,created_at:s,updated_at:s,account_id:d,entity_id:a,entity_type:r,version:t,data:c}).execute();let p=await e.selectFrom("corsair_entities").selectAll().where("id","=",f).executeTakeFirst();return u(p)},deleteById:async a=>{let y=await n(),d=await e.deleteFrom("corsair_entities").where("account_id","=",y).where("entity_type","=",r).where("id","=",a).executeTakeFirst();return Number(d.numDeletedRows)>0},deleteByEntityId:async a=>{let y=await n(),d=await e.deleteFrom("corsair_entities").where("account_id","=",y).where("entity_type","=",r).where("entity_id","=",a).executeTakeFirst();return Number(d.numDeletedRows)>0},count:async()=>{let a=await n(),y=await e.selectFrom("corsair_entities").select(d=>d.fn.countAll().as("count")).where("account_id","=",a).where("entity_type","=",r).executeTakeFirst();return G(y?.count)}}}var X={corsair_integrations:I,corsair_accounts:_,corsair_entities:F,corsair_events:A};function Y(e){return X[e]}function N(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function m(e){if(!e)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function T(e){if(!e)return[];let n=[];for(let r in e){let t=r,i=e[t];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let o=i;"in"in o&&Array.isArray(o.in)?n.push({field:t,operator:"in",value:o.in}):"like"in o&&typeof o.like=="string"&&n.push({field:t,operator:"like",value:o.like})}else n.push({field:t,value:i})}return n}function g(e,n){if(!n?.length)return e;let r=e;for(let t of n){let i=t.operator??"=";r=r.where(t.field,i,t.value)}return r}function q(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function D(e,n){let r=Y(n),t=()=>(m(e),e),i=()=>t().db.selectFrom(n),o=()=>t().db.insertInto(n),u=()=>t().db.updateTable(n),a=()=>t().db.deleteFrom(n);function y(c){let s={};for(let[l,f]of Object.entries(c))s[l]=N(f);return r.parse(s)}function d(c){let s={};for(let[l,f]of Object.entries(c))s[l]=N(f);return r.parse(s)}return{findById:async c=>{m(e);let s=i().selectAll();s=g(s,[{field:"id",value:c}]);let l=await s.executeTakeFirst();return l?y(l):null},findOne:async c=>{m(e);let s=i().selectAll();s=g(s,T(c));let l=await s.executeTakeFirst();return l?y(l):null},findMany:async c=>{m(e);let s=i().selectAll();return s=g(s,T(c?.where)),typeof c?.limit=="number"&&(s=s.limit(c.limit)),typeof c?.offset=="number"&&(s=s.offset(c.offset)),(await s.execute()).map(f=>y(f))},create:async c=>{m(e);let s=new Date,l={id:c.id??C(),created_at:s,updated_at:s,...c},f=await o().values(l).returningAll().executeTakeFirst();return f?y(f):d(l)},update:async(c,s)=>{m(e);let l={...s,updated_at:new Date},f=u().set(l).returningAll();f=g(f,[{field:"id",value:c}]);let p=await f.executeTakeFirst();return p?y(p):null},updateMany:async(c,s)=>{m(e);let l={...s,updated_at:new Date},f=i().select("id");f=g(f,T(c));let p=await f.execute();for(let k of p){let x=u().set(l);x=g(x,[{field:"id",value:k.id}]),await x.execute()}return p.length},delete:async c=>{m(e);let s=a();s=g(s,[{field:"id",value:c}]);let l=await s.executeTakeFirst();return Number(l?.numDeletedRows??0)>0},deleteMany:async c=>{m(e);let s=a();s=g(s,T(c));let l=await s.executeTakeFirst();return Number(l?.numDeletedRows??0)},count:async c=>{m(e);let s=i().select(f=>f.fn.countAll().as("count"));s=g(s,T(c));let l=await s.executeTakeFirst();return q(l?.count)}}}function V(e){let n=D(e,"corsair_integrations");return{...n,findByName:r=>n.findOne({name:r}),upsertByName:async(r,t)=>{let i=await n.findOne({name:r});return i?await n.update(i.id,t):n.create({...t,name:r})}}}function ee(e){let n=D(e,"corsair_accounts");return{...n,findByTenantAndIntegration:async(r,t)=>{m(e);let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();return i?n.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,t)=>n.findMany({where:{tenant_id:r},limit:t?.limit,offset:t?.offset}),upsertByTenantAndIntegration:async(r,t,i)=>{let o=await n.findOne({tenant_id:r,integration_id:t});return o?await n.update(o.id,i):n.create({...i,tenant_id:r,integration_id:t})}}}function te(e){let n=D(e,"corsair_entities");return{...n,findByEntityId:({accountId:r,entityType:t,entityId:i})=>n.findOne({account_id:r,entity_type:t,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:t,entityIds:i})=>i.length===0?[]:(m(e),await e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",t).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:t,limit:i,offset:o})=>n.findMany({where:{account_id:r,entity_type:t},limit:i,offset:o}),searchByEntityId:async({accountId:r,entityType:t,query:i,limit:o,offset:u})=>{m(e);let a=e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",t).where("entity_id","like",`%${i}%`);return typeof o=="number"&&(a=a.limit(o)),typeof u=="number"&&(a=a.offset(u)),await a.execute()},upsertByEntityId:async({accountId:r,entityType:t,entityId:i,version:o,data:u})=>{let a=await n.findOne({account_id:r,entity_type:t,entity_id:i});return a?await n.update(a.id,{version:o,data:u}):n.create({account_id:r,entity_type:t,entity_id:i,version:o,data:u})},deleteByEntityId:async({accountId:r,entityType:t,entityId:i})=>{m(e);let o=await e.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",t).where("entity_id","=",i).executeTakeFirst();return Number(o.numDeletedRows)>0}}}function ne(e){let n=D(e,"corsair_events");return{...n,listByAccount:(r,t)=>n.findMany({where:{account_id:r},limit:t?.limit,offset:t?.offset}),listByStatus:(r,t)=>{let i={status:r};return t?.accountId&&(i.account_id=t.accountId),n.findMany({where:i,limit:t?.limit,offset:t?.offset})},listPending:r=>{let t={status:"pending"};return r?.accountId&&(t.account_id=r.accountId),n.findMany({where:t,limit:r?.limit??100})},updateStatus:(r,t)=>n.update(r,{status:t})}}function W(e){return{integrations:V(e),accounts:ee(e),entities:te(e),events:ne(e)}}function re(e,n,r,t,i){let o=null;async function u(){if(o!==null)return o;m(e);let a=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n.integrationName).executeTakeFirst();if(!a)throw new Error(`Integration "${n.integrationName}" not found. Make sure to create the integration first.`);let y=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n.tenantId).where("integration_id","=",a.id).executeTakeFirst();if(!y)throw new Error(`Account not found for tenant "${n.tenantId}" and integration "${n.integrationName}". Make sure to create the account first.`);return o=y.id,o}return m(e),v(e.db,u,r,t,i)}function j(e){let{database:n,integrationName:r,schema:t,tenantId:i}=e,o=W(n),u={tenantId:i,integrationName:r},a=null;async function y(){if(a!==null)return a;m(n);let c=await n.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!c)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);let s=await n.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",i).where("integration_id","=",c.id).executeTakeFirst();if(!s)throw new Error(`Account not found for tenant "${i}" and integration "${r}". Make sure to create the account first.`);return a=s.id,a}let d={};for(let[c,s]of Object.entries(t.entities))d[c]=re(n,u,c,t.version,s);return{...d,$orm:o,$integrationName:r,$tenantId:i,$getAccountId:y}}function pe(e,n){let r=W(e);return{$tenantId:n,$orm:r,listAccounts:t=>r.accounts.listByTenant(n,t),findAccountByIntegration:t=>r.accounts.findByTenantAndIntegration(n,t),listEntities:async t=>{m(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let o=i.map(a=>a.id),u=e.db.selectFrom("corsair_entities").selectAll().where("account_id","in",o);return t?.entityType&&(u=u.where("entity_type","=",t.entityType)),typeof t?.limit=="number"&&(u=u.limit(t.limit)),typeof t?.offset=="number"&&(u=u.offset(t.offset)),await u.execute()},listEvents:async t=>{m(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let o=i.map(a=>a.id),u=e.db.selectFrom("corsair_events").selectAll().where("account_id","in",o);return t?.status&&(u=u.where("status","=",t.status)),typeof t?.limit=="number"&&(u=u.limit(t.limit)),typeof t?.offset=="number"&&(u=u.offset(t.offset)),await u.execute()},forIntegration:t=>j({database:e,integrationName:t.integrationName,schema:t.schema,tenantId:n})}}function ge(e,n){return{forTenant:r=>j({database:e,integrationName:n.integrationName,schema:n.schema,tenantId:r})}}export{C as a,v as b,X as c,W as d,j as e,pe as f,ge as g};
@@ -1,5 +1,5 @@
1
- import{G as R,H as v,j as m,k as A,l as _}from"./chunk-LIZVHWQK.js";import{a as j}from"./chunk-UBM25HVI.js";import{Kysely as F}from"kysely";import{ZodBoolean as x,ZodDate as E,ZodEnum as D,ZodNullable as K,ZodNumber as N,ZodObject as B,ZodOptional as Z,ZodRecord as L,ZodString as U,ZodType as W}from"zod";var I={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:{}}}};async function pn(n,e){let s=[],i=d=>{s.push(d),console.log(d)},a=d=>{s.push(d),console.warn(d)},t=e?.caller??"script",f=q(n);if(!f)throw new Error("setupCorsair: invalid corsair instance");if(!f.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let o=Q(n,f.plugins,e),r={...f,database:f.database},c=r.database.db;await X(c,a);let l=await nn(c,r,o.tenantId,o.provisionAccounts,i);e?.credentials&&Object.keys(e.credentials).length>0&&await sn(n,o,e.credentials,r,i,a);let y=await rn(l,o,i,t);if(e?.backfill){i("[corsair:setup] Starting backfill...");let d=v({plugins:f.plugins,database:c,kek:f.kek,multiTenancy:!0}).withTenant(o.tenantId);await on(d,f.plugins,y,i,a),i("[corsair:setup] Backfill complete.")}return s.join(`
2
- `)}function w(n){return typeof n=="object"&&n!==null}function Y(n){return!w(n)||!Array.isArray(n.plugins)||typeof n.kek!="string"||typeof n.multiTenancy!="boolean"?!1:n.database===void 0?!0:w(n.database)?n.database.db instanceof F:!1}function q(n){let e=Object.getOwnPropertyDescriptor(n,R);if(e)return Y(e.value)?e.value:void 0}function z(n){return n==="oauth_2"||n==="api_key"||n==="bot_token"}function P(n){let e=n.options?.authType;return z(e)?e:void 0}function H(n){return"withTenant"in n&&typeof n.withTenant=="function"}function $(n,e,s){let i=s==="integration"?n.authConfig?.[e]?.integration??[]:n.authConfig?.[e]?.account??[];return new Set([...m[e][s],...i])}function J(n,e){if(!n)return!1;for(let[s,i]of Object.entries(n)){let a=e.find(o=>o.id===s);if(!a)continue;let t=P(a);if(!t)continue;let f=$(a,t,"account");for(let o of Object.keys(i))if(f.has(o))return!0}return!1}function Q(n,e,s){let i=H(n),a=s?.tenantId?.trim(),t=a!==void 0&&a.length>0;if(i&&s?.backfill&&!t)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(i&&J(s?.credentials,e)&&!t)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(t&&!a)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:i,tenantIdProvided:t,tenantId:t?a:"default",provisionAccounts:!i||t}}function C(n,e){if(!w(n))return;let s=n[e];return typeof s=="function"?(...i)=>Reflect.apply(s,n,i):void 0}function O(n,e){return w(n)?e===0?!0:Object.values(n).every(s=>O(s,e-1)):!1}function V(n){return O(n,4)}var G={...j};function S(n){if(n instanceof B){let e={};for(let[s,i]of Object.entries(n.shape))e[s]=i instanceof W?S(i):"unknown";return e}return n instanceof K?`${S(n.unwrap())} | null`:n instanceof Z?`${S(n.unwrap())} | undefined`:n instanceof D?n.options.join(" | "):n instanceof U?"string":n instanceof N?"number":n instanceof x?"boolean":n instanceof E?"date":n instanceof L?"jsonb":"unknown"}async function X(n,e){let s=await n.introspection.getTables(),i=new Set(s.map(a=>a.name));for(let[a,t]of Object.entries(G))i.has(a)||e(`[corsair:setup] Table "${a}" does not exist. Run your database migrations before calling setupCorsair.
3
- Schema: ${JSON.stringify(S(t),null,2)}`)}async function nn(n,e,s,i,a){let t=new Date,f=new Map;for(let o of e.plugins){let r=o.id,c=P(o),l=await n.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!l){let u=crypto.randomUUID();await n.insertInto("corsair_integrations").values({id:u,name:r,config:{},created_at:t,updated_at:t}).execute(),l=await n.selectFrom("corsair_integrations").selectAll().where("id","=",u).executeTakeFirst(),a(`[corsair:setup] Created integration: ${r}`)}let y=c?o.authConfig?.[c]?.integration??[]:[],d=c?o.authConfig?.[c]?.account??[]:[],g=c&&l?A({authType:c,integrationName:r,kek:e.kek,database:e.database,extraIntegrationFields:y}):void 0;if(l&&!l.dek&&g&&(await g.issue_new_dek(),a(`[corsair:setup] Issued integration DEK: ${r}`)),!l||!c||!g)continue;let p;if(i){let u=await n.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",s).where("integration_id","=",l.id).executeTakeFirst();if(!u){let h=crypto.randomUUID();await n.insertInto("corsair_accounts").values({id:h,tenant_id:s,integration_id:l.id,config:{},created_at:t,updated_at:t}).execute(),u=await n.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),a(`[corsair:setup] Created account: ${r}`)}p=u&&_({authType:c,integrationName:r,tenantId:s,kek:e.kek,database:e.database,extraAccountFields:d}),u&&p&&!u.dek&&(await p.issue_new_dek(),a(`[corsair:setup] Issued account DEK: ${r}`))}f.set(r,{pluginId:r,authType:c,integration:g,account:p,integrationFields:[...m[c].integration,...y],accountFields:i?[...m[c].account,...d]:[]})}return f}function en(n){if(!w(n))return;let e=n.keys;return w(e)?e:void 0}function tn(n,e){return"withTenant"in n&&typeof n.withTenant=="function"?n.withTenant(e):n}async function sn(n,e,s,i,a,t){let f=en(n),o=e.provisionAccounts?tn(n,e.tenantId):void 0;for(let[r,c]of Object.entries(s)){let l=i.plugins.find(b=>b.id===r);if(!l){t(`[corsair:setup] Unknown plugin '${r}' \u2014 skipping credentials.`);continue}let y=P(l);if(!y){t(`[corsair:setup] Plugin '${r}' has no auth type \u2014 skipping credentials.`);continue}let d=$(l,y,"integration"),g=$(l,y,"account"),p=f?.[r],u=o?.[r],h=w(u)?u.keys:void 0;for(let[b,T]of Object.entries(c))if(T){if(d.has(b)){if(e.multiTenant&&e.tenantIdProvided)throw new Error(`[corsair:setup] '${r}.${b}' is an integration-level credential shared across all tenants. You passed tenantId="${e.tenantId}", which only scopes account-level credentials. Run setup without --tenant if you intend to change this credential globally.`);let k=C(p,`set_${b}`);if(!k){t(`[corsair:setup] Cannot set integration field '${b}' for '${r}'.`);continue}await k(T),a(`[corsair:setup] Set ${r} integration.${b}`);continue}if(g.has(b)){if(e.multiTenant&&!e.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${r}.${b}' on a multi-tenant instance`);let k=C(h,`set_${b}`);if(!k){t(`[corsair:setup] Cannot set account field '${b}' for '${r}'.`);continue}await k(T),a(`[corsair:setup] Set ${r} account.${b} (tenant=${e.tenantId})`);continue}t(`[corsair:setup] Unknown credential field '${b}' for plugin '${r}'.`)}}}var M=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function an(n,e,s,i,a,t,f,o,r){let c=[],l=[];for(let d of a){if(M.has(d))continue;let g=C(s,`get_${d}`);if(!g)continue;let p=null;try{let u=await g();p=typeof u=="string"?u:null}catch{}p||c.push(d)}if(i&&t.length>0)for(let d of t){if(M.has(d))continue;let g=C(i,`get_${d}`);if(!g)continue;let p=null;try{let u=await g();p=typeof u=="string"?u:null}catch{}p||l.push(d)}let y=c.length===0&&l.length===0;if(y)o(`[corsair:setup] '${n}' (${e}) is configured \u2713`);else{let d=[...c,...l];if(r==="cli"){let g=d.map(p=>`${p}=VALUE`).join(" ");o(`[corsair:setup] '${n}' (${e}) needs credentials. Run:
1
+ import{r as m,s as _,t as R,ya as v,za as j}from"./chunk-SFZI4EL2.js";import{c as A}from"./chunk-3X6WVI5I.js";import{Kysely as F}from"kysely";import{ZodBoolean as x,ZodDate as E,ZodEnum as D,ZodNullable as K,ZodNumber as N,ZodObject as B,ZodOptional as Z,ZodRecord as L,ZodString as U,ZodType as W}from"zod";var I={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:{}}}};async function pn(n,e){let s=[],i=d=>{s.push(d),console.log(d)},a=d=>{s.push(d),console.warn(d)},t=e?.caller??"script",f=q(n);if(!f)throw new Error("setupCorsair: invalid corsair instance");if(!f.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let o=Q(n,f.plugins,e),r={...f,database:f.database},c=r.database.db;await X(c,a);let l=await nn(c,r,o.tenantId,o.provisionAccounts,i);e?.credentials&&Object.keys(e.credentials).length>0&&await sn(n,o,e.credentials,r,i,a);let y=await rn(l,o,i,t);if(e?.backfill){i("[corsair:setup] Starting backfill...");let d=j({plugins:f.plugins,database:c,kek:f.kek,multiTenancy:!0}).withTenant(o.tenantId);await on(d,f.plugins,y,i,a),i("[corsair:setup] Backfill complete.")}return s.join(`
2
+ `)}function w(n){return typeof n=="object"&&n!==null}function Y(n){return!w(n)||!Array.isArray(n.plugins)||typeof n.kek!="string"||typeof n.multiTenancy!="boolean"?!1:n.database===void 0?!0:w(n.database)?n.database.db instanceof F:!1}function q(n){let e=Object.getOwnPropertyDescriptor(n,v);if(e)return Y(e.value)?e.value:void 0}function z(n){return n==="oauth_2"||n==="api_key"||n==="bot_token"}function P(n){let e=n.options?.authType;return z(e)?e:void 0}function H(n){return"withTenant"in n&&typeof n.withTenant=="function"}function $(n,e,s){let i=s==="integration"?n.authConfig?.[e]?.integration??[]:n.authConfig?.[e]?.account??[];return new Set([...m[e][s],...i])}function J(n,e){if(!n)return!1;for(let[s,i]of Object.entries(n)){let a=e.find(o=>o.id===s);if(!a)continue;let t=P(a);if(!t)continue;let f=$(a,t,"account");for(let o of Object.keys(i))if(f.has(o))return!0}return!1}function Q(n,e,s){let i=H(n),a=s?.tenantId?.trim(),t=a!==void 0&&a.length>0;if(i&&s?.backfill&&!t)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(i&&J(s?.credentials,e)&&!t)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(t&&!a)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:i,tenantIdProvided:t,tenantId:t?a:"default",provisionAccounts:!i||t}}function C(n,e){if(!w(n))return;let s=n[e];return typeof s=="function"?(...i)=>Reflect.apply(s,n,i):void 0}function O(n,e){return w(n)?e===0?!0:Object.values(n).every(s=>O(s,e-1)):!1}function V(n){return O(n,4)}var G={...A};function S(n){if(n instanceof B){let e={};for(let[s,i]of Object.entries(n.shape))e[s]=i instanceof W?S(i):"unknown";return e}return n instanceof K?`${S(n.unwrap())} | null`:n instanceof Z?`${S(n.unwrap())} | undefined`:n instanceof D?n.options.join(" | "):n instanceof U?"string":n instanceof N?"number":n instanceof x?"boolean":n instanceof E?"date":n instanceof L?"jsonb":"unknown"}async function X(n,e){let s=await n.introspection.getTables(),i=new Set(s.map(a=>a.name));for(let[a,t]of Object.entries(G))i.has(a)||e(`[corsair:setup] Table "${a}" does not exist. Run your database migrations before calling setupCorsair.
3
+ Schema: ${JSON.stringify(S(t),null,2)}`)}async function nn(n,e,s,i,a){let t=new Date,f=new Map;for(let o of e.plugins){let r=o.id,c=P(o),l=await n.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!l){let u=crypto.randomUUID();await n.insertInto("corsair_integrations").values({id:u,name:r,config:{},created_at:t,updated_at:t}).execute(),l=await n.selectFrom("corsair_integrations").selectAll().where("id","=",u).executeTakeFirst(),a(`[corsair:setup] Created integration: ${r}`)}let y=c?o.authConfig?.[c]?.integration??[]:[],d=c?o.authConfig?.[c]?.account??[]:[],g=c&&l?_({authType:c,integrationName:r,kek:e.kek,database:e.database,extraIntegrationFields:y}):void 0;if(l&&!l.dek&&g&&(await g.issue_new_dek(),a(`[corsair:setup] Issued integration DEK: ${r}`)),!l||!c||!g)continue;let p;if(i){let u=await n.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",s).where("integration_id","=",l.id).executeTakeFirst();if(!u){let h=crypto.randomUUID();await n.insertInto("corsair_accounts").values({id:h,tenant_id:s,integration_id:l.id,config:{},created_at:t,updated_at:t}).execute(),u=await n.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),a(`[corsair:setup] Created account: ${r}`)}p=u&&R({authType:c,integrationName:r,tenantId:s,kek:e.kek,database:e.database,extraAccountFields:d}),u&&p&&!u.dek&&(await p.issue_new_dek(),a(`[corsair:setup] Issued account DEK: ${r}`))}f.set(r,{pluginId:r,authType:c,integration:g,account:p,integrationFields:[...m[c].integration,...y],accountFields:i?[...m[c].account,...d]:[]})}return f}function en(n){if(!w(n))return;let e=n.keys;return w(e)?e:void 0}function tn(n,e){return"withTenant"in n&&typeof n.withTenant=="function"?n.withTenant(e):n}async function sn(n,e,s,i,a,t){let f=en(n),o=e.provisionAccounts?tn(n,e.tenantId):void 0;for(let[r,c]of Object.entries(s)){let l=i.plugins.find(b=>b.id===r);if(!l){t(`[corsair:setup] Unknown plugin '${r}' \u2014 skipping credentials.`);continue}let y=P(l);if(!y){t(`[corsair:setup] Plugin '${r}' has no auth type \u2014 skipping credentials.`);continue}let d=$(l,y,"integration"),g=$(l,y,"account"),p=f?.[r],u=o?.[r],h=w(u)?u.keys:void 0;for(let[b,T]of Object.entries(c))if(T){if(d.has(b)){if(e.multiTenant&&e.tenantIdProvided)throw new Error(`[corsair:setup] '${r}.${b}' is an integration-level credential shared across all tenants. You passed tenantId="${e.tenantId}", which only scopes account-level credentials. Run setup without --tenant if you intend to change this credential globally.`);let k=C(p,`set_${b}`);if(!k){t(`[corsair:setup] Cannot set integration field '${b}' for '${r}'.`);continue}await k(T),a(`[corsair:setup] Set ${r} integration.${b}`);continue}if(g.has(b)){if(e.multiTenant&&!e.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${r}.${b}' on a multi-tenant instance`);let k=C(h,`set_${b}`);if(!k){t(`[corsair:setup] Cannot set account field '${b}' for '${r}'.`);continue}await k(T),a(`[corsair:setup] Set ${r} account.${b} (tenant=${e.tenantId})`);continue}t(`[corsair:setup] Unknown credential field '${b}' for plugin '${r}'.`)}}}var M=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function an(n,e,s,i,a,t,f,o,r){let c=[],l=[];for(let d of a){if(M.has(d))continue;let g=C(s,`get_${d}`);if(!g)continue;let p=null;try{let u=await g();p=typeof u=="string"?u:null}catch{}p||c.push(d)}if(i&&t.length>0)for(let d of t){if(M.has(d))continue;let g=C(i,`get_${d}`);if(!g)continue;let p=null;try{let u=await g();p=typeof u=="string"?u:null}catch{}p||l.push(d)}let y=c.length===0&&l.length===0;if(y)o(`[corsair:setup] '${n}' (${e}) is configured \u2713`);else{let d=[...c,...l];if(r==="cli"){let g=d.map(p=>`${p}=VALUE`).join(" ");o(`[corsair:setup] '${n}' (${e}) needs credentials. Run:
4
4
  corsair setup --${n} ${g}`)}else{let g=[`[corsair:setup] '${n}' (${e}) needs credentials. Call:`];for(let p of c)g.push(` await corsair.keys.${n}.set_${p}(value)`);for(let p of l){let u=f.provisionAccounts?f.tenantId==="default"?`corsair.${n}`:`corsair.withTenant(${JSON.stringify(f.tenantId)}).${n}`:`corsair.withTenant(<tenant>).${n}`;g.push(` await ${u}.keys.set_${p}(value)`)}o(g.join(`
5
5
  `))}}return y}async function rn(n,e,s,i){let a=new Set;for(let t of n.values())await an(t.pluginId,t.authType,t.integration,t.account,t.integrationFields,t.accountFields,e,s,i)&&a.add(t.pluginId);return a}async function on(n,e,s,i,a){if(!V(I)){a("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let t=I,f=new Set(e.map(o=>o.id));for(let[o,r]of Object.entries(t)){if(!f.has(o))continue;if(!s.has(o)){i(`[corsair:setup] Skipping backfill for '${o}' \u2014 auth not configured.`);continue}let c=w(n)?n[o]:void 0,l=w(c)?c.api:void 0;if(l)for(let[y,d]of Object.entries(r))for(let[g,p]of Object.entries(d)){i(`[corsair:setup] Backfilling ${o} \u203A ${y}.${g}...`);try{let u=w(l)?l[y]:void 0;await C(u,g)?.(p)}catch(u){a(`[corsair:setup] ${o} \u203A ${y}.${g} failed: `+(u instanceof Error?u.message:String(u)))}}}}export{pn as a,sn as b};
@@ -0,0 +1 @@
1
+ import{a as c}from"./chunk-QAIKSQAD.js";import{Kysely as o,PostgresDialect as f,SqliteDialect as C}from"kysely";import{PostgresJSDialect as b}from"kysely-postgres-js";function _(t){return typeof t.query=="function"&&typeof t.connect=="function"}function m(t){let r=t;return typeof r.prepare=="function"&&typeof r.exec=="function"&&typeof r.close=="function"&&!("query"in t)}function x(t){return typeof t=="function"&&typeof t.begin=="function"&&typeof t.end=="function"}function p(t,r){return typeof t=="function"?t.bind(r):t}var w=114,D=3802;function k(t){if(typeof t!="object"||t===null||Buffer.isBuffer(t))return!1;if(Array.isArray(t))return!0;let r=Object.getPrototypeOf(t);return r===Object.prototype||r===null}function S(t){return t instanceof Date?t.toISOString():k(t)?JSON.stringify(t):t}function I(t){let r=t.options?.serializers;if(!r)return;let n=a=>a;r[w]=n,r[D]=n}function P(t){return new Proxy(t,{get(r,n,a){return n!=="reserve"?p(Reflect.get(r,n,a),r):async function(){let d=await r.reserve();return new Proxy(d,{get(i,s,u){return s!=="unsafe"?p(Reflect.get(i,s,u),i):function(l,y,g){return i.unsafe(l,y?.map(S),g)}}})}}})}function T(t){return typeof t.selectFrom=="function"}function R(t){if(T(t))return{db:t};if(m(t))return{db:new o({dialect:new C({database:t}),plugins:[new c]})};if(_(t))return{db:new o({dialect:new f({pool:t})})};if(x(t))return I(t),{db:new o({dialect:new b({postgres:P(t)})})};throw new Error("Unsupported database input. Expected a pg Pool, postgres.js Sql, better-sqlite3 Database, or a Kysely instance.")}import{z as e}from"zod";var U=e.object({id:e.string(),created_at:e.coerce.date(),updated_at:e.coerce.date(),name:e.string(),config:e.record(e.string(),e.unknown()).nullable().transform(t=>t??{}),dek:e.string().nullish()}),h=e.object({id:e.string(),created_at:e.coerce.date(),updated_at:e.coerce.date(),tenant_id:e.string(),integration_id:e.string(),config:e.record(e.string(),e.unknown()).nullable().transform(t=>t??{}),dek:e.string().nullish()}),A=e.object({id:e.string(),created_at:e.coerce.date(),updated_at:e.coerce.date(),account_id:e.string(),entity_id:e.string(),entity_type:e.string(),version:e.string(),data:e.record(e.string(),e.unknown()).nullable().transform(t=>t??{})}),z=e.object({id:e.string(),created_at:e.coerce.date(),updated_at:e.coerce.date(),account_id:e.string(),event_type:e.string(),payload:e.record(e.string(),e.unknown()).nullable().transform(t=>t??{}),status:e.enum(["pending","processing","completed","failed"]).optional()}),j=e.object({id:e.string(),created_at:e.coerce.date(),updated_at:e.coerce.date(),token:e.string(),plugin:e.string(),endpoint:e.string(),args:e.string(),tenant_id:e.string(),status:e.enum(["pending","approved","executing","completed","denied","expired","failed"]).default("pending"),expires_at:e.string(),error:e.string().nullable().optional()});export{R as a,U as b,h as c,A as d,z as e,j as f};
@@ -0,0 +1,26 @@
1
+ import{a as Fn,b as rn,d as Ce}from"./chunk-3X6WVI5I.js";import{a as Mn}from"./chunk-IGGCNGU2.js";import*as St from"querystring";var Te=["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"],Nn={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 ge(e){let n=Nn[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var fe="https://auth.corsair.dev";var q=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret, deliveryUrl } to createCorsair()."),this.name="HubNotConfiguredError"}};function Ft(e){let n=e[x];if(!n)throw new Error("Invalid corsair instance");return n}function xe(e){let n=(e.apiUrl?.trim()||fe).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim(),i=e.deliveryUrl.trim();if(!t||!r||!i)throw new Error("Hub config requires non-empty projectApiKey, signingSecret, and deliveryUrl");return{apiUrl:n,projectApiKey:t,signingSecret:r,deliveryUrl:i,oauthCallbackUrl:e.oauthCallbackUrl?.trim()}}function Nt(e){return e.apiUrl.trim().length>0&&e.deliveryUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function G(e){let n=Ft(e).hub;if(!n||!Nt(n))throw new q;return n}function Pe(e){return e.oauthCallbackUrl?e.oauthCallbackUrl:`${e.apiUrl.replace(/\/$/,"")}/oauth/callback`}import*as ye from"crypto";function L(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function on(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 Y(e,n){let t=ye.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var $t=600*1e3;function Ae(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"),s=Buffer.from(i,"base64url"),a=Buffer.from(o,"base64url");return s.length!==a.length||!ye.timingSafeEqual(s,a)?null:on(r,{maxAgeMs:$t})}function Re(e){return typeof e=="string"&&e.length>0}function Wt(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!Re(n.connectUrl)||!Re(n.token)||!Re(n.projectId))throw new Error("Hub API returned an incomplete connect session (expected connectUrl, token, and projectId)");let t={connectUrl:n.connectUrl,token:n.token,projectId:n.projectId};return Re(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Bt(e,n){if(n===404)return"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.";if(e&&typeof e=="object"){let t=e;if(t.error)return t.error;if(t.message)return t.message}return`Hub API returned HTTP ${n}`}async function Ut(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 Lt(e){let n=e[x];if(!n?.kek)throw new Error("Corsair KEK is required to create a managed connect session");return n.kek}async function Ie(e,n){let t=G(e),r=t.apiUrl.replace(/\/$/,""),i=n.oauthMode??"byo",o=n.providerName??ge(n.plugin),s;if(i==="managed"){let d=Lt(e),l=Y(L(n.plugin,n.tenantId),d);s={plugin:n.plugin,tenantId:n.tenantId,providerName:o,state:l,deliveryUrl:t.deliveryUrl,source:n.source,oauthMode:"managed"}}else{let d=Pe(t),{url:l,state:u}=await sn(e,n.plugin,{tenantId:n.tenantId,redirectUri:d});s={plugin:n.plugin,tenantId:n.tenantId,providerName:o,oauthUrl:l,state:u,deliveryUrl:t.deliveryUrl,source:n.source,oauthMode:"byo"}}let a=await fetch(`${r}/connect/sessions`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${t.projectApiKey}`},body:JSON.stringify(s)}),c=await Ut(a);if(!a.ok)throw new Error(Bt(c,a.status));return Wt(c)}var Kt=new Set(["localhost","127.0.0.1","[::1]"]);function an(e){let n=new URL(e).hostname;return Kt.has(n)}function jt(e){if(e==="byo"||e==="managed")return e}function Zt(e){if(e==="client"||e==="server")return e}function cn(e){let n=e.plugin?.trim(),t=e.tenantId?.trim()||"default",r=Zt(e.source),i=jt(e.oauthMode),o=e.providerName?.trim();if(!n)return{error:"plugin is required",status:400};if(!r)return{error:'source is required and must be "client" or "server"',status:400};if(e.oauthMode&&!i)return{error:'oauthMode must be "byo" or "managed"',status:400};let s={plugin:n,tenantId:t,source:r,oauthMode:i};return o&&(s.providerName=o),s}function un(e){let{searchParams:n}=new URL(e),t=n.get("oauthMode");return{plugin:n.get("plugin")??void 0,tenantId:n.get("tenantId")??void 0,source:n.get("source")??void 0,oauthMode:t??void 0,providerName:n.get("providerName")??void 0}}function dn(e,n){return e.oauthMode!=="managed"||e.source!=="server"?null:an(n)?{error:'managed OAuth with a loopback delivery URL requires source: "client"',status:400}:null}function qt(e){return{ok:!0,connectUrl:e.connectUrl,token:e.token,projectId:e.projectId,expiresAt:e.expiresAt}}async function Gt(e,n,t){if(t?.resolveTenantId){let r=await t.resolveTenantId(e);return r?.trim()?r.trim():{error:"Unauthorized",status:401}}return n.tenantId?.trim()||t?.defaultTenantId?.trim()||"default"}async function ln(e,n,t){let i=n.method.toUpperCase()==="GET"?un(n.url):await n.json().catch(()=>null);if(!i)return{error:"Invalid JSON body",status:400};let o=await Gt(n,i,t);if(typeof o!="string")return o;let s=cn({...i,tenantId:o});if("error"in s)return s;let a=G(e),c=dn(s,a.deliveryUrl);if(c)return c;let d=await Ie(e,s);return qt(d)}async function pn(e,n,t){try{let r=await ln(e,n,t);return"error"in r?Response.json({error:r.error},{status:r.status}):Response.json(r)}catch(r){if(r instanceof q)return Response.json({error:r.message},{status:503});let i=r instanceof Error?r.message:String(r);return Response.json({error:i},{status:500})}}async function ve(e,n,t){let r=n.method.toUpperCase();return r!=="GET"&&r!=="POST"?Response.json({error:"Method not allowed"},{status:405}):pn(e,n,t)}import{createHmac as cr,timingSafeEqual as ur}from"crypto";async function _e(e,n,t){for(let r of e){if(r.id!==n)continue;let i=r.oauthWebhookTenantLinkResolver;return i?i(t):null}return null}import{createCipheriv as $n,createDecipheriv as Wn,randomBytes as Ee,scrypt as zt}from"crypto";import{promisify as Jt}from"util";var Bn=Jt(zt),Se="aes-256-gcm",Un=12,Oe=16,Vt=16,he=32;function H(){return Ee(he).toString("base64")}async function M(e,n){let t=Ee(Vt),r=await Bn(n,t,he),i=Ee(Un),o=$n(Se,r,i,{authTagLength:Oe}),s=Buffer.concat([o.update(e,"utf8"),o.final()]),a=o.getAuthTag();return[t.toString("base64"),i.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function F(e,n){let[t,r,i,o]=e.split(":");if(!t||!r||!i||!o)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(i,"base64"),d=Buffer.from(o,"base64"),l=await Bn(n,s,he),u=Wn(Se,l,a,{authTagLength:Oe});return u.setAuthTag(c),Buffer.concat([u.update(d),u.final()]).toString("utf8")}function gn(e,n){let t=Buffer.from(n,"base64"),r=Ee(Un),i=$n(Se,t,r,{authTagLength:Oe}),o=Buffer.concat([i.update(e,"utf8"),i.final()]),s=i.getAuthTag();return[r.toString("base64"),s.toString("base64"),o.toString("base64")].join(":")}function me(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"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(i,"base64"),d=Wn(Se,o,s,{authTagLength:Oe});return d.setAuthTag(a),Buffer.concat([d.update(c),d.final()]).toString("utf8")}function X(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=gn(i,n);return t}function z(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=me(i,n);return t}function ke(e,n,t){let r=z(e,n);return X(r,t)}var ie={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 Ln(e,n,t){let r={};for(let i of t)r[`get_${i}`]=async()=>(await e())[i]??null,r[`set_${i}`]=async o=>{let s=[null,void 0,""].includes(o)?null:o;await n({[i]:s})};return r}var fn=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function N(e){let{authType:n,integrationName:t,kek:r,database:i,extraIntegrationFields:o=[]}=e,s=[...ie[n].integration,...o],a=null,c={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let p=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!p)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:p.id,config:fn(p.config),dek:p.dek??null},a},updateIntegration:async p=>{let y=await c.getIntegration();await i.db.updateTable("corsair_integrations").set({...p.config!==void 0?{config:p.config}:{},...p.dek!==void 0?{dek:p.dek}:{},updated_at:new Date}).where("id","=",y.id).execute(),a=null}},d=null,l=async()=>{if(d)return d;let p=await c.getIntegration();if(!p.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return d=await F(p.dek,r),d},u=async()=>{let p=await c.getIntegration(),y=await l(),m=p.config;return!m||Object.keys(m).length===0?{}:z(m,y)};return{get_dek:l,issue_new_dek:async()=>{let p=await c.getIntegration(),y=H(),m={};if(p.dek){let w=await F(p.dek,r),T=p.config;T&&Object.keys(T).length>0&&(m=ke(T,w,y))}let k=await M(y,r);return await c.updateIntegration({config:m,dek:k}),d=y,y},...Ln(u,async p=>{let y=await l(),m;try{m=await u()}catch(T){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,T),m={}}let k={...m};for(let[T,h]of Object.entries(p))h===null?delete k[T]:k[T]=h;let w=X(k,y);await c.updateIntegration({config:w})},s)}}function K(e){let{authType:n,integrationName:t,tenantId:r,kek:i,database:o,extraAccountFields:s=[]}=e,a=[...ie[n].account,...s],c=null,d=null,l=async()=>{if(d)return d;let h=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!h)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return d={id:h.id,config:fn(h.config),dek:h.dek??null},d},u={kek:i,integrationName:t,tenantId:r,getIntegration:l,getAccount:async()=>{if(c)return c;let h=await l(),b=await o.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",h.id).executeTakeFirst();if(!b)throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`);return c={id:b.id,config:fn(b.config),dek:b.dek??null},c},updateAccount:async h=>{let b=await u.getAccount();await o.db.updateTable("corsair_accounts").set({...h.config!==void 0?{config:h.config}:{},...h.dek!==void 0?{dek:h.dek}:{},updated_at:new Date}).where("id","=",b.id).execute(),c=null}},g=null,f=null,p=async()=>{if(g)return g;let h=await u.getAccount();if(!h.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await F(h.dek,i),g},y=async()=>{if(f)return f;let h=await u.getIntegration();if(!h.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await F(h.dek,i),f},m=async()=>{let h=await u.getAccount(),b=await p(),C=h.config;return!C||Object.keys(C).length===0?{}:z(C,b)},k=async()=>{let h=await u.getIntegration(),b=await y(),C=h.config;return!C||Object.keys(C).length===0?{}:z(C,b)},T={get_dek:p,issue_new_dek:async()=>{let h=await u.getAccount(),b=H(),C={};if(h.dek){let O=await F(h.dek,i),P=h.config;P&&Object.keys(P).length>0&&(C=ke(P,O,b))}let E=await M(b,i);return await u.updateAccount({config:C,dek:E}),g=b,b},...Ln(m,async h=>{let b=await p(),C;try{C=await m()}catch(P){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,P),C={}}let E={...C};for(let[P,_]of Object.entries(h))_===null?delete E[P]:E[P]=_;let O=X(E,b);await u.updateAccount({config:O})},a)};return n==="oauth_2"&&(T.get_integration_credentials=async()=>{let h=await k();return{client_id:h.client_id||null,client_secret:h.client_secret||null,redirect_url:h.redirect_url??null}}),T}async function Kn(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=H(),o=await M(i,t);return await e.db.updateTable("corsair_integrations").set({dek:o,updated_at:new Date}).where("id","=",r.id).execute(),i}async function jn(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 s=H(),a=await M(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",o.id).execute(),s}var Zn=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function Qt(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 Yt(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 F(n.dek,e.kek),r=Zn(n.config),i={};Object.keys(r).length>0&&(i=z(r,t)),i[e.link.linkType]=e.link.externalId;let o=X(i,t);await e.database.db.updateTable("corsair_accounts").set({config:o,updated_at:new Date}).where("id","=",n.id).execute()}async function ce(e){let{database:n,kek:t,pluginId:r,tenantId:i,link:o,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await Qt({database:n,pluginId:r,tenantId:i}),d=!1;if(s){let l=K({authType:s,integrationName:r,tenantId:i,kek:t,database:n,extraAccountFields:a}),u=`set_${o.linkType}`,g=l[u];typeof g=="function"&&(await g(o.externalId),d=!0)}d||await Yt({database:n,kek:t,accountId:c,link:o})}async function yn(e){let{database:n,kek:t,pluginId:r,linkType:i,externalId:o}=e,s=await n.db.selectFrom("corsair_accounts as accounts").innerJoin("corsair_integrations as integrations","integrations.id","accounts.integration_id").selectAll("accounts").where("integrations.name","=",r).execute();for(let a of s)if(a.dek)try{let c=await F(a.dek,t),l=Zn(a.config)[i];if(!l)continue;if(me(l,c)===o)return a}catch{continue}return null}async function De(e){return(await yn(e))?.tenant_id??null}async function qn(e){return De({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var ee=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};function Xt(e){let n=e[x];if(!n)throw new ee("invalid_corsair_instance","Invalid corsair instance");return n}function er(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw new ee("plugin_not_found",`Plugin '${n}' not found`);return t}async function nr(e,n,t,r){let i=Ce(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 a=H(),c=await M(a,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:c})}async function ue(e,n){let{plugin:t,tenantId:r,accessToken:i,refreshToken:o,expiresIn:s,scope:a}=n;if(!i.trim())throw new ee("no_access_token","Managed OAuth delivery missing access_token");let c=Xt(e);if(!c.database)throw new ee("no_database","No database configured on corsair instance");let d=er(c,t);await nr(c.database,t,r,c.kek);let l=K({authType:"managed",integrationName:t,tenantId:r,kek:c.kek,database:c.database});await l.set_access_token(i),o&&await l.set_refresh_token(o),s&&await l.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await l.set_scope(a);try{let u=await _e(c.plugins,t,{access_token:i,refresh_token:o,scope:a});if(u)try{let g=d.authConfig?.managed?.account??[];await ce({database:c.database,kek:c.kek,pluginId:t,tenantId:r,link:u,authType:"managed",extraAccountFields:g})}catch(g){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,g)}}catch(u){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,u)}return{plugin:t,tenantId:r}}function tr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Gn(e,n,t=[]){for(let[r,i]of Object.entries(e))if(tr(i)){if(i.match(n))return{webhook:i,path:[...t,r]}}else if(i&&typeof i=="object"){let o=Gn(i,n,[...t,r]);if(o)return o}return null}function rr(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function or(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 zn(e,n,t,r){let i=rr(n),o=typeof t=="string"?JSON.parse(t):t;(!o||typeof o=="object"&&Object.keys(o).length===0)&&i["x-goog-resource-uri"]&&(o=or(i)||o);let a={headers:i,body:o,...r?{query:r}:{}},c=r?.tenantId||"default",d=e.withTenant?e.withTenant(c):e,l=Te;for(let u of l){let g=d[u];if(!g||!g.webhooks||g.pluginWebhookMatcher&&!g.pluginWebhookMatcher(a))continue;let f=Gn(g.webhooks,a);if(!f)continue;let p=f.path.join("."),y={payload:o,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let m=await f.webhook.handler(y),k=!!Object.keys(m.returnToSender||{})?.length;return{plugin:u,action:p,body:o,response:k?{...m?.returnToSender,success:!0}:{success:!0},...m.responseHeaders&&{responseHeaders:m.responseHeaders}}}catch(m){return console.error(`Error executing webhook handler for ${u}.${p}:`,m),{plugin:u,action:p,body:o,response:{success:!1,error:m instanceof Error?m.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHmac as ir,timingSafeEqual as sr}from"crypto";function He(e){return e.deliveryMode==="oauth.tokens"||typeof e.accessToken=="string"&&e.accessToken.length>0}function Jn(e){let n=e.trim();return n.length>0?n:null}function ar(e,n){let t=Jn(n);if(!t)throw new Error("Signing secret is required for browser delivery tokens");return ir("sha256",t).update(e).digest("base64url")}function Me(e,n){let t=Jn(n);if(!t)return null;let r=e.split(".");if(r.length!==2)return null;let[i,o]=r;if(!i||!o)return null;let s=ar(i,t);try{if(!sr(Buffer.from(o,"utf8"),Buffer.from(s,"utf8")))return null}catch{return null}let a;try{a=JSON.parse(Buffer.from(i,"base64url").toString("utf8"))}catch{return null}return a.exp*1e3<Date.now()?null:a}function dr(e){let n=e[x];if(!n)throw new Error("Invalid corsair instance");return n}function lr(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}function pr(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function gr(e,n,t){if(!t.trim()||!n)return!1;let r=cr("sha256",t.trim()).update(e).digest("hex");try{return ur(Buffer.from(r,"utf8"),Buffer.from(n,"utf8"))}catch{return!1}}async function fr(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 De({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function yr(e,n,t){let r=await fr(e,n,t),i={...t.query??{},...r?{tenantId:r}:{}},o=await zn(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 s=o.response?.returnToSender,a=s&&typeof s=="object"&&typeof s.validationToken=="string"&&Object.keys(s).length===1?s.validationToken:s||(o.response?.data??o.response);return{status:"ok",webhookResponse:{status:o.response?.statusCode??200,body:a,headers:o.responseHeaders}}}async function hr(e,n){return await be(e,n),{status:"ok"}}async function mr(e,n){return await ue(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function hn(e,n,t={}){let r=dr(e),i=pr(lr(n.headers,"x-corsair-signature"));if(t.signingSecret?.trim()){if(!gr(n.body,i,t.signingSecret))return{status:"failed",retryable:!1,error:"Invalid tunnel signature"}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let o;try{o=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}switch(o.type){case"webhook":return yr(e,r,o.payload);case"oauth.callback":return hr(e,o.payload);case"oauth.tokens":return mr(e,o.payload);default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${o.type}`}}}async function Fe(e,n){let t=G(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=Me(i,t.signingSecret);if(!o)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};try{if(He(o)){if(!o.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await ue(e,{plugin:o.plugin,tenantId:o.tenantId,accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn,scope:o.scope})}else{if(!o.code||!o.state||!o.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await be(e,{code:o.code,state:o.state,redirectUri:o.redirectUri})}}catch(s){return{type:"json",status:400,body:{error:s instanceof Error?s.message:"OAuth callback failed"}}}return{type:"redirect",url:o.hubSuccessUrl}}async function Ne(e,n){let t=G(e),r=await hn(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,s=i.headers;return i.body&&typeof i.body=="object"&&!(i.body instanceof ArrayBuffer)?{type:"json",status:o,body:i.body,headers:s}:{type:"text",status:o,body:typeof i.body=="string"?i.body:i.body?JSON.stringify(i.body):null,headers:s}}function mn(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 kn(e,n){return n.method==="GET"?Fe(e,n.url):Ne(e,{headers:n.headers,body:n.body??""})}async function bn(e,n){try{let t=await kn(e,n);return mn(t)}catch(t){if(t instanceof q)return Response.json({error:t.message},{status:503});throw t}}async function $e(e,n){let t=n.method.toUpperCase();return t!=="GET"&&t!=="POST"?Response.json({error:"Method not allowed"},{status:405}):bn(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0})}var J=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 kr=300;async function br(e){let n=await e.text();if(!n)return null;try{return JSON.parse(n)}catch{throw new Error(`Hub API returned invalid JSON (HTTP ${e.status})`)}}function wr(e,n){if(e&&typeof e=="object"){let t=e;if(t.error)return t.error;if(t.message)return t.message}return`Hub token refresh failed (HTTP ${n})`}async function wn(e,n){let{keys:t,hub:r,plugin:i,tenantId:o}=e,s=n?.forceRefresh??!1,[a,c,d]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!d)throw new J(i,"managed");let l=Math.floor(Date.now()/1e3);if(!s&&a&&c&&Number(c)>l+kr)return{accessToken:a,expiresAt:Number(c),refreshed:!1};if(!d&&a&&!s)return{accessToken:a,expiresAt:c?Number(c):l+3600,refreshed:!1};let u=r.apiUrl.replace(/\/$/,""),g=await fetch(`${u}/oauth/refresh`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.projectApiKey}`},body:JSON.stringify({plugin:i,tenantId:o})}),f=await br(g);if(!g.ok)throw new Error(wr(f,g.status));let p=f;if(!p.access_token)throw new Error("Hub token refresh returned no access_token");let y=p.expires_in?l+p.expires_in:c?Number(c):l+3600;return await t.set_access_token(p.access_token),await t.set_expires_at(String(y)),p.refresh_token&&await t.set_refresh_token(p.refresh_token),p.scope&&await t.set_scope(p.scope),{accessToken:p.access_token,expiresAt:y,refreshed:!0}}async function Vn(e,n){e._refreshAuth=async()=>(await wn(n,{forceRefresh:!0})).accessToken}function Qn(e,n){return{delivery:t=>$e(e,t),createConnectSession:t=>ve(e,t,n)}}function We(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(i,o){let s=t.length>1;throw new Error(`corsair.keys.${String(o)}: Cannot access keys because ${t.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
2
+
3
+ To generate a KEK, run: openssl rand -base64 ${he}`)}})}var Cr=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Yn(e,n,t,r,i){let o={pluginId:n,operation:t,input:r,originalError:e},s=Object.keys(i).find(d=>i[d]?.match(e,o));return await(i[s||"DEFAULT"]?.handler||Cr)(e,o)}import{randomBytes as Tr}from"crypto";import{v4 as xr}from"uuid";var Pr={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 Ar(e,n,t){return t!==void 0?t:Pr[n][e]}function et(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 nt(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 Xn(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 tt(e){let n=Ar(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}'.`,`
4
+ Action: ${r}`,`
5
+ 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(),s=e.tenantId??"default",a=await e.db.db.selectFrom("corsair_permissions").selectAll().where("plugin","=",e.pluginId).where("endpoint","=",e.endpointPath).where("args","=",i).where("tenant_id","=",s).where("expires_at",">",o).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(a){if(a.status==="approved"){let p=e.db,y=a.id;return{result:"allow",onComplete:async()=>{await p.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",y).execute()}}}return a.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
6
+ Action: ${r}`,`
7
+ Permission ID: ${a.id}`,`
8
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Xn(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token})}let c=xr(),d=Tr(32).toString("hex"),l=e.timeoutMs??600*1e3,u=new Date(Date.now()+l).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:c,created_at:new Date,updated_at:new Date,token:d,plugin:e.pluginId,endpoint:e.endpointPath,args:i,tenant_id:s,status:"pending",expires_at:u}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
9
+ Action: ${r}`,`
10
+ Permission ID: ${c}`,`
11
+ Permission token: ${d}`,`
12
+ Expires at: ${u}`,`
13
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Xn(e.db,c,l):{result:"blocked",reason:"pending",id:c,token:d}}function Rr(e){return typeof e=="function"}function Ir(e,n,t){let r=Y(L(e,n.tenantId??t??"default"),n.kek),i=new URL(n.baseUrl);i.searchParams.set("state",r);let o=i.toString(),s=n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:o,state:r}):`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${o}`;return new Error(s)}function Cn({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:i,errorHandlers:o,currentPath:s=[],keyBuilder:a,permissionsConfig:c,endpointMeta:d,database:l,approvalConfig:u,tenantId:g,connectConfig:f}){for(let[p,y]of Object.entries(e)){let m=n?.[p];if(Rr(y)){let k=m,w=[...s,p].join("."),T=async(h={})=>{let b;if(c){let v=d?.[w],{result:re,reason:D,onComplete:pe,token:Z,id:oe}=await tt({pluginId:i,endpointPath:w,args:h,mode:c.mode,override:c.overrides?.[w],riskLevel:v?.riskLevel??"write",meta:v,db:l,timeoutMs:u?et(u.timeout):void 0,tenantId:g,approvalMode:u?.mode});if(re==="blocked"){let A;throw D==="denied"?A=`Action '${w}' was denied by the user. Await further instructions before proceeding.`:D==="policy"?A=`Action '${w}' is blocked by the permission policy. Update the corsair config to allow it.`:D==="timeout"?A=`Action '${w}' timed out waiting for approval.`:u?.formatAsyncMessage&&Z&&oe?A=u.formatAsyncMessage({token:Z,id:oe,plugin:i,endpoint:w,args:h}):A=`Action '${w}' requires user approval before it can run.`,new Error(A)}b=pe}let C=async(v,re,D)=>{try{return await y(re,D)}catch(pe){if(pe instanceof Error){let Z=await Yn(pe,i,w,typeof D=="object"&&D!==null?D:{args:D},o);if(v<(Z.maxRetries||0)){let oe=v+1;console.log(`Retrying (${oe} / ${Z.maxRetries})...`);let A;if(Z.headersRetryAfterMs)A=Z.headersRetryAfterMs;else switch(Z.retryStrategy){case"exponential_backoff":A=Math.pow(2,oe-1)*1e3;break;case"exponential_backoff_jitter":let tn=Math.pow(2,oe-1)*1e3,Mt=(Math.random()-.5)*1e3;A=Math.max(0,tn+Mt);break;case"linear_1s":A=1e3;break;case"linear_2s":A=2e3;break;case"linear_3s":A=3e3;break;case"linear_4s":A=4e3;break;default:A=1e3;break}await new Promise(tn=>setTimeout(tn,A)),await C(oe,re,D),console.log(`[corsair:${i}:${w}] Retry strategy:`,Z)}}throw pe}},E;try{E=a?await a(t,"endpoint"):void 0}catch(v){throw f?.oauthConfig&&f.kek&&v instanceof J&&v.authType==="oauth_2"?Ir(i,f,g):v}if(!k?.before&&!k?.after){let v=await C(0,{...t,key:E},h);return await b?.(),v}let O={...t,key:E},P=k.before?await k.before(O,h):{ctx:O,args:h,continue:!0,passToAfter:void 0};if(P.continue===!1)return;let _=await C(0,P.ctx,P.args);return await k.after?.(P.ctx,_,P.passToAfter),await b?.(),_};r[p]=T}else if(y&&typeof y=="object"){let k={};Cn({endpoints:y,hooks:m,ctx:t,tree:k,pluginId:i,errorHandlers:o,currentPath:[...s,p],keyBuilder:a,permissionsConfig:c,endpointMeta:d,database:l,approvalConfig:u,tenantId:g,connectConfig:f}),r[p]=k}}}function vr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Tn({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:i}){for(let[o,s]of Object.entries(e)){let a=n?.[o];if(vr(s)){let c=a,d=async l=>{let u=(f,p)=>s.handler(f,p),g=i?await i(t,"webhook"):void 0;return!c?.before&&!c?.after?u({...t,key:g},l):(async()=>{let f={...t,key:g},p=c.before?await c.before(f,l):{ctx:f,args:l,continue:!0,passToAfter:void 0};if(p.continue===!1)return;let y=await u(p.ctx,p.args);return y?.success===!0&&await c.after?.(p.ctx,y,p.passToAfter),y})()};r[o]={match:s.match,handler:d}}else if(s&&typeof s=="object"){let c={};Tn({webhooks:s,hooks:a,ctx:t,webhooksTree:c,keyBuilder:i}),r[o]=c}}}function _r(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 Er(e,n,t,r,i){return e?rn(e.db,n,t,r,i):{findByEntityId:async()=>null,findById:async()=>null,findManyByEntityIds:async()=>[],list:async()=>[],search:async()=>[],upsertByEntityId:async()=>{throw new Error("Database not configured")},deleteById:async()=>!1,deleteByEntityId:async()=>!1,count:async()=>0}}function xn(e,n){let{database:t,tenantId:r,kek:i,rootErrorHandlers:o,approvalConfig:s,connectConfig:a,hubConfig:c}=n,d={},l={};for(let u of e)d[u.id]={},l[u.id]={};for(let u of e){let g=u.schema,f=r??"default",p=_r(t,u.id,f);if(g?.entities){let _={};for(let[v,re]of Object.entries(g.entities)){let D=t?rn(t.db,p,v,g.version,re):Er(void 0,p,v,g.version,re);_[v]=D}l[u.id].db=_,d[u.id].db=_}let y=u.options,m=u.authConfig,k;if(t&&i&&y?.authType){let _=m?.[y.authType]?.account??[];k=K({authType:y.authType,integrationName:u.id,tenantId:f,kek:i,database:t,extraAccountFields:_}),d[u.id].keys=k}let w={database:t,db:l[u.id]?.db??{},$getAccountId:p,...u.options?{options:u.options}:{},...k?{keys:k,authType:y?.authType}:{},tenantId:f,...c?{hub:c}:{}},T=u.endpoints??{},h=u.hooks,b={...o,...u.errorHandlers},C={},E=u.options?.permissions;Cn({endpoints:T,hooks:h,ctx:w,tree:C,pluginId:u.id,errorHandlers:b,currentPath:[],keyBuilder:u.keyBuilder,permissionsConfig:E,endpointMeta:u.endpointMeta,database:t,approvalConfig:s,tenantId:r,connectConfig:a?{...a,oauthConfig:u.oauthConfig,kek:i,tenantId:f}:void 0}),Object.keys(C).length>0&&(d[u.id].api=C),w.endpoints=C;let O=u.webhooks??{},P=u.webhookHooks;if(Object.keys(O).length>0){let _={};Tn({webhooks:O,hooks:P,ctx:w,webhooksTree:_,keyBuilder:u.keyBuilder}),d[u.id].webhooks=_,u.pluginWebhookMatcher&&(d[u.id].pluginWebhookMatcher=u.pluginWebhookMatcher),u.pluginTenantWebhookMatcher&&(d[u.id].pluginTenantWebhookMatcher=u.pluginTenantWebhookMatcher)}}return d}function rt(e,n,t){let r={};for(let i of e){let o=i.options,s=i.authConfig;if(o?.authType){let a=s?.[o.authType]?.integration??[],c=N({authType:o.authType,integrationName:i.id,kek:t,database:n,extraIntegrationFields:a});r[i.id]=c}}return r}import*as ot from"querystring";var $=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Sr(e){let n=e[x];if(!n)throw new $("invalid_corsair_instance","Invalid corsair instance");return n}function Or(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw new $("plugin_not_found",`Plugin '${n}' not found`);return t}function Dr(e){let n=e.oauthConfig;if(!n)throw new $("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Pn(e,n){let t=Sr(e);if(!t.database)throw new $("no_database","No database configured on corsair instance");let r=t.connect?.redirectUri;if(!r)throw new $("no_redirect_uri","No redirectUri configured. Set connect.redirectUri in createCorsair().");let i=Ae(n,t.kek);if(!i)throw new $("invalid_state","Invalid or tampered state parameter");let{plugin:o,tenantId:s}=i,a=Or(t,o),c=Dr(a),l=await N({authType:"oauth_2",integrationName:o,kek:t.kek,database:t.database}).get_client_id();if(!l)throw new $("client_id_not_configured",`client_id not configured for '${o}'`);let u={...c.authParams,client_id:l,redirect_uri:r,response_type:"code",scope:c.scopes.join(" "),state:n},g=`${c.authUrl}?${ot.stringify(u)}`;return{plugin:o,tenantId:s,providerName:c.providerName,oauthUrl:g,state:n}}var R=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 I(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function it(e){let n={error:e.code,message:e.message,...e.extra};return I(e.status,n)}function ne(e){return new R(404,"not_found",e)}function V(e,n={}){return new R(400,"bad_request",e,n)}function st(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw ne(`Plugin '${n}' not found`);return t}async function An(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=N({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),i=ie[t].integration,o=r,s;try{s=await Promise.all(i.map(d=>o[`get_${d}`]()))}catch{s=i.map(()=>null)}let a=i.filter((d,l)=>s[l]==null),c;return t==="oauth_2"?c=!a.includes("client_id")&&!a.includes("client_secret"):c=a.length===0,{configured:c,missingFields:a}}async function at(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:i,missingFields:o}=await An(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 Be(){return{ok:!0}}async function Ue(e){return Promise.all(e.plugins.map(n=>at(n,e)))}async function Le(e,n){let t=st(e,n);return at(t,e)}async function ct(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 ut(e,n){let t=await ct(e,n),r=t.filter(i=>i.hasCredentials).map(i=>i.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Ke(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 s=!!r.dek;o.accounts.push({integrationName:r.integrationName,hasCredentials:s}),s&&o.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function je(e,n){if(!n)throw V("Tenant id must be a non-empty string");return ut(e,n)}async function Ze(e,n){let t=n?.id?.trim();if(!t)throw V("Tenant id is required",{missingFields:["id"]});return ut(e,t)}async function qe(e,n){let t=n?.trim()||"default",r={},i=e.database?await ct(e,t):[],o=new Map(i.map(s=>[s.integrationName,s]));for(let s of e.plugins){if(!(await An(s,e)).configured){r[s.id]="missing_credentials";continue}let c=o.get(s.id),d;c&&c.hasCredentials?d="connected":d="not_connected",r[s.id]=d}return r}async function Ge(e,n){if(!e.database)throw ne(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw ne(`Permission '${n}' not found`);return t}function Hr(e){if(!e.oauthConfig)throw V(`Plugin '${e.id}' has no oauthConfig`)}function Rn(e){if(!e.connect)throw new R(500,"connect_not_configured","createCorsair was not given a connect config. Set { connect: { baseUrl, redirectUri } } to enable /connect routes.");return e.connect}async function ze(e,n){let t=n?.plugin?.trim();if(!t)throw V("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",i=st(e,t);Hr(i);let o=Rn(e);if(!e.database||!e.kek)throw new R(500,"database_not_configured","A database and kek are required to issue connect links.");let s=await An(i,e);if(!s.configured)throw new R(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=Y(L(t,r),e.kek),c;try{c=new URL(o.baseUrl)}catch{throw new R(500,"connect_misconfigured","connect.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return c.searchParams.set("state",a),{connectUrl:c.toString(),state:a}}async function Je(e,n,t){let r=t?.trim();if(!r)throw V("state is required",{missingFields:["state"]});Rn(n);try{return await Pn(e,r)}catch(i){if(i instanceof $)switch(i.code){case"invalid_state":throw V("Invalid or expired state");case"client_id_not_configured":throw new R(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new R(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function Ve(e,n,t){let r=t?.code?.trim(),i=t?.state?.trim(),o=[];if(r||o.push("code"),i||o.push("state"),o.length)throw V("Missing required fields",{missingFields:o});let s=Rn(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:i,redirectUri:s.redirectUri})}catch(c){if(c instanceof Error&&c.name==="OAuthCallbackError")switch(c.code){case"invalid_state":throw V("Invalid or expired state");case"credentials_not_configured":throw new R(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new R(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function Qe(e,n){if(!e.database)throw ne("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw ne("Permission not found");return t}var dt=[{method:"GET",pattern:"/ok",handler:async()=>I(200,Be())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>I(200,await Ke(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>I(201,await Ze(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>I(200,await je(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>I(200,await Ue(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>I(200,await Le(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>I(200,await qe(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>I(200,await Ge(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?I(200,await Qe(e,t)):I(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({internal:e,body:n})=>I(200,await ze(e,n))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>I(200,await Je(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>I(200,await Ve(e,n,t))}];(()=>{let e=new Set;for(let n of dt){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Mr(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 s=t[o],a=r[o];if(s.startsWith(":"))i[s.slice(1)]=decodeURIComponent(a);else if(s!==a)return null}return i}function Fr(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}function Nr(e){let n=e[x];if(!n)throw new Error("managementHandler: invalid corsair instance (missing internal config)");return n}async function $r(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 R(400,"invalid_json","Request body is not valid JSON")}}var Wr="/api/corsair";function se(e,n={}){let t=n.basePath??Wr,r=Nr(e);return async i=>{try{let o=new URL(i.url),s=Fr(o.pathname,t),a=i.method.toUpperCase(),c=Object.fromEntries(o.searchParams);for(let d of dt){if(d.method!==a)continue;let l=Mr(d.pattern,s);if(!l)continue;let u=await $r(i);return await d.handler({corsair:e,internal:r,req:i,params:l,query:c,body:u})}throw ne(`No route for ${a} ${s}`)}catch(o){if(n.onError){let a=await n.onError(o,i);if(a)return a}if(o instanceof R)return it(o);let s=o instanceof Error?o.message:"Internal server error";return I(500,{error:"internal_error",message:s})}}}function Br(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[c,d]of Object.entries(e.headers))if(d!=null)if(Array.isArray(d))for(let l of d)o.append(c,l);else o.set(c,d);let s=e.method!=="GET"&&e.method!=="HEAD",a={method:e.method,headers:o};return s&&e.body!==void 0&&(a.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),o.has("content-type")||o.set("content-type","application/json")),new Request(i,a)}async function Ur(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 lt(e,n){let t=se(e,n);return async(r,i,o)=>{try{let s=await t(Br(r));await Ur(i,s)}catch(s){o(s)}}}function pt(e,n){let t=se(e,n);return r=>t(r.req.raw)}function gt(e,n){let t=se(e,n);return{GET:t,POST:t}}function ft(e){let n={[x]:e};return{ok:Be,tenants:{list:()=>Ke(e),create:t=>Ze(e,t),get:t=>je(e,t)},plugins:{list:()=>Ue(e),get:t=>Le(e,t)},connectionStatus:{get:t=>qe(e,t?.tenantId)},permissions:{get:t=>Ge(e,t),getByToken:t=>Qe(e,t)},connect:{createLink:t=>ze(e,t),resolve:t=>Je(n,e,t),oauthCallback:t=>Ve(n,e,t)}}}async function yt(e,n,t,r,i="pending"){if(!e)return null;try{let o=Fn(),s=new Date;return await e.db.insertInto("corsair_events").values({id:o,created_at:s,updated_at:s,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 Lr(e,n,t,r="pending"){try{let i=await e.$getAccountId();return yt(e.database,i,n,t,r)}catch(i){return console.warn("Failed to log event:",i),null}}import*as ht from"https";import*as mt from"querystring";function Ye(e,n,t,r,i){let o=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,c)=>{let d={code:e.trim(),redirect_uri:i,grant_type:"authorization_code"};s||(d.client_id=n,d.client_secret=t);let l=mt.stringify(d),u={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(l).toString()};s&&(u.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let g=ht.request({hostname:o.hostname,...o.port?{port:Number(o.port)}:{},path:o.pathname+o.search,method:"POST",headers:u},f=>{let p="";f.on("data",y=>{p+=y}),f.on("end",()=>{if(f.statusCode!==200){c(new Error(`Token exchange failed (${f.statusCode}): ${p}`));return}try{a(JSON.parse(p))}catch{c(new Error(`Token endpoint returned non-JSON response: ${p}`))}})});g.on("error",f=>c(new Error(`Request failed: ${f.message}`))),g.write(l),g.end()})}var kt=" ";function B(e){let n=e;return n._def??n.def??{}}function U(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 wt(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 Ct(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function en(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function de(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 Tt(e,n){return e.description??n.description}function Kr(e){let n=e;for(;n;){let t=B(n),r=Tt(n,t);if(r)return r;let i=U(t);if(Sn(i)||i==="ZodPipe"||i==="ZodEffects"||i==="ZodTransform"){n=wt(t,i);continue}break}}function Sn(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function S(e){let n=B(e),t=U(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??de(n)[0]??"unknown");case"ZodEnum":return de(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=W(n);return r?S(r):"unknown"}case"ZodNullable":{let r=W(n);return`${r?S(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=W(n);return r?S(r):"unknown"}case"ZodArray":{let r=Ct(n);if(!r)return"unknown[]";let i=B(r),o=U(i)==="ZodUnion",s=S(r);return`${o?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=en(e,n),i=Object.entries(r);return i.length===0?"{}":`{ ${i.map(([s,a])=>{let c=U(B(a));return`${c==="ZodOptional"||c==="ZodNullable"?s+"?":s}: ${S(a)}`}).join(", ")} }`}case"ZodUnion":return de(n).map(r=>S(r)).join(" | ");case"ZodIntersection":return`${S(n.left)} & ${S(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=wt(n,t);return r?S(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function Q(e){let n=B(e),t=U(n),r=Tt(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??de(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=de(n).map(o=>String(o));return{kind:"string",optional:!1,description:r,enum:i}}case"ZodOptional":{let i=W(n),o=i?Q(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodNullable":{let i=W(n),o=i?Q(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodDefault":case"ZodCatch":{let i=W(n);return i?{...Q(i),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let i=Ct(n);return{kind:"array",optional:!1,description:r,items:i?Q(i):{kind:"unknown",optional:!1}}}case"ZodObject":{let i=en(e,n),o={};for(let[s,a]of Object.entries(i))o[s]=Q(a);return{kind:"object",optional:!1,description:r,fields:o}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let i=de(n);for(let o of i){let s=B(o);if(U(s)==="ZodObject")return{...Q(o),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let i=W(n);return i?{...Q(i),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Rs(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),s=e.find(l=>l.id===i);if(!s)return null;let a=o;a.startsWith("api.")&&(a=a.slice(4));let c=te(s.endpointMeta,a),d=te(s.endpointSchemas,a);return!c&&!d?null:{input:d?.input?Q(d.input):null,output:d?.output?Q(d.output):null,description:c?.description}}var On=["equals","contains","startsWith","endsWith","in"],jr=["equals","gt","gte","lt","lte","in"],Zr=["equals"],qr=["equals","before","after","between"];function xt(e){let n=B(e);switch(U(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=W(n);return r?xt(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Dn(e){let n=B(e),t=U(n);if(Sn(t)){let o=W(n);return o?Dn(o):{}}if(t!=="ZodObject")return{};let r=en(e,n),i={};for(let[o,s]of Object.entries(r)){let a=xt(s);a==="string"?i[o]={type:"string",operators:On}:a==="number"?i[o]={type:"number",operators:jr}:a==="boolean"?i[o]={type:"boolean",operators:Zr}:a==="date"&&(i[o]={type:"date",operators:qr})}return i}function Pt(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function vn(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"&&vn(i,o,t)}}function _n(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function En(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];_n(i)?t.push(o.join(".")):i!==null&&typeof i=="object"&&En(i,o,t)}}function Hn(e,n){if(n.length===0)return null;let[t,...r]=n,i=Object.entries(e).find(([a])=>a.toLowerCase()===t);if(!i)return null;let[o,s]=i;if(r.length===0)return _n(s)?[o]:null;if(s!==null&&typeof s=="object"&&!_n(s)){let a=Hn(s,r);if(a!==null)return[o,...a]}return null}function At(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let o=0;o<n.length;o++){let s=" ".repeat(o+2);t.push(`${s}${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 s=" ".repeat(o+2);t.push(`${s}},`)}return t.push(" },"),t.push("})"),t.join(`
14
+ `)}var Gr=new Set(Te);function ae(e,n){let t=n?.type??"api",r=n?.plugin;if(r!==void 0){let o=e.find(a=>a.id===r);if(!o)return Gr.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 a=[];return En(o.webhooks,[],a),a.map(c=>`${o.id}.webhooks.${c}`)}if(t==="db"){let a=o.schema?.entities;return a?Object.keys(a).map(c=>`${o.id}.db.${c}.search`):[]}if(!o.endpoints)return[];let s=[];return vn(o.endpoints,[],s),s.map(a=>`${o.id}.api.${a}`)}let i={};if(t==="webhooks")for(let o of e){if(!o.webhooks)continue;let s=[];En(o.webhooks,[],s),i[o.id]=s.map(a=>`${o.id}.webhooks.${a}`)}else if(t==="db")for(let o of e){let s=o.schema?.entities;s&&(i[o.id]=Object.keys(s).map(a=>`${o.id}.db.${a}.search`))}else for(let o of e){if(!o.endpoints)continue;let s=[];vn(o.endpoints,[],s),i[o.id]=s.map(a=>`${o.id}.api.${a}`)}return i}function te(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function zr(e,n){let t=e.toLowerCase(),r=n.toLowerCase();if(!t.startsWith(`${r}.`)){let o=t.slice(n.length+1),s=o.startsWith(".")?o.slice(1):o;return s.startsWith("api.")&&(s=s.slice(4)),{shortPath:s,lookupKey:s}}let i=e.slice(n.length+1);return i.toLowerCase().startsWith("api.")&&(i=i.slice(4)),{shortPath:i,lookupKey:i.toLowerCase()}}function In(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
15
+ ${e.join(", ")}`:`${n}:
16
+ `+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
17
+ `)}function Is(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let i=t.slice(0,r),o=t.slice(r+1),s=e.find(a=>a.id===i);if(s){if(o.startsWith("db.")){let l=o.slice(3),u=l.lastIndexOf(".");if(u!==-1){let g=l.slice(0,u),f=l.slice(u+1),p=s.schema?.entities;if(f==="search"&&p){let y=Pt(p,g);if(y){let[m,k]=y,w=Dn(k),T=[`Search ${i} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${On.join(", ")}]`];for(let[h,b]of Object.entries(w))T.push(` ${h}?: ${b.type} [${b.operators.join(", ")}]`);return T.push("}"),T.join(`
18
+ `)}}}return In(ae(e,{type:"db"}),"Path not found. Available db operations")}if(o.startsWith("webhooks.")){let l=o.slice(9);if(s.webhooks){let u=Hn(s.webhooks,l.split("."));if(u!==null){let g=u.join("."),f=te(s.webhookSchemas,g.toLowerCase()),p=f?.response?S(f.response):null,y=[];return f?.description&&y.push(f.description),f?.payload&&y.push(`payload ${Xe(le(f.payload))}`),p&&y.push(`response: ${p}`),y.push(`usage:
19
+ ${At(i,u)}`),y.join(`
20
+
21
+ `)}}return In(ae(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=o;a.startsWith("api.")&&(a=a.slice(4));let c=te(s.endpointMeta,a),d=te(s.endpointSchemas,a);if(c||d){let l=[],u=[c?.riskLevel?`[${c.riskLevel}]`:"",c?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),g=[c?.description,u].filter(Boolean).join(" ");return g&&l.push(g),d?.input&&l.push(`input ${Xe(le(d.input))}`),d?.output&&l.push(`output ${Xe(le(d.output))}`),l.join(`
22
+
23
+ `)}}}return In(ae(e),"Path not found. Available operations")}function bt(e){let n=e;for(;;){let t=B(n),r=U(t);if(Sn(r)){let i=W(t);if(!i)return n;n=i;continue}return n}}function le(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=bt(e),t=B(n);if(U(t)==="ZodObject"){let i=en(n,t),o=[];for(let[s,a]of Object.entries(i)){let c=B(a),d=U(c),l=d==="ZodOptional"||d==="ZodNullable",u=bt(a),g=Kr(a);o.push({key:s,optional:l,type:S(u),...g!==void 0?{description:g}:{}})}return{kind:"object",fields:o}}return{kind:"inline",type:S(n)}}function Xe(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=kt.repeat(n+1),r=kt.repeat(n);return`{
24
+ ${e.fields.map(o=>{let s=o.optional?`${o.key}?`:o.key,a=o.description?` // ${o.description}`:"";return`${t}${s}: ${o.type}${a}`}).join(`
25
+ `)}
26
+ ${r}}`}return"unknown"}function Jr(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(l=>l.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let i=[];for(let l of t){let{shortPath:u,lookupKey:g}=zr(l,n),f=te(r.endpointMeta,g),p=te(r.endpointSchemas,g);!f&&!p||i.push({path:l,shortPath:u,description:f?.description,riskLevel:f?.riskLevel,irreversible:f?.irreversible,input:le(p?.input),output:le(p?.output)})}i.sort((l,u)=>l.path.localeCompare(u.path));let o=[],s=ae(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let l of s){let g=l.toLowerCase().slice(n.length+1),f=g.startsWith(".")?g.slice(1):g;if(!f.startsWith("webhooks."))continue;let p=f.slice(9),y=Hn(r.webhooks,p.split("."));if(y===null)continue;let m=y.join("."),k=te(r.webhookSchemas,m.toLowerCase()),w=k?.response?S(k.response):void 0;o.push({path:l,description:k?.description,payload:le(k?.payload),responseType:w,usageExample:At(n,y)})}o.sort((l,u)=>l.path.localeCompare(u.path));let a=[],c=ae(e,{plugin:n,type:"db"}),d=r.schema?.entities;if(Array.isArray(c)&&d)for(let l of c){let g=l.toLowerCase().slice(n.length+1),f=g.startsWith(".")?g.slice(1):g;if(!f.startsWith("db."))continue;let p=f.slice(3),y=p.lastIndexOf(".");if(y===-1)continue;let m=p.slice(0,y);if(p.slice(y+1)!=="search")continue;let w=Pt(d,m);if(!w)continue;let[T,h]=w,b=Dn(h),C=Object.entries(b).map(([E,O])=>({field:E,type:O.type,operators:O.operators}));a.push({path:l,entityName:T,filters:[{field:"entity_id",type:"string",operators:On},...C]})}return a.sort((l,u)=>l.path.localeCompare(u.path)),{ok:!0,data:{pluginId:n,api:i,webhooks:o,db:a}}}function Rt(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function Vr(e,n){let t=Rt(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 Qr(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function It(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function vt(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 we(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function Yr(e){return we(e.body)}function _t(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return nn(Array.isArray(r)?r:[r])}function Et(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let d=nn(Array.isArray(c)?c:[c]);if(d)return decodeURIComponent(d)}let r=_t({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 c of i){let d=n[c],l=Array.isArray(d)?d[0]:d;if(!(!l||typeof l!="string"))try{let g=(l.startsWith("http")?new URL(l):new URL(`https://example.invalid${l.startsWith("/")?l:`/${l}`}`)).searchParams.get("validationToken");if(g?.trim())return g.trim()}catch{continue}}let o=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=we(typeof o=="string"?(()=>{try{return JSON.parse(o)}catch{return o}})():o);return nn([s?.validationToken])??null}function Xr(e){if(Et(e))return!0;let n=we(e.body??e.payload);return It(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function nn(e){for(let n of e){let t=vt(n);if(t)return t}}function eo(e){let t=we(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var x=Symbol.for("corsair:internal");function Ns(e){let n=e.database?Mn(e.database):void 0,t=n&&e.kek?rt(e.plugins,n,e.kek):We(!!n,!!e.kek),r={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,approval:e.approval,connect:e.connect,hub:e.hub?xe(e.hub):void 0},i=nt(n),o=ft(r);if(e.multiTenancy)return Object.assign({withTenant:a=>{if(!a)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let c=xn(e.plugins,{database:n,tenantId:a,kek:e.kek,rootErrorHandlers:e.errorHandlers,approvalConfig:e.approval,connectConfig:e.connect,hubConfig:r.hub});return Object.assign(c,{[x]:r})},keys:t,permissions:i,manage:o},{[x]:r});let s=xn(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,approvalConfig:e.approval,connectConfig:e.connect,hubConfig:r.hub});return Object.assign({},s,{keys:t,permissions:i,manage:o,[x]:r})}var j=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Ot(e){let n=e[x];if(!n)throw new j("invalid_corsair_instance","Invalid corsair instance");return n}function Dt(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw new j("plugin_not_found",`Plugin '${n}' not found`);return t}function Ht(e){let n=e.oauthConfig;if(!n)throw new j("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function no(e,n,t,r){let i=Ce(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 a=H(),c=await M(a,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:c})}async function sn(e,n,t){let{tenantId:r,redirectUri:i}=t,o=Ot(e);if(!o.database)throw new Error("No database configured on corsair instance");let s=Dt(o,n),a=Ht(s),d=await N({authType:"oauth_2",integrationName:n,kek:o.kek,database:o.database}).get_client_id();if(!d)throw new Error(`client_id not configured for '${n}'`);let l=Y(L(n,r),o.kek),u={...a.authParams,client_id:d,redirect_uri:i,response_type:"code",scope:a.scopes.join(" "),state:l};return{url:`${a.authUrl}?${St.stringify(u)}`,state:l}}async function be(e,n){let{code:t,state:r,redirectUri:i}=n,o=Ot(e),s=Ae(r,o.kek);if(!s)throw new j("invalid_state","Invalid or tampered state parameter");let{plugin:a,tenantId:c}=s;if(!o.database)throw new j("no_database","No database configured on corsair instance");let d=Dt(o,a),l=Ht(d),u=N({authType:"oauth_2",integrationName:a,kek:o.kek,database:o.database}),g=await u.get_client_id(),f=await u.get_client_secret();if(!g||!f)throw new j("credentials_not_configured",`Credentials not configured for '${a}'`);await no(o.database,a,c,o.kek);let p=await Ye(t,g,f,l,i);if(!p.access_token)throw new j("no_access_token",`No access_token returned from ${l.providerName}`);let y=K({authType:"oauth_2",integrationName:a,tenantId:c,kek:o.kek,database:o.database});await y.set_access_token(p.access_token),p.refresh_token&&await y.set_refresh_token(p.refresh_token),p.expires_in&&await y.set_expires_at(String(Math.floor(Date.now()/1e3)+p.expires_in));try{let m=await _e(o.plugins,a,p);if(m)try{let k=d.authConfig?.oauth_2?.account??[];await ce({database:o.database,kek:o.kek,pluginId:a,tenantId:c,link:m,authType:"oauth_2",extraAccountFields:k})}catch(k){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${a}' tenant '${c}':`,k)}}catch(m){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${a}' tenant '${c}':`,m)}return{plugin:a,tenantId:c}}export{Nn as a,ge as b,fe as c,q as d,xe as e,G as f,Pe as g,L as h,on as i,H as j,M as k,F as l,gn as m,me as n,X as o,z as p,ke as q,ie as r,N as s,K as t,Kn as u,jn as v,ce as w,yn as x,De as y,qn as z,j as A,sn as B,be as C,Ie as D,an as E,cn as F,un as G,dn as H,ln as I,pn as J,ve as K,ee as L,ue as M,zn as N,He as O,Me as P,hn as Q,Fe as R,Ne as S,mn as T,kn as U,bn as V,$e as W,J as X,wn as Y,Vn as Z,Qn as _,Pn as $,se as aa,lt as ba,pt as ca,gt as da,yt as ea,Lr as fa,Ye as ga,Rs as ha,ae as ia,Is as ja,Xe as ka,Jr as la,Rt as ma,Vr as na,Qr as oa,It as pa,vt as qa,we as ra,Yr as sa,_t as ta,Et as ua,Xr as va,nn as wa,eo as xa,x as ya,Ns as za};
package/dist/core.d.ts CHANGED
@@ -1,12 +1,14 @@
1
- import { O as OAuthConfig, A as AuthTypes, a as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DSVPkmM-.js';
2
- export { e as AccountFieldNames, m as AllProviders, i as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, f as BaseKeyManager, n as BaseProviders, K as BeforeHookResult, p as BindEndpoints, a3 as BindWebhooks, a1 as Bivariant, q as BoundEndpointFn, r as BoundEndpointTree, a4 as BoundWebhook, a5 as BoundWebhookTree, b as CORSAIR_INTERNAL, j as CorsairClient, s as CorsairContext, t as CorsairEndpoint, w as CorsairErrorHandler, L as CorsairIntegration, c as CorsairInternalConfig, M as CorsairKeyBuilder, N as CorsairKeyBuilderBase, G as CorsairPermissionsNamespace, C as CorsairPlugin, Q as CorsairPluginContext, k as CorsairSingleTenantClient, l as CorsairTenantWrapper, a6 as CorsairWebhook, a7 as CorsairWebhookHandler, a8 as CorsairWebhookMatcher, S as EndpointHooks, T as EndpointMetaEntry, u as EndpointPathsOf, E as EndpointRiskLevel, v as EndpointTree, H as EnforcePermissionOptions, J as EnforcePermissionResult, x as ErrorContext, y as ErrorHandler, z as ErrorHandlerAndMatchFunction, D as ErrorMatcher, g as IntegrationFieldNames, U as KeyBuilderContext, h as OAuth2IntegrationCredentials, V as PermissionMode, W as PermissionPolicy, o as PickAuth, P as PluginAuthConfig, X as PluginEndpointMeta, Y as PluginPermissionsConfig, a9 as RawWebhookRequest, Z as RequiredPluginEndpointMeta, _ as RequiredPluginEndpointSchemas, $ as RequiredPluginWebhookSchemas, R as RetryStrategies, F as RetryStrategy, a2 as UnionToIntersection, a0 as WebhookHooks, aa as WebhookPathsOf, ab as WebhookRequest, ac as WebhookResponse, ad as WebhookTree, d as createCorsair } from './index-DSVPkmM-.js';
1
+ export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-BNgimVUH.js';
3
2
  import { CorsairDatabase } from './db.js';
4
- export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, R as ResolveConnectLinkResult, f as formatDocSchemaShape, i as introspectPluginForDocs, r as resolveConnectLink } from './index-BnkJ_TYy.js';
5
- import 'zod';
6
- import './orm.js';
3
+ import { A as AuthTypes, a as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './types-DAMJdQTn.js';
4
+ export { b as AccountFieldNames, f as AllProviders, e as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, c as BaseKeyManager, g as BaseProviders, k as Bivariant, d as IntegrationFieldNames, O as OAuth2IntegrationCredentials, h as PickAuth, P as PluginAuthConfig, j as ProviderDisplayNames, U as UnionToIntersection, i as formatProviderDisplayName } from './types-DAMJdQTn.js';
5
+ export { t as BeforeHookResult, B as BindEndpoints, L as BindWebhooks, f as BoundEndpointFn, g as BoundEndpointTree, M as BoundWebhook, N as BoundWebhookTree, d as CorsairClient, h as CorsairContext, i as CorsairEndpoint, k as CorsairErrorHandler, a as CorsairIntegration, u as CorsairKeyBuilder, v as CorsairKeyBuilderBase, Q as CorsairOAuthWebhookTenantLinkResolver, q as CorsairPermissionsNamespace, C as CorsairPlugin, w as CorsairPluginContext, c as CorsairSingleTenantClient, b as CorsairTenantWrapper, S as CorsairWebhook, U as CorsairWebhookHandler, V as CorsairWebhookMatcher, X as CorsairWebhookTenantMatcher, x as EndpointHooks, y as EndpointMetaEntry, E as EndpointPathsOf, z as EndpointRiskLevel, j as EndpointTree, r as EnforcePermissionOptions, s as EnforcePermissionResult, l as ErrorContext, m as ErrorHandler, n as ErrorHandlerAndMatchFunction, o as ErrorMatcher, K as KeyBuilderContext, O as OAuthConfig, P as PermissionMode, A as PermissionPolicy, D as PluginEndpointMeta, F as PluginPermissionsConfig, Y as RawWebhookRequest, G as RequiredPluginEndpointMeta, H as RequiredPluginEndpointSchemas, I as RequiredPluginWebhookSchemas, R as RetryStrategies, p as RetryStrategy, T as TokenResponse, J as WebhookHooks, Z as WebhookPathsOf, _ as WebhookRequest, $ as WebhookResponse, W as WebhookTenantMatch, a0 as WebhookTree, e as exchangeCodeForTokens } from './index-Cyd3nsjL.js';
6
+ export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, n as extractMicrosoftGraphValidationToken, o as firstString, f as formatDocSchemaShape, p as getHeader, i as introspectPluginForDocs, q as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, t as readQueryParam, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-Dc73JoO6.js';
7
7
  import 'kysely';
8
+ import 'zod';
8
9
  import 'pg';
9
10
  import 'postgres';
11
+ import './orm.js';
10
12
 
11
13
  /**
12
14
  * Context interface with account ID resolver for logging events.
@@ -108,18 +110,6 @@ declare function decryptConfig(encryptedConfig: Record<string, string>, dek: str
108
110
  */
109
111
  declare function reEncryptConfig(encryptedConfig: Record<string, string>, oldDek: string, newDek: string): Record<string, string>;
110
112
 
111
- type TokenResponse = {
112
- access_token?: string;
113
- refresh_token?: string;
114
- expires_in?: number;
115
- token_type?: string;
116
- };
117
- /**
118
- * Exchanges an OAuth authorization code for access/refresh tokens.
119
- * Supports both 'body' (default) and 'basic' token auth methods.
120
- */
121
- declare function exchangeCodeForTokens(code: string, clientId: string, clientSecret: string, oauthConfig: OAuthConfig, redirectUri: string): Promise<TokenResponse>;
122
-
123
113
  type IntegrationKeyManagerOptions<T extends AuthTypes> = {
124
114
  authType: T;
125
115
  integrationName: string;
@@ -161,4 +151,4 @@ declare function initializeIntegrationDEK(database: CorsairDatabase, integration
161
151
  */
162
152
  declare function initializeAccountDEK(database: CorsairDatabase, integrationName: string, tenantId: string, kek: string): Promise<string>;
163
153
 
164
- export { AccountKeyManagerFor, AuthTypes, type EventLoggingContext, IntegrationKeyManagerFor, OAuthConfig, type TokenResponse, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, exchangeCodeForTokens, generateDEK, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, reEncryptConfig };
154
+ export { AccountKeyManagerFor, AuthTypes, type EventLoggingContext, IntegrationKeyManagerFor, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, generateDEK, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, reEncryptConfig };
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{E as s,F as t,G as u,H as v,a,b,c,d,e,f,g,h,i,j,k,l,m,n,w as o,x as p,y as q,z as r}from"./chunk-LIZVHWQK.js";import"./chunk-OZHME3EO.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{a as AuthMissingError,j as BASE_AUTH_FIELDS,u as CORSAIR_INTERNAL,l as createAccountKeyManager,v as createCorsair,k as createIntegrationKeyManager,h as decryptConfig,d as decryptDEK,f as decryptWithDEK,g as encryptConfig,c as encryptDEK,e as encryptWithDEK,q as exchangeCodeForTokens,s as formatDocSchemaShape,b as generateDEK,n as initializeAccountDEK,m as initializeIntegrationDEK,t as introspectPluginForDocs,o as logEvent,p as logEventFromContext,i as reEncryptConfig,r as resolveConnectLink};
1
+ import{$ as q,X as p,a,b,ea as r,fa as s,ga as t,j as c,k as d,ka as u,l as e,la as v,m as f,ma as w,n as g,na as x,o as h,oa as y,p as i,pa as z,q as j,qa as A,r as k,ra as B,s as l,sa as C,t as m,ta as D,u as n,ua as E,v as o,va as F,wa as G,xa as H,ya as I,za as J}from"./chunk-SFZI4EL2.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{p as AuthMissingError,k 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,i as decryptConfig,e as decryptDEK,g as decryptWithDEK,h as encryptConfig,d as encryptDEK,f as encryptWithDEK,t as exchangeCodeForTokens,E as extractMicrosoftGraphValidationToken,G as firstString,u as formatDocSchemaShape,b as formatProviderDisplayName,c 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,j as reEncryptConfig,C as readBodyRecord,D as readQueryParam,q as resolveConnectLink,A as toExternalId};
package/dist/db.js CHANGED
@@ -1 +1 @@
1
- import{a as g}from"./chunk-N2XRSSRL.js";import{a as b,b as c,c as d,d as e,e as f}from"./chunk-3USHGH6P.js";import{a}from"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{c as CorsairAccountsSchema,d as CorsairEntitiesSchema,e as CorsairEventsSchema,b as CorsairIntegrationsSchema,f as CorsairPermissionsSchema,a as createCorsairDatabase,g as sql};
1
+ import{a as g}from"./chunk-N2XRSSRL.js";import{a,b,c,d,e,f}from"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{c as CorsairAccountsSchema,d as CorsairEntitiesSchema,e as CorsairEventsSchema,b as CorsairIntegrationsSchema,f as CorsairPermissionsSchema,a as createCorsairDatabase,g as sql};
package/dist/hub.d.ts ADDED
@@ -0,0 +1,129 @@
1
+ import { H as HubConfig, l as HubConfigInput, m as HubConnectSessionInput, n as HubConnectSessionResult, a as AccountKeyManagerFor } from './types-DAMJdQTn.js';
2
+ export { D as DEFAULT_HUB_API_URL, o as HubConnectSource, p as HubOAuthMode, i as formatProviderDisplayName } from './types-DAMJdQTn.js';
3
+ import { b as ProcessCorsairRequest } from './index-B6WTZEPl.js';
4
+
5
+ declare class HubNotConfiguredError extends Error {
6
+ constructor();
7
+ }
8
+ declare function normalizeHubConfig(input: HubConfigInput): HubConfig;
9
+ declare function getHubConfig(corsair: unknown): HubConfig;
10
+ declare function resolveHubOAuthCallbackUrl(config: HubConfig): string;
11
+
12
+ declare function createHubConnectSession(corsair: unknown, input: HubConnectSessionInput): Promise<HubConnectSessionResult>;
13
+
14
+ type HubConnectSessionRequestBody = {
15
+ plugin?: string;
16
+ tenantId?: string;
17
+ source?: string;
18
+ oauthMode?: string;
19
+ providerName?: string;
20
+ };
21
+ type HubConnectSessionParseError = {
22
+ error: string;
23
+ status: number;
24
+ };
25
+ type HubConnectSessionSuccessBody = {
26
+ ok: true;
27
+ connectUrl: string;
28
+ token: string;
29
+ projectId: string;
30
+ expiresAt?: string;
31
+ };
32
+ type ResolveHubConnectTenantId = (request: Request) => Promise<string | null | undefined> | string | null | undefined;
33
+ type HubConnectSessionResponseOptions = {
34
+ /**
35
+ * When provided, tenantId from the request body or query is ignored.
36
+ * Return null or undefined to respond with 401 Unauthorized.
37
+ */
38
+ resolveTenantId?: ResolveHubConnectTenantId;
39
+ /** Used when resolveTenantId is not provided. Defaults to "default". */
40
+ defaultTenantId?: string;
41
+ };
42
+ declare function isLoopbackDeliveryUrl(deliveryUrl: string): boolean;
43
+ declare function parseHubConnectSessionBody(body: HubConnectSessionRequestBody): HubConnectSessionInput | HubConnectSessionParseError;
44
+ declare function parseHubConnectSessionSearchParams(url: string): HubConnectSessionRequestBody;
45
+ declare function validateManagedOAuthLoopback(input: HubConnectSessionInput, deliveryUrl: string): HubConnectSessionParseError | null;
46
+ declare function handleHubConnectSessionRequest(corsair: unknown, request: Request, options?: HubConnectSessionResponseOptions): Promise<HubConnectSessionSuccessBody | HubConnectSessionParseError>;
47
+ declare function respondToHubConnectSession(corsair: unknown, request: Request, options?: HubConnectSessionResponseOptions): Promise<Response>;
48
+ declare function respondToHubConnectSessionFromRequest(corsair: unknown, request: Request, options?: HubConnectSessionResponseOptions): Promise<Response>;
49
+
50
+ type HubDeliveryResult = {
51
+ type: 'redirect';
52
+ url: string;
53
+ } | {
54
+ type: 'json';
55
+ body: unknown;
56
+ status: number;
57
+ headers?: Record<string, string>;
58
+ } | {
59
+ type: 'text';
60
+ body: string | null;
61
+ status: number;
62
+ headers?: Record<string, string>;
63
+ };
64
+ declare function handleHubDeliveryGet(corsair: unknown, requestUrl: string): Promise<HubDeliveryResult>;
65
+ declare function handleHubDeliveryPost(corsair: unknown, request: ProcessCorsairRequest): Promise<HubDeliveryResult>;
66
+
67
+ type HubDeliveryRequest = {
68
+ method: 'GET' | 'POST';
69
+ url: string;
70
+ headers: ProcessCorsairRequest['headers'];
71
+ body?: string;
72
+ };
73
+ declare function hubDeliveryToResponse(result: HubDeliveryResult): Response;
74
+ declare function handleHubDeliveryRequest(corsair: unknown, request: HubDeliveryRequest): Promise<HubDeliveryResult>;
75
+ declare function respondToHubDelivery(corsair: unknown, request: HubDeliveryRequest): Promise<Response>;
76
+ declare function respondToHubDeliveryFromRequest(corsair: unknown, request: Request): Promise<Response>;
77
+
78
+ type ManagedAuthContext = {
79
+ keys: AccountKeyManagerFor<'managed'>;
80
+ hub: HubConfig;
81
+ plugin: string;
82
+ tenantId: string;
83
+ };
84
+ type ManagedAccessTokenResult = {
85
+ accessToken: string;
86
+ expiresAt: number;
87
+ refreshed: boolean;
88
+ };
89
+ /**
90
+ * Returns a valid access token for a managed OAuth connection.
91
+ * Uses cached credentials when still valid; otherwise refreshes via the hub.
92
+ */
93
+ declare function getManagedAccessToken(ctx: ManagedAuthContext, options?: {
94
+ forceRefresh?: boolean;
95
+ }): Promise<ManagedAccessTokenResult>;
96
+ /**
97
+ * Attaches a `_refreshAuth` helper on the keyBuilder context for 401 retries.
98
+ */
99
+ declare function attachManagedRefreshAuth(ctx: Record<string, unknown>, managedContext: ManagedAuthContext): Promise<void>;
100
+
101
+ type ManagedOAuthDeliveryErrorCode = 'invalid_corsair_instance' | 'no_database' | 'plugin_not_found' | 'no_access_token';
102
+ declare class ManagedOAuthDeliveryError extends Error {
103
+ readonly code: ManagedOAuthDeliveryErrorCode;
104
+ constructor(code: ManagedOAuthDeliveryErrorCode, message: string);
105
+ }
106
+ type ProcessManagedOAuthDeliveryOptions = {
107
+ plugin: string;
108
+ tenantId: string;
109
+ accessToken: string;
110
+ refreshToken?: string;
111
+ expiresIn?: number;
112
+ scope?: string;
113
+ };
114
+ type ProcessManagedOAuthDeliveryResult = {
115
+ plugin: string;
116
+ tenantId: string;
117
+ };
118
+ /**
119
+ * Stores managed OAuth tokens delivered from the hub after a successful connect.
120
+ */
121
+ declare function processManagedOAuthDelivery(corsair: unknown, options: ProcessManagedOAuthDeliveryOptions): Promise<ProcessManagedOAuthDeliveryResult>;
122
+
123
+ type HubRouteHandlersOptions = HubConnectSessionResponseOptions;
124
+ declare function createHubRouteHandlers(corsair: unknown, options?: HubRouteHandlersOptions): {
125
+ delivery: (request: Request) => Promise<Response>;
126
+ createConnectSession: (request: Request) => Promise<Response>;
127
+ };
128
+
129
+ export { HubConfig, HubConfigInput, HubConnectSessionInput, type HubConnectSessionParseError, type HubConnectSessionRequestBody, type HubConnectSessionResponseOptions, HubConnectSessionResult, type HubConnectSessionSuccessBody, type HubDeliveryRequest, type HubDeliveryResult, HubNotConfiguredError, type HubRouteHandlersOptions, type ManagedAccessTokenResult, type ManagedAuthContext, ManagedOAuthDeliveryError, type ProcessManagedOAuthDeliveryOptions, type ProcessManagedOAuthDeliveryResult, type ResolveHubConnectTenantId, attachManagedRefreshAuth, createHubConnectSession, createHubRouteHandlers, getHubConfig, getManagedAccessToken, handleHubConnectSessionRequest, handleHubDeliveryGet, handleHubDeliveryPost, handleHubDeliveryRequest, hubDeliveryToResponse, isLoopbackDeliveryUrl, normalizeHubConfig, parseHubConnectSessionBody, parseHubConnectSessionSearchParams, processManagedOAuthDelivery, resolveHubOAuthCallbackUrl, respondToHubConnectSession, respondToHubConnectSessionFromRequest, respondToHubDelivery, respondToHubDeliveryFromRequest, validateManagedOAuthLoopback };
package/dist/hub.js ADDED
@@ -0,0 +1 @@
1
+ import{D as g,E as h,F as i,G as j,H as k,I as l,J as m,K as n,L as o,M as p,R as q,S as r,T as s,U as t,V as u,W as v,Y as w,Z as x,_ as y,b as a,c as b,d as c,e as d,f as e,g as f}from"./chunk-SFZI4EL2.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as DEFAULT_HUB_API_URL,c as HubNotConfiguredError,o as ManagedOAuthDeliveryError,x as attachManagedRefreshAuth,g as createHubConnectSession,y as createHubRouteHandlers,a as formatProviderDisplayName,e as getHubConfig,w as getManagedAccessToken,l as handleHubConnectSessionRequest,q as handleHubDeliveryGet,r as handleHubDeliveryPost,t as handleHubDeliveryRequest,s as hubDeliveryToResponse,h as isLoopbackDeliveryUrl,d as normalizeHubConfig,i as parseHubConnectSessionBody,j as parseHubConnectSessionSearchParams,p as processManagedOAuthDelivery,f as resolveHubOAuthCallbackUrl,m as respondToHubConnectSession,n as respondToHubConnectSessionFromRequest,u as respondToHubDelivery,v as respondToHubDeliveryFromRequest,k as validateManagedOAuthLoopback};
@@ -0,0 +1,52 @@
1
+ type TunnelType = 'oauth.callback' | 'oauth.tokens' | 'webhook' | 'permission.approve' | 'permission.deny' | 'auth.credentials' | 'run';
2
+ type TunnelEnvelope<TPayload = unknown> = {
3
+ type: TunnelType;
4
+ payload: TPayload;
5
+ };
6
+ type TunnelAck = {
7
+ status: 'ok' | 'failed';
8
+ retryable?: boolean;
9
+ error?: string;
10
+ webhookResponse?: {
11
+ status?: number;
12
+ body?: unknown;
13
+ headers?: Record<string, string>;
14
+ };
15
+ };
16
+ type WebhookTunnelPayload = {
17
+ headers: Record<string, string>;
18
+ body: string;
19
+ bodyBase64?: string;
20
+ bodyEncoding?: string;
21
+ query?: Record<string, string | string[] | undefined>;
22
+ plugin?: string;
23
+ linkType?: string;
24
+ externalId?: string;
25
+ tenantId?: string;
26
+ };
27
+ type OAuthCallbackTunnelPayload = {
28
+ code: string;
29
+ state: string;
30
+ redirectUri: string;
31
+ };
32
+ type OAuthTokensTunnelPayload = {
33
+ plugin: string;
34
+ tenantId: string;
35
+ accessToken: string;
36
+ refreshToken?: string;
37
+ expiresIn?: number;
38
+ scope?: string;
39
+ };
40
+ type ProcessCorsairRequest = {
41
+ headers: Headers | Record<string, string | string[] | undefined>;
42
+ body: string;
43
+ };
44
+ type ProcessCorsairOptions = {
45
+ /** HMAC signing secret shared with the tunnel relay. Required unless allowUnsignedTunnel is true. */
46
+ signingSecret?: string;
47
+ /** Local development only. Skips signature verification when signingSecret is omitted. */
48
+ allowUnsignedTunnel?: boolean;
49
+ };
50
+ declare function processCorsair(corsair: unknown, request: ProcessCorsairRequest, options?: ProcessCorsairOptions): Promise<TunnelAck>;
51
+
52
+ export { type OAuthCallbackTunnelPayload as O, type ProcessCorsairOptions as P, type TunnelAck as T, type WebhookTunnelPayload as W, type OAuthTokensTunnelPayload as a, type ProcessCorsairRequest as b, type TunnelEnvelope as c, type TunnelType as d, processCorsair as p };