corsair 0.1.68 → 0.1.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ import{z as t}from"zod";var n=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),name:t.string(),config:t.record(t.string(),t.unknown()).nullable().transform(e=>e??{}),dek:t.string().nullish()}),i=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),tenant_id:t.string(),integration_id:t.string(),config:t.record(t.string(),t.unknown()).nullable().transform(e=>e??{}),dek:t.string().nullish()}),a=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),account_id:t.string(),entity_id:t.string(),entity_type:t.string(),version:t.string(),data:t.record(t.string(),t.unknown()).nullable().transform(e=>e??{})}),o=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),account_id:t.string(),event_type:t.string(),payload:t.record(t.string(),t.unknown()).nullable().transform(e=>e??{}),status:t.enum(["pending","processing","completed","failed"]).optional()}),s=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),token:t.string(),plugin:t.string(),endpoint:t.string(),args:t.string(),tenant_id:t.string(),status:t.enum(["pending","approved","executing","completed","denied","expired","failed"]).default("pending"),expires_at:t.string(),error:t.string().nullable().optional()});export{n as a,i as b,a as c,o as d,s as e};
@@ -0,0 +1,5 @@
1
+ import{i as w,j as C,k as S,u as A,v as T}from"./chunk-XYRVJ76B.js";import{a as _}from"./chunk-UBM25HVI.js";import{Kysely as I}from"kysely";import{ZodBoolean as M,ZodDate as R,ZodEnum as j,ZodNullable as D,ZodNumber as F,ZodObject as O,ZodOptional as x,ZodRecord as E,ZodString as K,ZodType as B}from"zod";var h={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:{}}}};async function ie(e,t){let a=[],i=s=>{a.push(s),console.log(s)},o=s=>{a.push(s),console.warn(s)},f=t?.caller??"script",d=t?.tenantId;if(!d){if(e?.withTenant)throw new Error("setupCorsair: tenantId must be a non-empty string");d="default"}let n=v(e);if(!n)throw new Error("setupCorsair: invalid corsair instance");if(!n.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u={...n,database:n.database},c=u.database.db;await Y(c,o);let p=await H(c,u,d,i),y=await z(p,d,i,f);if(t?.backfill){i("[corsair:setup] Starting backfill...");let s=T({plugins:n.plugins,database:c,kek:n.kek,multiTenancy:!0}).withTenant(d);await Q(s,n.plugins,y,i,o),i("[corsair:setup] Backfill complete.")}return a.join(`
2
+ `)}function b(e){return typeof e=="object"&&e!==null}function Z(e){return!b(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:b(e.database)?e.database.db instanceof I:!1}function v(e){let t=Object.getOwnPropertyDescriptor(e,A);if(t)return Z(t.value)?t.value:void 0}function N(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"}function L(e){let t=e.options?.authType;return N(t)?t:void 0}function m(e,t){if(!b(e))return;let a=e[t];return typeof a=="function"?(...i)=>Reflect.apply(a,e,i):void 0}function $(e,t){return b(e)?t===0?!0:Object.values(e).every(a=>$(a,t-1)):!1}function U(e){return $(e,4)}var W={..._};function k(e){if(e instanceof O){let t={};for(let[a,i]of Object.entries(e.shape))t[a]=i instanceof B?k(i):"unknown";return t}return e instanceof D?`${k(e.unwrap())} | null`:e instanceof x?`${k(e.unwrap())} | undefined`:e instanceof j?e.options.join(" | "):e instanceof K?"string":e instanceof F?"number":e instanceof M?"boolean":e instanceof R?"date":e instanceof E?"jsonb":"unknown"}async function Y(e,t){let a=await e.introspection.getTables(),i=new Set(a.map(o=>o.name));for(let[o,f]of Object.entries(W))i.has(o)||t(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
3
+ Schema: ${JSON.stringify(k(f),null,2)}`)}async function H(e,t,a,i){let o=new Date,f=new Map;for(let d of t.plugins){let n=d.id,u=L(d),c=await e.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!c){let l=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:l,name:n,config:{},created_at:o,updated_at:o}).execute(),c=await e.selectFrom("corsair_integrations").selectAll().where("id","=",l).executeTakeFirst(),i(`[corsair:setup] Created integration: ${n}`)}let p=u?d.authConfig?.[u]?.integration??[]:[],y=u?d.authConfig?.[u]?.account??[]:[],s=u&&c?C({authType:u,integrationName:n,kek:t.kek,database:t.database,extraIntegrationFields:p}):void 0;if(c&&!c.dek&&s&&(await s.issue_new_dek(),i(`[corsair:setup] Issued integration DEK: ${n}`)),!c)continue;let r=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",a).where("integration_id","=",c.id).executeTakeFirst();if(!r){let l=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:l,tenant_id:a,integration_id:c.id,config:{},created_at:o,updated_at:o}).execute(),r=await e.selectFrom("corsair_accounts").selectAll().where("id","=",l).executeTakeFirst(),i(`[corsair:setup] Created account: ${n}`)}let g=u&&r?S({authType:u,integrationName:n,tenantId:a,kek:t.kek,database:t.database,extraAccountFields:y}):void 0;r&&!r.dek&&g&&(await g.issue_new_dek(),i(`[corsair:setup] Issued account DEK: ${n}`)),u&&s&&g&&f.set(n,{pluginId:n,authType:u,integration:s,account:g,integrationFields:[...w[u].integration,...p],accountFields:[...w[u].account,...y]})}return f}var P=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function J(e,t,a,i,o,f,d,n,u){let c=[],p=[];for(let s of o){if(P.has(s))continue;let r=m(a,`get_${s}`);if(!r)continue;let g=null;try{let l=await r();g=typeof l=="string"?l:null}catch{}g||c.push(s)}for(let s of f){if(P.has(s))continue;let r=m(i,`get_${s}`);if(!r)continue;let g=null;try{let l=await r();g=typeof l=="string"?l:null}catch{}g||p.push(s)}let y=c.length===0&&p.length===0;if(y)n(`[corsair:setup] '${e}' (${t}) is configured \u2713`);else{let s=[...c,...p];if(u==="cli"){let r=s.map(g=>`${g}=VALUE`).join(" ");n(`[corsair:setup] '${e}' (${t}) needs credentials. Run:
4
+ corsair setup --${e} ${r}`)}else{let r=[`[corsair:setup] '${e}' (${t}) needs credentials. Call:`];for(let g of c)r.push(` await corsair.keys.${e}.set_${g}(value)`);for(let g of p){let l=d==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(d)}).${e}`;r.push(` await ${l}.keys.set_${g}(value)`)}n(r.join(`
5
+ `))}}return y}async function z(e,t,a,i){let o=new Set;for(let f of e.values())await J(f.pluginId,f.authType,f.integration,f.account,f.integrationFields,f.accountFields,t,a,i)&&o.add(f.pluginId);return o}async function Q(e,t,a,i,o){if(!U(h)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let f=h,d=new Set(t.map(n=>n.id));for(let[n,u]of Object.entries(f)){if(!d.has(n))continue;if(!a.has(n)){i(`[corsair:setup] Skipping backfill for '${n}' \u2014 auth not configured.`);continue}let c=b(e)?e[n]:void 0,p=b(c)?c.api:void 0;if(p)for(let[y,s]of Object.entries(u))for(let[r,g]of Object.entries(s)){i(`[corsair:setup] Backfilling ${n} \u203A ${y}.${r}...`);try{let l=b(p)?p[y]:void 0;await m(l,r)?.(g)}catch(l){o(`[corsair:setup] ${n} \u203A ${y}.${r} failed: `+(l instanceof Error?l.message:String(l)))}}}}export{ie as a};
@@ -0,0 +1 @@
1
+ import{v7 as j}from"uuid";function g(){return j()}import{z as d}from"zod";import{sql as f}from"kysely";function m(e){return e.replace(/'/g,"''")}function k(e){let t=m(e);return f`data->>'${f.raw(t)}'`}function D(e){let t=m(e);return f`(data->>'${f.raw(t)}')::numeric`}function F(e){let t=m(e);return f`(data->>'${f.raw(t)}')::boolean`}function T(e){let t=m(e);return f`(data->>'${f.raw(t)}')::timestamptz`}function A(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function _(e){let t=e;for(;t;){if(t instanceof d.ZodOptional||t instanceof d.ZodNullable){t=t._def.innerType;continue}if(t instanceof d.ZodDefault){t=t._def.innerType;continue}break}return t}function R(e){let t=_(e);if(t instanceof d.ZodString)return"string";if(t instanceof d.ZodNumber)return"number";if(t instanceof d.ZodBoolean)return"boolean";if(t instanceof d.ZodDate)return"date"}function x(e){let t=_(e);if(!(t instanceof d.ZodObject))return{};let r=t.shape,n={};for(let[u,w]of Object.entries(r)){let s=R(w);s&&(n[u]=s)}return n}function B(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 Z(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 C(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 S(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[u,w]=n.between;u instanceof Date&&(e=e.where(t,">=",u)),w instanceof Date&&(e=e.where(t,"<=",w))}}return e}function I(e,t,r,n){return r==="number"?Z(e,D(t),n):r==="boolean"?C(e,F(t),n):r==="date"?S(e,T(t),n):B(e,k(t),n)}function W(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 Q(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function p(e,t,r){return e.selectFrom("corsair_entities").selectAll().where("account_id","=",t).where("entity_type","=",r)}function z(e,t,r,n,u){let w=x(u);function s(i){let o=A(i.data);return{...i,data:u.parse(o)}}return{findByEntityId:async i=>{let o=await t(),a=await p(e,o,r).where("entity_id","=",i).executeTakeFirst();return a?s(a):null},findById:async i=>{let o=await t(),a=await p(e,o,r).where("id","=",i).executeTakeFirst();return a?s(a):null},findManyByEntityIds:async i=>{if(i.length===0)return[];let o=await t();return(await p(e,o,r).where("entity_id","in",i).execute()).map(s)},list:async i=>{let o=await t(),a=p(e,o,r);return typeof i?.limit=="number"&&(a=a.limit(i.limit)),typeof i?.offset=="number"&&(a=a.offset(i.offset)),(await a.execute()).map(s)},search:async i=>{let o=await t(),a=p(e,o,r),l=new Set(["data","limit","offset"]);for(let[c,y]of Object.entries(i))l.has(c)||y===void 0||(a=W(a,c,y));if(i.data&&typeof i.data=="object")for(let[c,y]of Object.entries(i.data)){if(y===void 0)continue;let b=w[c]??"string";a=I(a,c,b,y)}return typeof i.limit=="number"&&(a=a.limit(i.limit)),typeof i.offset=="number"&&(a=a.offset(i.offset)),(await a.execute()).map(s)},upsertByEntityId:async(i,o)=>{let a=await t(),l=u.parse(o),h=new Date,c=await p(e,a,r).select("id").where("entity_id","=",i).executeTakeFirst();if(c?.id){await e.updateTable("corsair_entities").set({version:n,data:l,updated_at:h}).where("id","=",c.id).execute();let E=await e.selectFrom("corsair_entities").selectAll().where("id","=",c.id).executeTakeFirst();return s(E)}let y=g();await e.insertInto("corsair_entities").values({id:y,created_at:h,updated_at:h,account_id:a,entity_id:i,entity_type:r,version:n,data:l}).execute();let b=await e.selectFrom("corsair_entities").selectAll().where("id","=",y).executeTakeFirst();return s(b)},deleteById:async i=>{let o=await t(),a=await e.deleteFrom("corsair_entities").where("account_id","=",o).where("entity_type","=",r).where("id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0},deleteByEntityId:async i=>{let o=await t(),a=await e.deleteFrom("corsair_entities").where("account_id","=",o).where("entity_type","=",r).where("entity_id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0},count:async()=>{let i=await t(),o=await e.selectFrom("corsair_entities").select(a=>a.fn.countAll().as("count")).where("account_id","=",i).where("entity_type","=",r).executeTakeFirst();return Q(o?.count)}}}export{g as a,z as b};
@@ -1 +1 @@
1
- import{a as h,b}from"./chunk-2PB34FTK.js";import{a as E,b as I,c as x,d as D}from"./chunk-HO245J34.js";var k={corsair_integrations:E,corsair_accounts:I,corsair_entities:x,corsair_events:D};function F(t){return k[t]}function _(t){if(typeof t=="string")try{return JSON.parse(t)}catch{return t}return t}function d(t){if(!t)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function g(t){if(!t)return[];let n=[];for(let r in t){let e=r,i=t[e];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let s=i;"in"in s&&Array.isArray(s.in)?n.push({field:e,operator:"in",value:s.in}):"like"in s&&typeof s.like=="string"&&n.push({field:e,operator:"like",value:s.like})}else n.push({field:e,value:i})}return n}function p(t,n){if(!n?.length)return t;let r=t;for(let e of n){let i=e.operator??"=";r=r.where(e.field,i,e.value)}return r}function S(t){return typeof t=="number"?t:typeof t=="bigint"?Number(t):Number.parseInt(String(t??0),10)}function T(t,n){let r=F(n),e=()=>(d(t),t),i=()=>e().db.selectFrom(n),s=()=>e().db.insertInto(n),u=()=>e().db.updateTable(n),c=()=>e().db.deleteFrom(n);function m(o){let a={};for(let[l,y]of Object.entries(o))a[l]=_(y);return r.parse(a)}function C(o){let a={};for(let[l,y]of Object.entries(o))a[l]=_(y);return r.parse(a)}return{findById:async o=>{d(t);let a=i().selectAll();a=p(a,[{field:"id",value:o}]);let l=await a.executeTakeFirst();return l?m(l):null},findOne:async o=>{d(t);let a=i().selectAll();a=p(a,g(o));let l=await a.executeTakeFirst();return l?m(l):null},findMany:async o=>{d(t);let a=i().selectAll();return a=p(a,g(o?.where)),typeof o?.limit=="number"&&(a=a.limit(o.limit)),typeof o?.offset=="number"&&(a=a.offset(o.offset)),(await a.execute()).map(y=>m(y))},create:async o=>{d(t);let a=new Date,l={id:o.id??h(),created_at:a,updated_at:a,...o},y=await s().values(l).returningAll().executeTakeFirst();return y?m(y):C(l)},update:async(o,a)=>{d(t);let l={...a,updated_at:new Date},y=u().set(l).returningAll();y=p(y,[{field:"id",value:o}]);let f=await y.executeTakeFirst();return f?m(f):null},updateMany:async(o,a)=>{d(t);let l={...a,updated_at:new Date},y=i().select("id");y=p(y,g(o));let f=await y.execute();for(let P of f){let w=u().set(l);w=p(w,[{field:"id",value:P.id}]),await w.execute()}return f.length},delete:async o=>{d(t);let a=c();a=p(a,[{field:"id",value:o}]);let l=await a.executeTakeFirst();return Number(l?.numDeletedRows??0)>0},deleteMany:async o=>{d(t);let a=c();a=p(a,g(o));let l=await a.executeTakeFirst();return Number(l?.numDeletedRows??0)},count:async o=>{d(t);let a=i().select(y=>y.fn.countAll().as("count"));a=p(a,g(o));let l=await a.executeTakeFirst();return S(l?.count)}}}function R(t){let n=T(t,"corsair_integrations");return{...n,findByName:r=>n.findOne({name:r}),upsertByName:async(r,e)=>{let i=await n.findOne({name:r});return i?await n.update(i.id,e):n.create({...e,name:r})}}}function O(t){let n=T(t,"corsair_accounts");return{...n,findByTenantAndIntegration:async(r,e)=>{d(t);let i=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",e).executeTakeFirst();return i?n.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,e)=>n.findMany({where:{tenant_id:r},limit:e?.limit,offset:e?.offset}),upsertByTenantAndIntegration:async(r,e,i)=>{let s=await n.findOne({tenant_id:r,integration_id:e});return s?await n.update(s.id,i):n.create({...i,tenant_id:r,integration_id:e})}}}function v(t){let n=T(t,"corsair_entities");return{...n,findByEntityId:({accountId:r,entityType:e,entityId:i})=>n.findOne({account_id:r,entity_type:e,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:e,entityIds:i})=>i.length===0?[]:(d(t),await t.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",e).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:e,limit:i,offset:s})=>n.findMany({where:{account_id:r,entity_type:e},limit:i,offset:s}),searchByEntityId:async({accountId:r,entityType:e,query:i,limit:s,offset:u})=>{d(t);let c=t.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",e).where("entity_id","like",`%${i}%`);return typeof s=="number"&&(c=c.limit(s)),typeof u=="number"&&(c=c.offset(u)),await c.execute()},upsertByEntityId:async({accountId:r,entityType:e,entityId:i,version:s,data:u})=>{let c=await n.findOne({account_id:r,entity_type:e,entity_id:i});return c?await n.update(c.id,{version:s,data:u}):n.create({account_id:r,entity_type:e,entity_id:i,version:s,data:u})},deleteByEntityId:async({accountId:r,entityType:e,entityId:i})=>{d(t);let s=await t.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",e).where("entity_id","=",i).executeTakeFirst();return Number(s.numDeletedRows)>0}}}function N(t){let n=T(t,"corsair_events");return{...n,listByAccount:(r,e)=>n.findMany({where:{account_id:r},limit:e?.limit,offset:e?.offset}),listByStatus:(r,e)=>{let i={status:r};return e?.accountId&&(i.account_id=e.accountId),n.findMany({where:i,limit:e?.limit,offset:e?.offset})},listPending:r=>{let e={status:"pending"};return r?.accountId&&(e.account_id=r.accountId),n.findMany({where:e,limit:r?.limit??100})},updateStatus:(r,e)=>n.update(r,{status:e})}}function A(t){return{integrations:R(t),accounts:O(t),entities:v(t),events:N(t)}}function W(t,n,r,e,i){let s=null;async function u(){if(s!==null)return s;d(t);let c=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",n.integrationName).executeTakeFirst();if(!c)throw new Error(`Integration "${n.integrationName}" not found. Make sure to create the integration first.`);let m=await t.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n.tenantId).where("integration_id","=",c.id).executeTakeFirst();if(!m)throw new Error(`Account not found for tenant "${n.tenantId}" and integration "${n.integrationName}". Make sure to create the account first.`);return s=m.id,s}return d(t),b(t.db,u,r,e,i)}function B(t){let{database:n,integrationName:r,schema:e,tenantId:i}=t,s=A(n),u={tenantId:i,integrationName:r},c=null;async function m(){if(c!==null)return c;d(n);let o=await n.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!o)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);let a=await n.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",i).where("integration_id","=",o.id).executeTakeFirst();if(!a)throw new Error(`Account not found for tenant "${i}" and integration "${r}". Make sure to create the account first.`);return c=a.id,c}let C={};for(let[o,a]of Object.entries(e.entities))C[o]=W(n,u,o,e.version,a);return{...C,$orm:s,$integrationName:r,$tenantId:i,$getAccountId:m}}function U(t,n){let r=A(t);return{$tenantId:n,$orm:r,listAccounts:e=>r.accounts.listByTenant(n,e),findAccountByIntegration:e=>r.accounts.findByTenantAndIntegration(n,e),listEntities:async e=>{d(t);let i=await t.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let s=i.map(c=>c.id),u=t.db.selectFrom("corsair_entities").selectAll().where("account_id","in",s);return e?.entityType&&(u=u.where("entity_type","=",e.entityType)),typeof e?.limit=="number"&&(u=u.limit(e.limit)),typeof e?.offset=="number"&&(u=u.offset(e.offset)),await u.execute()},listEvents:async e=>{d(t);let i=await t.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let s=i.map(c=>c.id),u=t.db.selectFrom("corsair_events").selectAll().where("account_id","in",s);return e?.status&&(u=u.where("status","=",e.status)),typeof e?.limit=="number"&&(u=u.limit(e.limit)),typeof e?.offset=="number"&&(u=u.offset(e.offset)),await u.execute()},forIntegration:e=>B({database:t,integrationName:e.integrationName,schema:e.schema,tenantId:n})}}function Z(t,n){return{forTenant:r=>B({database:t,integrationName:n.integrationName,schema:n.schema,tenantId:r})}}export{k as a,A as b,B as c,U as d,Z as e};
1
+ import{a as h,b}from"./chunk-OZHME3EO.js";import{a as E,b as I,c as x,d as D}from"./chunk-3USHGH6P.js";var k={corsair_integrations:E,corsair_accounts:I,corsair_entities:x,corsair_events:D};function F(t){return k[t]}function _(t){if(typeof t=="string")try{return JSON.parse(t)}catch{return t}return t}function d(t){if(!t)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function g(t){if(!t)return[];let n=[];for(let r in t){let e=r,i=t[e];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let s=i;"in"in s&&Array.isArray(s.in)?n.push({field:e,operator:"in",value:s.in}):"like"in s&&typeof s.like=="string"&&n.push({field:e,operator:"like",value:s.like})}else n.push({field:e,value:i})}return n}function p(t,n){if(!n?.length)return t;let r=t;for(let e of n){let i=e.operator??"=";r=r.where(e.field,i,e.value)}return r}function S(t){return typeof t=="number"?t:typeof t=="bigint"?Number(t):Number.parseInt(String(t??0),10)}function T(t,n){let r=F(n),e=()=>(d(t),t),i=()=>e().db.selectFrom(n),s=()=>e().db.insertInto(n),u=()=>e().db.updateTable(n),c=()=>e().db.deleteFrom(n);function m(o){let a={};for(let[l,y]of Object.entries(o))a[l]=_(y);return r.parse(a)}function C(o){let a={};for(let[l,y]of Object.entries(o))a[l]=_(y);return r.parse(a)}return{findById:async o=>{d(t);let a=i().selectAll();a=p(a,[{field:"id",value:o}]);let l=await a.executeTakeFirst();return l?m(l):null},findOne:async o=>{d(t);let a=i().selectAll();a=p(a,g(o));let l=await a.executeTakeFirst();return l?m(l):null},findMany:async o=>{d(t);let a=i().selectAll();return a=p(a,g(o?.where)),typeof o?.limit=="number"&&(a=a.limit(o.limit)),typeof o?.offset=="number"&&(a=a.offset(o.offset)),(await a.execute()).map(y=>m(y))},create:async o=>{d(t);let a=new Date,l={id:o.id??h(),created_at:a,updated_at:a,...o},y=await s().values(l).returningAll().executeTakeFirst();return y?m(y):C(l)},update:async(o,a)=>{d(t);let l={...a,updated_at:new Date},y=u().set(l).returningAll();y=p(y,[{field:"id",value:o}]);let f=await y.executeTakeFirst();return f?m(f):null},updateMany:async(o,a)=>{d(t);let l={...a,updated_at:new Date},y=i().select("id");y=p(y,g(o));let f=await y.execute();for(let P of f){let w=u().set(l);w=p(w,[{field:"id",value:P.id}]),await w.execute()}return f.length},delete:async o=>{d(t);let a=c();a=p(a,[{field:"id",value:o}]);let l=await a.executeTakeFirst();return Number(l?.numDeletedRows??0)>0},deleteMany:async o=>{d(t);let a=c();a=p(a,g(o));let l=await a.executeTakeFirst();return Number(l?.numDeletedRows??0)},count:async o=>{d(t);let a=i().select(y=>y.fn.countAll().as("count"));a=p(a,g(o));let l=await a.executeTakeFirst();return S(l?.count)}}}function R(t){let n=T(t,"corsair_integrations");return{...n,findByName:r=>n.findOne({name:r}),upsertByName:async(r,e)=>{let i=await n.findOne({name:r});return i?await n.update(i.id,e):n.create({...e,name:r})}}}function O(t){let n=T(t,"corsair_accounts");return{...n,findByTenantAndIntegration:async(r,e)=>{d(t);let i=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",e).executeTakeFirst();return i?n.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,e)=>n.findMany({where:{tenant_id:r},limit:e?.limit,offset:e?.offset}),upsertByTenantAndIntegration:async(r,e,i)=>{let s=await n.findOne({tenant_id:r,integration_id:e});return s?await n.update(s.id,i):n.create({...i,tenant_id:r,integration_id:e})}}}function v(t){let n=T(t,"corsair_entities");return{...n,findByEntityId:({accountId:r,entityType:e,entityId:i})=>n.findOne({account_id:r,entity_type:e,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:e,entityIds:i})=>i.length===0?[]:(d(t),await t.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",e).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:e,limit:i,offset:s})=>n.findMany({where:{account_id:r,entity_type:e},limit:i,offset:s}),searchByEntityId:async({accountId:r,entityType:e,query:i,limit:s,offset:u})=>{d(t);let c=t.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",e).where("entity_id","like",`%${i}%`);return typeof s=="number"&&(c=c.limit(s)),typeof u=="number"&&(c=c.offset(u)),await c.execute()},upsertByEntityId:async({accountId:r,entityType:e,entityId:i,version:s,data:u})=>{let c=await n.findOne({account_id:r,entity_type:e,entity_id:i});return c?await n.update(c.id,{version:s,data:u}):n.create({account_id:r,entity_type:e,entity_id:i,version:s,data:u})},deleteByEntityId:async({accountId:r,entityType:e,entityId:i})=>{d(t);let s=await t.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",e).where("entity_id","=",i).executeTakeFirst();return Number(s.numDeletedRows)>0}}}function N(t){let n=T(t,"corsair_events");return{...n,listByAccount:(r,e)=>n.findMany({where:{account_id:r},limit:e?.limit,offset:e?.offset}),listByStatus:(r,e)=>{let i={status:r};return e?.accountId&&(i.account_id=e.accountId),n.findMany({where:i,limit:e?.limit,offset:e?.offset})},listPending:r=>{let e={status:"pending"};return r?.accountId&&(e.account_id=r.accountId),n.findMany({where:e,limit:r?.limit??100})},updateStatus:(r,e)=>n.update(r,{status:e})}}function A(t){return{integrations:R(t),accounts:O(t),entities:v(t),events:N(t)}}function W(t,n,r,e,i){let s=null;async function u(){if(s!==null)return s;d(t);let c=await t.db.selectFrom("corsair_integrations").selectAll().where("name","=",n.integrationName).executeTakeFirst();if(!c)throw new Error(`Integration "${n.integrationName}" not found. Make sure to create the integration first.`);let m=await t.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n.tenantId).where("integration_id","=",c.id).executeTakeFirst();if(!m)throw new Error(`Account not found for tenant "${n.tenantId}" and integration "${n.integrationName}". Make sure to create the account first.`);return s=m.id,s}return d(t),b(t.db,u,r,e,i)}function B(t){let{database:n,integrationName:r,schema:e,tenantId:i}=t,s=A(n),u={tenantId:i,integrationName:r},c=null;async function m(){if(c!==null)return c;d(n);let o=await n.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!o)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);let a=await n.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",i).where("integration_id","=",o.id).executeTakeFirst();if(!a)throw new Error(`Account not found for tenant "${i}" and integration "${r}". Make sure to create the account first.`);return c=a.id,c}let C={};for(let[o,a]of Object.entries(e.entities))C[o]=W(n,u,o,e.version,a);return{...C,$orm:s,$integrationName:r,$tenantId:i,$getAccountId:m}}function q(t,n){let r=A(t);return{$tenantId:n,$orm:r,listAccounts:e=>r.accounts.listByTenant(n,e),findAccountByIntegration:e=>r.accounts.findByTenantAndIntegration(n,e),listEntities:async e=>{d(t);let i=await t.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let s=i.map(c=>c.id),u=t.db.selectFrom("corsair_entities").selectAll().where("account_id","in",s);return e?.entityType&&(u=u.where("entity_type","=",e.entityType)),typeof e?.limit=="number"&&(u=u.limit(e.limit)),typeof e?.offset=="number"&&(u=u.offset(e.offset)),await u.execute()},listEvents:async e=>{d(t);let i=await t.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let s=i.map(c=>c.id),u=t.db.selectFrom("corsair_events").selectAll().where("account_id","in",s);return e?.status&&(u=u.where("status","=",e.status)),typeof e?.limit=="number"&&(u=u.limit(e.limit)),typeof e?.offset=="number"&&(u=u.offset(e.offset)),await u.execute()},forIntegration:e=>B({database:t,integrationName:e.integrationName,schema:e.schema,tenantId:n})}}function K(t,n){return{forTenant:r=>B({database:t,integrationName:n.integrationName,schema:n.schema,tenantId:r})}}export{k as a,A as b,B as c,q as d,K as e};
@@ -0,0 +1,26 @@
1
+ import{a as be,b as te}from"./chunk-OZHME3EO.js";import{a as ke}from"./chunk-ZGVIF3UY.js";import{createCipheriv as we,createDecipheriv as Te,randomBytes as G,scrypt as He}from"crypto";import{promisify as Ue}from"util";var Ce=Ue(He),J="aes-256-gcm",Pe=12,V=16,qe=16,H=32;function K(){return G(H).toString("base64")}async function M(e,t){let n=G(qe),r=await Ce(t,n,H),o=G(Pe),i=we(J,r,o,{authTagLength:V}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[n.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function O(e,t){let[n,r,o,i]=e.split(":");if(!n||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(n,"base64"),a=Buffer.from(r,"base64"),d=Buffer.from(o,"base64"),c=Buffer.from(i,"base64"),l=await Ce(t,s,H),p=Te(J,l,a,{authTagLength:V});return p.setAuthTag(d),Buffer.concat([p.update(c),p.final()]).toString("utf8")}function oe(e,t){let n=Buffer.from(t,"base64"),r=G(Pe),o=we(J,n,r,{authTagLength:V}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function re(e,t){let[n,r,o]=e.split(":");if(!n||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(t,"base64"),s=Buffer.from(n,"base64"),a=Buffer.from(r,"base64"),d=Buffer.from(o,"base64"),c=Te(J,i,s,{authTagLength:V});return c.setAuthTag(a),Buffer.concat([c.update(d),c.final()]).toString("utf8")}function Z(e,t){let n={};for(let[r,o]of Object.entries(e))n[r]=oe(o,t);return n}function S(e,t){let n={};for(let[r,o]of Object.entries(e))n[r]=re(o,t);return n}function U(e,t,n){let r=S(e,t);return Z(r,n)}function Y(e,t){let n=[];e||n.push("database"),t||n.push("kek");let r={};return new Proxy(r,{get(o,i){let s=n.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${n.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
2
+
3
+ To generate a KEK, run: openssl rand -base64 ${H}`)}})}var q={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"]}};function xe(e,t,n){let r={};for(let o of n)r[`get_${o}`]=async()=>(await e())[o]??null,r[`set_${o}`]=async i=>{let s=[null,void 0,""].includes(i)?null:i;await t({[o]:s})};return r}var ie=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function Q(e){let{authType:t,integrationName:n,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...q[t].integration,...i],a=null,d={kek:r,integrationName:n,getIntegration:async()=>{if(a)return a;let u=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!u)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);return a={id:u.id,config:ie(u.config),dek:u.dek??null},a},updateIntegration:async u=>{let f=await d.getIntegration();await o.db.updateTable("corsair_integrations").set({...u.config!==void 0?{config:u.config}:{},...u.dek!==void 0?{dek:u.dek}:{},updated_at:new Date}).where("id","=",f.id).execute(),a=null}},c=null,l=async()=>{if(c)return c;let u=await d.getIntegration();if(!u.dek)throw new Error(`No DEK found for integration "${n}". Initialize the integration first.`);return c=await O(u.dek,r),c},p=async()=>{let u=await d.getIntegration(),f=await l(),m=u.config;return!m||Object.keys(m).length===0?{}:S(m,f)};return{get_dek:l,issue_new_dek:async()=>{let u=await d.getIntegration(),f=K(),m={};if(u.dek){let P=await O(u.dek,r),b=u.config;b&&Object.keys(b).length>0&&(m=U(b,P,f))}let k=await M(f,r);return await d.updateIntegration({config:m,dek:k}),c=f,f},...xe(p,async u=>{let f=await l(),m;try{m=await p()}catch(b){console.error(`[corsair] Failed to decrypt config for integration "${n}", starting fresh:`,b),m={}}let k={...m};for(let[b,y]of Object.entries(u))y===null?delete k[b]:k[b]=y;let P=Z(k,f);await d.updateIntegration({config:P})},s)}}function X(e){let{authType:t,integrationName:n,tenantId:r,kek:o,database:i,extraAccountFields:s=[]}=e,a=[...q[t].account,...s],d=null,c=null,l=async()=>{if(c)return c;let y=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!y)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);return c={id:y.id,config:ie(y.config),dek:y.dek??null},c},p={kek:o,integrationName:n,tenantId:r,getIntegration:l,getAccount:async()=>{if(d)return d;let y=await l(),w=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",y.id).executeTakeFirst();if(!w)throw new Error(`Account not found for tenant "${r}" and integration "${n}". Make sure to create the account first.`);return d={id:w.id,config:ie(w.config),dek:w.dek??null},d},updateAccount:async y=>{let w=await p.getAccount();await i.db.updateTable("corsair_accounts").set({...y.config!==void 0?{config:y.config}:{},...y.dek!==void 0?{dek:y.dek}:{},updated_at:new Date}).where("id","=",w.id).execute(),d=null}},h=null,g=null,u=async()=>{if(h)return h;let y=await p.getAccount();if(!y.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${n}"). Initialize the account first.`);return h=await O(y.dek,o),h},f=async()=>{if(g)return g;let y=await p.getIntegration();if(!y.dek)throw new Error(`No DEK found for integration "${n}". Initialize the integration first.`);return g=await O(y.dek,o),g},m=async()=>{let y=await p.getAccount(),w=await u(),T=y.config;return!T||Object.keys(T).length===0?{}:S(T,w)},k=async()=>{let y=await p.getIntegration(),w=await f(),T=y.config;return!T||Object.keys(T).length===0?{}:S(T,w)},b={get_dek:u,issue_new_dek:async()=>{let y=await p.getAccount(),w=K(),T={};if(y.dek){let C=await O(y.dek,o),A=y.config;A&&Object.keys(A).length>0&&(T=U(A,C,w))}let I=await M(w,o);return await p.updateAccount({config:T,dek:I}),h=w,w},...xe(m,async y=>{let w=await u(),T;try{T=await m()}catch(A){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${n}"), starting fresh:`,A),T={}}let I={...T};for(let[A,E]of Object.entries(y))E===null?delete I[A]:I[A]=E;let C=Z(I,w);await p.updateAccount({config:C})},a)};return t==="oauth_2"&&(b.get_integration_credentials=async()=>{let y=await k();return{client_id:y.client_id||null,client_secret:y.client_secret||null,redirect_url:y.redirect_url??null}}),b}async function Ae(e,t,n){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!r)throw new Error(`Integration "${t}" not found.`);let o=K(),i=await M(o,n);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function Ee(e,t,n,r){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!o)throw new Error(`Integration "${t}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${n}" and integration "${t}".`);let s=K(),a=await M(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var ze=async(e,t)=>(console.error(`[corsair:${t.pluginId}:${t.operation}]`,{error:e.message,input:t.input}),{maxRetries:0});async function Re(e,t,n,r,o){let i={pluginId:t,operation:n,input:r,originalError:e},s=Object.keys(o).find(c=>o[c]?.match(e,i));return await(o[s||"DEFAULT"]?.handler||ze)(e,i)}import{randomBytes as Ge}from"crypto";import{v4 as Je}from"uuid";var Ve={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 Ye(e,t,n){return n!==void 0?n:Ve[t][e]}function De(e){let t=/(\d+)(d|h|m|s)/g,n=0,r;for(;(r=t.exec(e))!==null;){let o=parseInt(r[1],10);switch(r[2]){case"d":n+=o*864e5;break;case"h":n+=o*36e5;break;case"m":n+=o*6e4;break;case"s":n+=o*1e3;break}}return n>0?n:600*1e3}function _e(e){return{async find_by_permission_id(t){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("id","=",t).executeTakeFirst()},async find_by_token(t){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("token","=",t).executeTakeFirst()},async set_executing(t){e&&await e.db.updateTable("corsair_permissions").set({status:"executing",updated_at:new Date}).where("id","=",t).execute()},async set_completed(t){e&&await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",t).execute()}}}async function Ie(e,t,n){let r=Date.now()+n;for(;Date.now()<r;){let o=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",t).executeTakeFirst();if(!o)return{result:"blocked",reason:"pending"};if(o.status==="approved")return{result:"allow",onComplete:async()=>{await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",t).execute()}};if(o.status==="denied")return{result:"blocked",reason:"denied"};if(o.status==="expired"||o.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(i=>setTimeout(i,500))}return{result:"blocked",reason:"timeout"}}async function ve(e){let t=Ye(e.riskLevel,e.mode,e.override);if(t==="allow")return{result:"allow"};let n=e.meta?.irreversible?" (irreversible)":"",r=e.meta?.description?`${e.meta.description}${n}`:`${e.pluginId}.${e.endpointPath}${n}`;if(t==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
4
+ Action: ${r}`,`
5
+ To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let o=JSON.stringify(e.args),i=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","=",o).where("tenant_id","=",s).where("expires_at",">",i).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(a){if(a.status==="approved"){let u=e.db,f=a.id;return{result:"allow",onComplete:async()=>{await u.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.`,`
6
+ Action: ${r}`,`
7
+ Permission ID: ${a.id}`,`
8
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ie(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token})}let d=Je(),c=Ge(32).toString("hex"),l=e.timeoutMs??600*1e3,p=new Date(Date.now()+l).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:d,created_at:new Date,updated_at:new Date,token:c,plugin:e.pluginId,endpoint:e.endpointPath,args:o,tenant_id:s,status:"pending",expires_at:p}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
9
+ Action: ${r}`,`
10
+ Permission ID: ${d}`,`
11
+ Permission token: ${c}`,`
12
+ Expires at: ${p}`,`
13
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ie(e.db,d,l):{result:"blocked",reason:"pending",id:d,token:c}}function Qe(e){return typeof e=="function"}function se({endpoints:e,hooks:t,ctx:n,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}){for(let[g,u]of Object.entries(e)){let f=t?.[g];if(Qe(u)){let m=f,k=[...s,g].join("."),P=async(b={})=>{let y;if(d){let E=c?.[k],{result:B,reason:v,onComplete:W,token:F,id:$}=await ve({pluginId:o,endpointPath:k,args:b,mode:d.mode,override:d.overrides?.[k],riskLevel:E?.riskLevel??"write",meta:E,db:l,timeoutMs:p?De(p.timeout):void 0,tenantId:h,approvalMode:p?.mode});if(B==="blocked"){let x;throw v==="denied"?x=`Action '${k}' was denied by the user. Await further instructions before proceeding.`:v==="policy"?x=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`:v==="timeout"?x=`Action '${k}' timed out waiting for approval.`:p?.formatAsyncMessage&&F&&$?x=p.formatAsyncMessage({token:F,id:$,plugin:o,endpoint:k,args:b}):x=`Action '${k}' requires user approval before it can run.`,new Error(x)}y=W}let w=async(E,B,v)=>{try{return await u(B,v)}catch(W){if(W instanceof Error){let F=await Re(W,o,k,typeof v=="object"&&v!==null?v:{args:v},i);if(E<(F.maxRetries||0)){let $=E+1;console.log(`Retrying (${$} / ${F.maxRetries})...`);let x;if(F.headersRetryAfterMs)x=F.headersRetryAfterMs;else switch(F.retryStrategy){case"exponential_backoff":x=Math.pow(2,$-1)*1e3;break;case"exponential_backoff_jitter":let ne=Math.pow(2,$-1)*1e3,We=(Math.random()-.5)*1e3;x=Math.max(0,ne+We);break;case"linear_1s":x=1e3;break;case"linear_2s":x=2e3;break;case"linear_3s":x=3e3;break;case"linear_4s":x=4e3;break;default:x=1e3;break}await new Promise(ne=>setTimeout(ne,x)),await w($,B,v),console.log(`[corsair:${o}:${k}] Retry strategy:`,F)}}throw W}},T=a?await a(n,"endpoint"):void 0;if(!m?.before&&!m?.after){let E=await w(0,{...n,key:T},b);return await y?.(),E}let I={...n,key:T},C=m.before?await m.before(I,b):{ctx:I,args:b,continue:!0,passToAfter:void 0};if(C.continue===!1)return;let A=await w(0,C.ctx,C.args);return await m.after?.(C.ctx,A,C.passToAfter),await y?.(),A};r[g]=P}else if(u&&typeof u=="object"){let m={};se({endpoints:u,hooks:f,ctx:n,tree:m,pluginId:o,errorHandlers:i,currentPath:[...s,g],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}),r[g]=m}}}function Xe(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function ae({webhooks:e,hooks:t,ctx:n,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=t?.[i];if(Xe(s)){let d=a,c=async l=>{let p=(g,u)=>s.handler(g,u),h=o?await o(n,"webhook"):void 0;return!d?.before&&!d?.after?p({...n,key:h},l):(async()=>{let g={...n,key:h},u=d.before?await d.before(g,l):{ctx:g,args:l,continue:!0,passToAfter:void 0};if(u.continue===!1)return;let f=await p(u.ctx,u.args);return f?.success===!0&&await d.after?.(u.ctx,f,u.passToAfter),f})()};r[i]={match:s.match,handler:c}}else if(s&&typeof s=="object"){let d={};ae({webhooks:s,hooks:a,ctx:n,webhooksTree:d,keyBuilder:o}),r[i]=d}}}function en(e,t,n){let r=null;return async()=>{if(r)return r;if(!e)throw new Error("Database not configured");let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!o)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${n}" and integration "${t}". Make sure to create the account first.`);return r=i.id,r}}function nn(e,t,n,r,o){return e?te(e.db,t,n,r,o):{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 ce(e,t){let{database:n,tenantId:r,kek:o,rootErrorHandlers:i,approvalConfig:s}=t,a={},d={};for(let c of e)a[c.id]={},d[c.id]={};for(let c of e){let l=c.schema,p=r??"default",h=en(n,c.id,p);if(l?.entities){let C={};for(let[A,E]of Object.entries(l.entities)){let B=n?te(n.db,h,A,l.version,E):nn(void 0,h,A,l.version,E);C[A]=B}d[c.id].db=C,a[c.id].db=C}let g=c.options,u=c.authConfig,f;if(n&&o&&g?.authType){let C=u?.[g.authType]?.account??[];f=X({authType:g.authType,integrationName:c.id,tenantId:p,kek:o,database:n,extraAccountFields:C}),a[c.id].keys=f}let m={database:n,db:d[c.id]?.db??{},$getAccountId:h,...c.options?{options:c.options}:{},...f?{keys:f,authType:g?.authType}:{},...r?{tenantId:r}:{}},k=c.endpoints??{},P=c.hooks,b={...i,...c.errorHandlers},y={},w=c.options?.permissions;se({endpoints:k,hooks:P,ctx:m,tree:y,pluginId:c.id,errorHandlers:b,currentPath:[],keyBuilder:c.keyBuilder,permissionsConfig:w,endpointMeta:c.endpointMeta,database:n,approvalConfig:s,tenantId:r}),Object.keys(y).length>0&&(a[c.id].api=y),m.endpoints=y;let T=c.webhooks??{},I=c.webhookHooks;if(Object.keys(T).length>0){let C={};ae({webhooks:T,hooks:I,ctx:m,webhooksTree:C,keyBuilder:c.keyBuilder}),a[c.id].webhooks=C,c.pluginWebhookMatcher&&(a[c.id].pluginWebhookMatcher=c.pluginWebhookMatcher)}}return a}function Fe(e,t,n){let r={};for(let o of e){let i=o.options,s=o.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],d=Q({authType:i.authType,integrationName:o.id,kek:n,database:t,extraIntegrationFields:a});r[o.id]=d}}return r}async function Oe(e,t,n,r,o="pending"){if(!e)return null;try{let i=be(),s=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:s,updated_at:s,account_id:t,event_type:n,payload:r,status:o}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function tn(e,t,n,r="pending"){try{let o=await e.$getAccountId();return Oe(e.database,o,t,n,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as $e from"https";import*as Ke from"querystring";function Me(e,t,n,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,d)=>{let c={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(c.client_id=t,c.client_secret=n);let l=Ke.stringify(c),p={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(l).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${t}:${n}`).toString("base64")}`);let h=$e.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},g=>{let u="";g.on("data",f=>{u+=f}),g.on("end",()=>{if(g.statusCode!==200){d(new Error(`Token exchange failed (${g.statusCode}): ${u}`));return}try{a(JSON.parse(u))}catch{d(new Error(`Token endpoint returned non-JSON response: ${u}`))}})});h.on("error",g=>d(new Error(`Request failed: ${g.message}`))),h.write(l),h.end()})}var Se=["ably","airtable","amplitude","asana","box","cal","calendly","cloudflare","cursor","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","github","gitlab","gmail","googlecalendar","googledrive","googlesheets","hackernews","hubspot","intercom","jira","linear","monday","notion","onedrive","openweathermap","oura","outlook","pagerduty","posthog","razorpay","reddit","resend","sentry","sharepoint","slack","spotify","strava","stripe","tavily","teams","telegram","todoist","trello","twitter","twitterapiio","typeform","vapi","youtube","zoom"];var Ne=" ";function D(e){return e._def}function _(e){let t=e.typeName;if(t)return t;let n=e.type;if(n)return`Zod${n.charAt(0).toUpperCase()}${n.slice(1)}`}function L(e){return e.innerType}function on(e){return e.element??e.type}function ee(e,t){let n=t.shape??e.shape;return typeof n=="function"?n():n}function R(e){let t=D(e),n=_(t);switch(n){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(t.value);case"ZodEnum":return t.values.map(r=>String(r)).join(" | ");case"ZodOptional":return R(L(t));case"ZodNullable":return`${R(L(t))} | null`;case"ZodArray":{let r=on(t),o=D(r),i=_(o)==="ZodUnion",s=R(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=ee(e,t),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let d=_(D(a));return`${d==="ZodOptional"||d==="ZodNullable"?s+"?":s}: ${R(a)}`}).join(", ")} }`}case"ZodUnion":return t.options.map(R).join(" | ");case"ZodIntersection":return`${R(t.left)} & ${R(t.right)}`;default:return(n??"unknown").replace("Zod","").toLowerCase()}}function z(e,t){let n=D(e),r=_(n);if(r==="ZodOptional")return z(L(n),t);if(r!=="ZodObject")return R(e);let o=ee(e,n),i=Object.entries(o);if(i.length===0)return"{}";let s=Ne.repeat(t+1),a=Ne.repeat(t),d=[];for(let[c,l]of i){let p=D(l),h=_(p),u=h==="ZodOptional"||h==="ZodNullable"?`${c}?`:c,f=h==="ZodOptional"||h==="ZodNullable"?p.innerType:l,m=D(f),k=_(m),P=m?.description,b=P?` // ${P}`:"";k==="ZodObject"?d.push(`${s}${u}: ${z(f,t+1)}${b}`):d.push(`${s}${u}: ${R(l)}${b}`)}return`{
14
+ ${d.join(`
15
+ `)}
16
+ ${a}}`}var fe=["equals","contains","startsWith","endsWith","in"],rn=["equals","gt","gte","lt","lte","in"],sn=["equals"],an=["equals","before","after","between"];function Ze(e){let t=D(e);switch(_(t)){case"ZodOptional":case"ZodNullable":case"ZodDefault":return Ze(L(t));case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function ye(e){let t=D(e),n=_(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")return ye(L(t));if(n!=="ZodObject")return{};let r=ee(e,t),o={};for(let[i,s]of Object.entries(r)){let a=Ze(s);a==="string"?o[i]={type:"string",operators:fe}:a==="number"?o[i]={type:"number",operators:rn}:a==="boolean"?o[i]={type:"boolean",operators:sn}:a==="date"&&(o[i]={type:"date",operators:an})}return o}function je(e,t){for(let[n,r]of Object.entries(e))if(n.toLowerCase()===t)return[n,r]}function le(e,t,n){for(let[r,o]of Object.entries(e)){let i=[...t,r];typeof o=="function"?n.push(i.join(".")):o!==null&&typeof o=="object"&&le(o,i,n)}}function pe(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function ge(e,t,n){for(let[r,o]of Object.entries(e)){let i=[...t,r];pe(o)?n.push(i.join(".")):o!==null&&typeof o=="object"&&ge(o,i,n)}}function he(e,t){if(t.length===0)return null;let[n,...r]=t,o=Object.entries(e).find(([a])=>a.toLowerCase()===n);if(!o)return null;let[i,s]=o;if(r.length===0)return pe(s)?[i]:null;if(s!==null&&typeof s=="object"&&!pe(s)){let a=he(s,r);if(a!==null)return[i,...a]}return null}function Le(e,t){let n=[];n.push(`${e}({`),n.push(" webhookHooks: {");for(let i=0;i<t.length;i++){let s=" ".repeat(i+2);n.push(`${s}${t[i]}: {`)}let r=" ".repeat(t.length+2),o=r+" ";n.push(`${r}before(ctx, args) {`),n.push(`${o}return { ctx, args };`),n.push(`${r}},`),n.push(`${r}after(ctx, response) {`),n.push(`${r}},`);for(let i=t.length-1;i>=0;i--){let s=" ".repeat(i+2);n.push(`${s}},`)}return n.push(" },"),n.push("})"),n.join(`
17
+ `)}var cn=new Set(Se);function N(e,t){let n=t?.type??"api",r=t?.plugin;if(r!==void 0){let i=e.find(a=>a.id===r);if(!i)return cn.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:N(e);if(n==="webhooks"){if(!i.webhooks)return[];let a=[];return ge(i.webhooks,[],a),a.map(d=>`${i.id}.webhooks.${d}`)}if(n==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(d=>`${i.id}.db.${d}.search`):[]}if(!i.endpoints)return[];let s=[];return le(i.endpoints,[],s),s.map(a=>`${i.id}.api.${a}`)}let o={};if(n==="webhooks")for(let i of e){if(!i.webhooks)continue;let s=[];ge(i.webhooks,[],s),o[i.id]=s.map(a=>`${i.id}.webhooks.${a}`)}else if(n==="db")for(let i of e){let s=i.schema?.entities;s&&(o[i.id]=Object.keys(s).map(a=>`${i.id}.db.${a}.search`))}else for(let i of e){if(!i.endpoints)continue;let s=[];le(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function j(e,t){if(e){for(let[n,r]of Object.entries(e))if(n.toLowerCase()===t)return r}}function dn(e,t){let n=e.toLowerCase(),r=t.toLowerCase();if(!n.startsWith(`${r}.`)){let i=n.slice(t.length+1),s=i.startsWith(".")?i.slice(1):i;return s.startsWith("api.")&&(s=s.slice(4)),{shortPath:s,lookupKey:s}}let o=e.slice(t.length+1);return o.toLowerCase().startsWith("api.")&&(o=o.slice(4)),{shortPath:o,lookupKey:o.toLowerCase()}}function de(e,t){return typeof e=="string"?e:Array.isArray(e)?`${t}:
18
+ ${e.join(", ")}`:`${t}:
19
+ `+Object.entries(e).map(([n,r])=>` ${n}: ${r.join(", ")}`).join(`
20
+ `)}function qn(e,t){let n=t.toLowerCase(),r=n.indexOf(".");if(r!==-1){let o=n.slice(0,r),i=n.slice(r+1),s=e.find(a=>a.id===o);if(s){if(i.startsWith("db.")){let l=i.slice(3),p=l.lastIndexOf(".");if(p!==-1){let h=l.slice(0,p),g=l.slice(p+1),u=s.schema?.entities;if(g==="search"&&u){let f=je(u,h);if(f){let[m,k]=f,P=ye(k),b=[`Search ${o} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${fe.join(", ")}]`];for(let[y,w]of Object.entries(P))b.push(` ${y}?: ${w.type} [${w.operators.join(", ")}]`);return b.push("}"),b.join(`
21
+ `)}}}return de(N(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let l=i.slice(9);if(s.webhooks){let p=he(s.webhooks,l.split("."));if(p!==null){let h=p.join("."),g=j(s.webhookSchemas,h.toLowerCase()),u=g?.response?R(g.response):null,f=[];return g?.description&&f.push(g.description),g?.payload&&f.push(`payload ${z(g.payload,0)}`),u&&f.push(`response: ${u}`),f.push(`usage:
22
+ ${Le(o,p)}`),f.join(`
23
+
24
+ `)}}return de(N(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let d=j(s.endpointMeta,a),c=j(s.endpointSchemas,a);if(d||c){let l=[],p=[d?.riskLevel?`[${d.riskLevel}]`:"",d?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),h=[d?.description,p].filter(Boolean).join(" ");return h&&l.push(h),c?.input&&l.push(`input ${z(c.input,0)}`),c?.output&&l.push(`output ${z(c.output,0)}`),l.join(`
25
+
26
+ `)}}}return de(N(e),"Path not found. Available operations")}function Be(e){let t=e;for(;;){let n=D(t),r=_(n);if(r==="ZodOptional"||r==="ZodNullable"||r==="ZodDefault"){t=L(n);continue}return t}}function ue(e){if(e===void 0)return{kind:"inline",type:"unknown"};let t=Be(e),n=D(t);if(_(n)==="ZodObject"){let o=ee(t,n),i=[];for(let[s,a]of Object.entries(o)){let d=D(a),c=_(d),l=c==="ZodOptional"||c==="ZodNullable",p=Be(a),g=D(p)?.description;i.push({key:s,optional:l,type:R(p),description:g})}return{kind:"object",fields:i}}return{kind:"inline",type:R(t)}}function un(e,t){let n=N(e,{plugin:t,type:"api"});if(typeof n=="string")return{ok:!1,error:n};if(!Array.isArray(n))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===t);if(!r)return{ok:!1,error:`Plugin "${t}" is not configured on this instance.`};let o=[];for(let l of n){let{shortPath:p,lookupKey:h}=dn(l,t),g=j(r.endpointMeta,h),u=j(r.endpointSchemas,h);!g&&!u||o.push({path:l,shortPath:p,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:ue(u?.input),output:ue(u?.output)})}o.sort((l,p)=>l.path.localeCompare(p.path));let i=[],s=N(e,{plugin:t,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let l of s){let h=l.toLowerCase().slice(t.length+1),g=h.startsWith(".")?h.slice(1):h;if(!g.startsWith("webhooks."))continue;let u=g.slice(9),f=he(r.webhooks,u.split("."));if(f===null)continue;let m=f.join("."),k=j(r.webhookSchemas,m.toLowerCase()),P=k?.response?R(k.response):void 0;i.push({path:l,description:k?.description,payload:ue(k?.payload),responseType:P,usageExample:Le(t,f)})}i.sort((l,p)=>l.path.localeCompare(p.path));let a=[],d=N(e,{plugin:t,type:"db"}),c=r.schema?.entities;if(Array.isArray(d)&&c)for(let l of d){let h=l.toLowerCase().slice(t.length+1),g=h.startsWith(".")?h.slice(1):h;if(!g.startsWith("db."))continue;let u=g.slice(3),f=u.lastIndexOf(".");if(f===-1)continue;let m=u.slice(0,f);if(u.slice(f+1)!=="search")continue;let P=je(c,m);if(!P)continue;let[b,y]=P,w=ye(y),T=Object.entries(w).map(([I,C])=>({field:I,type:C.type,operators:C.operators}));a.push({path:l,entityName:b,filters:[{field:"entity_id",type:"string",operators:fe},...T]})}return a.sort((l,p)=>l.path.localeCompare(p.path)),{ok:!0,data:{pluginId:t,api:o,webhooks:i,db:a}}}var me=Symbol.for("corsair:internal");function Qn(e){let t=e.database?ke(e.database):void 0,n=t&&e.kek?Fe(e.plugins,t,e.kek):Y(!!t,!!e.kek),r={plugins:e.plugins,database:t,kek:e.kek,multiTenancy:!!e.multiTenancy,approval:e.approval},o=_e(t);if(e.multiTenancy)return Object.assign({withTenant:s=>{if(!s)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let a=ce(e.plugins,{database:t,tenantId:s,kek:e.kek,rootErrorHandlers:e.errorHandlers,approvalConfig:e.approval});return Object.assign(a,{[me]:r})},keys:n,permissions:o},{[me]:r});let i=ce(e.plugins,{database:t,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,approvalConfig:e.approval});return Object.assign({},i,{keys:n,permissions:o,[me]:r})}export{K as a,M as b,O as c,oe as d,re as e,Z as f,S as g,U as h,q as i,Q as j,X as k,Ae as l,Ee as m,Oe as n,tn as o,Me as p,Se as q,N as r,qn as s,un as t,me as u,Qn as v};
package/dist/core.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, D as DocSchemaFieldRow, b as DocSchemaShape, d as DocsApiEndpoint, e as DocsDbEntity, f as DocsDbFilterField, g as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, c as createCorsair, i as introspectPluginForDocs } from './index-TDdpzfoQ.js';
1
+ export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, D as DocSchemaFieldRow, b as DocSchemaShape, d as DocsApiEndpoint, e as DocsDbEntity, f as DocsDbFilterField, g as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, c as createCorsair, i as introspectPluginForDocs } from './index-D3gJMi1B.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { O as OAuthConfig, A as AuthTypes, g as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DYb70ur1.js';
4
- export { h as AccountFieldNames, n as AllProviders, m as BASE_AUTH_FIELDS, i as BaseAuthFieldConfig, j as BaseKeyManager, f as BaseProviders, K as BeforeHookResult, p as BindEndpoints, a3 as BindWebhooks, a1 as Bivariant, q as BoundEndpointFn, r as BoundEndpointTree, a4 as BoundWebhook, B as BoundWebhookTree, d as CorsairClient, s as CorsairContext, t as CorsairEndpoint, w as CorsairErrorHandler, a as CorsairIntegration, L as CorsairKeyBuilder, M as CorsairKeyBuilderBase, e as CorsairPermissionsNamespace, C as CorsairPlugin, N as CorsairPluginContext, c as CorsairSingleTenantClient, b as CorsairTenantWrapper, a5 as CorsairWebhook, a6 as CorsairWebhookHandler, a7 as CorsairWebhookMatcher, Q as EndpointHooks, S as EndpointMetaEntry, u as EndpointPathsOf, E as EndpointRiskLevel, v as EndpointTree, H as EnforcePermissionOptions, J as EnforcePermissionResult, x as ErrorContext, y as ErrorHandler, z as ErrorHandlerAndMatchFunction, D as ErrorMatcher, k as IntegrationFieldNames, T as KeyBuilderContext, l as OAuth2IntegrationCredentials, U as PermissionMode, V as PermissionPolicy, o as PickAuth, P as PluginAuthConfig, X as PluginEndpointMeta, Y as PluginPermissionsConfig, R as RawWebhookRequest, Z as RequiredPluginEndpointMeta, _ as RequiredPluginEndpointSchemas, $ as RequiredPluginWebhookSchemas, F as RetryStrategies, G as RetryStrategy, a2 as UnionToIntersection, a0 as WebhookHooks, a8 as WebhookPathsOf, a9 as WebhookRequest, W as WebhookResponse, aa as WebhookTree } from './index-DYb70ur1.js';
3
+ import { O as OAuthConfig, A as AuthTypes, g as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DANE8UMK.js';
4
+ export { h as AccountFieldNames, n as AllProviders, m as BASE_AUTH_FIELDS, i as BaseAuthFieldConfig, j as BaseKeyManager, f as BaseProviders, K as BeforeHookResult, p as BindEndpoints, a3 as BindWebhooks, a1 as Bivariant, q as BoundEndpointFn, r as BoundEndpointTree, a4 as BoundWebhook, B as BoundWebhookTree, d as CorsairClient, s as CorsairContext, t as CorsairEndpoint, w as CorsairErrorHandler, a as CorsairIntegration, L as CorsairKeyBuilder, M as CorsairKeyBuilderBase, e as CorsairPermissionsNamespace, C as CorsairPlugin, N as CorsairPluginContext, c as CorsairSingleTenantClient, b as CorsairTenantWrapper, a5 as CorsairWebhook, a6 as CorsairWebhookHandler, a7 as CorsairWebhookMatcher, Q as EndpointHooks, S as EndpointMetaEntry, u as EndpointPathsOf, E as EndpointRiskLevel, v as EndpointTree, H as EnforcePermissionOptions, J as EnforcePermissionResult, x as ErrorContext, y as ErrorHandler, z as ErrorHandlerAndMatchFunction, D as ErrorMatcher, k as IntegrationFieldNames, T as KeyBuilderContext, l as OAuth2IntegrationCredentials, U as PermissionMode, V as PermissionPolicy, o as PickAuth, P as PluginAuthConfig, X as PluginEndpointMeta, Y as PluginPermissionsConfig, R as RawWebhookRequest, Z as RequiredPluginEndpointMeta, _ as RequiredPluginEndpointSchemas, $ as RequiredPluginWebhookSchemas, F as RetryStrategies, G as RetryStrategy, a2 as UnionToIntersection, a0 as WebhookHooks, a8 as WebhookPathsOf, a9 as WebhookRequest, W as WebhookResponse, aa as WebhookTree } from './index-DANE8UMK.js';
5
5
  import 'kysely';
6
6
  import 'zod';
7
7
  import 'pg';
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,t as q,u as r,v as s}from"./chunk-GN4ET25A.js";import"./chunk-2PB34FTK.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{i as BASE_AUTH_FIELDS,r as CORSAIR_INTERNAL,k as createAccountKeyManager,s as createCorsair,j as createIntegrationKeyManager,g as decryptConfig,c as decryptDEK,e as decryptWithDEK,f as encryptConfig,b as encryptDEK,d as encryptWithDEK,p as exchangeCodeForTokens,a as generateDEK,m as initializeAccountDEK,l as initializeIntegrationDEK,q as introspectPluginForDocs,n as logEvent,o as logEventFromContext,h as reEncryptConfig};
1
+ import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,t as q,u as r,v as s}from"./chunk-XYRVJ76B.js";import"./chunk-OZHME3EO.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{i as BASE_AUTH_FIELDS,r as CORSAIR_INTERNAL,k as createAccountKeyManager,s as createCorsair,j as createIntegrationKeyManager,g as decryptConfig,c as decryptDEK,e as decryptWithDEK,f as encryptConfig,b as encryptDEK,d as encryptWithDEK,p as exchangeCodeForTokens,a as generateDEK,m as initializeAccountDEK,l as initializeIntegrationDEK,q as introspectPluginForDocs,n as logEvent,o as logEventFromContext,h as reEncryptConfig};
package/dist/db.d.ts CHANGED
@@ -6,157 +6,70 @@ import { Sql } from 'postgres';
6
6
 
7
7
  declare const CorsairIntegrationsSchema: z.ZodObject<{
8
8
  id: z.ZodString;
9
- created_at: z.ZodDate;
10
- updated_at: z.ZodDate;
9
+ created_at: z.ZodCoercedDate<unknown>;
10
+ updated_at: z.ZodCoercedDate<unknown>;
11
11
  name: z.ZodString;
12
- config: z.ZodEffects<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, Record<string, unknown>, Record<string, unknown> | null>;
12
+ config: z.ZodPipe<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, unknown>, Record<string, unknown> | null>>;
13
13
  dek: z.ZodOptional<z.ZodNullable<z.ZodString>>;
14
- }, "strip", z.ZodTypeAny, {
15
- id: string;
16
- created_at: Date;
17
- updated_at: Date;
18
- name: string;
19
- config: Record<string, unknown>;
20
- dek?: string | null | undefined;
21
- }, {
22
- id: string;
23
- created_at: Date;
24
- updated_at: Date;
25
- name: string;
26
- config: Record<string, unknown> | null;
27
- dek?: string | null | undefined;
28
- }>;
14
+ }, z.core.$strip>;
29
15
  type CorsairIntegration = z.infer<typeof CorsairIntegrationsSchema>;
30
16
  declare const CorsairAccountsSchema: z.ZodObject<{
31
17
  id: z.ZodString;
32
- created_at: z.ZodDate;
33
- updated_at: z.ZodDate;
18
+ created_at: z.ZodCoercedDate<unknown>;
19
+ updated_at: z.ZodCoercedDate<unknown>;
34
20
  tenant_id: z.ZodString;
35
21
  integration_id: z.ZodString;
36
- config: z.ZodEffects<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, Record<string, unknown>, Record<string, unknown> | null>;
22
+ config: z.ZodPipe<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, unknown>, Record<string, unknown> | null>>;
37
23
  dek: z.ZodOptional<z.ZodNullable<z.ZodString>>;
38
- }, "strip", z.ZodTypeAny, {
39
- id: string;
40
- created_at: Date;
41
- updated_at: Date;
42
- config: Record<string, unknown>;
43
- tenant_id: string;
44
- integration_id: string;
45
- dek?: string | null | undefined;
46
- }, {
47
- id: string;
48
- created_at: Date;
49
- updated_at: Date;
50
- config: Record<string, unknown> | null;
51
- tenant_id: string;
52
- integration_id: string;
53
- dek?: string | null | undefined;
54
- }>;
24
+ }, z.core.$strip>;
55
25
  type CorsairAccount = z.infer<typeof CorsairAccountsSchema>;
56
26
  declare const CorsairEntitiesSchema: z.ZodObject<{
57
27
  id: z.ZodString;
58
- created_at: z.ZodDate;
59
- updated_at: z.ZodDate;
28
+ created_at: z.ZodCoercedDate<unknown>;
29
+ updated_at: z.ZodCoercedDate<unknown>;
60
30
  account_id: z.ZodString;
61
31
  entity_id: z.ZodString;
62
32
  entity_type: z.ZodString;
63
33
  version: z.ZodString;
64
- data: z.ZodEffects<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, Record<string, unknown>, Record<string, unknown> | null>;
65
- }, "strip", z.ZodTypeAny, {
66
- id: string;
67
- created_at: Date;
68
- updated_at: Date;
69
- account_id: string;
70
- entity_id: string;
71
- entity_type: string;
72
- version: string;
73
- data: Record<string, unknown>;
74
- }, {
75
- id: string;
76
- created_at: Date;
77
- updated_at: Date;
78
- account_id: string;
79
- entity_id: string;
80
- entity_type: string;
81
- version: string;
82
- data: Record<string, unknown> | null;
83
- }>;
34
+ data: z.ZodPipe<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, unknown>, Record<string, unknown> | null>>;
35
+ }, z.core.$strip>;
84
36
  type CorsairEntity = z.infer<typeof CorsairEntitiesSchema>;
85
37
  declare const CorsairEventsSchema: z.ZodObject<{
86
38
  id: z.ZodString;
87
- created_at: z.ZodDate;
88
- updated_at: z.ZodDate;
39
+ created_at: z.ZodCoercedDate<unknown>;
40
+ updated_at: z.ZodCoercedDate<unknown>;
89
41
  account_id: z.ZodString;
90
42
  event_type: z.ZodString;
91
- payload: z.ZodEffects<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, Record<string, unknown>, Record<string, unknown> | null>;
92
- status: z.ZodOptional<z.ZodEnum<["pending", "processing", "completed", "failed"]>>;
93
- }, "strip", z.ZodTypeAny, {
94
- id: string;
95
- created_at: Date;
96
- updated_at: Date;
97
- account_id: string;
98
- event_type: string;
99
- payload: Record<string, unknown>;
100
- status?: "pending" | "processing" | "completed" | "failed" | undefined;
101
- }, {
102
- id: string;
103
- created_at: Date;
104
- updated_at: Date;
105
- account_id: string;
106
- event_type: string;
107
- payload: Record<string, unknown> | null;
108
- status?: "pending" | "processing" | "completed" | "failed" | undefined;
109
- }>;
43
+ payload: z.ZodPipe<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, unknown>, Record<string, unknown> | null>>;
44
+ status: z.ZodOptional<z.ZodEnum<{
45
+ pending: "pending";
46
+ processing: "processing";
47
+ completed: "completed";
48
+ failed: "failed";
49
+ }>>;
50
+ }, z.core.$strip>;
110
51
  type CorsairEvent = z.infer<typeof CorsairEventsSchema>;
111
52
  declare const CorsairPermissionsSchema: z.ZodObject<{
112
53
  id: z.ZodString;
113
- created_at: z.ZodDate;
114
- updated_at: z.ZodDate;
115
- /** 32-byte hex-encoded secure random token, single-use. Embedded in the review URL. */
54
+ created_at: z.ZodCoercedDate<unknown>;
55
+ updated_at: z.ZodCoercedDate<unknown>;
116
56
  token: z.ZodString;
117
- /** Plugin identifier, e.g. 'github' */
118
57
  plugin: z.ZodString;
119
- /** Dot-notation endpoint path, e.g. 'repositories.delete' */
120
58
  endpoint: z.ZodString;
121
- /** JSON-encoded args that will be forwarded to the endpoint upon approval */
122
59
  args: z.ZodString;
123
- /**
124
- * Tenant ID for multi-tenant corsair instances. Stored so executePermission
125
- * can scope the corsair instance correctly when executing the approved action.
126
- * Defaults to 'default' for single-tenant instances.
127
- */
128
60
  tenant_id: z.ZodString;
129
- /** Current state of the approval request */
130
- status: z.ZodDefault<z.ZodEnum<["pending", "approved", "executing", "completed", "denied", "expired", "failed"]>>;
131
- /** ISO8601 timestamp — when this request becomes invalid */
61
+ status: z.ZodDefault<z.ZodEnum<{
62
+ pending: "pending";
63
+ completed: "completed";
64
+ failed: "failed";
65
+ approved: "approved";
66
+ executing: "executing";
67
+ denied: "denied";
68
+ expired: "expired";
69
+ }>>;
132
70
  expires_at: z.ZodString;
133
- /** Stringified error captured when status transitions to 'failed'. Null otherwise. */
134
71
  error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
135
- }, "strip", z.ZodTypeAny, {
136
- id: string;
137
- created_at: Date;
138
- updated_at: Date;
139
- status: "pending" | "completed" | "failed" | "approved" | "executing" | "denied" | "expired";
140
- tenant_id: string;
141
- token: string;
142
- plugin: string;
143
- endpoint: string;
144
- args: string;
145
- expires_at: string;
146
- error?: string | null | undefined;
147
- }, {
148
- id: string;
149
- created_at: Date;
150
- updated_at: Date;
151
- tenant_id: string;
152
- token: string;
153
- plugin: string;
154
- endpoint: string;
155
- args: string;
156
- expires_at: string;
157
- status?: "pending" | "completed" | "failed" | "approved" | "executing" | "denied" | "expired" | undefined;
158
- error?: string | null | undefined;
159
- }>;
72
+ }, z.core.$strip>;
160
73
  type CorsairPermission = z.infer<typeof CorsairPermissionsSchema>;
161
74
  type CorsairPermissionInsert = {
162
75
  id?: string;
package/dist/db.js CHANGED
@@ -1 +1 @@
1
- import{a as g}from"./chunk-N2XRSSRL.js";import{a as b,b as c,c as d,d as e,e as f}from"./chunk-HO245J34.js";import{a}from"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{c as CorsairAccountsSchema,d as CorsairEntitiesSchema,e as CorsairEventsSchema,b as CorsairIntegrationsSchema,f as CorsairPermissionsSchema,a as createCorsairDatabase,g as sql};
1
+ import{a as g}from"./chunk-N2XRSSRL.js";import{a as b,b as c,c as d,d as e,e as f}from"./chunk-3USHGH6P.js";import{a}from"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{c as CorsairAccountsSchema,d as CorsairEntitiesSchema,e as CorsairEventsSchema,b as CorsairIntegrationsSchema,f as CorsairPermissionsSchema,a as createCorsairDatabase,g as sql};
@@ -1,4 +1,4 @@
1
- import { E as EndpointRiskLevel, C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-DYb70ur1.js';
1
+ import { E as EndpointRiskLevel, C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-DANE8UMK.js';
2
2
  import { CorsairDatabase } from './db.js';
3
3
 
4
4
  /** @deprecated get_schema now returns a plain string. This type is kept for backwards compatibility. */
@@ -3,8 +3,8 @@ import { CorsairPluginSchema, PluginEntityClients } from './orm.js';
3
3
  import { CorsairDatabase, CorsairDatabaseInput, CorsairPermission } from './db.js';
4
4
 
5
5
  type AllErrors = 'RATE_LIMIT_ERROR' | 'AUTH_ERROR' | 'PERMISSION_ERROR' | 'NETWORK_ERROR' | 'TIMEOUT_ERROR' | 'SERVER_ERROR' | 'VALIDATION_ERROR' | 'NOT_FOUND_ERROR' | 'BAD_REQUEST_ERROR' | 'PARSING_ERROR' | 'DEFAULT' | (string & {});
6
- declare const BaseProviders: readonly ["ably", "airtable", "amplitude", "asana", "box", "cal", "calendly", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tavily", "teams", "telegram", "todoist", "trello", "twitter", "twitterapiio", "typeform", "vapi", "youtube", "zoom"];
7
- type AllProviders = 'ably' | 'airtable' | 'amplitude' | 'asana' | 'box' | 'cal' | 'calendly' | 'cursor' | 'discord' | 'dodopayments' | 'dropbox' | 'exa' | 'figma' | 'firecrawl' | 'fireflies' | 'github' | 'gitlab' | 'gmail' | 'googlecalendar' | 'googledrive' | 'googlesheets' | 'hackernews' | 'hubspot' | 'intercom' | 'jira' | 'linear' | 'monday' | 'notion' | 'onedrive' | 'openweathermap' | 'oura' | 'outlook' | 'pagerduty' | 'posthog' | 'razorpay' | 'reddit' | 'resend' | 'sentry' | 'sharepoint' | 'slack' | 'spotify' | 'strava' | 'stripe' | 'tavily' | 'teams' | 'telegram' | 'todoist' | 'trello' | 'twitter' | 'twitterapiio' | 'typeform' | 'vapi' | 'youtube' | 'zoom' | (string & {});
6
+ declare const BaseProviders: readonly ["ably", "airtable", "amplitude", "asana", "box", "cal", "calendly", "cloudflare", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tavily", "teams", "telegram", "todoist", "trello", "twitter", "twitterapiio", "typeform", "vapi", "youtube", "zoom"];
7
+ type AllProviders = 'ably' | 'airtable' | 'amplitude' | 'asana' | 'box' | 'cal' | 'calendly' | 'cloudflare' | 'cursor' | 'discord' | 'dodopayments' | 'dropbox' | 'exa' | 'figma' | 'firecrawl' | 'fireflies' | 'github' | 'gitlab' | 'gmail' | 'googlecalendar' | 'googledrive' | 'googlesheets' | 'hackernews' | 'hubspot' | 'intercom' | 'jira' | 'linear' | 'monday' | 'notion' | 'onedrive' | 'openweathermap' | 'oura' | 'outlook' | 'pagerduty' | 'posthog' | 'razorpay' | 'reddit' | 'resend' | 'sentry' | 'sharepoint' | 'slack' | 'spotify' | 'strava' | 'stripe' | 'tavily' | 'teams' | 'telegram' | 'todoist' | 'trello' | 'twitter' | 'twitterapiio' | 'typeform' | 'vapi' | 'youtube' | 'zoom' | (string & {});
8
8
  type AuthTypes = 'oauth_2' | 'api_key' | 'bot_token';
9
9
  type PickAuth<T extends AuthTypes> = T;
10
10
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { L as ListOperationsOptions } from './index-TDdpzfoQ.js';
2
- export { c as createCorsair } from './index-TDdpzfoQ.js';
3
- import { c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, d as CorsairClient, e as CorsairPermissionsNamespace, B as BoundWebhookTree, R as RawWebhookRequest, f as BaseProviders, W as WebhookResponse } from './index-DYb70ur1.js';
1
+ import { L as ListOperationsOptions } from './index-D3gJMi1B.js';
2
+ export { c as createCorsair } from './index-D3gJMi1B.js';
3
+ import { c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, d as CorsairClient, e as CorsairPermissionsNamespace, B as BoundWebhookTree, R as RawWebhookRequest, f as BaseProviders, W as WebhookResponse } from './index-DANE8UMK.js';
4
4
  export { SetupCorsairOptions, setupCorsair } from './setup.js';
5
5
  import './db.js';
6
6
  import 'kysely';
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import{a as I}from"./chunk-AUAZUOIF.js";import{q as m,r as k,s as b,u as y,v as W}from"./chunk-GN4ET25A.js";import"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";function w(n){let r=n[y];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function O(n,r){let o=k(w(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
1
+ import{a as I}from"./chunk-AEZOR7GA.js";import{q as m,r as k,s as b,u as y,v as W}from"./chunk-XYRVJ76B.js";import"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";function w(n){let r=n[y];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function O(n,r){let o=k(w(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
2
2
  `):Object.values(o).flat().join(`
3
3
  `)}function S(n,r){return b(w(n),r)}var T=Symbol.for("corsair:internal");function B(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 x(n){return n[T]?.database}async function A(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=x(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 t=e.tenant_id??"default",g=(n.withTenant?n.withTenant(t):n)[e.plugin];if(!g?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let p=B(g.api,e.endpoint.split("."));if(!p)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let i=typeof e.args=="string"?JSON.parse(e.args):e.args,u=await p(i);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:u}}catch(i){let u=i instanceof Error?i.message:String(i),d=x(n);return d&&await d.db.updateTable("corsair_permissions").set({status:"failed",error:u,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:u}}}function E(n){return n!==null&&typeof n=="object"&&"match"in n&&"handler"in n&&typeof n.match=="function"&&typeof n.handler=="function"}function C(n,r,o=[]){for(let[e,t]of Object.entries(n))if(E(t)){if(t.match(r))return{webhook:t,path:[...o,e]}}else if(t&&typeof t=="object"){let s=C(t,r,[...o,e]);if(s)return s}return null}function $(n){let r={};for(let[o,e]of Object.entries(n))r[o.toLowerCase()]=Array.isArray(e)?e[0]:e;return r}function j(n){let r=n["x-goog-resource-uri"],o=n["x-goog-channel-id"];if(!r||!o)return null;let e={resourceId:n["x-goog-resource-id"]||"",resourceState:n["x-goog-resource-state"]||"",resourceUri:r,channelId:o,channelExpiration:n["x-goog-channel-expiration"]||""};return r.includes("/drive/")&&(e.kind="drive#change"),{message:{data:Buffer.from(JSON.stringify(e)).toString("base64"),messageId:n["x-goog-message-number"]||""}}}async function _(n,r,o,e){let t=$(r),s=typeof o=="string"?JSON.parse(o):o;(!s||typeof s=="object"&&Object.keys(s).length===0)&&t["x-goog-resource-uri"]&&(s=j(t)||s);let p={headers:t,body:s},i=e?.tenantId||"default",u=n.withTenant?n.withTenant(i):n,d=m;for(let l of d){let c=u[l];if(!c||!c.webhooks||c.pluginWebhookMatcher&&!c.pluginWebhookMatcher(p))continue;let f=C(c.webhooks,p);if(!f)continue;let h=f.path.join("."),R={payload:s,headers:t,rawBody:typeof o=="string"?o:JSON.stringify(o)};try{let a=await f.webhook.handler(R),P=!!Object.keys(a.returnToSender||{})?.length;return{plugin:l,action:h,body:s,response:P?{...a?.returnToSender,success:!0}:{success:!0},...a.responseHeaders&&{responseHeaders:a.responseHeaders}}}catch(a){return console.error(`Error executing webhook handler for ${l}.${h}:`,a),{plugin:l,action:h,body:s,response:{success:!1,error:a instanceof Error?a.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}export{W as createCorsair,A as executePermission,S as getSchema,O as listOperations,_ as processWebhook,I as setupCorsair};
package/dist/oauth.js CHANGED
@@ -1 +1 @@
1
- import{a as m,b as w,j as h,k as A,p as C,u as y}from"./chunk-GN4ET25A.js";import{b as _}from"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";import*as l from"crypto";import*as b from"querystring";function x(e,t){return Buffer.from(JSON.stringify({plugin:e,tenantId:t})).toString("base64url")}function S(e){try{let t=e.includes(".")?e.split(".")[0]:e,n=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));return n!==null&&typeof n=="object"&&"plugin"in n&&"tenantId"in n&&typeof n.plugin=="string"&&typeof n.tenantId=="string"?n:null}catch{return null}}function N(e,t){let n=l.createHmac("sha256",t).update(e).digest("base64url");return`${e}.${n}`}function U(e,t){let n=e.lastIndexOf(".");if(n===-1)return null;let a=e.slice(0,n),i=e.slice(n+1),r=l.createHmac("sha256",t).update(a).digest("base64url"),s=Buffer.from(i,"base64url"),o=Buffer.from(r,"base64url");return s.length!==o.length||!l.timingSafeEqual(s,o)?null:S(a)}function I(e){let t=e[y];if(!t)throw new Error("Invalid corsair instance");return t}function P(e,t){let n=e.plugins.find(a=>a.id===t);if(!n)throw new Error(`Plugin '${t}' not found`);return n}function E(e){let t=e.oauthConfig;if(!t)throw new Error(`Plugin '${e.id}' has no oauthConfig`);return t}async function R(e,t,n,a){let i=_(e),r=await i.integrations.findByName(t);if(!r)throw new Error(`Integration '${t}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:n,integration_id:r.id}))return;let o=m(),c=await w(o,a);await i.accounts.create({tenant_id:n,integration_id:r.id,config:{},dek:c})}async function $(e,t,n){let{tenantId:a,redirectUri:i}=n,r=I(e);if(!r.database)throw new Error("No database configured on corsair instance");let s=P(r,t),o=E(s),f=await h({authType:"oauth_2",integrationName:t,kek:r.kek,database:r.database}).get_client_id();if(!f)throw new Error(`client_id not configured for '${t}'`);let g=N(x(t,a),r.kek),d={...o.authParams,client_id:f,redirect_uri:i,response_type:"code",scope:o.scopes.join(" "),state:g};return{url:`${o.authUrl}?${b.stringify(d)}`,state:g}}async function K(e,t){let{code:n,state:a,redirectUri:i}=t,r=I(e),s=U(a,r.kek);if(!s)throw new Error("Invalid or tampered state parameter");let{plugin:o,tenantId:c}=s;if(!r.database)throw new Error("No database configured on corsair instance");let f=P(r,o),g=E(f),d=h({authType:"oauth_2",integrationName:o,kek:r.kek,database:r.database}),k=await d.get_client_id(),O=await d.get_client_secret();if(!k||!O)throw new Error(`Credentials not configured for '${o}'`);await R(r.database,o,c,r.kek);let u=await C(n,k,O,g,i);if(!u.access_token)throw new Error(`No access_token returned from ${g.providerName}`);let p=A({authType:"oauth_2",integrationName:o,tenantId:c,kek:r.kek,database:r.database});return await p.set_access_token(u.access_token),u.refresh_token&&await p.set_refresh_token(u.refresh_token),u.expires_in&&await p.set_expires_at(String(Math.floor(Date.now()/1e3)+u.expires_in)),{plugin:o,tenantId:c}}export{S as decodeOAuthState,x as encodeOAuthState,$ as generateOAuthUrl,K as processOAuthCallback};
1
+ import{a as m,b as w,j as h,k as A,p as C,u as y}from"./chunk-XYRVJ76B.js";import{b as _}from"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";import*as l from"crypto";import*as b from"querystring";function x(e,t){return Buffer.from(JSON.stringify({plugin:e,tenantId:t})).toString("base64url")}function S(e){try{let t=e.includes(".")?e.split(".")[0]:e,n=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));return n!==null&&typeof n=="object"&&"plugin"in n&&"tenantId"in n&&typeof n.plugin=="string"&&typeof n.tenantId=="string"?n:null}catch{return null}}function N(e,t){let n=l.createHmac("sha256",t).update(e).digest("base64url");return`${e}.${n}`}function U(e,t){let n=e.lastIndexOf(".");if(n===-1)return null;let a=e.slice(0,n),i=e.slice(n+1),r=l.createHmac("sha256",t).update(a).digest("base64url"),s=Buffer.from(i,"base64url"),o=Buffer.from(r,"base64url");return s.length!==o.length||!l.timingSafeEqual(s,o)?null:S(a)}function I(e){let t=e[y];if(!t)throw new Error("Invalid corsair instance");return t}function P(e,t){let n=e.plugins.find(a=>a.id===t);if(!n)throw new Error(`Plugin '${t}' not found`);return n}function E(e){let t=e.oauthConfig;if(!t)throw new Error(`Plugin '${e.id}' has no oauthConfig`);return t}async function R(e,t,n,a){let i=_(e),r=await i.integrations.findByName(t);if(!r)throw new Error(`Integration '${t}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:n,integration_id:r.id}))return;let o=m(),c=await w(o,a);await i.accounts.create({tenant_id:n,integration_id:r.id,config:{},dek:c})}async function $(e,t,n){let{tenantId:a,redirectUri:i}=n,r=I(e);if(!r.database)throw new Error("No database configured on corsair instance");let s=P(r,t),o=E(s),f=await h({authType:"oauth_2",integrationName:t,kek:r.kek,database:r.database}).get_client_id();if(!f)throw new Error(`client_id not configured for '${t}'`);let g=N(x(t,a),r.kek),d={...o.authParams,client_id:f,redirect_uri:i,response_type:"code",scope:o.scopes.join(" "),state:g};return{url:`${o.authUrl}?${b.stringify(d)}`,state:g}}async function K(e,t){let{code:n,state:a,redirectUri:i}=t,r=I(e),s=U(a,r.kek);if(!s)throw new Error("Invalid or tampered state parameter");let{plugin:o,tenantId:c}=s;if(!r.database)throw new Error("No database configured on corsair instance");let f=P(r,o),g=E(f),d=h({authType:"oauth_2",integrationName:o,kek:r.kek,database:r.database}),k=await d.get_client_id(),O=await d.get_client_secret();if(!k||!O)throw new Error(`Credentials not configured for '${o}'`);await R(r.database,o,c,r.kek);let u=await C(n,k,O,g,i);if(!u.access_token)throw new Error(`No access_token returned from ${g.providerName}`);let p=A({authType:"oauth_2",integrationName:o,tenantId:c,kek:r.kek,database:r.database});return await p.set_access_token(u.access_token),u.refresh_token&&await p.set_refresh_token(u.refresh_token),u.expires_in&&await p.set_expires_at(String(Math.floor(Date.now()/1e3)+u.expires_in)),{plugin:o,tenantId:c}}export{S as decodeOAuthState,x as encodeOAuthState,$ as generateOAuthUrl,K as processOAuthCallback};
package/dist/orm.js CHANGED
@@ -1 +1 @@
1
- import"./chunk-N2XRSSRL.js";import{b as o,c as e,d as n,e as s}from"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import{a as r,b as t,c as i,d as a}from"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{t as CorsairAccountsSchema,i as CorsairEntitiesSchema,a as CorsairEventsSchema,r as CorsairIntegrationsSchema,o as createCorsairOrm,e as createPluginOrm,s as createPluginOrmFactory,n as createTenantScopedOrm};
1
+ import"./chunk-N2XRSSRL.js";import{b as o,c as e,d as n,e as s}from"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import{a as r,b as t,c as i,d as a}from"./chunk-3USHGH6P.js";import"./chunk-ZGVIF3UY.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,4 +1,4 @@
1
- import { C as CorsairPlugin, c as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-DYb70ur1.js';
1
+ import { C as CorsairPlugin, c as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-DANE8UMK.js';
2
2
  import 'zod';
3
3
  import './orm.js';
4
4
  import './db.js';
package/dist/setup.js CHANGED
@@ -1 +1 @@
1
- import{a as o}from"./chunk-AUAZUOIF.js";import"./chunk-GN4ET25A.js";import"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{o as setupCorsair};
1
+ import{a as o}from"./chunk-AEZOR7GA.js";import"./chunk-XYRVJ76B.js";import"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{o as setupCorsair};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsair",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,7 +52,7 @@
52
52
  "kysely": "^0.28.5",
53
53
  "kysely-postgres-js": "^3.0.0",
54
54
  "uuid": "^13.0.0",
55
- "zod": "^3.25.76"
55
+ "zod": "^4.1.13"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/jest": "^29.5.14",
@@ -1 +0,0 @@
1
- import{v7 as j}from"uuid";function g(){return j()}import{z as u}from"zod";import{sql as d}from"kysely";function m(e){return e.replace(/'/g,"''")}function k(e){let t=m(e);return d`data->>'${d.raw(t)}'`}function D(e){let t=m(e);return d`(data->>'${d.raw(t)}')::numeric`}function F(e){let t=m(e);return d`(data->>'${d.raw(t)}')::boolean`}function T(e){let t=m(e);return d`(data->>'${d.raw(t)}')::timestamptz`}function A(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function _(e){let t=e;for(;t;){if(t instanceof u.ZodOptional||t instanceof u.ZodNullable){t=t._def.innerType;continue}if(t instanceof u.ZodDefault){t=t._def.innerType;continue}if(t instanceof u.ZodEffects){t=t._def.schema;continue}break}return t}function x(e){let t=_(e);if(t instanceof u.ZodString)return"string";if(t instanceof u.ZodNumber)return"number";if(t instanceof u.ZodBoolean)return"boolean";if(t instanceof u.ZodDate)return"date"}function B(e){let t=_(e);if(!(t instanceof u.ZodObject))return{};let r=t.shape,n={};for(let[y,w]of Object.entries(r)){let s=x(w);s&&(n[y]=s)}return n}function R(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 Z(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 C(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 S(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[y,w]=n.between;y instanceof Date&&(e=e.where(t,">=",y)),w instanceof Date&&(e=e.where(t,"<=",w))}}return e}function I(e,t,r,n){return r==="number"?Z(e,D(t),n):r==="boolean"?C(e,F(t),n):r==="date"?S(e,T(t),n):R(e,k(t),n)}function W(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 Q(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function p(e,t,r){return e.selectFrom("corsair_entities").selectAll().where("account_id","=",t).where("entity_type","=",r)}function z(e,t,r,n,y){let w=B(y);function s(i){let o=A(i.data);return{...i,data:y.parse(o)}}return{findByEntityId:async i=>{let o=await t(),a=await p(e,o,r).where("entity_id","=",i).executeTakeFirst();return a?s(a):null},findById:async i=>{let o=await t(),a=await p(e,o,r).where("id","=",i).executeTakeFirst();return a?s(a):null},findManyByEntityIds:async i=>{if(i.length===0)return[];let o=await t();return(await p(e,o,r).where("entity_id","in",i).execute()).map(s)},list:async i=>{let o=await t(),a=p(e,o,r);return typeof i?.limit=="number"&&(a=a.limit(i.limit)),typeof i?.offset=="number"&&(a=a.offset(i.offset)),(await a.execute()).map(s)},search:async i=>{let o=await t(),a=p(e,o,r),l=new Set(["data","limit","offset"]);for(let[c,f]of Object.entries(i))l.has(c)||f===void 0||(a=W(a,c,f));if(i.data&&typeof i.data=="object")for(let[c,f]of Object.entries(i.data)){if(f===void 0)continue;let b=w[c]??"string";a=I(a,c,b,f)}return typeof i.limit=="number"&&(a=a.limit(i.limit)),typeof i.offset=="number"&&(a=a.offset(i.offset)),(await a.execute()).map(s)},upsertByEntityId:async(i,o)=>{let a=await t(),l=y.parse(o),h=new Date,c=await p(e,a,r).select("id").where("entity_id","=",i).executeTakeFirst();if(c?.id){await e.updateTable("corsair_entities").set({version:n,data:l,updated_at:h}).where("id","=",c.id).execute();let E=await e.selectFrom("corsair_entities").selectAll().where("id","=",c.id).executeTakeFirst();return s(E)}let f=g();await e.insertInto("corsair_entities").values({id:f,created_at:h,updated_at:h,account_id:a,entity_id:i,entity_type:r,version:n,data:l}).execute();let b=await e.selectFrom("corsair_entities").selectAll().where("id","=",f).executeTakeFirst();return s(b)},deleteById:async i=>{let o=await t(),a=await e.deleteFrom("corsair_entities").where("account_id","=",o).where("entity_type","=",r).where("id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0},deleteByEntityId:async i=>{let o=await t(),a=await e.deleteFrom("corsair_entities").where("account_id","=",o).where("entity_type","=",r).where("entity_id","=",i).executeTakeFirst();return Number(a.numDeletedRows)>0},count:async()=>{let i=await t(),o=await e.selectFrom("corsair_entities").select(a=>a.fn.countAll().as("count")).where("account_id","=",i).where("entity_type","=",r).executeTakeFirst();return Q(o?.count)}}}export{g as a,z as b};
@@ -1,5 +0,0 @@
1
- import{i as w,j as C,k as S,u as A,v as T}from"./chunk-GN4ET25A.js";import{a as _}from"./chunk-7IH5DNUL.js";import{Kysely as I}from"kysely";import{ZodBoolean as M,ZodDate as R,ZodEffects as j,ZodEnum as D,ZodNullable as E,ZodNumber as F,ZodObject as O,ZodOptional as x,ZodRecord as K,ZodString as B,ZodType as v}from"zod";var h={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:{}}}};async function se(e,t){let r=[],i=s=>{r.push(s),console.log(s)},o=s=>{r.push(s),console.warn(s)},f=t?.caller??"script",d=t?.tenantId;if(!d){if(e?.withTenant)throw new Error("setupCorsair: tenantId must be a non-empty string");d="default"}let n=Z(e);if(!n)throw new Error("setupCorsair: invalid corsair instance");if(!n.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u={...n,database:n.database},c=u.database.db;await H(c,o);let p=await J(c,u,d,i),y=await Q(p,d,i,f);if(t?.backfill){i("[corsair:setup] Starting backfill...");let s=T({plugins:n.plugins,database:c,kek:n.kek,multiTenancy:!0}).withTenant(d);await V(s,n.plugins,y,i,o),i("[corsair:setup] Backfill complete.")}return r.join(`
2
- `)}function b(e){return typeof e=="object"&&e!==null}function N(e){return!b(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:b(e.database)?e.database.db instanceof I:!1}function Z(e){let t=Object.getOwnPropertyDescriptor(e,A);if(t)return N(t.value)?t.value:void 0}function L(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"}function U(e){let t=e.options?.authType;return L(t)?t:void 0}function m(e,t){if(!b(e))return;let r=e[t];return typeof r=="function"?(...i)=>Reflect.apply(r,e,i):void 0}function $(e,t){return b(e)?t===0?!0:Object.values(e).every(r=>$(r,t-1)):!1}function W(e){return $(e,4)}var Y={..._};function k(e){if(e instanceof O){let t={};for(let[r,i]of Object.entries(e.shape))t[r]=i instanceof v?k(i):"unknown";return t}return e instanceof j?k(e.innerType()):e instanceof E?`${k(e.unwrap())} | null`:e instanceof x?`${k(e.unwrap())} | undefined`:e instanceof D?e.options.join(" | "):e instanceof B?"string":e instanceof F?"number":e instanceof M?"boolean":e instanceof R?"date":e instanceof K?"jsonb":"unknown"}async function H(e,t){let r=await e.introspection.getTables(),i=new Set(r.map(o=>o.name));for(let[o,f]of Object.entries(Y))i.has(o)||t(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
3
- Schema: ${JSON.stringify(k(f),null,2)}`)}async function J(e,t,r,i){let o=new Date,f=new Map;for(let d of t.plugins){let n=d.id,u=U(d),c=await e.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!c){let l=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:l,name:n,config:{},created_at:o,updated_at:o}).execute(),c=await e.selectFrom("corsair_integrations").selectAll().where("id","=",l).executeTakeFirst(),i(`[corsair:setup] Created integration: ${n}`)}let p=u?d.authConfig?.[u]?.integration??[]:[],y=u?d.authConfig?.[u]?.account??[]:[],s=u&&c?C({authType:u,integrationName:n,kek:t.kek,database:t.database,extraIntegrationFields:p}):void 0;if(c&&!c.dek&&s&&(await s.issue_new_dek(),i(`[corsair:setup] Issued integration DEK: ${n}`)),!c)continue;let a=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",c.id).executeTakeFirst();if(!a){let l=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:l,tenant_id:r,integration_id:c.id,config:{},created_at:o,updated_at:o}).execute(),a=await e.selectFrom("corsair_accounts").selectAll().where("id","=",l).executeTakeFirst(),i(`[corsair:setup] Created account: ${n}`)}let g=u&&a?S({authType:u,integrationName:n,tenantId:r,kek:t.kek,database:t.database,extraAccountFields:y}):void 0;a&&!a.dek&&g&&(await g.issue_new_dek(),i(`[corsair:setup] Issued account DEK: ${n}`)),u&&s&&g&&f.set(n,{pluginId:n,authType:u,integration:s,account:g,integrationFields:[...w[u].integration,...p],accountFields:[...w[u].account,...y]})}return f}var P=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function z(e,t,r,i,o,f,d,n,u){let c=[],p=[];for(let s of o){if(P.has(s))continue;let a=m(r,`get_${s}`);if(!a)continue;let g=null;try{let l=await a();g=typeof l=="string"?l:null}catch{}g||c.push(s)}for(let s of f){if(P.has(s))continue;let a=m(i,`get_${s}`);if(!a)continue;let g=null;try{let l=await a();g=typeof l=="string"?l:null}catch{}g||p.push(s)}let y=c.length===0&&p.length===0;if(y)n(`[corsair:setup] '${e}' (${t}) is configured \u2713`);else{let s=[...c,...p];if(u==="cli"){let a=s.map(g=>`${g}=VALUE`).join(" ");n(`[corsair:setup] '${e}' (${t}) needs credentials. Run:
4
- corsair setup --${e} ${a}`)}else{let a=[`[corsair:setup] '${e}' (${t}) needs credentials. Call:`];for(let g of c)a.push(` await corsair.keys.${e}.set_${g}(value)`);for(let g of p){let l=d==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(d)}).${e}`;a.push(` await ${l}.keys.set_${g}(value)`)}n(a.join(`
5
- `))}}return y}async function Q(e,t,r,i){let o=new Set;for(let f of e.values())await z(f.pluginId,f.authType,f.integration,f.account,f.integrationFields,f.accountFields,t,r,i)&&o.add(f.pluginId);return o}async function V(e,t,r,i,o){if(!W(h)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let f=h,d=new Set(t.map(n=>n.id));for(let[n,u]of Object.entries(f)){if(!d.has(n))continue;if(!r.has(n)){i(`[corsair:setup] Skipping backfill for '${n}' \u2014 auth not configured.`);continue}let c=b(e)?e[n]:void 0,p=b(c)?c.api:void 0;if(p)for(let[y,s]of Object.entries(u))for(let[a,g]of Object.entries(s)){i(`[corsair:setup] Backfilling ${n} \u203A ${y}.${a}...`);try{let l=b(p)?p[y]:void 0;await m(l,a)?.(g)}catch(l){o(`[corsair:setup] ${n} \u203A ${y}.${a} failed: `+(l instanceof Error?l.message:String(l)))}}}}export{se as a};
@@ -1,26 +0,0 @@
1
- import{a as he,b as X}from"./chunk-2PB34FTK.js";import{a as ye}from"./chunk-ZGVIF3UY.js";import{createCipheriv as me,createDecipheriv as ke,randomBytes as U,scrypt as Ze}from"crypto";import{promisify as je}from"util";var be=je(Ze),q="aes-256-gcm",we=12,z=16,Le=16,j=32;function F(){return U(j).toString("base64")}async function $(e,t){let n=U(Le),o=await be(t,n,j),r=U(we),i=me(q,o,r,{authTagLength:z}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[n.toString("base64"),r.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function v(e,t){let[n,o,r,i]=e.split(":");if(!n||!o||!r||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(n,"base64"),a=Buffer.from(o,"base64"),d=Buffer.from(r,"base64"),c=Buffer.from(i,"base64"),l=await be(t,s,j),p=ke(q,l,a,{authTagLength:z});return p.setAuthTag(d),Buffer.concat([p.update(c),p.final()]).toString("utf8")}function ee(e,t){let n=Buffer.from(t,"base64"),o=U(we),r=me(q,n,o,{authTagLength:z}),i=Buffer.concat([r.update(e,"utf8"),r.final()]),s=r.getAuthTag();return[o.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function ne(e,t){let[n,o,r]=e.split(":");if(!n||!o||!r)throw new Error("Invalid encrypted data format");let i=Buffer.from(t,"base64"),s=Buffer.from(n,"base64"),a=Buffer.from(o,"base64"),d=Buffer.from(r,"base64"),c=ke(q,i,s,{authTagLength:z});return c.setAuthTag(a),Buffer.concat([c.update(d),c.final()]).toString("utf8")}function N(e,t){let n={};for(let[o,r]of Object.entries(e))n[o]=ee(r,t);return n}function K(e,t){let n={};for(let[o,r]of Object.entries(e))n[o]=ne(r,t);return n}function L(e,t,n){let o=K(e,t);return N(o,n)}function G(e,t){let n=[];e||n.push("database"),t||n.push("kek");let o={};return new Proxy(o,{get(r,i){let s=n.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${n.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
2
-
3
- To generate a KEK, run: openssl rand -base64 ${j}`)}})}var W={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"]}};function Te(e,t,n){let o={};for(let r of n)o[`get_${r}`]=async()=>(await e())[r]??null,o[`set_${r}`]=async i=>{let s=[null,void 0,""].includes(i)?null:i;await t({[r]:s})};return o}var te=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function J(e){let{authType:t,integrationName:n,kek:o,database:r,extraIntegrationFields:i=[]}=e,s=[...W[t].integration,...i],a=null,d={kek:o,integrationName:n,getIntegration:async()=>{if(a)return a;let u=await r.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!u)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);return a={id:u.id,config:te(u.config),dek:u.dek??null},a},updateIntegration:async u=>{let f=await d.getIntegration();await r.db.updateTable("corsair_integrations").set({...u.config!==void 0?{config:u.config}:{},...u.dek!==void 0?{dek:u.dek}:{},updated_at:new Date}).where("id","=",f.id).execute(),a=null}},c=null,l=async()=>{if(c)return c;let u=await d.getIntegration();if(!u.dek)throw new Error(`No DEK found for integration "${n}". Initialize the integration first.`);return c=await v(u.dek,o),c},p=async()=>{let u=await d.getIntegration(),f=await l(),m=u.config;return!m||Object.keys(m).length===0?{}:K(m,f)};return{get_dek:l,issue_new_dek:async()=>{let u=await d.getIntegration(),f=F(),m={};if(u.dek){let P=await v(u.dek,o),b=u.config;b&&Object.keys(b).length>0&&(m=L(b,P,f))}let k=await $(f,o);return await d.updateIntegration({config:m,dek:k}),c=f,f},...Te(p,async u=>{let f=await l(),m;try{m=await p()}catch(b){console.error(`[corsair] Failed to decrypt config for integration "${n}", starting fresh:`,b),m={}}let k={...m};for(let[b,y]of Object.entries(u))y===null?delete k[b]:k[b]=y;let P=N(k,f);await d.updateIntegration({config:P})},s)}}function V(e){let{authType:t,integrationName:n,tenantId:o,kek:r,database:i,extraAccountFields:s=[]}=e,a=[...W[t].account,...s],d=null,c=null,l=async()=>{if(c)return c;let y=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!y)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);return c={id:y.id,config:te(y.config),dek:y.dek??null},c},p={kek:r,integrationName:n,tenantId:o,getIntegration:l,getAccount:async()=>{if(d)return d;let y=await l(),w=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",o).where("integration_id","=",y.id).executeTakeFirst();if(!w)throw new Error(`Account not found for tenant "${o}" and integration "${n}". Make sure to create the account first.`);return d={id:w.id,config:te(w.config),dek:w.dek??null},d},updateAccount:async y=>{let w=await p.getAccount();await i.db.updateTable("corsair_accounts").set({...y.config!==void 0?{config:y.config}:{},...y.dek!==void 0?{dek:y.dek}:{},updated_at:new Date}).where("id","=",w.id).execute(),d=null}},h=null,g=null,u=async()=>{if(h)return h;let y=await p.getAccount();if(!y.dek)throw new Error(`No DEK found for account (tenant: "${o}", integration: "${n}"). Initialize the account first.`);return h=await v(y.dek,r),h},f=async()=>{if(g)return g;let y=await p.getIntegration();if(!y.dek)throw new Error(`No DEK found for integration "${n}". Initialize the integration first.`);return g=await v(y.dek,r),g},m=async()=>{let y=await p.getAccount(),w=await u(),T=y.config;return!T||Object.keys(T).length===0?{}:K(T,w)},k=async()=>{let y=await p.getIntegration(),w=await f(),T=y.config;return!T||Object.keys(T).length===0?{}:K(T,w)},b={get_dek:u,issue_new_dek:async()=>{let y=await p.getAccount(),w=F(),T={};if(y.dek){let C=await v(y.dek,r),A=y.config;A&&Object.keys(A).length>0&&(T=L(A,C,w))}let _=await $(w,r);return await p.updateAccount({config:T,dek:_}),h=w,w},...Te(m,async y=>{let w=await u(),T;try{T=await m()}catch(A){console.error(`[corsair] Failed to decrypt config for account (tenant: "${o}", integration: "${n}"), starting fresh:`,A),T={}}let _={...T};for(let[A,E]of Object.entries(y))E===null?delete _[A]:_[A]=E;let C=N(_,w);await p.updateAccount({config:C})},a)};return t==="oauth_2"&&(b.get_integration_credentials=async()=>{let y=await k();return{client_id:y.client_id||null,client_secret:y.client_secret||null,redirect_url:y.redirect_url??null}}),b}async function Ce(e,t,n){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!o)throw new Error(`Integration "${t}" not found.`);let r=F(),i=await $(r,n);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",o.id).execute(),r}async function Pe(e,t,n,o){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!r)throw new Error(`Integration "${t}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n).where("integration_id","=",r.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${n}" and integration "${t}".`);let s=F(),a=await $(s,o);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var We=async(e,t)=>(console.error(`[corsair:${t.pluginId}:${t.operation}]`,{error:e.message,input:t.input}),{maxRetries:0});async function xe(e,t,n,o,r){let i={pluginId:t,operation:n,input:o,originalError:e},s=Object.keys(r).find(c=>r[c]?.match(e,i));return await(r[s||"DEFAULT"]?.handler||We)(e,i)}import{randomBytes as He}from"crypto";import{v4 as Ue}from"uuid";var qe={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 ze(e,t,n){return n!==void 0?n:qe[t][e]}function Re(e){let t=/(\d+)(d|h|m|s)/g,n=0,o;for(;(o=t.exec(e))!==null;){let r=parseInt(o[1],10);switch(o[2]){case"d":n+=r*864e5;break;case"h":n+=r*36e5;break;case"m":n+=r*6e4;break;case"s":n+=r*1e3;break}}return n>0?n:600*1e3}function Ee(e){return{async find_by_permission_id(t){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("id","=",t).executeTakeFirst()},async find_by_token(t){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("token","=",t).executeTakeFirst()},async set_executing(t){e&&await e.db.updateTable("corsair_permissions").set({status:"executing",updated_at:new Date}).where("id","=",t).execute()},async set_completed(t){e&&await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",t).execute()}}}async function Ae(e,t,n){let o=Date.now()+n;for(;Date.now()<o;){let r=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",t).executeTakeFirst();if(!r)return{result:"blocked",reason:"pending"};if(r.status==="approved")return{result:"allow",onComplete:async()=>{await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",t).execute()}};if(r.status==="denied")return{result:"blocked",reason:"denied"};if(r.status==="expired"||r.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(i=>setTimeout(i,500))}return{result:"blocked",reason:"timeout"}}async function _e(e){let t=ze(e.riskLevel,e.mode,e.override);if(t==="allow")return{result:"allow"};let n=e.meta?.irreversible?" (irreversible)":"",o=e.meta?.description?`${e.meta.description}${n}`:`${e.pluginId}.${e.endpointPath}${n}`;if(t==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
4
- Action: ${o}`,`
5
- To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let r=JSON.stringify(e.args),i=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","=",r).where("tenant_id","=",s).where("expires_at",">",i).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(a){if(a.status==="approved"){let u=e.db,f=a.id;return{result:"allow",onComplete:async()=>{await u.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.`,`
6
- Action: ${o}`,`
7
- Permission ID: ${a.id}`,`
8
- Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ae(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token})}let d=Ue(),c=He(32).toString("hex"),l=e.timeoutMs??600*1e3,p=new Date(Date.now()+l).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:d,created_at:new Date,updated_at:new Date,token:c,plugin:e.pluginId,endpoint:e.endpointPath,args:r,tenant_id:s,status:"pending",expires_at:p}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
9
- Action: ${o}`,`
10
- Permission ID: ${d}`,`
11
- Permission token: ${c}`,`
12
- Expires at: ${p}`,`
13
- Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ae(e.db,d,l):{result:"blocked",reason:"pending",id:d,token:c}}function Ge(e){return typeof e=="function"}function oe({endpoints:e,hooks:t,ctx:n,tree:o,pluginId:r,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}){for(let[g,u]of Object.entries(e)){let f=t?.[g];if(Ge(u)){let m=f,k=[...s,g].join("."),P=async(b={})=>{let y;if(d){let E=c?.[k],{result:S,reason:I,onComplete:Z,token:D,id:O}=await _e({pluginId:r,endpointPath:k,args:b,mode:d.mode,override:d.overrides?.[k],riskLevel:E?.riskLevel??"write",meta:E,db:l,timeoutMs:p?Re(p.timeout):void 0,tenantId:h,approvalMode:p?.mode});if(S==="blocked"){let x;throw I==="denied"?x=`Action '${k}' was denied by the user. Await further instructions before proceeding.`:I==="policy"?x=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`:I==="timeout"?x=`Action '${k}' timed out waiting for approval.`:p?.formatAsyncMessage&&D&&O?x=p.formatAsyncMessage({token:D,id:O,plugin:r,endpoint:k,args:b}):x=`Action '${k}' requires user approval before it can run.`,new Error(x)}y=Z}let w=async(E,S,I)=>{try{return await u(S,I)}catch(Z){if(Z instanceof Error){let D=await xe(Z,r,k,typeof I=="object"&&I!==null?I:{args:I},i);if(E<(D.maxRetries||0)){let O=E+1;console.log(`Retrying (${O} / ${D.maxRetries})...`);let x;if(D.headersRetryAfterMs)x=D.headersRetryAfterMs;else switch(D.retryStrategy){case"exponential_backoff":x=Math.pow(2,O-1)*1e3;break;case"exponential_backoff_jitter":let Q=Math.pow(2,O-1)*1e3,Be=(Math.random()-.5)*1e3;x=Math.max(0,Q+Be);break;case"linear_1s":x=1e3;break;case"linear_2s":x=2e3;break;case"linear_3s":x=3e3;break;case"linear_4s":x=4e3;break;default:x=1e3;break}await new Promise(Q=>setTimeout(Q,x)),await w(O,S,I),console.log(`[corsair:${r}:${k}] Retry strategy:`,D)}}throw Z}},T=a?await a(n,"endpoint"):void 0;if(!m?.before&&!m?.after){let E=await w(0,{...n,key:T},b);return await y?.(),E}let _={...n,key:T},C=m.before?await m.before(_,b):{ctx:_,args:b,continue:!0,passToAfter:void 0};if(C.continue===!1)return;let A=await w(0,C.ctx,C.args);return await m.after?.(C.ctx,A,C.passToAfter),await y?.(),A};o[g]=P}else if(u&&typeof u=="object"){let m={};oe({endpoints:u,hooks:f,ctx:n,tree:m,pluginId:r,errorHandlers:i,currentPath:[...s,g],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}),o[g]=m}}}function Je(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function re({webhooks:e,hooks:t,ctx:n,webhooksTree:o,keyBuilder:r}){for(let[i,s]of Object.entries(e)){let a=t?.[i];if(Je(s)){let d=a,c=async l=>{let p=(g,u)=>s.handler(g,u),h=r?await r(n,"webhook"):void 0;return!d?.before&&!d?.after?p({...n,key:h},l):(async()=>{let g={...n,key:h},u=d.before?await d.before(g,l):{ctx:g,args:l,continue:!0,passToAfter:void 0};if(u.continue===!1)return;let f=await p(u.ctx,u.args);return f?.success===!0&&await d.after?.(u.ctx,f,u.passToAfter),f})()};o[i]={match:s.match,handler:c}}else if(s&&typeof s=="object"){let d={};re({webhooks:s,hooks:a,ctx:n,webhooksTree:d,keyBuilder:r}),o[i]=d}}}function Ve(e,t,n){let o=null;return async()=>{if(o)return o;if(!e)throw new Error("Database not configured");let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!r)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n).where("integration_id","=",r.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${n}" and integration "${t}". Make sure to create the account first.`);return o=i.id,o}}function Ye(e,t,n,o,r){return e?X(e.db,t,n,o,r):{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 ie(e,t){let{database:n,tenantId:o,kek:r,rootErrorHandlers:i,approvalConfig:s}=t,a={},d={};for(let c of e)a[c.id]={},d[c.id]={};for(let c of e){let l=c.schema,p=o??"default",h=Ve(n,c.id,p);if(l?.entities){let C={};for(let[A,E]of Object.entries(l.entities)){let S=n?X(n.db,h,A,l.version,E):Ye(void 0,h,A,l.version,E);C[A]=S}d[c.id].db=C,a[c.id].db=C}let g=c.options,u=c.authConfig,f;if(n&&r&&g?.authType){let C=u?.[g.authType]?.account??[];f=V({authType:g.authType,integrationName:c.id,tenantId:p,kek:r,database:n,extraAccountFields:C}),a[c.id].keys=f}let m={database:n,db:d[c.id]?.db??{},$getAccountId:h,...c.options?{options:c.options}:{},...f?{keys:f,authType:g?.authType}:{},...o?{tenantId:o}:{}},k=c.endpoints??{},P=c.hooks,b={...i,...c.errorHandlers},y={},w=c.options?.permissions;oe({endpoints:k,hooks:P,ctx:m,tree:y,pluginId:c.id,errorHandlers:b,currentPath:[],keyBuilder:c.keyBuilder,permissionsConfig:w,endpointMeta:c.endpointMeta,database:n,approvalConfig:s,tenantId:o}),Object.keys(y).length>0&&(a[c.id].api=y),m.endpoints=y;let T=c.webhooks??{},_=c.webhookHooks;if(Object.keys(T).length>0){let C={};re({webhooks:T,hooks:_,ctx:m,webhooksTree:C,keyBuilder:c.keyBuilder}),a[c.id].webhooks=C,c.pluginWebhookMatcher&&(a[c.id].pluginWebhookMatcher=c.pluginWebhookMatcher)}}return a}function Ie(e,t,n){let o={};for(let r of e){let i=r.options,s=r.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],d=J({authType:i.authType,integrationName:r.id,kek:n,database:t,extraIntegrationFields:a});o[r.id]=d}}return o}async function De(e,t,n,o,r="pending"){if(!e)return null;try{let i=he(),s=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:s,updated_at:s,account_id:t,event_type:n,payload:o,status:r}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function Qe(e,t,n,o="pending"){try{let r=await e.$getAccountId();return De(e.database,r,t,n,o)}catch(r){return console.warn("Failed to log event:",r),null}}import*as ve from"https";import*as Oe from"querystring";function Fe(e,t,n,o,r){let i=new URL(o.tokenUrl),s=o.tokenAuthMethod==="basic";return new Promise((a,d)=>{let c={code:e.trim(),redirect_uri:r,grant_type:"authorization_code"};s||(c.client_id=t,c.client_secret=n);let l=Oe.stringify(c),p={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(l).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${t}:${n}`).toString("base64")}`);let h=ve.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},g=>{let u="";g.on("data",f=>{u+=f}),g.on("end",()=>{if(g.statusCode!==200){d(new Error(`Token exchange failed (${g.statusCode}): ${u}`));return}try{a(JSON.parse(u))}catch{d(new Error(`Token endpoint returned non-JSON response: ${u}`))}})});h.on("error",g=>d(new Error(`Request failed: ${g.message}`))),h.write(l),h.end()})}var $e=["ably","airtable","amplitude","asana","box","cal","calendly","cursor","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","github","gitlab","gmail","googlecalendar","googledrive","googlesheets","hackernews","hubspot","intercom","jira","linear","monday","notion","onedrive","openweathermap","oura","outlook","pagerduty","posthog","razorpay","reddit","resend","sentry","sharepoint","slack","spotify","strava","stripe","tavily","teams","telegram","todoist","trello","twitter","twitterapiio","typeform","vapi","youtube","zoom"];var Ke=" ";function R(e){let t=e._def,n=t.typeName;switch(n){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(t.value);case"ZodEnum":return t.values.map(o=>String(o)).join(" | ");case"ZodOptional":return R(t.innerType);case"ZodNullable":return`${R(t.innerType)} | null`;case"ZodArray":{let o=t.type,i=o._def.typeName==="ZodUnion",s=R(o);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let o=t.shape(),r=Object.entries(o);return r.length===0?"{}":`{ ${r.map(([s,a])=>{let d=a._def.typeName;return`${d==="ZodOptional"||d==="ZodNullable"?s+"?":s}: ${R(a)}`}).join(", ")} }`}case"ZodUnion":return t.options.map(R).join(" | ");case"ZodIntersection":return`${R(t.left)} & ${R(t.right)}`;case"ZodEffects":return R(t.schema);default:return(n??"unknown").replace("Zod","").toLowerCase()}}function H(e,t){let n=e._def,o=n.typeName;if(o==="ZodOptional"||o==="ZodEffects")return H(o==="ZodOptional"?n.innerType:n.schema,t);if(o!=="ZodObject")return R(e);let r=n.shape(),i=Object.entries(r);if(i.length===0)return"{}";let s=Ke.repeat(t+1),a=Ke.repeat(t),d=[];for(let[c,l]of i){let p=l._def,h=p.typeName,u=h==="ZodOptional"||h==="ZodNullable"?`${c}?`:c,f=h==="ZodOptional"||h==="ZodNullable"?p.innerType:l,m=f?._def,k=m?.typeName,P=m?.description,b=P?` // ${P}`:"";k==="ZodObject"?d.push(`${s}${u}: ${H(f,t+1)}${b}`):d.push(`${s}${u}: ${R(l)}${b}`)}return`{
14
- ${d.join(`
15
- `)}
16
- ${a}}`}var pe=["equals","contains","startsWith","endsWith","in"],Xe=["equals","gt","gte","lt","lte","in"],en=["equals"],nn=["equals","before","after","between"];function ce(e){let t=e._def;switch(t.typeName){case"ZodOptional":case"ZodNullable":case"ZodDefault":return ce(t.innerType);case"ZodEffects":return ce(t.schema);case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Y(e){let t=e._def,n=t.typeName;if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")return Y(t.innerType);if(n==="ZodEffects")return Y(t.schema);if(n!=="ZodObject")return{};let o=t.shape(),r={};for(let[i,s]of Object.entries(o)){let a=ce(s);a==="string"?r[i]={type:"string",operators:pe}:a==="number"?r[i]={type:"number",operators:Xe}:a==="boolean"?r[i]={type:"boolean",operators:en}:a==="date"&&(r[i]={type:"date",operators:nn})}return r}function Se(e,t){for(let[n,o]of Object.entries(e))if(n.toLowerCase()===t)return[n,o]}function de(e,t,n){for(let[o,r]of Object.entries(e)){let i=[...t,o];typeof r=="function"?n.push(i.join(".")):r!==null&&typeof r=="object"&&de(r,i,n)}}function ue(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function le(e,t,n){for(let[o,r]of Object.entries(e)){let i=[...t,o];ue(r)?n.push(i.join(".")):r!==null&&typeof r=="object"&&le(r,i,n)}}function ge(e,t){if(t.length===0)return null;let[n,...o]=t,r=Object.entries(e).find(([a])=>a.toLowerCase()===n);if(!r)return null;let[i,s]=r;if(o.length===0)return ue(s)?[i]:null;if(s!==null&&typeof s=="object"&&!ue(s)){let a=ge(s,o);if(a!==null)return[i,...a]}return null}function Ne(e,t){let n=[];n.push(`${e}({`),n.push(" webhookHooks: {");for(let i=0;i<t.length;i++){let s=" ".repeat(i+2);n.push(`${s}${t[i]}: {`)}let o=" ".repeat(t.length+2),r=o+" ";n.push(`${o}before(ctx, args) {`),n.push(`${r}return { ctx, args };`),n.push(`${o}},`),n.push(`${o}after(ctx, response) {`),n.push(`${o}},`);for(let i=t.length-1;i>=0;i--){let s=" ".repeat(i+2);n.push(`${s}},`)}return n.push(" },"),n.push("})"),n.join(`
17
- `)}var tn=new Set($e);function M(e,t){let n=t?.type??"api",o=t?.plugin;if(o!==void 0){let i=e.find(a=>a.id===o);if(!i)return tn.has(o)?`This plugin (${o}) is not configured. Please add it to the Corsair instance to see its associated methods.`:M(e);if(n==="webhooks"){if(!i.webhooks)return[];let a=[];return le(i.webhooks,[],a),a.map(d=>`${i.id}.webhooks.${d}`)}if(n==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(d=>`${i.id}.db.${d}.search`):[]}if(!i.endpoints)return[];let s=[];return de(i.endpoints,[],s),s.map(a=>`${i.id}.api.${a}`)}let r={};if(n==="webhooks")for(let i of e){if(!i.webhooks)continue;let s=[];le(i.webhooks,[],s),r[i.id]=s.map(a=>`${i.id}.webhooks.${a}`)}else if(n==="db")for(let i of e){let s=i.schema?.entities;s&&(r[i.id]=Object.keys(s).map(a=>`${i.id}.db.${a}.search`))}else for(let i of e){if(!i.endpoints)continue;let s=[];de(i.endpoints,[],s),r[i.id]=s.map(a=>`${i.id}.api.${a}`)}return r}function B(e,t){if(e){for(let[n,o]of Object.entries(e))if(n.toLowerCase()===t)return o}}function on(e,t){let n=e.toLowerCase(),o=t.toLowerCase();if(!n.startsWith(`${o}.`)){let i=n.slice(t.length+1),s=i.startsWith(".")?i.slice(1):i;return s.startsWith("api.")&&(s=s.slice(4)),{shortPath:s,lookupKey:s}}let r=e.slice(t.length+1);return r.toLowerCase().startsWith("api.")&&(r=r.slice(4)),{shortPath:r,lookupKey:r.toLowerCase()}}function se(e,t){return typeof e=="string"?e:Array.isArray(e)?`${t}:
18
- ${e.join(", ")}`:`${t}:
19
- `+Object.entries(e).map(([n,o])=>` ${n}: ${o.join(", ")}`).join(`
20
- `)}function jn(e,t){let n=t.toLowerCase(),o=n.indexOf(".");if(o!==-1){let r=n.slice(0,o),i=n.slice(o+1),s=e.find(a=>a.id===r);if(s){if(i.startsWith("db.")){let l=i.slice(3),p=l.lastIndexOf(".");if(p!==-1){let h=l.slice(0,p),g=l.slice(p+1),u=s.schema?.entities;if(g==="search"&&u){let f=Se(u,h);if(f){let[m,k]=f,P=Y(k),b=[`Search ${r} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${pe.join(", ")}]`];for(let[y,w]of Object.entries(P))b.push(` ${y}?: ${w.type} [${w.operators.join(", ")}]`);return b.push("}"),b.join(`
21
- `)}}}return se(M(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let l=i.slice(9);if(s.webhooks){let p=ge(s.webhooks,l.split("."));if(p!==null){let h=p.join("."),g=B(s.webhookSchemas,h.toLowerCase()),u=g?.response?R(g.response):null,f=[];return g?.description&&f.push(g.description),g?.payload&&f.push(`payload ${H(g.payload,0)}`),u&&f.push(`response: ${u}`),f.push(`usage:
22
- ${Ne(r,p)}`),f.join(`
23
-
24
- `)}}return se(M(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let d=B(s.endpointMeta,a),c=B(s.endpointSchemas,a);if(d||c){let l=[],p=[d?.riskLevel?`[${d.riskLevel}]`:"",d?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),h=[d?.description,p].filter(Boolean).join(" ");return h&&l.push(h),c?.input&&l.push(`input ${H(c.input,0)}`),c?.output&&l.push(`output ${H(c.output,0)}`),l.join(`
25
-
26
- `)}}}return se(M(e),"Path not found. Available operations")}function Me(e){let t=e;for(;;){let n=t._def,o=n.typeName;if(o==="ZodOptional"||o==="ZodNullable"||o==="ZodDefault"){t=n.innerType;continue}if(o==="ZodEffects"){t=n.schema;continue}return t}}function ae(e){if(e===void 0)return{kind:"inline",type:"unknown"};let t=Me(e),n=t._def;if(n.typeName==="ZodObject"){let r=n.shape(),i=[];for(let[s,a]of Object.entries(r)){let c=a._def.typeName,l=c==="ZodOptional"||c==="ZodNullable",p=Me(a),g=p._def?.description;i.push({key:s,optional:l,type:R(p),description:g})}return{kind:"object",fields:i}}return{kind:"inline",type:R(t)}}function rn(e,t){let n=M(e,{plugin:t,type:"api"});if(typeof n=="string")return{ok:!1,error:n};if(!Array.isArray(n))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let o=e.find(l=>l.id===t);if(!o)return{ok:!1,error:`Plugin "${t}" is not configured on this instance.`};let r=[];for(let l of n){let{shortPath:p,lookupKey:h}=on(l,t),g=B(o.endpointMeta,h),u=B(o.endpointSchemas,h);!g&&!u||r.push({path:l,shortPath:p,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:ae(u?.input),output:ae(u?.output)})}r.sort((l,p)=>l.path.localeCompare(p.path));let i=[],s=M(e,{plugin:t,type:"webhooks"});if(Array.isArray(s)&&o.webhooks)for(let l of s){let h=l.toLowerCase().slice(t.length+1),g=h.startsWith(".")?h.slice(1):h;if(!g.startsWith("webhooks."))continue;let u=g.slice(9),f=ge(o.webhooks,u.split("."));if(f===null)continue;let m=f.join("."),k=B(o.webhookSchemas,m.toLowerCase()),P=k?.response?R(k.response):void 0;i.push({path:l,description:k?.description,payload:ae(k?.payload),responseType:P,usageExample:Ne(t,f)})}i.sort((l,p)=>l.path.localeCompare(p.path));let a=[],d=M(e,{plugin:t,type:"db"}),c=o.schema?.entities;if(Array.isArray(d)&&c)for(let l of d){let h=l.toLowerCase().slice(t.length+1),g=h.startsWith(".")?h.slice(1):h;if(!g.startsWith("db."))continue;let u=g.slice(3),f=u.lastIndexOf(".");if(f===-1)continue;let m=u.slice(0,f);if(u.slice(f+1)!=="search")continue;let P=Se(c,m);if(!P)continue;let[b,y]=P,w=Y(y),T=Object.entries(w).map(([_,C])=>({field:_,type:C.type,operators:C.operators}));a.push({path:l,entityName:b,filters:[{field:"entity_id",type:"string",operators:pe},...T]})}return a.sort((l,p)=>l.path.localeCompare(p.path)),{ok:!0,data:{pluginId:t,api:r,webhooks:i,db:a}}}var fe=Symbol.for("corsair:internal");function zn(e){let t=e.database?ye(e.database):void 0,n=t&&e.kek?Ie(e.plugins,t,e.kek):G(!!t,!!e.kek),o={plugins:e.plugins,database:t,kek:e.kek,multiTenancy:!!e.multiTenancy,approval:e.approval},r=Ee(t);if(e.multiTenancy)return Object.assign({withTenant:s=>{if(!s)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let a=ie(e.plugins,{database:t,tenantId:s,kek:e.kek,rootErrorHandlers:e.errorHandlers,approvalConfig:e.approval});return Object.assign(a,{[fe]:o})},keys:n,permissions:r},{[fe]:o});let i=ie(e.plugins,{database:t,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,approvalConfig:e.approval});return Object.assign({},i,{keys:n,permissions:r,[fe]:o})}export{F as a,$ as b,v as c,ee as d,ne as e,N as f,K as g,L as h,W as i,J as j,V as k,Ce as l,Pe as m,De as n,Qe as o,Fe as p,$e as q,M as r,jn as s,rn as t,fe as u,zn as v};
@@ -1 +0,0 @@
1
- import{z as t}from"zod";var n=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),name:t.string(),config:t.record(t.unknown()).nullable().transform(e=>e??{}),dek:t.string().nullish()}),a=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),tenant_id:t.string(),integration_id:t.string(),config:t.record(t.unknown()).nullable().transform(e=>e??{}),dek:t.string().nullish()}),i=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),account_id:t.string(),entity_id:t.string(),entity_type:t.string(),version:t.string(),data:t.record(t.unknown()).nullable().transform(e=>e??{})}),o=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),account_id:t.string(),event_type:t.string(),payload:t.record(t.unknown()).nullable().transform(e=>e??{}),status:t.enum(["pending","processing","completed","failed"]).optional()}),s=t.object({id:t.string(),created_at:t.coerce.date(),updated_at:t.coerce.date(),token:t.string(),plugin:t.string(),endpoint:t.string(),args:t.string(),tenant_id:t.string(),status:t.enum(["pending","approved","executing","completed","denied","expired","failed"]).default("pending"),expires_at:t.string(),error:t.string().nullable().optional()});export{n as a,a as b,i as c,o as d,s as e};