corsair 0.1.64 → 0.1.65

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.
@@ -1,26 +1,26 @@
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 Se}from"crypto";import{promisify as Ne}from"util";var be=Ne(Se),z="aes-256-gcm",we=12,q=16,Be=16,j=32;function O(){return U(j).toString("base64")}async function K(e,t){let n=U(Be),o=await be(t,n,j),r=U(we),i=me(z,o,r,{authTagLength:q}),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(z,l,a,{authTagLength:q});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(z,n,o,{authTagLength:q}),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(z,i,s,{authTagLength:q});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 M(e,t){let n={};for(let[o,r]of Object.entries(e))n[o]=ne(r,t);return n}function W(e,t,n){let o=M(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.
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
2
 
3
- To generate a KEK, run: openssl rand -base64 ${j}`)}})}var L={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 V(e){let{authType:t,integrationName:n,kek:o,database:r,extraIntegrationFields:i=[]}=e,s=[...L[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?{}:M(m,f)};return{get_dek:l,issue_new_dek:async()=>{let u=await d.getIntegration(),f=O(),m={};if(u.dek){let P=await v(u.dek,o),b=u.config;b&&Object.keys(b).length>0&&(m=W(b,P,f))}let k=await K(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,g]of Object.entries(u))g===null?delete k[b]:k[b]=g;let P=N(k,f);await d.updateIntegration({config:P})},s)}}function J(e){let{authType:t,integrationName:n,tenantId:o,kek:r,database:i,extraAccountFields:s=[]}=e,a=[...L[t].account,...s],d=null,c=null,l=async()=>{if(c)return c;let g=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!g)throw new Error(`Integration "${n}" not found. Make sure to create the integration first.`);return c={id:g.id,config:te(g.config),dek:g.dek??null},c},p={kek:r,integrationName:n,tenantId:o,getIntegration:l,getAccount:async()=>{if(d)return d;let g=await l(),w=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",o).where("integration_id","=",g.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 g=>{let w=await p.getAccount();await i.db.updateTable("corsair_accounts").set({...g.config!==void 0?{config:g.config}:{},...g.dek!==void 0?{dek:g.dek}:{},updated_at:new Date}).where("id","=",w.id).execute(),d=null}},h=null,y=null,u=async()=>{if(h)return h;let g=await p.getAccount();if(!g.dek)throw new Error(`No DEK found for account (tenant: "${o}", integration: "${n}"). Initialize the account first.`);return h=await v(g.dek,r),h},f=async()=>{if(y)return y;let g=await p.getIntegration();if(!g.dek)throw new Error(`No DEK found for integration "${n}". Initialize the integration first.`);return y=await v(g.dek,r),y},m=async()=>{let g=await p.getAccount(),w=await u(),T=g.config;return!T||Object.keys(T).length===0?{}:M(T,w)},k=async()=>{let g=await p.getIntegration(),w=await f(),T=g.config;return!T||Object.keys(T).length===0?{}:M(T,w)},b={get_dek:u,issue_new_dek:async()=>{let g=await p.getAccount(),w=O(),T={};if(g.dek){let C=await v(g.dek,r),A=g.config;A&&Object.keys(A).length>0&&(T=W(A,C,w))}let I=await K(w,r);return await p.updateAccount({config:T,dek:I}),h=w,w},...Te(m,async g=>{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 I={...T};for(let[A,R]of Object.entries(g))R===null?delete I[A]:I[A]=R;let C=N(I,w);await p.updateAccount({config:C})},a)};return t==="oauth_2"&&(b.get_integration_credentials=async()=>{let g=await k();return{client_id:g.client_id||null,client_secret:g.client_secret||null,redirect_url:g.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=O(),i=await K(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=O(),a=await K(s,o);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 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||Ze)(e,i)}import{randomBytes as je}from"crypto";import{v4 as We}from"uuid";var Le={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 He(e,t,n){return n!==void 0?n:Le[t][e]}function Ee(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 Re(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 Ie(e){let t=He(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}'.`,`
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
4
  Action: ${o}`,`
5
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
6
  Action: ${o}`,`
7
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=We(),c=je(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.`,`
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
9
  Action: ${o}`,`
10
10
  Permission ID: ${d}`,`
11
11
  Permission token: ${c}`,`
12
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 Ue(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[y,u]of Object.entries(e)){let f=t?.[y];if(Ue(u)){let m=f,k=[...s,y].join("."),P=async(b={})=>{let g;if(d){let R=c?.[k],{result:S,reason:_,onComplete:Z,token:D,id:F}=await Ie({pluginId:r,endpointPath:k,args:b,mode:d.mode,override:d.overrides?.[k],riskLevel:R?.riskLevel??"write",meta:R,db:l,timeoutMs:p?Ee(p.timeout):void 0,tenantId:h,approvalMode:p?.mode});if(S==="blocked"){let x;throw _==="denied"?x=`Action '${k}' was denied by the user. Await further instructions before proceeding.`:_==="policy"?x=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`:_==="timeout"?x=`Action '${k}' timed out waiting for approval.`:p?.formatAsyncMessage&&D&&F?x=p.formatAsyncMessage({token:D,id:F,plugin:r,endpoint:k,args:b}):x=`Action '${k}' requires user approval before it can run.`,new Error(x)}g=Z}let w=async(R,S,_)=>{try{return await u(S,_)}catch(Z){if(Z instanceof Error){let D=await xe(Z,r,k,typeof _=="object"&&_!==null?_:{args:_},i);if(R<(D.maxRetries||0)){let F=R+1;console.log(`Retrying (${F} / ${D.maxRetries})...`);let x;if(D.headersRetryAfterMs)x=D.headersRetryAfterMs;else switch(D.retryStrategy){case"exponential_backoff":x=Math.pow(2,F-1)*1e3;break;case"exponential_backoff_jitter":let Q=Math.pow(2,F-1)*1e3,$e=(Math.random()-.5)*1e3;x=Math.max(0,Q+$e);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(F,S,_),console.log(`[corsair:${r}:${k}] Retry strategy:`,D)}}throw Z}},T=a?await a(n,"endpoint"):void 0;if(!m?.before&&!m?.after){let R=await w(0,{...n,key:T},b);return await g?.(),R}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 g?.(),A};o[y]=P}else if(u&&typeof u=="object"){let m={};oe({endpoints:u,hooks:f,ctx:n,tree:m,pluginId:r,errorHandlers:i,currentPath:[...s,y],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}),o[y]=m}}}function ze(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(ze(s)){let d=a,c=async l=>{let p=(y,u)=>s.handler(y,u),h=r?await r(n,"webhook"):void 0;return!d?.before&&!d?.after?p({...n,key:h},l):(async()=>{let y={...n,key:h},u=d.before?await d.before(y,l):{ctx:y,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 qe(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 Ge(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=qe(n,c.id,p);if(l?.entities){let C={};for(let[A,R]of Object.entries(l.entities)){let S=n?X(n.db,h,A,l.version,R):Ge(void 0,h,A,l.version,R);C[A]=S}d[c.id].db=C,a[c.id].db=C}let y=c.options,u=c.authConfig,f;if(n&&r&&y?.authType){let C=u?.[y.authType]?.account??[];f=J({authType:y.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:y?.authType}:{},...o?{tenantId:o}:{}},k=c.endpoints??{},P=c.hooks,b={...i,...c.errorHandlers},g={},w=c.options?.permissions;oe({endpoints:k,hooks:P,ctx:m,tree:g,pluginId:c.id,errorHandlers:b,currentPath:[],keyBuilder:c.keyBuilder,permissionsConfig:w,endpointMeta:c.endpointMeta,database:n,approvalConfig:s,tenantId:o}),Object.keys(g).length>0&&(a[c.id].api=g),m.endpoints=g;let T=c.webhooks??{},I=c.webhookHooks;if(Object.keys(T).length>0){let C={};re({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 _e(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=V({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 Ve(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}}var ve=["ably","airtable","amplitude","asana","box","cal","calendly","cursor","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","github","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","youtube","zoom"];var Fe=" ";function E(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 E(t.innerType);case"ZodNullable":return`${E(t.innerType)} | null`;case"ZodArray":{let o=t.type,i=o._def.typeName==="ZodUnion",s=E(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}: ${E(a)}`}).join(", ")} }`}case"ZodUnion":return t.options.map(E).join(" | ");case"ZodIntersection":return`${E(t.left)} & ${E(t.right)}`;case"ZodEffects":return E(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 E(e);let r=n.shape(),i=Object.entries(r);if(i.length===0)return"{}";let s=Fe.repeat(t+1),a=Fe.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}: ${E(l)}${b}`)}return`{
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","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
14
  ${d.join(`
15
15
  `)}
16
- ${a}}`}var pe=["equals","contains","startsWith","endsWith","in"],Je=["equals","gt","gte","lt","lte","in"],Ye=["equals"],Qe=["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:Je}:a==="boolean"?r[i]={type:"boolean",operators:Ye}:a==="date"&&(r[i]={type:"date",operators:Qe})}return r}function Ke(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 Me(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 Xe=new Set(ve);function $(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 Xe.has(o)?`This plugin (${o}) is not configured. Please add it to the Corsair instance to see its associated methods.`:$(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 en(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}:
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
18
  ${e.join(", ")}`:`${t}:
19
19
  `+Object.entries(e).map(([n,o])=>` ${n}: ${o.join(", ")}`).join(`
20
- `)}function $n(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),y=l.slice(p+1),u=s.schema?.entities;if(y==="search"&&u){let f=Ke(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[g,w]of Object.entries(P))b.push(` ${g}?: ${w.type} [${w.operators.join(", ")}]`);return b.push("}"),b.join(`
21
- `)}}}return se($(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("."),y=B(s.webhookSchemas,h.toLowerCase()),u=y?.response?E(y.response):null,f=[];return y?.description&&f.push(y.description),y?.payload&&f.push(`payload ${H(y.payload,0)}`),u&&f.push(`response: ${u}`),f.push(`usage:
22
- ${Me(r,p)}`),f.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
23
 
24
- `)}}return se($(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(`
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
25
 
26
- `)}}}return se($(e),"Path not found. Available operations")}function Oe(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=Oe(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=Oe(a),y=p._def?.description;i.push({key:s,optional:l,type:E(p),description:y})}return{kind:"object",fields:i}}return{kind:"inline",type:E(t)}}function nn(e,t){let 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 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}=en(l,t),y=B(o.endpointMeta,h),u=B(o.endpointSchemas,h);!y&&!u||r.push({path:l,shortPath:p,description:y?.description,riskLevel:y?.riskLevel,irreversible:y?.irreversible,input:ae(u?.input),output:ae(u?.output)})}r.sort((l,p)=>l.path.localeCompare(p.path));let i=[],s=$(e,{plugin:t,type:"webhooks"});if(Array.isArray(s)&&o.webhooks)for(let l of s){let h=l.toLowerCase().slice(t.length+1),y=h.startsWith(".")?h.slice(1):h;if(!y.startsWith("webhooks."))continue;let u=y.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?E(k.response):void 0;i.push({path:l,description:k?.description,payload:ae(k?.payload),responseType:P,usageExample:Me(t,f)})}i.sort((l,p)=>l.path.localeCompare(p.path));let a=[],d=$(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),y=h.startsWith(".")?h.slice(1):h;if(!y.startsWith("db."))continue;let u=y.slice(3),f=u.lastIndexOf(".");if(f===-1)continue;let m=u.slice(0,f);if(u.slice(f+1)!=="search")continue;let P=Ke(c,m);if(!P)continue;let[b,g]=P,w=Y(g),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: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 Wn(e){let t=e.database?ye(e.database):void 0,n=t&&e.kek?_e(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=Re(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{O as a,K as b,v as c,ee as d,ne as e,N as f,M as g,W as h,L as i,V as j,J as k,Ce as l,Pe as m,De as n,Ve as o,ve as p,$ as q,$n as r,nn as s,fe as t,Wn as u};
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,4 +1,4 @@
1
- import{t as k,u as w}from"./chunk-5UALNYME.js";import{a as m}from"./chunk-7IH5DNUL.js";import{ZodBoolean as h,ZodDate as _,ZodEffects as $,ZodEnum as P,ZodNullable as K,ZodNumber as M,ZodObject as T,ZodOptional as v,ZodRecord as A,ZodString as j}from"zod";var b={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},pullRequests:{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 Y(e,c){let l=[],r=t=>{l.push(t),console.log(t)},o=t=>{l.push(t),console.warn(t)},g=c?.caller??"script",s=e[k];if(!s)throw new Error("setupCorsair: invalid corsair instance");if(s.multiTenancy)throw new Error("setupCorsair: multi-tenancy instances are not supported. Create your corsair instance without multiTenancy: true.");if(!s.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u=s.database.db,n=w({plugins:s.plugins,database:s.database.db,kek:s.kek});await D(u,o),await E(u,n,s.plugins,r),c?.credentials&&Object.keys(c.credentials).length>0&&await I(n,c.credentials,r,o);let a=await Z(n,s.plugins,r,g);return c?.backfill&&(r("[corsair:setup] Starting backfill..."),await L(n,s.plugins,a,r,o),r("[corsair:setup] Backfill complete.")),l.join(`
1
+ import{u as k,v as w}from"./chunk-4BDS3PPC.js";import{a as m}from"./chunk-7IH5DNUL.js";import{ZodBoolean as h,ZodDate as _,ZodEffects as $,ZodEnum as P,ZodNullable as K,ZodNumber as M,ZodObject as T,ZodOptional as v,ZodRecord as A,ZodString as j}from"zod";var b={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},pullRequests:{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 Y(e,c){let l=[],r=t=>{l.push(t),console.log(t)},o=t=>{l.push(t),console.warn(t)},g=c?.caller??"script",s=e[k];if(!s)throw new Error("setupCorsair: invalid corsair instance");if(s.multiTenancy)throw new Error("setupCorsair: multi-tenancy instances are not supported. Create your corsair instance without multiTenancy: true.");if(!s.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u=s.database.db,n=w({plugins:s.plugins,database:s.database.db,kek:s.kek});await D(u,o),await E(u,n,s.plugins,r),c?.credentials&&Object.keys(c.credentials).length>0&&await I(n,c.credentials,r,o);let a=await Z(n,s.plugins,r,g);return c?.backfill&&(r("[corsair:setup] Starting backfill..."),await L(n,s.plugins,a,r,o),r("[corsair:setup] Backfill complete.")),l.join(`
2
2
  `)}var O={...m};function p(e){if(e instanceof T){let c={};for(let[l,r]of Object.entries(e.shape))c[l]=p(r);return c}return e instanceof $?p(e.innerType()):e instanceof K?`${p(e.unwrap())} | null`:e instanceof v?`${p(e.unwrap())} | undefined`:e instanceof P?e.options.join(" | "):e instanceof j?"string":e instanceof M?"number":e instanceof h?"boolean":e instanceof _?"date":e instanceof A?"jsonb":"unknown"}async function D(e,c){let l=await e.introspection.getTables(),r=new Set(l.map(o=>o.name));for(let[o,g]of Object.entries(O))r.has(o)||c(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
3
3
  Schema: ${JSON.stringify(p(g),null,2)}`)}var C="default";async function E(e,c,l,r){let o=new Date,g=c.keys,s=c;for(let u of l){let n=u.id,a=await e.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!a){let f=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:f,name:n,config:{},created_at:o,updated_at:o}).execute(),a=await e.selectFrom("corsair_integrations").selectAll().where("id","=",f).executeTakeFirst(),r(`[corsair:setup] Created integration: ${n}`)}let t=g[n];if(a&&!a.dek&&t&&(await t.issue_new_dek(),r(`[corsair:setup] Issued integration DEK: ${n}`)),!a)continue;let i=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",C).where("integration_id","=",a.id).executeTakeFirst();if(!i){let f=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:f,tenant_id:C,integration_id:a.id,config:{},created_at:o,updated_at:o}).execute(),i=await e.selectFrom("corsair_accounts").selectAll().where("id","=",f).executeTakeFirst(),r(`[corsair:setup] Created account: ${n}`)}let d=s[n]?.keys;i&&!i.dek&&d&&(await d.issue_new_dek(),r(`[corsair:setup] Issued account DEK: ${n}`))}}async function I(e,c,l,r){let o=e.keys,g=e;for(let[s,u]of Object.entries(c)){let n=o[s],a=g[s]?.keys;for(let[t,i]of Object.entries(u)){let d=`set_${t}`;n&&typeof n[d]=="function"?(await n[d](i),l(`[corsair:setup] Set integration credential: ${s}.${t}`)):a&&typeof a[d]=="function"?(await a[d](i),l(`[corsair:setup] Set account credential: ${s}.${t}`)):r(`[corsair:setup] No setter found for '${s}.${t}' \u2014 skipping.`)}}}var S=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function x(e,c,l,r,o,g){let s=[],u=[];for(let a of Object.keys(l)){if(!a.startsWith("set_"))continue;let t=a.slice(4);if(S.has(t))continue;let i=l[`get_${t}`];if(!i)continue;let d=null;try{d=await i()}catch{}d||s.push(t)}for(let a of Object.keys(r)){if(!a.startsWith("set_"))continue;let t=a.slice(4);if(S.has(t))continue;let i=r[`get_${t}`];if(!i)continue;let d=null;try{d=await i()}catch{}d||u.push(t)}let n=s.length===0&&u.length===0;if(n)o(`[corsair:setup] '${e}' (${c}) is configured \u2713`);else{let a=[...s,...u];if(g==="cli"){let t=a.map(i=>`${i}=VALUE`).join(" ");o(`[corsair:setup] '${e}' (${c}) needs credentials. Run:
4
4
  corsair setup --${e} ${t}`)}else{let t=[`[corsair:setup] '${e}' (${c}) needs credentials. Call:`];for(let i of s)t.push(` await corsair.keys.${e}.set_${i}(value)`);for(let i of u)t.push(` await corsair.${e}.keys.set_${i}(value)`);o(t.join(`
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-DYzTFbSd.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-DLUKAEBX.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { A as AuthTypes, d as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DDWTZpI-.js';
4
- export { e as AccountFieldNames, j as AllProviders, h as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, f as BaseKeyManager, k as BaseProviders, G as BeforeHookResult, m as BindEndpoints, a0 as BindWebhooks, _ as Bivariant, n as BoundEndpointFn, o as BoundEndpointTree, a1 as BoundWebhook, a2 as BoundWebhookTree, i as CorsairClient, p as CorsairContext, q as CorsairEndpoint, t as CorsairErrorHandler, a as CorsairIntegration, H as CorsairKeyBuilder, J as CorsairKeyBuilderBase, z as CorsairPermissionsNamespace, C as CorsairPlugin, K as CorsairPluginContext, c as CorsairSingleTenantClient, b as CorsairTenantWrapper, a3 as CorsairWebhook, a4 as CorsairWebhookHandler, a5 as CorsairWebhookMatcher, L as EndpointHooks, M as EndpointMetaEntry, r as EndpointPathsOf, E as EndpointRiskLevel, s as EndpointTree, D as EnforcePermissionOptions, F as EnforcePermissionResult, u as ErrorContext, v as ErrorHandler, w as ErrorHandlerAndMatchFunction, x as ErrorMatcher, g as IntegrationFieldNames, N as KeyBuilderContext, O as OAuth2IntegrationCredentials, Q as OAuthConfig, S as PermissionMode, T as PermissionPolicy, l as PickAuth, P as PluginAuthConfig, U as PluginEndpointMeta, V as PluginPermissionsConfig, a6 as RawWebhookRequest, W as RequiredPluginEndpointMeta, X as RequiredPluginEndpointSchemas, Y as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, $ as UnionToIntersection, Z as WebhookHooks, a7 as WebhookPathsOf, a8 as WebhookRequest, a9 as WebhookResponse, aa as WebhookTree } from './index-DDWTZpI-.js';
3
+ import { A as AuthTypes, g as AccountKeyManagerFor, I as IntegrationKeyManagerFor, O as OAuthConfig } from './index-h_UAleEL.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-h_UAleEL.js';
5
5
  import 'kysely';
6
6
  import 'zod';
7
7
  import 'pg';
@@ -149,4 +149,16 @@ declare function initializeIntegrationDEK(database: CorsairDatabase, integration
149
149
  */
150
150
  declare function initializeAccountDEK(database: CorsairDatabase, integrationName: string, tenantId: string, kek: string): Promise<string>;
151
151
 
152
- export { AccountKeyManagerFor, AuthTypes, type EventLoggingContext, IntegrationKeyManagerFor, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, generateDEK, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, reEncryptConfig };
152
+ type TokenResponse = {
153
+ access_token?: string;
154
+ refresh_token?: string;
155
+ expires_in?: number;
156
+ token_type?: string;
157
+ };
158
+ /**
159
+ * Exchanges an OAuth authorization code for access/refresh tokens.
160
+ * Supports both 'body' (default) and 'basic' token auth methods.
161
+ */
162
+ declare function exchangeCodeForTokens(code: string, clientId: string, clientSecret: string, oauthConfig: OAuthConfig, redirectUri: string): Promise<TokenResponse>;
163
+
164
+ export { AccountKeyManagerFor, AuthTypes, type EventLoggingContext, IntegrationKeyManagerFor, OAuthConfig, type TokenResponse, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, exchangeCodeForTokens, generateDEK, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, reEncryptConfig };
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,s as p,t as q,u as r}from"./chunk-5UALNYME.js";import"./chunk-2PB34FTK.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{i as BASE_AUTH_FIELDS,q as CORSAIR_INTERNAL,k as createAccountKeyManager,r as createCorsair,j as createIntegrationKeyManager,g as decryptConfig,c as decryptDEK,e as decryptWithDEK,f as encryptConfig,b as encryptDEK,d as encryptWithDEK,a as generateDEK,m as initializeAccountDEK,l as initializeIntegrationDEK,p 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-4BDS3PPC.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,4 +1,4 @@
1
- import { E as EndpointRiskLevel, C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-DDWTZpI-.js';
1
+ import { E as EndpointRiskLevel, C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-h_UAleEL.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", "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", "youtube", "zoom"];
7
- type AllProviders = 'ably' | 'airtable' | 'amplitude' | 'asana' | 'box' | 'cal' | 'calendly' | 'cursor' | 'discord' | 'dodopayments' | 'dropbox' | 'exa' | 'figma' | 'firecrawl' | 'fireflies' | 'github' | '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' | 'youtube' | 'zoom' | (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", "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' | 'youtube' | 'zoom' | (string & {});
8
8
  type AuthTypes = 'oauth_2' | 'api_key' | 'bot_token';
9
9
  type PickAuth<T extends AuthTypes> = T;
10
10
 
@@ -1125,4 +1125,4 @@ type CorsairSingleTenantClient<Plugins extends readonly CorsairPlugin[]> = Corsa
1125
1125
  permissions: CorsairPermissionsNamespace;
1126
1126
  };
1127
1127
 
1128
- export { type UnionToIntersection$1 as $, type AuthTypes as A, type BaseAuthFieldConfig as B, type CorsairPlugin as C, type EnforcePermissionOptions as D, type EndpointRiskLevel as E, type EnforcePermissionResult as F, type BeforeHookResult as G, type CorsairKeyBuilder as H, type IntegrationKeyManagerFor as I, type CorsairKeyBuilderBase as J, type CorsairPluginContext as K, type EndpointHooks as L, type EndpointMetaEntry as M, type KeyBuilderContext as N, type OAuth2IntegrationCredentials as O, type PluginAuthConfig as P, type OAuthConfig as Q, type RetryStrategies as R, type PermissionMode as S, type PermissionPolicy as T, type PluginEndpointMeta as U, type PluginPermissionsConfig as V, type RequiredPluginEndpointMeta as W, type RequiredPluginEndpointSchemas as X, type RequiredPluginWebhookSchemas as Y, type WebhookHooks as Z, type Bivariant$2 as _, type CorsairIntegration as a, type BindWebhooks as a0, type BoundWebhook as a1, type BoundWebhookTree as a2, type CorsairWebhook as a3, type CorsairWebhookHandler as a4, type CorsairWebhookMatcher as a5, type RawWebhookRequest as a6, type WebhookPathsOf as a7, type WebhookRequest as a8, type WebhookResponse as a9, type WebhookTree as aa, type CorsairTenantWrapper as b, type CorsairSingleTenantClient as c, type AccountKeyManagerFor as d, type AccountFieldNames as e, type BaseKeyManager as f, type IntegrationFieldNames as g, BASE_AUTH_FIELDS as h, type CorsairClient as i, type AllProviders as j, BaseProviders as k, type PickAuth as l, type BindEndpoints as m, type BoundEndpointFn as n, type BoundEndpointTree as o, type CorsairContext as p, type CorsairEndpoint as q, type EndpointPathsOf as r, type EndpointTree as s, type CorsairErrorHandler as t, type ErrorContext as u, type ErrorHandler as v, type ErrorHandlerAndMatchFunction as w, type ErrorMatcher as x, type RetryStrategy as y, type CorsairPermissionsNamespace as z };
1128
+ export { type RequiredPluginWebhookSchemas as $, type AuthTypes as A, type BoundWebhookTree as B, type CorsairPlugin as C, type ErrorMatcher as D, type EndpointRiskLevel as E, type RetryStrategies as F, type RetryStrategy as G, type EnforcePermissionOptions as H, type IntegrationKeyManagerFor as I, type EnforcePermissionResult as J, type BeforeHookResult as K, type CorsairKeyBuilder as L, type CorsairKeyBuilderBase as M, type CorsairPluginContext as N, type OAuthConfig as O, type PluginAuthConfig as P, type EndpointHooks as Q, type RawWebhookRequest as R, type EndpointMetaEntry as S, type KeyBuilderContext as T, type PermissionMode as U, type PermissionPolicy as V, type WebhookResponse as W, type PluginEndpointMeta as X, type PluginPermissionsConfig as Y, type RequiredPluginEndpointMeta as Z, type RequiredPluginEndpointSchemas as _, type CorsairIntegration as a, type WebhookHooks as a0, type Bivariant$2 as a1, type UnionToIntersection$1 as a2, type BindWebhooks as a3, type BoundWebhook as a4, type CorsairWebhook as a5, type CorsairWebhookHandler as a6, type CorsairWebhookMatcher as a7, type WebhookPathsOf as a8, type WebhookRequest as a9, type WebhookTree as aa, type CorsairTenantWrapper as b, type CorsairSingleTenantClient as c, type CorsairClient as d, type CorsairPermissionsNamespace as e, BaseProviders as f, type AccountKeyManagerFor as g, type AccountFieldNames as h, type BaseAuthFieldConfig as i, type BaseKeyManager as j, type IntegrationFieldNames as k, type OAuth2IntegrationCredentials as l, BASE_AUTH_FIELDS as m, type AllProviders as n, type PickAuth as o, type BindEndpoints as p, type BoundEndpointFn as q, type BoundEndpointTree as r, type CorsairContext as s, type CorsairEndpoint as t, type EndpointPathsOf as u, type EndpointTree as v, type CorsairErrorHandler as w, type ErrorContext as x, type ErrorHandler as y, type ErrorHandlerAndMatchFunction as z };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { L as ListOperationsOptions } from './index-DYzTFbSd.js';
2
- export { c as createCorsair } from './index-DYzTFbSd.js';
3
- import { c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, i as CorsairClient, z as CorsairPermissionsNamespace, a2 as BoundWebhookTree, a6 as RawWebhookRequest, k as BaseProviders, a9 as WebhookResponse } from './index-DDWTZpI-.js';
1
+ import { L as ListOperationsOptions } from './index-DLUKAEBX.js';
2
+ export { c as createCorsair } from './index-DLUKAEBX.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-h_UAleEL.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-NJCJHDYW.js";import{p as m,q as k,r as b,t as y,u as W}from"./chunk-5UALNYME.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-CEZCHZQC.js";import{q as m,r as k,s as b,u as y,v as W}from"./chunk-4BDS3PPC.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(`
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};
@@ -0,0 +1,49 @@
1
+ type OAuthState = {
2
+ plugin: string;
3
+ tenantId: string;
4
+ };
5
+ declare function encodeOAuthState(plugin: string, tenantId: string): string;
6
+ declare function decodeOAuthState(state: string): OAuthState | null;
7
+ type GenerateOAuthUrlOptions = {
8
+ tenantId: string;
9
+ redirectUri: string;
10
+ };
11
+ type GenerateOAuthUrlResult = {
12
+ url: string;
13
+ state: string;
14
+ };
15
+ /**
16
+ * Builds an OAuth authorization URL for the given plugin and tenant.
17
+ *
18
+ * Embed the returned `url` in a button or link for the customer to click.
19
+ * The returned `state` is HMAC-signed — pass it to processOAuthCallback as-is.
20
+ *
21
+ * Requires the plugin to have an oauthConfig (e.g. googlecalendar, gmail,
22
+ * notion, spotify). Plugins like slack and linear use API keys, not OAuth.
23
+ * The plugin's client_id and client_secret must be set via `corsair setup`.
24
+ *
25
+ * Works for both multi-tenant and single-tenant corsair instances.
26
+ */
27
+ declare function generateOAuthUrl(corsair: unknown, pluginId: string, options: GenerateOAuthUrlOptions): Promise<GenerateOAuthUrlResult>;
28
+ type ProcessOAuthCallbackOptions = {
29
+ code: string;
30
+ state: string;
31
+ /** Must exactly match the redirectUri passed to generateOAuthUrl. */
32
+ redirectUri: string;
33
+ };
34
+ type ProcessOAuthCallbackResult = {
35
+ plugin: string;
36
+ tenantId: string;
37
+ };
38
+ /**
39
+ * Completes the OAuth flow by exchanging the authorization code for tokens
40
+ * and storing them encrypted in the database for the tenant.
41
+ *
42
+ * Call this inside your /api/auth route after receiving `code` and `state`
43
+ * from the provider redirect.
44
+ *
45
+ * @throws if state is invalid, credentials are missing, or token exchange fails
46
+ */
47
+ declare function processOAuthCallback(corsair: unknown, options: ProcessOAuthCallbackOptions): Promise<ProcessOAuthCallbackResult>;
48
+
49
+ export { type GenerateOAuthUrlOptions, type GenerateOAuthUrlResult, type ProcessOAuthCallbackOptions, type ProcessOAuthCallbackResult, decodeOAuthState, encodeOAuthState, generateOAuthUrl, processOAuthCallback };
package/dist/oauth.js ADDED
@@ -0,0 +1 @@
1
+ import{a as m,b as w,j as h,k as A,p as C,u as y}from"./chunk-4BDS3PPC.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};
package/dist/setup.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as CorsairPlugin, c as CorsairSingleTenantClient } from './index-DDWTZpI-.js';
1
+ import { C as CorsairPlugin, c as CorsairSingleTenantClient } from './index-h_UAleEL.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-NJCJHDYW.js";import"./chunk-5UALNYME.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-CEZCHZQC.js";import"./chunk-4BDS3PPC.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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsair",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,6 +37,11 @@
37
37
  "types": "./dist/http.d.ts",
38
38
  "default": "./dist/http.js"
39
39
  },
40
+ "./oauth": {
41
+ "dev-source": "./oauth.ts",
42
+ "types": "./dist/oauth.d.ts",
43
+ "default": "./dist/oauth.js"
44
+ },
40
45
  "./tests": {
41
46
  "dev-source": "./tests.ts",
42
47
  "types": "./dist/tests.d.ts",