corsair 0.1.72 → 0.1.74

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,5 @@
1
+ import{C as R,D as v,j as m,k as A,l as _}from"./chunk-GL3UP7AE.js";import{a as j}from"./chunk-UBM25HVI.js";import{Kysely as F}from"kysely";import{ZodBoolean as x,ZodDate as E,ZodEnum as D,ZodNullable as K,ZodNumber as N,ZodObject as B,ZodOptional as Z,ZodRecord as L,ZodString as U,ZodType as W}from"zod";var I={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},repositories:{list:{}}},discord:{guilds:{list:{}},channels:{list:{}}},hubspot:{contacts:{getMany:{}},companies:{getMany:{}},deals:{getMany:{}}},gmail:{messages:{list:{}},labels:{list:{}},drafts:{list:{}},threads:{list:{}}},googlecalendar:{events:{getMany:{}}},googledrive:{files:{list:{}},folders:{list:{}},sharedDrives:{list:{}}},notion:{databases:{getManyDatabases:{}},databasePages:{getManyDatabasePages:{}},users:{getManyUsers:{}}},airtable:{bases:{getMany:{}}},todoist:{projects:{getMany:{}},tasks:{getMany:{}}},cal:{bookings:{list:{}}}};async function pn(n,e){let s=[],i=d=>{s.push(d),console.log(d)},a=d=>{s.push(d),console.warn(d)},t=e?.caller??"script",f=q(n);if(!f)throw new Error("setupCorsair: invalid corsair instance");if(!f.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let o=Q(n,f.plugins,e),r={...f,database:f.database},c=r.database.db;await X(c,a);let l=await nn(c,r,o.tenantId,o.provisionAccounts,i);e?.credentials&&Object.keys(e.credentials).length>0&&await sn(n,o,e.credentials,r,i,a);let y=await rn(l,o,i,t);if(e?.backfill){i("[corsair:setup] Starting backfill...");let d=v({plugins:f.plugins,database:c,kek:f.kek,multiTenancy:!0}).withTenant(o.tenantId);await on(d,f.plugins,y,i,a),i("[corsair:setup] Backfill complete.")}return s.join(`
2
+ `)}function w(n){return typeof n=="object"&&n!==null}function Y(n){return!w(n)||!Array.isArray(n.plugins)||typeof n.kek!="string"||typeof n.multiTenancy!="boolean"?!1:n.database===void 0?!0:w(n.database)?n.database.db instanceof F:!1}function q(n){let e=Object.getOwnPropertyDescriptor(n,R);if(e)return Y(e.value)?e.value:void 0}function H(n){return n==="oauth_2"||n==="api_key"||n==="bot_token"}function P(n){let e=n.options?.authType;return H(e)?e:void 0}function J(n){return"withTenant"in n&&typeof n.withTenant=="function"}function $(n,e,s){let i=s==="integration"?n.authConfig?.[e]?.integration??[]:n.authConfig?.[e]?.account??[];return new Set([...m[e][s],...i])}function z(n,e){if(!n)return!1;for(let[s,i]of Object.entries(n)){let a=e.find(o=>o.id===s);if(!a)continue;let t=P(a);if(!t)continue;let f=$(a,t,"account");for(let o of Object.keys(i))if(f.has(o))return!0}return!1}function Q(n,e,s){let i=J(n),a=s?.tenantId?.trim(),t=a!==void 0&&a.length>0;if(i&&s?.backfill&&!t)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(i&&z(s?.credentials,e)&&!t)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(t&&!a)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:i,tenantIdProvided:t,tenantId:t?a:"default",provisionAccounts:!i||t}}function C(n,e){if(!w(n))return;let s=n[e];return typeof s=="function"?(...i)=>Reflect.apply(s,n,i):void 0}function O(n,e){return w(n)?e===0?!0:Object.values(n).every(s=>O(s,e-1)):!1}function V(n){return O(n,4)}var G={...j};function S(n){if(n instanceof B){let e={};for(let[s,i]of Object.entries(n.shape))e[s]=i instanceof W?S(i):"unknown";return e}return n instanceof K?`${S(n.unwrap())} | null`:n instanceof Z?`${S(n.unwrap())} | undefined`:n instanceof D?n.options.join(" | "):n instanceof U?"string":n instanceof N?"number":n instanceof x?"boolean":n instanceof E?"date":n instanceof L?"jsonb":"unknown"}async function X(n,e){let s=await n.introspection.getTables(),i=new Set(s.map(a=>a.name));for(let[a,t]of Object.entries(G))i.has(a)||e(`[corsair:setup] Table "${a}" does not exist. Run your database migrations before calling setupCorsair.
3
+ Schema: ${JSON.stringify(S(t),null,2)}`)}async function nn(n,e,s,i,a){let t=new Date,f=new Map;for(let o of e.plugins){let r=o.id,c=P(o),l=await n.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!l){let u=crypto.randomUUID();await n.insertInto("corsair_integrations").values({id:u,name:r,config:{},created_at:t,updated_at:t}).execute(),l=await n.selectFrom("corsair_integrations").selectAll().where("id","=",u).executeTakeFirst(),a(`[corsair:setup] Created integration: ${r}`)}let y=c?o.authConfig?.[c]?.integration??[]:[],d=c?o.authConfig?.[c]?.account??[]:[],g=c&&l?A({authType:c,integrationName:r,kek:e.kek,database:e.database,extraIntegrationFields:y}):void 0;if(l&&!l.dek&&g&&(await g.issue_new_dek(),a(`[corsair:setup] Issued integration DEK: ${r}`)),!l||!c||!g)continue;let p;if(i){let u=await n.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",s).where("integration_id","=",l.id).executeTakeFirst();if(!u){let h=crypto.randomUUID();await n.insertInto("corsair_accounts").values({id:h,tenant_id:s,integration_id:l.id,config:{},created_at:t,updated_at:t}).execute(),u=await n.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),a(`[corsair:setup] Created account: ${r}`)}p=u&&_({authType:c,integrationName:r,tenantId:s,kek:e.kek,database:e.database,extraAccountFields:d}),u&&p&&!u.dek&&(await p.issue_new_dek(),a(`[corsair:setup] Issued account DEK: ${r}`))}f.set(r,{pluginId:r,authType:c,integration:g,account:p,integrationFields:[...m[c].integration,...y],accountFields:i?[...m[c].account,...d]:[]})}return f}function en(n){if(!w(n))return;let e=n.keys;return w(e)?e:void 0}function tn(n,e){return"withTenant"in n&&typeof n.withTenant=="function"?n.withTenant(e):n}async function sn(n,e,s,i,a,t){let f=en(n),o=e.provisionAccounts?tn(n,e.tenantId):void 0;for(let[r,c]of Object.entries(s)){let l=i.plugins.find(b=>b.id===r);if(!l){t(`[corsair:setup] Unknown plugin '${r}' \u2014 skipping credentials.`);continue}let y=P(l);if(!y){t(`[corsair:setup] Plugin '${r}' has no auth type \u2014 skipping credentials.`);continue}let d=$(l,y,"integration"),g=$(l,y,"account"),p=f?.[r],u=o?.[r],h=w(u)?u.keys:void 0;for(let[b,T]of Object.entries(c))if(T){if(d.has(b)){if(e.multiTenant&&e.tenantIdProvided)throw new Error(`[corsair:setup] '${r}.${b}' is an integration-level credential shared across all tenants. You passed tenantId="${e.tenantId}", which only scopes account-level credentials. Run setup without --tenant if you intend to change this credential globally.`);let k=C(p,`set_${b}`);if(!k){t(`[corsair:setup] Cannot set integration field '${b}' for '${r}'.`);continue}await k(T),a(`[corsair:setup] Set ${r} integration.${b}`);continue}if(g.has(b)){if(e.multiTenant&&!e.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${r}.${b}' on a multi-tenant instance`);let k=C(h,`set_${b}`);if(!k){t(`[corsair:setup] Cannot set account field '${b}' for '${r}'.`);continue}await k(T),a(`[corsair:setup] Set ${r} account.${b} (tenant=${e.tenantId})`);continue}t(`[corsair:setup] Unknown credential field '${b}' for plugin '${r}'.`)}}}var M=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function an(n,e,s,i,a,t,f,o,r){let c=[],l=[];for(let d of a){if(M.has(d))continue;let g=C(s,`get_${d}`);if(!g)continue;let p=null;try{let u=await g();p=typeof u=="string"?u:null}catch{}p||c.push(d)}if(i&&t.length>0)for(let d of t){if(M.has(d))continue;let g=C(i,`get_${d}`);if(!g)continue;let p=null;try{let u=await g();p=typeof u=="string"?u:null}catch{}p||l.push(d)}let y=c.length===0&&l.length===0;if(y)o(`[corsair:setup] '${n}' (${e}) is configured \u2713`);else{let d=[...c,...l];if(r==="cli"){let g=d.map(p=>`${p}=VALUE`).join(" ");o(`[corsair:setup] '${n}' (${e}) needs credentials. Run:
4
+ corsair setup --${n} ${g}`)}else{let g=[`[corsair:setup] '${n}' (${e}) needs credentials. Call:`];for(let p of c)g.push(` await corsair.keys.${n}.set_${p}(value)`);for(let p of l){let u=f.provisionAccounts?f.tenantId==="default"?`corsair.${n}`:`corsair.withTenant(${JSON.stringify(f.tenantId)}).${n}`:`corsair.withTenant(<tenant>).${n}`;g.push(` await ${u}.keys.set_${p}(value)`)}o(g.join(`
5
+ `))}}return y}async function rn(n,e,s,i){let a=new Set;for(let t of n.values())await an(t.pluginId,t.authType,t.integration,t.account,t.integrationFields,t.accountFields,e,s,i)&&a.add(t.pluginId);return a}async function on(n,e,s,i,a){if(!V(I)){a("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let t=I,f=new Set(e.map(o=>o.id));for(let[o,r]of Object.entries(t)){if(!f.has(o))continue;if(!s.has(o)){i(`[corsair:setup] Skipping backfill for '${o}' \u2014 auth not configured.`);continue}let c=w(n)?n[o]:void 0,l=w(c)?c.api:void 0;if(l)for(let[y,d]of Object.entries(r))for(let[g,p]of Object.entries(d)){i(`[corsair:setup] Backfilling ${o} \u203A ${y}.${g}...`);try{let u=w(l)?l[y]:void 0;await C(u,g)?.(p)}catch(u){a(`[corsair:setup] ${o} \u203A ${y}.${g} failed: `+(u instanceof Error?u.message:String(u)))}}}}export{pn as a,sn as b};
@@ -0,0 +1 @@
1
+ import{a as i}from"./chunk-QAIKSQAD.js";import{Kysely as s,PostgresDialect as b,SqliteDialect as w}from"kysely";import{PostgresJSDialect as C}from"kysely-postgres-js";function D(e){return typeof e.query=="function"&&typeof e.connect=="function"}function d(e){let n=e;return typeof n.prepare=="function"&&typeof n.exec=="function"&&typeof n.close=="function"&&!("query"in e)}function S(e){return typeof e=="function"&&typeof e.begin=="function"&&typeof e.end=="function"}function u(e,n){return typeof e=="function"?e.bind(n):e}var g=114,m=3802;function q(e){if(typeof e!="object"||e===null||Buffer.isBuffer(e))return!1;if(Array.isArray(e))return!0;let n=Object.getPrototypeOf(e);return n===Object.prototype||n===null}function k(e){return e instanceof Date?e.toISOString():q(e)?JSON.stringify(e):e}function P(e){let n=e.options?.serializers;if(!n)return;let t=r=>r;n[g]=t,n[m]=t}function K(e){return new Proxy(e,{get(n,t,r){return t!=="reserve"?u(Reflect.get(n,t,r),n):async function(){let c=await n.reserve();return new Proxy(c,{get(o,a,f){return a!=="unsafe"?u(Reflect.get(o,a,f),o):function(y,l,p){return o.unsafe(y,l?.map(k),p)}}})}}})}function I(e){return typeof e.selectFrom=="function"}function J(e){if(I(e))return{db:e};if(d(e))return{db:new s({dialect:new w({database:e}),plugins:[new i]})};if(D(e))return{db:new s({dialect:new b({pool:e})})};if(S(e))return P(e),{db:new s({dialect:new C({postgres:K(e)})})};throw new Error("Unsupported database input. Expected a pg Pool, postgres.js Sql, better-sqlite3 Database, or a Kysely instance.")}export{J as a};
@@ -1,4 +1,4 @@
1
- import{a as Pe,b as de}from"./chunk-OZHME3EO.js";import{a as xe}from"./chunk-6KMLS5U6.js";var N=class extends Error{pluginId;constructor(n,r){super(r??`[auth-missing:${n}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n}};import{createCipheriv as Ee,createDecipheriv as Re,randomBytes as ne,scrypt as on}from"crypto";import{promisify as sn}from"util";var Ie=sn(on),te="aes-256-gcm",De=12,re=16,an=16,V=32;function B(){return ne(V).toString("base64")}async function j(e,n){let r=ne(an),t=await Ie(n,r,V),o=ne(De),i=Ee(te,t,o,{authTagLength:re}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[r.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function M(e,n){let[r,t,o,i]=e.split(":");if(!r||!t||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(r,"base64"),a=Buffer.from(t,"base64"),d=Buffer.from(o,"base64"),p=Buffer.from(i,"base64"),c=await Ie(n,s,V),l=Re(te,c,a,{authTagLength:re});return l.setAuthTag(d),Buffer.concat([l.update(p),l.final()]).toString("utf8")}function ue(e,n){let r=Buffer.from(n,"base64"),t=ne(De),o=Ee(te,r,t,{authTagLength:re}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[t.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function le(e,n){let[r,t,o]=e.split(":");if(!r||!t||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(r,"base64"),a=Buffer.from(t,"base64"),d=Buffer.from(o,"base64"),p=Re(te,i,s,{authTagLength:re});return p.setAuthTag(a),Buffer.concat([p.update(d),p.final()]).toString("utf8")}function H(e,n){let r={};for(let[t,o]of Object.entries(e))r[t]=ue(o,n);return r}function L(e,n){let r={};for(let[t,o]of Object.entries(e))r[t]=le(o,n);return r}function Y(e,n,r){let t=L(e,n);return H(t,r)}function oe(e,n){let r=[];e||r.push("database"),n||r.push("kek");let t={};return new Proxy(t,{get(o,i){let s=r.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${r.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
1
+ import{a as Pe,b as de}from"./chunk-OZHME3EO.js";import{a as xe}from"./chunk-FL4GOHVN.js";var N=class extends Error{pluginId;constructor(n,r){super(r??`[auth-missing:${n}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n}};import{createCipheriv as Ee,createDecipheriv as Re,randomBytes as ne,scrypt as on}from"crypto";import{promisify as sn}from"util";var Ie=sn(on),te="aes-256-gcm",De=12,re=16,an=16,V=32;function B(){return ne(V).toString("base64")}async function j(e,n){let r=ne(an),t=await Ie(n,r,V),o=ne(De),i=Ee(te,t,o,{authTagLength:re}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[r.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function M(e,n){let[r,t,o,i]=e.split(":");if(!r||!t||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(r,"base64"),a=Buffer.from(t,"base64"),d=Buffer.from(o,"base64"),p=Buffer.from(i,"base64"),c=await Ie(n,s,V),l=Re(te,c,a,{authTagLength:re});return l.setAuthTag(d),Buffer.concat([l.update(p),l.final()]).toString("utf8")}function ue(e,n){let r=Buffer.from(n,"base64"),t=ne(De),o=Ee(te,r,t,{authTagLength:re}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[t.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function le(e,n){let[r,t,o]=e.split(":");if(!r||!t||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(r,"base64"),a=Buffer.from(t,"base64"),d=Buffer.from(o,"base64"),p=Re(te,i,s,{authTagLength:re});return p.setAuthTag(a),Buffer.concat([p.update(d),p.final()]).toString("utf8")}function H(e,n){let r={};for(let[t,o]of Object.entries(e))r[t]=ue(o,n);return r}function L(e,n){let r={};for(let[t,o]of Object.entries(e))r[t]=le(o,n);return r}function Y(e,n,r){let t=L(e,n);return H(t,r)}function oe(e,n){let r=[];e||r.push("database"),n||r.push("kek");let t={};return new Proxy(t,{get(o,i){let s=r.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${r.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
2
2
 
3
3
  To generate a KEK, run: openssl rand -base64 ${V}`)}})}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 ve(e,n,r){let t={};for(let o of r)t[`get_${o}`]=async()=>(await e())[o]??null,t[`set_${o}`]=async i=>{let s=[null,void 0,""].includes(i)?null:i;await n({[o]:s})};return t}var pe=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function q(e){let{authType:n,integrationName:r,kek:t,database:o,extraIntegrationFields:i=[]}=e,s=[...Q[n].integration,...i],a=null,d={kek:t,integrationName:r,getIntegration:async()=>{if(a)return a;let u=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!u)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);return a={id:u.id,config:pe(u.config),dek:u.dek??null},a},updateIntegration:async u=>{let h=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","=",h.id).execute(),a=null}},p=null,c=async()=>{if(p)return p;let u=await d.getIntegration();if(!u.dek)throw new Error(`No DEK found for integration "${r}". Initialize the integration first.`);return p=await M(u.dek,t),p},l=async()=>{let u=await d.getIntegration(),h=await c(),b=u.config;return!b||Object.keys(b).length===0?{}:L(b,h)};return{get_dek:c,issue_new_dek:async()=>{let u=await d.getIntegration(),h=B(),b={};if(u.dek){let w=await M(u.dek,t),A=u.config;A&&Object.keys(A).length>0&&(b=Y(A,w,h))}let k=await j(h,t);return await d.updateIntegration({config:b,dek:k}),p=h,h},...ve(l,async u=>{let h=await c(),b;try{b=await l()}catch(A){console.error(`[corsair] Failed to decrypt config for integration "${r}", starting fresh:`,A),b={}}let k={...b};for(let[A,y]of Object.entries(u))y===null?delete k[A]:k[A]=y;let w=H(k,h);await d.updateIntegration({config:w})},s)}}function ie(e){let{authType:n,integrationName:r,tenantId:t,kek:o,database:i,extraAccountFields:s=[]}=e,a=[...Q[n].account,...s],d=null,p=null,c=async()=>{if(p)return p;let y=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",r).executeTakeFirst();if(!y)throw new Error(`Integration "${r}" not found. Make sure to create the integration first.`);return p={id:y.id,config:pe(y.config),dek:y.dek??null},p},l={kek:o,integrationName:r,tenantId:t,getIntegration:c,getAccount:async()=>{if(d)return d;let y=await c(),m=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",y.id).executeTakeFirst();if(!m)throw new Error(`Account not found for tenant "${t}" and integration "${r}". Make sure to create the account first.`);return d={id:m.id,config:pe(m.config),dek:m.dek??null},d},updateAccount:async y=>{let m=await l.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","=",m.id).execute(),d=null}},f=null,g=null,u=async()=>{if(f)return f;let y=await l.getAccount();if(!y.dek)throw new Error(`No DEK found for account (tenant: "${t}", integration: "${r}"). Initialize the account first.`);return f=await M(y.dek,o),f},h=async()=>{if(g)return g;let y=await l.getIntegration();if(!y.dek)throw new Error(`No DEK found for integration "${r}". Initialize the integration first.`);return g=await M(y.dek,o),g},b=async()=>{let y=await l.getAccount(),m=await u(),T=y.config;return!T||Object.keys(T).length===0?{}:L(T,m)},k=async()=>{let y=await l.getIntegration(),m=await h(),T=y.config;return!T||Object.keys(T).length===0?{}:L(T,m)},A={get_dek:u,issue_new_dek:async()=>{let y=await l.getAccount(),m=B(),T={};if(y.dek){let I=await M(y.dek,o),C=y.config;C&&Object.keys(C).length>0&&(T=Y(C,I,m))}let P=await j(m,o);return await l.updateAccount({config:T,dek:P}),f=m,m},...ve(b,async y=>{let m=await u(),T;try{T=await b()}catch(C){console.error(`[corsair] Failed to decrypt config for account (tenant: "${t}", integration: "${r}"), starting fresh:`,C),T={}}let P={...T};for(let[C,O]of Object.entries(y))O===null?delete P[C]:P[C]=O;let I=H(P,m);await l.updateAccount({config:I})},a)};return n==="oauth_2"&&(A.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}}),A}async function _e(e,n,r){let t=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!t)throw new Error(`Integration "${n}" not found.`);let o=B(),i=await j(o,r);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",t.id).execute(),o}async function Se(e,n,r,t){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!o)throw new Error(`Integration "${n}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${r}" and integration "${n}".`);let s=B(),a=await j(s,t);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}import*as X from"crypto";function Oe(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function cn(e,{maxAgeMs:n}={}){try{let r=e.includes(".")?e.split(".")[0]:e,t=JSON.parse(Buffer.from(r,"base64url").toString("utf-8"));if(t!==null&&typeof t=="object"&&"plugin"in t&&"tenantId"in t&&typeof t.plugin=="string"&&typeof t.tenantId=="string"){let o=t;return n!==void 0&&typeof o.iat=="number"&&Date.now()-o.iat>n?null:o}return null}catch{return null}}function Fe(e,n){let r=X.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${r}`}var dn=600*1e3;function $e(e,n){let r=e.lastIndexOf(".");if(r===-1)return null;let t=e.slice(0,r),o=e.slice(r+1),i=X.createHmac("sha256",n).update(t).digest("base64url"),s=Buffer.from(o,"base64url"),a=Buffer.from(i,"base64url");return s.length!==a.length||!X.timingSafeEqual(s,a)?null:cn(t,{maxAgeMs:dn})}var un=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Me(e,n,r,t,o){let i={pluginId:n,operation:r,input:t,originalError:e},s=Object.keys(o).find(p=>o[p]?.match(e,i));return await(o[s||"DEFAULT"]?.handler||un)(e,i)}import{randomBytes as ln}from"crypto";import{v4 as pn}from"uuid";var gn={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 fn(e,n,r){return r!==void 0?r:gn[n][e]}function Ke(e){let n=/(\d+)(d|h|m|s)/g,r=0,t;for(;(t=n.exec(e))!==null;){let o=parseInt(t[1],10);switch(t[2]){case"d":r+=o*864e5;break;case"h":r+=o*36e5;break;case"m":r+=o*6e4;break;case"s":r+=o*1e3;break}}return r>0?r:600*1e3}function Ne(e){return{async find_by_permission_id(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst()},async find_by_token(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst()},async set_executing(n){e&&await e.db.updateTable("corsair_permissions").set({status:"executing",updated_at:new Date}).where("id","=",n).execute()},async set_completed(n){e&&await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}}}async function Ze(e,n,r){let t=Date.now()+r;for(;Date.now()<t;){let o=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).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","=",n).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 Be(e){let n=fn(e.riskLevel,e.mode,e.override);if(n==="allow")return{result:"allow"};let r=e.meta?.irreversible?" (irreversible)":"",t=e.meta?.description?`${e.meta.description}${r}`:`${e.pluginId}.${e.endpointPath}${r}`;if(n==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
4
4
  Action: ${t}`,`
@@ -0,0 +1 @@
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};
package/dist/core.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- export { A as AuthMissingError, C as CORSAIR_INTERNAL, a as CorsairInternalConfig, D as DocSchemaFieldRow, b as DocSchemaShape, d as DocsApiEndpoint, e as DocsDbEntity, g as DocsDbFilterField, h as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, R as ResolveConnectLinkResult, c as createCorsair, f as formatDocSchemaShape, i as introspectPluginForDocs, r as resolveConnectLink } from './index-Cadh5O_D.js';
1
+ import { O as OAuthConfig, A as AuthTypes, g as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DLSRcm5o.js';
2
+ export { j as AccountFieldNames, p as AllProviders, o as BASE_AUTH_FIELDS, k as BaseAuthFieldConfig, l as BaseKeyManager, e as BaseProviders, M as BeforeHookResult, r as BindEndpoints, a6 as BindWebhooks, a4 as Bivariant, s as BoundEndpointFn, t as BoundEndpointTree, a7 as BoundWebhook, B as BoundWebhookTree, h as CORSAIR_INTERNAL, c as CorsairClient, u as CorsairContext, v as CorsairEndpoint, y as CorsairErrorHandler, N as CorsairIntegration, i as CorsairInternalConfig, Q as CorsairKeyBuilder, S as CorsairKeyBuilderBase, d as CorsairPermissionsNamespace, a as CorsairPlugin, T as CorsairPluginContext, C as CorsairSingleTenantClient, b as CorsairTenantWrapper, a8 as CorsairWebhook, a9 as CorsairWebhookHandler, aa as CorsairWebhookMatcher, U as EndpointHooks, V as EndpointMetaEntry, w as EndpointPathsOf, E as EndpointRiskLevel, x as EndpointTree, K as EnforcePermissionOptions, L as EnforcePermissionResult, z as ErrorContext, D as ErrorHandler, F as ErrorHandlerAndMatchFunction, G as ErrorMatcher, m as IntegrationFieldNames, X as KeyBuilderContext, n as OAuth2IntegrationCredentials, Y as PermissionMode, Z as PermissionPolicy, q as PickAuth, P as PluginAuthConfig, _ as PluginEndpointMeta, $ as PluginPermissionsConfig, R as RawWebhookRequest, a0 as RequiredPluginEndpointMeta, a1 as RequiredPluginEndpointSchemas, a2 as RequiredPluginWebhookSchemas, H as RetryStrategies, J as RetryStrategy, a5 as UnionToIntersection, a3 as WebhookHooks, ab as WebhookPathsOf, ac as WebhookRequest, W as WebhookResponse, ad as WebhookTree, f as createCorsair } from './index-DLSRcm5o.js';
2
3
  import { CorsairDatabase } from './db.js';
3
- import { O as OAuthConfig, A as AuthTypes, f as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-CN2IlLdT.js';
4
- export { g as AccountFieldNames, m as AllProviders, l as BASE_AUTH_FIELDS, h as BaseAuthFieldConfig, i as BaseKeyManager, e as BaseProviders, H as BeforeHookResult, o as BindEndpoints, a3 as BindWebhooks, a1 as Bivariant, p as BoundEndpointFn, q as BoundEndpointTree, a4 as BoundWebhook, B as BoundWebhookTree, c as CorsairClient, r as CorsairContext, s as CorsairEndpoint, u as CorsairErrorHandler, J as CorsairIntegration, K as CorsairKeyBuilder, L as CorsairKeyBuilderBase, d as CorsairPermissionsNamespace, a as CorsairPlugin, M as CorsairPluginContext, C as CorsairSingleTenantClient, b as CorsairTenantWrapper, a5 as CorsairWebhook, a6 as CorsairWebhookHandler, a7 as CorsairWebhookMatcher, N as EndpointHooks, Q as EndpointMetaEntry, E as EndpointPathsOf, S as EndpointRiskLevel, t as EndpointTree, F as EnforcePermissionOptions, G as EnforcePermissionResult, v as ErrorContext, w as ErrorHandler, x as ErrorHandlerAndMatchFunction, y as ErrorMatcher, j as IntegrationFieldNames, T as KeyBuilderContext, k as OAuth2IntegrationCredentials, U as PermissionMode, V as PermissionPolicy, n as PickAuth, P as PluginAuthConfig, X as PluginEndpointMeta, Y as PluginPermissionsConfig, R as RawWebhookRequest, Z as RequiredPluginEndpointMeta, _ as RequiredPluginEndpointSchemas, $ as RequiredPluginWebhookSchemas, z as RetryStrategies, D as RetryStrategy, a2 as UnionToIntersection, a0 as WebhookHooks, a8 as WebhookPathsOf, a9 as WebhookRequest, W as WebhookResponse, aa as WebhookTree } from './index-CN2IlLdT.js';
5
- import 'kysely';
4
+ export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, R as ResolveConnectLinkResult, f as formatDocSchemaShape, i as introspectPluginForDocs, r as resolveConnectLink } from './index-Cc9JiMef.js';
6
5
  import 'zod';
6
+ import './orm.js';
7
+ import 'kysely';
7
8
  import 'pg';
8
9
  import 'postgres';
9
- import './orm.js';
10
10
 
11
11
  /**
12
12
  * Context interface with account ID resolver for logging events.
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{A as s,B as t,C as u,D as v,a,b,c,d,e,f,g,h,i,j,k,l,m,n,s as o,t as p,u as q,v as r}from"./chunk-W6KENKHM.js";import"./chunk-OZHME3EO.js";import"./chunk-6KMLS5U6.js";import"./chunk-QAIKSQAD.js";export{a as AuthMissingError,j as BASE_AUTH_FIELDS,u as CORSAIR_INTERNAL,l as createAccountKeyManager,v as createCorsair,k as createIntegrationKeyManager,h as decryptConfig,d as decryptDEK,f as decryptWithDEK,g as encryptConfig,c as encryptDEK,e as encryptWithDEK,q as exchangeCodeForTokens,s as formatDocSchemaShape,b as generateDEK,n as initializeAccountDEK,m as initializeIntegrationDEK,t as introspectPluginForDocs,o as logEvent,p as logEventFromContext,i as reEncryptConfig,r as resolveConnectLink};
1
+ import{A as s,B as t,C as u,D as v,a,b,c,d,e,f,g,h,i,j,k,l,m,n,s as o,t as p,u as q,v as r}from"./chunk-GL3UP7AE.js";import"./chunk-OZHME3EO.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{a as AuthMissingError,j as BASE_AUTH_FIELDS,u as CORSAIR_INTERNAL,l as createAccountKeyManager,v as createCorsair,k as createIntegrationKeyManager,h as decryptConfig,d as decryptDEK,f as decryptWithDEK,g as encryptConfig,c as encryptDEK,e as encryptWithDEK,q as exchangeCodeForTokens,s as formatDocSchemaShape,b as generateDEK,n as initializeAccountDEK,m as initializeIntegrationDEK,t as introspectPluginForDocs,o as logEvent,p as logEventFromContext,i as reEncryptConfig,r as resolveConnectLink};
package/dist/db.d.ts CHANGED
@@ -97,8 +97,7 @@ type CorsairIntegrationInsert = {
97
97
  created_at?: Date;
98
98
  updated_at?: Date;
99
99
  name: string;
100
- /** Omit to use the database default (`{}`). */
101
- config?: Record<string, unknown>;
100
+ config: Record<string, unknown>;
102
101
  dek?: string;
103
102
  };
104
103
  type CorsairAccountInsert = {
@@ -107,8 +106,7 @@ type CorsairAccountInsert = {
107
106
  updated_at?: Date;
108
107
  tenant_id: string;
109
108
  integration_id: string;
110
- /** Omit to use the database default (`{}`). */
111
- config?: Record<string, unknown>;
109
+ config: Record<string, unknown>;
112
110
  dek?: string;
113
111
  };
114
112
  type CorsairEntityInsert = {
package/dist/db.js CHANGED
@@ -1 +1 @@
1
- import{a as g}from"./chunk-N2XRSSRL.js";import{a as b,b as c,c as d,d as e,e as f}from"./chunk-3USHGH6P.js";import{a}from"./chunk-6KMLS5U6.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-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{c as CorsairAccountsSchema,d as CorsairEntitiesSchema,e as CorsairEventsSchema,b as CorsairIntegrationsSchema,f as CorsairPermissionsSchema,a as createCorsairDatabase,g as sql};
@@ -1,5 +1,4 @@
1
- import { S as EndpointRiskLevel, a as CorsairPlugin, J as CorsairIntegration, b as CorsairTenantWrapper, C as CorsairSingleTenantClient } from './index-CN2IlLdT.js';
2
- import { CorsairDatabase } from './db.js';
1
+ import { E as EndpointRiskLevel, a as CorsairPlugin } from './index-DLSRcm5o.js';
3
2
 
4
3
  /**
5
4
  * Error thrown when a plugin endpoint is called but the user has not authenticated
@@ -184,53 +183,4 @@ declare function formatDocSchemaShape(shape: DocSchemaShape | undefined, depth?:
184
183
  */
185
184
  declare function introspectPluginForDocs(plugins: readonly CorsairPlugin[], pluginId: string): IntrospectPluginForDocsResult;
186
185
 
187
- declare const CORSAIR_INTERNAL: unique symbol;
188
- type CorsairInternalConfig = {
189
- plugins: readonly CorsairPlugin[];
190
- database: CorsairDatabase | undefined;
191
- kek: string;
192
- multiTenancy: boolean;
193
- approval?: {
194
- timeout: string;
195
- onTimeout: 'deny' | 'approve';
196
- mode?: 'synchronous' | 'asynchronous' | (() => 'synchronous' | 'asynchronous');
197
- /** Called when a permission is blocked in async mode. Return the message surfaced to the LLM. */
198
- formatAsyncMessage?: (opts: {
199
- token: string;
200
- id: string;
201
- plugin: string;
202
- endpoint: string;
203
- args: unknown;
204
- }) => string;
205
- };
206
- connect?: {
207
- baseUrl: string;
208
- redirectUri: string;
209
- onAuthMissing?: (opts: {
210
- plugin: string;
211
- connectUrl: string;
212
- state: string;
213
- }) => string;
214
- };
215
- };
216
- /**
217
- * Creates a Corsair integration with multi-tenancy enabled.
218
- * Returns a wrapper with a `withTenant()` method to scope operations to specific tenants,
219
- * and a `keys` property for integration-level key management.
220
- * @param config - Configuration with plugins, database, and multiTenancy: true
221
- * @returns A tenant wrapper with `withTenant(tenantId)` method and integration-level `keys`
222
- */
223
- declare function createCorsair<const Plugins extends readonly CorsairPlugin[]>(config: CorsairIntegration<Plugins> & {
224
- multiTenancy: true;
225
- }): CorsairTenantWrapper<Plugins>;
226
- /**
227
- * Creates a Corsair integration without multi-tenancy.
228
- * Returns a direct client instance with both plugin APIs and integration-level keys.
229
- * @param config - Configuration with plugins and optional database
230
- * @returns A Corsair client instance with plugin APIs and integration-level `keys`
231
- */
232
- declare function createCorsair<const Plugins extends readonly CorsairPlugin[]>(config: CorsairIntegration<Plugins> & {
233
- multiTenancy?: false | undefined;
234
- }): CorsairSingleTenantClient<Plugins>;
235
-
236
- export { AuthMissingError as A, CORSAIR_INTERNAL as C, type DocSchemaFieldRow as D, type EndpointSchemaResult as E, type FormFieldSchema as F, type IntrospectPluginForDocsResult as I, type ListOperationsOptions as L, type PluginDocsIntrospection as P, type ResolveConnectLinkResult as R, type CorsairInternalConfig as a, type DocSchemaShape as b, createCorsair as c, type DocsApiEndpoint as d, type DocsDbEntity as e, formatDocSchemaShape as f, type DocsDbFilterField as g, type DocsWebhook as h, introspectPluginForDocs as i, resolveConnectLink as r };
186
+ export { AuthMissingError as A, type DocSchemaFieldRow as D, type EndpointSchemaResult as E, type FormFieldSchema as F, type IntrospectPluginForDocsResult as I, type ListOperationsOptions as L, type PluginDocsIntrospection as P, type ResolveConnectLinkResult as R, type DocSchemaShape as a, type DocsApiEndpoint as b, type DocsDbEntity as c, type DocsDbFilterField as d, type DocsWebhook as e, formatDocSchemaShape as f, introspectPluginForDocs as i, resolveConnectLink as r };
@@ -1,6 +1,6 @@
1
+ import { CorsairDatabase, CorsairDatabaseInput, CorsairPermission } from './db.js';
1
2
  import { ZodTypeAny } from 'zod';
2
3
  import { CorsairPluginSchema, PluginEntityClients } from './orm.js';
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
6
  declare const BaseProviders: readonly ["airtable", "amplitude", "asana", "bitwarden", "bluesky", "box", "cal", "calendly", "cloudflare", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "grafana", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tally", "tavily", "teams", "telegram", "todoist", "trello", "twitter", "twitterapiio", "typeform", "vapi", "xquik", "youtube", "zendesk", "zoom"];
@@ -1140,4 +1140,53 @@ type CorsairSingleTenantClient<Plugins extends readonly CorsairPlugin[]> = Corsa
1140
1140
  permissions: CorsairPermissionsNamespace;
1141
1141
  };
1142
1142
 
1143
- export { type RequiredPluginWebhookSchemas as $, type AuthTypes as A, type BoundWebhookTree as B, type CorsairSingleTenantClient as C, type RetryStrategy as D, type EndpointPathsOf as E, type EnforcePermissionOptions as F, type EnforcePermissionResult as G, type BeforeHookResult as H, type IntegrationKeyManagerFor as I, type CorsairIntegration as J, type CorsairKeyBuilder as K, type CorsairKeyBuilderBase as L, type CorsairPluginContext as M, type EndpointHooks as N, type OAuthConfig as O, type PluginAuthConfig as P, type EndpointMetaEntry as Q, type RawWebhookRequest as R, type EndpointRiskLevel 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 CorsairPlugin 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 CorsairClient as c, type CorsairPermissionsNamespace as d, BaseProviders as e, type AccountKeyManagerFor as f, type AccountFieldNames as g, type BaseAuthFieldConfig as h, type BaseKeyManager as i, type IntegrationFieldNames as j, type OAuth2IntegrationCredentials as k, BASE_AUTH_FIELDS as l, type AllProviders as m, type PickAuth as n, type BindEndpoints as o, type BoundEndpointFn as p, type BoundEndpointTree as q, type CorsairContext as r, type CorsairEndpoint as s, type EndpointTree as t, type CorsairErrorHandler as u, type ErrorContext as v, type ErrorHandler as w, type ErrorHandlerAndMatchFunction as x, type ErrorMatcher as y, type RetryStrategies as z };
1143
+ declare const CORSAIR_INTERNAL: unique symbol;
1144
+ type CorsairInternalConfig = {
1145
+ plugins: readonly CorsairPlugin[];
1146
+ database: CorsairDatabase | undefined;
1147
+ kek: string;
1148
+ multiTenancy: boolean;
1149
+ approval?: {
1150
+ timeout: string;
1151
+ onTimeout: 'deny' | 'approve';
1152
+ mode?: 'synchronous' | 'asynchronous' | (() => 'synchronous' | 'asynchronous');
1153
+ /** Called when a permission is blocked in async mode. Return the message surfaced to the LLM. */
1154
+ formatAsyncMessage?: (opts: {
1155
+ token: string;
1156
+ id: string;
1157
+ plugin: string;
1158
+ endpoint: string;
1159
+ args: unknown;
1160
+ }) => string;
1161
+ };
1162
+ connect?: {
1163
+ baseUrl: string;
1164
+ redirectUri: string;
1165
+ onAuthMissing?: (opts: {
1166
+ plugin: string;
1167
+ connectUrl: string;
1168
+ state: string;
1169
+ }) => string;
1170
+ };
1171
+ };
1172
+ /**
1173
+ * Creates a Corsair integration with multi-tenancy enabled.
1174
+ * Returns a wrapper with a `withTenant()` method to scope operations to specific tenants,
1175
+ * and a `keys` property for integration-level key management.
1176
+ * @param config - Configuration with plugins, database, and multiTenancy: true
1177
+ * @returns A tenant wrapper with `withTenant(tenantId)` method and integration-level `keys`
1178
+ */
1179
+ declare function createCorsair<const Plugins extends readonly CorsairPlugin[]>(config: CorsairIntegration<Plugins> & {
1180
+ multiTenancy: true;
1181
+ }): CorsairTenantWrapper<Plugins>;
1182
+ /**
1183
+ * Creates a Corsair integration without multi-tenancy.
1184
+ * Returns a direct client instance with both plugin APIs and integration-level keys.
1185
+ * @param config - Configuration with plugins and optional database
1186
+ * @returns A Corsair client instance with plugin APIs and integration-level `keys`
1187
+ */
1188
+ declare function createCorsair<const Plugins extends readonly CorsairPlugin[]>(config: CorsairIntegration<Plugins> & {
1189
+ multiTenancy?: false | undefined;
1190
+ }): CorsairSingleTenantClient<Plugins>;
1191
+
1192
+ export { type PluginPermissionsConfig as $, type AuthTypes as A, type BoundWebhookTree as B, type CorsairSingleTenantClient as C, type ErrorHandler as D, type EndpointRiskLevel as E, type ErrorHandlerAndMatchFunction as F, type ErrorMatcher as G, type RetryStrategies as H, type IntegrationKeyManagerFor as I, type RetryStrategy as J, type EnforcePermissionOptions as K, type EnforcePermissionResult as L, type BeforeHookResult as M, type CorsairIntegration as N, type OAuthConfig as O, type PluginAuthConfig as P, type CorsairKeyBuilder as Q, type RawWebhookRequest as R, type CorsairKeyBuilderBase as S, type CorsairPluginContext as T, type EndpointHooks as U, type EndpointMetaEntry as V, type WebhookResponse as W, type KeyBuilderContext as X, type PermissionMode as Y, type PermissionPolicy as Z, type PluginEndpointMeta as _, type CorsairPlugin as a, type RequiredPluginEndpointMeta as a0, type RequiredPluginEndpointSchemas as a1, type RequiredPluginWebhookSchemas as a2, type WebhookHooks as a3, type Bivariant$2 as a4, type UnionToIntersection$1 as a5, type BindWebhooks as a6, type BoundWebhook as a7, type CorsairWebhook as a8, type CorsairWebhookHandler as a9, type CorsairWebhookMatcher as aa, type WebhookPathsOf as ab, type WebhookRequest as ac, type WebhookTree as ad, type CorsairTenantWrapper as b, type CorsairClient as c, type CorsairPermissionsNamespace as d, BaseProviders as e, createCorsair as f, type AccountKeyManagerFor as g, CORSAIR_INTERNAL as h, type CorsairInternalConfig as i, type AccountFieldNames as j, type BaseAuthFieldConfig as k, type BaseKeyManager as l, type IntegrationFieldNames as m, type OAuth2IntegrationCredentials as n, BASE_AUTH_FIELDS as o, type AllProviders as p, type PickAuth as q, type BindEndpoints as r, type BoundEndpointFn as s, type BoundEndpointTree as t, type CorsairContext as u, type CorsairEndpoint as v, type EndpointPathsOf as w, type EndpointTree as x, type CorsairErrorHandler as y, type ErrorContext as z };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { F as FormFieldSchema, L as ListOperationsOptions } from './index-Cadh5O_D.js';
2
- export { A as AuthMissingError, R as ResolveConnectLinkResult, c as createCorsair, f as formatDocSchemaShape, r as resolveConnectLink } from './index-Cadh5O_D.js';
3
- import { C as CorsairSingleTenantClient, a as CorsairPlugin, b as CorsairTenantWrapper, c as CorsairClient, d as CorsairPermissionsNamespace, B as BoundWebhookTree, R as RawWebhookRequest, e as BaseProviders, W as WebhookResponse } from './index-CN2IlLdT.js';
1
+ import { C as CorsairSingleTenantClient, a as CorsairPlugin, b as CorsairTenantWrapper, c as CorsairClient, d as CorsairPermissionsNamespace, B as BoundWebhookTree, R as RawWebhookRequest, e as BaseProviders, W as WebhookResponse } from './index-DLSRcm5o.js';
2
+ export { f as createCorsair } from './index-DLSRcm5o.js';
3
+ import { F as FormFieldSchema, L as ListOperationsOptions } from './index-Cc9JiMef.js';
4
+ export { A as AuthMissingError, R as ResolveConnectLinkResult, f as formatDocSchemaShape, r as resolveConnectLink } from './index-Cc9JiMef.js';
4
5
  export { SetupCorsairOptions, setupCorsair } from './setup.js';
5
6
  import './db.js';
6
7
  import 'kysely';
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import{a as A}from"./chunk-UEIITBYY.js";import{A as x,C,D as T,a as I,v as O,w as k,x as y,y as b,z as w}from"./chunk-W6KENKHM.js";import"./chunk-AAWROBCK.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-6KMLS5U6.js";import"./chunk-QAIKSQAD.js";function h(n){let r=n[C];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function B(n,r){let o=b(h(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
1
+ import{a as A}from"./chunk-5UXO4GNS.js";import{A as x,C,D as T,a as I,v as O,w as k,x as y,y as b,z as w}from"./chunk-GL3UP7AE.js";import"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";function h(n){let r=n[C];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function B(n,r){let o=b(h(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
2
2
  `):Object.values(o).flat().join(`
3
3
  `)}function E(n,r){return w(h(n),r)}function F(n,r){return y(h(n),r)}var $=Symbol.for("corsair:internal");function j(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 S(n){return n[$]?.database}async function _(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=S(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 c=j(g.api,e.endpoint.split("."));if(!c)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 c(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=S(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 v(n){return n!==null&&typeof n=="object"&&"match"in n&&"handler"in n&&typeof n.match=="function"&&typeof n.handler=="function"}function R(n,r,o=[]){for(let[e,t]of Object.entries(n))if(v(t)){if(t.match(r))return{webhook:t,path:[...o,e]}}else if(t&&typeof t=="object"){let s=R(t,r,[...o,e]);if(s)return s}return null}function N(n){let r={};for(let[o,e]of Object.entries(n))r[o.toLowerCase()]=Array.isArray(e)?e[0]:e;return r}function L(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 D(n,r,o,e){let t=N(r),s=typeof o=="string"?JSON.parse(o):o;(!s||typeof s=="object"&&Object.keys(s).length===0)&&t["x-goog-resource-uri"]&&(s=L(t)||s);let c={headers:t,body:s},i=e?.tenantId||"default",u=n.withTenant?n.withTenant(i):n,d=k;for(let l of d){let p=u[l];if(!p||!p.webhooks||p.pluginWebhookMatcher&&!p.pluginWebhookMatcher(c))continue;let f=R(p.webhooks,c);if(!f)continue;let m=f.path.join("."),P={payload:s,headers:t,rawBody:typeof o=="string"?o:JSON.stringify(o)};try{let a=await f.webhook.handler(P),W=!!Object.keys(a.returnToSender||{})?.length;return{plugin:l,action:m,body:s,response:W?{...a?.returnToSender,success:!0}:{success:!0},...a.responseHeaders&&{responseHeaders:a.responseHeaders}}}catch(a){return console.error(`Error executing webhook handler for ${l}.${m}:`,a),{plugin:l,action:m,body:s,response:{success:!1,error:a instanceof Error?a.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}export{I as AuthMissingError,T as createCorsair,_ as executePermission,x as formatDocSchemaShape,E as getSchema,F as getStructuredSchema,B as listOperations,D as processWebhook,O as resolveConnectLink,A as setupCorsair};
package/dist/oauth.js CHANGED
@@ -1 +1 @@
1
- import{C as x,b as C,c as O,k as p,l as m,o as f,p as _,q as A,r as y,u as b}from"./chunk-W6KENKHM.js";import{b as P}from"./chunk-AAWROBCK.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-6KMLS5U6.js";import"./chunk-QAIKSQAD.js";import*as E from"querystring";function I(n){let e=n[x];if(!e)throw new Error("Invalid corsair instance");return e}function U(n,e){let o=n.plugins.find(a=>a.id===e);if(!o)throw new Error(`Plugin '${e}' not found`);return o}function N(n){let e=n.oauthConfig;if(!e)throw new Error(`Plugin '${n.id}' has no oauthConfig`);return e}async function R(n,e,o,a){let i=P(n),t=await i.integrations.findByName(e);if(!t)throw new Error(`Integration '${e}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:o,integration_id:t.id}))return;let r=C(),s=await O(r,a);await i.accounts.create({tenant_id:o,integration_id:t.id,dek:s})}async function S(n,e,o){let{tenantId:a,redirectUri:i}=o,t=I(n);if(!t.database)throw new Error("No database configured on corsair instance");let u=U(t,e),r=N(u),d=await p({authType:"oauth_2",integrationName:e,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new Error(`client_id not configured for '${e}'`);let g=A(f(e,a),t.kek),l={...r.authParams,client_id:d,redirect_uri:i,response_type:"code",scope:r.scopes.join(" "),state:g};return{url:`${r.authUrl}?${E.stringify(l)}`,state:g}}async function K(n,e){let{code:o,state:a,redirectUri:i}=e,t=I(n),u=y(a,t.kek);if(!u)throw new Error("Invalid or tampered state parameter");let{plugin:r,tenantId:s}=u;if(!t.database)throw new Error("No database configured on corsair instance");let d=U(t,r),g=N(d),l=p({authType:"oauth_2",integrationName:r,kek:t.kek,database:t.database}),k=await l.get_client_id(),w=await l.get_client_secret();if(!k||!w)throw new Error(`Credentials not configured for '${r}'`);await R(t.database,r,s,t.kek);let c=await b(o,k,w,g,i);if(!c.access_token)throw new Error(`No access_token returned from ${g.providerName}`);let h=m({authType:"oauth_2",integrationName:r,tenantId:s,kek:t.kek,database:t.database});return await h.set_access_token(c.access_token),c.refresh_token&&await h.set_refresh_token(c.refresh_token),c.expires_in&&await h.set_expires_at(String(Math.floor(Date.now()/1e3)+c.expires_in)),{plugin:r,tenantId:s}}export{_ as decodeOAuthState,f as encodeOAuthState,S as generateOAuthUrl,K as processOAuthCallback};
1
+ import{C as x,b as C,c as O,k as p,l as m,o as f,p as _,q as A,r as y,u as b}from"./chunk-GL3UP7AE.js";import{b as P}from"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";import*as E from"querystring";function I(n){let e=n[x];if(!e)throw new Error("Invalid corsair instance");return e}function U(n,e){let o=n.plugins.find(a=>a.id===e);if(!o)throw new Error(`Plugin '${e}' not found`);return o}function N(n){let e=n.oauthConfig;if(!e)throw new Error(`Plugin '${n.id}' has no oauthConfig`);return e}async function R(n,e,o,a){let i=P(n),t=await i.integrations.findByName(e);if(!t)throw new Error(`Integration '${e}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:o,integration_id:t.id}))return;let r=C(),s=await O(r,a);await i.accounts.create({tenant_id:o,integration_id:t.id,config:{},dek:s})}async function S(n,e,o){let{tenantId:a,redirectUri:i}=o,t=I(n);if(!t.database)throw new Error("No database configured on corsair instance");let u=U(t,e),r=N(u),d=await p({authType:"oauth_2",integrationName:e,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new Error(`client_id not configured for '${e}'`);let g=A(f(e,a),t.kek),l={...r.authParams,client_id:d,redirect_uri:i,response_type:"code",scope:r.scopes.join(" "),state:g};return{url:`${r.authUrl}?${E.stringify(l)}`,state:g}}async function K(n,e){let{code:o,state:a,redirectUri:i}=e,t=I(n),u=y(a,t.kek);if(!u)throw new Error("Invalid or tampered state parameter");let{plugin:r,tenantId:s}=u;if(!t.database)throw new Error("No database configured on corsair instance");let d=U(t,r),g=N(d),l=p({authType:"oauth_2",integrationName:r,kek:t.kek,database:t.database}),k=await l.get_client_id(),w=await l.get_client_secret();if(!k||!w)throw new Error(`Credentials not configured for '${r}'`);await R(t.database,r,s,t.kek);let c=await b(o,k,w,g,i);if(!c.access_token)throw new Error(`No access_token returned from ${g.providerName}`);let h=m({authType:"oauth_2",integrationName:r,tenantId:s,kek:t.kek,database:t.database});return await h.set_access_token(c.access_token),c.refresh_token&&await h.set_refresh_token(c.refresh_token),c.expires_in&&await h.set_expires_at(String(Math.floor(Date.now()/1e3)+c.expires_in)),{plugin:r,tenantId:s}}export{_ as decodeOAuthState,f as encodeOAuthState,S as generateOAuthUrl,K as processOAuthCallback};
package/dist/orm.d.ts CHANGED
@@ -15,11 +15,8 @@ type CorsairOrmTableName = keyof CorsairOrmDatabase;
15
15
  /**
16
16
  * Input type for creating a new row (without auto-generated fields).
17
17
  */
18
- type CreateInput<T> = Omit<T, 'id' | 'created_at' | 'updated_at' | 'config'> & {
18
+ type CreateInput<T> = Omit<T, 'id' | 'created_at' | 'updated_at'> & {
19
19
  id?: string;
20
- config?: T extends {
21
- config: infer C;
22
- } ? C : never;
23
20
  };
24
21
  /**
25
22
  * Input type for updating an existing row.
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-AAWROBCK.js";import"./chunk-OZHME3EO.js";import{a as r,b as t,c as i,d as a}from"./chunk-3USHGH6P.js";import"./chunk-6KMLS5U6.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-FL4GOHVN.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,18 +1,26 @@
1
- import { a as CorsairPlugin, C as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-CN2IlLdT.js';
1
+ import { a as CorsairPlugin, C as CorsairSingleTenantClient, b as CorsairTenantWrapper, i as CorsairInternalConfig } from './index-DLSRcm5o.js';
2
+ import { CorsairDatabase } from './db.js';
2
3
  import 'zod';
3
4
  import './orm.js';
4
- import './db.js';
5
5
  import 'kysely';
6
6
  import 'pg';
7
7
  import 'postgres';
8
8
 
9
+ /** Plugin id → credential field → value (from CLI `field=value` pairs). */
10
+ type SetupCredentials = Record<string, Record<string, string>>;
9
11
  interface SetupCorsairOptions {
10
12
  /**
11
- * Tenant to provision rows for. Defaults to "default".
12
- * Pass a specific tenant ID to create that tenant's `corsair_accounts` rows
13
- * and issue DEKs without touching other tenants.
13
+ * Tenant to provision account rows and account-level credentials for.
14
+ * Optional on single-tenant instances (defaults to `"default"`).
15
+ * On multi-tenant instances: required for account-level credentials and
16
+ * backfill; omit when only setting integration-level credentials.
14
17
  */
15
18
  tenantId?: string;
19
+ /**
20
+ * Credentials to persist during setup (integration-level fields use
21
+ * `corsair.keys.<plugin>`; account-level fields use the tenant client).
22
+ */
23
+ credentials?: SetupCredentials;
16
24
  /**
17
25
  * When true, calls list endpoints for every plugin defined in
18
26
  * setup/backfill.yaml to seed the local database with initial data.
@@ -25,7 +33,18 @@ interface SetupCorsairOptions {
25
33
  */
26
34
  caller?: 'cli' | 'script';
27
35
  }
36
+ type SetupLog = (msg: string) => void;
37
+ type SetupWarn = (msg: string) => void;
28
38
  type SetupCorsairInstance<Plugins extends readonly CorsairPlugin[]> = CorsairSingleTenantClient<Plugins> | CorsairTenantWrapper<Plugins>;
39
+ type SetupInternalConfig = CorsairInternalConfig & {
40
+ database: CorsairDatabase;
41
+ };
42
+ type SetupTenantScope = {
43
+ multiTenant: boolean;
44
+ tenantIdProvided: boolean;
45
+ tenantId: string;
46
+ provisionAccounts: boolean;
47
+ };
29
48
  /**
30
49
  * Initialises a corsair instance end-to-end:
31
50
  *
@@ -41,11 +60,12 @@ type SetupCorsairInstance<Plugins extends readonly CorsairPlugin[]> = CorsairSin
41
60
  * - Integration-level (shared across all tenants): `corsair.keys.plugin.set_*(value)`
42
61
  * - Account-level (per-tenant): `corsair.withTenant(tenantId).plugin.keys.set_*(value)`
43
62
  *
44
- * Multi-tenant corsair instances are accepted; pass `options.tenantId` to provision
45
- * rows for a specific tenant instead of the default account.
63
+ * Multi-tenant instances: pass `options.tenantId` for account-level work (account
64
+ * rows, account credentials, backfill). Integration-only setup may omit tenantId.
46
65
  *
47
66
  * Returns a newline-separated string of all setup output.
48
67
  */
49
68
  declare function setupCorsair<const Plugins extends readonly CorsairPlugin[]>(corsair: SetupCorsairInstance<Plugins>, options?: SetupCorsairOptions): Promise<string>;
69
+ declare function applySetupCredentials<const Plugins extends readonly CorsairPlugin[]>(corsair: SetupCorsairInstance<Plugins>, tenantScope: SetupTenantScope, credentials: SetupCredentials, internal: SetupInternalConfig, log: SetupLog, warn: SetupWarn): Promise<void>;
50
70
 
51
- export { type SetupCorsairOptions, setupCorsair };
71
+ export { type SetupCorsairOptions, type SetupCredentials, applySetupCredentials, setupCorsair };
package/dist/setup.js CHANGED
@@ -1 +1 @@
1
- import{a as o}from"./chunk-UEIITBYY.js";import"./chunk-W6KENKHM.js";import"./chunk-AAWROBCK.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-6KMLS5U6.js";import"./chunk-QAIKSQAD.js";export{o as setupCorsair};
1
+ import{a as o,b as r}from"./chunk-5UXO4GNS.js";import"./chunk-GL3UP7AE.js";import"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{r as applySetupCredentials,o as setupCorsair};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsair",
3
- "version": "0.1.72",
3
+ "version": "0.1.74",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- import{a}from"./chunk-QAIKSQAD.js";import{Kysely as n,PostgresDialect as b,SqliteDialect as C}from"kysely";import{PostgresJSDialect as D}from"kysely-postgres-js";function w(e){return typeof e.query=="function"&&typeof e.connect=="function"}function d(e){let t=e;return typeof t.prepare=="function"&&typeof t.exec=="function"&&typeof t.close=="function"&&!("query"in e)}function g(e){return typeof e=="function"&&typeof e.begin=="function"&&typeof e.end=="function"}function i(e,t){return typeof e=="function"?e.bind(t):e}function m(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&!Buffer.isBuffer(e)&&Object.getPrototypeOf(e)===Object.prototype&&Object.keys(e).length===0}function S(e){return e instanceof Date?e.toISOString():m(e)?"{}":e}function q(e){return new Proxy(e,{get(t,o,y){return o!=="reserve"?i(Reflect.get(t,o,y),t):async function(){let c=await t.reserve();return new Proxy(c,{get(r,s,f){return s!=="unsafe"?i(Reflect.get(r,s,f),r):function(u,l,p){return r.unsafe(u,l?.map(S),p)}}})}}})}function P(e){return typeof e.selectFrom=="function"}function I(e){if(P(e))return{db:e};if(d(e))return{db:new n({dialect:new C({database:e}),plugins:[new a]})};if(w(e))return{db:new n({dialect:new b({pool:e})})};if(g(e))return{db:new n({dialect:new D({postgres:q(e)})})};throw new Error("Unsupported database input. Expected a pg Pool, postgres.js Sql, better-sqlite3 Database, or a Kysely instance.")}export{I as a};
@@ -1 +0,0 @@
1
- import{a as b,b as h}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(e){return k[e]}function _(e){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype&&Object.keys(e).length===0}function R(e){if(!("config"in e)||!S(e.config))return e;let{config:n,...r}=e;return r}function d(e){if(!e)throw new Error("Corsair database is not configured. Pass `database` to createCorsair(...) to enable ORM.")}function g(e){if(!e)return[];let n=[];for(let r in e){let t=r,i=e[t];if(i!==void 0)if(typeof i=="object"&&i!==null&&!Array.isArray(i)&&!(i instanceof Date)){let s=i;"in"in s&&Array.isArray(s.in)?n.push({field:t,operator:"in",value:s.in}):"like"in s&&typeof s.like=="string"&&n.push({field:t,operator:"like",value:s.like})}else n.push({field:t,value:i})}return n}function p(e,n){if(!n?.length)return e;let r=e;for(let t of n){let i=t.operator??"=";r=r.where(t.field,i,t.value)}return r}function O(e){return typeof e=="number"?e:typeof e=="bigint"?Number(e):Number.parseInt(String(e??0),10)}function T(e,n){let r=F(n),t=()=>(d(e),e),i=()=>t().db.selectFrom(n),s=()=>t().db.insertInto(n),u=()=>t().db.updateTable(n),c=()=>t().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(e);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(e);let a=i().selectAll();a=p(a,g(o));let l=await a.executeTakeFirst();return l?m(l):null},findMany:async o=>{d(e);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(e);let a=new Date,l=R({id:o.id??b(),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(e);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(e);let l={...a,updated_at:new Date},y=i().select("id");y=p(y,g(o));let f=await y.execute();for(let B of f){let w=u().set(l);w=p(w,[{field:"id",value:B.id}]),await w.execute()}return f.length},delete:async o=>{d(e);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(e);let a=c();a=p(a,g(o));let l=await a.executeTakeFirst();return Number(l?.numDeletedRows??0)},count:async o=>{d(e);let a=i().select(y=>y.fn.countAll().as("count"));a=p(a,g(o));let l=await a.executeTakeFirst();return O(l?.count)}}}function N(e){let n=T(e,"corsair_integrations");return{...n,findByName:r=>n.findOne({name:r}),upsertByName:async(r,t)=>{let i=await n.findOne({name:r});return i?await n.update(i.id,t):n.create({...t,name:r})}}}function v(e){let n=T(e,"corsair_accounts");return{...n,findByTenantAndIntegration:async(r,t)=>{d(e);let i=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();return i?n.findOne({tenant_id:r,integration_id:i.id}):null},listByTenant:(r,t)=>n.findMany({where:{tenant_id:r},limit:t?.limit,offset:t?.offset}),upsertByTenantAndIntegration:async(r,t,i)=>{let s=await n.findOne({tenant_id:r,integration_id:t});return s?await n.update(s.id,i):n.create({...i,tenant_id:r,integration_id:t})}}}function W(e){let n=T(e,"corsair_entities");return{...n,findByEntityId:({accountId:r,entityType:t,entityId:i})=>n.findOne({account_id:r,entity_type:t,entity_id:i}),findManyByEntityIds:async({accountId:r,entityType:t,entityIds:i})=>i.length===0?[]:(d(e),await e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",t).where("entity_id","in",i).execute()),listByScope:({accountId:r,entityType:t,limit:i,offset:s})=>n.findMany({where:{account_id:r,entity_type:t},limit:i,offset:s}),searchByEntityId:async({accountId:r,entityType:t,query:i,limit:s,offset:u})=>{d(e);let c=e.db.selectFrom("corsair_entities").selectAll().where("account_id","=",r).where("entity_type","=",t).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:t,entityId:i,version:s,data:u})=>{let c=await n.findOne({account_id:r,entity_type:t,entity_id:i});return c?await n.update(c.id,{version:s,data:u}):n.create({account_id:r,entity_type:t,entity_id:i,version:s,data:u})},deleteByEntityId:async({accountId:r,entityType:t,entityId:i})=>{d(e);let s=await e.db.deleteFrom("corsair_entities").where("account_id","=",r).where("entity_type","=",t).where("entity_id","=",i).executeTakeFirst();return Number(s.numDeletedRows)>0}}}function M(e){let n=T(e,"corsair_events");return{...n,listByAccount:(r,t)=>n.findMany({where:{account_id:r},limit:t?.limit,offset:t?.offset}),listByStatus:(r,t)=>{let i={status:r};return t?.accountId&&(i.account_id=t.accountId),n.findMany({where:i,limit:t?.limit,offset:t?.offset})},listPending:r=>{let t={status:"pending"};return r?.accountId&&(t.account_id=r.accountId),n.findMany({where:t,limit:r?.limit??100})},updateStatus:(r,t)=>n.update(r,{status:t})}}function A(e){return{integrations:N(e),accounts:v(e),entities:W(e),events:M(e)}}function $(e,n,r,t,i){let s=null;async function u(){if(s!==null)return s;d(e);let c=await e.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 e.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(e),h(e.db,u,r,t,i)}function P(e){let{database:n,integrationName:r,schema:t,tenantId:i}=e,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(t.entities))C[o]=$(n,u,o,t.version,a);return{...C,$orm:s,$integrationName:r,$tenantId:i,$getAccountId:m}}function Z(e,n){let r=A(e);return{$tenantId:n,$orm:r,listAccounts:t=>r.accounts.listByTenant(n,t),findAccountByIntegration:t=>r.accounts.findByTenantAndIntegration(n,t),listEntities:async t=>{d(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let s=i.map(c=>c.id),u=e.db.selectFrom("corsair_entities").selectAll().where("account_id","in",s);return t?.entityType&&(u=u.where("entity_type","=",t.entityType)),typeof t?.limit=="number"&&(u=u.limit(t.limit)),typeof t?.offset=="number"&&(u=u.offset(t.offset)),await u.execute()},listEvents:async t=>{d(e);let i=await e.db.selectFrom("corsair_accounts").select("id").where("tenant_id","=",n).execute();if(i.length===0)return[];let s=i.map(c=>c.id),u=e.db.selectFrom("corsair_events").selectAll().where("account_id","in",s);return t?.status&&(u=u.where("status","=",t.status)),typeof t?.limit=="number"&&(u=u.limit(t.limit)),typeof t?.offset=="number"&&(u=u.offset(t.offset)),await u.execute()},forIntegration:t=>P({database:e,integrationName:t.integrationName,schema:t.schema,tenantId:n})}}function j(e,n){return{forTenant:r=>P({database:e,integrationName:n.integrationName,schema:n.schema,tenantId:r})}}export{k as a,A as b,P as c,Z as d,j as e};
@@ -1,5 +0,0 @@
1
- import{C as A,D as T,j as w,k as C,l as S}from"./chunk-W6KENKHM.js";import{a as _}from"./chunk-AAWROBCK.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};