corsair 0.1.76 → 0.1.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-3X6WVI5I.js +1 -0
- package/dist/chunk-IGGCNGU2.js +1 -0
- package/dist/chunk-J6HIPZAR.js +26 -0
- package/dist/{chunk-UPIMTWVI.js → chunk-KLJBBN2T.js} +3 -3
- package/dist/core.d.ts +8 -18
- package/dist/core.js +1 -1
- package/dist/db.js +1 -1
- package/dist/hub.d.ts +140 -0
- package/dist/hub.js +1 -0
- package/dist/{index-DSVPkmM-.d.ts → index-BHyMcpwm.d.ts} +389 -492
- package/dist/index-aVkEGoHG.d.ts +53 -0
- package/dist/index-mZfhN-6e.d.ts +55 -0
- package/dist/index.d.ts +17 -6
- package/dist/index.js +3 -3
- package/dist/oauth.d.ts +6 -1
- package/dist/oauth.js +1 -1
- package/dist/orm.js +1 -1
- package/dist/setup.d.ts +5 -3
- package/dist/setup.js +1 -1
- package/dist/tenant-links-UNTSO7K7.d.ts +43 -0
- package/dist/{index-BnkJ_TYy.d.ts → tenant-match-utils-DXoUP9o9.d.ts} +42 -2
- package/dist/tunnel.d.ts +35 -0
- package/dist/tunnel.js +1 -0
- package/dist/types-B1We8TTP.d.ts +249 -0
- package/package.json +12 -2
- package/dist/chunk-3USHGH6P.js +0 -1
- package/dist/chunk-FL4GOHVN.js +0 -1
- package/dist/chunk-LIZVHWQK.js +0 -26
- package/dist/chunk-OZHME3EO.js +0 -1
- package/dist/chunk-UBM25HVI.js +0 -1
|
@@ -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};
|
|
@@ -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 zn,b as pn,d as ve}from"./chunk-3X6WVI5I.js";import{a as Gn}from"./chunk-IGGCNGU2.js";import*as jt from"querystring";var Ie=["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"],Jn={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 be(e){let n=Jn[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var we="https://auth.corsair.dev";var G=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret, deliveryUrl } to createCorsair()."),this.name="HubNotConfiguredError"}};function Gt(e){let n=e[x];if(!n)throw new Error("Invalid corsair instance");return n}function Se(e){let n=(e.apiUrl?.trim()||we).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 zt(e){return e.apiUrl.trim().length>0&&e.deliveryUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function z(e){let n=Gt(e).hub;if(!n||!zt(n))throw new G;return n}function Ee(e){return e.oauthCallbackUrl?e.oauthCallbackUrl:`${e.apiUrl.replace(/\/$/,"")}/oauth/callback`}import*as Ce from"crypto";function K(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function gn(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 ee(e,n){let t=Ce.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Jt=600*1e3;function _e(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),i=e.slice(t+1),o=Ce.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(i,"base64url"),a=Buffer.from(o,"base64url");return s.length!==a.length||!Ce.timingSafeEqual(s,a)?null:gn(r,{maxAgeMs:Jt})}var Vt=new Set(["localhost","127.0.0.1","[::1]","::1"]);function ge(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Vt.has(n)}catch{return!1}}function se(e){return ge(e)?"client":"server"}function fn(e,n){return e==="client"||ge(n)}function ae(e){if(!e.source)return null;let n=ge(e.deliveryUrl);return e.source==="server"&&n?{error:'source "server" cannot be used with a loopback delivery URL \u2014 omit source to auto-detect or use "client"',status:400}:e.oauthMode==="managed"&&e.source==="client"&&!n?{error:'managed OAuth with source "client" requires a loopback delivery URL \u2014 omit source for production server delivery',status:400}:null}function Oe(e){return typeof e=="string"&&e.length>0}function Qt(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!Oe(n.connectUrl)||!Oe(n.token)||!Oe(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 Oe(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Yt(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 Xt(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 er(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 He(e,n){let t=z(e),r=t.apiUrl.replace(/\/$/,""),i=n.oauthMode??"byo";if(n.source){let d=ae({source:n.source,deliveryUrl:t.deliveryUrl,oauthMode:i});if(d)throw new Error(d.error)}let o=n.providerName??be(n.plugin),s=n.source??se(t.deliveryUrl),a;if(i==="managed"){let d=er(e),u=ee(K(n.plugin,n.tenantId),d);a={plugin:n.plugin,tenantId:n.tenantId,providerName:o,state:u,deliveryUrl:t.deliveryUrl,source:s,oauthMode:"managed"}}else{let d=Ee(t),{url:u,state:g}=await yn(e,n.plugin,{tenantId:n.tenantId,redirectUri:d});a={plugin:n.plugin,tenantId:n.tenantId,providerName:o,oauthUrl:u,state:g,deliveryUrl:t.deliveryUrl,source:s,oauthMode:"byo"}}let c=await fetch(`${r}/connect/sessions`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${t.projectApiKey}`},body:JSON.stringify(a)}),l=await Xt(c);if(!c.ok)throw new Error(Yt(l,c.status));return Qt(l)}function nr(e){if(e==="byo"||e==="managed")return e}function tr(e){if(e==="client"||e==="server")return e}function hn(e){let n=e.plugin?.trim(),t=e.tenantId?.trim()||"default",r=tr(e.source),i=nr(e.oauthMode),o=e.providerName?.trim();if(!n)return{error:"plugin is required",status:400};if(e.source!==void 0&&e.source!==null&&String(e.source).trim()!==""&&!r)return{error:'source 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,oauthMode:i};return r&&(s.source=r),o&&(s.providerName=o),s}function mn(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 rr(e){return{ok:!0,connectUrl:e.connectUrl,token:e.token,projectId:e.projectId,expiresAt:e.expiresAt}}async function or(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 kn(e,n,t){let i=n.method.toUpperCase()==="GET"?mn(n.url):await n.json().catch(()=>null);if(!i)return{error:"Invalid JSON body",status:400};let o=await or(n,i,t);if(typeof o!="string")return o;let s=hn({...i,tenantId:o});if("error"in s)return s;let a=z(e);if(s.source){let d=ae({source:s.source,deliveryUrl:a.deliveryUrl,oauthMode:s.oauthMode});if(d)return d}let c={...s,source:s.source??se(a.deliveryUrl)},l=await He(e,c);return rr(l)}async function bn(e,n,t){try{let r=await kn(e,n,t);return"error"in r?Response.json({error:r.error},{status:r.status}):Response.json(r)}catch(r){if(r instanceof G)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 De(e,n,t){let r=n.method.toUpperCase();return r!=="GET"&&r!=="POST"?Response.json({error:"Method not allowed"},{status:405}):bn(e,n,t)}import{createHmac as br,timingSafeEqual as wr}from"crypto";async function Me(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 Vn,createDecipheriv as Qn,randomBytes as Fe,scrypt as ir}from"crypto";import{promisify as sr}from"util";var Yn=sr(ir),Ne="aes-256-gcm",Xn=12,Ue=16,ar=16,Te=32;function D(){return Fe(Te).toString("base64")}async function M(e,n){let t=Fe(ar),r=await Yn(n,t,Te),i=Fe(Xn),o=Vn(Ne,r,i,{authTagLength:Ue}),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"),l=Buffer.from(o,"base64"),d=await Yn(n,s,Te),u=Qn(Ne,d,a,{authTagLength:Ue});return u.setAuthTag(c),Buffer.concat([u.update(l),u.final()]).toString("utf8")}function wn(e,n){let t=Buffer.from(n,"base64"),r=Fe(Xn),i=Vn(Ne,t,r,{authTagLength:Ue}),o=Buffer.concat([i.update(e,"utf8"),i.final()]),s=i.getAuthTag();return[r.toString("base64"),s.toString("base64"),o.toString("base64")].join(":")}function xe(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"),l=Qn(Ne,o,s,{authTagLength:Ue});return l.setAuthTag(a),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function ne(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=wn(i,n);return t}function J(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=xe(i,n);return t}function Pe(e,n,t){let r=J(e,n);return ne(r,t)}var ce={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 et(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 Cn=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=[...ce[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:Cn(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}},l=null,d=async()=>{if(l)return l;let p=await c.getIntegration();if(!p.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await F(p.dek,r),l},u=async()=>{let p=await c.getIntegration(),y=await d(),m=p.config;return!m||Object.keys(m).length===0?{}:J(m,y)};return{get_dek:d,issue_new_dek:async()=>{let p=await c.getIntegration(),y=D(),m={};if(p.dek){let T=await F(p.dek,r),k=p.config;k&&Object.keys(k).length>0&&(m=Pe(k,T,y))}let w=await M(y,r);return await c.updateIntegration({config:m,dek:w}),l=y,y},...et(u,async p=>{let y=await d(),m;try{m=await u()}catch(k){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,k),m={}}let w={...m};for(let[k,h]of Object.entries(p))h===null?delete w[k]:w[k]=h;let T=ne(w,y);await c.updateIntegration({config:T})},s)}}function Z(e){let{authType:n,integrationName:t,tenantId:r,kek:i,database:o,extraAccountFields:s=[]}=e,a=[...ce[n].account,...s],c=null,l=null,d=async()=>{if(l)return l;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 l={id:h.id,config:Cn(h.config),dek:h.dek??null},l},u={kek:i,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(c)return c;let h=await d(),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:Cn(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?{}:J(C,b)},w=async()=>{let h=await u.getIntegration(),b=await y(),C=h.config;return!C||Object.keys(C).length===0?{}:J(C,b)},k={get_dek:p,issue_new_dek:async()=>{let h=await u.getAccount(),b=D(),C={};if(h.dek){let S=await F(h.dek,i),E=h.config;E&&Object.keys(E).length>0&&(C=Pe(E,S,b))}let I=await M(b,i);return await u.updateAccount({config:C,dek:I}),g=b,b},...et(m,async h=>{let b=await p(),C;try{C=await m()}catch(E){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,E),C={}}let I={...C};for(let[E,P]of Object.entries(h))P===null?delete I[E]:I[E]=P;let S=ne(I,b);await u.updateAccount({config:S})},a)};return n==="oauth_2"&&(k.get_integration_credentials=async()=>{let h=await w();return{client_id:h.client_id||null,client_secret:h.client_secret||null,redirect_url:h.redirect_url??null}}),k}async function nt(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=D(),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 tt(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=D(),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 rt=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function cr(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 ur(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=rt(n.config),i={};Object.keys(r).length>0&&(i=J(r,t)),i[e.link.linkType]=e.link.externalId;let o=ne(i,t);await e.database.db.updateTable("corsair_accounts").set({config:o,updated_at:new Date}).where("id","=",n.id).execute()}async function fe(e){let{database:n,kek:t,pluginId:r,tenantId:i,link:o,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await cr({database:n,pluginId:r,tenantId:i}),l=!1;if(s){let d=Z({authType:s,integrationName:r,tenantId:i,kek:t,database:n,extraAccountFields:a}),u=`set_${o.linkType}`,g=d[u];typeof g=="function"&&(await g(o.externalId),l=!0)}l||await ur({database:n,kek:t,accountId:c,link:o})}async function Tn(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),d=rt(a.config)[i];if(!d)continue;if(xe(d,c)===o)return a}catch{continue}return null}async function $e(e){return(await Tn(e))?.tenant_id??null}async function ot(e){return $e({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var te=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};function dr(e){let n=e[x];if(!n)throw new te("invalid_corsair_instance","Invalid corsair instance");return n}function lr(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw new te("plugin_not_found",`Plugin '${n}' not found`);return t}async function pr(e,n,t,r){let i=ve(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=D(),c=await M(a,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:c})}async function ye(e,n){let{plugin:t,tenantId:r,accessToken:i,refreshToken:o,expiresIn:s,scope:a}=n;if(!i.trim())throw new te("no_access_token","Managed OAuth delivery missing access_token");let c=dr(e);if(!c.database)throw new te("no_database","No database configured on corsair instance");let l=lr(c,t);await pr(c.database,t,r,c.kek);let d=Z({authType:"managed",integrationName:t,tenantId:r,kek:c.kek,database:c.database});await d.set_access_token(i),o&&await d.set_refresh_token(o),s&&await d.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await d.set_scope(a);try{let u=await Me(c.plugins,t,{access_token:i,refresh_token:o,scope:a});if(u)try{let g=l.authConfig?.managed?.account??[];await fe({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 gr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function it(e,n,t=[]){for(let[r,i]of Object.entries(e))if(gr(i)){if(i.match(n))return{webhook:i,path:[...t,r]}}else if(i&&typeof i=="object"){let o=it(i,n,[...t,r]);if(o)return o}return null}function fr(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function yr(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 st(e,n,t,r){let i=fr(n),o=typeof t=="string"?JSON.parse(t):t;(!o||typeof o=="object"&&Object.keys(o).length===0)&&i["x-goog-resource-uri"]&&(o=yr(i)||o);let a={headers:i,body:o,...r?{query:r}:{}},c=r?.tenantId||"default",l=e.withTenant?e.withTenant(c):e,d=Ie;for(let u of d){let g=l[u];if(!g||!g.webhooks||g.pluginWebhookMatcher&&!g.pluginWebhookMatcher(a))continue;let f=it(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),w=!!Object.keys(m.returnToSender||{})?.length;return{plugin:u,action:p,body:o,response:w?{...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 hr,timingSafeEqual as mr}from"crypto";function Be(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function We(e){return e.deliveryMode==="oauth.tokens"||typeof e.accessToken=="string"&&e.accessToken.length>0}function at(e){let n=e.trim();return n.length>0?n:null}function kr(e,n){let t=at(n);if(!t)throw new Error("Signing secret is required for browser delivery tokens");return hr("sha256",t).update(e).digest("base64url")}function Le(e,n){let t=at(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=kr(i,t);try{if(!mr(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 ct(e){let n=e[x];if(!n)throw new Error("Invalid corsair instance");return n}function Cr(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 Tr(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function xr(e,n,t){if(!t.trim()||!n)return!1;let r=br("sha256",t.trim()).update(e).digest("hex");try{return wr(Buffer.from(r,"utf8"),Buffer.from(n,"utf8"))}catch{return!1}}async function Pr(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 $e({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Ar(e,n,t){let r=await Pr(e,n,t),i={...t.query??{},...r?{tenantId:r}:{}},o=await st(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 Rr(e,n){return await Ae(e,n),{status:"ok"}}async function vr(e,n){return await ye(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function Pn(e,n,t){let r=await xn(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function xn(e,n,t){let r=ct(e),i=n.token?.trim();if(!i)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let o=new Date().toISOString(),s=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",i).executeTakeFirst();return s?s.status!=="pending"?{status:"ok"}:s.expires_at<o?(await r.database.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",s.id).execute(),{status:"failed",retryable:!1,error:"Permission has expired"}):(await r.database.db.updateTable("corsair_permissions").set({status:t,updated_at:new Date}).where("id","=",s.id).execute(),{status:"ok"}):{status:"failed",retryable:!1,error:"Permission not found"}}async function An(e,n,t={}){let r=ct(e),i=Tr(Cr(n.headers,"x-corsair-signature"));if(t.signingSecret?.trim()){if(!xr(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 Ar(e,r,o.payload);case"oauth.callback":return Rr(e,o.payload);case"oauth.tokens":return vr(e,o.payload);case"permission.approve":return xn(e,o.payload,"approved");case"permission.deny":return xn(e,o.payload,"denied");default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${o.type}`}}}async function je(e,n){let t=z(e),i=new URL(n).searchParams.get("d");if(!i)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let o=Le(i,t.signingSecret);if(!o)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};try{if(Be(o)){if(!o.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await Pn(e,o.permissionToken,o.deliveryMode==="permission.approve"?"approved":"denied")}else if(We(o)){if(!o.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await ye(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 Ae(e,{code:o.code,state:o.state,redirectUri:o.redirectUri})}}catch(s){return{type:"json",status:400,body:{error:s instanceof Error?s.message:"Hub delivery failed"}}}return{type:"redirect",url:o.hubSuccessUrl}}async function Ke(e,n){let t=z(e),r=await An(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 Rn(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 vn(e,n){return n.method==="GET"?je(e,n.url):Ke(e,{headers:n.headers,body:n.body??""})}async function In(e,n){try{let t=await vn(e,n);return Rn(t)}catch(t){if(t instanceof G)return Response.json({error:t.message},{status:503});throw t}}async function Ze(e,n){let t=n.method.toUpperCase();return t!=="GET"&&t!=="POST"?Response.json({error:"Method not allowed"},{status:405}):In(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0})}var V=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 Ir=300;async function Sr(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 Er(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 Sn(e,n){let{keys:t,hub:r,plugin:i,tenantId:o}=e,s=n?.forceRefresh??!1,[a,c,l]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!l)throw new V(i,"managed");let d=Math.floor(Date.now()/1e3);if(!s&&a&&c&&Number(c)>d+Ir)return{accessToken:a,expiresAt:Number(c),refreshed:!1};if(!l&&a&&!s)return{accessToken:a,expiresAt:c?Number(c):d+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 Sr(g);if(!g.ok)throw new Error(Er(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?d+p.expires_in:c?Number(c):d+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 ut(e,n){e._refreshAuth=async()=>(await Sn(n,{forceRefresh:!0})).accessToken}function qe(e){return typeof e=="string"&&e.length>0}function _r(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!qe(n.approvalUrl)||!qe(n.token)||!qe(n.projectId)||!qe(n.expiresAt))throw new Error("Hub API returned an incomplete permission session (expected approvalUrl, token, projectId, and expiresAt)");return{approvalUrl:n.approvalUrl,token:n.token,projectId:n.projectId,expiresAt:n.expiresAt}}function Or(e,n){if(n===404)return"Hub REST API not found at /permission/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 Hr(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})`)}}async function En(e,n){let t=e.apiUrl.replace(/\/$/,""),r=await fetch(`${t}/permission/sessions`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.projectApiKey}`},body:JSON.stringify({permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,deliveryUrl:e.deliveryUrl,expiresAt:n.expiresAt})}),i=await Hr(r);if(!r.ok)throw new Error(Or(i,r.status));return _r(i)}function _n(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}function dt(e,n){return{delivery:t=>Ze(e,t),createConnectSession:t=>De(e,t,n)}}function Ge(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 ${Te}`)}})}var Dr=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function lt(e,n,t,r,i){let o={pluginId:n,operation:t,input:r,originalError:e},s=Object.keys(i).find(l=>i[l]?.match(e,o));return await(i[s||"DEFAULT"]?.handler||Dr)(e,o)}import{randomBytes as Mr}from"crypto";import{v4 as Fr}from"uuid";var Nr={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 Ur(e,n,t){return t!==void 0?t:Nr[n][e]}function On(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 gt(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 pt(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 ft(e){let n=Ur(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"?pt(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let c=Fr(),l=Mr(32).toString("hex"),d=e.timeoutMs??600*1e3,u=new Date(Date.now()+d).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:c,created_at:new Date,updated_at:new Date,token:l,plugin:e.pluginId,endpoint:e.endpointPath,args: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: ${l}`,`
|
|
12
|
+
Expires at: ${u}`,`
|
|
13
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?pt(e.db,c,d):{result:"blocked",reason:"pending",id:c,token:l,expiresAt:u}}function $r(e){return typeof e=="function"}function Br(e,n,t){let r=ee(K(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 Hn({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:i,errorHandlers:o,currentPath:s=[],keyBuilder:a,permissionsConfig:c,endpointMeta:l,database:d,approvalConfig:u,tenantId:g,connectConfig:f,hubConfig:p}){for(let[y,m]of Object.entries(e)){let w=n?.[y];if($r(m)){let T=w,k=[...s,y].join("."),h=async(b={})=>{let C;if(c){let v=l?.[k],{result:pe,reason:L,onComplete:ke,token:j,id:X,expiresAt:H}=await ft({pluginId:i,endpointPath:k,args:b,mode:c.mode,override:c.overrides?.[k],riskLevel:v?.riskLevel??"write",meta:v,db:d,timeoutMs:u?On(u.timeout):void 0,tenantId:g,approvalMode:u?.mode});if(pe==="blocked"){let _;if(L==="denied")_=`Action '${k}' was denied by the user. Await further instructions before proceeding.`;else if(L==="policy")_=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`;else if(L==="timeout")_=`Action '${k}' timed out waiting for approval.`;else if(j&&X)if(u?.formatAsyncMessage)_=u.formatAsyncMessage({token:j,id:X,plugin:i,endpoint:k,args:b});else if(p)try{let ie=u?On(u.timeout):6e5,ln=await En(p,{permissionId:X,permissionToken:j,plugin:i,endpoint:k,args:b,tenantId:g??"default",expiresAt:H??new Date(Date.now()+ie).toISOString()});_=_n(ln.approvalUrl)}catch(ie){let ln=ie instanceof Error?ie.message:String(ie);_=`Action '${k}' requires user approval before it can run. Could not create approval link: ${ln}`}else _=`Action '${k}' requires user approval before it can run.`;else _=`Action '${k}' requires user approval before it can run.`;throw new Error(_)}C=ke}let I=async(v,pe,L)=>{try{return await m(pe,L)}catch(ke){if(ke instanceof Error){let j=await lt(ke,i,k,typeof L=="object"&&L!==null?L:{args:L},o);if(v<(j.maxRetries||0)){let X=v+1;console.log(`Retrying (${X} / ${j.maxRetries})...`);let H;if(j.headersRetryAfterMs)H=j.headersRetryAfterMs;else switch(j.retryStrategy){case"exponential_backoff":H=Math.pow(2,X-1)*1e3;break;case"exponential_backoff_jitter":let _=Math.pow(2,X-1)*1e3,ie=(Math.random()-.5)*1e3;H=Math.max(0,_+ie);break;case"linear_1s":H=1e3;break;case"linear_2s":H=2e3;break;case"linear_3s":H=3e3;break;case"linear_4s":H=4e3;break;default:H=1e3;break}await new Promise(_=>setTimeout(_,H)),await I(X,pe,L),console.log(`[corsair:${i}:${k}] Retry strategy:`,j)}}throw ke}},S;try{S=a?await a(t,"endpoint"):void 0}catch(v){throw f?.oauthConfig&&f.kek&&v instanceof V&&v.authType==="oauth_2"?Br(i,f,g):v}if(!T?.before&&!T?.after){let v=await I(0,{...t,key:S},b);return await C?.(),v}let E={...t,key:S},P=T.before?await T.before(E,b):{ctx:E,args:b,continue:!0,passToAfter:void 0};if(P.continue===!1)return;let le=await I(0,P.ctx,P.args);return await T.after?.(P.ctx,le,P.passToAfter),await C?.(),le};r[y]=h}else if(m&&typeof m=="object"){let T={};Hn({endpoints:m,hooks:w,ctx:t,tree:T,pluginId:i,errorHandlers:o,currentPath:[...s,y],keyBuilder:a,permissionsConfig:c,endpointMeta:l,database:d,approvalConfig:u,tenantId:g,connectConfig:f,hubConfig:p}),r[y]=T}}}function Wr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Dn({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:i}){for(let[o,s]of Object.entries(e)){let a=n?.[o];if(Wr(s)){let c=a,l=async d=>{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},d):(async()=>{let f={...t,key:g},p=c.before?await c.before(f,d):{ctx:f,args:d,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:l}}else if(s&&typeof s=="object"){let c={};Dn({webhooks:s,hooks:a,ctx:t,webhooksTree:c,keyBuilder:i}),r[o]=c}}}function Lr(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 jr(e,n,t,r,i){return e?pn(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 Mn(e,n){let{database:t,tenantId:r,kek:i,rootErrorHandlers:o,approvalConfig:s,connectConfig:a,hubConfig:c}=n,l={},d={};for(let u of e)l[u.id]={},d[u.id]={};for(let u of e){let g=u.schema,f=r??"default",p=Lr(t,u.id,f);if(g?.entities){let P={};for(let[le,v]of Object.entries(g.entities)){let pe=t?pn(t.db,p,le,g.version,v):jr(void 0,p,le,g.version,v);P[le]=pe}d[u.id].db=P,l[u.id].db=P}let y=u.options,m=u.authConfig,w;if(t&&i&&y?.authType){let P=m?.[y.authType]?.account??[];w=Z({authType:y.authType,integrationName:u.id,tenantId:f,kek:i,database:t,extraAccountFields:P}),l[u.id].keys=w}let T={database:t,db:d[u.id]?.db??{},$getAccountId:p,...u.options?{options:u.options}:{},...w?{keys:w,authType:y?.authType}:{},tenantId:f,...c?{hub:c}:{}},k=u.endpoints??{},h=u.hooks,b={...o,...u.errorHandlers},C={},I=u.options?.permissions;Hn({endpoints:k,hooks:h,ctx:T,tree:C,pluginId:u.id,errorHandlers:b,currentPath:[],keyBuilder:u.keyBuilder,permissionsConfig:I,endpointMeta:u.endpointMeta,database:t,approvalConfig:s,tenantId:r,connectConfig:a?{...a,oauthConfig:u.oauthConfig,kek:i,tenantId:f}:void 0,hubConfig:c}),Object.keys(C).length>0&&(l[u.id].api=C),T.endpoints=C;let S=u.webhooks??{},E=u.webhookHooks;if(Object.keys(S).length>0){let P={};Dn({webhooks:S,hooks:E,ctx:T,webhooksTree:P,keyBuilder:u.keyBuilder}),l[u.id].webhooks=P,u.pluginWebhookMatcher&&(l[u.id].pluginWebhookMatcher=u.pluginWebhookMatcher),u.pluginTenantWebhookMatcher&&(l[u.id].pluginTenantWebhookMatcher=u.pluginTenantWebhookMatcher)}}return l}function yt(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 ht from"querystring";var U=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Kr(e){let n=e[x];if(!n)throw new U("invalid_corsair_instance","Invalid corsair instance");return n}function Zr(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw new U("plugin_not_found",`Plugin '${n}' not found`);return t}function qr(e){let n=e.oauthConfig;if(!n)throw new U("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Fn(e,n){let t=Kr(e);if(!t.database)throw new U("no_database","No database configured on corsair instance");let r=t.connect?.redirectUri;if(!r)throw new U("no_redirect_uri","No redirectUri configured. Set connect.redirectUri in createCorsair().");let i=_e(n,t.kek);if(!i)throw new U("invalid_state","Invalid or tampered state parameter");let{plugin:o,tenantId:s}=i,a=Zr(t,o),c=qr(a),d=await N({authType:"oauth_2",integrationName:o,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new U("client_id_not_configured",`client_id not configured for '${o}'`);let u={...c.authParams,client_id:d,redirect_uri:r,response_type:"code",scope:c.scopes.join(" "),state:n},g=`${c.authUrl}?${ht.stringify(u)}`;return{plugin:o,tenantId:s,providerName:c.providerName,oauthUrl:g,state:n}}var A=class extends Error{status;code;extra;constructor(n,t,r,i={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=i}};function R(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function mt(e){let n={error:e.code,message:e.message,...e.extra};return R(e.status,n)}function re(e){return new A(404,"not_found",e)}function Q(e,n={}){return new A(400,"bad_request",e,n)}function kt(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw re(`Plugin '${n}' not found`);return t}async function Nn(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=ce[t].integration,o=r,s;try{s=await Promise.all(i.map(l=>o[`get_${l}`]()))}catch{s=i.map(()=>null)}let a=i.filter((l,d)=>s[d]==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 bt(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:i,missingFields:o}=await Nn(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 ze(){return{ok:!0}}async function Je(e){return Promise.all(e.plugins.map(n=>bt(n,e)))}async function Ve(e,n){let t=kt(e,n);return bt(t,e)}async function wt(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 Ct(e,n){let t=await wt(e,n),r=t.filter(i=>i.hasCredentials).map(i=>i.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Qe(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 Ye(e,n){if(!n)throw Q("Tenant id must be a non-empty string");return Ct(e,n)}async function Xe(e,n){let t=n?.id?.trim();if(!t)throw Q("Tenant id is required",{missingFields:["id"]});return Ct(e,t)}async function en(e,n){let t=n?.trim()||"default",r={},i=e.database?await wt(e,t):[],o=new Map(i.map(s=>[s.integrationName,s]));for(let s of e.plugins){if(!(await Nn(s,e)).configured){r[s.id]="missing_credentials";continue}let c=o.get(s.id),l;c&&c.hasCredentials?l="connected":l="not_connected",r[s.id]=l}return r}async function nn(e,n){if(!e.database)throw re(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw re(`Permission '${n}' not found`);return t}function Gr(e){if(!e.oauthConfig)throw Q(`Plugin '${e.id}' has no oauthConfig`)}function Un(e){if(!e.connect)throw new A(500,"connect_not_configured","createCorsair was not given a connect config. Set { connect: { baseUrl, redirectUri } } to enable /connect routes.");return e.connect}async function tn(e,n){let t=n?.plugin?.trim();if(!t)throw Q("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",i=kt(e,t);Gr(i);let o=Un(e);if(!e.database||!e.kek)throw new A(500,"database_not_configured","A database and kek are required to issue connect links.");let s=await Nn(i,e);if(!s.configured)throw new A(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=ee(K(t,r),e.kek),c;try{c=new URL(o.baseUrl)}catch{throw new A(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 rn(e,n,t){let r=t?.trim();if(!r)throw Q("state is required",{missingFields:["state"]});Un(n);try{return await Fn(e,r)}catch(i){if(i instanceof U)switch(i.code){case"invalid_state":throw Q("Invalid or expired state");case"client_id_not_configured":throw new A(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new A(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function on(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 Q("Missing required fields",{missingFields:o});let s=Un(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 Q("Invalid or expired state");case"credentials_not_configured":throw new A(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new A(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function sn(e,n){if(!e.database)throw re("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw re("Permission not found");return t}var Tt=[{method:"GET",pattern:"/ok",handler:async()=>R(200,ze())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>R(200,await Qe(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>R(201,await Xe(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>R(200,await Ye(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>R(200,await Je(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>R(200,await Ve(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>R(200,await en(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>R(200,await nn(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?R(200,await sn(e,t)):R(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({internal:e,body:n})=>R(200,await tn(e,n))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>R(200,await rn(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>R(200,await on(e,n,t))}];(()=>{let e=new Set;for(let n of Tt){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function zr(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 Jr(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 Vr(e){let n=e[x];if(!n)throw new Error("managementHandler: invalid corsair instance (missing internal config)");return n}async function Qr(e){if(!(e.method==="GET"||e.method==="HEAD"||!(e.headers.get("content-type")??"").includes("application/json")))try{let t=await e.text();return t?JSON.parse(t):void 0}catch{throw new A(400,"invalid_json","Request body is not valid JSON")}}var Yr="/api/corsair";function ue(e,n={}){let t=n.basePath??Yr,r=Vr(e);return async i=>{try{let o=new URL(i.url),s=Jr(o.pathname,t),a=i.method.toUpperCase(),c=Object.fromEntries(o.searchParams);for(let l of Tt){if(l.method!==a)continue;let d=zr(l.pattern,s);if(!d)continue;let u=await Qr(i);return await l.handler({corsair:e,internal:r,req:i,params:d,query:c,body:u})}throw re(`No route for ${a} ${s}`)}catch(o){if(n.onError){let a=await n.onError(o,i);if(a)return a}if(o instanceof A)return mt(o);let s=o instanceof Error?o.message:"Internal server error";return R(500,{error:"internal_error",message:s})}}}function Xr(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,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let d of l)o.append(c,d);else o.set(c,l);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 eo(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 xt(e,n){let t=ue(e,n);return async(r,i,o)=>{try{let s=await t(Xr(r));await eo(i,s)}catch(s){o(s)}}}function Pt(e,n){let t=ue(e,n);return r=>t(r.req.raw)}function At(e,n){let t=ue(e,n);return{GET:t,POST:t}}function Rt(e){let n={[x]:e};return{ok:ze,tenants:{list:()=>Qe(e),create:t=>Xe(e,t),get:t=>Ye(e,t)},plugins:{list:()=>Je(e),get:t=>Ve(e,t)},connectionStatus:{get:t=>en(e,t?.tenantId)},permissions:{get:t=>nn(e,t),getByToken:t=>sn(e,t)},connect:{createLink:t=>tn(e,t),resolve:t=>rn(n,e,t),oauthCallback:t=>on(n,e,t)}}}async function vt(e,n,t,r,i="pending"){if(!e)return null;try{let o=zn(),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 no(e,n,t,r="pending"){try{let i=await e.$getAccountId();return vt(e.database,i,n,t,r)}catch(i){return console.warn("Failed to log event:",i),null}}import*as It from"https";import*as St from"querystring";function an(e,n,t,r,i){let o=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,c)=>{let l={code:e.trim(),redirect_uri:i,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let d=St.stringify(l),u={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(d).toString()};s&&(u.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let g=It.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(d),g.end()})}var Et=" ";function B(e){let n=e;return n._def??n.def??{}}function W(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 $(e){return e.innerType??e.schema??e.out??e.in}function Ot(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 $(e)}}function Ht(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function un(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function he(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 Dt(e,n){return e.description??n.description}function to(e){let n=e;for(;n;){let t=B(n),r=Dt(n,t);if(r)return r;let i=W(t);if(jn(i)||i==="ZodPipe"||i==="ZodEffects"||i==="ZodTransform"){n=Ot(t,i);continue}break}}function jn(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function O(e){let n=B(e),t=W(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??he(n)[0]??"unknown");case"ZodEnum":return he(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=$(n);return r?O(r):"unknown"}case"ZodNullable":{let r=$(n);return`${r?O(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=$(n);return r?O(r):"unknown"}case"ZodArray":{let r=Ht(n);if(!r)return"unknown[]";let i=B(r),o=W(i)==="ZodUnion",s=O(r);return`${o?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=un(e,n),i=Object.entries(r);return i.length===0?"{}":`{ ${i.map(([s,a])=>{let c=W(B(a));return`${c==="ZodOptional"||c==="ZodNullable"?s+"?":s}: ${O(a)}`}).join(", ")} }`}case"ZodUnion":return he(n).map(r=>O(r)).join(" | ");case"ZodIntersection":return`${O(n.left)} & ${O(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=Ot(n,t);return r?O(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function Y(e){let n=B(e),t=W(n),r=Dt(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??he(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=he(n).map(o=>String(o));return{kind:"string",optional:!1,description:r,enum:i}}case"ZodOptional":{let i=$(n),o=i?Y(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodNullable":{let i=$(n),o=i?Y(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodDefault":case"ZodCatch":{let i=$(n);return i?{...Y(i),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let i=Ht(n);return{kind:"array",optional:!1,description:r,items:i?Y(i):{kind:"unknown",optional:!1}}}case"ZodObject":{let i=un(e,n),o={};for(let[s,a]of Object.entries(i))o[s]=Y(a);return{kind:"object",optional:!1,description:r,fields:o}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let i=he(n);for(let o of i){let s=B(o);if(W(s)==="ZodObject")return{...Y(o),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let i=$(n);return i?{...Y(i),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function qs(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(d=>d.id===i);if(!s)return null;let a=o;a.startsWith("api.")&&(a=a.slice(4));let c=oe(s.endpointMeta,a),l=oe(s.endpointSchemas,a);return!c&&!l?null:{input:l?.input?Y(l.input):null,output:l?.output?Y(l.output):null,description:c?.description}}var Kn=["equals","contains","startsWith","endsWith","in"],ro=["equals","gt","gte","lt","lte","in"],oo=["equals"],io=["equals","before","after","between"];function Mt(e){let n=B(e);switch(W(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=$(n);return r?Mt(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Zn(e){let n=B(e),t=W(n);if(jn(t)){let o=$(n);return o?Zn(o):{}}if(t!=="ZodObject")return{};let r=un(e,n),i={};for(let[o,s]of Object.entries(r)){let a=Mt(s);a==="string"?i[o]={type:"string",operators:Kn}:a==="number"?i[o]={type:"number",operators:ro}:a==="boolean"?i[o]={type:"boolean",operators:oo}:a==="date"&&(i[o]={type:"date",operators:io})}return i}function Ft(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Bn(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"&&Bn(i,o,t)}}function Wn(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Ln(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];Wn(i)?t.push(o.join(".")):i!==null&&typeof i=="object"&&Ln(i,o,t)}}function qn(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 Wn(s)?[o]:null;if(s!==null&&typeof s=="object"&&!Wn(s)){let a=qn(s,r);if(a!==null)return[o,...a]}return null}function Nt(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 so=new Set(Ie);function de(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 so.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:de(e);if(t==="webhooks"){if(!o.webhooks)return[];let a=[];return Ln(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 Bn(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=[];Ln(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=[];Bn(o.endpoints,[],s),i[o.id]=s.map(a=>`${o.id}.api.${a}`)}return i}function oe(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function ao(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 $n(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 Gs(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 d=o.slice(3),u=d.lastIndexOf(".");if(u!==-1){let g=d.slice(0,u),f=d.slice(u+1),p=s.schema?.entities;if(f==="search"&&p){let y=Ft(p,g);if(y){let[m,w]=y,T=Zn(w),k=[`Search ${i} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${Kn.join(", ")}]`];for(let[h,b]of Object.entries(T))k.push(` ${h}?: ${b.type} [${b.operators.join(", ")}]`);return k.push("}"),k.join(`
|
|
18
|
+
`)}}}return $n(de(e,{type:"db"}),"Path not found. Available db operations")}if(o.startsWith("webhooks.")){let d=o.slice(9);if(s.webhooks){let u=qn(s.webhooks,d.split("."));if(u!==null){let g=u.join("."),f=oe(s.webhookSchemas,g.toLowerCase()),p=f?.response?O(f.response):null,y=[];return f?.description&&y.push(f.description),f?.payload&&y.push(`payload ${cn(me(f.payload))}`),p&&y.push(`response: ${p}`),y.push(`usage:
|
|
19
|
+
${Nt(i,u)}`),y.join(`
|
|
20
|
+
|
|
21
|
+
`)}}return $n(de(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=o;a.startsWith("api.")&&(a=a.slice(4));let c=oe(s.endpointMeta,a),l=oe(s.endpointSchemas,a);if(c||l){let d=[],u=[c?.riskLevel?`[${c.riskLevel}]`:"",c?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),g=[c?.description,u].filter(Boolean).join(" ");return g&&d.push(g),l?.input&&d.push(`input ${cn(me(l.input))}`),l?.output&&d.push(`output ${cn(me(l.output))}`),d.join(`
|
|
22
|
+
|
|
23
|
+
`)}}}return $n(de(e),"Path not found. Available operations")}function _t(e){let n=e;for(;;){let t=B(n),r=W(t);if(jn(r)){let i=$(t);if(!i)return n;n=i;continue}return n}}function me(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=_t(e),t=B(n);if(W(t)==="ZodObject"){let i=un(n,t),o=[];for(let[s,a]of Object.entries(i)){let c=B(a),l=W(c),d=l==="ZodOptional"||l==="ZodNullable",u=_t(a),g=to(a);o.push({key:s,optional:d,type:O(u),...g!==void 0?{description:g}:{}})}return{kind:"object",fields:o}}return{kind:"inline",type:O(n)}}function cn(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=Et.repeat(n+1),r=Et.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 co(e,n){let t=de(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(d=>d.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let i=[];for(let d of t){let{shortPath:u,lookupKey:g}=ao(d,n),f=oe(r.endpointMeta,g),p=oe(r.endpointSchemas,g);!f&&!p||i.push({path:d,shortPath:u,description:f?.description,riskLevel:f?.riskLevel,irreversible:f?.irreversible,input:me(p?.input),output:me(p?.output)})}i.sort((d,u)=>d.path.localeCompare(u.path));let o=[],s=de(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let d of s){let g=d.toLowerCase().slice(n.length+1),f=g.startsWith(".")?g.slice(1):g;if(!f.startsWith("webhooks."))continue;let p=f.slice(9),y=qn(r.webhooks,p.split("."));if(y===null)continue;let m=y.join("."),w=oe(r.webhookSchemas,m.toLowerCase()),T=w?.response?O(w.response):void 0;o.push({path:d,description:w?.description,payload:me(w?.payload),responseType:T,usageExample:Nt(n,y)})}o.sort((d,u)=>d.path.localeCompare(u.path));let a=[],c=de(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(c)&&l)for(let d of c){let g=d.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 T=Ft(l,m);if(!T)continue;let[k,h]=T,b=Zn(h),C=Object.entries(b).map(([I,S])=>({field:I,type:S.type,operators:S.operators}));a.push({path:d,entityName:k,filters:[{field:"entity_id",type:"string",operators:Kn},...C]})}return a.sort((d,u)=>d.path.localeCompare(u.path)),{ok:!0,data:{pluginId:n,api:i,webhooks:o,db:a}}}function Ut(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function uo(e,n){let t=Ut(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 lo(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function $t(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Bt(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 Re(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function po(e){return Re(e.body)}function Wt(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return dn(Array.isArray(r)?r:[r])}function Lt(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let l=dn(Array.isArray(c)?c:[c]);if(l)return decodeURIComponent(l)}let r=Wt({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 l=n[c],d=Array.isArray(l)?l[0]:l;if(!(!d||typeof d!="string"))try{let g=(d.startsWith("http")?new URL(d):new URL(`https://example.invalid${d.startsWith("/")?d:`/${d}`}`)).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=Re(typeof o=="string"?(()=>{try{return JSON.parse(o)}catch{return o}})():o);return dn([s?.validationToken])??null}function go(e){if(Lt(e))return!0;let n=Re(e.body??e.payload);return $t(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function dn(e){for(let n of e){let t=Bt(n);if(t)return t}}function fo(e){let t=Re(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 ra(e){let n=e.database?Gn(e.database):void 0,t=n&&e.kek?yt(e.plugins,n,e.kek):Ge(!!n,!!e.kek),r={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,approval:e.approval,connect:e.connect,hub:e.hub?Se(e.hub):void 0},i=gt(n),o=Rt(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=Mn(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=Mn(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 q=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Kt(e){let n=e[x];if(!n)throw new q("invalid_corsair_instance","Invalid corsair instance");return n}function Zt(e,n){let t=e.plugins.find(r=>r.id===n);if(!t)throw new q("plugin_not_found",`Plugin '${n}' not found`);return t}function qt(e){let n=e.oauthConfig;if(!n)throw new q("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function yo(e,n,t,r){let i=ve(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=D(),c=await M(a,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:c})}async function yn(e,n,t){let{tenantId:r,redirectUri:i}=t,o=Kt(e);if(!o.database)throw new Error("No database configured on corsair instance");let s=Zt(o,n),a=qt(s),l=await N({authType:"oauth_2",integrationName:n,kek:o.kek,database:o.database}).get_client_id();if(!l)throw new Error(`client_id not configured for '${n}'`);let d=ee(K(n,r),o.kek),u={...a.authParams,client_id:l,redirect_uri:i,response_type:"code",scope:a.scopes.join(" "),state:d};return{url:`${a.authUrl}?${jt.stringify(u)}`,state:d}}async function Ae(e,n){let{code:t,state:r,redirectUri:i}=n,o=Kt(e),s=_e(r,o.kek);if(!s)throw new q("invalid_state","Invalid or tampered state parameter");let{plugin:a,tenantId:c}=s;if(!o.database)throw new q("no_database","No database configured on corsair instance");let l=Zt(o,a),d=qt(l),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 q("credentials_not_configured",`Credentials not configured for '${a}'`);await yo(o.database,a,c,o.kek);let p=await an(t,g,f,d,i);if(!p.access_token)throw new q("no_access_token",`No access_token returned from ${d.providerName}`);let y=Z({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 Me(o.plugins,a,p);if(m)try{let w=l.authConfig?.oauth_2?.account??[];await fe({database:o.database,kek:o.kek,pluginId:a,tenantId:c,link:m,authType:"oauth_2",extraAccountFields:w})}catch(w){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${a}' tenant '${c}':`,w)}}catch(m){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${a}' tenant '${c}':`,m)}return{plugin:a,tenantId:c}}export{Jn as a,be as b,we as c,G as d,Se as e,z as f,Ee as g,K as h,gn as i,D as j,M as k,F as l,wn as m,xe as n,ne as o,J as p,Pe as q,ce as r,N as s,Z as t,nt as u,tt as v,fe as w,Tn as x,$e as y,ot as z,q as A,yn as B,Ae as C,ge as D,se as E,fn as F,ae as G,He as H,hn as I,mn as J,kn as K,bn as L,De as M,te as N,ye as O,st as P,Be as Q,We as R,Le as S,Pn as T,An as U,je as V,Ke as W,Rn as X,vn as Y,In as Z,Ze as _,V as $,Sn as aa,ut as ba,dt as ca,Fn as da,ue as ea,xt as fa,Pt as ga,At as ha,vt as ia,no as ja,an as ka,qs as la,de as ma,Gs as na,cn as oa,co as pa,Ut as qa,uo as ra,lo as sa,$t as ta,Bt as ua,Re as va,po as wa,Wt as xa,Lt as ya,go as za,dn as Aa,fo as Ba,x as Ca,ra as Da};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
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,
|
|
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?
|
|
1
|
+
import{Ca as v,Da as j,r as m,s as _,t as R}from"./chunk-J6HIPZAR.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};
|
package/dist/core.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
|
|
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-mZfhN-6e.js';
|
|
3
2
|
import { CorsairDatabase } from './db.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { A as AuthTypes, a as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './types-B1We8TTP.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-B1We8TTP.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-BHyMcpwm.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-DXoUP9o9.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,
|
|
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{
|
|
1
|
+
import{$ as p,Aa as G,Ba as H,Ca as I,Da as J,a,b,da as q,ia as r,j as c,ja as s,k as d,ka as t,l as e,m as f,n as g,o as h,oa as u,p as i,pa as v,q as j,qa as w,r as k,ra as x,s as l,sa as y,t as m,ta as z,u as n,ua as A,v as o,va as B,wa as C,xa as D,ya as E,za as F}from"./chunk-J6HIPZAR.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
|
|
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,140 @@
|
|
|
1
|
+
import { l as HubConnectSource, m as HubOAuthMode, H as HubConfig, n as HubConfigInput, o as HubConnectSessionInput, p as HubConnectSessionResult, a as AccountKeyManagerFor } from './types-B1We8TTP.js';
|
|
2
|
+
export { D as DEFAULT_HUB_API_URL, i as formatProviderDisplayName } from './types-B1We8TTP.js';
|
|
3
|
+
import { c as ProcessCorsairRequest } from './index-aVkEGoHG.js';
|
|
4
|
+
|
|
5
|
+
type ConnectSourceValidationError = {
|
|
6
|
+
error: string;
|
|
7
|
+
status: number;
|
|
8
|
+
};
|
|
9
|
+
declare function isLoopbackDeliveryUrl(deliveryUrl: string): boolean;
|
|
10
|
+
declare function resolveConnectSourceFromDeliveryUrl(deliveryUrl: string): HubConnectSource;
|
|
11
|
+
declare function shouldUseBrowserConnectDelivery(source: HubConnectSource, deliveryUrl: string): boolean;
|
|
12
|
+
declare function validateExplicitConnectSource(input: {
|
|
13
|
+
source?: HubConnectSource;
|
|
14
|
+
deliveryUrl: string;
|
|
15
|
+
oauthMode?: HubOAuthMode;
|
|
16
|
+
}): ConnectSourceValidationError | null;
|
|
17
|
+
|
|
18
|
+
declare class HubNotConfiguredError extends Error {
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
declare function normalizeHubConfig(input: HubConfigInput): HubConfig;
|
|
22
|
+
declare function getHubConfig(corsair: unknown): HubConfig;
|
|
23
|
+
declare function resolveHubOAuthCallbackUrl(config: HubConfig): string;
|
|
24
|
+
|
|
25
|
+
declare function createHubConnectSession(corsair: unknown, input: HubConnectSessionInput): Promise<HubConnectSessionResult>;
|
|
26
|
+
|
|
27
|
+
type HubConnectSessionRequestBody = {
|
|
28
|
+
plugin?: string;
|
|
29
|
+
tenantId?: string;
|
|
30
|
+
source?: string;
|
|
31
|
+
oauthMode?: string;
|
|
32
|
+
providerName?: string;
|
|
33
|
+
};
|
|
34
|
+
type HubConnectSessionParseError = {
|
|
35
|
+
error: string;
|
|
36
|
+
status: number;
|
|
37
|
+
};
|
|
38
|
+
type HubConnectSessionSuccessBody = {
|
|
39
|
+
ok: true;
|
|
40
|
+
connectUrl: string;
|
|
41
|
+
token: string;
|
|
42
|
+
projectId: string;
|
|
43
|
+
expiresAt?: string;
|
|
44
|
+
};
|
|
45
|
+
type ResolveHubConnectTenantId = (request: Request) => Promise<string | null | undefined> | string | null | undefined;
|
|
46
|
+
type HubConnectSessionResponseOptions = {
|
|
47
|
+
/**
|
|
48
|
+
* When provided, tenantId from the request body or query is ignored.
|
|
49
|
+
* Return null or undefined to respond with 401 Unauthorized.
|
|
50
|
+
*/
|
|
51
|
+
resolveTenantId?: ResolveHubConnectTenantId;
|
|
52
|
+
/** Used when resolveTenantId is not provided. Defaults to "default". */
|
|
53
|
+
defaultTenantId?: string;
|
|
54
|
+
};
|
|
55
|
+
declare function parseHubConnectSessionBody(body: HubConnectSessionRequestBody): HubConnectSessionInput | HubConnectSessionParseError;
|
|
56
|
+
declare function parseHubConnectSessionSearchParams(url: string): HubConnectSessionRequestBody;
|
|
57
|
+
declare function handleHubConnectSessionRequest(corsair: unknown, request: Request, options?: HubConnectSessionResponseOptions): Promise<HubConnectSessionSuccessBody | HubConnectSessionParseError>;
|
|
58
|
+
declare function respondToHubConnectSession(corsair: unknown, request: Request, options?: HubConnectSessionResponseOptions): Promise<Response>;
|
|
59
|
+
declare function respondToHubConnectSessionFromRequest(corsair: unknown, request: Request, options?: HubConnectSessionResponseOptions): Promise<Response>;
|
|
60
|
+
|
|
61
|
+
type HubDeliveryResult = {
|
|
62
|
+
type: 'redirect';
|
|
63
|
+
url: string;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'json';
|
|
66
|
+
body: unknown;
|
|
67
|
+
status: number;
|
|
68
|
+
headers?: Record<string, string>;
|
|
69
|
+
} | {
|
|
70
|
+
type: 'text';
|
|
71
|
+
body: string | null;
|
|
72
|
+
status: number;
|
|
73
|
+
headers?: Record<string, string>;
|
|
74
|
+
};
|
|
75
|
+
declare function handleHubDeliveryGet(corsair: unknown, requestUrl: string): Promise<HubDeliveryResult>;
|
|
76
|
+
declare function handleHubDeliveryPost(corsair: unknown, request: ProcessCorsairRequest): Promise<HubDeliveryResult>;
|
|
77
|
+
|
|
78
|
+
type HubDeliveryRequest = {
|
|
79
|
+
method: 'GET' | 'POST';
|
|
80
|
+
url: string;
|
|
81
|
+
headers: ProcessCorsairRequest['headers'];
|
|
82
|
+
body?: string;
|
|
83
|
+
};
|
|
84
|
+
declare function hubDeliveryToResponse(result: HubDeliveryResult): Response;
|
|
85
|
+
declare function handleHubDeliveryRequest(corsair: unknown, request: HubDeliveryRequest): Promise<HubDeliveryResult>;
|
|
86
|
+
declare function respondToHubDelivery(corsair: unknown, request: HubDeliveryRequest): Promise<Response>;
|
|
87
|
+
declare function respondToHubDeliveryFromRequest(corsair: unknown, request: Request): Promise<Response>;
|
|
88
|
+
|
|
89
|
+
type ManagedAuthContext = {
|
|
90
|
+
keys: AccountKeyManagerFor<'managed'>;
|
|
91
|
+
hub: HubConfig;
|
|
92
|
+
plugin: string;
|
|
93
|
+
tenantId: string;
|
|
94
|
+
};
|
|
95
|
+
type ManagedAccessTokenResult = {
|
|
96
|
+
accessToken: string;
|
|
97
|
+
expiresAt: number;
|
|
98
|
+
refreshed: boolean;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Returns a valid access token for a managed OAuth connection.
|
|
102
|
+
* Uses cached credentials when still valid; otherwise refreshes via the hub.
|
|
103
|
+
*/
|
|
104
|
+
declare function getManagedAccessToken(ctx: ManagedAuthContext, options?: {
|
|
105
|
+
forceRefresh?: boolean;
|
|
106
|
+
}): Promise<ManagedAccessTokenResult>;
|
|
107
|
+
/**
|
|
108
|
+
* Attaches a `_refreshAuth` helper on the keyBuilder context for 401 retries.
|
|
109
|
+
*/
|
|
110
|
+
declare function attachManagedRefreshAuth(ctx: Record<string, unknown>, managedContext: ManagedAuthContext): Promise<void>;
|
|
111
|
+
|
|
112
|
+
type ManagedOAuthDeliveryErrorCode = 'invalid_corsair_instance' | 'no_database' | 'plugin_not_found' | 'no_access_token';
|
|
113
|
+
declare class ManagedOAuthDeliveryError extends Error {
|
|
114
|
+
readonly code: ManagedOAuthDeliveryErrorCode;
|
|
115
|
+
constructor(code: ManagedOAuthDeliveryErrorCode, message: string);
|
|
116
|
+
}
|
|
117
|
+
type ProcessManagedOAuthDeliveryOptions = {
|
|
118
|
+
plugin: string;
|
|
119
|
+
tenantId: string;
|
|
120
|
+
accessToken: string;
|
|
121
|
+
refreshToken?: string;
|
|
122
|
+
expiresIn?: number;
|
|
123
|
+
scope?: string;
|
|
124
|
+
};
|
|
125
|
+
type ProcessManagedOAuthDeliveryResult = {
|
|
126
|
+
plugin: string;
|
|
127
|
+
tenantId: string;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Stores managed OAuth tokens delivered from the hub after a successful connect.
|
|
131
|
+
*/
|
|
132
|
+
declare function processManagedOAuthDelivery(corsair: unknown, options: ProcessManagedOAuthDeliveryOptions): Promise<ProcessManagedOAuthDeliveryResult>;
|
|
133
|
+
|
|
134
|
+
type HubRouteHandlersOptions = HubConnectSessionResponseOptions;
|
|
135
|
+
declare function createHubRouteHandlers(corsair: unknown, options?: HubRouteHandlersOptions): {
|
|
136
|
+
delivery: (request: Request) => Promise<Response>;
|
|
137
|
+
createConnectSession: (request: Request) => Promise<Response>;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export { type ConnectSourceValidationError, HubConfig, HubConfigInput, HubConnectSessionInput, type HubConnectSessionParseError, type HubConnectSessionRequestBody, type HubConnectSessionResponseOptions, HubConnectSessionResult, type HubConnectSessionSuccessBody, HubConnectSource, type HubDeliveryRequest, type HubDeliveryResult, HubNotConfiguredError, HubOAuthMode, 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, resolveConnectSourceFromDeliveryUrl, resolveHubOAuthCallbackUrl, respondToHubConnectSession, respondToHubConnectSessionFromRequest, respondToHubDelivery, respondToHubDeliveryFromRequest, shouldUseBrowserConnectDelivery, validateExplicitConnectSource };
|
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,N as q,O as r,V as s,W as t,X as u,Y as v,Z as w,_ as x,aa as y,b as a,ba as z,c as b,ca as A,d as c,e as d,f as e,g as f}from"./chunk-J6HIPZAR.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as DEFAULT_HUB_API_URL,c as HubNotConfiguredError,q as ManagedOAuthDeliveryError,z as attachManagedRefreshAuth,k as createHubConnectSession,A as createHubRouteHandlers,a as formatProviderDisplayName,e as getHubConfig,y as getManagedAccessToken,n as handleHubConnectSessionRequest,s as handleHubDeliveryGet,t as handleHubDeliveryPost,v as handleHubDeliveryRequest,u as hubDeliveryToResponse,g as isLoopbackDeliveryUrl,d as normalizeHubConfig,l as parseHubConnectSessionBody,m as parseHubConnectSessionSearchParams,r as processManagedOAuthDelivery,h as resolveConnectSourceFromDeliveryUrl,f as resolveHubOAuthCallbackUrl,o as respondToHubConnectSession,p as respondToHubConnectSessionFromRequest,w as respondToHubDelivery,x as respondToHubDeliveryFromRequest,i as shouldUseBrowserConnectDelivery,j as validateExplicitConnectSource};
|