corsair 0.1.81 → 0.1.82
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-NZS35HPL.js +1 -0
- package/dist/chunk-SBBVO5OB.js +38 -0
- package/dist/core.d.ts +3 -3
- package/dist/core.js +1 -1
- package/dist/hub.d.ts +9 -2
- package/dist/hub.js +1 -1
- package/dist/{index-B06cXWWA.d.ts → index-VQ5aPg7o.d.ts} +1 -1
- package/dist/{index-D9gndzCb.d.ts → index-t-u4QNP-.d.ts} +27 -2
- package/dist/index.d.ts +7 -7
- package/dist/index.js +2 -2
- package/dist/oauth.js +1 -1
- package/dist/orm.js +1 -1
- package/dist/setup.d.ts +2 -2
- package/dist/setup.js +1 -1
- package/dist/{tenant-links-CN6FYmyf.d.ts → tenant-links-x_63WNLM.d.ts} +1 -1
- package/dist/{tenant-match-utils-CAvC74W2.d.ts → tenant-match-utils-CXChw66S.d.ts} +1 -1
- package/dist/tunnel.d.ts +8 -23
- package/dist/tunnel.js +1 -1
- package/package.json +23 -1
- package/dist/chunk-6D4UDUPJ.js +0 -1
- package/dist/chunk-GJ743ML7.js +0 -30
- package/dist/{index-DXZWwzui.d.ts → index-Cl0-2f8A.d.ts} +198 -198
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as F,c as D,d as P,e as B}from"./chunk-IGGCNGU2.js";var R={oauth_2:{integration:["client_id","client_secret","redirect_url"],account:["access_token","refresh_token","expires_at","scope","webhook_signature"]},api_key:{integration:[],account:["api_key","webhook_signature"]},bot_token:{integration:[],account:["bot_token","webhook_signature"]},managed:{integration:[],account:["access_token","refresh_token","expires_at","scope","webhook_signature"]}};function L(e,t){if(!e||typeof e!="object")return;let r=e[t];return typeof r=="function"?(...n)=>Reflect.apply(r,e,n):void 0}import{Kysely as J}from"kysely";var H=Symbol.for("corsair:internal"),x=class extends Error{constructor(t="Invalid corsair instance"){super(t),this.name="InvalidCorsairInstanceError"}};function I(e){return typeof e=="object"&&e!==null}function S(e){return!I(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:I(e.database)?e.database.db instanceof J:!1}function O(e){if(!e||typeof e!="object")return;let r=Object.getOwnPropertyDescriptor(e,H)?.value;return S(r)?r:void 0}function G(e,t){let r=O(e);if(!r)throw t?.()??new x;return r}function N(e,t){return e.plugins.find(r=>r.id===t)}function X(e,t,r){let n=N(e,t);if(!n)throw r(`Plugin '${t}' not found`);return n}function Y(e){return"withTenant"in e&&typeof e.withTenant=="function"}import{v7 as q}from"uuid";function T(){return q()}function v(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function V(e){let t=e.options?.authType;return v(t)?t:void 0}function ee(e,t){let r=e.authConfig,n=R[t].account,i=r?.[t]?.account??[];return[...n,...i]}import{z as h}from"zod";import{sql as w}from"kysely";function A(e){return e.replace(/'/g,"''")}function W(e){let t=A(e);return w`data->>'${w.raw(t)}'`}function j(e){let t=A(e);return w`(data->>'${w.raw(t)}')::numeric`}function K(e){let t=A(e);return w`(data->>'${w.raw(t)}')::boolean`}function U(e){let t=A(e);return w`(data->>'${w.raw(t)}')::timestamptz`}function te(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function Z(e){let t=e;for(;t;){if(t instanceof h.ZodOptional||t instanceof h.ZodNullable){t=t._def.innerType;continue}if(t instanceof h.ZodDefault){t=t._def.innerType;continue}break}return t}function ne(e){let t=Z(e);if(t instanceof h.ZodString)return"string";if(t instanceof h.ZodNumber)return"number";if(t instanceof h.ZodBoolean)return"boolean";if(t instanceof h.ZodDate)return"date"}function re(e){let t=Z(e);if(!(t instanceof h.ZodObject))return{};let r=t.shape,n={};for(let[i,a]of Object.entries(r)){let u=ne(a);u&&(n[i]=u)}return n}function ie(e,t,r){if(typeof r=="string")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;"equals"in n&&typeof n.equals=="string"&&(e=e.where(t,"=",n.equals)),"contains"in n&&typeof n.contains=="string"&&(e=e.where(t,"like",`%${n.contains}%`)),"startsWith"in n&&typeof n.startsWith=="string"&&(e=e.where(t,"like",`${n.startsWith}%`)),"endsWith"in n&&typeof n.endsWith=="string"&&(e=e.where(t,"like",`%${n.endsWith}`)),"in"in n&&Array.isArray(n.in)&&(e=e.where(t,"in",n.in))}return e}function oe(e,t,r){if(typeof r=="number")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;typeof n.equals=="number"&&(e=e.where(t,"=",n.equals)),typeof n.gt=="number"&&(e=e.where(t,">",n.gt)),typeof n.gte=="number"&&(e=e.where(t,">=",n.gte)),typeof n.lt=="number"&&(e=e.where(t,"<",n.lt)),typeof n.lte=="number"&&(e=e.where(t,"<=",n.lte)),Array.isArray(n.in)&&(e=e.where(t,"in",n.in))}return e}function se(e,t,r){if(typeof r=="boolean")return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;typeof n.equals=="boolean"&&(e=e.where(t,"=",n.equals))}return e}function ae(e,t,r){if(r instanceof Date)return e.where(t,"=",r);if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;if(n.equals instanceof Date&&(e=e.where(t,"=",n.equals)),n.before instanceof Date&&(e=e.where(t,"<",n.before)),n.after instanceof Date&&(e=e.where(t,">",n.after)),Array.isArray(n.between)&&n.between.length===2){let[i,a]=n.between;i instanceof Date&&(e=e.where(t,">=",i)),a instanceof Date&&(e=e.where(t,"<=",a))}}return e}function ue(e,t,r,n){return r==="number"?oe(e,j(t),n):r==="boolean"?se(e,K(t),n):r==="date"?ae(e,U(t),n):ie(e,W(t),n)}function ce(e,t,r){if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let n=r;return"equals"in n&&(e=e.where(t,"=",n.equals)),"contains"in n&&typeof n.contains=="string"&&(e=e.where(t,"like",`%${n.contains}%`)),"startsWith"in n&&typeof n.startsWith=="string"&&(e=e.where(t,"like",`${n.startsWith}%`)),"endsWith"in n&&typeof n.endsWith=="string"&&(e=e.where(t,"like",`%${n.endsWith}`)),"in"in n&&Array.isArray(n.in)&&(e=e.where(t,"in",n.in)),e}return e.where(t,"=",r)}function de(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function C(e,t,r){return e.selectFrom("corsair_entities").selectAll().where("account_id","=",t).where("entity_type","=",r)}function $(e,t,r,n,i){let a=re(i);function u(o){let y=te(o.data);return{...o,data:i.parse(y)}}return{findByEntityId:async o=>{let y=await t(),d=await C(e,y,r).where("entity_id","=",o).executeTakeFirst();return d?u(d):null},findById:async o=>{let y=await t(),d=await C(e,y,r).where("id","=",o).executeTakeFirst();return d?u(d):null},findManyByEntityIds:async o=>{if(o.length===0)return[];let y=await t();return(await C(e,y,r).where("entity_id","in",o).execute()).map(u)},list:async o=>{let y=await t(),d=C(e,y,r);return typeof o?.limit=="number"&&(d=d.limit(o.limit)),typeof o?.offset=="number"&&(d=d.offset(o.offset)),(await d.execute()).map(u)},search:async o=>{let y=await t(),d=C(e,y,r),c=new Set(["data","limit","offset"]);for(let[l,f]of Object.entries(o))c.has(l)||f===void 0||(d=ce(d,l,f));if(o.data&&typeof o.data=="object")for(let[l,f]of Object.entries(o.data)){if(f===void 0)continue;let g=a[l]??"string";d=ue(d,l,g,f)}return typeof o.limit=="number"&&(d=d.limit(o.limit)),typeof o.offset=="number"&&(d=d.offset(o.offset)),(await d.execute()).map(u)},upsertByEntityId:async(o,y)=>{let d=await t(),c=i.parse(y),s=new Date,l=await C(e,d,r).select("id").where("entity_id","=",o).executeTakeFirst();if(l?.id){await e.updateTable("corsair_entities").set({version:n,data:c,updated_at:s}).where("id","=",l.id).execute();let E=await e.selectFrom("corsair_entities").selectAll().where("id","=",l.id).executeTakeFirst();return u(E)}let f=T();await e.insertInto("corsair_entities").values({id:f,created_at:s,updated_at:s,account_id:d,entity_id:o,entity_type:r,version:n,data:c}).execute();let g=await e.selectFrom("corsair_entities").selectAll().where("id","=",f).executeTakeFirst();return u(g)},deleteById:async o=>{let y=await t(),d=await e.deleteFrom("corsair_entities").where("account_id","=",y).where("entity_type","=",r).where("id","=",o).executeTakeFirst();return Number(d.numDeletedRows)>0},deleteByEntityId:async o=>{let y=await t(),d=await e.deleteFrom("corsair_entities").where("account_id","=",y).where("entity_type","=",r).where("entity_id","=",o).executeTakeFirst();return Number(d.numDeletedRows)>0},count:async()=>{let o=await t(),y=await e.selectFrom("corsair_entities").select(d=>d.fn.countAll().as("count")).where("account_id","=",o).where("entity_type","=",r).executeTakeFirst();return de(y?.count)}}}var le={corsair_integrations:F,corsair_accounts:D,corsair_entities:P,corsair_events:B};function ye(e){return le[e]}function M(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function p(e){if(!e)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function b(e){if(!e)return[];let t=[];for(let r in e){let n=r,i=e[n];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let a=i;"in"in a&&Array.isArray(a.in)?t.push({field:n,operator:"in",value:a.in}):"like"in a&&typeof a.like=="string"&&t.push({field:n,operator:"like",value:a.like})}else t.push({field:n,value:i})}return t}function m(e,t){if(!t?.length)return e;let r=e;for(let n of t){let i=n.operator??"=";r=r.where(n.field,i,n.value)}return r}function fe(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function k(e,t){let r=ye(t),n=()=>(p(e),e),i=()=>n().db.selectFrom(t),a=()=>n().db.insertInto(t),u=()=>n().db.updateTable(t),o=()=>n().db.deleteFrom(t);function y(c){let s={};for(let[l,f]of Object.entries(c))s[l]=M(f);return r.parse(s)}function d(c){let s={};for(let[l,f]of Object.entries(c))s[l]=M(f);return r.parse(s)}return{findById:async c=>{p(e);let s=i().selectAll();s=m(s,[{field:"id",value:c}]);let l=await s.executeTakeFirst();return l?y(l):null},findOne:async c=>{p(e);let s=i().selectAll();s=m(s,b(c));let l=await s.executeTakeFirst();return l?y(l):null},findMany:async c=>{p(e);let s=i().selectAll();return s=m(s,b(c?.where)),typeof c?.limit=="number"&&(s=s.limit(c.limit)),typeof c?.offset=="number"&&(s=s.offset(c.offset)),(await s.execute()).map(f=>y(f))},create:async c=>{p(e);let s=new Date,l={id:c.id??T(),created_at:s,updated_at:s,...c},f=await a().values(l).returningAll().executeTakeFirst();return f?y(f):d(l)},update:async(c,s)=>{p(e);let l={...s,updated_at:new Date},f=u().set(l).returningAll();f=m(f,[{field:"id",value:c}]);let g=await f.executeTakeFirst();return g?y(g):null},updateMany:async(c,s)=>{p(e);let l={...s,updated_at:new Date},f=i().select("id");f=m(f,b(c));let g=await f.execute();for(let E of g){let _=u().set(l);_=m(_,[{field:"id",value:E.id}]),await _.execute()}return g.length},delete:async c=>{p(e);let s=o();s=m(s,[{field:"id",value:c}]);let l=await s.executeTakeFirst();return Number(l?.numDeletedRows??0)>0},deleteMany:async c=>{p(e);let s=o();s=m(s,b(c));let l=await s.executeTakeFirst();return Number(l?.numDeletedRows??0)},count:async c=>{p(e);let s=i().select(f=>f.fn.countAll().as("count"));s=m(s,b(c));let l=await s.executeTakeFirst();return fe(l?.count)}}}function pe(e){let t=k(e,"corsair_integrations");return{...t,findByName:r=>t.findOne({name:r}),upsertByName:async(r,n)=>{let i=await t.findOne({name:r});return i?await t.update(i.id,n):t.create({...n,name:r})}}}function ge(e){let t=k(e,"corsair_accounts");return{...t,findByTenantAndIntegration:async(r,n)=>{p(e);let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();return i?t.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,n)=>t.findMany({where:{tenant_id:r},limit:n?.limit,offset:n?.offset}),upsertByTenantAndIntegration:async(r,n,i)=>{let a=await t.findOne({tenant_id:r,integration_id:n});return a?await t.update(a.id,i):t.create({...i,tenant_id:r,integration_id:n})}}}function me(e){let t=k(e,"corsair_entities");return{...t,findByEntityId:({accountId:r,entityType:n,entityId:i})=>t.findOne({account_id:r,entity_type:n,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:n,entityIds:i})=>i.length===0?[]:(p(e),await e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",n).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:n,limit:i,offset:a})=>t.findMany({where:{account_id:r,entity_type:n},limit:i,offset:a}),searchByEntityId:async({accountId:r,entityType:n,query:i,limit:a,offset:u})=>{p(e);let o=e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",n).where("entity_id","like",`%${i}%`);return typeof a=="number"&&(o=o.limit(a)),typeof u=="number"&&(o=o.offset(u)),await o.execute()},upsertByEntityId:async({accountId:r,entityType:n,entityId:i,version:a,data:u})=>{let o=await t.findOne({account_id:r,entity_type:n,entity_id:i});return o?await t.update(o.id,{version:a,data:u}):t.create({account_id:r,entity_type:n,entity_id:i,version:a,data:u})},deleteByEntityId:async({accountId:r,entityType:n,entityId:i})=>{p(e);let a=await e.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",n).where("entity_id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0}}}function we(e){let t=k(e,"corsair_events");return{...t,listByAccount:(r,n)=>t.findMany({where:{account_id:r},limit:n?.limit,offset:n?.offset}),listByStatus:(r,n)=>{let i={status:r};return n?.accountId&&(i.account_id=n.accountId),t.findMany({where:i,limit:n?.limit,offset:n?.offset})},listPending:r=>{let n={status:"pending"};return r?.accountId&&(n.account_id=r.accountId),t.findMany({where:n,limit:r?.limit??100})},updateStatus:(r,n)=>t.update(r,{status:n})}}function Q(e){return{integrations:pe(e),accounts:ge(e),entities:me(e),events:we(e)}}function he(e,t,r,n,i){let a=null;async function u(){if(a!==null)return a;p(e);let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t.integrationName).executeTakeFirst();if(!o)throw new Error(`Integration "${t.integrationName}" not found. Make sure to create the integration first.`);let y=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t.tenantId).where("integration_id","=",o.id).executeTakeFirst();if(!y)throw new Error(`Account not found for tenant "${t.tenantId}" and integration "${t.integrationName}". Make sure to create the account first.`);return a=y.id,a}return p(e),$(e.db,u,r,n,i)}function z(e){let{database:t,integrationName:r,schema:n,tenantId:i}=e,a=Q(t),u={tenantId:i,integrationName:r},o=null;async function y(){if(o!==null)return o;p(t);let c=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!c)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);let s=await t.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",i).where("integration_id","=",c.id).executeTakeFirst();if(!s)throw new Error(`Account not found for tenant "${i}" and integration "${r}". Make sure to create the account first.`);return o=s.id,o}let d={};for(let[c,s]of Object.entries(n.entities))d[c]=he(t,u,c,n.version,s);return{...d,$orm:a,$integrationName:r,$tenantId:i,$getAccountId:y}}function $e(e,t){let r=Q(e);return{$tenantId:t,$orm:r,listAccounts:n=>r.accounts.listByTenant(t,n),findAccountByIntegration:n=>r.accounts.findByTenantAndIntegration(t,n),listEntities:async n=>{p(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).execute();if(i.length===0)return[];let a=i.map(o=>o.id),u=e.db.selectFrom("corsair_entities").selectAll().where("account_id","in",a);return n?.entityType&&(u=u.where("entity_type","=",n.entityType)),typeof n?.limit=="number"&&(u=u.limit(n.limit)),typeof n?.offset=="number"&&(u=u.offset(n.offset)),await u.execute()},listEvents:async n=>{p(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).execute();if(i.length===0)return[];let a=i.map(o=>o.id),u=e.db.selectFrom("corsair_events").selectAll().where("account_id","in",a);return n?.status&&(u=u.where("status","=",n.status)),typeof n?.limit=="number"&&(u=u.limit(n.limit)),typeof n?.offset=="number"&&(u=u.offset(n.offset)),await u.execute()},forIntegration:n=>z({database:e,integrationName:n.integrationName,schema:n.schema,tenantId:t})}}function Me(e,t){return{forTenant:r=>z({database:e,integrationName:t.integrationName,schema:t.schema,tenantId:r})}}export{I as a,O as b,G as c,X as d,Y as e,L as f,R as g,V as h,ee as i,T as j,$ as k,le as l,Q as m,z as n,$e as o,Me as p};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import{a as ie,b as ft,c as T,d as F,e as yt,f as z,g as N,h as se,i as Le,j as ht,k as vn,l as mt,m as bt}from"./chunk-NZS35HPL.js";import{a as gt}from"./chunk-IGGCNGU2.js";import*as vr from"querystring";var je=["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"],kt={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 Ie(e){let n=kt[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}var Se="https://auth.corsair.dev";var Y=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret, deliveryUrl } to createCorsair()."),this.name="HubNotConfiguredError"}};function Ke(e){let n=(e.apiUrl?.trim()||Se).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 Sr(e){return e.apiUrl.trim().length>0&&e.deliveryUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function H(e){let n=T(e).hub;if(!n||!Sr(n))throw new Y;return n}function Ze(e){return e.oauthCallbackUrl?e.oauthCallbackUrl:`${e.apiUrl.replace(/\/$/,"")}/oauth/callback`}function U(e){return typeof e=="string"&&e.length>0}function wt(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!U(n.connectUrl)||!U(n.token)||!U(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 U(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Ct(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!U(n.approvalUrl)||!U(n.token)||!U(n.projectId)||!U(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 Pt(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(!U(n.access_token))throw new Error("Hub token refresh returned no access_token");return{access_token:n.access_token,refresh_token:U(n.refresh_token)?n.refresh_token:void 0,expires_in:typeof n.expires_in=="number"?n.expires_in:void 0,scope:U(n.scope)?n.scope:void 0}}function Tt(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}function _r(e){return e.replace(/\/$/,"")}async function Er(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 Or(e,n,t){if(n===404&&t)return t;let r=Tt(e);return r||`Hub API returned HTTP ${n}`}async function ke(e){let n=_r(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`},body:JSON.stringify(e.body)}),r=await Er(t);if(!t.ok)throw new Error(Or(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import*as _e from"crypto";function J(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function In(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 ae(e,n){let t=_e.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Dr=600*1e3;function qe(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),i=e.slice(t+1),o=_e.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(i,"base64url"),a=Buffer.from(o,"base64url");return s.length!==a.length||!_e.timingSafeEqual(s,a)?null:In(r,{maxAgeMs:Dr})}var Mr=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Ee(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Mr.has(n)}catch{return!1}}function we(e){return Ee(e)?"client":"server"}function At(e,n){return e==="client"||Ee(n)}function Ce(e){if(!e.source)return null;let n=Ee(e.deliveryUrl);return e.source==="server"&&n?{error:'source "server" cannot be used with a loopback delivery URL \u2014 omit source to auto-detect or use "client"',status:400}:e.oauthMode==="managed"&&e.source==="client"&&!n?{error:'managed OAuth with source "client" requires a loopback delivery URL \u2014 omit source for production server delivery',status:400}:null}import{ZodBoolean as Br,ZodDate as $r,ZodEnum as Fr,ZodNullable as Nr,ZodNumber as Ur,ZodObject as Wr,ZodOptional as Lr,ZodRecord as jr,ZodString as Kr,ZodType as Zr}from"zod";var Hr={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:{}}}},Sn=Hr;async function Rt(e,n){let t=[],r=g=>{t.push(g),console.log(g)},i=g=>{t.push(g),console.warn(g)},o=n?.caller??"script",s=ft(e);if(!s)throw new Error("setupCorsair: invalid corsair instance");if(!s.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let a=Gr(e,s.plugins,n),c={...s,database:s.database},d=c.database.db;await Vr(d,i);let l=await Yr(d,c,a.tenantId,a.provisionAccounts,r);n?.credentials&&Object.keys(n.credentials).length>0&&await eo(e,a,n.credentials,c,r,i);let u=await to(l,a,r,o);if(n?.backfill){r("[corsair:setup] Starting backfill...");let g=It({plugins:s.plugins,database:d,kek:s.kek,multiTenancy:!0}).withTenant(a.tenantId);await ro(g,s.plugins,u,r,i),r("[corsair:setup] Backfill complete.")}return t.join(`
|
|
2
|
+
`)}function _n(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...N[n][t],...r])}function qr(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let i=n.find(a=>a.id===t);if(!i)continue;let o=se(i);if(!o)continue;let s=_n(i,o,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function Gr(e,n,t){let r=yt(e),i=t?.tenantId?.trim(),o=i!==void 0&&i.length>0;if(r&&t?.backfill&&!o)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(r&&qr(t?.credentials,n)&&!o)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(o&&!i)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:r,tenantIdProvided:o,tenantId:o?i:"default",provisionAccounts:!r||o}}function vt(e,n){return ie(e)?n===0?!0:Object.values(e).every(t=>vt(t,n-1)):!1}function zr(e){return vt(e,4)}var Jr={...mt};function Ge(e){if(e instanceof Wr){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Zr?Ge(r):"unknown";return n}return e instanceof Nr?`${Ge(e.unwrap())} | null`:e instanceof Lr?`${Ge(e.unwrap())} | undefined`:e instanceof Fr?e.options.join(" | "):e instanceof Kr?"string":e instanceof Ur?"number":e instanceof Br?"boolean":e instanceof $r?"date":e instanceof jr?"jsonb":"unknown"}async function Vr(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(i=>i.name));for(let[i,o]of Object.entries(Jr))r.has(i)||n(`[corsair:setup] Table "${i}" does not exist. Run your database migrations before calling setupCorsair.
|
|
3
|
+
Schema: ${JSON.stringify(Ge(o),null,2)}`)}async function Yr(e,n,t,r,i){let o=new Date,s=new Map;for(let a of n.plugins){let c=a.id,d=se(a),l=await e.selectFrom("corsair_integrations").selectAll().where("name","=",c).executeTakeFirst();if(!l){let f=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:f,name:c,config:{},created_at:o,updated_at:o}).execute(),l=await e.selectFrom("corsair_integrations").selectAll().where("id","=",f).executeTakeFirst(),i(`[corsair:setup] Created integration: ${c}`)}let u=d?a.authConfig?.[d]?.integration??[]:[],g=d?a.authConfig?.[d]?.account??[]:[],y=d&&l?D({authType:d,integrationName:c,kek:n.kek,database:n.database,extraIntegrationFields:u}):void 0;if(l&&!l.dek&&y&&(await y.issue_new_dek(),i(`[corsair:setup] Issued integration DEK: ${c}`)),!l||!d||!y)continue;let p;if(r){let f=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",l.id).executeTakeFirst();if(!f){let h=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:h,tenant_id:t,integration_id:l.id,config:{},created_at:o,updated_at:o}).execute(),f=await e.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),i(`[corsair:setup] Created account: ${c}`)}p=f&&I({authType:d,integrationName:c,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:g}),f&&p&&!f.dek&&(await p.issue_new_dek(),i(`[corsair:setup] Issued account DEK: ${c}`))}s.set(c,{pluginId:c,authType:d,integration:y,account:p,integrationFields:[...N[d].integration,...u],accountFields:r?[...N[d].account,...g]:[]})}return s}function Qr(e){if(!ie(e))return;let n=e.keys;return ie(n)?n:void 0}function Xr(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function eo(e,n,t,r,i,o){let s=Qr(e),a=n.provisionAccounts?Xr(e,n.tenantId):void 0;for(let[c,d]of Object.entries(t)){let l=r.plugins.find(m=>m.id===c);if(!l){o(`[corsair:setup] Unknown plugin '${c}' \u2014 skipping credentials.`);continue}let u=se(l);if(!u){o(`[corsair:setup] Plugin '${c}' has no auth type \u2014 skipping credentials.`);continue}let g=_n(l,u,"integration"),y=_n(l,u,"account"),p=s?.[c],f=a?.[c],h=ie(f)?f.keys:void 0;for(let[m,C]of Object.entries(d))if(C){if(g.has(m)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${c}.${m}' is an integration-level credential shared across all tenants. You passed tenantId="${n.tenantId}", which only scopes account-level credentials. Run setup without --tenant if you intend to change this credential globally.`);let k=z(p,`set_${m}`);if(!k){o(`[corsair:setup] Cannot set integration field '${m}' for '${c}'.`);continue}await k(C),i(`[corsair:setup] Set ${c} integration.${m}`);continue}if(y.has(m)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${c}.${m}' on a multi-tenant instance`);let k=z(h,`set_${m}`);if(!k){o(`[corsair:setup] Cannot set account field '${m}' for '${c}'.`);continue}await k(C),i(`[corsair:setup] Set ${c} account.${m} (tenant=${n.tenantId})`);continue}o(`[corsair:setup] Unknown credential field '${m}' for plugin '${c}'.`)}}}var xt=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function no(e,n,t,r,i,o,s,a,c){let d=[],l=[];for(let g of i){if(xt.has(g))continue;let y=z(t,`get_${g}`);if(!y)continue;let p=null;try{let f=await y();p=typeof f=="string"?f:null}catch{}p||d.push(g)}if(r&&o.length>0)for(let g of o){if(xt.has(g))continue;let y=z(r,`get_${g}`);if(!y)continue;let p=null;try{let f=await y();p=typeof f=="string"?f:null}catch{}p||l.push(g)}let u=d.length===0&&l.length===0;if(u)a(`[corsair:setup] '${e}' (${n}) is configured \u2713`);else{let g=[...d,...l];if(c==="cli"){let y=g.map(p=>`${p}=VALUE`).join(" ");a(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
|
|
4
|
+
corsair setup --${e} ${y}`)}else{let y=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let p of d)y.push(` await corsair.keys.${e}.set_${p}(value)`);for(let p of l){let f=s.provisionAccounts?s.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(s.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;y.push(` await ${f}.keys.set_${p}(value)`)}a(y.join(`
|
|
5
|
+
`))}}return u}async function to(e,n,t,r){let i=new Set;for(let o of e.values())await no(o.pluginId,o.authType,o.integration,o.account,o.integrationFields,o.accountFields,n,t,r)&&i.add(o.pluginId);return i}async function ro(e,n,t,r,i){if(!zr(Sn)){i("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let o=Sn,s=new Set(n.map(a=>a.id));for(let[a,c]of Object.entries(o)){if(!s.has(a))continue;if(!t.has(a)){r(`[corsair:setup] Skipping backfill for '${a}' \u2014 auth not configured.`);continue}let d=ie(e)?e[a]:void 0,l=ie(d)?d.api:void 0;if(l)for(let[u,g]of Object.entries(c))for(let[y,p]of Object.entries(g)){r(`[corsair:setup] Backfilling ${a} \u203A ${u}.${y}...`);try{let f=ie(l)?l[u]:void 0;await z(f,y)?.(p)}catch(f){i(`[corsair:setup] ${a} \u203A ${u}.${y} failed: `+(f instanceof Error?f.message:String(f)))}}}}async function Pe(e,n){if(!T(e).database)throw new Error("A database must be configured to provision Corsair for connect");await Rt(e,{tenantId:n})}var oo=new Set(["webhook_signature","expires_at","scope"]);function io(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function so(e){return e==="oauth_2"||e==="managed"?["access_token"]:e==="api_key"?["api_key"]:e==="bot_token"?["bot_token"]:[]}async function ao(e,n,t,r){let i=so(t);if(i.length===0)return!0;let s=(typeof e.withTenant=="function"?e.withTenant(r):e)[n.id],a=s&&typeof s=="object"&&"keys"in s?s.keys:null;if(!a)return!1;for(let c of i){if((t==="oauth_2"||t==="managed")&&c==="refresh_token")continue;let d=z(a,`get_${c}`);if(!d)continue;let l=null;try{let u=await d();l=typeof u=="string"?u:null}catch{l=null}if(!l)return!1}return!0}function co(e,n){return e==="oauth_2"||e==="managed"?[]:n.filter(t=>!oo.has(t))}async function ze(e,n,t={}){let r=T(e),i=H(e),o=Ze(i),s=[],a=t.pluginIds?new Set(t.pluginIds):null;for(let c of r.plugins){if(a&&!a.has(c.id))continue;let d=se(c);if(!d)continue;let l=io(d),u=t.providerNameOverrides?.[c.id]??Ie(c.id),g=await ao(e,c,d,n),y=Le(c,d),p={plugin:c.id,providerName:u,authKind:l,alreadyConfigured:g};if(l==="oauth"){let h=t.oauthModeOverrides?.[c.id]??(d==="managed"?"managed":"byo");if(p.oauthMode=h,!t.skipOAuthUrlGeneration)if(h==="managed")p.state=ae(J(c.id,n),r.kek);else try{let m=await En(e,c.id,{tenantId:n,redirectUri:o});p.oauthUrl=m.url,p.state=m.state}catch(m){p.setupError=m instanceof Error?m.message:`Could not prepare OAuth for ${c.id}`}}else{let f=co(d,y);f.length>0&&(p.credentialFields=f)}s.push(p)}return s}function St(e,n){let t=H(e);if(n){let r=Ce({source:n,deliveryUrl:t.deliveryUrl});if(r)throw new Error(r.error);return n}return we(t.deliveryUrl)}async function _t(e,n){await Pe(e,n)}async function Je(e,n){let t=H(e);await _t(e,n.tenantId);let r=n.plugin?[n.plugin]:void 0,i=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,o=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,s=await ze(e,n.tenantId,{pluginIds:r,oauthModeOverrides:i,providerNameOverrides:o});if(s.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");let a=St(e,n.source);return ke({hub:t,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:{tenantId:n.tenantId,deliveryUrl:t.deliveryUrl,source:a,plugins:s},parseResponse:wt})}function uo(e){if(e==="byo"||e==="managed")return e}function lo(e){if(e==="client"||e==="server")return e}function On(e){let n=e.plugin?.trim(),t=e.tenantId?.trim()||"default",r=lo(e.source),i=uo(e.oauthMode),o=e.providerName?.trim();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={tenantId:t,oauthMode:i};return n&&(s.plugin=n),r&&(s.source=r),o&&(s.providerName=o),s}function Dn(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 po(e){return{ok:!0,connectUrl:e.connectUrl,token:e.token,projectId:e.projectId,expiresAt:e.expiresAt}}async function go(e,n,t){if(t?.resolveTenantId){let r=await t.resolveTenantId(e);return r?.trim()?r.trim():{error:"Unauthorized",status:401}}return t?.allowClientProvidedTenantId&&n.tenantId?.trim()?n.tenantId.trim():t?.defaultTenantId?.trim()||"default"}async function Mn(e,n,t){let i=n.method.toUpperCase()==="GET"?Dn(n.url):await n.json().catch(()=>null);if(!i)return{error:"Invalid JSON body",status:400};let o=await go(n,i,t);if(typeof o!="string")return o;let s=On({...i,tenantId:o});if("error"in s)return s;let a=H(e);if(s.source){let l=Ce({source:s.source,deliveryUrl:a.deliveryUrl,oauthMode:s.oauthMode});if(l)return l}let c={...s,source:s.source??we(a.deliveryUrl)},d=await Je(e,c);return po(d)}async function Hn(e,n,t){try{let r=await Mn(e,n,t);return"error"in r?Response.json({error:r.error},{status:r.status}):Response.json(r)}catch(r){if(r instanceof Y)return Response.json({error:r.message},{status:503});let i=r instanceof Error?r.message:String(r);return Response.json({error:i},{status:500})}}async function Ve(e,n,t){let r=n.method.toUpperCase();return r!=="GET"&&r!=="POST"?Response.json({error:"Method not allowed"},{status:405}):Hn(e,n,t)}async function Oe(e,n,t={}){let r=await ze(e,n,{...t,skipOAuthUrlGeneration:!0});return{tenantId:n,plugins:r.map(i=>({plugin:i.plugin,providerName:i.providerName,authKind:i.authKind,connected:i.alreadyConfigured??!1}))}}var V=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function Ye(e,n){let t=T(e,()=>new V("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new V("no_database","Database not configured");let r=F(t,n.plugin,l=>new V("plugin_not_found",l)),i=se(r);if(!i)throw new V("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(i==="oauth_2"||i==="managed")throw new V("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await Pe(e,n.tenantId);let o=new Set(Le(r,i)),a=r.authConfig?.[i]?.account??[],c=I({authType:i,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),d=0;for(let[l,u]of Object.entries(n.credentials)){if(!u.trim())continue;if(!o.has(l))throw new V("invalid_credentials",`Unknown credential field '${l}' for plugin '${n.plugin}'`);let g=z(c,`set_${l}`);if(!g)throw new V("invalid_credentials",`Cannot set credential field '${l}' for plugin '${n.plugin}'`);await g(u.trim()),d+=1}if(d===0)throw new V("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var Qe=new Map;function fo(e){for(let[n,t]of Qe)t<=e&&Qe.delete(n)}function Xe(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return fo(r),Qe.has(t)?{ok:!1,error:"Delivery request already consumed"}:(Qe.set(t,r+n),{ok:!0})}async function en(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 Et,createDecipheriv as Ot,randomBytes as nn,scrypt as yo}from"crypto";import{promisify as ho}from"util";var Dt=ho(yo),tn="aes-256-gcm",Mt=12,rn=16,mo=16,De=32;function Q(){return nn(De).toString("base64")}async function X(e,n){let t=nn(mo),r=await Dt(n,t,De),i=nn(Mt),o=Et(tn,r,i,{authTagLength:rn}),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 W(e,n){let[t,r,i,o]=e.split(":");if(!t||!r||!i||!o)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(i,"base64"),d=Buffer.from(o,"base64"),l=await Dt(n,s,De),u=Ot(tn,l,a,{authTagLength:rn});return u.setAuthTag(c),Buffer.concat([u.update(d),u.final()]).toString("utf8")}function Bn(e,n){let t=Buffer.from(n,"base64"),r=nn(Mt),i=Et(tn,t,r,{authTagLength:rn}),o=Buffer.concat([i.update(e,"utf8"),i.final()]),s=i.getAuthTag();return[r.toString("base64"),s.toString("base64"),o.toString("base64")].join(":")}function Me(e,n){let[t,r,i]=e.split(":");if(!t||!r||!i)throw new Error("Invalid encrypted data format");let o=Buffer.from(n,"base64"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(i,"base64"),d=Ot(tn,o,s,{authTagLength:rn});return d.setAuthTag(a),Buffer.concat([d.update(c),d.final()]).toString("utf8")}function ce(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=Bn(i,n);return t}function ee(e,n){let t={};for(let[r,i]of Object.entries(e))t[r]=Me(i,n);return t}function He(e,n,t){let r=ee(e,n);return ce(r,t)}function Ht(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 $n=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function D(e){let{authType:n,integrationName:t,kek:r,database:i,extraIntegrationFields:o=[]}=e,s=[...N[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:$n(p.config),dek:p.dek??null},a},updateIntegration:async p=>{let f=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","=",f.id).execute(),a=null}},d=null,l=async()=>{if(d)return d;let p=await c.getIntegration();if(!p.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return d=await W(p.dek,r),d},u=async()=>{let p=await c.getIntegration(),f=await l(),h=p.config;return!h||Object.keys(h).length===0?{}:ee(h,f)};return{get_dek:l,issue_new_dek:async()=>{let p=await c.getIntegration(),f=Q(),h={};if(p.dek){let C=await W(p.dek,r),k=p.config;k&&Object.keys(k).length>0&&(h=He(k,C,f))}let m=await X(f,r);return await c.updateIntegration({config:h,dek:m}),d=f,f},...Ht(u,async p=>{let f=await l(),h;try{h=await u()}catch(k){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,k),h={}}let m={...h};for(let[k,b]of Object.entries(p))b===null?delete m[k]:m[k]=b;let C=ce(m,f);await c.updateIntegration({config:C})},s)}}function I(e){let{authType:n,integrationName:t,tenantId:r,kek:i,database:o,extraAccountFields:s=[]}=e,a=[...N[n].account,...s],c=null,d=null,l=async()=>{if(d)return d;let b=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!b)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return d={id:b.id,config:$n(b.config),dek:b.dek??null},d},u={kek:i,integrationName:t,tenantId:r,getIntegration:l,getAccount:async()=>{if(c)return c;let b=await l(),w=await o.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",b.id).executeTakeFirst();if(!w)throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`);return c={id:w.id,config:$n(w.config),dek:w.dek??null},c},updateAccount:async b=>{let w=await u.getAccount();await o.db.updateTable("corsair_accounts").set({...b.config!==void 0?{config:b.config}:{},...b.dek!==void 0?{dek:b.dek}:{},updated_at:new Date}).where("id","=",w.id).execute(),c=null}},g=null,y=null,p=async()=>{if(g)return g;let b=await u.getAccount();if(!b.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await W(b.dek,i),g},f=async()=>{if(y)return y;let b=await u.getIntegration();if(!b.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return y=await W(b.dek,i),y},h=async()=>{let b=await u.getAccount(),w=await p(),P=b.config;return!P||Object.keys(P).length===0?{}:ee(P,w)},m=async()=>{let b=await u.getIntegration(),w=await f(),P=b.config;return!P||Object.keys(P).length===0?{}:ee(P,w)},k={get_dek:p,issue_new_dek:async()=>{let b=await u.getAccount(),w=Q(),P={};if(b.dek){let _=await W(b.dek,i),E=b.config;E&&Object.keys(E).length>0&&(P=He(E,_,w))}let S=await X(w,i);return await u.updateAccount({config:P,dek:S}),g=w,w},...Ht(h,async b=>{let w=await p(),P;try{P=await h()}catch(E){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,E),P={}}let S={...P};for(let[E,A]of Object.entries(b))A===null?delete S[E]:S[E]=A;let _=ce(S,w);await u.updateAccount({config:_})},a)};return n==="oauth_2"&&(k.get_integration_credentials=async()=>{let b=await m();return{client_id:b.client_id||null,client_secret:b.client_secret||null,redirect_url:b.redirect_url??null}}),k}async function Bt(e,n,t){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!r)throw new Error(`Integration "${n}" not found.`);let i=Q(),o=await X(i,t);return await e.db.updateTable("corsair_integrations").set({dek:o,updated_at:new Date}).where("id","=",r.id).execute(),i}async function $t(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=Q(),a=await X(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",o.id).execute(),s}var Ft=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function bo(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 ko(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 W(n.dek,e.kek),r=Ft(n.config),i={};Object.keys(r).length>0&&(i=ee(r,t)),i[e.link.linkType]=e.link.externalId;let o=ce(i,t);await e.database.db.updateTable("corsair_accounts").set({config:o,updated_at:new Date}).where("id","=",n.id).execute()}async function Te(e){let{database:n,kek:t,pluginId:r,tenantId:i,link:o,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await bo({database:n,pluginId:r,tenantId:i}),d=!1;if(s){let l=I({authType:s,integrationName:r,tenantId:i,kek:t,database:n,extraAccountFields:a}),u=`set_${o.linkType}`,g=l[u];typeof g=="function"&&(await g(o.externalId),d=!0)}d||await ko({database:n,kek:t,accountId:c,link:o})}async function Fn(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 W(a.dek,t),l=Ft(a.config)[i];if(!l)continue;if(Me(l,c)===o)return a}catch{continue}return null}async function on(e){return(await Fn(e))?.tenant_id??null}async function Nt(e){return on({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}var ue=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Ae(e,n){let{plugin:t,tenantId:r,accessToken:i,refreshToken:o,expiresIn:s,scope:a}=n;if(!i.trim())throw new ue("no_access_token","Managed OAuth delivery missing access_token");let c=T(e,()=>new ue("invalid_corsair_instance","Invalid corsair instance"));if(!c.database)throw new ue("no_database","No database configured on corsair instance");let d=F(c,t,u=>new ue("plugin_not_found",u));await Pe(e,r);let l=I({authType:"managed",integrationName:t,tenantId:r,kek:c.kek,database:c.database});await l.set_access_token(i),o&&await l.set_refresh_token(o),s&&await l.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await l.set_scope(a);try{let u=await en(c.plugins,t,{access_token:i,refresh_token:o,scope:a});if(u)try{let g=d.authConfig?.managed?.account??[];await Te({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 wo(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Ut(e,n,t=[]){for(let[r,i]of Object.entries(e))if(wo(i)){if(i.match(n))return{webhook:i,path:[...t,r]}}else if(i&&typeof i=="object"){let o=Ut(i,n,[...t,r]);if(o)return o}return null}function Co(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Po(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 Wt(e,n,t,r){let i=Co(n),o=typeof t=="string"?JSON.parse(t):t;(!o||typeof o=="object"&&Object.keys(o).length===0)&&i["x-goog-resource-uri"]&&(o=Po(i)||o);let a={headers:i,body:o,...r?{query:r}:{}},c=r?.tenantId||"default",d=e.withTenant?e.withTenant(c):e,l=je;for(let u of l){let g=d[u];if(!g||!g.webhooks||g.pluginWebhookMatcher&&!g.pluginWebhookMatcher(a))continue;let y=Ut(g.webhooks,a);if(!y)continue;let p=y.path.join("."),f={payload:o,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let h=await y.webhook.handler(f),m=!!Object.keys(h.returnToSender||{})?.length;return{plugin:u,action:p,body:o,response:m?{...h?.returnToSender,success:!0}:{success:!0},...h.responseHeaders&&{responseHeaders:h.responseHeaders}}}catch(h){return console.error(`Error executing webhook handler for ${u}.${p}:`,h),{plugin:u,action:p,body:o,response:{success:!1,error:h instanceof Error?h.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHmac as To,timingSafeEqual as Ao}from"crypto";var xo=300*1e3;function Ro(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function Nn(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=Ro(e.signatureHeader);if(!t)return{ok:!1,error:"Invalid tunnel signature"};let r=Number(e.timestampHeader);if(!Number.isFinite(r))return{ok:!1,error:"Invalid or missing tunnel timestamp"};if(Math.abs(Date.now()-r*1e3)>xo)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let o=To("sha256",n).update(e.body).digest("hex");try{if(!Ao(Buffer.from(o,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}import{createHmac as vo,timingSafeEqual as Io}from"crypto";function ge(e){return e.deliveryMode==="connect.status"}function fe(e){return e.deliveryMode==="auth.credentials"}function Be(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function $e(e){return e.deliveryMode==="oauth.tokens"}function sn(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!ge(e)&&!fe(e)&&!Be(e)&&!$e(e)}function jt(e){let n=e.trim();return n.length>0?n:null}function So(e,n){let t=jt(n);if(!t)throw new Error("Signing secret is required for browser delivery tokens");return vo("sha256",t).update(e).digest("base64url")}function an(e,n){let t=jt(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=So(i,t);try{if(!Io(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 Un(e,n){if(e instanceof Headers)return e.get(n)??void 0;let t=e[n]??e[n.toLowerCase()];return Array.isArray(t)?t[0]:typeof t=="string"?t:void 0}async function Eo(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 on({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Oo(e,n,t){let r=await Eo(e,n,t),i={...t.query??{},...r?{tenantId:r}:{}},o=await Wt(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 Do(e,n){return await Fe(e,n),{status:"ok"}}async function Mo(e,n){return await Ae(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function Ln(e,n,t){let r=await Wn(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function Wn(e,n,t){let r=T(e),i=n.token?.trim();if(!i)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let o=new Date().toISOString(),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 Ho(e,n){try{return await Ye(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function Bo(e,n){let t=n.tenantId?.trim()||"default";try{return{status:"ok",webhookResponse:{status:200,body:await Oe(e,t,{pluginIds:n.plugins})}}}catch(r){return{status:"failed",retryable:!1,error:r instanceof Error?r.message:"Connect status introspection failed"}}}async function jn(e,n,t={}){let r=T(e),i=Un(n.headers,"x-corsair-signature"),o=Un(n.headers,"x-corsair-timestamp"),s=Un(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let c=Nn({body:n.body,signatureHeader:i,timestampHeader:o,signingSecret:t.signingSecret});if(!c.ok)return{status:"failed",retryable:!1,error:c.error};if(!s?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let d=Xe(`nonce:${s.trim()}`,3e5);if(!d.ok)return{status:"failed",retryable:!1,error:d.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let a;try{a=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}switch(a.type){case"webhook":return Oo(e,r,a.payload);case"oauth.callback":return Do(e,a.payload);case"oauth.tokens":return Mo(e,a.payload);case"permission.approve":return Wn(e,a.payload,"approved");case"permission.deny":return Wn(e,a.payload,"denied");case"auth.credentials":return Ho(e,a.payload);case"connect.status":return Bo(e,a.payload);default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${a.type}`}}}var $o="corsair:client-bridge";function Kt(e){let n=JSON.stringify({type:$o,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(e.hubOrigin);return`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><script>
|
|
6
|
+
(function () {
|
|
7
|
+
var message = ${n};
|
|
8
|
+
var targetOrigin = ${t};
|
|
9
|
+
if (window.parent && window.parent !== window) {
|
|
10
|
+
window.parent.postMessage(message, targetOrigin);
|
|
11
|
+
}
|
|
12
|
+
})();
|
|
13
|
+
</script></body></html>`}var Fo=[".corsair.dev"];function No(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Uo(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:No(n)?!0:Fo.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Zt(e){return!e||!Uo(e)?null:{"Access-Control-Allow-Origin":e,"Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"content-type, x-corsair-signature, x-corsair-timestamp, x-corsair-project, x-corsair-nonce, access-control-request-private-network","Access-Control-Allow-Private-Network":"true","Access-Control-Max-Age":"0",Vary:"Origin"}}function qt(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,i]of Object.entries(n))t.set(r,i);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function cn(e,n){let t=new URL(e);return n.error?(t.searchParams.set("error",n.error),t.toString()):n.connectedPlugin?(t.searchParams.set("connected",n.connectedPlugin),t.toString()):(n.status!==void 0&&t.searchParams.set("status",Buffer.from(JSON.stringify(n.status)).toString("base64url")),t.toString())}async function Kn(e,n){let t=H(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=an(i,t.signingSecret);if(!o)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=Xe(`browser:${o.jti}`,6e4);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(ge(o)){if(!o.hubSuccessUrl)return{type:"json",status:400,body:{error:"Connect status delivery missing hubSuccessUrl"}};let a=o.tenantId?.trim()||"default",c=await Oe(e,a,{pluginIds:o.statusPlugins});return{type:"redirect",url:cn(o.hubSuccessUrl,{status:c})}}if(fe(o))return o.hubSuccessUrl?o.credentials?(await Ye(e,{plugin:o.plugin,tenantId:o.tenantId,credentials:o.credentials}),{type:"redirect",url:cn(o.hubSuccessUrl,{connectedPlugin:o.plugin})}):{type:"redirect",url:cn(o.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(Be(o)){if(!o.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await Ln(e,o.permissionToken,o.deliveryMode==="permission.approve"?"approved":"denied")}else if($e(o)){if(!o.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Ae(e,{plugin:o.plugin,tenantId:o.tenantId,accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn,scope:o.scope})}else{if(!sn(o)||!o.code||!o.state||!o.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await Fe(e,{code:o.code,state:o.state,redirectUri:o.redirectUri})}}catch(a){let c=a instanceof Error?a.message:"Hub delivery failed";return(ge(o)||fe(o))&&o.hubSuccessUrl?{type:"redirect",url:cn(o.hubSuccessUrl,{error:c})}:(ge(o)||fe(o))&&o.hubOrigin&&o.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Kt({hubOrigin:o.hubOrigin,requestId:o.requestId,ok:!1,error:c})}:{type:"json",status:400,body:{error:c}}}return{type:"redirect",url:o.hubSuccessUrl}}async function Zn(e,n){let t=H(e),r=await jn(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 qn(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 Gn(e,n){return n.method==="GET"?Kn(e,n.url):Zn(e,{headers:n.headers,body:n.body??""})}async function zn(e,n){try{let t=await Gn(e,n);return qn(t)}catch(t){if(t instanceof Y)return Response.json({error:t.message},{status:503});throw t}}async function Ne(e,n){let t=n.method.toUpperCase(),r=Zt(n.headers.get("origin"));if(t==="OPTIONS")return r?new Response(null,{status:204,headers:r}):Response.json({error:"Method not allowed"},{status:405});if(t!=="GET"&&t!=="POST")return Response.json({error:"Method not allowed"},{status:405});let i=await zn(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return qt(i,r)}var ne=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 Wo=300;async function Jn(e,n){let{keys:t,hub:r,plugin:i,tenantId:o}=e,s=n?.forceRefresh??!1,[a,c,d]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!d)throw new ne(i,"managed");let l=Math.floor(Date.now()/1e3);if(!s&&a&&c&&Number(c)>l+Wo)return{accessToken:a,expiresAt:Number(c),refreshed:!1};if(!d&&a&&!s)return{accessToken:a,expiresAt:c?Number(c):l+3600,refreshed:!1};let u=await ke({hub:r,path:"/oauth/refresh",body:{plugin:i,tenantId:o},parseResponse:Pt}),g=u.expires_in?l+u.expires_in:c?Number(c):l+3600;return await t.set_access_token(u.access_token),await t.set_expires_at(String(g)),u.refresh_token&&await t.set_refresh_token(u.refresh_token),u.scope&&await t.set_scope(u.scope),{accessToken:u.access_token,expiresAt:g,refreshed:!0}}async function Gt(e,n){e._refreshAuth=async()=>(await Jn(n,{forceRefresh:!0})).accessToken}async function Vn(e,n){return ke({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:{permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,deliveryUrl:e.deliveryUrl,expiresAt:n.expiresAt},parseResponse:Ct})}function Yn(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}function zt(e,n){return{delivery:t=>Ne(e,t),deliveryOptions:t=>Ne(e,t),createConnectSession:t=>Ve(e,t,n)}}function un(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.
|
|
14
|
+
|
|
15
|
+
To generate a KEK, run: openssl rand -base64 ${De}`)}})}var Lo=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Jt(e,n,t,r,i){let o={pluginId:n,operation:t,input:r,originalError:e},s=Object.keys(i).find(d=>i[d]?.match(e,o));return await(i[s||"DEFAULT"]?.handler||Lo)(e,o)}import{randomBytes as jo}from"crypto";import{v4 as Ko}from"uuid";var Zo={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 qo(e,n,t){return t!==void 0?t:Zo[n][e]}function Qn(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 Yt(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 Vt(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 Qt(e){let n=qo(e.riskLevel,e.mode,e.override);if(n==="allow")return{result:"allow"};let t=e.meta?.irreversible?" (irreversible)":"",r=e.meta?.description?`${e.meta.description}${t}`:`${e.pluginId}.${e.endpointPath}${t}`;if(n==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
|
|
16
|
+
Action: ${r}`,`
|
|
17
|
+
To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let i=JSON.stringify(e.args),o=new Date().toISOString(),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,f=a.id;return{result:"allow",onComplete:async()=>{await p.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",f).execute()}}}return a.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
|
|
18
|
+
Action: ${r}`,`
|
|
19
|
+
Permission ID: ${a.id}`,`
|
|
20
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Vt(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let c=Ko(),d=jo(32).toString("hex"),l=e.timeoutMs??600*1e3,u=new Date(Date.now()+l).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:c,created_at:new Date,updated_at:new Date,token:d,plugin:e.pluginId,endpoint:e.endpointPath,args:i,tenant_id:s,status:"pending",expires_at:u}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
|
|
21
|
+
Action: ${r}`,`
|
|
22
|
+
Permission ID: ${c}`,`
|
|
23
|
+
Permission token: ${d}`,`
|
|
24
|
+
Expires at: ${u}`,`
|
|
25
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Vt(e.db,c,l):{result:"blocked",reason:"pending",id:c,token:d,expiresAt:u}}function Go(e){return typeof e=="function"}function zo(e,n,t){let r=ae(J(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 Xn({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:i,errorHandlers:o,currentPath:s=[],keyBuilder:a,permissionsConfig:c,endpointMeta:d,database:l,approvalConfig:u,tenantId:g,connectConfig:y,hubConfig:p}){for(let[f,h]of Object.entries(e)){let m=n?.[f];if(Go(h)){let C=m,k=[...s,f].join("."),b=async(w={})=>{let P;if(c){let v=d?.[k],{result:be,reason:q,onComplete:ve,token:G,id:oe,expiresAt:$}=await Qt({pluginId:i,endpointPath:k,args:w,mode:c.mode,override:c.overrides?.[k],riskLevel:v?.riskLevel??"write",meta:v,db:l,timeoutMs:u?Qn(u.timeout):void 0,tenantId:g,approvalMode:u?.mode});if(be==="blocked"){let O;if(q==="denied")O=`Action '${k}' was denied by the user. Await further instructions before proceeding.`;else if(q==="policy")O=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`;else if(q==="timeout")O=`Action '${k}' timed out waiting for approval.`;else if(G&&oe)if(u?.formatAsyncMessage)O=u.formatAsyncMessage({token:G,id:oe,plugin:i,endpoint:k,args:w});else if(p)try{let pe=u?Qn(u.timeout):6e5,Rn=await Vn(p,{permissionId:oe,permissionToken:G,plugin:i,endpoint:k,args:w,tenantId:g??"default",expiresAt:$??new Date(Date.now()+pe).toISOString()});O=Yn(Rn.approvalUrl)}catch(pe){let Rn=pe instanceof Error?pe.message:String(pe);O=`Action '${k}' requires user approval before it can run. Could not create approval link: ${Rn}`}else O=`Action '${k}' requires user approval before it can run.`;else O=`Action '${k}' requires user approval before it can run.`;throw new Error(O)}P=ve}let S=async(v,be,q)=>{try{return await h(be,q)}catch(ve){if(ve instanceof Error){let G=await Jt(ve,i,k,typeof q=="object"&&q!==null?q:{args:q},o);if(v<(G.maxRetries||0)){let oe=v+1;console.log(`Retrying (${oe} / ${G.maxRetries})...`);let $;if(G.headersRetryAfterMs)$=G.headersRetryAfterMs;else switch(G.retryStrategy){case"exponential_backoff":$=Math.pow(2,oe-1)*1e3;break;case"exponential_backoff_jitter":let O=Math.pow(2,oe-1)*1e3,pe=(Math.random()-.5)*1e3;$=Math.max(0,O+pe);break;case"linear_1s":$=1e3;break;case"linear_2s":$=2e3;break;case"linear_3s":$=3e3;break;case"linear_4s":$=4e3;break;default:$=1e3;break}await new Promise(O=>setTimeout(O,$)),await S(oe,be,q),console.log(`[corsair:${i}:${k}] Retry strategy:`,G)}}throw ve}},_;try{_=a?await a(t,"endpoint"):void 0}catch(v){throw y?.oauthConfig&&y.kek&&v instanceof ne&&v.authType==="oauth_2"?zo(i,y,g):v}if(!C?.before&&!C?.after){let v=await S(0,{...t,key:_},w);return await P?.(),v}let E={...t,key:_},A=C.before?await C.before(E,w):{ctx:E,args:w,continue:!0,passToAfter:void 0};if(A.continue===!1)return;let me=await S(0,A.ctx,A.args);return await C.after?.(A.ctx,me,A.passToAfter),await P?.(),me};r[f]=b}else if(h&&typeof h=="object"){let C={};Xn({endpoints:h,hooks:m,ctx:t,tree:C,pluginId:i,errorHandlers:o,currentPath:[...s,f],keyBuilder:a,permissionsConfig:c,endpointMeta:d,database:l,approvalConfig:u,tenantId:g,connectConfig:y,hubConfig:p}),r[f]=C}}}function Jo(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function et({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:i}){for(let[o,s]of Object.entries(e)){let a=n?.[o];if(Jo(s)){let c=a,d=async l=>{let u=(y,p)=>s.handler(y,p),g=i?await i(t,"webhook"):void 0;return!c?.before&&!c?.after?u({...t,key:g},l):(async()=>{let y={...t,key:g},p=c.before?await c.before(y,l):{ctx:y,args:l,continue:!0,passToAfter:void 0};if(p.continue===!1)return;let f=await u(p.ctx,p.args);return f?.success===!0&&await c.after?.(p.ctx,f,p.passToAfter),f})()};r[o]={match:s.match,handler:d}}else if(s&&typeof s=="object"){let c={};et({webhooks:s,hooks:a,ctx:t,webhooksTree:c,keyBuilder:i}),r[o]=c}}}function Vo(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 Yo(e,n,t,r,i){return e?vn(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 nt(e,n){let{database:t,tenantId:r,kek:i,rootErrorHandlers:o,approvalConfig:s,connectConfig:a,hubConfig:c}=n,d={},l={};for(let u of e)d[u.id]={},l[u.id]={};for(let u of e){let g=u.schema,y=r??"default",p=Vo(t,u.id,y);if(g?.entities){let A={};for(let[me,v]of Object.entries(g.entities)){let be=t?vn(t.db,p,me,g.version,v):Yo(void 0,p,me,g.version,v);A[me]=be}l[u.id].db=A,d[u.id].db=A}let f=u.options,h=u.authConfig,m;if(t&&i&&f?.authType){let A=h?.[f.authType]?.account??[];m=I({authType:f.authType,integrationName:u.id,tenantId:y,kek:i,database:t,extraAccountFields:A}),d[u.id].keys=m}let C={database:t,db:l[u.id]?.db??{},$getAccountId:p,...u.options?{options:u.options}:{},...m?{keys:m,authType:f?.authType}:{},tenantId:y,...c?{hub:c}:{}},k=u.endpoints??{},b=u.hooks,w={...o,...u.errorHandlers},P={},S=u.options?.permissions;Xn({endpoints:k,hooks:b,ctx:C,tree:P,pluginId:u.id,errorHandlers:w,currentPath:[],keyBuilder:u.keyBuilder,permissionsConfig:S,endpointMeta:u.endpointMeta,database:t,approvalConfig:s,tenantId:r,connectConfig:a?{...a,oauthConfig:u.oauthConfig,kek:i,tenantId:y}:void 0,hubConfig:c}),Object.keys(P).length>0&&(d[u.id].api=P),C.endpoints=P;let _=u.webhooks??{},E=u.webhookHooks;if(Object.keys(_).length>0){let A={};et({webhooks:_,hooks:E,ctx:C,webhooksTree:A,keyBuilder:u.keyBuilder}),d[u.id].webhooks=A,u.pluginWebhookMatcher&&(d[u.id].pluginWebhookMatcher=u.pluginWebhookMatcher),u.pluginTenantWebhookMatcher&&(d[u.id].pluginTenantWebhookMatcher=u.pluginTenantWebhookMatcher)}}return d}function Xt(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=D({authType:o.authType,integrationName:i.id,kek:t,database:n,extraIntegrationFields:a});r[i.id]=c}}return r}import*as er from"querystring";var L=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Qo(e){let n=e.oauthConfig;if(!n)throw new L("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function tt(e,n){let t=T(e,()=>new L("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new L("no_database","No database configured on corsair instance");let r=t.connect?.redirectUri;if(!r)throw new L("no_redirect_uri","No redirectUri configured. Set connect.redirectUri in createCorsair().");let i=qe(n,t.kek);if(!i)throw new L("invalid_state","Invalid or tampered state parameter");let{plugin:o,tenantId:s}=i,a=F(t,o,y=>new L("plugin_not_found",y)),c=Qo(a),l=await D({authType:"oauth_2",integrationName:o,kek:t.kek,database:t.database}).get_client_id();if(!l)throw new L("client_id_not_configured",`client_id not configured for '${o}'`);let u={...c.authParams,client_id:l,redirect_uri:r,response_type:"code",scope:c.scopes.join(" "),state:n},g=`${c.authUrl}?${er.stringify(u)}`;return{plugin:o,tenantId:s,providerName:c.providerName,oauthUrl:g,state:n}}var x=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 nr(e){let n={error:e.code,message:e.message,...e.extra};return R(e.status,n)}function de(e){return new x(404,"not_found",e)}function te(e,n={}){return new x(400,"bad_request",e,n)}function tr(e,n){return F(e,n,t=>de(t))}async function rt(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=D({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),i=N[t].integration,o=r,s;try{s=await Promise.all(i.map(d=>o[`get_${d}`]()))}catch{s=i.map(()=>null)}let a=i.filter((d,l)=>s[l]==null),c;return t==="oauth_2"?c=!a.includes("client_id")&&!a.includes("client_secret"):c=a.length===0,{configured:c,missingFields:a}}async function rr(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:i,missingFields:o}=await rt(e,n);return{id:e.id,authType:t,configured:i,missingFields:o,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function dn(){return{ok:!0}}async function ln(e){return Promise.all(e.plugins.map(n=>rr(n,e)))}async function pn(e,n){let t=tr(e,n);return rr(t,e)}async function or(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 ir(e,n){let t=await or(e,n),r=t.filter(i=>i.hasCredentials).map(i=>i.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function gn(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 fn(e,n){if(!n)throw te("Tenant id must be a non-empty string");return ir(e,n)}async function yn(e,n){let t=n?.id?.trim();if(!t)throw te("Tenant id is required",{missingFields:["id"]});return ir(e,t)}async function hn(e,n){let t=n?.trim()||"default",r={},i=e.database?await or(e,t):[],o=new Map(i.map(s=>[s.integrationName,s]));for(let s of e.plugins){if(!(await rt(s,e)).configured){r[s.id]="missing_credentials";continue}let c=o.get(s.id),d;c&&c.hasCredentials?d="connected":d="not_connected",r[s.id]=d}return r}async function mn(e,n){if(!e.database)throw de(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw de(`Permission '${n}' not found`);return t}function Xo(e){if(!e.oauthConfig)throw te(`Plugin '${e.id}' has no oauthConfig`)}function ot(e){if(!e.connect)throw new x(500,"connect_not_configured","createCorsair was not given a connect config. Set { connect: { baseUrl, redirectUri } } to enable /connect routes.");return e.connect}async function bn(e,n){let t=n?.plugin?.trim();if(!t)throw te("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",i=tr(e,t);Xo(i);let o=ot(e);if(!e.database||!e.kek)throw new x(500,"database_not_configured","A database and kek are required to issue connect links.");let s=await rt(i,e);if(!s.configured)throw new x(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=ae(J(t,r),e.kek),c;try{c=new URL(o.baseUrl)}catch{throw new x(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 kn(e,n,t){let r=t?.trim();if(!r)throw te("state is required",{missingFields:["state"]});ot(n);try{return await tt(e,r)}catch(i){if(i instanceof L)switch(i.code){case"invalid_state":throw te("Invalid or expired state");case"client_id_not_configured":throw new x(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new x(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function wn(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 te("Missing required fields",{missingFields:o});let s=ot(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 te("Invalid or expired state");case"credentials_not_configured":throw new x(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new x(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function Cn(e,n){if(!e.database)throw de("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw de("Permission not found");return t}var sr=[{method:"GET",pattern:"/ok",handler:async()=>R(200,dn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>R(200,await gn(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>R(201,await yn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>R(200,await fn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>R(200,await ln(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>R(200,await pn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>R(200,await hn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>R(200,await mn(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 Cn(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 bn(e,n))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>R(200,await kn(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>R(200,await wn(e,n,t))}];(()=>{let e=new Set;for(let n of sr){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function ei(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 ni(e,n){if(!n)return e;let t=n.endsWith("/")?n.slice(0,-1):n;return e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length):e}async function ti(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 x(400,"invalid_json","Request body is not valid JSON")}}var ri="/api/corsair";function ye(e,n={}){let t=n.basePath??ri,r=T(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async i=>{try{let o=new URL(i.url),s=ni(o.pathname,t),a=i.method.toUpperCase(),c=Object.fromEntries(o.searchParams);for(let d of sr){if(d.method!==a)continue;let l=ei(d.pattern,s);if(!l)continue;let u=await ti(i);return await d.handler({corsair:e,internal:r,req:i,params:l,query:c,body:u})}throw de(`No route for ${a} ${s}`)}catch(o){if(n.onError){let a=await n.onError(o,i);if(a)return a}if(o instanceof x)return nr(o);let s=o instanceof Error?o.message:"Internal server error";return R(500,{error:"internal_error",message:s})}}}function oi(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,i=`${t}://${n}${r}`,o=new Headers;for(let[c,d]of Object.entries(e.headers))if(d!=null)if(Array.isArray(d))for(let l of d)o.append(c,l);else o.set(c,d);let s=e.method!=="GET"&&e.method!=="HEAD",a={method:e.method,headers:o};return s&&e.body!==void 0&&(a.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),o.has("content-type")||o.set("content-type","application/json")),new Request(i,a)}async function ii(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 ar(e,n){let t=ye(e,n);return async(r,i,o)=>{try{let s=await t(oi(r));await ii(i,s)}catch(s){o(s)}}}function cr(e,n){let t=ye(e,n);return r=>t(r.req.raw)}function ur(e,n){let t=ye(e,n);return{GET:t,POST:t}}function dr(e){let n={[Ue]:e};return{ok:dn,tenants:{list:()=>gn(e),create:t=>yn(e,t),get:t=>fn(e,t)},plugins:{list:()=>ln(e),get:t=>pn(e,t)},connectionStatus:{get:t=>hn(e,t?.tenantId)},permissions:{get:t=>mn(e,t),getByToken:t=>Cn(e,t)},connect:{createLink:t=>bn(e,t),resolve:t=>kn(n,e,t),oauthCallback:t=>wn(n,e,t)}}}async function lr(e,n,t,r,i="pending"){if(!e)return null;try{let o=ht(),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 si(e,n,t,r="pending"){try{let i=await e.$getAccountId();return lr(e.database,i,n,t,r)}catch(i){return console.warn("Failed to log event:",i),null}}import*as pr from"https";import*as gr from"querystring";function Pn(e,n,t,r,i){let o=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,c)=>{let d={code:e.trim(),redirect_uri:i,grant_type:"authorization_code"};s||(d.client_id=n,d.client_secret=t);let l=gr.stringify(d),u={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(l).toString()};s&&(u.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let g=pr.request({hostname:o.hostname,...o.port?{port:Number(o.port)}:{},path:o.pathname+o.search,method:"POST",headers:u},y=>{let p="";y.on("data",f=>{p+=f}),y.on("end",()=>{if(y.statusCode!==200){c(new Error(`Token exchange failed (${y.statusCode}): ${p}`));return}try{a(JSON.parse(p))}catch{c(new Error(`Token endpoint returned non-JSON response: ${p}`))}})});g.on("error",y=>c(new Error(`Request failed: ${y.message}`))),g.write(l),g.end()})}var fr=" ";function K(e){let n=e;return n._def??n.def??{}}function Z(e){let n=e.typeName;if(n)return n;let t=e.type;if(t)return`Zod${t.split("_").map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("")}`}function j(e){return e.innerType??e.schema??e.out??e.in}function hr(e,n){switch(n){case"ZodPipe":return e.in??e.innerType;case"ZodEffects":return e.schema??e.innerType;case"ZodTransform":return e.schema??e.innerType??e.in;default:return j(e)}}function mr(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function An(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function xe(e){return Array.isArray(e.options)?e.options:Array.isArray(e.values)?e.values:e.entries!==null&&typeof e.entries=="object"&&!Array.isArray(e.entries)?Object.values(e.entries):[]}function br(e,n){return e.description??n.description}function ai(e){let n=e;for(;n;){let t=K(n),r=br(n,t);if(r)return r;let i=Z(t);if(ut(i)||i==="ZodPipe"||i==="ZodEffects"||i==="ZodTransform"){n=hr(t,i);continue}break}}function ut(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function M(e){let n=K(e),t=Z(n);switch(t){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"Date";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(n.value??xe(n)[0]??"unknown");case"ZodEnum":return xe(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=j(n);return r?M(r):"unknown"}case"ZodNullable":{let r=j(n);return`${r?M(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=j(n);return r?M(r):"unknown"}case"ZodArray":{let r=mr(n);if(!r)return"unknown[]";let i=K(r),o=Z(i)==="ZodUnion",s=M(r);return`${o?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=An(e,n),i=Object.entries(r);return i.length===0?"{}":`{ ${i.map(([s,a])=>{let c=Z(K(a));return`${c==="ZodOptional"||c==="ZodNullable"?s+"?":s}: ${M(a)}`}).join(", ")} }`}case"ZodUnion":return xe(n).map(r=>M(r)).join(" | ");case"ZodIntersection":return`${M(n.left)} & ${M(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=hr(n,t);return r?M(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function re(e){let n=K(e),t=Z(n),r=br(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??xe(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=xe(n).map(o=>String(o));return{kind:"string",optional:!1,description:r,enum:i}}case"ZodOptional":{let i=j(n),o=i?re(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodNullable":{let i=j(n),o=i?re(i):{kind:"unknown",optional:!1};return{...o,optional:!0,description:r??o.description}}case"ZodDefault":case"ZodCatch":{let i=j(n);return i?{...re(i),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let i=mr(n);return{kind:"array",optional:!1,description:r,items:i?re(i):{kind:"unknown",optional:!1}}}case"ZodObject":{let i=An(e,n),o={};for(let[s,a]of Object.entries(i))o[s]=re(a);return{kind:"object",optional:!1,description:r,fields:o}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let i=xe(n);for(let o of i){let s=K(o);if(Z(s)==="ZodObject")return{...re(o),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let i=j(n);return i?{...re(i),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Jc(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let i=t.slice(0,r),o=t.slice(r+1),s=e.find(l=>l.id===i);if(!s)return null;let a=o;a.startsWith("api.")&&(a=a.slice(4));let c=le(s.endpointMeta,a),d=le(s.endpointSchemas,a);return!c&&!d?null:{input:d?.input?re(d.input):null,output:d?.output?re(d.output):null,description:c?.description}}var dt=["equals","contains","startsWith","endsWith","in"],ci=["equals","gt","gte","lt","lte","in"],ui=["equals"],di=["equals","before","after","between"];function kr(e){let n=K(e);switch(Z(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=j(n);return r?kr(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function lt(e){let n=K(e),t=Z(n);if(ut(t)){let o=j(n);return o?lt(o):{}}if(t!=="ZodObject")return{};let r=An(e,n),i={};for(let[o,s]of Object.entries(r)){let a=kr(s);a==="string"?i[o]={type:"string",operators:dt}:a==="number"?i[o]={type:"number",operators:ci}:a==="boolean"?i[o]={type:"boolean",operators:ui}:a==="date"&&(i[o]={type:"date",operators:di})}return i}function wr(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function st(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"&&st(i,o,t)}}function at(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function ct(e,n,t){for(let[r,i]of Object.entries(e)){let o=[...n,r];at(i)?t.push(o.join(".")):i!==null&&typeof i=="object"&&ct(i,o,t)}}function pt(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 at(s)?[o]:null;if(s!==null&&typeof s=="object"&&!at(s)){let a=pt(s,r);if(a!==null)return[o,...a]}return null}function Cr(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(`
|
|
26
|
+
`)}var li=new Set(je);function he(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 li.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:he(e);if(t==="webhooks"){if(!o.webhooks)return[];let a=[];return ct(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 st(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=[];ct(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=[];st(o.endpoints,[],s),i[o.id]=s.map(a=>`${o.id}.api.${a}`)}return i}function le(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function pi(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 it(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
|
|
27
|
+
${e.join(", ")}`:`${n}:
|
|
28
|
+
`+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
|
|
29
|
+
`)}function Vc(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let i=t.slice(0,r),o=t.slice(r+1),s=e.find(a=>a.id===i);if(s){if(o.startsWith("db.")){let l=o.slice(3),u=l.lastIndexOf(".");if(u!==-1){let g=l.slice(0,u),y=l.slice(u+1),p=s.schema?.entities;if(y==="search"&&p){let f=wr(p,g);if(f){let[h,m]=f,C=lt(m),k=[`Search ${i} ${h} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${dt.join(", ")}]`];for(let[b,w]of Object.entries(C))k.push(` ${b}?: ${w.type} [${w.operators.join(", ")}]`);return k.push("}"),k.join(`
|
|
30
|
+
`)}}}return it(he(e,{type:"db"}),"Path not found. Available db operations")}if(o.startsWith("webhooks.")){let l=o.slice(9);if(s.webhooks){let u=pt(s.webhooks,l.split("."));if(u!==null){let g=u.join("."),y=le(s.webhookSchemas,g.toLowerCase()),p=y?.response?M(y.response):null,f=[];return y?.description&&f.push(y.description),y?.payload&&f.push(`payload ${Tn(Re(y.payload))}`),p&&f.push(`response: ${p}`),f.push(`usage:
|
|
31
|
+
${Cr(i,u)}`),f.join(`
|
|
32
|
+
|
|
33
|
+
`)}}return it(he(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=o;a.startsWith("api.")&&(a=a.slice(4));let c=le(s.endpointMeta,a),d=le(s.endpointSchemas,a);if(c||d){let l=[],u=[c?.riskLevel?`[${c.riskLevel}]`:"",c?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),g=[c?.description,u].filter(Boolean).join(" ");return g&&l.push(g),d?.input&&l.push(`input ${Tn(Re(d.input))}`),d?.output&&l.push(`output ${Tn(Re(d.output))}`),l.join(`
|
|
34
|
+
|
|
35
|
+
`)}}}return it(he(e),"Path not found. Available operations")}function yr(e){let n=e;for(;;){let t=K(n),r=Z(t);if(ut(r)){let i=j(t);if(!i)return n;n=i;continue}return n}}function Re(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=yr(e),t=K(n);if(Z(t)==="ZodObject"){let i=An(n,t),o=[];for(let[s,a]of Object.entries(i)){let c=K(a),d=Z(c),l=d==="ZodOptional"||d==="ZodNullable",u=yr(a),g=ai(a);o.push({key:s,optional:l,type:M(u),...g!==void 0?{description:g}:{}})}return{kind:"object",fields:o}}return{kind:"inline",type:M(n)}}function Tn(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=fr.repeat(n+1),r=fr.repeat(n);return`{
|
|
36
|
+
${e.fields.map(o=>{let s=o.optional?`${o.key}?`:o.key,a=o.description?` // ${o.description}`:"";return`${t}${s}: ${o.type}${a}`}).join(`
|
|
37
|
+
`)}
|
|
38
|
+
${r}}`}return"unknown"}function gi(e,n){let t=he(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(l=>l.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let i=[];for(let l of t){let{shortPath:u,lookupKey:g}=pi(l,n),y=le(r.endpointMeta,g),p=le(r.endpointSchemas,g);!y&&!p||i.push({path:l,shortPath:u,description:y?.description,riskLevel:y?.riskLevel,irreversible:y?.irreversible,input:Re(p?.input),output:Re(p?.output)})}i.sort((l,u)=>l.path.localeCompare(u.path));let o=[],s=he(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let l of s){let g=l.toLowerCase().slice(n.length+1),y=g.startsWith(".")?g.slice(1):g;if(!y.startsWith("webhooks."))continue;let p=y.slice(9),f=pt(r.webhooks,p.split("."));if(f===null)continue;let h=f.join("."),m=le(r.webhookSchemas,h.toLowerCase()),C=m?.response?M(m.response):void 0;o.push({path:l,description:m?.description,payload:Re(m?.payload),responseType:C,usageExample:Cr(n,f)})}o.sort((l,u)=>l.path.localeCompare(u.path));let a=[],c=he(e,{plugin:n,type:"db"}),d=r.schema?.entities;if(Array.isArray(c)&&d)for(let l of c){let g=l.toLowerCase().slice(n.length+1),y=g.startsWith(".")?g.slice(1):g;if(!y.startsWith("db."))continue;let p=y.slice(3),f=p.lastIndexOf(".");if(f===-1)continue;let h=p.slice(0,f);if(p.slice(f+1)!=="search")continue;let C=wr(d,h);if(!C)continue;let[k,b]=C,w=lt(b),P=Object.entries(w).map(([S,_])=>({field:S,type:_.type,operators:_.operators}));a.push({path:l,entityName:k,filters:[{field:"entity_id",type:"string",operators:dt},...P]})}return a.sort((l,u)=>l.path.localeCompare(u.path)),{ok:!0,data:{pluginId:n,api:i,webhooks:o,db:a}}}function Pr(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function fi(e,n){let t=Pr(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 yi(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function Tr(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Ar(e){if(typeof e=="string"){let n=e.trim();return n.length>0?n:void 0}if(typeof e=="number"&&Number.isFinite(e))return String(e)}function We(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function hi(e){return We(e.body)}function xr(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return xn(Array.isArray(r)?r:[r])}function Rr(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let d=xn(Array.isArray(c)?c:[c]);if(d)return decodeURIComponent(d)}let r=xr({query:e.query},"validationToken");if(r)return r;let i=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let c of i){let d=n[c],l=Array.isArray(d)?d[0]:d;if(!(!l||typeof l!="string"))try{let g=(l.startsWith("http")?new URL(l):new URL(`https://example.invalid${l.startsWith("/")?l:`/${l}`}`)).searchParams.get("validationToken");if(g?.trim())return g.trim()}catch{continue}}let o=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=We(typeof o=="string"?(()=>{try{return JSON.parse(o)}catch{return o}})():o);return xn([s?.validationToken])??null}function mi(e){if(Rr(e))return!0;let n=We(e.body??e.payload);return Tr(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function xn(e){for(let n of e){let t=Ar(n);if(t)return t}}function bi(e){let t=We(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Ue=Symbol.for("corsair:internal");function It(e){let n=e.database?gt(e.database):void 0,t=n&&e.kek?Xt(e.plugins,n,e.kek):un(!!n,!!e.kek),r={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,approval:e.approval,connect:e.connect,hub:e.hub?Ke(e.hub):void 0},i=Yt(n),o=dr(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=nt(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,{[Ue]:r})},keys:t,permissions:i,manage:o},{[Ue]:r});let s=nt(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,[Ue]:r})}var B=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Ir(e){let n=e.oauthConfig;if(!n)throw new B("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function ki(e,n,t,r){let i=bt(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=Q(),c=await X(a,r);await i.accounts.create({tenant_id:t,integration_id:o.id,config:{},dek:c})}async function En(e,n,t){let{tenantId:r,redirectUri:i}=t,o=T(e,()=>new B("invalid_corsair_instance","Invalid corsair instance"));if(!o.database)throw new Error("No database configured on corsair instance");let s=F(o,n,g=>new B("plugin_not_found",g)),a=Ir(s),d=await D({authType:"oauth_2",integrationName:n,kek:o.kek,database:o.database}).get_client_id();if(!d)throw new Error(`client_id not configured for '${n}'`);let l=ae(J(n,r),o.kek),u={...a.authParams,client_id:d,redirect_uri:i,response_type:"code",scope:a.scopes.join(" "),state:l};return{url:`${a.authUrl}?${vr.stringify(u)}`,state:l}}async function Fe(e,n){let{code:t,state:r,redirectUri:i}=n,o=T(e,()=>new B("invalid_corsair_instance","Invalid corsair instance")),s=qe(r,o.kek);if(!s)throw new B("invalid_state","Invalid or tampered state parameter");let{plugin:a,tenantId:c}=s;if(!o.database)throw new B("no_database","No database configured on corsair instance");let d=F(o,a,h=>new B("plugin_not_found",h)),l=Ir(d),u=D({authType:"oauth_2",integrationName:a,kek:o.kek,database:o.database}),g=await u.get_client_id(),y=await u.get_client_secret();if(!g||!y)throw new B("credentials_not_configured",`Credentials not configured for '${a}'`);await ki(o.database,a,c,o.kek);let p=await Pn(t,g,y,l,i);if(!p.access_token)throw new B("no_access_token",`No access_token returned from ${l.providerName}`);let f=I({authType:"oauth_2",integrationName:a,tenantId:c,kek:o.kek,database:o.database});await f.set_access_token(p.access_token),p.refresh_token&&await f.set_refresh_token(p.refresh_token),p.expires_in&&await f.set_expires_at(String(Math.floor(Date.now()/1e3)+p.expires_in));try{let h=await en(o.plugins,a,p);if(h)try{let m=d.authConfig?.oauth_2?.account??[];await Te({database:o.database,kek:o.kek,pluginId:a,tenantId:c,link:h,authType:"oauth_2",extraAccountFields:m})}catch(m){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${a}' tenant '${c}':`,m)}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${a}' tenant '${c}':`,h)}return{plugin:a,tenantId:c}}export{kt as a,Ie as b,Se as c,Y as d,Ke as e,H as f,Ze as g,J as h,In as i,Q as j,X as k,W as l,Bn as m,Me as n,ce as o,ee as p,He as q,D as r,I as s,Bt as t,$t as u,Te as v,Fn as w,on as x,Nt as y,B as z,En as A,Fe as B,Ee as C,we as D,At as E,Ce as F,Rt as G,eo as H,Je as I,On as J,Dn as K,Mn as L,Hn as M,Ve as N,ue as O,Ae as P,Wt as Q,ge as R,fe as S,Be as T,$e as U,sn as V,an as W,Ln as X,jn as Y,Kn as Z,Zn as _,qn as $,Gn as aa,zn as ba,Ne as ca,ne as da,Jn as ea,Gt as fa,zt as ga,tt as ha,ye as ia,ar as ja,cr as ka,ur as la,lr as ma,si as na,Pn as oa,Jc as pa,he as qa,Vc as ra,Tn as sa,gi as ta,Pr as ua,fi as va,yi as wa,Tr as xa,Ar as ya,We as za,hi as Aa,xr as Ba,Rr as Ca,mi as Da,xn as Ea,bi as Fa,Ue as Ga,It as Ha};
|
package/dist/core.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-
|
|
1
|
+
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-VQ5aPg7o.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
3
|
import { A as AuthTypes, a as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './types-CqV508wD.js';
|
|
4
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-CqV508wD.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-
|
|
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-
|
|
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-Cl0-2f8A.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-CXChw66S.js';
|
|
7
7
|
import 'kysely';
|
|
8
8
|
import 'zod';
|
|
9
9
|
import 'pg';
|
package/dist/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Aa as
|
|
1
|
+
import{Aa as C,Ba as D,Ca as E,Da as F,Ea as G,Fa as H,Ga as I,Ha as J,a,b,da as p,ha as q,j as d,k as e,l as f,m as g,ma as r,n as h,na as s,o as i,oa as t,p as j,q as k,r as l,s as m,sa as u,t as n,ta as v,u as o,ua as w,va as x,wa as y,xa as z,ya as A,za as B}from"./chunk-SBBVO5OB.js";import{g as c}from"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{p as AuthMissingError,c as BASE_AUTH_FIELDS,I as CORSAIR_INTERNAL,a as ProviderDisplayNames,B as asRecord,y as collectPluginWebhookMatchers,m as createAccountKeyManager,J as createCorsair,l as createIntegrationKeyManager,H as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,t as exchangeCodeForTokens,E as extractMicrosoftGraphValidationToken,G as firstString,u as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,z as getHeader,o as initializeAccountDEK,n as initializeIntegrationDEK,v as introspectPluginForDocs,F as isMicrosoftGraphValidationHandshake,r as logEvent,s as logEventFromContext,w as matchWebhookPlugin,x as matchWebhookPluginAndTenant,k as reEncryptConfig,C as readBodyRecord,D as readQueryParam,q as resolveConnectLink,A as toExternalId};
|
package/dist/hub.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { l as HubOAuthMode, m as HubConnectSource, H as HubConfig, n as HubConfigInput, o as HubConnectSessionInput, p as HubConnectSessionResult, a as AccountKeyManagerFor } from './types-CqV508wD.js';
|
|
2
2
|
export { D as DEFAULT_HUB_API_URL, q as HubPermissionSessionInput, r as HubPermissionSessionResult, i as formatProviderDisplayName } from './types-CqV508wD.js';
|
|
3
|
-
import { c as ProcessCorsairRequest } from './index-
|
|
4
|
-
export { d as TunnelEnvelope, e as TunnelType } from './index-
|
|
3
|
+
import { c as ProcessCorsairRequest } from './index-t-u4QNP-.js';
|
|
4
|
+
export { d as TunnelEnvelope, e as TunnelType } from './index-t-u4QNP-.js';
|
|
5
5
|
|
|
6
6
|
type ConnectAuthKind = 'oauth' | 'api_key' | 'bot_token';
|
|
7
7
|
type ConnectPluginManifestEntry = {
|
|
@@ -13,6 +13,7 @@ type ConnectPluginManifestEntry = {
|
|
|
13
13
|
oauthMode?: HubOAuthMode;
|
|
14
14
|
oauthUrl?: string;
|
|
15
15
|
state?: string;
|
|
16
|
+
setupError?: string;
|
|
16
17
|
};
|
|
17
18
|
type CreateConnectSessionRequestBody = {
|
|
18
19
|
tenantId: string;
|
|
@@ -86,6 +87,11 @@ type HubConnectSessionResponseOptions = {
|
|
|
86
87
|
resolveTenantId?: ResolveHubConnectTenantId;
|
|
87
88
|
/** Used when resolveTenantId is not provided. Defaults to "default". */
|
|
88
89
|
defaultTenantId?: string;
|
|
90
|
+
/**
|
|
91
|
+
* When false (default), tenantId from the request body/query is ignored unless
|
|
92
|
+
* resolveTenantId is provided. Set true only for trusted local/dev flows.
|
|
93
|
+
*/
|
|
94
|
+
allowClientProvidedTenantId?: boolean;
|
|
89
95
|
};
|
|
90
96
|
declare function parseHubConnectSessionBody(body: HubConnectSessionRequestBody): HubConnectSessionInput | HubConnectSessionParseError;
|
|
91
97
|
declare function parseHubConnectSessionSearchParams(url: string): HubConnectSessionRequestBody;
|
|
@@ -158,6 +164,7 @@ declare function processManagedOAuthDelivery(corsair: unknown, options: ProcessM
|
|
|
158
164
|
type HubRouteHandlersOptions = HubConnectSessionResponseOptions;
|
|
159
165
|
declare function createHubRouteHandlers(corsair: unknown, options?: HubRouteHandlersOptions): {
|
|
160
166
|
delivery: (request: Request) => Promise<Response>;
|
|
167
|
+
deliveryOptions: (request: Request) => Promise<Response>;
|
|
161
168
|
createConnectSession: (request: Request) => Promise<Response>;
|
|
162
169
|
};
|
|
163
170
|
|
package/dist/hub.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as
|
|
1
|
+
import{$ as u,C as g,D as h,E as i,F as j,I as k,J as l,K as m,L as n,M as o,N as p,O as q,P as r,Z as s,_ as t,aa as v,b as a,ba as w,c as b,ca as x,d as c,e as d,ea as y,f as e,fa as z,g as f,ga as A}from"./chunk-SBBVO5OB.js";import"./chunk-NZS35HPL.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};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CorsairDatabase } from './db.js';
|
|
2
2
|
import { H as HubConfig } from './types-CqV508wD.js';
|
|
3
|
-
import { C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-
|
|
3
|
+
import { C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-Cl0-2f8A.js';
|
|
4
4
|
|
|
5
5
|
declare const CORSAIR_INTERNAL: unique symbol;
|
|
6
6
|
type CorsairInternalConfig = {
|
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
type TunnelType = 'oauth.callback' | 'oauth.tokens' | 'webhook' | 'permission.approve' | 'permission.deny' | 'auth.credentials' | 'run';
|
|
1
|
+
type TunnelType = 'oauth.callback' | 'oauth.tokens' | 'webhook' | 'permission.approve' | 'permission.deny' | 'auth.credentials' | 'connect.status' | 'run';
|
|
2
2
|
type TunnelEnvelope<TPayload = unknown> = {
|
|
3
3
|
type: TunnelType;
|
|
4
4
|
payload: TPayload;
|
|
5
5
|
};
|
|
6
|
+
type BrowserDeliveryMode = 'oauth.callback' | 'oauth.tokens' | 'permission.approve' | 'permission.deny' | 'connect.status' | 'auth.credentials';
|
|
7
|
+
type BrowserDeliveryPayload = {
|
|
8
|
+
jti: string;
|
|
9
|
+
connectJti: string;
|
|
10
|
+
projectId: string;
|
|
11
|
+
plugin: string;
|
|
12
|
+
tenantId: string;
|
|
13
|
+
hubSuccessUrl: string;
|
|
14
|
+
exp: number;
|
|
15
|
+
iat: number;
|
|
16
|
+
deliveryMode?: BrowserDeliveryMode;
|
|
17
|
+
code?: string;
|
|
18
|
+
state?: string;
|
|
19
|
+
redirectUri?: string;
|
|
20
|
+
accessToken?: string;
|
|
21
|
+
refreshToken?: string;
|
|
22
|
+
expiresIn?: number;
|
|
23
|
+
scope?: string;
|
|
24
|
+
permissionToken?: string;
|
|
25
|
+
/** Hub page origin for iframe postMessage replies (client bridge). */
|
|
26
|
+
hubOrigin?: string;
|
|
27
|
+
requestId?: string;
|
|
28
|
+
statusPlugins?: string[];
|
|
29
|
+
credentials?: Record<string, string>;
|
|
30
|
+
};
|
|
6
31
|
|
|
7
32
|
type TunnelAck = {
|
|
8
33
|
status: 'ok' | 'failed';
|
|
@@ -51,4 +76,4 @@ type ProcessCorsairOptions = {
|
|
|
51
76
|
};
|
|
52
77
|
declare function processCorsair(corsair: unknown, request: ProcessCorsairRequest, options?: ProcessCorsairOptions): Promise<TunnelAck>;
|
|
53
78
|
|
|
54
|
-
export { type OAuthCallbackTunnelPayload as O, type ProcessCorsairOptions as P, type TunnelAck as T, type WebhookTunnelPayload as W, applyPermissionDecision as a, type OAuthTokensTunnelPayload as b, type ProcessCorsairRequest as c, type TunnelEnvelope as d, type TunnelType as e, processCorsair as p };
|
|
79
|
+
export { type BrowserDeliveryPayload as B, type OAuthCallbackTunnelPayload as O, type ProcessCorsairOptions as P, type TunnelAck as T, type WebhookTunnelPayload as W, applyPermissionDecision as a, type OAuthTokensTunnelPayload as b, type ProcessCorsairRequest as c, type TunnelEnvelope as d, type TunnelType as e, processCorsair as p };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { a1 as ManagementOk, a2 as Tenant, a3 as CreateTenantInput, a4 as PluginInfo, a5 as ConnectionStatus, a6 as PermissionRecord, a7 as CreateConnectLinkInput, a8 as ConnectLink, a9 as ResolvedConnectLink, aa as OAuthCallbackInput, ab as OAuthCallbackResult, c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, d as CorsairClient, q as CorsairPermissionsNamespace, N as BoundWebhookTree, Y as RawWebhookRequest, X as CorsairWebhookTenantMatcher, $ as WebhookResponse } from './index-
|
|
2
|
-
export { ac as CorsairManageNamespace, ad as PluginConnectionState } from './index-
|
|
3
|
-
export { c as createCorsair } from './index-
|
|
4
|
-
import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-
|
|
5
|
-
export { A as AuthMissingError, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, o as firstString, f as formatDocSchemaShape, p as getHeader, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-
|
|
1
|
+
import { a1 as ManagementOk, a2 as Tenant, a3 as CreateTenantInput, a4 as PluginInfo, a5 as ConnectionStatus, a6 as PermissionRecord, a7 as CreateConnectLinkInput, a8 as ConnectLink, a9 as ResolvedConnectLink, aa as OAuthCallbackInput, ab as OAuthCallbackResult, c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, d as CorsairClient, q as CorsairPermissionsNamespace, N as BoundWebhookTree, Y as RawWebhookRequest, X as CorsairWebhookTenantMatcher, $ as WebhookResponse } from './index-Cl0-2f8A.js';
|
|
2
|
+
export { ac as CorsairManageNamespace, ad as PluginConnectionState } from './index-Cl0-2f8A.js';
|
|
3
|
+
export { c as createCorsair } from './index-VQ5aPg7o.js';
|
|
4
|
+
import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-CXChw66S.js';
|
|
5
|
+
export { A as AuthMissingError, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, o as firstString, f as formatDocSchemaShape, p as getHeader, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-CXChw66S.js';
|
|
6
6
|
export { SetupCorsairOptions, setupCorsair } from './setup.js';
|
|
7
|
-
export { O as OAuthCallbackTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, p as processCorsair } from './index-
|
|
7
|
+
export { O as OAuthCallbackTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, p as processCorsair } from './index-t-u4QNP-.js';
|
|
8
8
|
import { g as BaseProviders } from './types-CqV508wD.js';
|
|
9
|
-
export { R as ResolveAccountFromWebhookLinkInput, W as WebhookTenantLink, r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-
|
|
9
|
+
export { R as ResolveAccountFromWebhookLinkInput, W as WebhookTenantLink, r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-x_63WNLM.js';
|
|
10
10
|
import 'zod';
|
|
11
11
|
import './db.js';
|
|
12
12
|
import 'kysely';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{Aa as D,Ea as H,Fa as j,G as w,Ga as k,Ha as B,Q as I,Y as S,da as T,ha as O,ia as L,ja as A,ka as v,la as $,pa as d,qa as g,ra as C,sa as f,ua as E,v as P,va as M,w as x,wa as W,x as b,xa as F,y as R,ya as _,za as N}from"./chunk-SBBVO5OB.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";var c=class extends Error{status;code;extra;constructor(r,o,e,a={}){super(e),this.name="CorsairClientError",this.status=r,this.code=o,this.extra=a}};function J(n){return n.endsWith("/")?n.slice(0,-1):n}async function y(n){let r={};try{r=await n.json()}catch{}let o=typeof r.error=="string"?r.error:"request_failed",e=typeof r.message=="string"?r.message:`Request failed (${n.status})`,{error:a,message:u,...t}=r;return new c(n.status,o,e,t)}function U(n){let r=J(n.baseURL),o=n.fetch??((...t)=>globalThis.fetch(...t));async function e(t,s){let i=s&&Object.keys(s).length?`?${new URLSearchParams(s).toString()}`:"",p=await o(`${r}${t}${i}`,{method:"GET"});if(!p.ok)throw await y(p);return await p.json()}async function a(t,s){let i=await o(`${r}${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw await y(i);return await i.json()}let u=encodeURIComponent;return{ok:()=>e("/ok"),tenants:{list:()=>e("/tenants"),create:t=>a("/tenants",t),get:t=>e(`/tenants/${u(t)}`)},plugins:{list:()=>e("/plugins"),get:t=>e(`/plugins/${u(t)}`)},connectionStatus:{get:t=>{let s={};return t?.tenantId&&(s.tenantId=t.tenantId),e("/connection-status",s)}},permissions:{get:t=>e(`/permissions/${u(t)}`),getByToken:t=>a("/permissions/lookup-by-token",{token:t})},connect:{createLink:t=>a("/connect/links",t),resolve:t=>e("/connect/resolve",{state:t}),oauthCallback:t=>a("/connect/oauth/callback",t)}}}function l(n){let r=n[k];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function q(n,r){let o=g(l(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
|
|
2
2
|
`):Object.values(o).flat().join(`
|
|
3
|
-
`)}function G(n,r){return C(l(n),r)}function Y(n,r){return d(l(n),r)}var z=Symbol.for("corsair:internal");function K(n,r){let o=n;for(let e of r){if(!o||typeof o!="object")return null;o=o[e]}return typeof o=="function"?o:null}function h(n){return n[z]?.database}async function Q(n,r){let o=new Date().toISOString(),e=await n.permissions.find_by_token(r);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<o){let i=h(n);return i&&await i.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let a=e.tenant_id??"default",t=(n.withTenant?n.withTenant(a):n)[e.plugin];if(!t?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let s=K(t.api,e.endpoint.split("."));if(!s)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let i=typeof e.args=="string"?JSON.parse(e.args):e.args,p=await s(i);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:p}}catch(i){let p=i instanceof Error?i.message:String(i),m=h(n);return m&&await m.db.updateTable("corsair_permissions").set({status:"failed",error:p,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:p}}}export{
|
|
3
|
+
`)}function G(n,r){return C(l(n),r)}function Y(n,r){return d(l(n),r)}var z=Symbol.for("corsair:internal");function K(n,r){let o=n;for(let e of r){if(!o||typeof o!="object")return null;o=o[e]}return typeof o=="function"?o:null}function h(n){return n[z]?.database}async function Q(n,r){let o=new Date().toISOString(),e=await n.permissions.find_by_token(r);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<o){let i=h(n);return i&&await i.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let a=e.tenant_id??"default",t=(n.withTenant?n.withTenant(a):n)[e.plugin];if(!t?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let s=K(t.api,e.endpoint.split("."));if(!s)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let i=typeof e.args=="string"?JSON.parse(e.args):e.args,p=await s(i);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:p}}catch(i){let p=i instanceof Error?i.message:String(i),m=h(n);return m&&await m.db.updateTable("corsair_permissions").set({status:"failed",error:p,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:p}}}export{T as AuthMissingError,c as CorsairClientError,N as asRecord,W as collectPluginWebhookMatchers,B as createCorsair,U as createCorsairClient,j as decodePubSubData,Q as executePermission,H as firstString,f as formatDocSchemaShape,F as getHeader,G as getSchema,Y as getStructuredSchema,q as listOperations,L as managementHandler,E as matchWebhookPlugin,M as matchWebhookPluginAndTenant,S as processCorsair,I as processWebhook,D as readBodyRecord,x as resolveAccountFromWebhookLink,O as resolveConnectLink,R as resolveTenantFromWebhookLink,b as resolveTenantIdFromWebhookLink,P as setWebhookTenantLink,w as setupCorsair,A as toExpressHandler,_ as toExternalId,v as toHonoHandler,$ as toNextJsHandler};
|
package/dist/oauth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as d,B as e,h as a,i as b,z as c}from"./chunk-
|
|
1
|
+
import{A as d,B as e,h as a,i as b,z as c}from"./chunk-SBBVO5OB.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{c as OAuthCallbackError,b as decodeOAuthState,a as encodeOAuthState,d as generateOAuthUrl,e as processOAuthCallback};
|
package/dist/orm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./chunk-N2XRSSRL.js";import{m as o,n as e,o as n,p as s}from"./chunk-
|
|
1
|
+
import"./chunk-N2XRSSRL.js";import{m as o,n as e,o as n,p as s}from"./chunk-NZS35HPL.js";import{b as r,c as t,d as i,e as a}from"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{t as CorsairAccountsSchema,i as CorsairEntitiesSchema,a as CorsairEventsSchema,r as CorsairIntegrationsSchema,o as createCorsairOrm,e as createPluginOrm,s as createPluginOrmFactory,n as createTenantScopedOrm};
|
package/dist/setup.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as CorsairInternalConfig } from './index-
|
|
1
|
+
import { a as CorsairInternalConfig } from './index-VQ5aPg7o.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
|
-
import { C as CorsairPlugin, c as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-
|
|
3
|
+
import { C as CorsairPlugin, c as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-Cl0-2f8A.js';
|
|
4
4
|
import './types-CqV508wD.js';
|
|
5
5
|
import 'kysely';
|
|
6
6
|
import 'zod';
|
package/dist/setup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{G as a,H as b}from"./chunk-
|
|
1
|
+
import{G as a,H as b}from"./chunk-SBBVO5OB.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as applySetupCredentials,a as setupCorsair};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as AuthTypes } from './types-CqV508wD.js';
|
|
2
|
-
import { W as WebhookTenantMatch } from './index-
|
|
2
|
+
import { W as WebhookTenantMatch } from './index-Cl0-2f8A.js';
|
|
3
3
|
import { CorsairDatabase, CorsairAccount } from './db.js';
|
|
4
4
|
|
|
5
5
|
type WebhookTenantLink = WebhookTenantMatch;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z as EndpointRiskLevel, C as CorsairPlugin, V as CorsairWebhookMatcher, X as CorsairWebhookTenantMatcher, Y as RawWebhookRequest, W as WebhookTenantMatch } from './index-
|
|
1
|
+
import { z as EndpointRiskLevel, C as CorsairPlugin, V as CorsairWebhookMatcher, X as CorsairWebhookTenantMatcher, Y as RawWebhookRequest, W as WebhookTenantMatch } from './index-Cl0-2f8A.js';
|
|
2
2
|
import { f as AllProviders } from './types-CqV508wD.js';
|
|
3
3
|
|
|
4
4
|
/**
|
package/dist/tunnel.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
import { B as BrowserDeliveryPayload } from './index-t-u4QNP-.js';
|
|
2
|
+
export { O as OAuthCallbackTunnelPayload, b as OAuthTokensTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, a as applyPermissionDecision, p as processCorsair } from './index-t-u4QNP-.js';
|
|
3
|
+
export { r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-x_63WNLM.js';
|
|
3
4
|
import './types-CqV508wD.js';
|
|
4
|
-
import './index-
|
|
5
|
+
import './index-Cl0-2f8A.js';
|
|
5
6
|
import 'zod';
|
|
6
7
|
import './db.js';
|
|
7
8
|
import 'kysely';
|
|
@@ -9,27 +10,11 @@ import 'pg';
|
|
|
9
10
|
import 'postgres';
|
|
10
11
|
import './orm.js';
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
connectJti: string;
|
|
15
|
-
projectId: string;
|
|
16
|
-
plugin: string;
|
|
17
|
-
tenantId: string;
|
|
18
|
-
hubSuccessUrl: string;
|
|
19
|
-
exp: number;
|
|
20
|
-
iat: number;
|
|
21
|
-
deliveryMode?: 'oauth.callback' | 'oauth.tokens' | 'permission.approve' | 'permission.deny';
|
|
22
|
-
code?: string;
|
|
23
|
-
state?: string;
|
|
24
|
-
redirectUri?: string;
|
|
25
|
-
accessToken?: string;
|
|
26
|
-
refreshToken?: string;
|
|
27
|
-
expiresIn?: number;
|
|
28
|
-
scope?: string;
|
|
29
|
-
permissionToken?: string;
|
|
30
|
-
};
|
|
13
|
+
declare function isConnectStatusBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
14
|
+
declare function isAuthCredentialsBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
31
15
|
declare function isPermissionBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
32
16
|
declare function isManagedBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
17
|
+
declare function isByoOAuthBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
|
|
33
18
|
declare function verifyBrowserDeliveryToken(token: string, signingSecret: string): BrowserDeliveryPayload | null;
|
|
34
19
|
|
|
35
|
-
export {
|
|
20
|
+
export { BrowserDeliveryPayload, isAuthCredentialsBrowserDelivery, isByoOAuthBrowserDelivery, isConnectStatusBrowserDelivery, isManagedBrowserDelivery, isPermissionBrowserDelivery, verifyBrowserDeliveryToken };
|
package/dist/tunnel.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as e,S as f,T as g,U as h,V as i,v as a,w as b,x as c,y as d}from"./chunk-
|
|
1
|
+
import{R as e,S as f,T as g,U as h,V as i,W as j,X as k,Y as l,v as a,w as b,x as c,y as d}from"./chunk-SBBVO5OB.js";import"./chunk-NZS35HPL.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{k as applyPermissionDecision,f as isAuthCredentialsBrowserDelivery,i as isByoOAuthBrowserDelivery,e as isConnectStatusBrowserDelivery,h as isManagedBrowserDelivery,g as isPermissionBrowserDelivery,l as processCorsair,b as resolveAccountFromWebhookLink,d as resolveTenantFromWebhookLink,c as resolveTenantIdFromWebhookLink,a as setWebhookTenantLink,j as verifyBrowserDeliveryToken};
|