corsair 0.1.65 → 0.1.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-CDFPFO6N.js +5 -0
- package/dist/{chunk-4BDS3PPC.js → chunk-GN4ET25A.js} +1 -1
- package/dist/core.d.ts +15 -15
- package/dist/core.js +1 -1
- package/dist/{index-h_UAleEL.d.ts → index-DYb70ur1.d.ts} +2 -2
- package/dist/{index-DLUKAEBX.d.ts → index-TDdpzfoQ.d.ts} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/oauth.js +1 -1
- package/dist/setup.d.ts +12 -4
- package/dist/setup.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CEZCHZQC.js +0 -5
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{i as h,j as C,k as S,u as $,v as A}from"./chunk-GN4ET25A.js";import{a as P}from"./chunk-7IH5DNUL.js";import{Kysely as T}from"kysely";import{ZodBoolean as R,ZodDate as M,ZodEffects as j,ZodEnum as v,ZodNullable as O,ZodNumber as D,ZodObject as E,ZodOptional as F,ZodRecord as x,ZodString as K,ZodType as B}from"zod";var m={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},repositories:{list:{}}},discord:{guilds:{list:{}},channels:{list:{}}},hubspot:{contacts:{getMany:{}},companies:{getMany:{}},deals:{getMany:{}}},gmail:{messages:{list:{}},labels:{list:{}},drafts:{list:{}},threads:{list:{}}},googlecalendar:{events:{getMany:{}}},googledrive:{files:{list:{}},folders:{list:{}},sharedDrives:{list:{}}},notion:{databases:{getManyDatabases:{}},databasePages:{getManyDatabasePages:{}},users:{getManyUsers:{}}},airtable:{bases:{getMany:{}}},todoist:{projects:{getMany:{}},tasks:{getMany:{}}},cal:{bookings:{list:{}}}};async function se(e,t){let a=[],s=r=>{a.push(r),console.log(r)},c=r=>{a.push(r),console.warn(r)},o=t?.caller??"script",y=t?.tenantId!==void 0,n=t?.tenantId??"default";if(!n)throw new Error("setupCorsair: tenantId must be a non-empty string");let i=L(e);if(!i)throw new Error("setupCorsair: invalid corsair instance");if(!i.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let u={...i,database:i.database},f=u.database.db;await H(f,c);let p=await J(f,u,n,s);t?.credentials&&Object.keys(t.credentials).length>0&&await z(p,t.credentials,{tenantId:n,tenantIdWasProvided:y},s,c);let l=await V(p,n,s,o);if(t?.backfill){s("[corsair:setup] Starting backfill...");let r=A({plugins:i.plugins,database:f,kek:i.kek,multiTenancy:!0}).withTenant(n);await q(r,i.plugins,l,s,c),s("[corsair:setup] Backfill complete.")}return a.join(`
|
|
2
|
+
`)}function b(e){return typeof e=="object"&&e!==null}function N(e){return!b(e)||!Array.isArray(e.plugins)||typeof e.kek!="string"||typeof e.multiTenancy!="boolean"?!1:e.database===void 0?!0:b(e.database)?e.database.db instanceof T:!1}function L(e){let t=Object.getOwnPropertyDescriptor(e,$);if(t)return N(t.value)?t.value:void 0}function Z(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"}function W(e){let t=e.options?.authType;return Z(t)?t:void 0}function k(e,t){if(!b(e))return;let a=e[t];return typeof a=="function"?(...s)=>Reflect.apply(a,e,s):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 Y={...P};function w(e){if(e instanceof E){let t={};for(let[a,s]of Object.entries(e.shape))t[a]=s instanceof B?w(s):"unknown";return t}return e instanceof j?w(e.innerType()):e instanceof O?`${w(e.unwrap())} | null`:e instanceof F?`${w(e.unwrap())} | undefined`:e instanceof v?e.options.join(" | "):e instanceof K?"string":e instanceof D?"number":e instanceof R?"boolean":e instanceof M?"date":e instanceof x?"jsonb":"unknown"}async function H(e,t){let a=await e.introspection.getTables(),s=new Set(a.map(c=>c.name));for(let[c,o]of Object.entries(Y))s.has(c)||t(`[corsair:setup] Table "${c}" does not exist. Run your database migrations before calling setupCorsair.
|
|
3
|
+
Schema: ${JSON.stringify(w(o),null,2)}`)}async function J(e,t,a,s){let c=new Date,o=new Map;for(let y of t.plugins){let n=y.id,i=W(y),u=await e.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!u){let d=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:d,name:n,config:{},created_at:c,updated_at:c}).execute(),u=await e.selectFrom("corsair_integrations").selectAll().where("id","=",d).executeTakeFirst(),s(`[corsair:setup] Created integration: ${n}`)}let f=i?y.authConfig?.[i]?.integration??[]:[],p=i?y.authConfig?.[i]?.account??[]:[],l=i&&u?C({authType:i,integrationName:n,kek:t.kek,database:t.database,extraIntegrationFields:f}):void 0;if(u&&!u.dek&&l&&(await l.issue_new_dek(),s(`[corsair:setup] Issued integration DEK: ${n}`)),!u)continue;let r=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",a).where("integration_id","=",u.id).executeTakeFirst();if(!r){let d=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:d,tenant_id:a,integration_id:u.id,config:{},created_at:c,updated_at:c}).execute(),r=await e.selectFrom("corsair_accounts").selectAll().where("id","=",d).executeTakeFirst(),s(`[corsair:setup] Created account: ${n}`)}let g=i&&r?S({authType:i,integrationName:n,tenantId:a,kek:t.kek,database:t.database,extraAccountFields:p}):void 0;r&&!r.dek&&g&&(await g.issue_new_dek(),s(`[corsair:setup] Issued account DEK: ${n}`)),i&&l&&g&&o.set(n,{pluginId:n,authType:i,integration:l,account:g,integrationFields:[...h[i].integration,...f],accountFields:[...h[i].account,...p]})}return o}async function z(e,t,a,s,c){for(let[o,y]of Object.entries(t)){let n=e.get(o);for(let[i,u]of Object.entries(y)){let f=`set_${i}`,p=k(n?.integration,f),l=k(n?.account,f);if(p){if(a.tenantIdWasProvided)throw new Error(`[corsair:setup] '${o}.${i}' is an integration-level credential shared across all tenants. You passed tenantId="${a.tenantId}", which only scopes account-level credentials. Run setup without tenantId if you intend to change this credential globally.`);await p(u),s(`[corsair:setup] Set integration credential: ${o}.${i}`)}else l?(await l(u),s(`[corsair:setup] Set account credential: ${o}.${i}`)):c(`[corsair:setup] No setter found for '${o}.${i}' - skipping.`)}}}var I=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Q(e,t,a,s,c,o,y,n,i){let u=[],f=[];for(let l of c){if(I.has(l))continue;let r=k(a,`get_${l}`);if(!r)continue;let g=null;try{let d=await r();g=typeof d=="string"?d:null}catch{}g||u.push(l)}for(let l of o){if(I.has(l))continue;let r=k(s,`get_${l}`);if(!r)continue;let g=null;try{let d=await r();g=typeof d=="string"?d:null}catch{}g||f.push(l)}let p=u.length===0&&f.length===0;if(p)n(`[corsair:setup] '${e}' (${t}) is configured \u2713`);else{let l=[...u,...f];if(i==="cli"){let r=l.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 u)r.push(` await corsair.keys.${e}.set_${g}(value)`);for(let g of f){let d=y==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(y)}).${e}`;r.push(` await ${d}.keys.set_${g}(value)`)}n(r.join(`
|
|
5
|
+
`))}}return p}async function V(e,t,a,s){let c=new Set;for(let o of e.values())await Q(o.pluginId,o.authType,o.integration,o.account,o.integrationFields,o.accountFields,t,a,s)&&c.add(o.pluginId);return c}async function q(e,t,a,s,c){if(!U(m)){c("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let o=m,y=new Set(t.map(n=>n.id));for(let[n,i]of Object.entries(o)){if(!y.has(n))continue;if(!a.has(n)){s(`[corsair:setup] Skipping backfill for '${n}' \u2014 auth not configured.`);continue}let u=b(e)?e[n]:void 0,f=b(u)?u.api:void 0;if(f)for(let[p,l]of Object.entries(i))for(let[r,g]of Object.entries(l)){s(`[corsair:setup] Backfilling ${n} \u203A ${p}.${r}...`);try{let d=b(f)?f[p]:void 0;await k(d,r)?.(g)}catch(d){c(`[corsair:setup] ${n} \u203A ${p}.${r} failed: `+(d instanceof Error?d.message:String(d)))}}}}export{se as a};
|
|
@@ -10,7 +10,7 @@ To generate a KEK, run: openssl rand -base64 ${j}`)}})}var W={oauth_2:{integrati
|
|
|
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 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`{
|
|
13
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ae(e.db,d,l):{result:"blocked",reason:"pending",id:d,token:c}}function Ge(e){return typeof e=="function"}function oe({endpoints:e,hooks:t,ctx:n,tree:o,pluginId:r,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}){for(let[g,u]of Object.entries(e)){let f=t?.[g];if(Ge(u)){let m=f,k=[...s,g].join("."),P=async(b={})=>{let y;if(d){let E=c?.[k],{result:S,reason:I,onComplete:Z,token:D,id:O}=await _e({pluginId:r,endpointPath:k,args:b,mode:d.mode,override:d.overrides?.[k],riskLevel:E?.riskLevel??"write",meta:E,db:l,timeoutMs:p?Re(p.timeout):void 0,tenantId:h,approvalMode:p?.mode});if(S==="blocked"){let x;throw I==="denied"?x=`Action '${k}' was denied by the user. Await further instructions before proceeding.`:I==="policy"?x=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`:I==="timeout"?x=`Action '${k}' timed out waiting for approval.`:p?.formatAsyncMessage&&D&&O?x=p.formatAsyncMessage({token:D,id:O,plugin:r,endpoint:k,args:b}):x=`Action '${k}' requires user approval before it can run.`,new Error(x)}y=Z}let w=async(E,S,I)=>{try{return await u(S,I)}catch(Z){if(Z instanceof Error){let D=await xe(Z,r,k,typeof I=="object"&&I!==null?I:{args:I},i);if(E<(D.maxRetries||0)){let O=E+1;console.log(`Retrying (${O} / ${D.maxRetries})...`);let x;if(D.headersRetryAfterMs)x=D.headersRetryAfterMs;else switch(D.retryStrategy){case"exponential_backoff":x=Math.pow(2,O-1)*1e3;break;case"exponential_backoff_jitter":let Q=Math.pow(2,O-1)*1e3,Be=(Math.random()-.5)*1e3;x=Math.max(0,Q+Be);break;case"linear_1s":x=1e3;break;case"linear_2s":x=2e3;break;case"linear_3s":x=3e3;break;case"linear_4s":x=4e3;break;default:x=1e3;break}await new Promise(Q=>setTimeout(Q,x)),await w(O,S,I),console.log(`[corsair:${r}:${k}] Retry strategy:`,D)}}throw Z}},T=a?await a(n,"endpoint"):void 0;if(!m?.before&&!m?.after){let E=await w(0,{...n,key:T},b);return await y?.(),E}let _={...n,key:T},C=m.before?await m.before(_,b):{ctx:_,args:b,continue:!0,passToAfter:void 0};if(C.continue===!1)return;let A=await w(0,C.ctx,C.args);return await m.after?.(C.ctx,A,C.passToAfter),await y?.(),A};o[g]=P}else if(u&&typeof u=="object"){let m={};oe({endpoints:u,hooks:f,ctx:n,tree:m,pluginId:r,errorHandlers:i,currentPath:[...s,g],keyBuilder:a,permissionsConfig:d,endpointMeta:c,database:l,approvalConfig:p,tenantId:h}),o[g]=m}}}function Je(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function re({webhooks:e,hooks:t,ctx:n,webhooksTree:o,keyBuilder:r}){for(let[i,s]of Object.entries(e)){let a=t?.[i];if(Je(s)){let d=a,c=async l=>{let p=(g,u)=>s.handler(g,u),h=r?await r(n,"webhook"):void 0;return!d?.before&&!d?.after?p({...n,key:h},l):(async()=>{let g={...n,key:h},u=d.before?await d.before(g,l):{ctx:g,args:l,continue:!0,passToAfter:void 0};if(u.continue===!1)return;let f=await p(u.ctx,u.args);return f?.success===!0&&await d.after?.(u.ctx,f,u.passToAfter),f})()};o[i]={match:s.match,handler:c}}else if(s&&typeof s=="object"){let d={};re({webhooks:s,hooks:a,ctx:n,webhooksTree:d,keyBuilder:r}),o[i]=d}}}function Ve(e,t,n){let o=null;return async()=>{if(o)return o;if(!e)throw new Error("Database not configured");let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!r)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",n).where("integration_id","=",r.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${n}" and integration "${t}". Make sure to create the account first.`);return o=i.id,o}}function Ye(e,t,n,o,r){return e?X(e.db,t,n,o,r):{findByEntityId:async()=>null,findById:async()=>null,findManyByEntityIds:async()=>[],list:async()=>[],search:async()=>[],upsertByEntityId:async()=>{throw new Error("Database not configured")},deleteById:async()=>!1,deleteByEntityId:async()=>!1,count:async()=>0}}function ie(e,t){let{database:n,tenantId:o,kek:r,rootErrorHandlers:i,approvalConfig:s}=t,a={},d={};for(let c of e)a[c.id]={},d[c.id]={};for(let c of e){let l=c.schema,p=o??"default",h=Ve(n,c.id,p);if(l?.entities){let C={};for(let[A,E]of Object.entries(l.entities)){let S=n?X(n.db,h,A,l.version,E):Ye(void 0,h,A,l.version,E);C[A]=S}d[c.id].db=C,a[c.id].db=C}let g=c.options,u=c.authConfig,f;if(n&&r&&g?.authType){let C=u?.[g.authType]?.account??[];f=V({authType:g.authType,integrationName:c.id,tenantId:p,kek:r,database:n,extraAccountFields:C}),a[c.id].keys=f}let m={database:n,db:d[c.id]?.db??{},$getAccountId:h,...c.options?{options:c.options}:{},...f?{keys:f,authType:g?.authType}:{},...o?{tenantId:o}:{}},k=c.endpoints??{},P=c.hooks,b={...i,...c.errorHandlers},y={},w=c.options?.permissions;oe({endpoints:k,hooks:P,ctx:m,tree:y,pluginId:c.id,errorHandlers:b,currentPath:[],keyBuilder:c.keyBuilder,permissionsConfig:w,endpointMeta:c.endpointMeta,database:n,approvalConfig:s,tenantId:o}),Object.keys(y).length>0&&(a[c.id].api=y),m.endpoints=y;let T=c.webhooks??{},_=c.webhookHooks;if(Object.keys(T).length>0){let C={};re({webhooks:T,hooks:_,ctx:m,webhooksTree:C,keyBuilder:c.keyBuilder}),a[c.id].webhooks=C,c.pluginWebhookMatcher&&(a[c.id].pluginWebhookMatcher=c.pluginWebhookMatcher)}}return a}function Ie(e,t,n){let o={};for(let r of e){let i=r.options,s=r.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],d=J({authType:i.authType,integrationName:r.id,kek:n,database:t,extraIntegrationFields:a});o[r.id]=d}}return o}async function De(e,t,n,o,r="pending"){if(!e)return null;try{let i=he(),s=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:s,updated_at:s,account_id:t,event_type:n,payload:o,status:r}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function Qe(e,t,n,o="pending"){try{let r=await e.$getAccountId();return De(e.database,r,t,n,o)}catch(r){return console.warn("Failed to log event:",r),null}}import*as ve from"https";import*as Oe from"querystring";function Fe(e,t,n,o,r){let i=new URL(o.tokenUrl),s=o.tokenAuthMethod==="basic";return new Promise((a,d)=>{let c={code:e.trim(),redirect_uri:r,grant_type:"authorization_code"};s||(c.client_id=t,c.client_secret=n);let l=Oe.stringify(c),p={"Content-Type":"application/x-www-form-urlencoded","Content-Length":Buffer.byteLength(l).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${t}:${n}`).toString("base64")}`);let h=ve.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},g=>{let u="";g.on("data",f=>{u+=f}),g.on("end",()=>{if(g.statusCode!==200){d(new Error(`Token exchange failed (${g.statusCode}): ${u}`));return}try{a(JSON.parse(u))}catch{d(new Error(`Token endpoint returned non-JSON response: ${u}`))}})});h.on("error",g=>d(new Error(`Request failed: ${g.message}`))),h.write(l),h.end()})}var $e=["ably","airtable","amplitude","asana","box","cal","calendly","cursor","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","github","gitlab","gmail","googlecalendar","googledrive","googlesheets","hackernews","hubspot","intercom","jira","linear","monday","notion","onedrive","openweathermap","oura","outlook","pagerduty","posthog","razorpay","reddit","resend","sentry","sharepoint","slack","spotify","strava","stripe","tavily","teams","telegram","todoist","trello","twitter","twitterapiio","typeform","vapi","youtube","zoom"];var Ke=" ";function R(e){let t=e._def,n=t.typeName;switch(n){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(t.value);case"ZodEnum":return t.values.map(o=>String(o)).join(" | ");case"ZodOptional":return R(t.innerType);case"ZodNullable":return`${R(t.innerType)} | null`;case"ZodArray":{let o=t.type,i=o._def.typeName==="ZodUnion",s=R(o);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let o=t.shape(),r=Object.entries(o);return r.length===0?"{}":`{ ${r.map(([s,a])=>{let d=a._def.typeName;return`${d==="ZodOptional"||d==="ZodNullable"?s+"?":s}: ${R(a)}`}).join(", ")} }`}case"ZodUnion":return t.options.map(R).join(" | ");case"ZodIntersection":return`${R(t.left)} & ${R(t.right)}`;case"ZodEffects":return R(t.schema);default:return(n??"unknown").replace("Zod","").toLowerCase()}}function H(e,t){let n=e._def,o=n.typeName;if(o==="ZodOptional"||o==="ZodEffects")return H(o==="ZodOptional"?n.innerType:n.schema,t);if(o!=="ZodObject")return R(e);let r=n.shape(),i=Object.entries(r);if(i.length===0)return"{}";let s=Ke.repeat(t+1),a=Ke.repeat(t),d=[];for(let[c,l]of i){let p=l._def,h=p.typeName,u=h==="ZodOptional"||h==="ZodNullable"?`${c}?`:c,f=h==="ZodOptional"||h==="ZodNullable"?p.innerType:l,m=f?._def,k=m?.typeName,P=m?.description,b=P?` // ${P}`:"";k==="ZodObject"?d.push(`${s}${u}: ${H(f,t+1)}${b}`):d.push(`${s}${u}: ${R(l)}${b}`)}return`{
|
|
14
14
|
${d.join(`
|
|
15
15
|
`)}
|
|
16
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(`
|
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-
|
|
1
|
+
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, D as DocSchemaFieldRow, b as DocSchemaShape, d as DocsApiEndpoint, e as DocsDbEntity, f as DocsDbFilterField, g as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, P as PluginDocsIntrospection, c as createCorsair, i as introspectPluginForDocs } from './index-TDdpzfoQ.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
|
-
import { A as AuthTypes, g as AccountKeyManagerFor, I as IntegrationKeyManagerFor
|
|
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-
|
|
3
|
+
import { O as OAuthConfig, A as AuthTypes, g as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DYb70ur1.js';
|
|
4
|
+
export { h as AccountFieldNames, n as AllProviders, m as BASE_AUTH_FIELDS, i as BaseAuthFieldConfig, j as BaseKeyManager, f as BaseProviders, K as BeforeHookResult, p as BindEndpoints, a3 as BindWebhooks, a1 as Bivariant, q as BoundEndpointFn, r as BoundEndpointTree, a4 as BoundWebhook, B as BoundWebhookTree, d as CorsairClient, s as CorsairContext, t as CorsairEndpoint, w as CorsairErrorHandler, a as CorsairIntegration, L as CorsairKeyBuilder, M as CorsairKeyBuilderBase, e as CorsairPermissionsNamespace, C as CorsairPlugin, N as CorsairPluginContext, c as CorsairSingleTenantClient, b as CorsairTenantWrapper, a5 as CorsairWebhook, a6 as CorsairWebhookHandler, a7 as CorsairWebhookMatcher, Q as EndpointHooks, S as EndpointMetaEntry, u as EndpointPathsOf, E as EndpointRiskLevel, v as EndpointTree, H as EnforcePermissionOptions, J as EnforcePermissionResult, x as ErrorContext, y as ErrorHandler, z as ErrorHandlerAndMatchFunction, D as ErrorMatcher, k as IntegrationFieldNames, T as KeyBuilderContext, l as OAuth2IntegrationCredentials, U as PermissionMode, V as PermissionPolicy, o as PickAuth, P as PluginAuthConfig, X as PluginEndpointMeta, Y as PluginPermissionsConfig, R as RawWebhookRequest, Z as RequiredPluginEndpointMeta, _ as RequiredPluginEndpointSchemas, $ as RequiredPluginWebhookSchemas, F as RetryStrategies, G as RetryStrategy, a2 as UnionToIntersection, a0 as WebhookHooks, a8 as WebhookPathsOf, a9 as WebhookRequest, W as WebhookResponse, aa as WebhookTree } from './index-DYb70ur1.js';
|
|
5
5
|
import 'kysely';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import 'pg';
|
|
@@ -108,6 +108,18 @@ declare function decryptConfig(encryptedConfig: Record<string, string>, dek: str
|
|
|
108
108
|
*/
|
|
109
109
|
declare function reEncryptConfig(encryptedConfig: Record<string, string>, oldDek: string, newDek: string): Record<string, string>;
|
|
110
110
|
|
|
111
|
+
type TokenResponse = {
|
|
112
|
+
access_token?: string;
|
|
113
|
+
refresh_token?: string;
|
|
114
|
+
expires_in?: number;
|
|
115
|
+
token_type?: string;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Exchanges an OAuth authorization code for access/refresh tokens.
|
|
119
|
+
* Supports both 'body' (default) and 'basic' token auth methods.
|
|
120
|
+
*/
|
|
121
|
+
declare function exchangeCodeForTokens(code: string, clientId: string, clientSecret: string, oauthConfig: OAuthConfig, redirectUri: string): Promise<TokenResponse>;
|
|
122
|
+
|
|
111
123
|
type IntegrationKeyManagerOptions<T extends AuthTypes> = {
|
|
112
124
|
authType: T;
|
|
113
125
|
integrationName: string;
|
|
@@ -149,16 +161,4 @@ declare function initializeIntegrationDEK(database: CorsairDatabase, integration
|
|
|
149
161
|
*/
|
|
150
162
|
declare function initializeAccountDEK(database: CorsairDatabase, integrationName: string, tenantId: string, kek: string): Promise<string>;
|
|
151
163
|
|
|
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
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,p,t as q,u as r,v as s}from"./chunk-
|
|
1
|
+
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,t as q,u as r,v as s}from"./chunk-GN4ET25A.js";import"./chunk-2PB34FTK.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{i as BASE_AUTH_FIELDS,r as CORSAIR_INTERNAL,k as createAccountKeyManager,s as createCorsair,j as createIntegrationKeyManager,g as decryptConfig,c as decryptDEK,e as decryptWithDEK,f as encryptConfig,b as encryptDEK,d as encryptWithDEK,p as exchangeCodeForTokens,a as generateDEK,m as initializeAccountDEK,l as initializeIntegrationDEK,q as introspectPluginForDocs,n as logEvent,o as logEventFromContext,h as reEncryptConfig};
|
|
@@ -3,8 +3,8 @@ import { CorsairPluginSchema, PluginEntityClients } from './orm.js';
|
|
|
3
3
|
import { CorsairDatabase, CorsairDatabaseInput, CorsairPermission } from './db.js';
|
|
4
4
|
|
|
5
5
|
type AllErrors = 'RATE_LIMIT_ERROR' | 'AUTH_ERROR' | 'PERMISSION_ERROR' | 'NETWORK_ERROR' | 'TIMEOUT_ERROR' | 'SERVER_ERROR' | 'VALIDATION_ERROR' | 'NOT_FOUND_ERROR' | 'BAD_REQUEST_ERROR' | 'PARSING_ERROR' | 'DEFAULT' | (string & {});
|
|
6
|
-
declare const BaseProviders: readonly ["ably", "airtable", "amplitude", "asana", "box", "cal", "calendly", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tavily", "teams", "telegram", "todoist", "trello", "twitter", "twitterapiio", "typeform", "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 & {});
|
|
6
|
+
declare const BaseProviders: readonly ["ably", "airtable", "amplitude", "asana", "box", "cal", "calendly", "cursor", "discord", "dodopayments", "dropbox", "exa", "figma", "firecrawl", "fireflies", "github", "gitlab", "gmail", "googlecalendar", "googledrive", "googlesheets", "hackernews", "hubspot", "intercom", "jira", "linear", "monday", "notion", "onedrive", "openweathermap", "oura", "outlook", "pagerduty", "posthog", "razorpay", "reddit", "resend", "sentry", "sharepoint", "slack", "spotify", "strava", "stripe", "tavily", "teams", "telegram", "todoist", "trello", "twitter", "twitterapiio", "typeform", "vapi", "youtube", "zoom"];
|
|
7
|
+
type AllProviders = 'ably' | 'airtable' | 'amplitude' | 'asana' | 'box' | 'cal' | 'calendly' | 'cursor' | 'discord' | 'dodopayments' | 'dropbox' | 'exa' | 'figma' | 'firecrawl' | 'fireflies' | 'github' | 'gitlab' | 'gmail' | 'googlecalendar' | 'googledrive' | 'googlesheets' | 'hackernews' | 'hubspot' | 'intercom' | 'jira' | 'linear' | 'monday' | 'notion' | 'onedrive' | 'openweathermap' | 'oura' | 'outlook' | 'pagerduty' | 'posthog' | 'razorpay' | 'reddit' | 'resend' | 'sentry' | 'sharepoint' | 'slack' | 'spotify' | 'strava' | 'stripe' | 'tavily' | 'teams' | 'telegram' | 'todoist' | 'trello' | 'twitter' | 'twitterapiio' | 'typeform' | 'vapi' | 'youtube' | 'zoom' | (string & {});
|
|
8
8
|
type AuthTypes = 'oauth_2' | 'api_key' | 'bot_token';
|
|
9
9
|
type PickAuth<T extends AuthTypes> = T;
|
|
10
10
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as EndpointRiskLevel, C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-
|
|
1
|
+
import { E as EndpointRiskLevel, C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-DYb70ur1.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. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { L as ListOperationsOptions } from './index-
|
|
2
|
-
export { c as createCorsair } from './index-
|
|
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-
|
|
1
|
+
import { L as ListOperationsOptions } from './index-TDdpzfoQ.js';
|
|
2
|
+
export { c as createCorsair } from './index-TDdpzfoQ.js';
|
|
3
|
+
import { c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, d as CorsairClient, e as CorsairPermissionsNamespace, B as BoundWebhookTree, R as RawWebhookRequest, f as BaseProviders, W as WebhookResponse } from './index-DYb70ur1.js';
|
|
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-
|
|
1
|
+
import{a as I}from"./chunk-CDFPFO6N.js";import{q as m,r as k,s as b,u as y,v as W}from"./chunk-GN4ET25A.js";import"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";function w(n){let r=n[y];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function O(n,r){let o=k(w(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
|
|
2
2
|
`):Object.values(o).flat().join(`
|
|
3
3
|
`)}function S(n,r){return b(w(n),r)}var T=Symbol.for("corsair:internal");function B(n,r){let o=n;for(let e of r){if(!o||typeof o!="object")return null;o=o[e]}return typeof o=="function"?o:null}function x(n){return n[T]?.database}async function A(n,r){let o=new Date().toISOString(),e=await n.permissions.find_by_token(r);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<o){let i=x(n);return i&&await i.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let t=e.tenant_id??"default",g=(n.withTenant?n.withTenant(t):n)[e.plugin];if(!g?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let p=B(g.api,e.endpoint.split("."));if(!p)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let i=typeof e.args=="string"?JSON.parse(e.args):e.args,u=await p(i);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:u}}catch(i){let u=i instanceof Error?i.message:String(i),d=x(n);return d&&await d.db.updateTable("corsair_permissions").set({status:"failed",error:u,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:u}}}function E(n){return n!==null&&typeof n=="object"&&"match"in n&&"handler"in n&&typeof n.match=="function"&&typeof n.handler=="function"}function C(n,r,o=[]){for(let[e,t]of Object.entries(n))if(E(t)){if(t.match(r))return{webhook:t,path:[...o,e]}}else if(t&&typeof t=="object"){let s=C(t,r,[...o,e]);if(s)return s}return null}function $(n){let r={};for(let[o,e]of Object.entries(n))r[o.toLowerCase()]=Array.isArray(e)?e[0]:e;return r}function j(n){let r=n["x-goog-resource-uri"],o=n["x-goog-channel-id"];if(!r||!o)return null;let e={resourceId:n["x-goog-resource-id"]||"",resourceState:n["x-goog-resource-state"]||"",resourceUri:r,channelId:o,channelExpiration:n["x-goog-channel-expiration"]||""};return r.includes("/drive/")&&(e.kind="drive#change"),{message:{data:Buffer.from(JSON.stringify(e)).toString("base64"),messageId:n["x-goog-message-number"]||""}}}async function _(n,r,o,e){let t=$(r),s=typeof o=="string"?JSON.parse(o):o;(!s||typeof s=="object"&&Object.keys(s).length===0)&&t["x-goog-resource-uri"]&&(s=j(t)||s);let p={headers:t,body:s},i=e?.tenantId||"default",u=n.withTenant?n.withTenant(i):n,d=m;for(let l of d){let c=u[l];if(!c||!c.webhooks||c.pluginWebhookMatcher&&!c.pluginWebhookMatcher(p))continue;let f=C(c.webhooks,p);if(!f)continue;let h=f.path.join("."),R={payload:s,headers:t,rawBody:typeof o=="string"?o:JSON.stringify(o)};try{let a=await f.webhook.handler(R),P=!!Object.keys(a.returnToSender||{})?.length;return{plugin:l,action:h,body:s,response:P?{...a?.returnToSender,success:!0}:{success:!0},...a.responseHeaders&&{responseHeaders:a.responseHeaders}}}catch(a){return console.error(`Error executing webhook handler for ${l}.${h}:`,a),{plugin:l,action:h,body:s,response:{success:!1,error:a instanceof Error?a.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}export{W as createCorsair,A as executePermission,S as getSchema,O as listOperations,_ as processWebhook,I as setupCorsair};
|
package/dist/oauth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as m,b as w,j as h,k as A,p as C,u as y}from"./chunk-
|
|
1
|
+
import{a as m,b as w,j as h,k as A,p as C,u as y}from"./chunk-GN4ET25A.js";import{b as _}from"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";import*as l from"crypto";import*as b from"querystring";function x(e,t){return Buffer.from(JSON.stringify({plugin:e,tenantId:t})).toString("base64url")}function S(e){try{let t=e.includes(".")?e.split(".")[0]:e,n=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));return n!==null&&typeof n=="object"&&"plugin"in n&&"tenantId"in n&&typeof n.plugin=="string"&&typeof n.tenantId=="string"?n:null}catch{return null}}function N(e,t){let n=l.createHmac("sha256",t).update(e).digest("base64url");return`${e}.${n}`}function U(e,t){let n=e.lastIndexOf(".");if(n===-1)return null;let a=e.slice(0,n),i=e.slice(n+1),r=l.createHmac("sha256",t).update(a).digest("base64url"),s=Buffer.from(i,"base64url"),o=Buffer.from(r,"base64url");return s.length!==o.length||!l.timingSafeEqual(s,o)?null:S(a)}function I(e){let t=e[y];if(!t)throw new Error("Invalid corsair instance");return t}function P(e,t){let n=e.plugins.find(a=>a.id===t);if(!n)throw new Error(`Plugin '${t}' not found`);return n}function E(e){let t=e.oauthConfig;if(!t)throw new Error(`Plugin '${e.id}' has no oauthConfig`);return t}async function R(e,t,n,a){let i=_(e),r=await i.integrations.findByName(t);if(!r)throw new Error(`Integration '${t}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:n,integration_id:r.id}))return;let o=m(),c=await w(o,a);await i.accounts.create({tenant_id:n,integration_id:r.id,config:{},dek:c})}async function $(e,t,n){let{tenantId:a,redirectUri:i}=n,r=I(e);if(!r.database)throw new Error("No database configured on corsair instance");let s=P(r,t),o=E(s),f=await h({authType:"oauth_2",integrationName:t,kek:r.kek,database:r.database}).get_client_id();if(!f)throw new Error(`client_id not configured for '${t}'`);let g=N(x(t,a),r.kek),d={...o.authParams,client_id:f,redirect_uri:i,response_type:"code",scope:o.scopes.join(" "),state:g};return{url:`${o.authUrl}?${b.stringify(d)}`,state:g}}async function K(e,t){let{code:n,state:a,redirectUri:i}=t,r=I(e),s=U(a,r.kek);if(!s)throw new Error("Invalid or tampered state parameter");let{plugin:o,tenantId:c}=s;if(!r.database)throw new Error("No database configured on corsair instance");let f=P(r,o),g=E(f),d=h({authType:"oauth_2",integrationName:o,kek:r.kek,database:r.database}),k=await d.get_client_id(),O=await d.get_client_secret();if(!k||!O)throw new Error(`Credentials not configured for '${o}'`);await R(r.database,o,c,r.kek);let u=await C(n,k,O,g,i);if(!u.access_token)throw new Error(`No access_token returned from ${g.providerName}`);let p=A({authType:"oauth_2",integrationName:o,tenantId:c,kek:r.kek,database:r.database});return await p.set_access_token(u.access_token),u.refresh_token&&await p.set_refresh_token(u.refresh_token),u.expires_in&&await p.set_expires_at(String(Math.floor(Date.now()/1e3)+u.expires_in)),{plugin:o,tenantId:c}}export{S as decodeOAuthState,x as encodeOAuthState,$ as generateOAuthUrl,K as processOAuthCallback};
|
package/dist/setup.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CorsairPlugin, c as CorsairSingleTenantClient } from './index-
|
|
1
|
+
import { C as CorsairPlugin, c as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-DYb70ur1.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import './orm.js';
|
|
4
4
|
import './db.js';
|
|
@@ -7,6 +7,12 @@ import 'pg';
|
|
|
7
7
|
import 'postgres';
|
|
8
8
|
|
|
9
9
|
interface SetupCorsairOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Tenant to configure. Defaults to "default" to preserve single-tenant setup
|
|
12
|
+
* behavior, and is used to scope account rows, account credentials, auth
|
|
13
|
+
* checks, and optional backfill.
|
|
14
|
+
*/
|
|
15
|
+
tenantId?: string;
|
|
10
16
|
/**
|
|
11
17
|
* When true, calls list endpoints for every plugin defined in
|
|
12
18
|
* setup/backfill.yaml to seed the local database with initial data.
|
|
@@ -29,22 +35,24 @@ interface SetupCorsairOptions {
|
|
|
29
35
|
*/
|
|
30
36
|
caller?: 'cli' | 'script';
|
|
31
37
|
}
|
|
38
|
+
type SetupCorsairInstance<Plugins extends readonly CorsairPlugin[]> = CorsairSingleTenantClient<Plugins> | CorsairTenantWrapper<Plugins>;
|
|
32
39
|
/**
|
|
33
40
|
* Initialises a corsair instance end-to-end:
|
|
34
41
|
*
|
|
35
42
|
* 1. Checks that all required corsair_* tables exist (warns if any are missing).
|
|
36
43
|
* 2. Ensures every configured plugin has rows in `corsair_integrations` and
|
|
37
|
-
* `corsair_accounts`
|
|
44
|
+
* `corsair_accounts` for the requested tenant and issues DEKs where needed.
|
|
38
45
|
* 3. Applies any credentials passed via `options.credentials`.
|
|
39
46
|
* 4. Checks auth status for each plugin and logs guidance for any missing credentials.
|
|
40
47
|
* When `caller` is 'cli', guidance is printed as CLI flags instead of JS calls.
|
|
41
48
|
* 5. If `{ backfill: true }`, calls the list endpoints defined in
|
|
42
49
|
* `setup/backfill.yaml` for each plugin that has auth configured.
|
|
43
50
|
*
|
|
44
|
-
*
|
|
51
|
+
* Multi-tenant corsair instances are accepted; pass `options.tenantId` to target
|
|
52
|
+
* a non-default tenant.
|
|
45
53
|
*
|
|
46
54
|
* Returns a newline-separated string of all setup output.
|
|
47
55
|
*/
|
|
48
|
-
declare function setupCorsair<const Plugins extends readonly CorsairPlugin[]>(corsair:
|
|
56
|
+
declare function setupCorsair<const Plugins extends readonly CorsairPlugin[]>(corsair: SetupCorsairInstance<Plugins>, options?: SetupCorsairOptions): Promise<string>;
|
|
49
57
|
|
|
50
58
|
export { type SetupCorsairOptions, setupCorsair };
|
package/dist/setup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as o}from"./chunk-
|
|
1
|
+
import{a as o}from"./chunk-CDFPFO6N.js";import"./chunk-GN4ET25A.js";import"./chunk-7IH5DNUL.js";import"./chunk-2PB34FTK.js";import"./chunk-HO245J34.js";import"./chunk-ZGVIF3UY.js";import"./chunk-QAIKSQAD.js";export{o as setupCorsair};
|
package/package.json
CHANGED
package/dist/chunk-CEZCHZQC.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
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
|
-
`)}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
|
-
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
|
-
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(`
|
|
5
|
-
`))}}return n}async function Z(e,c,l,r){let o=new Set,g=e.keys,s=e;for(let u of c){let n=u.id,a=u.options?.authType??"unknown",t=g[n],i=s[n]?.keys;t&&i&&await x(n,a,t,i,l,r)&&o.add(n)}return o}async function L(e,c,l,r,o){let g=b,s=new Set(c.map(n=>n.id)),u=e;for(let[n,a]of Object.entries(g)){if(!s.has(n))continue;if(!l.has(n)){r(`[corsair:setup] Skipping backfill for '${n}' \u2014 auth not configured.`);continue}let t=u[n]?.api;if(t)for(let[i,d]of Object.entries(a))for(let[f,R]of Object.entries(d)){r(`[corsair:setup] Backfilling ${n} \u203A ${i}.${f}...`);try{await t[i]?.[f]?.(R)}catch(y){o(`[corsair:setup] ${n} \u203A ${i}.${f} failed: `+(y instanceof Error?y.message:String(y)))}}}}export{Y as a};
|