@corsair-dev/gmail 0.1.5 → 0.1.6

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/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # @corsair-dev/gmail
2
+
3
+ Gmail plugin for Corsair.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @corsair-dev/gmail
9
+ ```
10
+
11
+ ## Endpoints
12
+
13
+ | Operation | Operation ID | Risk | Description |
14
+ |-----------|--------------|------|-------------|
15
+ | `drafts.create` | `gmail.api.drafts.create` | `write` | Create a new draft |
16
+ | `drafts.delete` | `gmail.api.drafts.delete` | `destructive` | Delete a draft [DESTRUCTIVE] |
17
+ | `drafts.get` | `gmail.api.drafts.get` | `read` | Get a specific draft |
18
+ | `drafts.list` | `gmail.api.drafts.list` | `read` | List drafts in the mailbox |
19
+ | `drafts.send` | `gmail.api.drafts.send` | `write` | Send a draft as an email |
20
+ | `drafts.update` | `gmail.api.drafts.update` | `write` | Update an existing draft |
21
+ | `labels.create` | `gmail.api.labels.create` | `write` | Create a new label |
22
+ | `labels.delete` | `gmail.api.labels.delete` | `destructive` | Delete a label [DESTRUCTIVE] |
23
+ | `labels.get` | `gmail.api.labels.get` | `read` | Get a specific label |
24
+ | `labels.list` | `gmail.api.labels.list` | `read` | List all labels in the mailbox |
25
+ | `labels.update` | `gmail.api.labels.update` | `write` | Update an existing label |
26
+ | `messages.batchModify` | `gmail.api.messages.batchModify` | `write` | Add or remove labels from multiple messages in bulk |
27
+ | `messages.delete` | `gmail.api.messages.delete` | `destructive` | Permanently delete a message [DESTRUCTIVE · IRREVERSIBLE] |
28
+ | `messages.get` | `gmail.api.messages.get` | `read` | Get a specific message |
29
+ | `messages.list` | `gmail.api.messages.list` | `read` | List messages in a mailbox |
30
+ | `messages.modify` | `gmail.api.messages.modify` | `write` | Add or remove labels from a message |
31
+ | `messages.send` | `gmail.api.messages.send` | `write` | Send an email to one or more recipients |
32
+ | `messages.trash` | `gmail.api.messages.trash` | `write` | Move a message to the trash |
33
+ | `messages.untrash` | `gmail.api.messages.untrash` | `write` | Restore a message from the trash |
34
+ | `threads.delete` | `gmail.api.threads.delete` | `destructive` | Permanently delete a thread [DESTRUCTIVE · IRREVERSIBLE] |
35
+ | `threads.get` | `gmail.api.threads.get` | `read` | Get a specific thread |
36
+ | `threads.list` | `gmail.api.threads.list` | `read` | List threads in the mailbox |
37
+ | `threads.modify` | `gmail.api.threads.modify` | `write` | Add or remove labels from a thread |
38
+ | `threads.trash` | `gmail.api.threads.trash` | `write` | Move a thread to the trash |
39
+ | `threads.untrash` | `gmail.api.threads.untrash` | `write` | Restore a thread from the trash |
40
+
41
+ ## Auth
42
+
43
+ Auth: OAuth 2.0. Corsair prompts your tenant for credentials on first use.
44
+
45
+ ## Webhooks
46
+
47
+ Handles 1 webhook event. See the reference for payloads and `webhookHooks`.
48
+
49
+ ## Reference
50
+
51
+ Full docs, types, and examples: https://docs.corsair.dev/plugins/gmail
52
+
53
+ ## License
54
+
55
+ Apache-2.0
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{AuthMissingError as us,getOAuthAccessToken as gs}from"corsair/core";import{logEventFromContext as S}from"corsair/core";import{request as Ve}from"corsair/http";var B="https://gmail.googleapis.com/gmail/v1";async function y(e,t,a={}){let{method:o="GET",body:n,query:i}=a;return await Ve({BASE:B,VERSION:"1.0.0",WITH_CREDENTIALS:!1,CREDENTIALS:"omit",TOKEN:t,HEADERS:{"Content-Type":"application/json"}},{method:o,url:e,body:o==="POST"||o==="PUT"||o==="PATCH"?n:void 0,mediaType:"application/json",query:o==="GET"?i:void 0})}function Ke(e){return e instanceof Error&&"status"in e&&e.status===401}async function p(e,t,a={}){try{return await y(e,t.key,a)}catch(o){if(Ke(o)&&t._refreshAuth){let n=await t._refreshAuth();return await y(e,n,a)}throw o}}var Y=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts`,e,{method:"GET",query:{maxResults:t.maxResults,pageToken:t.pageToken,q:t.q}});if(a.drafts&&e.db.drafts)try{for(let o of a.drafts)o.id&&await e.db.drafts.upsertByEntityId(o.id,{...o,id:o.id,messageId:o.message?.id,createdAt:new Date})}catch(o){console.warn("Failed to save drafts to database:",o)}return await S(e,"gmail.drafts.list",{...t},"completed"),a},Z=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts/${t.id}`,e,{method:"GET",query:{format:t.format}});if(a.id&&e.db.drafts)try{await e.db.drafts.upsertByEntityId(a.id,{...a,id:a.id,messageId:a.message?.id,createdAt:new Date})}catch(o){console.warn("Failed to save draft to database:",o)}return await S(e,"gmail.drafts.get",{...t},"completed"),a},Q=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts`,e,{method:"POST",body:t.draft});return a.id&&await e.endpoints.drafts.get({id:a.id,userId:t.userId}),await S(e,"gmail.drafts.create",{...t},"completed"),a},ee=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts/${t.id}`,e,{method:"PUT",body:t.draft});return a.id&&await e.endpoints.drafts.get({id:a.id,userId:t.userId}),await S(e,"gmail.drafts.update",{...t},"completed"),a},te=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/drafts/${t.id}`,e,{method:"DELETE"}),e.db.drafts)try{await e.db.drafts.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete draft from database:",a)}await S(e,"gmail.drafts.delete",{...t},"completed")},se=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts/send`,e,{method:"POST",body:{id:t.id,message:t.message}});return await S(e,"gmail.drafts.send",{...t},"completed"),a};import{logEventFromContext as D}from"corsair/core";var ae=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels`,e,{method:"GET"});if(a.labels&&e.db.labels)try{for(let o of a.labels)o.id&&await e.db.labels.upsertByEntityId(o.id,{...o,id:o.id,createdAt:new Date})}catch(o){console.warn("Failed to save labels to database:",o)}return await D(e,"gmail.labels.list",{...t},"completed"),a},oe=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels/${t.id}`,e,{method:"GET"});if(a.id&&e.db.labels)try{await e.db.labels.upsertByEntityId(a.id,{id:a.id,name:a.name,messageListVisibility:a.messageListVisibility,labelListVisibility:a.labelListVisibility,type:a.type,messagesTotal:a.messagesTotal,messagesUnread:a.messagesUnread,threadsTotal:a.threadsTotal,threadsUnread:a.threadsUnread,createdAt:new Date})}catch(o){console.warn("Failed to save label to database:",o)}return await D(e,"gmail.labels.get",{...t},"completed"),a},ie=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels`,e,{method:"POST",body:t.label});return a.id&&await e.endpoints.labels.get({id:a.id,userId:t.userId}),await D(e,"gmail.labels.create",{...t},"completed"),a},ne=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels/${t.id}`,e,{method:"PUT",body:t.label});return a.id&&await e.endpoints.labels.get({id:a.id,userId:t.userId}),await D(e,"gmail.labels.update",{...t},"completed"),a},re=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/labels/${t.id}`,e,{method:"DELETE"}),e.db.labels)try{await e.db.labels.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete label from database:",a)}await D(e,"gmail.labels.delete",{...t},"completed")};import{logEventFromContext as I}from"corsair/core";function F(e,t){return e?.headers?e.headers.find(o=>o.name?.toLowerCase()===t.toLowerCase())?.value:void 0}function Ye(e){if(e.payload)return F(e.payload,"Subject")}function Ze(e){if(e.payload)return F(e.payload,"From")}function Qe(e){if(e.payload)return F(e.payload,"To")}function de(e){if(!e)return;let t,a;if(e.body?.data)try{let o=Buffer.from(e.body.data,"base64").toString("utf-8");e.mimeType==="text/plain"?t=o:e.mimeType==="text/html"&&(a=o)}catch{}if(e.parts&&e.parts.length>0)for(let o of e.parts){let n=de(o);n&&(o.mimeType==="text/plain"?t=n:o.mimeType==="text/html"&&!t&&(a=n))}return t||a}function et(e){if(e.payload)return de(e.payload)}var le=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages`,e,{method:"GET",query:{q:t.q,maxResults:t.maxResults,pageToken:t.pageToken,labelIds:t.labelIds?.join(","),includeSpamTrash:t.includeSpamTrash}});if(a.messages&&e.db.messages)try{for(let o of a.messages)o.id&&await e.db.messages.upsertByEntityId(o.id,{...o,id:o.id,createdAt:new Date})}catch(o){console.warn("Failed to save messages to database:",o)}return await I(e,"gmail.messages.list",{...t},"completed"),a},me=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/${t.id}`,e,{method:"GET",query:{format:t.format,metadataHeaders:t.metadataHeaders?.join(",")}});if(a.id&&e.db.messages)try{let o=Ye(a),n=et(a),i=Ze(a),d=Qe(a);await e.db.messages.upsertByEntityId(a.id,{...a,subject:o,body:n,from:i,to:d,id:a.id,createdAt:new Date})}catch(o){console.warn("Failed to save message to database:",o)}return await I(e,"gmail.messages.get",{...t},"completed"),a},pe=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/send`,e,{method:"POST",body:{raw:t.raw,threadId:t.threadId}});return a.id&&await e.endpoints.messages.get({id:a.id,userId:t.userId}),await I(e,"gmail.messages.send",{...t},"completed"),a},ue=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/messages/${t.id}`,e,{method:"DELETE"}),e.db.messages)try{await e.db.messages.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete message from database:",a)}await I(e,"gmail.messages.delete",{...t},"completed")},ge=async(e,t)=>{let a={};t.addLabelIds&&t.addLabelIds.length>0&&(a.addLabelIds=t.addLabelIds),t.removeLabelIds&&t.removeLabelIds.length>0&&(a.removeLabelIds=t.removeLabelIds);let o=await p(`/users/${t.userId||"me"}/messages/${t.id}/modify`,e,{method:"POST",body:a});return o.id&&await e.endpoints.messages.get({id:o.id,userId:t.userId}),await I(e,"gmail.messages.modify",{...t},"completed"),o},ce=async(e,t)=>{let a={ids:t.ids};t.addLabelIds&&t.addLabelIds.length>0&&(a.addLabelIds=t.addLabelIds),t.removeLabelIds&&t.removeLabelIds.length>0&&(a.removeLabelIds=t.removeLabelIds),await p(`/users/${t.userId||"me"}/messages/batchModify`,e,{method:"POST",body:a}),await I(e,"gmail.messages.batchModify",{...t},"completed")},he=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/${t.id}/trash`,e,{method:"POST"});return a.id&&await e.endpoints.messages.get({id:a.id,userId:t.userId}),await I(e,"gmail.messages.trash",{...t},"completed"),a},fe=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/${t.id}/untrash`,e,{method:"POST"});return a.id&&await e.endpoints.messages.get({id:a.id,userId:t.userId}),await I(e,"gmail.messages.untrash",{...t},"completed"),a};import{logEventFromContext as L}from"corsair/core";var be=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads`,e,{method:"GET",query:{q:t.q,maxResults:t.maxResults,pageToken:t.pageToken,labelIds:t.labelIds?.join(","),includeSpamTrash:t.includeSpamTrash}});if(a.threads&&e.db.threads)try{for(let o of a.threads)o.id&&await e.db.threads.upsertByEntityId(o.id,{...o,id:o.id,createdAt:new Date})}catch(o){console.warn("Failed to save threads to database:",o)}return await L(e,"gmail.threads.list",{...t},"completed"),a},ye=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads/${t.id}`,e,{method:"GET",query:{format:t.format,metadataHeaders:t.metadataHeaders?.join(",")}});if(a.id&&e.db.threads)try{await e.db.threads.upsertByEntityId(a.id,{...a,id:a.id,createdAt:new Date})}catch(o){console.warn("Failed to save thread to database:",o)}return await L(e,"gmail.threads.get",{...t},"completed"),a},Ee=async(e,t)=>{let a={};t.addLabelIds&&t.addLabelIds.length>0&&(a.addLabelIds=t.addLabelIds),t.removeLabelIds&&t.removeLabelIds.length>0&&(a.removeLabelIds=t.removeLabelIds);let o=await p(`/users/${t.userId||"me"}/threads/${t.id}/modify`,e,{method:"POST",body:a});return o.id&&await e.endpoints.threads.get({id:o.id,userId:t.userId}),await L(e,"gmail.threads.modify",{...t},"completed"),o},Ge=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/threads/${t.id}`,e,{method:"DELETE"}),e.db.threads)try{await e.db.threads.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete thread from database:",a)}await L(e,"gmail.threads.delete",{...t},"completed")},Ie=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads/${t.id}/trash`,e,{method:"POST"});return a.id&&await e.endpoints.threads.get({id:a.id,userId:t.userId}),await L(e,"gmail.threads.trash",{...t},"completed"),a},we=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads/${t.id}/untrash`,e,{method:"POST"});return a.id&&await e.endpoints.threads.get({id:a.id,userId:t.userId}),await L(e,"gmail.threads.untrash",{...t},"completed"),a};import{z as s}from"zod";var Te="Base64url-encoded RFC 2822 email \u2014 do NOT pass plain email text. Build the MIME message (From, To, Subject, Content-Type headers, blank line, body; lines separated by \\r\\n), then base64url-encode: standard base64, replace + with -, / with _, remove trailing =.",q=s.object({raw:s.string().optional().describe(Te),threadId:s.string().optional()}),at=s.object({userId:s.string().optional(),q:s.string().optional(),maxResults:s.number().optional(),pageToken:s.string().optional(),labelIds:s.array(s.string()).optional(),includeSpamTrash:s.boolean().optional()}),ot=s.object({userId:s.string().optional(),id:s.string(),format:s.enum(["minimal","full","raw","metadata"]).optional(),metadataHeaders:s.array(s.string()).optional()}),it=s.object({userId:s.string().optional(),raw:s.string().describe(Te),threadId:s.string().optional()}),nt=s.object({userId:s.string().optional(),id:s.string()}),rt=s.object({userId:s.string().optional(),id:s.string(),addLabelIds:s.array(s.string()).optional(),removeLabelIds:s.array(s.string()).optional()}),dt=s.object({userId:s.string().optional(),ids:s.array(s.string()).optional(),addLabelIds:s.array(s.string()).optional(),removeLabelIds:s.array(s.string()).optional()}),lt=s.object({userId:s.string().optional(),id:s.string()}),mt=s.object({userId:s.string().optional(),id:s.string()}),pt=s.object({userId:s.string().optional()}),ut=s.object({userId:s.string().optional(),id:s.string()}),gt=s.object({userId:s.string().optional(),label:s.object({name:s.string().optional(),messageListVisibility:s.enum(["show","hide"]).optional(),labelListVisibility:s.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),color:s.object({textColor:s.string().optional(),backgroundColor:s.string().optional()}).optional()})}),ct=s.object({userId:s.string().optional(),id:s.string(),label:s.object({name:s.string().optional(),messageListVisibility:s.enum(["show","hide"]).optional(),labelListVisibility:s.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),color:s.object({textColor:s.string().optional(),backgroundColor:s.string().optional()}).optional()})}),ht=s.object({userId:s.string().optional(),id:s.string()}),ft=s.object({userId:s.string().optional(),maxResults:s.number().optional(),pageToken:s.string().optional(),q:s.string().optional()}),bt=s.object({userId:s.string().optional(),id:s.string(),format:s.enum(["minimal","full","raw","metadata"]).optional()}),yt=s.object({userId:s.string().optional(),draft:s.object({message:q.optional()}).optional().describe("Draft payload. message.raw must be a base64url-encoded RFC 2822 email, not plain text.")}),Et=s.object({userId:s.string().optional(),id:s.string(),draft:s.object({message:q.optional()}).optional().describe("Updated draft payload. message.raw must be a base64url-encoded RFC 2822 email, not plain text.")}),Gt=s.object({userId:s.string().optional(),id:s.string()}),It=s.object({userId:s.string().optional(),id:s.string().optional(),message:q.optional().describe("Optional message body when sending without a draft id. raw must be base64url-encoded RFC 2822, not plain text.")}),wt=s.object({userId:s.string().optional(),q:s.string().optional(),maxResults:s.number().optional(),pageToken:s.string().optional(),labelIds:s.array(s.string()).optional(),includeSpamTrash:s.boolean().optional()}),Tt=s.object({userId:s.string().optional(),id:s.string(),format:s.enum(["minimal","full","metadata"]).optional(),metadataHeaders:s.array(s.string()).optional()}),Mt=s.object({userId:s.string().optional(),id:s.string(),addLabelIds:s.array(s.string()).optional(),removeLabelIds:s.array(s.string()).optional()}),St=s.object({userId:s.string().optional(),id:s.string()}),Lt=s.object({userId:s.string().optional(),id:s.string()}),kt=s.object({userId:s.string().optional(),id:s.string()}),vt=s.object({userId:s.string().optional()}),g={messagesList:at,messagesGet:ot,messagesSend:it,messagesDelete:nt,messagesModify:rt,messagesBatchModify:dt,messagesTrash:lt,messagesUntrash:mt,labelsList:pt,labelsGet:ut,labelsCreate:gt,labelsUpdate:ct,labelsDelete:ht,draftsList:ft,draftsGet:bt,draftsCreate:yt,draftsUpdate:Et,draftsDelete:Gt,draftsSend:It,threadsList:wt,threadsGet:Tt,threadsModify:Mt,threadsDelete:St,threadsTrash:Lt,threadsUntrash:kt,usersGetProfile:vt},Pt=s.object({name:s.string().optional(),value:s.string().optional()}),Ct=s.object({attachmentId:s.string().optional(),size:s.number().optional(),data:s.string().optional()}),Dt=s.object({partId:s.string().optional(),mimeType:s.string().optional(),filename:s.string().optional(),headers:s.array(Pt).optional(),body:Ct.optional()}),Me=Dt.extend({parts:s.lazy(()=>s.array(Me).optional())}),E=s.object({id:s.string().optional(),threadId:s.string().optional(),labelIds:s.array(s.string()).optional(),snippet:s.string().optional(),historyId:s.string().optional(),internalDate:s.union([s.string(),s.number(),s.date()]).transform(e=>{if(e instanceof Date)return e;if(typeof e=="number")return new Date(e);if(typeof e=="string"){let t=Number(e);return isNaN(t)?null:new Date(t)}return null}).nullable().optional(),sizeEstimate:s.number().optional(),payload:Me.optional(),raw:s.string().optional().describe("Full RFC 2822 message in base64url encoding (when format=raw). Not plain text \u2014 decode base64url before reading headers/body.")}),Rt=s.object({messages:s.array(E).optional(),nextPageToken:s.string().optional(),resultSizeEstimate:s.number().optional()}),xt=s.object({textColor:s.string().optional(),backgroundColor:s.string().optional()}),N=s.object({id:s.string().optional(),name:s.string().optional(),messageListVisibility:s.enum(["show","hide"]).optional(),labelListVisibility:s.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),type:s.enum(["system","user"]).optional(),messagesTotal:s.number().optional(),messagesUnread:s.number().optional(),threadsTotal:s.number().optional(),threadsUnread:s.number().optional(),color:xt.optional()}),At=s.object({labels:s.array(N).optional()}),U=s.object({id:s.string().optional(),message:E.optional()}),Ot=s.object({drafts:s.array(U).optional(),nextPageToken:s.string().optional(),resultSizeEstimate:s.number().optional()}),R=s.object({id:s.string().optional(),snippet:s.string().optional(),historyId:s.string().optional(),messages:s.array(E).optional()}),jt=s.object({threads:s.array(R).optional(),nextPageToken:s.string().optional(),resultSizeEstimate:s.number().optional()}),Bt=s.object({emailAddress:s.string().optional(),messagesTotal:s.number().optional(),threadsTotal:s.number().optional(),historyId:s.string().optional()}),c={messagesList:Rt,messagesGet:E,messagesSend:E,messagesDelete:s.void(),messagesModify:E,messagesBatchModify:s.void(),messagesTrash:E,messagesUntrash:E,labelsList:At,labelsGet:N,labelsCreate:N,labelsUpdate:N,labelsDelete:s.void(),draftsList:Ot,draftsGet:U,draftsCreate:U,draftsUpdate:U,draftsDelete:s.void(),draftsSend:E,threadsList:jt,threadsGet:R,threadsModify:R,threadsDelete:s.void(),threadsTrash:R,threadsUntrash:R,usersGetProfile:Bt};var G={list:le,get:me,send:pe,delete:ue,modify:ge,batchModify:ce,trash:he,untrash:fe},k={list:ae,get:oe,create:ie,update:ne,delete:re},w={list:Y,get:Z,create:Q,update:ee,delete:te,send:se},T={list:be,get:ye,modify:Ee,delete:Ge,trash:Ie,untrash:we};import{z as x}from"zod";import{z as r}from"zod";var Nt=r.object({name:r.string().optional(),value:r.string().optional()}),Ut=r.object({attachmentId:r.string().optional(),size:r.number().optional(),data:r.string().optional()}),Se=r.lazy(()=>r.object({partId:r.string().optional(),mimeType:r.string().optional(),filename:r.string().optional(),headers:r.array(Nt).optional(),body:Ut.optional(),parts:r.array(Se).optional()})),Le=r.object({id:r.string(),threadId:r.string().optional(),labelIds:r.array(r.string()).optional(),snippet:r.string().optional(),historyId:r.string().optional(),internalDate:r.string().optional(),sizeEstimate:r.number().optional(),payload:Se.optional(),raw:r.string().optional(),subject:r.string().optional(),body:r.string().optional(),from:r.string().optional(),to:r.string().optional(),createdAt:r.coerce.date().nullable().optional()}),ke=r.object({id:r.string(),name:r.string().optional(),messageListVisibility:r.enum(["show","hide"]).optional(),labelListVisibility:r.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),type:r.enum(["system","user"]).optional(),messagesTotal:r.number().optional(),messagesUnread:r.number().optional(),threadsTotal:r.number().optional(),threadsUnread:r.number().optional(),createdAt:r.coerce.date().nullable().optional()}),ve=r.object({id:r.string(),messageId:r.string().optional(),createdAt:r.coerce.date().nullable().optional()}),Pe=r.object({id:r.string(),snippet:r.string().optional(),historyId:r.string().optional(),createdAt:r.coerce.date().nullable().optional()});var $s=x.object({clientId:x.string(),clientSecret:x.string(),accessToken:x.string(),refreshToken:x.string()}),H={version:"1.0.0",entities:{messages:Le,labels:ke,drafts:ve,threads:Pe}};var Ce=2e4;async function De(e,t){let a=await e.keys.get_access_token();if(!a)return null;let o=await e.keys.get_integration_credentials();if(!o.topic_id)return null;let n={authorization:`Bearer ${a}`},i=await fetch(`${B}/users/me/watch`,{method:"POST",signal:AbortSignal.timeout(Ce),headers:{...n,"content-type":"application/json"},body:JSON.stringify({topicName:o.topic_id,labelIds:["INBOX"]})});if(!i.ok)throw new Error(`Gmail watch failed (${i.status}): ${await i.text()}`);let d=await fetch(`${B}/users/me/profile`,{headers:n,signal:AbortSignal.timeout(Ce)});if(!d.ok)throw new Error(`Gmail profile fetch failed (${d.status}): ${await d.text()}`);let{emailAddress:u}=await d.json();return u?{webhookLink:{linkType:"email_address",externalId:u},webhookSecret:o.pubsub_audience??void 0}:null}import{logEventFromContext as V}from"corsair/core";import{z as m}from"zod";var $t=m.object({data:m.string().optional(),attributes:m.record(m.string(),m.string()).optional(),messageId:m.string().optional(),publishTime:m.string().optional()}),Re=m.object({message:$t.optional(),subscription:m.string().optional(),event:m.unknown().optional()}),Wt=m.object({emailAddress:m.string().optional(),historyId:m.coerce.string().optional()}),_t=m.object({type:m.literal("messageReceived"),emailAddress:m.string(),historyId:m.string(),message:m.custom()}),Ft=m.object({type:m.literal("messageDeleted"),emailAddress:m.string(),historyId:m.string(),message:m.custom()}),qt=m.object({type:m.literal("messageLabelChanged"),emailAddress:m.string(),historyId:m.string(),message:m.custom(),labelsAdded:m.array(m.string()).optional(),labelsRemoved:m.array(m.string()).optional()}),xe=m.union([_t,Ft,qt]);function v(e){let t=Buffer.from(e,"base64").toString("utf-8");return Wt.parse(JSON.parse(t))}function z(e){return t=>{let a=t.body;if(!a.message?.data)return!1;try{let o=v(a.message.data);return!!o.historyId&&!!o.emailAddress}catch{return!1}}}var Ht=100,zt=10,Vt=10;function K(e,t){let a=e.options?.webhookEvents;return a?a.includes(t):!0}async function Ae(e,t,a){let o=[],n;do{let i=await y(`/users/${t}/history`,e,{method:"GET",query:{startHistoryId:a,maxResults:Ht,...n?{pageToken:n}:{}}});i.history&&o.push(...i.history),n=i.nextPageToken}while(n);return o}async function Kt(e,t,a){return y(`/users/${t}/messages/${a}`,e,{method:"GET",query:{format:"minimal"}})}function J(e,t){return e?.headers?e.headers.find(o=>o.name?.toLowerCase()===t.toLowerCase())?.value:void 0}function Jt(e){if(e.payload)return J(e.payload,"Subject")}function Xt(e){if(e.payload)return J(e.payload,"From")}function Yt(e){if(e.payload)return J(e.payload,"To")}function Oe(e){if(!e)return;let t,a;if(e.body?.data)try{let o=Buffer.from(e.body.data,"base64").toString("utf-8");e.mimeType==="text/plain"?t=o:e.mimeType==="text/html"&&(a=o)}catch{}if(e.parts&&e.parts.length>0)for(let o of e.parts){let n=Oe(o);n&&(o.mimeType==="text/plain"?t=n:o.mimeType==="text/html"&&!t&&(a=n))}return t||a}function Zt(e){if(e.payload)return Oe(e.payload)}function Qt(e){let t=[],a=[],o=[];if(!e)return{added:t,deleted:a,modified:o};for(let n of e){if(n.messagesAdded)for(let i of n.messagesAdded)i.message?.id&&t.push(i.message.id);if(n.messagesDeleted)for(let i of n.messagesDeleted)i.message?.id&&a.push(i.message.id);if(n.labelsAdded||n.labelsRemoved){if(n.labelsAdded)for(let i of n.labelsAdded)i.message?.id&&o.push(i.message.id);if(n.labelsRemoved)for(let i of n.labelsRemoved)i.message?.id&&o.push(i.message.id)}}return{added:[...new Set(t)],deleted:[...new Set(a)],modified:[...new Set(o)]}}async function je(e,t,a){let[o,n]=await Promise.all([y(`/users/${t}/messages/${a}`,e,{method:"GET",query:{format:"full"}}),y(`/users/${t}/messages/${a}`,e,{method:"GET",query:{format:"raw"}}).catch(()=>null)]);return{...o,raw:n?.raw}}async function es(e,t,a,o){return y(`/users/${t}/messages/${a}/attachments/${o}`,e,{method:"GET"})}async function Be(e,t,a){if(!a.payload)return a;let o=async i=>{if(!i)return i;if(i.body?.attachmentId)try{let d=await es(e,t,a.id,i.body.attachmentId);return{...i,body:{...i.body,data:d.data,size:d.size}}}catch(d){return console.warn(`Failed to fetch attachment ${i.body.attachmentId} for message ${a.id}:`,d),i}if(i.parts&&i.parts.length>0){let d=await Promise.all(i.parts.map(o));return{...i,parts:d.filter(u=>u!==void 0)}}return i},n=await o(a.payload);return{...a,payload:n}}function $(e){let t=Number(e);return t>1?String(t-1):e}function Ne(e){return typeof e!="object"||e===null?!1:"status"in e&&e.status===404?!0:"statusCode"in e&&e.statusCode===404}async function ts(e){try{return await e.keys?.get_last_history_id?.()||null}catch{return null}}async function W(e,t,a){let o=Number(t),n=a?Number(a):Number.NaN;if(!(Number.isFinite(o)&&Number.isFinite(n)&&o<=n))try{await e.keys?.set_last_history_id?.(t)}catch(i){console.warn("Failed to persist Gmail webhook history cursor:",i)}}function ss(e){let t=0;for(let a of e){let o=a.id?Number(a.id):Number.NaN;Number.isFinite(o)&&o>t&&(t=o)}return t>0?String(t):null}async function Ue(e,t){return!e.db?.messages||!t.id?"":(await e.db.messages.upsertByEntityId(t.id,{...t,id:t.id,subject:Jt(t),body:Zt(t),from:Xt(t),to:Yt(t),createdAt:new Date}))?.id??""}async function as(e,t,a,o){let n=await y(`/users/${a}/messages`,t,{method:"GET",query:{maxResults:zt}}),i=[],d=[];if(!n.messages?.length)return{added:i,modified:d};let u=Number(o);for(let l of n.messages)if(l.id)try{let f=await Kt(t,a,l.id);(f.historyId?Number(f.historyId):0)>=u-Vt&&(e.db?.messages&&await e.db.messages.existsByEntityId(l.id)?d.push(l.id):i.push(l.id))}catch{}return{added:i,modified:d}}async function os(e,t,a,o){let n=null,i="",d=0;for(let u of o)try{let l=await je(t,a,u),f=await Be(t,a,l);n||(n=f);try{let b=await Ue(e,f);!i&&b&&(i=b)}catch(b){throw console.error(`Failed to save message ${f.id} to database:`,b),b}}catch(l){d++,console.warn(`Failed to process message ${u}:`,l)}return{message:n,corsairEntityId:i,failedCount:d}}async function is(e,t,a,o){let n=null,i="",d=0;if(!e.db?.messages)return{message:null,corsairEntityId:i,failedCount:d};for(let u of o)try{let l=null;try{l=await y(`/users/${a}/messages/${u}`,t,{method:"GET",query:{format:"full"}})}catch(f){if(!Ne(f))throw f}if(!n&&l&&(n=l),!i){let f=await e.db.messages.findIdByEntityId(u);f&&(i=f)}await e.db.messages.deleteByEntityId(u)}catch(l){d++,console.warn(`Failed to delete message ${u} from database:`,l)}return{message:n,corsairEntityId:i,failedCount:d}}async function ns(e,t,a,o){let n=null,i="",d=0;if(!e.db?.messages)return{message:null,corsairEntityId:i,failedCount:d};for(let u of o)try{let l=await je(t,a,u),f=await Be(t,a,l);n||(n=f);try{let b=await Ue(e,f);!i&&b&&(i=b)}catch(b){throw console.error(`Failed to update message ${f.id} in database:`,b),b}}catch(l){d++,console.warn(`Failed to process message ${u}:`,l)}return{message:n,corsairEntityId:i,failedCount:d}}var $e={match:z("messageChanged"),handler:async(e,t)=>{let o=t.payload.message?.data;if(!o)return{success:!1,error:"No message data in notification"};let n;try{n=v(o)}catch{return{success:!1,error:"Invalid push notification format"}}if(!n.historyId||!n.emailAddress)return{success:!1,error:"Invalid push notification format"};let i=e.key,d=n.emailAddress,u=n.historyId;try{let l=await ts(e),f=l??$(u),b;try{b=await Ae(i,d,f)}catch(h){if(l&&Ne(h))b=await Ae(i,d,$(u));else throw h}let M=Qt(b),qe=new Set(M.added),He=new Set(M.deleted),P=M.added,_=M.deleted,C=M.modified.filter(h=>!qe.has(h)&&!He.has(h)),ze=P.length>0||_.length>0||C.length>0,X=!1;if(!ze&&!l){let h=await as(e,i,d,u);P=h.added,C=h.modified,X=!0}let A=P.length>0&&K(e,"messageReceived")?await os(e,i,d,P):null,O=_.length>0&&K(e,"messageDeleted")?await is(e,i,d,_):null,j=C.length>0&&K(e,"messageLabelChanged")?await ns(e,i,d,C):null;if((A?.failedCount??0)+(O?.failedCount??0)+(j?.failedCount??0)>0)l||await W(e,$(u),l);else{let h=ss(b);h?await W(e,h,l):X&&(P.length>0||C.length>0)?await W(e,u,l):l||await W(e,$(u),l)}if(A){let h={type:"messageReceived",emailAddress:d,historyId:u,message:A.message??{}};return await V(e,"gmail.webhook.messageReceived",{...h},"completed"),{success:!0,corsairEntityId:A.corsairEntityId,data:h}}if(O){let h={type:"messageDeleted",emailAddress:d,historyId:u,message:O.message??{}};return await V(e,"gmail.webhook.messageDeleted",{...h},"completed"),{success:!0,corsairEntityId:O.corsairEntityId,data:h}}if(j){let h={type:"messageLabelChanged",emailAddress:d,historyId:u,message:j.message??{}};return await V(e,"gmail.webhook.messageLabelChanged",{...h},"completed"),{success:!0,corsairEntityId:j.corsairEntityId,data:h}}return{success:!0,corsairEntityId:"",data:void 0}}catch(l){return console.error("Failed to process Gmail webhook:",l),{success:!1,error:`Failed to process message: ${l instanceof Error?l.message:"Unknown error"}`}}}};var We={messageChanged:$e};import{toExternalId as rs}from"corsair/core";async function _e(e){let t=e.access_token;if(!t)return null;let a=await fetch("https://gmail.googleapis.com/gmail/v1/users/me/profile",{headers:{Authorization:`Bearer ${t}`}});if(!a.ok)return null;let o=await a.json(),n=rs(o.emailAddress);return n?{linkType:"email_address",externalId:n}:null}import{asRecord as ds,decodePubSubData as ls,firstString as ms,readBodyRecord as ps}from"corsair/core";function Fe(e){let t=ps(e);if(!t)return null;let a=ds(ls(t)),o=ms([a?.emailAddress]);return o?{linkType:"email_address",externalId:o}:null}var cs={oauth_2:{integration:["topic_id","pubsub_audience"],account:["email_address","last_history_id"]}},hs={messages:{list:G.list,get:G.get,send:G.send,delete:G.delete,modify:G.modify,batchModify:G.batchModify,trash:G.trash,untrash:G.untrash},labels:{list:k.list,get:k.get,create:k.create,update:k.update,delete:k.delete},drafts:{list:w.list,get:w.get,create:w.create,update:w.update,delete:w.delete,send:w.send},threads:{list:T.list,get:T.get,modify:T.modify,delete:T.delete,trash:T.trash,untrash:T.untrash}},fs={"messages.list":{input:g.messagesList,output:c.messagesList},"messages.get":{input:g.messagesGet,output:c.messagesGet},"messages.send":{input:g.messagesSend,output:c.messagesSend},"messages.delete":{input:g.messagesDelete,output:c.messagesDelete},"messages.modify":{input:g.messagesModify,output:c.messagesModify},"messages.batchModify":{input:g.messagesBatchModify,output:c.messagesBatchModify},"messages.trash":{input:g.messagesTrash,output:c.messagesTrash},"messages.untrash":{input:g.messagesUntrash,output:c.messagesUntrash},"labels.list":{input:g.labelsList,output:c.labelsList},"labels.get":{input:g.labelsGet,output:c.labelsGet},"labels.create":{input:g.labelsCreate,output:c.labelsCreate},"labels.update":{input:g.labelsUpdate,output:c.labelsUpdate},"labels.delete":{input:g.labelsDelete,output:c.labelsDelete},"drafts.list":{input:g.draftsList,output:c.draftsList},"drafts.get":{input:g.draftsGet,output:c.draftsGet},"drafts.create":{input:g.draftsCreate,output:c.draftsCreate},"drafts.update":{input:g.draftsUpdate,output:c.draftsUpdate},"drafts.delete":{input:g.draftsDelete,output:c.draftsDelete},"drafts.send":{input:g.draftsSend,output:c.draftsSend},"threads.list":{input:g.threadsList,output:c.threadsList},"threads.get":{input:g.threadsGet,output:c.threadsGet},"threads.modify":{input:g.threadsModify,output:c.threadsModify},"threads.delete":{input:g.threadsDelete,output:c.threadsDelete},"threads.trash":{input:g.threadsTrash,output:c.threadsTrash},"threads.untrash":{input:g.threadsUntrash,output:c.threadsUntrash}},bs={messageChanged:We.messageChanged},ys={messageChanged:{description:"A Gmail message was received, deleted, or had its labels changed",payload:Re,response:xe}},Es="oauth_2",Gs={"messages.list":{riskLevel:"read",description:"List messages in a mailbox"},"messages.get":{riskLevel:"read",description:"Get a specific message"},"messages.send":{riskLevel:"write",description:"Send an email to one or more recipients"},"messages.delete":{riskLevel:"destructive",irreversible:!0,description:"Permanently delete a message [DESTRUCTIVE \xB7 IRREVERSIBLE]"},"messages.modify":{riskLevel:"write",description:"Add or remove labels from a message"},"messages.batchModify":{riskLevel:"write",description:"Add or remove labels from multiple messages in bulk"},"messages.trash":{riskLevel:"write",description:"Move a message to the trash"},"messages.untrash":{riskLevel:"write",description:"Restore a message from the trash"},"labels.list":{riskLevel:"read",description:"List all labels in the mailbox"},"labels.get":{riskLevel:"read",description:"Get a specific label"},"labels.create":{riskLevel:"write",description:"Create a new label"},"labels.update":{riskLevel:"write",description:"Update an existing label"},"labels.delete":{riskLevel:"destructive",description:"Delete a label [DESTRUCTIVE]"},"drafts.list":{riskLevel:"read",description:"List drafts in the mailbox"},"drafts.get":{riskLevel:"read",description:"Get a specific draft"},"drafts.create":{riskLevel:"write",description:"Create a new draft"},"drafts.update":{riskLevel:"write",description:"Update an existing draft"},"drafts.delete":{riskLevel:"destructive",description:"Delete a draft [DESTRUCTIVE]"},"drafts.send":{riskLevel:"write",description:"Send a draft as an email"},"threads.list":{riskLevel:"read",description:"List threads in the mailbox"},"threads.get":{riskLevel:"read",description:"Get a specific thread"},"threads.modify":{riskLevel:"write",description:"Add or remove labels from a thread"},"threads.delete":{riskLevel:"destructive",irreversible:!0,description:"Permanently delete a thread [DESTRUCTIVE \xB7 IRREVERSIBLE]"},"threads.trash":{riskLevel:"write",description:"Move a thread to the trash"},"threads.untrash":{riskLevel:"write",description:"Restore a thread from the trash"}};function ua(e={}){let t={...e,authType:e.authType??Es};return{id:"gmail",schema:H,options:t,authConfig:cs,oauthConfig:{providerName:"Google",authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:["https://www.googleapis.com/auth/gmail.modify","https://www.googleapis.com/auth/gmail.labels","https://www.googleapis.com/auth/gmail.send","https://www.googleapis.com/auth/gmail.compose"],authParams:{access_type:"offline",prompt:"consent"}},hooks:t.hooks,webhookHooks:t.webhookHooks,endpoints:hs,webhooks:bs,endpointMeta:Gs,endpointSchemas:fs,webhookSchemas:ys,keyBuilder:async a=>{let o=a.authType;if(t.key)return t.key;if(a.authType==="oauth_2")return gs(a,{plugin:"gmail",tokenUrl:"https://oauth2.googleapis.com/token"});throw new us("gmail","oauth_2")},pluginWebhookMatcher:a=>{let o=a.headers;if(!(o.from==="noreply@google.com"||typeof o["user-agent"]=="string"&&o["user-agent"].includes("APIs-Google")))return!1;let i=a.body;if(!i?.message?.data)return!1;try{let d=v(i.message.data);return!!d.emailAddress&&!!d.historyId}catch{return!1}},pluginTenantWebhookMatcher:Fe,oauthWebhookTenantLinkResolver:_e,subscribe:De}}export{H as GmailSchema,z as createGmailWebhookMatcher,v as decodePubSubMessage,ua as gmail,cs as gmailAuthConfig,fs as gmailEndpointSchemas,hs as gmailEndpointsNested,bs as gmailWebhooksNested};
1
+ import{AuthMissingError as us,getOAuthAccessToken as gs}from"corsair/core";import{logEventFromContext as S}from"corsair/core";import{request as Ve}from"corsair/http";var B="https://gmail.googleapis.com/gmail/v1";async function y(e,t,a={}){let{method:o="GET",body:n,query:i}=a;return await Ve({BASE:B,VERSION:"1.0.0",WITH_CREDENTIALS:!1,CREDENTIALS:"omit",TOKEN:t,HEADERS:{"Content-Type":"application/json"}},{method:o,url:e,body:o==="POST"||o==="PUT"||o==="PATCH"?n:void 0,mediaType:"application/json",query:o==="GET"?i:void 0})}function Ke(e){return e instanceof Error&&"status"in e&&e.status===401}async function p(e,t,a={}){try{return await y(e,t.key,a)}catch(o){if(Ke(o)&&t._refreshAuth){let n=await t._refreshAuth();return await y(e,n,a)}throw o}}var Y=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts`,e,{method:"GET",query:{maxResults:t.maxResults,pageToken:t.pageToken,q:t.q}});if(a.drafts&&e.db.drafts)try{for(let o of a.drafts)o.id&&await e.db.drafts.upsertByEntityId(o.id,{...o,id:o.id,messageId:o.message?.id,createdAt:new Date})}catch(o){console.warn("Failed to save drafts to database:",o)}return await S(e,"gmail.drafts.list",{...t},"completed"),a},Z=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts/${t.id}`,e,{method:"GET",query:{format:t.format}});if(a.id&&e.db.drafts)try{await e.db.drafts.upsertByEntityId(a.id,{...a,id:a.id,messageId:a.message?.id,createdAt:new Date})}catch(o){console.warn("Failed to save draft to database:",o)}return await S(e,"gmail.drafts.get",{...t},"completed"),a},Q=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts`,e,{method:"POST",body:t.draft});return a.id&&await e.endpoints.drafts.get({id:a.id,userId:t.userId}),await S(e,"gmail.drafts.create",{...t},"completed"),a},ee=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts/${t.id}`,e,{method:"PUT",body:t.draft});return a.id&&await e.endpoints.drafts.get({id:a.id,userId:t.userId}),await S(e,"gmail.drafts.update",{...t},"completed"),a},te=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/drafts/${t.id}`,e,{method:"DELETE"}),e.db.drafts)try{await e.db.drafts.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete draft from database:",a)}await S(e,"gmail.drafts.delete",{...t},"completed")},se=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/drafts/send`,e,{method:"POST",body:{id:t.id,message:t.message}});return await S(e,"gmail.drafts.send",{...t},"completed"),a};import{logEventFromContext as D}from"corsair/core";var ae=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels`,e,{method:"GET"});if(a.labels&&e.db.labels)try{for(let o of a.labels)o.id&&await e.db.labels.upsertByEntityId(o.id,{...o,id:o.id,createdAt:new Date})}catch(o){console.warn("Failed to save labels to database:",o)}return await D(e,"gmail.labels.list",{...t},"completed"),a},oe=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels/${t.id}`,e,{method:"GET"});if(a.id&&e.db.labels)try{await e.db.labels.upsertByEntityId(a.id,{id:a.id,name:a.name,messageListVisibility:a.messageListVisibility,labelListVisibility:a.labelListVisibility,type:a.type,messagesTotal:a.messagesTotal,messagesUnread:a.messagesUnread,threadsTotal:a.threadsTotal,threadsUnread:a.threadsUnread,createdAt:new Date})}catch(o){console.warn("Failed to save label to database:",o)}return await D(e,"gmail.labels.get",{...t},"completed"),a},ie=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels`,e,{method:"POST",body:t.label});return a.id&&await e.endpoints.labels.get({id:a.id,userId:t.userId}),await D(e,"gmail.labels.create",{...t},"completed"),a},ne=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/labels/${t.id}`,e,{method:"PUT",body:t.label});return a.id&&await e.endpoints.labels.get({id:a.id,userId:t.userId}),await D(e,"gmail.labels.update",{...t},"completed"),a},re=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/labels/${t.id}`,e,{method:"DELETE"}),e.db.labels)try{await e.db.labels.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete label from database:",a)}await D(e,"gmail.labels.delete",{...t},"completed")};import{logEventFromContext as I}from"corsair/core";function F(e,t){return e?.headers?e.headers.find(o=>o.name?.toLowerCase()===t.toLowerCase())?.value:void 0}function Ye(e){if(e.payload)return F(e.payload,"Subject")}function Ze(e){if(e.payload)return F(e.payload,"From")}function Qe(e){if(e.payload)return F(e.payload,"To")}function de(e){if(!e)return;let t,a;if(e.body?.data)try{let o=Buffer.from(e.body.data,"base64").toString("utf-8");e.mimeType==="text/plain"?t=o:e.mimeType==="text/html"&&(a=o)}catch{}if(e.parts&&e.parts.length>0)for(let o of e.parts){let n=de(o);n&&(o.mimeType==="text/plain"?t=n:o.mimeType==="text/html"&&!t&&(a=n))}return t||a}function et(e){if(e.payload)return de(e.payload)}var le=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages`,e,{method:"GET",query:{q:t.q,maxResults:t.maxResults,pageToken:t.pageToken,labelIds:t.labelIds?.join(","),includeSpamTrash:t.includeSpamTrash}});if(a.messages&&e.db.messages)try{for(let o of a.messages)o.id&&await e.db.messages.upsertByEntityId(o.id,{...o,id:o.id,createdAt:new Date})}catch(o){console.warn("Failed to save messages to database:",o)}return await I(e,"gmail.messages.list",{...t},"completed"),a},me=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/${t.id}`,e,{method:"GET",query:{format:t.format,metadataHeaders:t.metadataHeaders?.join(",")}});if(a.id&&e.db.messages)try{let o=Ye(a),n=et(a),i=Ze(a),d=Qe(a);await e.db.messages.upsertByEntityId(a.id,{...a,subject:o,body:n,from:i,to:d,id:a.id,createdAt:new Date})}catch(o){console.warn("Failed to save message to database:",o)}return await I(e,"gmail.messages.get",{...t},"completed"),a},pe=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/send`,e,{method:"POST",body:{raw:t.raw,threadId:t.threadId}});return a.id&&await e.endpoints.messages.get({id:a.id,userId:t.userId}),await I(e,"gmail.messages.send",{...t},"completed"),a},ue=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/messages/${t.id}`,e,{method:"DELETE"}),e.db.messages)try{await e.db.messages.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete message from database:",a)}await I(e,"gmail.messages.delete",{...t},"completed")},ge=async(e,t)=>{let a={};t.addLabelIds&&t.addLabelIds.length>0&&(a.addLabelIds=t.addLabelIds),t.removeLabelIds&&t.removeLabelIds.length>0&&(a.removeLabelIds=t.removeLabelIds);let o=await p(`/users/${t.userId||"me"}/messages/${t.id}/modify`,e,{method:"POST",body:a});return o.id&&await e.endpoints.messages.get({id:o.id,userId:t.userId}),await I(e,"gmail.messages.modify",{...t},"completed"),o},ce=async(e,t)=>{let a={ids:t.ids};t.addLabelIds&&t.addLabelIds.length>0&&(a.addLabelIds=t.addLabelIds),t.removeLabelIds&&t.removeLabelIds.length>0&&(a.removeLabelIds=t.removeLabelIds),await p(`/users/${t.userId||"me"}/messages/batchModify`,e,{method:"POST",body:a}),await I(e,"gmail.messages.batchModify",{...t},"completed")},he=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/${t.id}/trash`,e,{method:"POST"});return a.id&&await e.endpoints.messages.get({id:a.id,userId:t.userId}),await I(e,"gmail.messages.trash",{...t},"completed"),a},fe=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/messages/${t.id}/untrash`,e,{method:"POST"});return a.id&&await e.endpoints.messages.get({id:a.id,userId:t.userId}),await I(e,"gmail.messages.untrash",{...t},"completed"),a};import{logEventFromContext as L}from"corsair/core";var be=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads`,e,{method:"GET",query:{q:t.q,maxResults:t.maxResults,pageToken:t.pageToken,labelIds:t.labelIds?.join(","),includeSpamTrash:t.includeSpamTrash}});if(a.threads&&e.db.threads)try{for(let o of a.threads)o.id&&await e.db.threads.upsertByEntityId(o.id,{...o,id:o.id,createdAt:new Date})}catch(o){console.warn("Failed to save threads to database:",o)}return await L(e,"gmail.threads.list",{...t},"completed"),a},ye=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads/${t.id}`,e,{method:"GET",query:{format:t.format,metadataHeaders:t.metadataHeaders?.join(",")}});if(a.id&&e.db.threads)try{await e.db.threads.upsertByEntityId(a.id,{...a,id:a.id,createdAt:new Date})}catch(o){console.warn("Failed to save thread to database:",o)}return await L(e,"gmail.threads.get",{...t},"completed"),a},Ge=async(e,t)=>{let a={};t.addLabelIds&&t.addLabelIds.length>0&&(a.addLabelIds=t.addLabelIds),t.removeLabelIds&&t.removeLabelIds.length>0&&(a.removeLabelIds=t.removeLabelIds);let o=await p(`/users/${t.userId||"me"}/threads/${t.id}/modify`,e,{method:"POST",body:a});return o.id&&await e.endpoints.threads.get({id:o.id,userId:t.userId}),await L(e,"gmail.threads.modify",{...t},"completed"),o},Ee=async(e,t)=>{if(await p(`/users/${t.userId||"me"}/threads/${t.id}`,e,{method:"DELETE"}),e.db.threads)try{await e.db.threads.deleteByEntityId(t.id)}catch(a){console.warn("Failed to delete thread from database:",a)}await L(e,"gmail.threads.delete",{...t},"completed")},Ie=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads/${t.id}/trash`,e,{method:"POST"});return a.id&&await e.endpoints.threads.get({id:a.id,userId:t.userId}),await L(e,"gmail.threads.trash",{...t},"completed"),a},we=async(e,t)=>{let a=await p(`/users/${t.userId||"me"}/threads/${t.id}/untrash`,e,{method:"POST"});return a.id&&await e.endpoints.threads.get({id:a.id,userId:t.userId}),await L(e,"gmail.threads.untrash",{...t},"completed"),a};import{z as s}from"zod";var Te="Base64url-encoded RFC 2822 email \u2014 do NOT pass plain email text. Build the MIME message (From, To, Subject, Content-Type headers, blank line, body; lines separated by \\r\\n), then base64url-encode: standard base64, replace + with -, / with _, remove trailing =.",q=s.object({raw:s.string().optional().describe(Te),threadId:s.string().optional()}),at=s.object({userId:s.string().optional(),q:s.string().optional(),maxResults:s.number().optional(),pageToken:s.string().optional(),labelIds:s.array(s.string()).optional(),includeSpamTrash:s.boolean().optional()}),ot=s.object({userId:s.string().optional(),id:s.string(),format:s.enum(["minimal","full","raw","metadata"]).optional(),metadataHeaders:s.array(s.string()).optional()}),it=s.object({userId:s.string().optional(),raw:s.string().describe(Te),threadId:s.string().optional()}),nt=s.object({userId:s.string().optional(),id:s.string()}),rt=s.object({userId:s.string().optional(),id:s.string(),addLabelIds:s.array(s.string()).optional(),removeLabelIds:s.array(s.string()).optional()}),dt=s.object({userId:s.string().optional(),ids:s.array(s.string()).optional(),addLabelIds:s.array(s.string()).optional(),removeLabelIds:s.array(s.string()).optional()}),lt=s.object({userId:s.string().optional(),id:s.string()}),mt=s.object({userId:s.string().optional(),id:s.string()}),pt=s.object({userId:s.string().optional()}),ut=s.object({userId:s.string().optional(),id:s.string()}),gt=s.object({userId:s.string().optional(),label:s.object({name:s.string().optional(),messageListVisibility:s.enum(["show","hide"]).optional(),labelListVisibility:s.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),color:s.object({textColor:s.string().optional(),backgroundColor:s.string().optional()}).optional()})}),ct=s.object({userId:s.string().optional(),id:s.string(),label:s.object({name:s.string().optional(),messageListVisibility:s.enum(["show","hide"]).optional(),labelListVisibility:s.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),color:s.object({textColor:s.string().optional(),backgroundColor:s.string().optional()}).optional()})}),ht=s.object({userId:s.string().optional(),id:s.string()}),ft=s.object({userId:s.string().optional(),maxResults:s.number().optional(),pageToken:s.string().optional(),q:s.string().optional()}),bt=s.object({userId:s.string().optional(),id:s.string(),format:s.enum(["minimal","full","raw","metadata"]).optional()}),yt=s.object({userId:s.string().optional(),draft:s.object({message:q.optional()}).optional().describe("Draft payload. message.raw must be a base64url-encoded RFC 2822 email, not plain text.")}),Gt=s.object({userId:s.string().optional(),id:s.string(),draft:s.object({message:q.optional()}).optional().describe("Updated draft payload. message.raw must be a base64url-encoded RFC 2822 email, not plain text.")}),Et=s.object({userId:s.string().optional(),id:s.string()}),It=s.object({userId:s.string().optional(),id:s.string().optional(),message:q.optional().describe("Optional message body when sending without a draft id. raw must be base64url-encoded RFC 2822, not plain text.")}),wt=s.object({userId:s.string().optional(),q:s.string().optional(),maxResults:s.number().optional(),pageToken:s.string().optional(),labelIds:s.array(s.string()).optional(),includeSpamTrash:s.boolean().optional()}),Tt=s.object({userId:s.string().optional(),id:s.string(),format:s.enum(["minimal","full","metadata"]).optional(),metadataHeaders:s.array(s.string()).optional()}),Mt=s.object({userId:s.string().optional(),id:s.string(),addLabelIds:s.array(s.string()).optional(),removeLabelIds:s.array(s.string()).optional()}),St=s.object({userId:s.string().optional(),id:s.string()}),Lt=s.object({userId:s.string().optional(),id:s.string()}),kt=s.object({userId:s.string().optional(),id:s.string()}),vt=s.object({userId:s.string().optional()}),g={messagesList:at,messagesGet:ot,messagesSend:it,messagesDelete:nt,messagesModify:rt,messagesBatchModify:dt,messagesTrash:lt,messagesUntrash:mt,labelsList:pt,labelsGet:ut,labelsCreate:gt,labelsUpdate:ct,labelsDelete:ht,draftsList:ft,draftsGet:bt,draftsCreate:yt,draftsUpdate:Gt,draftsDelete:Et,draftsSend:It,threadsList:wt,threadsGet:Tt,threadsModify:Mt,threadsDelete:St,threadsTrash:Lt,threadsUntrash:kt,usersGetProfile:vt},Pt=s.object({name:s.string().optional(),value:s.string().optional()}),Ct=s.object({attachmentId:s.string().optional(),size:s.number().optional(),data:s.string().optional()}),Dt=s.object({partId:s.string().optional(),mimeType:s.string().optional(),filename:s.string().optional(),headers:s.array(Pt).optional(),body:Ct.optional()}),Me=Dt.extend({parts:s.lazy(()=>s.array(Me).optional())}),G=s.object({id:s.string().optional(),threadId:s.string().optional(),labelIds:s.array(s.string()).optional(),snippet:s.string().optional(),historyId:s.string().optional(),internalDate:s.union([s.string(),s.number(),s.date()]).transform(e=>{if(e instanceof Date)return e;if(typeof e=="number")return new Date(e);if(typeof e=="string"){let t=Number(e);return isNaN(t)?null:new Date(t)}return null}).nullable().optional(),sizeEstimate:s.number().optional(),payload:Me.optional(),raw:s.string().optional().describe("Full RFC 2822 message in base64url encoding (when format=raw). Not plain text \u2014 decode base64url before reading headers/body.")}),Rt=s.object({messages:s.array(G).optional(),nextPageToken:s.string().optional(),resultSizeEstimate:s.number().optional()}),xt=s.object({textColor:s.string().optional(),backgroundColor:s.string().optional()}),N=s.object({id:s.string().optional(),name:s.string().optional(),messageListVisibility:s.enum(["show","hide"]).optional(),labelListVisibility:s.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),type:s.enum(["system","user"]).optional(),messagesTotal:s.number().optional(),messagesUnread:s.number().optional(),threadsTotal:s.number().optional(),threadsUnread:s.number().optional(),color:xt.optional()}),At=s.object({labels:s.array(N).optional()}),U=s.object({id:s.string().optional(),message:G.optional()}),Ot=s.object({drafts:s.array(U).optional(),nextPageToken:s.string().optional(),resultSizeEstimate:s.number().optional()}),R=s.object({id:s.string().optional(),snippet:s.string().optional(),historyId:s.string().optional(),messages:s.array(G).optional()}),jt=s.object({threads:s.array(R).optional(),nextPageToken:s.string().optional(),resultSizeEstimate:s.number().optional()}),Bt=s.object({emailAddress:s.string().optional(),messagesTotal:s.number().optional(),threadsTotal:s.number().optional(),historyId:s.string().optional()}),c={messagesList:Rt,messagesGet:G,messagesSend:G,messagesDelete:s.void(),messagesModify:G,messagesBatchModify:s.void(),messagesTrash:G,messagesUntrash:G,labelsList:At,labelsGet:N,labelsCreate:N,labelsUpdate:N,labelsDelete:s.void(),draftsList:Ot,draftsGet:U,draftsCreate:U,draftsUpdate:U,draftsDelete:s.void(),draftsSend:G,threadsList:jt,threadsGet:R,threadsModify:R,threadsDelete:s.void(),threadsTrash:R,threadsUntrash:R,usersGetProfile:Bt};var E={list:le,get:me,send:pe,delete:ue,modify:ge,batchModify:ce,trash:he,untrash:fe},k={list:ae,get:oe,create:ie,update:ne,delete:re},w={list:Y,get:Z,create:Q,update:ee,delete:te,send:se},T={list:be,get:ye,modify:Ge,delete:Ee,trash:Ie,untrash:we};import{z as x}from"zod";import{z as r}from"zod";var Nt=r.object({name:r.string().optional(),value:r.string().optional()}),Ut=r.object({attachmentId:r.string().optional(),size:r.number().optional(),data:r.string().optional()}),Se=r.lazy(()=>r.object({partId:r.string().optional(),mimeType:r.string().optional(),filename:r.string().optional(),headers:r.array(Nt).optional(),body:Ut.optional(),parts:r.array(Se).optional()})),Le=r.object({id:r.string(),threadId:r.string().optional(),labelIds:r.array(r.string()).optional(),snippet:r.string().optional(),historyId:r.string().optional(),internalDate:r.string().optional(),sizeEstimate:r.number().optional(),payload:Se.optional(),raw:r.string().optional(),subject:r.string().optional(),body:r.string().optional(),from:r.string().optional(),to:r.string().optional(),createdAt:r.coerce.date().nullable().optional()}),ke=r.object({id:r.string(),name:r.string().optional(),messageListVisibility:r.enum(["show","hide"]).optional(),labelListVisibility:r.enum(["labelShow","labelShowIfUnread","labelHide"]).optional(),type:r.enum(["system","user"]).optional(),messagesTotal:r.number().optional(),messagesUnread:r.number().optional(),threadsTotal:r.number().optional(),threadsUnread:r.number().optional(),createdAt:r.coerce.date().nullable().optional()}),ve=r.object({id:r.string(),messageId:r.string().optional(),createdAt:r.coerce.date().nullable().optional()}),Pe=r.object({id:r.string(),snippet:r.string().optional(),historyId:r.string().optional(),createdAt:r.coerce.date().nullable().optional()});var $s=x.object({clientId:x.string(),clientSecret:x.string(),accessToken:x.string(),refreshToken:x.string()}),H={version:"1.0.0",entities:{messages:Le,labels:ke,drafts:ve,threads:Pe}};var Ce=2e4;async function De(e,t){let a=await e.keys.get_access_token();if(!a)return null;let o=await e.keys.get_integration_credentials();if(!o.topic_id)return null;let n={authorization:`Bearer ${a}`},i=await fetch(`${B}/users/me/watch`,{method:"POST",signal:AbortSignal.timeout(Ce),headers:{...n,"content-type":"application/json"},body:JSON.stringify({topicName:o.topic_id,labelIds:["INBOX"]})});if(!i.ok)throw new Error(`Gmail watch failed (${i.status}): ${await i.text()}`);let d=await fetch(`${B}/users/me/profile`,{headers:n,signal:AbortSignal.timeout(Ce)});if(!d.ok)throw new Error(`Gmail profile fetch failed (${d.status}): ${await d.text()}`);let{emailAddress:u}=await d.json();return u?{webhookLink:{linkType:"email_address",externalId:u},webhookSecret:o.pubsub_audience??void 0}:null}import{logEventFromContext as V}from"corsair/core";import{z as m}from"zod";var $t=m.object({data:m.string().optional(),attributes:m.record(m.string(),m.string()).optional(),messageId:m.string().optional(),publishTime:m.string().optional()}),Re=m.object({message:$t.optional(),subscription:m.string().optional(),event:m.unknown().optional()}),Wt=m.object({emailAddress:m.string().optional(),historyId:m.coerce.string().optional()}),_t=m.object({type:m.literal("messageReceived"),emailAddress:m.string(),historyId:m.string(),message:m.custom()}),Ft=m.object({type:m.literal("messageDeleted"),emailAddress:m.string(),historyId:m.string(),message:m.custom()}),qt=m.object({type:m.literal("messageLabelChanged"),emailAddress:m.string(),historyId:m.string(),message:m.custom(),labelsAdded:m.array(m.string()).optional(),labelsRemoved:m.array(m.string()).optional()}),xe=m.union([_t,Ft,qt]);function v(e){let t=Buffer.from(e,"base64").toString("utf-8");return Wt.parse(JSON.parse(t))}function z(e){return t=>{let a=t.body;if(!a.message?.data)return!1;try{let o=v(a.message.data);return!!o.historyId&&!!o.emailAddress}catch{return!1}}}var Ht=100,zt=10,Vt=10;function K(e,t){let a=e.options?.webhookEvents;return a?a.includes(t):!0}async function Ae(e,t,a){let o=[],n;do{let i=await y(`/users/${t}/history`,e,{method:"GET",query:{startHistoryId:a,maxResults:Ht,...n?{pageToken:n}:{}}});i.history&&o.push(...i.history),n=i.nextPageToken}while(n);return o}async function Kt(e,t,a){return y(`/users/${t}/messages/${a}`,e,{method:"GET",query:{format:"minimal"}})}function J(e,t){return e?.headers?e.headers.find(o=>o.name?.toLowerCase()===t.toLowerCase())?.value:void 0}function Jt(e){if(e.payload)return J(e.payload,"Subject")}function Xt(e){if(e.payload)return J(e.payload,"From")}function Yt(e){if(e.payload)return J(e.payload,"To")}function Oe(e){if(!e)return;let t,a;if(e.body?.data)try{let o=Buffer.from(e.body.data,"base64").toString("utf-8");e.mimeType==="text/plain"?t=o:e.mimeType==="text/html"&&(a=o)}catch{}if(e.parts&&e.parts.length>0)for(let o of e.parts){let n=Oe(o);n&&(o.mimeType==="text/plain"?t=n:o.mimeType==="text/html"&&!t&&(a=n))}return t||a}function Zt(e){if(e.payload)return Oe(e.payload)}function Qt(e){let t=[],a=[],o=[];if(!e)return{added:t,deleted:a,modified:o};for(let n of e){if(n.messagesAdded)for(let i of n.messagesAdded)i.message?.id&&t.push(i.message.id);if(n.messagesDeleted)for(let i of n.messagesDeleted)i.message?.id&&a.push(i.message.id);if(n.labelsAdded||n.labelsRemoved){if(n.labelsAdded)for(let i of n.labelsAdded)i.message?.id&&o.push(i.message.id);if(n.labelsRemoved)for(let i of n.labelsRemoved)i.message?.id&&o.push(i.message.id)}}return{added:[...new Set(t)],deleted:[...new Set(a)],modified:[...new Set(o)]}}async function je(e,t,a){let[o,n]=await Promise.all([y(`/users/${t}/messages/${a}`,e,{method:"GET",query:{format:"full"}}),y(`/users/${t}/messages/${a}`,e,{method:"GET",query:{format:"raw"}}).catch(()=>null)]);return{...o,raw:n?.raw}}async function es(e,t,a,o){return y(`/users/${t}/messages/${a}/attachments/${o}`,e,{method:"GET"})}async function Be(e,t,a){if(!a.payload)return a;let o=async i=>{if(!i)return i;if(i.body?.attachmentId)try{let d=await es(e,t,a.id,i.body.attachmentId);return{...i,body:{...i.body,data:d.data,size:d.size}}}catch(d){return console.warn(`Failed to fetch attachment ${i.body.attachmentId} for message ${a.id}:`,d),i}if(i.parts&&i.parts.length>0){let d=await Promise.all(i.parts.map(o));return{...i,parts:d.filter(u=>u!==void 0)}}return i},n=await o(a.payload);return{...a,payload:n}}function $(e){let t=Number(e);return t>1?String(t-1):e}function Ne(e){return typeof e!="object"||e===null?!1:"status"in e&&e.status===404?!0:"statusCode"in e&&e.statusCode===404}async function ts(e){try{return await e.keys?.get_last_history_id?.()||null}catch{return null}}async function W(e,t,a){let o=Number(t),n=a?Number(a):Number.NaN;if(!(Number.isFinite(o)&&Number.isFinite(n)&&o<=n))try{await e.keys?.set_last_history_id?.(t)}catch(i){console.warn("Failed to persist Gmail webhook history cursor:",i)}}function ss(e){let t=0;for(let a of e){let o=a.id?Number(a.id):Number.NaN;Number.isFinite(o)&&o>t&&(t=o)}return t>0?String(t):null}async function Ue(e,t){return!e.db?.messages||!t.id?"":(await e.db.messages.upsertByEntityId(t.id,{...t,id:t.id,subject:Jt(t),body:Zt(t),from:Xt(t),to:Yt(t),createdAt:new Date}))?.id??""}async function as(e,t,a,o){let n=await y(`/users/${a}/messages`,t,{method:"GET",query:{maxResults:zt}}),i=[],d=[];if(!n.messages?.length)return{added:i,modified:d};let u=Number(o);for(let l of n.messages)if(l.id)try{let f=await Kt(t,a,l.id);(f.historyId?Number(f.historyId):0)>=u-Vt&&(e.db?.messages&&await e.db.messages.existsByEntityId(l.id)?d.push(l.id):i.push(l.id))}catch{}return{added:i,modified:d}}async function os(e,t,a,o){let n=null,i="",d=0;for(let u of o)try{let l=await je(t,a,u),f=await Be(t,a,l);n||(n=f);try{let b=await Ue(e,f);!i&&b&&(i=b)}catch(b){throw console.error(`Failed to save message ${f.id} to database:`,b),b}}catch(l){d++,console.warn(`Failed to process message ${u}:`,l)}return{message:n,corsairEntityId:i,failedCount:d}}async function is(e,t,a,o){let n=null,i="",d=0;if(!e.db?.messages)return{message:null,corsairEntityId:i,failedCount:d};for(let u of o)try{let l=null;try{l=await y(`/users/${a}/messages/${u}`,t,{method:"GET",query:{format:"full"}})}catch(f){if(!Ne(f))throw f}if(!n&&l&&(n=l),!i){let f=await e.db.messages.findIdByEntityId(u);f&&(i=f)}await e.db.messages.deleteByEntityId(u)}catch(l){d++,console.warn(`Failed to delete message ${u} from database:`,l)}return{message:n,corsairEntityId:i,failedCount:d}}async function ns(e,t,a,o){let n=null,i="",d=0;if(!e.db?.messages)return{message:null,corsairEntityId:i,failedCount:d};for(let u of o)try{let l=await je(t,a,u),f=await Be(t,a,l);n||(n=f);try{let b=await Ue(e,f);!i&&b&&(i=b)}catch(b){throw console.error(`Failed to update message ${f.id} in database:`,b),b}}catch(l){d++,console.warn(`Failed to process message ${u}:`,l)}return{message:n,corsairEntityId:i,failedCount:d}}var $e={match:z("messageChanged"),handler:async(e,t)=>{let o=t.payload.message?.data;if(!o)return{success:!1,error:"No message data in notification"};let n;try{n=v(o)}catch{return{success:!1,error:"Invalid push notification format"}}if(!n.historyId||!n.emailAddress)return{success:!1,error:"Invalid push notification format"};let i=e.key,d=n.emailAddress,u=n.historyId;try{let l=await ts(e),f=l??$(u),b;try{b=await Ae(i,d,f)}catch(h){if(l&&Ne(h))b=await Ae(i,d,$(u));else throw h}let M=Qt(b),qe=new Set(M.added),He=new Set(M.deleted),P=M.added,_=M.deleted,C=M.modified.filter(h=>!qe.has(h)&&!He.has(h)),ze=P.length>0||_.length>0||C.length>0,X=!1;if(!ze&&!l){let h=await as(e,i,d,u);P=h.added,C=h.modified,X=!0}let A=P.length>0&&K(e,"messageReceived")?await os(e,i,d,P):null,O=_.length>0&&K(e,"messageDeleted")?await is(e,i,d,_):null,j=C.length>0&&K(e,"messageLabelChanged")?await ns(e,i,d,C):null;if((A?.failedCount??0)+(O?.failedCount??0)+(j?.failedCount??0)>0)l||await W(e,$(u),l);else{let h=ss(b);h?await W(e,h,l):X&&(P.length>0||C.length>0)?await W(e,u,l):l||await W(e,$(u),l)}if(A){let h={type:"messageReceived",emailAddress:d,historyId:u,message:A.message??{}};return await V(e,"gmail.webhook.messageReceived",{...h},"completed"),{success:!0,corsairEntityId:A.corsairEntityId,data:h}}if(O){let h={type:"messageDeleted",emailAddress:d,historyId:u,message:O.message??{}};return await V(e,"gmail.webhook.messageDeleted",{...h},"completed"),{success:!0,corsairEntityId:O.corsairEntityId,data:h}}if(j){let h={type:"messageLabelChanged",emailAddress:d,historyId:u,message:j.message??{}};return await V(e,"gmail.webhook.messageLabelChanged",{...h},"completed"),{success:!0,corsairEntityId:j.corsairEntityId,data:h}}return{success:!0,corsairEntityId:"",data:void 0}}catch(l){return console.error("Failed to process Gmail webhook:",l),{success:!1,error:`Failed to process message: ${l instanceof Error?l.message:"Unknown error"}`}}}};var We={messageChanged:$e};import{toExternalId as rs}from"corsair/core";async function _e(e){let t=e.access_token;if(!t)return null;let a=await fetch("https://gmail.googleapis.com/gmail/v1/users/me/profile",{headers:{Authorization:`Bearer ${t}`}});if(!a.ok)return null;let o=await a.json(),n=rs(o.emailAddress);return n?{linkType:"email_address",externalId:n}:null}import{asRecord as ds,decodePubSubData as ls,firstString as ms,readBodyRecord as ps}from"corsair/core";function Fe(e){let t=ps(e);if(!t)return null;let a=ds(ls(t)),o=ms([a?.emailAddress]);return o?{linkType:"email_address",externalId:o}:null}var cs={oauth_2:{integration:["topic_id","pubsub_audience"],account:["email_address","last_history_id"]}},hs={messages:{list:E.list,get:E.get,send:E.send,delete:E.delete,modify:E.modify,batchModify:E.batchModify,trash:E.trash,untrash:E.untrash},labels:{list:k.list,get:k.get,create:k.create,update:k.update,delete:k.delete},drafts:{list:w.list,get:w.get,create:w.create,update:w.update,delete:w.delete,send:w.send},threads:{list:T.list,get:T.get,modify:T.modify,delete:T.delete,trash:T.trash,untrash:T.untrash}},fs={"messages.list":{input:g.messagesList,output:c.messagesList},"messages.get":{input:g.messagesGet,output:c.messagesGet},"messages.send":{input:g.messagesSend,output:c.messagesSend},"messages.delete":{input:g.messagesDelete,output:c.messagesDelete},"messages.modify":{input:g.messagesModify,output:c.messagesModify},"messages.batchModify":{input:g.messagesBatchModify,output:c.messagesBatchModify},"messages.trash":{input:g.messagesTrash,output:c.messagesTrash},"messages.untrash":{input:g.messagesUntrash,output:c.messagesUntrash},"labels.list":{input:g.labelsList,output:c.labelsList},"labels.get":{input:g.labelsGet,output:c.labelsGet},"labels.create":{input:g.labelsCreate,output:c.labelsCreate},"labels.update":{input:g.labelsUpdate,output:c.labelsUpdate},"labels.delete":{input:g.labelsDelete,output:c.labelsDelete},"drafts.list":{input:g.draftsList,output:c.draftsList},"drafts.get":{input:g.draftsGet,output:c.draftsGet},"drafts.create":{input:g.draftsCreate,output:c.draftsCreate},"drafts.update":{input:g.draftsUpdate,output:c.draftsUpdate},"drafts.delete":{input:g.draftsDelete,output:c.draftsDelete},"drafts.send":{input:g.draftsSend,output:c.draftsSend},"threads.list":{input:g.threadsList,output:c.threadsList},"threads.get":{input:g.threadsGet,output:c.threadsGet},"threads.modify":{input:g.threadsModify,output:c.threadsModify},"threads.delete":{input:g.threadsDelete,output:c.threadsDelete},"threads.trash":{input:g.threadsTrash,output:c.threadsTrash},"threads.untrash":{input:g.threadsUntrash,output:c.threadsUntrash}},bs={messageChanged:We.messageChanged},ys={messageChanged:{description:"A Gmail message was received, deleted, or had its labels changed",payload:Re,response:xe}},Gs="oauth_2",Es={"messages.list":{riskLevel:"read",description:"List messages in a mailbox"},"messages.get":{riskLevel:"read",description:"Get a specific message"},"messages.send":{riskLevel:"write",description:"Send an email to one or more recipients"},"messages.delete":{riskLevel:"destructive",irreversible:!0,description:"Permanently delete a message [DESTRUCTIVE \xB7 IRREVERSIBLE]"},"messages.modify":{riskLevel:"write",description:"Add or remove labels from a message"},"messages.batchModify":{riskLevel:"write",description:"Add or remove labels from multiple messages in bulk"},"messages.trash":{riskLevel:"write",description:"Move a message to the trash"},"messages.untrash":{riskLevel:"write",description:"Restore a message from the trash"},"labels.list":{riskLevel:"read",description:"List all labels in the mailbox"},"labels.get":{riskLevel:"read",description:"Get a specific label"},"labels.create":{riskLevel:"write",description:"Create a new label"},"labels.update":{riskLevel:"write",description:"Update an existing label"},"labels.delete":{riskLevel:"destructive",description:"Delete a label"},"drafts.list":{riskLevel:"read",description:"List drafts in the mailbox"},"drafts.get":{riskLevel:"read",description:"Get a specific draft"},"drafts.create":{riskLevel:"write",description:"Create a new draft"},"drafts.update":{riskLevel:"write",description:"Update an existing draft"},"drafts.delete":{riskLevel:"destructive",description:"Delete a draft"},"drafts.send":{riskLevel:"write",description:"Send a draft as an email"},"threads.list":{riskLevel:"read",description:"List threads in the mailbox"},"threads.get":{riskLevel:"read",description:"Get a specific thread"},"threads.modify":{riskLevel:"write",description:"Add or remove labels from a thread"},"threads.delete":{riskLevel:"destructive",irreversible:!0,description:"Permanently delete a thread [DESTRUCTIVE \xB7 IRREVERSIBLE]"},"threads.trash":{riskLevel:"write",description:"Move a thread to the trash"},"threads.untrash":{riskLevel:"write",description:"Restore a thread from the trash"}};function ua(e={}){let t={...e,authType:e.authType??Gs};return{id:"gmail",schema:H,options:t,authConfig:cs,oauthConfig:{providerName:"Google",authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:["https://www.googleapis.com/auth/gmail.modify","https://www.googleapis.com/auth/gmail.labels","https://www.googleapis.com/auth/gmail.send","https://www.googleapis.com/auth/gmail.compose"],authParams:{access_type:"offline",prompt:"consent"}},hooks:t.hooks,webhookHooks:t.webhookHooks,endpoints:hs,webhooks:bs,endpointMeta:Es,endpointSchemas:fs,webhookSchemas:ys,keyBuilder:async a=>{let o=a.authType;if(t.key)return t.key;if(a.authType==="oauth_2")return gs(a,{plugin:"gmail",tokenUrl:"https://oauth2.googleapis.com/token"});throw new us("gmail","oauth_2")},pluginWebhookMatcher:a=>{let o=a.headers;if(!(o.from==="noreply@google.com"||typeof o["user-agent"]=="string"&&o["user-agent"].includes("APIs-Google")))return!1;let i=a.body;if(!i?.message?.data)return!1;try{let d=v(i.message.data);return!!d.emailAddress&&!!d.historyId}catch{return!1}},pluginTenantWebhookMatcher:Fe,oauthWebhookTenantLinkResolver:_e,subscribe:De}}export{H as GmailSchema,z as createGmailWebhookMatcher,v as decodePubSubMessage,ua as gmail,cs as gmailAuthConfig,fs as gmailEndpointSchemas,hs as gmailEndpointsNested,bs as gmailWebhooksNested};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corsair-dev/gmail",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Gmail plugin for Corsair",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,18 +28,24 @@
28
28
  "typescript": "^5.9.3",
29
29
  "zod": "^4.1.13",
30
30
  "jest": "^29.7.0",
31
- "corsair": "0.1.120"
31
+ "corsair": "0.1.129"
32
32
  },
33
33
  "keywords": [
34
34
  "corsair",
35
35
  "gmail",
36
36
  "plugin"
37
37
  ],
38
- "author": "",
38
+ "author": "Corsair (https://corsair.dev)",
39
39
  "license": "Apache-2.0",
40
40
  "files": [
41
41
  "dist"
42
42
  ],
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/corsairdev/corsair.git",
46
+ "directory": "packages/gmail"
47
+ },
48
+ "homepage": "https://docs.corsair.dev/plugins/gmail",
43
49
  "scripts": {
44
50
  "build": "rm -rf dist && tsc --build --force && tsup",
45
51
  "typecheck": "tsc --noEmit",