@warriorteam/messenger-sdk 1.0.0 → 1.2.0

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 CHANGED
@@ -9,7 +9,7 @@ A modern TypeScript SDK for the Facebook Messenger Platform API, designed with s
9
9
  - 🔄 **Dual module support** - ESM and CommonJS
10
10
  - ✅ **Comprehensive validation** - Built-in message and template validation
11
11
  - 🛡️ **Error handling** - Detailed error types and messages
12
- - 📚 **Complete API coverage** - Send API, Templates, Attachments, Moderation
12
+ - 📚 **Complete API coverage** - Send API, Templates, Attachments, Moderation, Profile
13
13
 
14
14
  ## Installation
15
15
 
@@ -197,6 +197,49 @@ await messenger.moderation.unblockUser('USER_PSID');
197
197
  await messenger.moderation.unbanUser('USER_PSID');
198
198
  ```
199
199
 
200
+ ### Profile API
201
+
202
+ #### Get User Profile Information
203
+
204
+ ```typescript
205
+ // Get basic profile info (first_name, last_name, profile_pic)
206
+ const profile = await messenger.profile.getBasic('USER_PSID');
207
+ console.log(`Hello ${profile.first_name}!`);
208
+
209
+ // Get comprehensive profile with all fields
210
+ const fullProfile = await messenger.profile.getFull('USER_PSID');
211
+ console.log('Profile:', fullProfile);
212
+ // Returns: { id, name, first_name, last_name, profile_pic, locale, timezone, gender }
213
+
214
+ // Get specific fields only
215
+ const customProfile = await messenger.profile.get({
216
+ psid: 'USER_PSID',
217
+ fields: ['first_name', 'locale', 'timezone']
218
+ });
219
+
220
+ // Helper methods for common use cases
221
+ const nameInfo = await messenger.profile.getName('USER_PSID');
222
+ const profilePic = await messenger.profile.getProfilePicture('USER_PSID');
223
+ ```
224
+
225
+ #### Personalize Messages
226
+
227
+ ```typescript
228
+ // Use profile info to personalize messages
229
+ const profile = await messenger.profile.getName('USER_PSID');
230
+ const greeting = profile.first_name
231
+ ? `Hello ${profile.first_name}! Welcome back!`
232
+ : 'Hello! Welcome back!';
233
+
234
+ await messenger.send.message({
235
+ recipient: { id: 'USER_PSID' },
236
+ messaging_type: 'RESPONSE',
237
+ message: { text: greeting }
238
+ });
239
+ ```
240
+
241
+ **Note**: Profile API requires "Advanced User Profile Access" feature and user interaction to grant permissions.
242
+
200
243
  ## Error Handling
201
244
 
202
245
  The SDK provides specific error types for different scenarios:
@@ -232,6 +275,8 @@ Check the `examples/` directory for complete usage examples:
232
275
  - `send-message.ts` - Basic message sending
233
276
  - `upload-attachment.ts` - Attachment handling
234
277
  - `send-template.ts` - Template messages
278
+ - `user-profile.ts` - Profile API usage
279
+ - `moderation.ts` - User moderation
235
280
 
236
281
  ## Development
237
282
 
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var f="v23.0",R="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},E={TEXT_MESSAGE_MAX_CHARS:2e3},U={IMAGE_MAX_SIZE:8*1024*1024,OTHER_MAX_SIZE:25*1024*1024,VIDEO_TIMEOUT:75,OTHER_TIMEOUT:10},o={GENERIC_ELEMENTS_MAX:10,GENERIC_TITLE_MAX_CHARS:80,GENERIC_SUBTITLE_MAX_CHARS:80,BUTTON_TEXT_MAX_CHARS:640,BUTTONS_MAX_COUNT:3,BUTTON_TITLE_MAX_CHARS:20,POSTBACK_PAYLOAD_MAX_CHARS:1e3,MEDIA_ELEMENTS_COUNT:1,MEDIA_BUTTONS_MAX_COUNT:3};var c=class extends Error{code;type;subcode;fbtrace_id;statusCode;response;constructor(e,s,r){super(e.message),this.name="MessengerAPIError",this.code=e.code,this.type=e.type,this.subcode=e.error_subcode,this.fbtrace_id=e.fbtrace_id,this.statusCode=s,this.response=r;}},l=class extends Error{cause;constructor(e,s){super(e),this.name="MessengerNetworkError",this.cause=s;}},u=class extends Error{timeout;constructor(e){super(`Request timed out after ${e}ms`),this.name="MessengerTimeoutError",this.timeout=e;}},m=class extends Error{constructor(e){super(e),this.name="MessengerConfigError";}};var S=class{config;constructor(e){this.config={accessToken:e.accessToken,version:e.version,baseUrl:e.baseUrl||R,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query),r;for(let i=0;i<=this.config.maxRetries;i++)try{let a=await this.makeRequest(s,e);return await this.handleResponse(a)}catch(a){if(r=a,a instanceof c&&a.statusCode>=400&&a.statusCode<500||i===this.config.maxRetries)throw a;await this.delay(1e3*(i+1));}throw r||new Error("Unknown error occurred")}buildUrl(e,s){let r=new URL(`${this.config.baseUrl}/${this.config.version}${e}`);return r.searchParams.append("access_token",this.config.accessToken),s&&Object.entries(s).forEach(([i,a])=>{r.searchParams.append(i,String(a));}),r.toString()}async makeRequest(e,s){let r=new AbortController,i=setTimeout(()=>r.abort(),this.config.timeout);try{let a={method:s.method,headers:{"Content-Type":"application/json"},signal:r.signal};return s.body&&(a.body=JSON.stringify(s.body)),await fetch(e,a)}catch(a){throw a instanceof Error?a.name==="AbortError"?new u(this.config.timeout):new l(`Network request failed: ${a.message}`,a):a}finally{clearTimeout(i);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let i=await e.json();throw new c(i.error,e.status,i)}else {let i=await e.text();throw new c({message:i||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,i)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var T=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function P(t){if(!t||t.trim()==="")throw new T("Text message cannot be empty");if(t.length>E.TEXT_MESSAGE_MAX_CHARS)throw new T(`Text message cannot exceed ${E.TEXT_MESSAGE_MAX_CHARS} characters`)}var d=class{constructor(e){this.httpClient=e;}async message(e){return e.message?.text&&P(e.message.text),this.httpClient.request({method:"POST",path:p.MESSAGES,body:e})}async action(e,s){return this.httpClient.request({method:"POST",path:p.MESSAGES,body:{recipient:{id:e},messaging_type:"RESPONSE",sender_action:s}})}async typingOn(e){return this.action(e,"typing_on")}async typingOff(e){return this.action(e,"typing_off")}async markSeen(e){return this.action(e,"mark_seen")}async attachment(e){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{attachment_id:e.attachment_id}}}})}async attachmentFromUrl(e){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{url:e.url}}}})}};var _=class{constructor(e){this.httpClient=e;}async upload(e){let s={message:{attachment:{type:e.type,payload:{url:e.url,is_reusable:e.is_reusable??true}}}};return this.httpClient.request({method:"POST",path:p.MESSAGE_ATTACHMENTS,body:s})}};var h=class{constructor(e){this.httpClient=e;}async moderate(e){return this.httpClient.request({method:"POST",path:p.MODERATE_CONVERSATIONS,body:e})}async blockUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["block_user"]})}async unblockUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["unblock_user"]})}async banUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["ban_user"]})}async unbanUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["unban_user"]})}async moveToSpam(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["move_to_spam"]})}async blockAndSpam(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["block_user","move_to_spam"]})}};var n=class extends Error{constructor(e){super(e),this.name="TemplateValidationError";}};function b(t){if(t.length===0)throw new n("Generic template must have at least 1 element");if(t.length>o.GENERIC_ELEMENTS_MAX)throw new n(`Generic template cannot have more than ${o.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{I(e,s);});}function I(t,e){if(!t.title||t.title.trim()==="")throw new n(`Element ${e}: title is required`);if(t.title.length>o.GENERIC_TITLE_MAX_CHARS)throw new n(`Element ${e}: title cannot exceed ${o.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>o.GENERIC_SUBTITLE_MAX_CHARS)throw new n(`Element ${e}: subtitle cannot exceed ${o.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!y(t.image_url))throw new n(`Element ${e}: image_url must be HTTPS`);if(t.buttons&&A(t.buttons,`Element ${e}`),!!!(t.subtitle||t.image_url||t.default_action||t.buttons&&t.buttons.length>0))throw new n(`Element ${e}: must have at least one additional property beyond title`)}function w(t,e){if(!t||t.trim()==="")throw new n("Button template text is required");if(t.length>o.BUTTON_TEXT_MAX_CHARS)throw new n(`Button template text cannot exceed ${o.BUTTON_TEXT_MAX_CHARS} characters`);if(e.length===0)throw new n("Button template must have at least 1 button");A(e,"Button template");}function C(t){if(!t.media_type)throw new n("Media template element must have media_type");if(!t.url&&!t.attachment_id)throw new n("Media template element must have either url or attachment_id");if(t.url&&t.attachment_id)throw new n("Media template element cannot have both url and attachment_id");if(t.url&&!y(t.url))throw new n("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>o.MEDIA_BUTTONS_MAX_COUNT)throw new n(`Media template cannot have more than ${o.MEDIA_BUTTONS_MAX_COUNT} buttons`);A(t.buttons,"Media template");}}function A(t,e){if(t.length>o.BUTTONS_MAX_COUNT)throw new n(`${e} cannot have more than ${o.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{x(s,`${e} button ${r}`);});}function x(t,e){if(!t.type)throw new n(`${e}: type is required`);if(t.type!=="account_unlink"&&(!t.title||t.title.trim()===""))throw new n(`${e}: title is required for ${t.type} buttons`);if(t.title&&t.title.length>o.BUTTON_TITLE_MAX_CHARS)throw new n(`${e}: title cannot exceed ${o.BUTTON_TITLE_MAX_CHARS} characters`);switch(t.type){case "web_url":if(!t.url)throw new n(`${e}: url is required for web_url buttons`);if(!y(t.url))throw new n(`${e}: url must be HTTPS for web_url buttons`);break;case "postback":if(!t.payload)throw new n(`${e}: payload is required for postback buttons`);if(t.payload.length>o.POSTBACK_PAYLOAD_MAX_CHARS)throw new n(`${e}: payload cannot exceed ${o.POSTBACK_PAYLOAD_MAX_CHARS} characters`);break;case "phone_number":if(!t.payload)throw new n(`${e}: payload is required for phone_number buttons`);if(!t.payload.startsWith("+"))throw new n(`${e}: phone_number payload must start with + (e.g., +1234567890)`);break;case "game_play":break;case "account_link":if(!t.url)throw new n(`${e}: url is required for account_link buttons`);if(!y(t.url))throw new n(`${e}: url must be HTTPS for account_link buttons`);break;}if(t.type==="web_url"&&t.messenger_extensions&&t.fallback_url&&!y(t.fallback_url))throw new n(`${e}: fallback_url must be HTTPS`)}function y(t){try{return new URL(t).protocol==="https:"}catch{return false}}var g=class{constructor(e){this.httpClient=e;}async generic(e){b(e.elements);let s={template_type:"generic",elements:e.elements,image_aspect_ratio:e.image_aspect_ratio},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}async button(e){w(e.text,e.buttons);let s={template_type:"button",text:e.text,buttons:e.buttons},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}async media(e){C(e.element);let s={template_type:"media",elements:[e.element]},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}async product(e){let s={template_type:"product",elements:e.elements},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}};var M=class{send;attachments;moderation;templates;httpClient;constructor(e){this.validateConfig(e);let s={accessToken:e.accessToken,version:e.version||f,baseUrl:e.baseUrl,timeout:e.timeout,maxRetries:e.maxRetries};this.httpClient=new S(s),this.send=new d(this.httpClient),this.attachments=new _(this.httpClient),this.moderation=new h(this.httpClient),this.templates=new g(this.httpClient);}validateConfig(e){if(!e.accessToken)throw new m("Access token is required");if(typeof e.accessToken!="string"||e.accessToken.trim()==="")throw new m("Access token must be a non-empty string");if(e.version&&typeof e.version!="string")throw new m("API version must be a string");if(e.timeout&&(typeof e.timeout!="number"||e.timeout<=0))throw new m("Timeout must be a positive number");if(e.maxRetries&&(typeof e.maxRetries!="number"||e.maxRetries<0))throw new m("Max retries must be a non-negative number")}};
2
- exports.ATTACHMENT_LIMITS=U;exports.AttachmentsAPI=_;exports.MESSAGE_LIMITS=E;exports.MessageValidationError=T;exports.Messenger=M;exports.MessengerAPIError=c;exports.MessengerConfigError=m;exports.MessengerNetworkError=l;exports.MessengerTimeoutError=u;exports.ModerationAPI=h;exports.SendAPI=d;exports.TEMPLATE_LIMITS=o;exports.TemplateValidationError=n;exports.TemplatesAPI=g;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var R="v23.0",b="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},A={TEXT_MESSAGE_MAX_CHARS:2e3},v={IMAGE_MAX_SIZE:8*1024*1024,OTHER_MAX_SIZE:25*1024*1024,VIDEO_TIMEOUT:75,OTHER_TIMEOUT:10},i={GENERIC_ELEMENTS_MAX:10,GENERIC_TITLE_MAX_CHARS:80,GENERIC_SUBTITLE_MAX_CHARS:80,BUTTON_TEXT_MAX_CHARS:640,BUTTONS_MAX_COUNT:3,BUTTON_TITLE_MAX_CHARS:20,POSTBACK_PAYLOAD_MAX_CHARS:1e3,MEDIA_ELEMENTS_COUNT:1,MEDIA_BUTTONS_MAX_COUNT:3};var m=class extends Error{code;type;subcode;fbtrace_id;statusCode;response;constructor(e,s,r){super(e.message),this.name="MessengerAPIError",this.code=e.code,this.type=e.type,this.subcode=e.error_subcode,this.fbtrace_id=e.fbtrace_id,this.statusCode=s,this.response=r;}},l=class extends Error{cause;constructor(e,s){super(e),this.name="MessengerNetworkError",this.cause=s;}},T=class extends Error{timeout;constructor(e){super(`Request timed out after ${e}ms`),this.name="MessengerTimeoutError",this.timeout=e;}},c=class extends Error{constructor(e){super(e),this.name="MessengerConfigError";}};var f=class{config;constructor(e){this.config={accessToken:e.accessToken,version:e.version,baseUrl:e.baseUrl||b,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query,e.accessToken),r;for(let n=0;n<=this.config.maxRetries;n++)try{let a=await this.makeRequest(s,e);return await this.handleResponse(a)}catch(a){if(r=a,a instanceof m&&a.statusCode>=400&&a.statusCode<500||n===this.config.maxRetries)throw a;await this.delay(1e3*(n+1));}throw r||new Error("Unknown error occurred")}buildUrl(e,s,r){let n=new URL(`${this.config.baseUrl}/${this.config.version}${e}`),a=r||this.config.accessToken;if(!a)throw new Error("Access token is required. Provide it in constructor or method options.");return n.searchParams.append("access_token",a),s&&Object.entries(s).forEach(([M,U])=>{n.searchParams.append(M,String(U));}),n.toString()}async makeRequest(e,s){let r=new AbortController,n=setTimeout(()=>r.abort(),this.config.timeout);try{let a={method:s.method,headers:{"Content-Type":"application/json"},signal:r.signal};return s.body&&(a.body=JSON.stringify(s.body)),await fetch(e,a)}catch(a){throw a instanceof Error?a.name==="AbortError"?new T(this.config.timeout):new l(`Network request failed: ${a.message}`,a):a}finally{clearTimeout(n);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let n=await e.json();throw new m(n.error,e.status,n)}else {let n=await e.text();throw new m({message:n||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,n)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var u=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function w(t){if(!t||t.trim()==="")throw new u("Text message cannot be empty");if(t.length>A.TEXT_MESSAGE_MAX_CHARS)throw new u(`Text message cannot exceed ${A.TEXT_MESSAGE_MAX_CHARS} characters`)}var d=class{constructor(e){this.httpClient=e;}async message(e,s){return e.message?.text&&w(e.message.text),this.httpClient.request({method:"POST",path:p.MESSAGES,body:e,accessToken:s?.accessToken})}async action(e,s,r){return this.httpClient.request({method:"POST",path:p.MESSAGES,body:{recipient:{id:e},messaging_type:"RESPONSE",sender_action:s},accessToken:r?.accessToken})}async typingOn(e,s){return this.action(e,"typing_on",s)}async typingOff(e,s){return this.action(e,"typing_off",s)}async markSeen(e,s){return this.action(e,"mark_seen",s)}async attachment(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{attachment_id:e.attachment_id}}}},s)}async attachmentFromUrl(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{url:e.url}}}},s)}};var h=class{constructor(e){this.httpClient=e;}async upload(e,s){let r={message:{attachment:{type:e.type,payload:{url:e.url,is_reusable:e.is_reusable??true}}}};return this.httpClient.request({method:"POST",path:p.MESSAGE_ATTACHMENTS,body:r,accessToken:s?.accessToken})}};var g=class{constructor(e){this.httpClient=e;}async moderate(e,s){return this.httpClient.request({method:"POST",path:p.MODERATE_CONVERSATIONS,body:e,accessToken:s?.accessToken})}async blockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user"]},s)}async unblockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unblock_user"]},s)}async banUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["ban_user"]},s)}async unbanUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unban_user"]},s)}async moveToSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["move_to_spam"]},s)}async blockAndSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user","move_to_spam"]},s)}};var o=class extends Error{constructor(e){super(e),this.name="TemplateValidationError";}};function C(t){if(t.length===0)throw new o("Generic template must have at least 1 element");if(t.length>i.GENERIC_ELEMENTS_MAX)throw new o(`Generic template cannot have more than ${i.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{G(e,s);});}function G(t,e){if(!t.title||t.title.trim()==="")throw new o(`Element ${e}: title is required`);if(t.title.length>i.GENERIC_TITLE_MAX_CHARS)throw new o(`Element ${e}: title cannot exceed ${i.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>i.GENERIC_SUBTITLE_MAX_CHARS)throw new o(`Element ${e}: subtitle cannot exceed ${i.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!_(t.image_url))throw new o(`Element ${e}: image_url must be HTTPS`);if(t.buttons&&P(t.buttons,`Element ${e}`),!!!(t.subtitle||t.image_url||t.default_action||t.buttons&&t.buttons.length>0))throw new o(`Element ${e}: must have at least one additional property beyond title`)}function O(t,e){if(!t||t.trim()==="")throw new o("Button template text is required");if(t.length>i.BUTTON_TEXT_MAX_CHARS)throw new o(`Button template text cannot exceed ${i.BUTTON_TEXT_MAX_CHARS} characters`);if(e.length===0)throw new o("Button template must have at least 1 button");P(e,"Button template");}function I(t){if(!t.media_type)throw new o("Media template element must have media_type");if(!t.url&&!t.attachment_id)throw new o("Media template element must have either url or attachment_id");if(t.url&&t.attachment_id)throw new o("Media template element cannot have both url and attachment_id");if(t.url&&!_(t.url))throw new o("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>i.MEDIA_BUTTONS_MAX_COUNT)throw new o(`Media template cannot have more than ${i.MEDIA_BUTTONS_MAX_COUNT} buttons`);P(t.buttons,"Media template");}}function P(t,e){if(t.length>i.BUTTONS_MAX_COUNT)throw new o(`${e} cannot have more than ${i.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{H(s,`${e} button ${r}`);});}function H(t,e){if(!t.type)throw new o(`${e}: type is required`);if(t.type!=="account_unlink"&&(!t.title||t.title.trim()===""))throw new o(`${e}: title is required for ${t.type} buttons`);if(t.title&&t.title.length>i.BUTTON_TITLE_MAX_CHARS)throw new o(`${e}: title cannot exceed ${i.BUTTON_TITLE_MAX_CHARS} characters`);switch(t.type){case "web_url":if(!t.url)throw new o(`${e}: url is required for web_url buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for web_url buttons`);break;case "postback":if(!t.payload)throw new o(`${e}: payload is required for postback buttons`);if(t.payload.length>i.POSTBACK_PAYLOAD_MAX_CHARS)throw new o(`${e}: payload cannot exceed ${i.POSTBACK_PAYLOAD_MAX_CHARS} characters`);break;case "phone_number":if(!t.payload)throw new o(`${e}: payload is required for phone_number buttons`);if(!t.payload.startsWith("+"))throw new o(`${e}: phone_number payload must start with + (e.g., +1234567890)`);break;case "game_play":break;case "account_link":if(!t.url)throw new o(`${e}: url is required for account_link buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for account_link buttons`);break;}if(t.type==="web_url"&&t.messenger_extensions&&t.fallback_url&&!_(t.fallback_url))throw new o(`${e}: fallback_url must be HTTPS`)}function _(t){try{return new URL(t).protocol==="https:"}catch{return false}}var y=class{constructor(e){this.httpClient=e;}async generic(e,s){C(e.elements);let r={template_type:"generic",elements:e.elements,image_aspect_ratio:e.image_aspect_ratio},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async button(e,s){O(e.text,e.buttons);let r={template_type:"button",text:e.text,buttons:e.buttons},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async media(e,s){I(e.element);let r={template_type:"media",elements:[e.element]},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async product(e,s){let r={template_type:"product",elements:e.elements},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}};var E=class{constructor(e){this.httpClient=e;}async get(e,s){let{psid:r,fields:n=["first_name","last_name"]}=e,a=new URLSearchParams({fields:n.join(",")});return this.httpClient.request({method:"GET",path:`/${r}?${a.toString()}`,body:void 0,accessToken:s?.accessToken})}async getBasic(e,s){return this.get({psid:e,fields:["first_name","last_name","profile_pic"]},s)}async getFull(e,s){return this.get({psid:e,fields:["id","name","first_name","last_name","profile_pic","locale","timezone","gender"]},s)}async getName(e,s){return this.get({psid:e,fields:["first_name","last_name"]},s)}async getProfilePicture(e,s){return this.get({psid:e,fields:["profile_pic"]},s)}};var S=class{send;attachments;moderation;templates;profile;httpClient;constructor(e={}){this.validateConfig(e);let s={accessToken:e.accessToken,version:e.version||R,baseUrl:e.baseUrl,timeout:e.timeout,maxRetries:e.maxRetries};this.httpClient=new f(s),this.send=new d(this.httpClient),this.attachments=new h(this.httpClient),this.moderation=new g(this.httpClient),this.templates=new y(this.httpClient),this.profile=new E(this.httpClient);}validateConfig(e){if(e.accessToken!==void 0&&(typeof e.accessToken!="string"||e.accessToken.trim()===""))throw new c("Access token must be a non-empty string");if(e.version&&typeof e.version!="string")throw new c("API version must be a string");if(e.timeout&&(typeof e.timeout!="number"||e.timeout<=0))throw new c("Timeout must be a positive number");if(e.maxRetries&&(typeof e.maxRetries!="number"||e.maxRetries<0))throw new c("Max retries must be a non-negative number")}};
2
+ exports.ATTACHMENT_LIMITS=v;exports.AttachmentsAPI=h;exports.MESSAGE_LIMITS=A;exports.MessageValidationError=u;exports.Messenger=S;exports.MessengerAPIError=m;exports.MessengerConfigError=c;exports.MessengerNetworkError=l;exports.MessengerTimeoutError=T;exports.ModerationAPI=g;exports.ProfileAPI=E;exports.SendAPI=d;exports.TEMPLATE_LIMITS=i;exports.TemplateValidationError=o;exports.TemplatesAPI=y;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/core/errors.ts","../src/core/http-client.ts","../src/utils/message-validators.ts","../src/resources/send.ts","../src/resources/attachments.ts","../src/resources/moderation.ts","../src/utils/validators.ts","../src/resources/templates.ts","../src/client.ts"],"names":["DEFAULT_API_VERSION","BASE_URL","API_ENDPOINTS","MESSAGE_LIMITS","ATTACHMENT_LIMITS","TEMPLATE_LIMITS","MessengerAPIError","error","statusCode","response","MessengerNetworkError","message","cause","MessengerTimeoutError","timeout","MessengerConfigError","HTTPClient","config","options","url","lastError","attempt","path","query","key","value","controller","timeoutId","fetchOptions","isJson","errorData","text","ms","resolve","MessageValidationError","validateTextMessage","SendAPI","httpClient","request","recipientId","action","AttachmentsAPI","body","ModerationAPI","userIds","user_ids","id","TemplateValidationError","validateGenericTemplate","elements","element","index","validateGenericElement","isHttpsUrl","validateButtons","validateButtonTemplate","buttons","validateMediaTemplate","context","button","validateButton","TemplatesAPI","payload","Messenger","clientConfig"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_API_VERSION = 'v23.0';\nexport const BASE_URL = 'https://graph.facebook.com';\nexport const DEFAULT_TIMEOUT = 30000; // 30 seconds\nexport const MAX_RETRY_ATTEMPTS = 3;\nexport const RETRY_DELAY_MS = 1000;\n\nexport const API_ENDPOINTS = {\n MESSAGES: '/me/messages',\n MESSAGE_ATTACHMENTS: '/me/message_attachments',\n MODERATE_CONVERSATIONS: '/me/moderate_conversations',\n PASS_THREAD_CONTROL: '/me/pass_thread_control',\n TAKE_THREAD_CONTROL: '/me/take_thread_control',\n REQUEST_THREAD_CONTROL: '/me/request_thread_control',\n} as const;\n\n// Validation constants\nexport const MESSAGE_LIMITS = {\n // Text messages\n TEXT_MESSAGE_MAX_CHARS: 2000,\n} as const;\n\nexport const ATTACHMENT_LIMITS = {\n // File size limits in bytes\n IMAGE_MAX_SIZE: 8 * 1024 * 1024, // 8MB\n OTHER_MAX_SIZE: 25 * 1024 * 1024, // 25MB (video, audio, file)\n \n // Timeout limits in seconds\n VIDEO_TIMEOUT: 75,\n OTHER_TIMEOUT: 10,\n} as const;\n\nexport const TEMPLATE_LIMITS = {\n // Generic Template\n GENERIC_ELEMENTS_MAX: 10,\n GENERIC_TITLE_MAX_CHARS: 80,\n GENERIC_SUBTITLE_MAX_CHARS: 80,\n \n // Button Template \n BUTTON_TEXT_MAX_CHARS: 640,\n BUTTONS_MAX_COUNT: 3,\n BUTTON_TITLE_MAX_CHARS: 20,\n \n // All Templates\n POSTBACK_PAYLOAD_MAX_CHARS: 1000,\n \n // Media Template\n MEDIA_ELEMENTS_COUNT: 1, // Exactly 1 element required\n MEDIA_BUTTONS_MAX_COUNT: 3,\n} as const;","import type { MessengerError } from '../types/responses.js';\n\nexport class MessengerAPIError extends Error {\n public readonly code: number;\n public readonly type: string;\n public readonly subcode?: number;\n public readonly fbtrace_id?: string;\n public readonly statusCode: number;\n public readonly response?: any;\n\n constructor(error: MessengerError, statusCode: number, response?: any) {\n super(error.message);\n this.name = 'MessengerAPIError';\n this.code = error.code;\n this.type = error.type;\n this.subcode = error.error_subcode;\n this.fbtrace_id = error.fbtrace_id;\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\nexport class MessengerNetworkError extends Error {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'MessengerNetworkError';\n this.cause = cause;\n }\n}\n\nexport class MessengerTimeoutError extends Error {\n public readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Request timed out after ${timeout}ms`);\n this.name = 'MessengerTimeoutError';\n this.timeout = timeout;\n }\n}\n\nexport class MessengerConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessengerConfigError';\n }\n}","import { BASE_URL, DEFAULT_TIMEOUT, MAX_RETRY_ATTEMPTS, RETRY_DELAY_MS } from './constants.js';\nimport { MessengerAPIError, MessengerNetworkError, MessengerTimeoutError } from './errors.js';\nimport type { ErrorResponse } from '../types/responses.js';\n\nexport interface ClientConfig {\n accessToken: string;\n version: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'DELETE';\n path: string;\n body?: any;\n query?: Record<string, string | number | boolean>;\n}\n\nexport class HTTPClient {\n private readonly config: Required<ClientConfig>;\n\n constructor(config: ClientConfig) {\n this.config = {\n accessToken: config.accessToken,\n version: config.version,\n baseUrl: config.baseUrl || BASE_URL,\n timeout: config.timeout || DEFAULT_TIMEOUT,\n maxRetries: config.maxRetries || MAX_RETRY_ATTEMPTS,\n };\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n const url = this.buildUrl(options.path, options.query);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await this.makeRequest(url, options);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n \n // Don't retry on client errors (4xx)\n if (error instanceof MessengerAPIError && error.statusCode >= 400 && error.statusCode < 500) {\n throw error;\n }\n\n // Don't retry on timeout for the last attempt\n if (attempt === this.config.maxRetries) {\n throw error;\n }\n\n // Wait before retrying\n await this.delay(RETRY_DELAY_MS * (attempt + 1));\n }\n }\n\n throw lastError || new Error('Unknown error occurred');\n }\n\n private buildUrl(path: string, query?: Record<string, string | number | boolean>): string {\n const url = new URL(`${this.config.baseUrl}/${this.config.version}${path}`);\n \n // Always add access token\n url.searchParams.append('access_token', this.config.accessToken);\n \n // Add additional query parameters\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n return url.toString();\n }\n\n private async makeRequest(url: string, options: RequestOptions): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers: {\n 'Content-Type': 'application/json',\n },\n signal: controller.signal,\n };\n\n if (options.body) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new MessengerTimeoutError(this.config.timeout);\n }\n throw new MessengerNetworkError(`Network request failed: ${error.message}`, error);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type');\n const isJson = contentType?.includes('application/json');\n\n if (!response.ok) {\n if (isJson) {\n const errorData = await response.json() as ErrorResponse;\n throw new MessengerAPIError(errorData.error, response.status, errorData);\n } else {\n const text = await response.text();\n throw new MessengerAPIError(\n {\n message: text || `HTTP ${response.status} ${response.statusText}`,\n type: 'http_error',\n code: response.status,\n fbtrace_id: '',\n },\n response.status,\n text\n );\n }\n }\n\n if (isJson) {\n return await response.json() as T;\n }\n\n // For non-JSON responses, return the text\n return await response.text() as unknown as T;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}","import { MESSAGE_LIMITS } from '../core/constants.js';\n\nexport class MessageValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessageValidationError';\n }\n}\n\nexport function validateTextMessage(text: string): void {\n if (!text || text.trim() === '') {\n throw new MessageValidationError('Text message cannot be empty');\n }\n\n if (text.length > MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS) {\n throw new MessageValidationError(\n `Text message cannot exceed ${MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS} characters`\n );\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { SendMessageRequest, SenderAction, Recipient } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport type { AttachmentType } from '../types/attachments.js';\nimport { validateTextMessage } from '../utils/message-validators.js';\n\nexport class SendAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async message(request: SendMessageRequest): Promise<SendMessageResponse> {\n // Validate text message length if present\n if (request.message?.text) {\n validateTextMessage(request.message.text);\n }\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async action(recipientId: string, action: SenderAction): Promise<SendMessageResponse> {\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: {\n recipient: { id: recipientId },\n messaging_type: 'RESPONSE',\n sender_action: action,\n },\n });\n }\n\n async typingOn(recipientId: string): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_on');\n }\n\n async typingOff(recipientId: string): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_off');\n }\n\n async markSeen(recipientId: string): Promise<SendMessageResponse> {\n return this.action(recipientId, 'mark_seen');\n }\n\n // Convenience methods for sending attachments\n\n /**\n * Send an attachment using a previously uploaded attachment_id\n */\n async attachment(options: {\n recipient: Recipient;\n type: AttachmentType;\n attachment_id: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n attachment_id: options.attachment_id,\n },\n },\n },\n });\n }\n\n /**\n * Upload and send an attachment from URL in a single request\n */\n async attachmentFromUrl(options: {\n recipient: Recipient;\n type: AttachmentType;\n url: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n url: options.url,\n },\n },\n },\n });\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { AttachmentUploadRequest, AttachmentUploadResponse } from '../types/attachments.js';\n\nexport class AttachmentsAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async upload(request: AttachmentUploadRequest): Promise<AttachmentUploadResponse> {\n // Format according to official API - no message wrapper needed\n const body = {\n message: {\n attachment: {\n type: request.type,\n payload: {\n url: request.url,\n is_reusable: request.is_reusable ?? true,\n },\n },\n },\n };\n\n return this.httpClient.request<AttachmentUploadResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGE_ATTACHMENTS,\n body,\n });\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { \n ModerateConversationsRequest,\n ModerateConversationsResponse\n} from '../types/moderation.js';\n\nexport class ModerationAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Moderate conversations with specified actions\n * Up to 10 user IDs and up to 2 actions per request\n */\n async moderate(request: ModerateConversationsRequest): Promise<ModerateConversationsResponse> {\n return this.httpClient.request<ModerateConversationsResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MODERATE_CONVERSATIONS,\n body: request,\n });\n }\n\n /**\n * Block a user from messaging the page\n * Prevents messaging but user can still interact with page content on Facebook\n */\n async blockUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds) \n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user'],\n });\n }\n\n /**\n * Unblock a user to allow messaging again\n */\n async unblockUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unblock_user'],\n });\n }\n\n /**\n * Ban a user from both messaging and Facebook interactions\n * More restrictive than blocking - prevents all interactions\n * Note: Cannot ban user who was unbanned in last 48 hours\n */\n async banUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['ban_user'],\n });\n }\n\n /**\n * Unban a user to restore all interactions\n * Note: Banned user cannot be unblocked, they must be unbanned first\n */\n async unbanUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unban_user'],\n });\n }\n\n /**\n * Move conversation to spam folder in Meta Business Suite Inbox\n */\n async moveToSpam(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['move_to_spam'],\n });\n }\n\n /**\n * Block user and move to spam (common moderation action)\n */\n async blockAndSpam(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user', 'move_to_spam'],\n });\n }\n}","import { TEMPLATE_LIMITS } from '../core/constants.js';\nimport type { Button, GenericTemplateElement, MediaTemplateElement } from '../types/templates.js';\n\nexport class TemplateValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TemplateValidationError';\n }\n}\n\nexport function validateGenericTemplate(elements: GenericTemplateElement[]): void {\n if (elements.length === 0) {\n throw new TemplateValidationError('Generic template must have at least 1 element');\n }\n\n if (elements.length > TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX) {\n throw new TemplateValidationError(\n `Generic template cannot have more than ${TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX} elements`\n );\n }\n\n elements.forEach((element, index) => {\n validateGenericElement(element, index);\n });\n}\n\nexport function validateGenericElement(element: GenericTemplateElement, index: number): void {\n if (!element.title || element.title.trim() === '') {\n throw new TemplateValidationError(`Element ${index}: title is required`);\n }\n\n if (element.title.length > TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: title cannot exceed ${TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.subtitle && element.subtitle.length > TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: subtitle cannot exceed ${TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.image_url && !isHttpsUrl(element.image_url)) {\n throw new TemplateValidationError(`Element ${index}: image_url must be HTTPS`);\n }\n\n if (element.buttons) {\n validateButtons(element.buttons, `Element ${index}`);\n }\n\n // Validate that element has at least one property beyond title\n const hasAdditionalProperty = !!(\n element.subtitle ||\n element.image_url ||\n element.default_action ||\n (element.buttons && element.buttons.length > 0)\n );\n\n if (!hasAdditionalProperty) {\n throw new TemplateValidationError(\n `Element ${index}: must have at least one additional property beyond title`\n );\n }\n}\n\nexport function validateButtonTemplate(text: string, buttons: Button[]): void {\n if (!text || text.trim() === '') {\n throw new TemplateValidationError('Button template text is required');\n }\n\n if (text.length > TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS) {\n throw new TemplateValidationError(\n `Button template text cannot exceed ${TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS} characters`\n );\n }\n\n if (buttons.length === 0) {\n throw new TemplateValidationError('Button template must have at least 1 button');\n }\n\n validateButtons(buttons, 'Button template');\n}\n\nexport function validateMediaTemplate(element: MediaTemplateElement): void {\n if (!element.media_type) {\n throw new TemplateValidationError('Media template element must have media_type');\n }\n\n if (!element.url && !element.attachment_id) {\n throw new TemplateValidationError('Media template element must have either url or attachment_id');\n }\n\n if (element.url && element.attachment_id) {\n throw new TemplateValidationError(\n 'Media template element cannot have both url and attachment_id'\n );\n }\n\n if (element.url && !isHttpsUrl(element.url)) {\n throw new TemplateValidationError('Media template url must be HTTPS');\n }\n\n if (element.buttons) {\n if (element.buttons.length > TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `Media template cannot have more than ${TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT} buttons`\n );\n }\n validateButtons(element.buttons, 'Media template');\n }\n}\n\nexport function validateButtons(buttons: Button[], context: string): void {\n if (buttons.length > TEMPLATE_LIMITS.BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `${context} cannot have more than ${TEMPLATE_LIMITS.BUTTONS_MAX_COUNT} buttons`\n );\n }\n\n buttons.forEach((button, index) => {\n validateButton(button, `${context} button ${index}`);\n });\n}\n\nexport function validateButton(button: Button, context: string): void {\n if (!button.type) {\n throw new TemplateValidationError(`${context}: type is required`);\n }\n\n // Title is required for most button types (not for account_unlink)\n if (button.type !== 'account_unlink' && (!button.title || button.title.trim() === '')) {\n throw new TemplateValidationError(`${context}: title is required for ${button.type} buttons`);\n }\n\n if (button.title && button.title.length > TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: title cannot exceed ${TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS} characters`\n );\n }\n\n // Type-specific validations\n switch (button.type) {\n case 'web_url':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for web_url buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for web_url buttons`);\n }\n break;\n\n case 'postback':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for postback buttons`);\n }\n if (button.payload.length > TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: payload cannot exceed ${TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS} characters`\n );\n }\n break;\n\n case 'phone_number':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for phone_number buttons`);\n }\n // Basic phone number validation (starts with +)\n if (!button.payload.startsWith('+')) {\n throw new TemplateValidationError(\n `${context}: phone_number payload must start with + (e.g., +1234567890)`\n );\n }\n break;\n\n case 'game_play':\n // game_play buttons may have optional game_metadata\n break;\n\n case 'account_link':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for account_link buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for account_link buttons`);\n }\n break;\n\n case 'account_unlink':\n // account_unlink buttons don't require additional properties\n break;\n }\n\n // Validate webview properties for web_url buttons\n if (button.type === 'web_url' && button.messenger_extensions && button.fallback_url) {\n if (!isHttpsUrl(button.fallback_url)) {\n throw new TemplateValidationError(`${context}: fallback_url must be HTTPS`);\n }\n }\n}\n\nfunction isHttpsUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.protocol === 'https:';\n } catch {\n return false;\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { Recipient, SendMessageRequest, MessagingType } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport { validateGenericTemplate, validateButtonTemplate, validateMediaTemplate } from '../utils/validators.js';\nimport type {\n GenericTemplatePayload,\n ButtonTemplatePayload,\n MediaTemplatePayload,\n ProductTemplatePayload,\n GenericTemplateElement,\n Button,\n MediaTemplateElement,\n ProductTemplateElement,\n} from '../types/templates.js';\n\nexport class TemplatesAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async generic(options: {\n recipient: Recipient;\n elements: GenericTemplateElement[];\n messaging_type?: MessagingType;\n image_aspect_ratio?: 'horizontal' | 'square';\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n // Validate template\n validateGenericTemplate(options.elements);\n\n const payload: GenericTemplatePayload = {\n template_type: 'generic',\n elements: options.elements,\n image_aspect_ratio: options.image_aspect_ratio,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async button(options: {\n recipient: Recipient;\n text: string;\n buttons: Button[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n // Validate template\n validateButtonTemplate(options.text, options.buttons);\n\n const payload: ButtonTemplatePayload = {\n template_type: 'button',\n text: options.text,\n buttons: options.buttons,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async media(options: {\n recipient: Recipient;\n element: MediaTemplateElement;\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n // Validate template\n validateMediaTemplate(options.element);\n\n const payload: MediaTemplatePayload = {\n template_type: 'media',\n elements: [options.element],\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async product(options: {\n recipient: Recipient;\n elements: ProductTemplateElement[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n const payload: ProductTemplatePayload = {\n template_type: 'product',\n elements: options.elements,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n}","import { HTTPClient, type ClientConfig } from './core/http-client.js';\nimport { DEFAULT_API_VERSION } from './core/constants.js';\nimport { MessengerConfigError } from './core/errors.js';\nimport { SendAPI } from './resources/send.js';\nimport { AttachmentsAPI } from './resources/attachments.js';\nimport { ModerationAPI } from './resources/moderation.js';\nimport { TemplatesAPI } from './resources/templates.js';\n\nexport interface MessengerConfig {\n accessToken: string;\n version?: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class Messenger {\n public readonly send: SendAPI;\n public readonly attachments: AttachmentsAPI;\n public readonly moderation: ModerationAPI;\n public readonly templates: TemplatesAPI;\n\n private readonly httpClient: HTTPClient;\n\n constructor(config: MessengerConfig) {\n this.validateConfig(config);\n\n const clientConfig: ClientConfig = {\n accessToken: config.accessToken,\n version: config.version || DEFAULT_API_VERSION,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n };\n\n this.httpClient = new HTTPClient(clientConfig);\n\n // Initialize API resources\n this.send = new SendAPI(this.httpClient);\n this.attachments = new AttachmentsAPI(this.httpClient);\n this.moderation = new ModerationAPI(this.httpClient);\n this.templates = new TemplatesAPI(this.httpClient);\n }\n\n private validateConfig(config: MessengerConfig): void {\n if (!config.accessToken) {\n throw new MessengerConfigError('Access token is required');\n }\n\n if (typeof config.accessToken !== 'string' || config.accessToken.trim() === '') {\n throw new MessengerConfigError('Access token must be a non-empty string');\n }\n\n if (config.version && typeof config.version !== 'string') {\n throw new MessengerConfigError('API version must be a string');\n }\n\n if (config.timeout && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new MessengerConfigError('Timeout must be a positive number');\n }\n\n if (config.maxRetries && (typeof config.maxRetries !== 'number' || config.maxRetries < 0)) {\n throw new MessengerConfigError('Max retries must be a non-negative number');\n }\n }\n}"]}
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/core/errors.ts","../src/core/http-client.ts","../src/utils/message-validators.ts","../src/resources/send.ts","../src/resources/attachments.ts","../src/resources/moderation.ts","../src/utils/validators.ts","../src/resources/templates.ts","../src/resources/profile.ts","../src/client.ts"],"names":["DEFAULT_API_VERSION","BASE_URL","API_ENDPOINTS","MESSAGE_LIMITS","ATTACHMENT_LIMITS","TEMPLATE_LIMITS","MessengerAPIError","error","statusCode","response","MessengerNetworkError","message","cause","MessengerTimeoutError","timeout","MessengerConfigError","HTTPClient","config","options","url","lastError","attempt","path","query","accessTokenOverride","accessToken","key","value","controller","timeoutId","fetchOptions","isJson","errorData","text","ms","resolve","MessageValidationError","validateTextMessage","SendAPI","httpClient","request","recipientId","action","apiOptions","AttachmentsAPI","body","ModerationAPI","userIds","user_ids","id","TemplateValidationError","validateGenericTemplate","elements","element","index","validateGenericElement","isHttpsUrl","validateButtons","validateButtonTemplate","buttons","validateMediaTemplate","context","button","validateButton","TemplatesAPI","payload","ProfileAPI","psid","fields","queryParams","Messenger","clientConfig"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_API_VERSION = 'v23.0';\nexport const BASE_URL = 'https://graph.facebook.com';\nexport const DEFAULT_TIMEOUT = 30000; // 30 seconds\nexport const MAX_RETRY_ATTEMPTS = 3;\nexport const RETRY_DELAY_MS = 1000;\n\nexport const API_ENDPOINTS = {\n MESSAGES: '/me/messages',\n MESSAGE_ATTACHMENTS: '/me/message_attachments',\n MODERATE_CONVERSATIONS: '/me/moderate_conversations',\n USER_PROFILE: '', // Dynamic endpoint: /{PSID}\n} as const;\n\n// Validation constants\nexport const MESSAGE_LIMITS = {\n // Text messages\n TEXT_MESSAGE_MAX_CHARS: 2000,\n} as const;\n\nexport const ATTACHMENT_LIMITS = {\n // File size limits in bytes\n IMAGE_MAX_SIZE: 8 * 1024 * 1024, // 8MB\n OTHER_MAX_SIZE: 25 * 1024 * 1024, // 25MB (video, audio, file)\n \n // Timeout limits in seconds\n VIDEO_TIMEOUT: 75,\n OTHER_TIMEOUT: 10,\n} as const;\n\nexport const TEMPLATE_LIMITS = {\n // Generic Template\n GENERIC_ELEMENTS_MAX: 10,\n GENERIC_TITLE_MAX_CHARS: 80,\n GENERIC_SUBTITLE_MAX_CHARS: 80,\n \n // Button Template \n BUTTON_TEXT_MAX_CHARS: 640,\n BUTTONS_MAX_COUNT: 3,\n BUTTON_TITLE_MAX_CHARS: 20,\n \n // All Templates\n POSTBACK_PAYLOAD_MAX_CHARS: 1000,\n \n // Media Template\n MEDIA_ELEMENTS_COUNT: 1, // Exactly 1 element required\n MEDIA_BUTTONS_MAX_COUNT: 3,\n} as const;","import type { MessengerError } from '../types/responses.js';\n\nexport class MessengerAPIError extends Error {\n public readonly code: number;\n public readonly type: string;\n public readonly subcode?: number;\n public readonly fbtrace_id?: string;\n public readonly statusCode: number;\n public readonly response?: any;\n\n constructor(error: MessengerError, statusCode: number, response?: any) {\n super(error.message);\n this.name = 'MessengerAPIError';\n this.code = error.code;\n this.type = error.type;\n this.subcode = error.error_subcode;\n this.fbtrace_id = error.fbtrace_id;\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\nexport class MessengerNetworkError extends Error {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'MessengerNetworkError';\n this.cause = cause;\n }\n}\n\nexport class MessengerTimeoutError extends Error {\n public readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Request timed out after ${timeout}ms`);\n this.name = 'MessengerTimeoutError';\n this.timeout = timeout;\n }\n}\n\nexport class MessengerConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessengerConfigError';\n }\n}","import { BASE_URL, DEFAULT_TIMEOUT, MAX_RETRY_ATTEMPTS, RETRY_DELAY_MS } from './constants.js';\nimport { MessengerAPIError, MessengerNetworkError, MessengerTimeoutError } from './errors.js';\nimport type { ErrorResponse } from '../types/responses.js';\n\nexport interface ClientConfig {\n accessToken?: string;\n version: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport interface APIOptions {\n accessToken?: string;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'DELETE';\n path: string;\n body?: any;\n query?: Record<string, string | number | boolean>;\n accessToken?: string;\n}\n\nexport class HTTPClient {\n private readonly config: Required<Omit<ClientConfig, 'accessToken'>> & { accessToken?: string };\n\n constructor(config: ClientConfig) {\n this.config = {\n accessToken: config.accessToken,\n version: config.version,\n baseUrl: config.baseUrl || BASE_URL,\n timeout: config.timeout || DEFAULT_TIMEOUT,\n maxRetries: config.maxRetries || MAX_RETRY_ATTEMPTS,\n };\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n const url = this.buildUrl(options.path, options.query, options.accessToken);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await this.makeRequest(url, options);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Don't retry on client errors (4xx)\n if (\n error instanceof MessengerAPIError &&\n error.statusCode >= 400 &&\n error.statusCode < 500\n ) {\n throw error;\n }\n\n // Don't retry on timeout for the last attempt\n if (attempt === this.config.maxRetries) {\n throw error;\n }\n\n // Wait before retrying\n await this.delay(RETRY_DELAY_MS * (attempt + 1));\n }\n }\n\n throw lastError || new Error('Unknown error occurred');\n }\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean>,\n accessTokenOverride?: string,\n ): string {\n const url = new URL(`${this.config.baseUrl}/${this.config.version}${path}`);\n\n // Use override token if provided, otherwise use config token\n const accessToken = accessTokenOverride || this.config.accessToken;\n\n if (!accessToken) {\n throw new Error('Access token is required. Provide it in constructor or method options.');\n }\n\n url.searchParams.append('access_token', accessToken);\n\n // Add additional query parameters\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n return url.toString();\n }\n\n private async makeRequest(url: string, options: RequestOptions): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers: {\n 'Content-Type': 'application/json',\n },\n signal: controller.signal,\n };\n\n if (options.body) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new MessengerTimeoutError(this.config.timeout);\n }\n throw new MessengerNetworkError(`Network request failed: ${error.message}`, error);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type');\n const isJson = contentType?.includes('application/json');\n\n if (!response.ok) {\n if (isJson) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new MessengerAPIError(errorData.error, response.status, errorData);\n } else {\n const text = await response.text();\n throw new MessengerAPIError(\n {\n message: text || `HTTP ${response.status} ${response.statusText}`,\n type: 'http_error',\n code: response.status,\n fbtrace_id: '',\n },\n response.status,\n text,\n );\n }\n }\n\n if (isJson) {\n return (await response.json()) as T;\n }\n\n // For non-JSON responses, return the text\n return (await response.text()) as unknown as T;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { MESSAGE_LIMITS } from '../core/constants.js';\n\nexport class MessageValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessageValidationError';\n }\n}\n\nexport function validateTextMessage(text: string): void {\n if (!text || text.trim() === '') {\n throw new MessageValidationError('Text message cannot be empty');\n }\n\n if (text.length > MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS) {\n throw new MessageValidationError(\n `Text message cannot exceed ${MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS} characters`\n );\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { SendMessageRequest, SenderAction, Recipient } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport type { AttachmentType } from '../types/attachments.js';\nimport { validateTextMessage } from '../utils/message-validators.js';\n\nexport class SendAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse> {\n // Validate text message length if present\n if (request.message?.text) {\n validateTextMessage(request.message.text);\n }\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: options?.accessToken,\n });\n }\n\n async action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse> {\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: {\n recipient: { id: recipientId },\n messaging_type: 'RESPONSE',\n sender_action: action,\n },\n accessToken: options?.accessToken,\n });\n }\n\n async typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_on', options);\n }\n\n async typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_off', options);\n }\n\n async markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'mark_seen', options);\n }\n\n // Convenience methods for sending attachments\n\n /**\n * Send an attachment using a previously uploaded attachment_id\n */\n async attachment(options: {\n recipient: Recipient;\n type: AttachmentType;\n attachment_id: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n attachment_id: options.attachment_id,\n },\n },\n },\n }, apiOptions);\n }\n\n /**\n * Upload and send an attachment from URL in a single request\n */\n async attachmentFromUrl(options: {\n recipient: Recipient;\n type: AttachmentType;\n url: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n url: options.url,\n },\n },\n },\n }, apiOptions);\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { AttachmentUploadRequest, AttachmentUploadResponse } from '../types/attachments.js';\n\nexport class AttachmentsAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async upload(\n request: AttachmentUploadRequest,\n options?: APIOptions,\n ): Promise<AttachmentUploadResponse> {\n // Format according to official API - no message wrapper needed\n const body = {\n message: {\n attachment: {\n type: request.type,\n payload: {\n url: request.url,\n is_reusable: request.is_reusable ?? true,\n },\n },\n },\n };\n\n return this.httpClient.request<AttachmentUploadResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGE_ATTACHMENTS,\n body,\n accessToken: options?.accessToken,\n });\n }\n}\n","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { \n ModerateConversationsRequest,\n ModerateConversationsResponse\n} from '../types/moderation.js';\n\nexport class ModerationAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Moderate conversations with specified actions\n * Up to 10 user IDs and up to 2 actions per request\n */\n async moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse> {\n return this.httpClient.request<ModerateConversationsResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MODERATE_CONVERSATIONS,\n body: request,\n accessToken: options?.accessToken,\n });\n }\n\n /**\n * Block a user from messaging the page\n * Prevents messaging but user can still interact with page content on Facebook\n */\n async blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds) \n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user'],\n }, options);\n }\n\n /**\n * Unblock a user to allow messaging again\n */\n async unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unblock_user'],\n }, options);\n }\n\n /**\n * Ban a user from both messaging and Facebook interactions\n * More restrictive than blocking - prevents all interactions\n * Note: Cannot ban user who was unbanned in last 48 hours\n */\n async banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['ban_user'],\n }, options);\n }\n\n /**\n * Unban a user to restore all interactions\n * Note: Banned user cannot be unblocked, they must be unbanned first\n */\n async unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unban_user'],\n }, options);\n }\n\n /**\n * Move conversation to spam folder in Meta Business Suite Inbox\n */\n async moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['move_to_spam'],\n }, options);\n }\n\n /**\n * Block user and move to spam (common moderation action)\n */\n async blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user', 'move_to_spam'],\n }, options);\n }\n}","import { TEMPLATE_LIMITS } from '../core/constants.js';\nimport type { Button, GenericTemplateElement, MediaTemplateElement } from '../types/templates.js';\n\nexport class TemplateValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TemplateValidationError';\n }\n}\n\nexport function validateGenericTemplate(elements: GenericTemplateElement[]): void {\n if (elements.length === 0) {\n throw new TemplateValidationError('Generic template must have at least 1 element');\n }\n\n if (elements.length > TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX) {\n throw new TemplateValidationError(\n `Generic template cannot have more than ${TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX} elements`\n );\n }\n\n elements.forEach((element, index) => {\n validateGenericElement(element, index);\n });\n}\n\nexport function validateGenericElement(element: GenericTemplateElement, index: number): void {\n if (!element.title || element.title.trim() === '') {\n throw new TemplateValidationError(`Element ${index}: title is required`);\n }\n\n if (element.title.length > TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: title cannot exceed ${TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.subtitle && element.subtitle.length > TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: subtitle cannot exceed ${TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.image_url && !isHttpsUrl(element.image_url)) {\n throw new TemplateValidationError(`Element ${index}: image_url must be HTTPS`);\n }\n\n if (element.buttons) {\n validateButtons(element.buttons, `Element ${index}`);\n }\n\n // Validate that element has at least one property beyond title\n const hasAdditionalProperty = !!(\n element.subtitle ||\n element.image_url ||\n element.default_action ||\n (element.buttons && element.buttons.length > 0)\n );\n\n if (!hasAdditionalProperty) {\n throw new TemplateValidationError(\n `Element ${index}: must have at least one additional property beyond title`\n );\n }\n}\n\nexport function validateButtonTemplate(text: string, buttons: Button[]): void {\n if (!text || text.trim() === '') {\n throw new TemplateValidationError('Button template text is required');\n }\n\n if (text.length > TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS) {\n throw new TemplateValidationError(\n `Button template text cannot exceed ${TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS} characters`\n );\n }\n\n if (buttons.length === 0) {\n throw new TemplateValidationError('Button template must have at least 1 button');\n }\n\n validateButtons(buttons, 'Button template');\n}\n\nexport function validateMediaTemplate(element: MediaTemplateElement): void {\n if (!element.media_type) {\n throw new TemplateValidationError('Media template element must have media_type');\n }\n\n if (!element.url && !element.attachment_id) {\n throw new TemplateValidationError('Media template element must have either url or attachment_id');\n }\n\n if (element.url && element.attachment_id) {\n throw new TemplateValidationError(\n 'Media template element cannot have both url and attachment_id'\n );\n }\n\n if (element.url && !isHttpsUrl(element.url)) {\n throw new TemplateValidationError('Media template url must be HTTPS');\n }\n\n if (element.buttons) {\n if (element.buttons.length > TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `Media template cannot have more than ${TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT} buttons`\n );\n }\n validateButtons(element.buttons, 'Media template');\n }\n}\n\nexport function validateButtons(buttons: Button[], context: string): void {\n if (buttons.length > TEMPLATE_LIMITS.BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `${context} cannot have more than ${TEMPLATE_LIMITS.BUTTONS_MAX_COUNT} buttons`\n );\n }\n\n buttons.forEach((button, index) => {\n validateButton(button, `${context} button ${index}`);\n });\n}\n\nexport function validateButton(button: Button, context: string): void {\n if (!button.type) {\n throw new TemplateValidationError(`${context}: type is required`);\n }\n\n // Title is required for most button types (not for account_unlink)\n if (button.type !== 'account_unlink' && (!button.title || button.title.trim() === '')) {\n throw new TemplateValidationError(`${context}: title is required for ${button.type} buttons`);\n }\n\n if (button.title && button.title.length > TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: title cannot exceed ${TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS} characters`\n );\n }\n\n // Type-specific validations\n switch (button.type) {\n case 'web_url':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for web_url buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for web_url buttons`);\n }\n break;\n\n case 'postback':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for postback buttons`);\n }\n if (button.payload.length > TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: payload cannot exceed ${TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS} characters`\n );\n }\n break;\n\n case 'phone_number':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for phone_number buttons`);\n }\n // Basic phone number validation (starts with +)\n if (!button.payload.startsWith('+')) {\n throw new TemplateValidationError(\n `${context}: phone_number payload must start with + (e.g., +1234567890)`\n );\n }\n break;\n\n case 'game_play':\n // game_play buttons may have optional game_metadata\n break;\n\n case 'account_link':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for account_link buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for account_link buttons`);\n }\n break;\n\n case 'account_unlink':\n // account_unlink buttons don't require additional properties\n break;\n }\n\n // Validate webview properties for web_url buttons\n if (button.type === 'web_url' && button.messenger_extensions && button.fallback_url) {\n if (!isHttpsUrl(button.fallback_url)) {\n throw new TemplateValidationError(`${context}: fallback_url must be HTTPS`);\n }\n }\n}\n\nfunction isHttpsUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.protocol === 'https:';\n } catch {\n return false;\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { Recipient, SendMessageRequest, MessagingType } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport { validateGenericTemplate, validateButtonTemplate, validateMediaTemplate } from '../utils/validators.js';\nimport type {\n GenericTemplatePayload,\n ButtonTemplatePayload,\n MediaTemplatePayload,\n ProductTemplatePayload,\n GenericTemplateElement,\n Button,\n MediaTemplateElement,\n ProductTemplateElement,\n} from '../types/templates.js';\n\nexport class TemplatesAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async generic(options: {\n recipient: Recipient;\n elements: GenericTemplateElement[];\n messaging_type?: MessagingType;\n image_aspect_ratio?: 'horizontal' | 'square';\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateGenericTemplate(options.elements);\n\n const payload: GenericTemplatePayload = {\n template_type: 'generic',\n elements: options.elements,\n image_aspect_ratio: options.image_aspect_ratio,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async button(options: {\n recipient: Recipient;\n text: string;\n buttons: Button[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateButtonTemplate(options.text, options.buttons);\n\n const payload: ButtonTemplatePayload = {\n template_type: 'button',\n text: options.text,\n buttons: options.buttons,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async media(options: {\n recipient: Recipient;\n element: MediaTemplateElement;\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateMediaTemplate(options.element);\n\n const payload: MediaTemplatePayload = {\n template_type: 'media',\n elements: [options.element],\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async product(options: {\n recipient: Recipient;\n elements: ProductTemplateElement[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n const payload: ProductTemplatePayload = {\n template_type: 'product',\n elements: options.elements,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport type { \n GetProfileRequest,\n UserProfile\n} from '../types/profile.js';\n\nexport class ProfileAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Get user profile information using PSID\n * Requires \"Advanced User Profile Access\" feature\n */\n async get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile> {\n const { psid, fields = ['first_name', 'last_name'] } = request;\n \n const queryParams = new URLSearchParams({\n fields: fields.join(','),\n });\n\n return this.httpClient.request<UserProfile>({\n method: 'GET',\n path: `/${psid}?${queryParams.toString()}`,\n body: undefined,\n accessToken: options?.accessToken,\n });\n }\n\n /**\n * Get user profile with default fields (first_name, last_name, profile_pic)\n */\n async getBasic(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name', 'profile_pic'],\n }, options);\n }\n\n /**\n * Get comprehensive user profile with all available fields\n */\n async getFull(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['id', 'name', 'first_name', 'last_name', 'profile_pic', 'locale', 'timezone', 'gender'],\n }, options);\n }\n\n /**\n * Get user's name (first_name and last_name)\n */\n async getName(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name'],\n }, options);\n }\n\n /**\n * Get user's profile picture URL\n */\n async getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['profile_pic'],\n }, options);\n }\n}","import { HTTPClient, type ClientConfig } from './core/http-client.js';\nimport { DEFAULT_API_VERSION } from './core/constants.js';\nimport { MessengerConfigError } from './core/errors.js';\nimport { SendAPI } from './resources/send.js';\nimport { AttachmentsAPI } from './resources/attachments.js';\nimport { ModerationAPI } from './resources/moderation.js';\nimport { TemplatesAPI } from './resources/templates.js';\nimport { ProfileAPI } from './resources/profile.js';\n\nexport interface MessengerConfig {\n accessToken?: string;\n version?: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class Messenger {\n public readonly send: SendAPI;\n public readonly attachments: AttachmentsAPI;\n public readonly moderation: ModerationAPI;\n public readonly templates: TemplatesAPI;\n public readonly profile: ProfileAPI;\n\n private readonly httpClient: HTTPClient;\n\n constructor(config: MessengerConfig = {}) {\n this.validateConfig(config);\n\n const clientConfig: ClientConfig = {\n accessToken: config.accessToken,\n version: config.version || DEFAULT_API_VERSION,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n };\n\n this.httpClient = new HTTPClient(clientConfig);\n\n // Initialize API resources\n this.send = new SendAPI(this.httpClient);\n this.attachments = new AttachmentsAPI(this.httpClient);\n this.moderation = new ModerationAPI(this.httpClient);\n this.templates = new TemplatesAPI(this.httpClient);\n this.profile = new ProfileAPI(this.httpClient);\n }\n\n private validateConfig(config: MessengerConfig): void {\n if (config.accessToken !== undefined) {\n if (typeof config.accessToken !== 'string' || config.accessToken.trim() === '') {\n throw new MessengerConfigError('Access token must be a non-empty string');\n }\n }\n\n if (config.version && typeof config.version !== 'string') {\n throw new MessengerConfigError('API version must be a string');\n }\n\n if (config.timeout && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new MessengerConfigError('Timeout must be a positive number');\n }\n\n if (config.maxRetries && (typeof config.maxRetries !== 'number' || config.maxRetries < 0)) {\n throw new MessengerConfigError('Max retries must be a non-negative number');\n }\n }\n}"]}
package/dist/index.d.cts CHANGED
@@ -1,15 +1,19 @@
1
1
  interface ClientConfig {
2
- accessToken: string;
2
+ accessToken?: string;
3
3
  version: string;
4
4
  baseUrl?: string;
5
5
  timeout?: number;
6
6
  maxRetries?: number;
7
7
  }
8
+ interface APIOptions {
9
+ accessToken?: string;
10
+ }
8
11
  interface RequestOptions {
9
12
  method: 'GET' | 'POST' | 'DELETE';
10
13
  path: string;
11
14
  body?: any;
12
15
  query?: Record<string, string | number | boolean>;
16
+ accessToken?: string;
13
17
  }
14
18
  declare class HTTPClient {
15
19
  private readonly config;
@@ -97,11 +101,11 @@ interface AttachmentUploadResponse {
97
101
  declare class SendAPI {
98
102
  private httpClient;
99
103
  constructor(httpClient: HTTPClient);
100
- message(request: SendMessageRequest): Promise<SendMessageResponse>;
101
- action(recipientId: string, action: SenderAction): Promise<SendMessageResponse>;
102
- typingOn(recipientId: string): Promise<SendMessageResponse>;
103
- typingOff(recipientId: string): Promise<SendMessageResponse>;
104
- markSeen(recipientId: string): Promise<SendMessageResponse>;
104
+ message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse>;
105
+ action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse>;
106
+ typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
107
+ typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
108
+ markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
105
109
  /**
106
110
  * Send an attachment using a previously uploaded attachment_id
107
111
  */
@@ -110,7 +114,7 @@ declare class SendAPI {
110
114
  type: AttachmentType;
111
115
  attachment_id: string;
112
116
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
113
- }): Promise<SendMessageResponse>;
117
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
114
118
  /**
115
119
  * Upload and send an attachment from URL in a single request
116
120
  */
@@ -119,13 +123,13 @@ declare class SendAPI {
119
123
  type: AttachmentType;
120
124
  url: string;
121
125
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
122
- }): Promise<SendMessageResponse>;
126
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
123
127
  }
124
128
 
125
129
  declare class AttachmentsAPI {
126
130
  private httpClient;
127
131
  constructor(httpClient: HTTPClient);
128
- upload(request: AttachmentUploadRequest): Promise<AttachmentUploadResponse>;
132
+ upload(request: AttachmentUploadRequest, options?: APIOptions): Promise<AttachmentUploadResponse>;
129
133
  }
130
134
 
131
135
  interface UserId {
@@ -147,35 +151,35 @@ declare class ModerationAPI {
147
151
  * Moderate conversations with specified actions
148
152
  * Up to 10 user IDs and up to 2 actions per request
149
153
  */
150
- moderate(request: ModerateConversationsRequest): Promise<ModerateConversationsResponse>;
154
+ moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse>;
151
155
  /**
152
156
  * Block a user from messaging the page
153
157
  * Prevents messaging but user can still interact with page content on Facebook
154
158
  */
155
- blockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
159
+ blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
156
160
  /**
157
161
  * Unblock a user to allow messaging again
158
162
  */
159
- unblockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
163
+ unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
160
164
  /**
161
165
  * Ban a user from both messaging and Facebook interactions
162
166
  * More restrictive than blocking - prevents all interactions
163
167
  * Note: Cannot ban user who was unbanned in last 48 hours
164
168
  */
165
- banUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
169
+ banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
166
170
  /**
167
171
  * Unban a user to restore all interactions
168
172
  * Note: Banned user cannot be unblocked, they must be unbanned first
169
173
  */
170
- unbanUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
174
+ unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
171
175
  /**
172
176
  * Move conversation to spam folder in Meta Business Suite Inbox
173
177
  */
174
- moveToSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
178
+ moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
175
179
  /**
176
180
  * Block user and move to spam (common moderation action)
177
181
  */
178
- blockAndSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
182
+ blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
179
183
  }
180
184
 
181
185
  interface Button {
@@ -246,7 +250,7 @@ declare class TemplatesAPI {
246
250
  image_aspect_ratio?: 'horizontal' | 'square';
247
251
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
248
252
  tag?: string;
249
- }): Promise<SendMessageResponse>;
253
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
250
254
  button(options: {
251
255
  recipient: Recipient;
252
256
  text: string;
@@ -254,25 +258,67 @@ declare class TemplatesAPI {
254
258
  messaging_type?: MessagingType;
255
259
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
256
260
  tag?: string;
257
- }): Promise<SendMessageResponse>;
261
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
258
262
  media(options: {
259
263
  recipient: Recipient;
260
264
  element: MediaTemplateElement;
261
265
  messaging_type?: MessagingType;
262
266
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
263
267
  tag?: string;
264
- }): Promise<SendMessageResponse>;
268
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
265
269
  product(options: {
266
270
  recipient: Recipient;
267
271
  elements: ProductTemplateElement[];
268
272
  messaging_type?: MessagingType;
269
273
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
270
274
  tag?: string;
271
- }): Promise<SendMessageResponse>;
275
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
276
+ }
277
+
278
+ type ProfileField = 'id' | 'name' | 'first_name' | 'last_name' | 'profile_pic' | 'locale' | 'timezone' | 'gender';
279
+ interface GetProfileRequest {
280
+ psid: string;
281
+ fields?: ProfileField[];
282
+ }
283
+ interface UserProfile {
284
+ id?: string;
285
+ name?: string;
286
+ first_name?: string;
287
+ last_name?: string;
288
+ profile_pic?: string;
289
+ locale?: string;
290
+ timezone?: number;
291
+ gender?: string;
292
+ }
293
+
294
+ declare class ProfileAPI {
295
+ private httpClient;
296
+ constructor(httpClient: HTTPClient);
297
+ /**
298
+ * Get user profile information using PSID
299
+ * Requires "Advanced User Profile Access" feature
300
+ */
301
+ get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile>;
302
+ /**
303
+ * Get user profile with default fields (first_name, last_name, profile_pic)
304
+ */
305
+ getBasic(psid: string, options?: APIOptions): Promise<UserProfile>;
306
+ /**
307
+ * Get comprehensive user profile with all available fields
308
+ */
309
+ getFull(psid: string, options?: APIOptions): Promise<UserProfile>;
310
+ /**
311
+ * Get user's name (first_name and last_name)
312
+ */
313
+ getName(psid: string, options?: APIOptions): Promise<UserProfile>;
314
+ /**
315
+ * Get user's profile picture URL
316
+ */
317
+ getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile>;
272
318
  }
273
319
 
274
320
  interface MessengerConfig {
275
- accessToken: string;
321
+ accessToken?: string;
276
322
  version?: string;
277
323
  baseUrl?: string;
278
324
  timeout?: number;
@@ -283,8 +329,9 @@ declare class Messenger {
283
329
  readonly attachments: AttachmentsAPI;
284
330
  readonly moderation: ModerationAPI;
285
331
  readonly templates: TemplatesAPI;
332
+ readonly profile: ProfileAPI;
286
333
  private readonly httpClient;
287
- constructor(config: MessengerConfig);
334
+ constructor(config?: MessengerConfig);
288
335
  private validateConfig;
289
336
  }
290
337
 
@@ -338,4 +385,4 @@ declare const TEMPLATE_LIMITS: {
338
385
  readonly MEDIA_BUTTONS_MAX_COUNT: 3;
339
386
  };
340
387
 
341
- export { ATTACHMENT_LIMITS, type AttachmentType, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsAPI, type Button, type ButtonTemplatePayload, type DefaultAction, type ErrorResponse, type GenericTemplateElement, type GenericTemplatePayload, MESSAGE_LIMITS, type MediaTemplateElement, type MediaTemplatePayload, type Message, MessageValidationError, type MessagingType, Messenger, MessengerAPIError, type MessengerConfig, MessengerConfigError, type MessengerError, MessengerNetworkError, MessengerTimeoutError, type ModerateConversationsRequest, type ModerateConversationsResponse, ModerationAPI, type ModerationAction, type ProductTemplateElement, type ProductTemplatePayload, type QuickReply, type Recipient, SendAPI, type SendMessageRequest, type SendMessageResponse, type SenderAction, TEMPLATE_LIMITS, TemplateValidationError, TemplatesAPI, type UserId };
388
+ export { ATTACHMENT_LIMITS, type AttachmentType, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsAPI, type Button, type ButtonTemplatePayload, type DefaultAction, type ErrorResponse, type GenericTemplateElement, type GenericTemplatePayload, type GetProfileRequest, MESSAGE_LIMITS, type MediaTemplateElement, type MediaTemplatePayload, type Message, MessageValidationError, type MessagingType, Messenger, MessengerAPIError, type MessengerConfig, MessengerConfigError, type MessengerError, MessengerNetworkError, MessengerTimeoutError, type ModerateConversationsRequest, type ModerateConversationsResponse, ModerationAPI, type ModerationAction, type ProductTemplateElement, type ProductTemplatePayload, ProfileAPI, type ProfileField, type QuickReply, type Recipient, SendAPI, type SendMessageRequest, type SendMessageResponse, type SenderAction, TEMPLATE_LIMITS, TemplateValidationError, TemplatesAPI, type UserId, type UserProfile };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,19 @@
1
1
  interface ClientConfig {
2
- accessToken: string;
2
+ accessToken?: string;
3
3
  version: string;
4
4
  baseUrl?: string;
5
5
  timeout?: number;
6
6
  maxRetries?: number;
7
7
  }
8
+ interface APIOptions {
9
+ accessToken?: string;
10
+ }
8
11
  interface RequestOptions {
9
12
  method: 'GET' | 'POST' | 'DELETE';
10
13
  path: string;
11
14
  body?: any;
12
15
  query?: Record<string, string | number | boolean>;
16
+ accessToken?: string;
13
17
  }
14
18
  declare class HTTPClient {
15
19
  private readonly config;
@@ -97,11 +101,11 @@ interface AttachmentUploadResponse {
97
101
  declare class SendAPI {
98
102
  private httpClient;
99
103
  constructor(httpClient: HTTPClient);
100
- message(request: SendMessageRequest): Promise<SendMessageResponse>;
101
- action(recipientId: string, action: SenderAction): Promise<SendMessageResponse>;
102
- typingOn(recipientId: string): Promise<SendMessageResponse>;
103
- typingOff(recipientId: string): Promise<SendMessageResponse>;
104
- markSeen(recipientId: string): Promise<SendMessageResponse>;
104
+ message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse>;
105
+ action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse>;
106
+ typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
107
+ typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
108
+ markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
105
109
  /**
106
110
  * Send an attachment using a previously uploaded attachment_id
107
111
  */
@@ -110,7 +114,7 @@ declare class SendAPI {
110
114
  type: AttachmentType;
111
115
  attachment_id: string;
112
116
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
113
- }): Promise<SendMessageResponse>;
117
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
114
118
  /**
115
119
  * Upload and send an attachment from URL in a single request
116
120
  */
@@ -119,13 +123,13 @@ declare class SendAPI {
119
123
  type: AttachmentType;
120
124
  url: string;
121
125
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
122
- }): Promise<SendMessageResponse>;
126
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
123
127
  }
124
128
 
125
129
  declare class AttachmentsAPI {
126
130
  private httpClient;
127
131
  constructor(httpClient: HTTPClient);
128
- upload(request: AttachmentUploadRequest): Promise<AttachmentUploadResponse>;
132
+ upload(request: AttachmentUploadRequest, options?: APIOptions): Promise<AttachmentUploadResponse>;
129
133
  }
130
134
 
131
135
  interface UserId {
@@ -147,35 +151,35 @@ declare class ModerationAPI {
147
151
  * Moderate conversations with specified actions
148
152
  * Up to 10 user IDs and up to 2 actions per request
149
153
  */
150
- moderate(request: ModerateConversationsRequest): Promise<ModerateConversationsResponse>;
154
+ moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse>;
151
155
  /**
152
156
  * Block a user from messaging the page
153
157
  * Prevents messaging but user can still interact with page content on Facebook
154
158
  */
155
- blockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
159
+ blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
156
160
  /**
157
161
  * Unblock a user to allow messaging again
158
162
  */
159
- unblockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
163
+ unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
160
164
  /**
161
165
  * Ban a user from both messaging and Facebook interactions
162
166
  * More restrictive than blocking - prevents all interactions
163
167
  * Note: Cannot ban user who was unbanned in last 48 hours
164
168
  */
165
- banUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
169
+ banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
166
170
  /**
167
171
  * Unban a user to restore all interactions
168
172
  * Note: Banned user cannot be unblocked, they must be unbanned first
169
173
  */
170
- unbanUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
174
+ unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
171
175
  /**
172
176
  * Move conversation to spam folder in Meta Business Suite Inbox
173
177
  */
174
- moveToSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
178
+ moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
175
179
  /**
176
180
  * Block user and move to spam (common moderation action)
177
181
  */
178
- blockAndSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
182
+ blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
179
183
  }
180
184
 
181
185
  interface Button {
@@ -246,7 +250,7 @@ declare class TemplatesAPI {
246
250
  image_aspect_ratio?: 'horizontal' | 'square';
247
251
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
248
252
  tag?: string;
249
- }): Promise<SendMessageResponse>;
253
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
250
254
  button(options: {
251
255
  recipient: Recipient;
252
256
  text: string;
@@ -254,25 +258,67 @@ declare class TemplatesAPI {
254
258
  messaging_type?: MessagingType;
255
259
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
256
260
  tag?: string;
257
- }): Promise<SendMessageResponse>;
261
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
258
262
  media(options: {
259
263
  recipient: Recipient;
260
264
  element: MediaTemplateElement;
261
265
  messaging_type?: MessagingType;
262
266
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
263
267
  tag?: string;
264
- }): Promise<SendMessageResponse>;
268
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
265
269
  product(options: {
266
270
  recipient: Recipient;
267
271
  elements: ProductTemplateElement[];
268
272
  messaging_type?: MessagingType;
269
273
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
270
274
  tag?: string;
271
- }): Promise<SendMessageResponse>;
275
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
276
+ }
277
+
278
+ type ProfileField = 'id' | 'name' | 'first_name' | 'last_name' | 'profile_pic' | 'locale' | 'timezone' | 'gender';
279
+ interface GetProfileRequest {
280
+ psid: string;
281
+ fields?: ProfileField[];
282
+ }
283
+ interface UserProfile {
284
+ id?: string;
285
+ name?: string;
286
+ first_name?: string;
287
+ last_name?: string;
288
+ profile_pic?: string;
289
+ locale?: string;
290
+ timezone?: number;
291
+ gender?: string;
292
+ }
293
+
294
+ declare class ProfileAPI {
295
+ private httpClient;
296
+ constructor(httpClient: HTTPClient);
297
+ /**
298
+ * Get user profile information using PSID
299
+ * Requires "Advanced User Profile Access" feature
300
+ */
301
+ get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile>;
302
+ /**
303
+ * Get user profile with default fields (first_name, last_name, profile_pic)
304
+ */
305
+ getBasic(psid: string, options?: APIOptions): Promise<UserProfile>;
306
+ /**
307
+ * Get comprehensive user profile with all available fields
308
+ */
309
+ getFull(psid: string, options?: APIOptions): Promise<UserProfile>;
310
+ /**
311
+ * Get user's name (first_name and last_name)
312
+ */
313
+ getName(psid: string, options?: APIOptions): Promise<UserProfile>;
314
+ /**
315
+ * Get user's profile picture URL
316
+ */
317
+ getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile>;
272
318
  }
273
319
 
274
320
  interface MessengerConfig {
275
- accessToken: string;
321
+ accessToken?: string;
276
322
  version?: string;
277
323
  baseUrl?: string;
278
324
  timeout?: number;
@@ -283,8 +329,9 @@ declare class Messenger {
283
329
  readonly attachments: AttachmentsAPI;
284
330
  readonly moderation: ModerationAPI;
285
331
  readonly templates: TemplatesAPI;
332
+ readonly profile: ProfileAPI;
286
333
  private readonly httpClient;
287
- constructor(config: MessengerConfig);
334
+ constructor(config?: MessengerConfig);
288
335
  private validateConfig;
289
336
  }
290
337
 
@@ -338,4 +385,4 @@ declare const TEMPLATE_LIMITS: {
338
385
  readonly MEDIA_BUTTONS_MAX_COUNT: 3;
339
386
  };
340
387
 
341
- export { ATTACHMENT_LIMITS, type AttachmentType, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsAPI, type Button, type ButtonTemplatePayload, type DefaultAction, type ErrorResponse, type GenericTemplateElement, type GenericTemplatePayload, MESSAGE_LIMITS, type MediaTemplateElement, type MediaTemplatePayload, type Message, MessageValidationError, type MessagingType, Messenger, MessengerAPIError, type MessengerConfig, MessengerConfigError, type MessengerError, MessengerNetworkError, MessengerTimeoutError, type ModerateConversationsRequest, type ModerateConversationsResponse, ModerationAPI, type ModerationAction, type ProductTemplateElement, type ProductTemplatePayload, type QuickReply, type Recipient, SendAPI, type SendMessageRequest, type SendMessageResponse, type SenderAction, TEMPLATE_LIMITS, TemplateValidationError, TemplatesAPI, type UserId };
388
+ export { ATTACHMENT_LIMITS, type AttachmentType, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsAPI, type Button, type ButtonTemplatePayload, type DefaultAction, type ErrorResponse, type GenericTemplateElement, type GenericTemplatePayload, type GetProfileRequest, MESSAGE_LIMITS, type MediaTemplateElement, type MediaTemplatePayload, type Message, MessageValidationError, type MessagingType, Messenger, MessengerAPIError, type MessengerConfig, MessengerConfigError, type MessengerError, MessengerNetworkError, MessengerTimeoutError, type ModerateConversationsRequest, type ModerateConversationsResponse, ModerationAPI, type ModerationAction, type ProductTemplateElement, type ProductTemplatePayload, ProfileAPI, type ProfileField, type QuickReply, type Recipient, SendAPI, type SendMessageRequest, type SendMessageResponse, type SenderAction, TEMPLATE_LIMITS, TemplateValidationError, TemplatesAPI, type UserId, type UserProfile };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- var f="v23.0",R="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},E={TEXT_MESSAGE_MAX_CHARS:2e3},U={IMAGE_MAX_SIZE:8*1024*1024,OTHER_MAX_SIZE:25*1024*1024,VIDEO_TIMEOUT:75,OTHER_TIMEOUT:10},o={GENERIC_ELEMENTS_MAX:10,GENERIC_TITLE_MAX_CHARS:80,GENERIC_SUBTITLE_MAX_CHARS:80,BUTTON_TEXT_MAX_CHARS:640,BUTTONS_MAX_COUNT:3,BUTTON_TITLE_MAX_CHARS:20,POSTBACK_PAYLOAD_MAX_CHARS:1e3,MEDIA_ELEMENTS_COUNT:1,MEDIA_BUTTONS_MAX_COUNT:3};var c=class extends Error{code;type;subcode;fbtrace_id;statusCode;response;constructor(e,s,r){super(e.message),this.name="MessengerAPIError",this.code=e.code,this.type=e.type,this.subcode=e.error_subcode,this.fbtrace_id=e.fbtrace_id,this.statusCode=s,this.response=r;}},l=class extends Error{cause;constructor(e,s){super(e),this.name="MessengerNetworkError",this.cause=s;}},u=class extends Error{timeout;constructor(e){super(`Request timed out after ${e}ms`),this.name="MessengerTimeoutError",this.timeout=e;}},m=class extends Error{constructor(e){super(e),this.name="MessengerConfigError";}};var S=class{config;constructor(e){this.config={accessToken:e.accessToken,version:e.version,baseUrl:e.baseUrl||R,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query),r;for(let i=0;i<=this.config.maxRetries;i++)try{let a=await this.makeRequest(s,e);return await this.handleResponse(a)}catch(a){if(r=a,a instanceof c&&a.statusCode>=400&&a.statusCode<500||i===this.config.maxRetries)throw a;await this.delay(1e3*(i+1));}throw r||new Error("Unknown error occurred")}buildUrl(e,s){let r=new URL(`${this.config.baseUrl}/${this.config.version}${e}`);return r.searchParams.append("access_token",this.config.accessToken),s&&Object.entries(s).forEach(([i,a])=>{r.searchParams.append(i,String(a));}),r.toString()}async makeRequest(e,s){let r=new AbortController,i=setTimeout(()=>r.abort(),this.config.timeout);try{let a={method:s.method,headers:{"Content-Type":"application/json"},signal:r.signal};return s.body&&(a.body=JSON.stringify(s.body)),await fetch(e,a)}catch(a){throw a instanceof Error?a.name==="AbortError"?new u(this.config.timeout):new l(`Network request failed: ${a.message}`,a):a}finally{clearTimeout(i);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let i=await e.json();throw new c(i.error,e.status,i)}else {let i=await e.text();throw new c({message:i||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,i)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var T=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function P(t){if(!t||t.trim()==="")throw new T("Text message cannot be empty");if(t.length>E.TEXT_MESSAGE_MAX_CHARS)throw new T(`Text message cannot exceed ${E.TEXT_MESSAGE_MAX_CHARS} characters`)}var d=class{constructor(e){this.httpClient=e;}async message(e){return e.message?.text&&P(e.message.text),this.httpClient.request({method:"POST",path:p.MESSAGES,body:e})}async action(e,s){return this.httpClient.request({method:"POST",path:p.MESSAGES,body:{recipient:{id:e},messaging_type:"RESPONSE",sender_action:s}})}async typingOn(e){return this.action(e,"typing_on")}async typingOff(e){return this.action(e,"typing_off")}async markSeen(e){return this.action(e,"mark_seen")}async attachment(e){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{attachment_id:e.attachment_id}}}})}async attachmentFromUrl(e){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{url:e.url}}}})}};var _=class{constructor(e){this.httpClient=e;}async upload(e){let s={message:{attachment:{type:e.type,payload:{url:e.url,is_reusable:e.is_reusable??true}}}};return this.httpClient.request({method:"POST",path:p.MESSAGE_ATTACHMENTS,body:s})}};var h=class{constructor(e){this.httpClient=e;}async moderate(e){return this.httpClient.request({method:"POST",path:p.MODERATE_CONVERSATIONS,body:e})}async blockUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["block_user"]})}async unblockUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["unblock_user"]})}async banUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["ban_user"]})}async unbanUser(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["unban_user"]})}async moveToSpam(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["move_to_spam"]})}async blockAndSpam(e){let s=Array.isArray(e)?e.map(r=>({id:r})):[{id:e}];return this.moderate({user_ids:s,actions:["block_user","move_to_spam"]})}};var n=class extends Error{constructor(e){super(e),this.name="TemplateValidationError";}};function b(t){if(t.length===0)throw new n("Generic template must have at least 1 element");if(t.length>o.GENERIC_ELEMENTS_MAX)throw new n(`Generic template cannot have more than ${o.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{I(e,s);});}function I(t,e){if(!t.title||t.title.trim()==="")throw new n(`Element ${e}: title is required`);if(t.title.length>o.GENERIC_TITLE_MAX_CHARS)throw new n(`Element ${e}: title cannot exceed ${o.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>o.GENERIC_SUBTITLE_MAX_CHARS)throw new n(`Element ${e}: subtitle cannot exceed ${o.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!y(t.image_url))throw new n(`Element ${e}: image_url must be HTTPS`);if(t.buttons&&A(t.buttons,`Element ${e}`),!!!(t.subtitle||t.image_url||t.default_action||t.buttons&&t.buttons.length>0))throw new n(`Element ${e}: must have at least one additional property beyond title`)}function w(t,e){if(!t||t.trim()==="")throw new n("Button template text is required");if(t.length>o.BUTTON_TEXT_MAX_CHARS)throw new n(`Button template text cannot exceed ${o.BUTTON_TEXT_MAX_CHARS} characters`);if(e.length===0)throw new n("Button template must have at least 1 button");A(e,"Button template");}function C(t){if(!t.media_type)throw new n("Media template element must have media_type");if(!t.url&&!t.attachment_id)throw new n("Media template element must have either url or attachment_id");if(t.url&&t.attachment_id)throw new n("Media template element cannot have both url and attachment_id");if(t.url&&!y(t.url))throw new n("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>o.MEDIA_BUTTONS_MAX_COUNT)throw new n(`Media template cannot have more than ${o.MEDIA_BUTTONS_MAX_COUNT} buttons`);A(t.buttons,"Media template");}}function A(t,e){if(t.length>o.BUTTONS_MAX_COUNT)throw new n(`${e} cannot have more than ${o.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{x(s,`${e} button ${r}`);});}function x(t,e){if(!t.type)throw new n(`${e}: type is required`);if(t.type!=="account_unlink"&&(!t.title||t.title.trim()===""))throw new n(`${e}: title is required for ${t.type} buttons`);if(t.title&&t.title.length>o.BUTTON_TITLE_MAX_CHARS)throw new n(`${e}: title cannot exceed ${o.BUTTON_TITLE_MAX_CHARS} characters`);switch(t.type){case "web_url":if(!t.url)throw new n(`${e}: url is required for web_url buttons`);if(!y(t.url))throw new n(`${e}: url must be HTTPS for web_url buttons`);break;case "postback":if(!t.payload)throw new n(`${e}: payload is required for postback buttons`);if(t.payload.length>o.POSTBACK_PAYLOAD_MAX_CHARS)throw new n(`${e}: payload cannot exceed ${o.POSTBACK_PAYLOAD_MAX_CHARS} characters`);break;case "phone_number":if(!t.payload)throw new n(`${e}: payload is required for phone_number buttons`);if(!t.payload.startsWith("+"))throw new n(`${e}: phone_number payload must start with + (e.g., +1234567890)`);break;case "game_play":break;case "account_link":if(!t.url)throw new n(`${e}: url is required for account_link buttons`);if(!y(t.url))throw new n(`${e}: url must be HTTPS for account_link buttons`);break;}if(t.type==="web_url"&&t.messenger_extensions&&t.fallback_url&&!y(t.fallback_url))throw new n(`${e}: fallback_url must be HTTPS`)}function y(t){try{return new URL(t).protocol==="https:"}catch{return false}}var g=class{constructor(e){this.httpClient=e;}async generic(e){b(e.elements);let s={template_type:"generic",elements:e.elements,image_aspect_ratio:e.image_aspect_ratio},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}async button(e){w(e.text,e.buttons);let s={template_type:"button",text:e.text,buttons:e.buttons},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}async media(e){C(e.element);let s={template_type:"media",elements:[e.element]},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}async product(e){let s={template_type:"product",elements:e.elements},r={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:s}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:r})}};var M=class{send;attachments;moderation;templates;httpClient;constructor(e){this.validateConfig(e);let s={accessToken:e.accessToken,version:e.version||f,baseUrl:e.baseUrl,timeout:e.timeout,maxRetries:e.maxRetries};this.httpClient=new S(s),this.send=new d(this.httpClient),this.attachments=new _(this.httpClient),this.moderation=new h(this.httpClient),this.templates=new g(this.httpClient);}validateConfig(e){if(!e.accessToken)throw new m("Access token is required");if(typeof e.accessToken!="string"||e.accessToken.trim()==="")throw new m("Access token must be a non-empty string");if(e.version&&typeof e.version!="string")throw new m("API version must be a string");if(e.timeout&&(typeof e.timeout!="number"||e.timeout<=0))throw new m("Timeout must be a positive number");if(e.maxRetries&&(typeof e.maxRetries!="number"||e.maxRetries<0))throw new m("Max retries must be a non-negative number")}};
2
- export{U as ATTACHMENT_LIMITS,_ as AttachmentsAPI,E as MESSAGE_LIMITS,T as MessageValidationError,M as Messenger,c as MessengerAPIError,m as MessengerConfigError,l as MessengerNetworkError,u as MessengerTimeoutError,h as ModerationAPI,d as SendAPI,o as TEMPLATE_LIMITS,n as TemplateValidationError,g as TemplatesAPI};//# sourceMappingURL=index.js.map
1
+ var R="v23.0",b="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},A={TEXT_MESSAGE_MAX_CHARS:2e3},v={IMAGE_MAX_SIZE:8*1024*1024,OTHER_MAX_SIZE:25*1024*1024,VIDEO_TIMEOUT:75,OTHER_TIMEOUT:10},i={GENERIC_ELEMENTS_MAX:10,GENERIC_TITLE_MAX_CHARS:80,GENERIC_SUBTITLE_MAX_CHARS:80,BUTTON_TEXT_MAX_CHARS:640,BUTTONS_MAX_COUNT:3,BUTTON_TITLE_MAX_CHARS:20,POSTBACK_PAYLOAD_MAX_CHARS:1e3,MEDIA_ELEMENTS_COUNT:1,MEDIA_BUTTONS_MAX_COUNT:3};var m=class extends Error{code;type;subcode;fbtrace_id;statusCode;response;constructor(e,s,r){super(e.message),this.name="MessengerAPIError",this.code=e.code,this.type=e.type,this.subcode=e.error_subcode,this.fbtrace_id=e.fbtrace_id,this.statusCode=s,this.response=r;}},l=class extends Error{cause;constructor(e,s){super(e),this.name="MessengerNetworkError",this.cause=s;}},T=class extends Error{timeout;constructor(e){super(`Request timed out after ${e}ms`),this.name="MessengerTimeoutError",this.timeout=e;}},c=class extends Error{constructor(e){super(e),this.name="MessengerConfigError";}};var f=class{config;constructor(e){this.config={accessToken:e.accessToken,version:e.version,baseUrl:e.baseUrl||b,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query,e.accessToken),r;for(let n=0;n<=this.config.maxRetries;n++)try{let a=await this.makeRequest(s,e);return await this.handleResponse(a)}catch(a){if(r=a,a instanceof m&&a.statusCode>=400&&a.statusCode<500||n===this.config.maxRetries)throw a;await this.delay(1e3*(n+1));}throw r||new Error("Unknown error occurred")}buildUrl(e,s,r){let n=new URL(`${this.config.baseUrl}/${this.config.version}${e}`),a=r||this.config.accessToken;if(!a)throw new Error("Access token is required. Provide it in constructor or method options.");return n.searchParams.append("access_token",a),s&&Object.entries(s).forEach(([M,U])=>{n.searchParams.append(M,String(U));}),n.toString()}async makeRequest(e,s){let r=new AbortController,n=setTimeout(()=>r.abort(),this.config.timeout);try{let a={method:s.method,headers:{"Content-Type":"application/json"},signal:r.signal};return s.body&&(a.body=JSON.stringify(s.body)),await fetch(e,a)}catch(a){throw a instanceof Error?a.name==="AbortError"?new T(this.config.timeout):new l(`Network request failed: ${a.message}`,a):a}finally{clearTimeout(n);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let n=await e.json();throw new m(n.error,e.status,n)}else {let n=await e.text();throw new m({message:n||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,n)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var u=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function w(t){if(!t||t.trim()==="")throw new u("Text message cannot be empty");if(t.length>A.TEXT_MESSAGE_MAX_CHARS)throw new u(`Text message cannot exceed ${A.TEXT_MESSAGE_MAX_CHARS} characters`)}var d=class{constructor(e){this.httpClient=e;}async message(e,s){return e.message?.text&&w(e.message.text),this.httpClient.request({method:"POST",path:p.MESSAGES,body:e,accessToken:s?.accessToken})}async action(e,s,r){return this.httpClient.request({method:"POST",path:p.MESSAGES,body:{recipient:{id:e},messaging_type:"RESPONSE",sender_action:s},accessToken:r?.accessToken})}async typingOn(e,s){return this.action(e,"typing_on",s)}async typingOff(e,s){return this.action(e,"typing_off",s)}async markSeen(e,s){return this.action(e,"mark_seen",s)}async attachment(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{attachment_id:e.attachment_id}}}},s)}async attachmentFromUrl(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{url:e.url}}}},s)}};var h=class{constructor(e){this.httpClient=e;}async upload(e,s){let r={message:{attachment:{type:e.type,payload:{url:e.url,is_reusable:e.is_reusable??true}}}};return this.httpClient.request({method:"POST",path:p.MESSAGE_ATTACHMENTS,body:r,accessToken:s?.accessToken})}};var g=class{constructor(e){this.httpClient=e;}async moderate(e,s){return this.httpClient.request({method:"POST",path:p.MODERATE_CONVERSATIONS,body:e,accessToken:s?.accessToken})}async blockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user"]},s)}async unblockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unblock_user"]},s)}async banUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["ban_user"]},s)}async unbanUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unban_user"]},s)}async moveToSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["move_to_spam"]},s)}async blockAndSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user","move_to_spam"]},s)}};var o=class extends Error{constructor(e){super(e),this.name="TemplateValidationError";}};function C(t){if(t.length===0)throw new o("Generic template must have at least 1 element");if(t.length>i.GENERIC_ELEMENTS_MAX)throw new o(`Generic template cannot have more than ${i.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{G(e,s);});}function G(t,e){if(!t.title||t.title.trim()==="")throw new o(`Element ${e}: title is required`);if(t.title.length>i.GENERIC_TITLE_MAX_CHARS)throw new o(`Element ${e}: title cannot exceed ${i.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>i.GENERIC_SUBTITLE_MAX_CHARS)throw new o(`Element ${e}: subtitle cannot exceed ${i.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!_(t.image_url))throw new o(`Element ${e}: image_url must be HTTPS`);if(t.buttons&&P(t.buttons,`Element ${e}`),!!!(t.subtitle||t.image_url||t.default_action||t.buttons&&t.buttons.length>0))throw new o(`Element ${e}: must have at least one additional property beyond title`)}function O(t,e){if(!t||t.trim()==="")throw new o("Button template text is required");if(t.length>i.BUTTON_TEXT_MAX_CHARS)throw new o(`Button template text cannot exceed ${i.BUTTON_TEXT_MAX_CHARS} characters`);if(e.length===0)throw new o("Button template must have at least 1 button");P(e,"Button template");}function I(t){if(!t.media_type)throw new o("Media template element must have media_type");if(!t.url&&!t.attachment_id)throw new o("Media template element must have either url or attachment_id");if(t.url&&t.attachment_id)throw new o("Media template element cannot have both url and attachment_id");if(t.url&&!_(t.url))throw new o("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>i.MEDIA_BUTTONS_MAX_COUNT)throw new o(`Media template cannot have more than ${i.MEDIA_BUTTONS_MAX_COUNT} buttons`);P(t.buttons,"Media template");}}function P(t,e){if(t.length>i.BUTTONS_MAX_COUNT)throw new o(`${e} cannot have more than ${i.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{H(s,`${e} button ${r}`);});}function H(t,e){if(!t.type)throw new o(`${e}: type is required`);if(t.type!=="account_unlink"&&(!t.title||t.title.trim()===""))throw new o(`${e}: title is required for ${t.type} buttons`);if(t.title&&t.title.length>i.BUTTON_TITLE_MAX_CHARS)throw new o(`${e}: title cannot exceed ${i.BUTTON_TITLE_MAX_CHARS} characters`);switch(t.type){case "web_url":if(!t.url)throw new o(`${e}: url is required for web_url buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for web_url buttons`);break;case "postback":if(!t.payload)throw new o(`${e}: payload is required for postback buttons`);if(t.payload.length>i.POSTBACK_PAYLOAD_MAX_CHARS)throw new o(`${e}: payload cannot exceed ${i.POSTBACK_PAYLOAD_MAX_CHARS} characters`);break;case "phone_number":if(!t.payload)throw new o(`${e}: payload is required for phone_number buttons`);if(!t.payload.startsWith("+"))throw new o(`${e}: phone_number payload must start with + (e.g., +1234567890)`);break;case "game_play":break;case "account_link":if(!t.url)throw new o(`${e}: url is required for account_link buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for account_link buttons`);break;}if(t.type==="web_url"&&t.messenger_extensions&&t.fallback_url&&!_(t.fallback_url))throw new o(`${e}: fallback_url must be HTTPS`)}function _(t){try{return new URL(t).protocol==="https:"}catch{return false}}var y=class{constructor(e){this.httpClient=e;}async generic(e,s){C(e.elements);let r={template_type:"generic",elements:e.elements,image_aspect_ratio:e.image_aspect_ratio},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async button(e,s){O(e.text,e.buttons);let r={template_type:"button",text:e.text,buttons:e.buttons},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async media(e,s){I(e.element);let r={template_type:"media",elements:[e.element]},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async product(e,s){let r={template_type:"product",elements:e.elements},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}};var E=class{constructor(e){this.httpClient=e;}async get(e,s){let{psid:r,fields:n=["first_name","last_name"]}=e,a=new URLSearchParams({fields:n.join(",")});return this.httpClient.request({method:"GET",path:`/${r}?${a.toString()}`,body:void 0,accessToken:s?.accessToken})}async getBasic(e,s){return this.get({psid:e,fields:["first_name","last_name","profile_pic"]},s)}async getFull(e,s){return this.get({psid:e,fields:["id","name","first_name","last_name","profile_pic","locale","timezone","gender"]},s)}async getName(e,s){return this.get({psid:e,fields:["first_name","last_name"]},s)}async getProfilePicture(e,s){return this.get({psid:e,fields:["profile_pic"]},s)}};var S=class{send;attachments;moderation;templates;profile;httpClient;constructor(e={}){this.validateConfig(e);let s={accessToken:e.accessToken,version:e.version||R,baseUrl:e.baseUrl,timeout:e.timeout,maxRetries:e.maxRetries};this.httpClient=new f(s),this.send=new d(this.httpClient),this.attachments=new h(this.httpClient),this.moderation=new g(this.httpClient),this.templates=new y(this.httpClient),this.profile=new E(this.httpClient);}validateConfig(e){if(e.accessToken!==void 0&&(typeof e.accessToken!="string"||e.accessToken.trim()===""))throw new c("Access token must be a non-empty string");if(e.version&&typeof e.version!="string")throw new c("API version must be a string");if(e.timeout&&(typeof e.timeout!="number"||e.timeout<=0))throw new c("Timeout must be a positive number");if(e.maxRetries&&(typeof e.maxRetries!="number"||e.maxRetries<0))throw new c("Max retries must be a non-negative number")}};
2
+ export{v as ATTACHMENT_LIMITS,h as AttachmentsAPI,A as MESSAGE_LIMITS,u as MessageValidationError,S as Messenger,m as MessengerAPIError,c as MessengerConfigError,l as MessengerNetworkError,T as MessengerTimeoutError,g as ModerationAPI,E as ProfileAPI,d as SendAPI,i as TEMPLATE_LIMITS,o as TemplateValidationError,y as TemplatesAPI};//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/core/errors.ts","../src/core/http-client.ts","../src/utils/message-validators.ts","../src/resources/send.ts","../src/resources/attachments.ts","../src/resources/moderation.ts","../src/utils/validators.ts","../src/resources/templates.ts","../src/client.ts"],"names":["DEFAULT_API_VERSION","BASE_URL","API_ENDPOINTS","MESSAGE_LIMITS","ATTACHMENT_LIMITS","TEMPLATE_LIMITS","MessengerAPIError","error","statusCode","response","MessengerNetworkError","message","cause","MessengerTimeoutError","timeout","MessengerConfigError","HTTPClient","config","options","url","lastError","attempt","path","query","key","value","controller","timeoutId","fetchOptions","isJson","errorData","text","ms","resolve","MessageValidationError","validateTextMessage","SendAPI","httpClient","request","recipientId","action","AttachmentsAPI","body","ModerationAPI","userIds","user_ids","id","TemplateValidationError","validateGenericTemplate","elements","element","index","validateGenericElement","isHttpsUrl","validateButtons","validateButtonTemplate","buttons","validateMediaTemplate","context","button","validateButton","TemplatesAPI","payload","Messenger","clientConfig"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_API_VERSION = 'v23.0';\nexport const BASE_URL = 'https://graph.facebook.com';\nexport const DEFAULT_TIMEOUT = 30000; // 30 seconds\nexport const MAX_RETRY_ATTEMPTS = 3;\nexport const RETRY_DELAY_MS = 1000;\n\nexport const API_ENDPOINTS = {\n MESSAGES: '/me/messages',\n MESSAGE_ATTACHMENTS: '/me/message_attachments',\n MODERATE_CONVERSATIONS: '/me/moderate_conversations',\n PASS_THREAD_CONTROL: '/me/pass_thread_control',\n TAKE_THREAD_CONTROL: '/me/take_thread_control',\n REQUEST_THREAD_CONTROL: '/me/request_thread_control',\n} as const;\n\n// Validation constants\nexport const MESSAGE_LIMITS = {\n // Text messages\n TEXT_MESSAGE_MAX_CHARS: 2000,\n} as const;\n\nexport const ATTACHMENT_LIMITS = {\n // File size limits in bytes\n IMAGE_MAX_SIZE: 8 * 1024 * 1024, // 8MB\n OTHER_MAX_SIZE: 25 * 1024 * 1024, // 25MB (video, audio, file)\n \n // Timeout limits in seconds\n VIDEO_TIMEOUT: 75,\n OTHER_TIMEOUT: 10,\n} as const;\n\nexport const TEMPLATE_LIMITS = {\n // Generic Template\n GENERIC_ELEMENTS_MAX: 10,\n GENERIC_TITLE_MAX_CHARS: 80,\n GENERIC_SUBTITLE_MAX_CHARS: 80,\n \n // Button Template \n BUTTON_TEXT_MAX_CHARS: 640,\n BUTTONS_MAX_COUNT: 3,\n BUTTON_TITLE_MAX_CHARS: 20,\n \n // All Templates\n POSTBACK_PAYLOAD_MAX_CHARS: 1000,\n \n // Media Template\n MEDIA_ELEMENTS_COUNT: 1, // Exactly 1 element required\n MEDIA_BUTTONS_MAX_COUNT: 3,\n} as const;","import type { MessengerError } from '../types/responses.js';\n\nexport class MessengerAPIError extends Error {\n public readonly code: number;\n public readonly type: string;\n public readonly subcode?: number;\n public readonly fbtrace_id?: string;\n public readonly statusCode: number;\n public readonly response?: any;\n\n constructor(error: MessengerError, statusCode: number, response?: any) {\n super(error.message);\n this.name = 'MessengerAPIError';\n this.code = error.code;\n this.type = error.type;\n this.subcode = error.error_subcode;\n this.fbtrace_id = error.fbtrace_id;\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\nexport class MessengerNetworkError extends Error {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'MessengerNetworkError';\n this.cause = cause;\n }\n}\n\nexport class MessengerTimeoutError extends Error {\n public readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Request timed out after ${timeout}ms`);\n this.name = 'MessengerTimeoutError';\n this.timeout = timeout;\n }\n}\n\nexport class MessengerConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessengerConfigError';\n }\n}","import { BASE_URL, DEFAULT_TIMEOUT, MAX_RETRY_ATTEMPTS, RETRY_DELAY_MS } from './constants.js';\nimport { MessengerAPIError, MessengerNetworkError, MessengerTimeoutError } from './errors.js';\nimport type { ErrorResponse } from '../types/responses.js';\n\nexport interface ClientConfig {\n accessToken: string;\n version: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'DELETE';\n path: string;\n body?: any;\n query?: Record<string, string | number | boolean>;\n}\n\nexport class HTTPClient {\n private readonly config: Required<ClientConfig>;\n\n constructor(config: ClientConfig) {\n this.config = {\n accessToken: config.accessToken,\n version: config.version,\n baseUrl: config.baseUrl || BASE_URL,\n timeout: config.timeout || DEFAULT_TIMEOUT,\n maxRetries: config.maxRetries || MAX_RETRY_ATTEMPTS,\n };\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n const url = this.buildUrl(options.path, options.query);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await this.makeRequest(url, options);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n \n // Don't retry on client errors (4xx)\n if (error instanceof MessengerAPIError && error.statusCode >= 400 && error.statusCode < 500) {\n throw error;\n }\n\n // Don't retry on timeout for the last attempt\n if (attempt === this.config.maxRetries) {\n throw error;\n }\n\n // Wait before retrying\n await this.delay(RETRY_DELAY_MS * (attempt + 1));\n }\n }\n\n throw lastError || new Error('Unknown error occurred');\n }\n\n private buildUrl(path: string, query?: Record<string, string | number | boolean>): string {\n const url = new URL(`${this.config.baseUrl}/${this.config.version}${path}`);\n \n // Always add access token\n url.searchParams.append('access_token', this.config.accessToken);\n \n // Add additional query parameters\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n return url.toString();\n }\n\n private async makeRequest(url: string, options: RequestOptions): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers: {\n 'Content-Type': 'application/json',\n },\n signal: controller.signal,\n };\n\n if (options.body) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new MessengerTimeoutError(this.config.timeout);\n }\n throw new MessengerNetworkError(`Network request failed: ${error.message}`, error);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type');\n const isJson = contentType?.includes('application/json');\n\n if (!response.ok) {\n if (isJson) {\n const errorData = await response.json() as ErrorResponse;\n throw new MessengerAPIError(errorData.error, response.status, errorData);\n } else {\n const text = await response.text();\n throw new MessengerAPIError(\n {\n message: text || `HTTP ${response.status} ${response.statusText}`,\n type: 'http_error',\n code: response.status,\n fbtrace_id: '',\n },\n response.status,\n text\n );\n }\n }\n\n if (isJson) {\n return await response.json() as T;\n }\n\n // For non-JSON responses, return the text\n return await response.text() as unknown as T;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}","import { MESSAGE_LIMITS } from '../core/constants.js';\n\nexport class MessageValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessageValidationError';\n }\n}\n\nexport function validateTextMessage(text: string): void {\n if (!text || text.trim() === '') {\n throw new MessageValidationError('Text message cannot be empty');\n }\n\n if (text.length > MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS) {\n throw new MessageValidationError(\n `Text message cannot exceed ${MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS} characters`\n );\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { SendMessageRequest, SenderAction, Recipient } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport type { AttachmentType } from '../types/attachments.js';\nimport { validateTextMessage } from '../utils/message-validators.js';\n\nexport class SendAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async message(request: SendMessageRequest): Promise<SendMessageResponse> {\n // Validate text message length if present\n if (request.message?.text) {\n validateTextMessage(request.message.text);\n }\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async action(recipientId: string, action: SenderAction): Promise<SendMessageResponse> {\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: {\n recipient: { id: recipientId },\n messaging_type: 'RESPONSE',\n sender_action: action,\n },\n });\n }\n\n async typingOn(recipientId: string): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_on');\n }\n\n async typingOff(recipientId: string): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_off');\n }\n\n async markSeen(recipientId: string): Promise<SendMessageResponse> {\n return this.action(recipientId, 'mark_seen');\n }\n\n // Convenience methods for sending attachments\n\n /**\n * Send an attachment using a previously uploaded attachment_id\n */\n async attachment(options: {\n recipient: Recipient;\n type: AttachmentType;\n attachment_id: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n attachment_id: options.attachment_id,\n },\n },\n },\n });\n }\n\n /**\n * Upload and send an attachment from URL in a single request\n */\n async attachmentFromUrl(options: {\n recipient: Recipient;\n type: AttachmentType;\n url: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n url: options.url,\n },\n },\n },\n });\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { AttachmentUploadRequest, AttachmentUploadResponse } from '../types/attachments.js';\n\nexport class AttachmentsAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async upload(request: AttachmentUploadRequest): Promise<AttachmentUploadResponse> {\n // Format according to official API - no message wrapper needed\n const body = {\n message: {\n attachment: {\n type: request.type,\n payload: {\n url: request.url,\n is_reusable: request.is_reusable ?? true,\n },\n },\n },\n };\n\n return this.httpClient.request<AttachmentUploadResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGE_ATTACHMENTS,\n body,\n });\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { \n ModerateConversationsRequest,\n ModerateConversationsResponse\n} from '../types/moderation.js';\n\nexport class ModerationAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Moderate conversations with specified actions\n * Up to 10 user IDs and up to 2 actions per request\n */\n async moderate(request: ModerateConversationsRequest): Promise<ModerateConversationsResponse> {\n return this.httpClient.request<ModerateConversationsResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MODERATE_CONVERSATIONS,\n body: request,\n });\n }\n\n /**\n * Block a user from messaging the page\n * Prevents messaging but user can still interact with page content on Facebook\n */\n async blockUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds) \n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user'],\n });\n }\n\n /**\n * Unblock a user to allow messaging again\n */\n async unblockUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unblock_user'],\n });\n }\n\n /**\n * Ban a user from both messaging and Facebook interactions\n * More restrictive than blocking - prevents all interactions\n * Note: Cannot ban user who was unbanned in last 48 hours\n */\n async banUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['ban_user'],\n });\n }\n\n /**\n * Unban a user to restore all interactions\n * Note: Banned user cannot be unblocked, they must be unbanned first\n */\n async unbanUser(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unban_user'],\n });\n }\n\n /**\n * Move conversation to spam folder in Meta Business Suite Inbox\n */\n async moveToSpam(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['move_to_spam'],\n });\n }\n\n /**\n * Block user and move to spam (common moderation action)\n */\n async blockAndSpam(userIds: string | string[]): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user', 'move_to_spam'],\n });\n }\n}","import { TEMPLATE_LIMITS } from '../core/constants.js';\nimport type { Button, GenericTemplateElement, MediaTemplateElement } from '../types/templates.js';\n\nexport class TemplateValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TemplateValidationError';\n }\n}\n\nexport function validateGenericTemplate(elements: GenericTemplateElement[]): void {\n if (elements.length === 0) {\n throw new TemplateValidationError('Generic template must have at least 1 element');\n }\n\n if (elements.length > TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX) {\n throw new TemplateValidationError(\n `Generic template cannot have more than ${TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX} elements`\n );\n }\n\n elements.forEach((element, index) => {\n validateGenericElement(element, index);\n });\n}\n\nexport function validateGenericElement(element: GenericTemplateElement, index: number): void {\n if (!element.title || element.title.trim() === '') {\n throw new TemplateValidationError(`Element ${index}: title is required`);\n }\n\n if (element.title.length > TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: title cannot exceed ${TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.subtitle && element.subtitle.length > TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: subtitle cannot exceed ${TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.image_url && !isHttpsUrl(element.image_url)) {\n throw new TemplateValidationError(`Element ${index}: image_url must be HTTPS`);\n }\n\n if (element.buttons) {\n validateButtons(element.buttons, `Element ${index}`);\n }\n\n // Validate that element has at least one property beyond title\n const hasAdditionalProperty = !!(\n element.subtitle ||\n element.image_url ||\n element.default_action ||\n (element.buttons && element.buttons.length > 0)\n );\n\n if (!hasAdditionalProperty) {\n throw new TemplateValidationError(\n `Element ${index}: must have at least one additional property beyond title`\n );\n }\n}\n\nexport function validateButtonTemplate(text: string, buttons: Button[]): void {\n if (!text || text.trim() === '') {\n throw new TemplateValidationError('Button template text is required');\n }\n\n if (text.length > TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS) {\n throw new TemplateValidationError(\n `Button template text cannot exceed ${TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS} characters`\n );\n }\n\n if (buttons.length === 0) {\n throw new TemplateValidationError('Button template must have at least 1 button');\n }\n\n validateButtons(buttons, 'Button template');\n}\n\nexport function validateMediaTemplate(element: MediaTemplateElement): void {\n if (!element.media_type) {\n throw new TemplateValidationError('Media template element must have media_type');\n }\n\n if (!element.url && !element.attachment_id) {\n throw new TemplateValidationError('Media template element must have either url or attachment_id');\n }\n\n if (element.url && element.attachment_id) {\n throw new TemplateValidationError(\n 'Media template element cannot have both url and attachment_id'\n );\n }\n\n if (element.url && !isHttpsUrl(element.url)) {\n throw new TemplateValidationError('Media template url must be HTTPS');\n }\n\n if (element.buttons) {\n if (element.buttons.length > TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `Media template cannot have more than ${TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT} buttons`\n );\n }\n validateButtons(element.buttons, 'Media template');\n }\n}\n\nexport function validateButtons(buttons: Button[], context: string): void {\n if (buttons.length > TEMPLATE_LIMITS.BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `${context} cannot have more than ${TEMPLATE_LIMITS.BUTTONS_MAX_COUNT} buttons`\n );\n }\n\n buttons.forEach((button, index) => {\n validateButton(button, `${context} button ${index}`);\n });\n}\n\nexport function validateButton(button: Button, context: string): void {\n if (!button.type) {\n throw new TemplateValidationError(`${context}: type is required`);\n }\n\n // Title is required for most button types (not for account_unlink)\n if (button.type !== 'account_unlink' && (!button.title || button.title.trim() === '')) {\n throw new TemplateValidationError(`${context}: title is required for ${button.type} buttons`);\n }\n\n if (button.title && button.title.length > TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: title cannot exceed ${TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS} characters`\n );\n }\n\n // Type-specific validations\n switch (button.type) {\n case 'web_url':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for web_url buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for web_url buttons`);\n }\n break;\n\n case 'postback':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for postback buttons`);\n }\n if (button.payload.length > TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: payload cannot exceed ${TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS} characters`\n );\n }\n break;\n\n case 'phone_number':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for phone_number buttons`);\n }\n // Basic phone number validation (starts with +)\n if (!button.payload.startsWith('+')) {\n throw new TemplateValidationError(\n `${context}: phone_number payload must start with + (e.g., +1234567890)`\n );\n }\n break;\n\n case 'game_play':\n // game_play buttons may have optional game_metadata\n break;\n\n case 'account_link':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for account_link buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for account_link buttons`);\n }\n break;\n\n case 'account_unlink':\n // account_unlink buttons don't require additional properties\n break;\n }\n\n // Validate webview properties for web_url buttons\n if (button.type === 'web_url' && button.messenger_extensions && button.fallback_url) {\n if (!isHttpsUrl(button.fallback_url)) {\n throw new TemplateValidationError(`${context}: fallback_url must be HTTPS`);\n }\n }\n}\n\nfunction isHttpsUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.protocol === 'https:';\n } catch {\n return false;\n }\n}","import type { HTTPClient } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { Recipient, SendMessageRequest, MessagingType } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport { validateGenericTemplate, validateButtonTemplate, validateMediaTemplate } from '../utils/validators.js';\nimport type {\n GenericTemplatePayload,\n ButtonTemplatePayload,\n MediaTemplatePayload,\n ProductTemplatePayload,\n GenericTemplateElement,\n Button,\n MediaTemplateElement,\n ProductTemplateElement,\n} from '../types/templates.js';\n\nexport class TemplatesAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async generic(options: {\n recipient: Recipient;\n elements: GenericTemplateElement[];\n messaging_type?: MessagingType;\n image_aspect_ratio?: 'horizontal' | 'square';\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n // Validate template\n validateGenericTemplate(options.elements);\n\n const payload: GenericTemplatePayload = {\n template_type: 'generic',\n elements: options.elements,\n image_aspect_ratio: options.image_aspect_ratio,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async button(options: {\n recipient: Recipient;\n text: string;\n buttons: Button[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n // Validate template\n validateButtonTemplate(options.text, options.buttons);\n\n const payload: ButtonTemplatePayload = {\n template_type: 'button',\n text: options.text,\n buttons: options.buttons,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async media(options: {\n recipient: Recipient;\n element: MediaTemplateElement;\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n // Validate template\n validateMediaTemplate(options.element);\n\n const payload: MediaTemplatePayload = {\n template_type: 'media',\n elements: [options.element],\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n\n async product(options: {\n recipient: Recipient;\n elements: ProductTemplateElement[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }): Promise<SendMessageResponse> {\n const payload: ProductTemplatePayload = {\n template_type: 'product',\n elements: options.elements,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n });\n }\n}","import { HTTPClient, type ClientConfig } from './core/http-client.js';\nimport { DEFAULT_API_VERSION } from './core/constants.js';\nimport { MessengerConfigError } from './core/errors.js';\nimport { SendAPI } from './resources/send.js';\nimport { AttachmentsAPI } from './resources/attachments.js';\nimport { ModerationAPI } from './resources/moderation.js';\nimport { TemplatesAPI } from './resources/templates.js';\n\nexport interface MessengerConfig {\n accessToken: string;\n version?: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class Messenger {\n public readonly send: SendAPI;\n public readonly attachments: AttachmentsAPI;\n public readonly moderation: ModerationAPI;\n public readonly templates: TemplatesAPI;\n\n private readonly httpClient: HTTPClient;\n\n constructor(config: MessengerConfig) {\n this.validateConfig(config);\n\n const clientConfig: ClientConfig = {\n accessToken: config.accessToken,\n version: config.version || DEFAULT_API_VERSION,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n };\n\n this.httpClient = new HTTPClient(clientConfig);\n\n // Initialize API resources\n this.send = new SendAPI(this.httpClient);\n this.attachments = new AttachmentsAPI(this.httpClient);\n this.moderation = new ModerationAPI(this.httpClient);\n this.templates = new TemplatesAPI(this.httpClient);\n }\n\n private validateConfig(config: MessengerConfig): void {\n if (!config.accessToken) {\n throw new MessengerConfigError('Access token is required');\n }\n\n if (typeof config.accessToken !== 'string' || config.accessToken.trim() === '') {\n throw new MessengerConfigError('Access token must be a non-empty string');\n }\n\n if (config.version && typeof config.version !== 'string') {\n throw new MessengerConfigError('API version must be a string');\n }\n\n if (config.timeout && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new MessengerConfigError('Timeout must be a positive number');\n }\n\n if (config.maxRetries && (typeof config.maxRetries !== 'number' || config.maxRetries < 0)) {\n throw new MessengerConfigError('Max retries must be a non-negative number');\n }\n }\n}"]}
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/core/errors.ts","../src/core/http-client.ts","../src/utils/message-validators.ts","../src/resources/send.ts","../src/resources/attachments.ts","../src/resources/moderation.ts","../src/utils/validators.ts","../src/resources/templates.ts","../src/resources/profile.ts","../src/client.ts"],"names":["DEFAULT_API_VERSION","BASE_URL","API_ENDPOINTS","MESSAGE_LIMITS","ATTACHMENT_LIMITS","TEMPLATE_LIMITS","MessengerAPIError","error","statusCode","response","MessengerNetworkError","message","cause","MessengerTimeoutError","timeout","MessengerConfigError","HTTPClient","config","options","url","lastError","attempt","path","query","accessTokenOverride","accessToken","key","value","controller","timeoutId","fetchOptions","isJson","errorData","text","ms","resolve","MessageValidationError","validateTextMessage","SendAPI","httpClient","request","recipientId","action","apiOptions","AttachmentsAPI","body","ModerationAPI","userIds","user_ids","id","TemplateValidationError","validateGenericTemplate","elements","element","index","validateGenericElement","isHttpsUrl","validateButtons","validateButtonTemplate","buttons","validateMediaTemplate","context","button","validateButton","TemplatesAPI","payload","ProfileAPI","psid","fields","queryParams","Messenger","clientConfig"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_API_VERSION = 'v23.0';\nexport const BASE_URL = 'https://graph.facebook.com';\nexport const DEFAULT_TIMEOUT = 30000; // 30 seconds\nexport const MAX_RETRY_ATTEMPTS = 3;\nexport const RETRY_DELAY_MS = 1000;\n\nexport const API_ENDPOINTS = {\n MESSAGES: '/me/messages',\n MESSAGE_ATTACHMENTS: '/me/message_attachments',\n MODERATE_CONVERSATIONS: '/me/moderate_conversations',\n USER_PROFILE: '', // Dynamic endpoint: /{PSID}\n} as const;\n\n// Validation constants\nexport const MESSAGE_LIMITS = {\n // Text messages\n TEXT_MESSAGE_MAX_CHARS: 2000,\n} as const;\n\nexport const ATTACHMENT_LIMITS = {\n // File size limits in bytes\n IMAGE_MAX_SIZE: 8 * 1024 * 1024, // 8MB\n OTHER_MAX_SIZE: 25 * 1024 * 1024, // 25MB (video, audio, file)\n \n // Timeout limits in seconds\n VIDEO_TIMEOUT: 75,\n OTHER_TIMEOUT: 10,\n} as const;\n\nexport const TEMPLATE_LIMITS = {\n // Generic Template\n GENERIC_ELEMENTS_MAX: 10,\n GENERIC_TITLE_MAX_CHARS: 80,\n GENERIC_SUBTITLE_MAX_CHARS: 80,\n \n // Button Template \n BUTTON_TEXT_MAX_CHARS: 640,\n BUTTONS_MAX_COUNT: 3,\n BUTTON_TITLE_MAX_CHARS: 20,\n \n // All Templates\n POSTBACK_PAYLOAD_MAX_CHARS: 1000,\n \n // Media Template\n MEDIA_ELEMENTS_COUNT: 1, // Exactly 1 element required\n MEDIA_BUTTONS_MAX_COUNT: 3,\n} as const;","import type { MessengerError } from '../types/responses.js';\n\nexport class MessengerAPIError extends Error {\n public readonly code: number;\n public readonly type: string;\n public readonly subcode?: number;\n public readonly fbtrace_id?: string;\n public readonly statusCode: number;\n public readonly response?: any;\n\n constructor(error: MessengerError, statusCode: number, response?: any) {\n super(error.message);\n this.name = 'MessengerAPIError';\n this.code = error.code;\n this.type = error.type;\n this.subcode = error.error_subcode;\n this.fbtrace_id = error.fbtrace_id;\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\nexport class MessengerNetworkError extends Error {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'MessengerNetworkError';\n this.cause = cause;\n }\n}\n\nexport class MessengerTimeoutError extends Error {\n public readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Request timed out after ${timeout}ms`);\n this.name = 'MessengerTimeoutError';\n this.timeout = timeout;\n }\n}\n\nexport class MessengerConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessengerConfigError';\n }\n}","import { BASE_URL, DEFAULT_TIMEOUT, MAX_RETRY_ATTEMPTS, RETRY_DELAY_MS } from './constants.js';\nimport { MessengerAPIError, MessengerNetworkError, MessengerTimeoutError } from './errors.js';\nimport type { ErrorResponse } from '../types/responses.js';\n\nexport interface ClientConfig {\n accessToken?: string;\n version: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport interface APIOptions {\n accessToken?: string;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'DELETE';\n path: string;\n body?: any;\n query?: Record<string, string | number | boolean>;\n accessToken?: string;\n}\n\nexport class HTTPClient {\n private readonly config: Required<Omit<ClientConfig, 'accessToken'>> & { accessToken?: string };\n\n constructor(config: ClientConfig) {\n this.config = {\n accessToken: config.accessToken,\n version: config.version,\n baseUrl: config.baseUrl || BASE_URL,\n timeout: config.timeout || DEFAULT_TIMEOUT,\n maxRetries: config.maxRetries || MAX_RETRY_ATTEMPTS,\n };\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n const url = this.buildUrl(options.path, options.query, options.accessToken);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await this.makeRequest(url, options);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Don't retry on client errors (4xx)\n if (\n error instanceof MessengerAPIError &&\n error.statusCode >= 400 &&\n error.statusCode < 500\n ) {\n throw error;\n }\n\n // Don't retry on timeout for the last attempt\n if (attempt === this.config.maxRetries) {\n throw error;\n }\n\n // Wait before retrying\n await this.delay(RETRY_DELAY_MS * (attempt + 1));\n }\n }\n\n throw lastError || new Error('Unknown error occurred');\n }\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean>,\n accessTokenOverride?: string,\n ): string {\n const url = new URL(`${this.config.baseUrl}/${this.config.version}${path}`);\n\n // Use override token if provided, otherwise use config token\n const accessToken = accessTokenOverride || this.config.accessToken;\n\n if (!accessToken) {\n throw new Error('Access token is required. Provide it in constructor or method options.');\n }\n\n url.searchParams.append('access_token', accessToken);\n\n // Add additional query parameters\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n return url.toString();\n }\n\n private async makeRequest(url: string, options: RequestOptions): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers: {\n 'Content-Type': 'application/json',\n },\n signal: controller.signal,\n };\n\n if (options.body) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new MessengerTimeoutError(this.config.timeout);\n }\n throw new MessengerNetworkError(`Network request failed: ${error.message}`, error);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type');\n const isJson = contentType?.includes('application/json');\n\n if (!response.ok) {\n if (isJson) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new MessengerAPIError(errorData.error, response.status, errorData);\n } else {\n const text = await response.text();\n throw new MessengerAPIError(\n {\n message: text || `HTTP ${response.status} ${response.statusText}`,\n type: 'http_error',\n code: response.status,\n fbtrace_id: '',\n },\n response.status,\n text,\n );\n }\n }\n\n if (isJson) {\n return (await response.json()) as T;\n }\n\n // For non-JSON responses, return the text\n return (await response.text()) as unknown as T;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { MESSAGE_LIMITS } from '../core/constants.js';\n\nexport class MessageValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessageValidationError';\n }\n}\n\nexport function validateTextMessage(text: string): void {\n if (!text || text.trim() === '') {\n throw new MessageValidationError('Text message cannot be empty');\n }\n\n if (text.length > MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS) {\n throw new MessageValidationError(\n `Text message cannot exceed ${MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS} characters`\n );\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { SendMessageRequest, SenderAction, Recipient } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport type { AttachmentType } from '../types/attachments.js';\nimport { validateTextMessage } from '../utils/message-validators.js';\n\nexport class SendAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse> {\n // Validate text message length if present\n if (request.message?.text) {\n validateTextMessage(request.message.text);\n }\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: options?.accessToken,\n });\n }\n\n async action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse> {\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: {\n recipient: { id: recipientId },\n messaging_type: 'RESPONSE',\n sender_action: action,\n },\n accessToken: options?.accessToken,\n });\n }\n\n async typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_on', options);\n }\n\n async typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_off', options);\n }\n\n async markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'mark_seen', options);\n }\n\n // Convenience methods for sending attachments\n\n /**\n * Send an attachment using a previously uploaded attachment_id\n */\n async attachment(options: {\n recipient: Recipient;\n type: AttachmentType;\n attachment_id: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n attachment_id: options.attachment_id,\n },\n },\n },\n }, apiOptions);\n }\n\n /**\n * Upload and send an attachment from URL in a single request\n */\n async attachmentFromUrl(options: {\n recipient: Recipient;\n type: AttachmentType;\n url: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n url: options.url,\n },\n },\n },\n }, apiOptions);\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { AttachmentUploadRequest, AttachmentUploadResponse } from '../types/attachments.js';\n\nexport class AttachmentsAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async upload(\n request: AttachmentUploadRequest,\n options?: APIOptions,\n ): Promise<AttachmentUploadResponse> {\n // Format according to official API - no message wrapper needed\n const body = {\n message: {\n attachment: {\n type: request.type,\n payload: {\n url: request.url,\n is_reusable: request.is_reusable ?? true,\n },\n },\n },\n };\n\n return this.httpClient.request<AttachmentUploadResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGE_ATTACHMENTS,\n body,\n accessToken: options?.accessToken,\n });\n }\n}\n","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { \n ModerateConversationsRequest,\n ModerateConversationsResponse\n} from '../types/moderation.js';\n\nexport class ModerationAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Moderate conversations with specified actions\n * Up to 10 user IDs and up to 2 actions per request\n */\n async moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse> {\n return this.httpClient.request<ModerateConversationsResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MODERATE_CONVERSATIONS,\n body: request,\n accessToken: options?.accessToken,\n });\n }\n\n /**\n * Block a user from messaging the page\n * Prevents messaging but user can still interact with page content on Facebook\n */\n async blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds) \n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user'],\n }, options);\n }\n\n /**\n * Unblock a user to allow messaging again\n */\n async unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unblock_user'],\n }, options);\n }\n\n /**\n * Ban a user from both messaging and Facebook interactions\n * More restrictive than blocking - prevents all interactions\n * Note: Cannot ban user who was unbanned in last 48 hours\n */\n async banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['ban_user'],\n }, options);\n }\n\n /**\n * Unban a user to restore all interactions\n * Note: Banned user cannot be unblocked, they must be unbanned first\n */\n async unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unban_user'],\n }, options);\n }\n\n /**\n * Move conversation to spam folder in Meta Business Suite Inbox\n */\n async moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['move_to_spam'],\n }, options);\n }\n\n /**\n * Block user and move to spam (common moderation action)\n */\n async blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user', 'move_to_spam'],\n }, options);\n }\n}","import { TEMPLATE_LIMITS } from '../core/constants.js';\nimport type { Button, GenericTemplateElement, MediaTemplateElement } from '../types/templates.js';\n\nexport class TemplateValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TemplateValidationError';\n }\n}\n\nexport function validateGenericTemplate(elements: GenericTemplateElement[]): void {\n if (elements.length === 0) {\n throw new TemplateValidationError('Generic template must have at least 1 element');\n }\n\n if (elements.length > TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX) {\n throw new TemplateValidationError(\n `Generic template cannot have more than ${TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX} elements`\n );\n }\n\n elements.forEach((element, index) => {\n validateGenericElement(element, index);\n });\n}\n\nexport function validateGenericElement(element: GenericTemplateElement, index: number): void {\n if (!element.title || element.title.trim() === '') {\n throw new TemplateValidationError(`Element ${index}: title is required`);\n }\n\n if (element.title.length > TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: title cannot exceed ${TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.subtitle && element.subtitle.length > TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: subtitle cannot exceed ${TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.image_url && !isHttpsUrl(element.image_url)) {\n throw new TemplateValidationError(`Element ${index}: image_url must be HTTPS`);\n }\n\n if (element.buttons) {\n validateButtons(element.buttons, `Element ${index}`);\n }\n\n // Validate that element has at least one property beyond title\n const hasAdditionalProperty = !!(\n element.subtitle ||\n element.image_url ||\n element.default_action ||\n (element.buttons && element.buttons.length > 0)\n );\n\n if (!hasAdditionalProperty) {\n throw new TemplateValidationError(\n `Element ${index}: must have at least one additional property beyond title`\n );\n }\n}\n\nexport function validateButtonTemplate(text: string, buttons: Button[]): void {\n if (!text || text.trim() === '') {\n throw new TemplateValidationError('Button template text is required');\n }\n\n if (text.length > TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS) {\n throw new TemplateValidationError(\n `Button template text cannot exceed ${TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS} characters`\n );\n }\n\n if (buttons.length === 0) {\n throw new TemplateValidationError('Button template must have at least 1 button');\n }\n\n validateButtons(buttons, 'Button template');\n}\n\nexport function validateMediaTemplate(element: MediaTemplateElement): void {\n if (!element.media_type) {\n throw new TemplateValidationError('Media template element must have media_type');\n }\n\n if (!element.url && !element.attachment_id) {\n throw new TemplateValidationError('Media template element must have either url or attachment_id');\n }\n\n if (element.url && element.attachment_id) {\n throw new TemplateValidationError(\n 'Media template element cannot have both url and attachment_id'\n );\n }\n\n if (element.url && !isHttpsUrl(element.url)) {\n throw new TemplateValidationError('Media template url must be HTTPS');\n }\n\n if (element.buttons) {\n if (element.buttons.length > TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `Media template cannot have more than ${TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT} buttons`\n );\n }\n validateButtons(element.buttons, 'Media template');\n }\n}\n\nexport function validateButtons(buttons: Button[], context: string): void {\n if (buttons.length > TEMPLATE_LIMITS.BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `${context} cannot have more than ${TEMPLATE_LIMITS.BUTTONS_MAX_COUNT} buttons`\n );\n }\n\n buttons.forEach((button, index) => {\n validateButton(button, `${context} button ${index}`);\n });\n}\n\nexport function validateButton(button: Button, context: string): void {\n if (!button.type) {\n throw new TemplateValidationError(`${context}: type is required`);\n }\n\n // Title is required for most button types (not for account_unlink)\n if (button.type !== 'account_unlink' && (!button.title || button.title.trim() === '')) {\n throw new TemplateValidationError(`${context}: title is required for ${button.type} buttons`);\n }\n\n if (button.title && button.title.length > TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: title cannot exceed ${TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS} characters`\n );\n }\n\n // Type-specific validations\n switch (button.type) {\n case 'web_url':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for web_url buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for web_url buttons`);\n }\n break;\n\n case 'postback':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for postback buttons`);\n }\n if (button.payload.length > TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: payload cannot exceed ${TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS} characters`\n );\n }\n break;\n\n case 'phone_number':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for phone_number buttons`);\n }\n // Basic phone number validation (starts with +)\n if (!button.payload.startsWith('+')) {\n throw new TemplateValidationError(\n `${context}: phone_number payload must start with + (e.g., +1234567890)`\n );\n }\n break;\n\n case 'game_play':\n // game_play buttons may have optional game_metadata\n break;\n\n case 'account_link':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for account_link buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for account_link buttons`);\n }\n break;\n\n case 'account_unlink':\n // account_unlink buttons don't require additional properties\n break;\n }\n\n // Validate webview properties for web_url buttons\n if (button.type === 'web_url' && button.messenger_extensions && button.fallback_url) {\n if (!isHttpsUrl(button.fallback_url)) {\n throw new TemplateValidationError(`${context}: fallback_url must be HTTPS`);\n }\n }\n}\n\nfunction isHttpsUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.protocol === 'https:';\n } catch {\n return false;\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { Recipient, SendMessageRequest, MessagingType } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport { validateGenericTemplate, validateButtonTemplate, validateMediaTemplate } from '../utils/validators.js';\nimport type {\n GenericTemplatePayload,\n ButtonTemplatePayload,\n MediaTemplatePayload,\n ProductTemplatePayload,\n GenericTemplateElement,\n Button,\n MediaTemplateElement,\n ProductTemplateElement,\n} from '../types/templates.js';\n\nexport class TemplatesAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async generic(options: {\n recipient: Recipient;\n elements: GenericTemplateElement[];\n messaging_type?: MessagingType;\n image_aspect_ratio?: 'horizontal' | 'square';\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateGenericTemplate(options.elements);\n\n const payload: GenericTemplatePayload = {\n template_type: 'generic',\n elements: options.elements,\n image_aspect_ratio: options.image_aspect_ratio,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async button(options: {\n recipient: Recipient;\n text: string;\n buttons: Button[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateButtonTemplate(options.text, options.buttons);\n\n const payload: ButtonTemplatePayload = {\n template_type: 'button',\n text: options.text,\n buttons: options.buttons,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async media(options: {\n recipient: Recipient;\n element: MediaTemplateElement;\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateMediaTemplate(options.element);\n\n const payload: MediaTemplatePayload = {\n template_type: 'media',\n elements: [options.element],\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async product(options: {\n recipient: Recipient;\n elements: ProductTemplateElement[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n const payload: ProductTemplatePayload = {\n template_type: 'product',\n elements: options.elements,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport type { \n GetProfileRequest,\n UserProfile\n} from '../types/profile.js';\n\nexport class ProfileAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Get user profile information using PSID\n * Requires \"Advanced User Profile Access\" feature\n */\n async get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile> {\n const { psid, fields = ['first_name', 'last_name'] } = request;\n \n const queryParams = new URLSearchParams({\n fields: fields.join(','),\n });\n\n return this.httpClient.request<UserProfile>({\n method: 'GET',\n path: `/${psid}?${queryParams.toString()}`,\n body: undefined,\n accessToken: options?.accessToken,\n });\n }\n\n /**\n * Get user profile with default fields (first_name, last_name, profile_pic)\n */\n async getBasic(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name', 'profile_pic'],\n }, options);\n }\n\n /**\n * Get comprehensive user profile with all available fields\n */\n async getFull(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['id', 'name', 'first_name', 'last_name', 'profile_pic', 'locale', 'timezone', 'gender'],\n }, options);\n }\n\n /**\n * Get user's name (first_name and last_name)\n */\n async getName(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name'],\n }, options);\n }\n\n /**\n * Get user's profile picture URL\n */\n async getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['profile_pic'],\n }, options);\n }\n}","import { HTTPClient, type ClientConfig } from './core/http-client.js';\nimport { DEFAULT_API_VERSION } from './core/constants.js';\nimport { MessengerConfigError } from './core/errors.js';\nimport { SendAPI } from './resources/send.js';\nimport { AttachmentsAPI } from './resources/attachments.js';\nimport { ModerationAPI } from './resources/moderation.js';\nimport { TemplatesAPI } from './resources/templates.js';\nimport { ProfileAPI } from './resources/profile.js';\n\nexport interface MessengerConfig {\n accessToken?: string;\n version?: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class Messenger {\n public readonly send: SendAPI;\n public readonly attachments: AttachmentsAPI;\n public readonly moderation: ModerationAPI;\n public readonly templates: TemplatesAPI;\n public readonly profile: ProfileAPI;\n\n private readonly httpClient: HTTPClient;\n\n constructor(config: MessengerConfig = {}) {\n this.validateConfig(config);\n\n const clientConfig: ClientConfig = {\n accessToken: config.accessToken,\n version: config.version || DEFAULT_API_VERSION,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n };\n\n this.httpClient = new HTTPClient(clientConfig);\n\n // Initialize API resources\n this.send = new SendAPI(this.httpClient);\n this.attachments = new AttachmentsAPI(this.httpClient);\n this.moderation = new ModerationAPI(this.httpClient);\n this.templates = new TemplatesAPI(this.httpClient);\n this.profile = new ProfileAPI(this.httpClient);\n }\n\n private validateConfig(config: MessengerConfig): void {\n if (config.accessToken !== undefined) {\n if (typeof config.accessToken !== 'string' || config.accessToken.trim() === '') {\n throw new MessengerConfigError('Access token must be a non-empty string');\n }\n }\n\n if (config.version && typeof config.version !== 'string') {\n throw new MessengerConfigError('API version must be a string');\n }\n\n if (config.timeout && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new MessengerConfigError('Timeout must be a positive number');\n }\n\n if (config.maxRetries && (typeof config.maxRetries !== 'number' || config.maxRetries < 0)) {\n throw new MessengerConfigError('Max retries must be a non-negative number');\n }\n }\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warriorteam/messenger-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "TypeScript SDK for Facebook Messenger Platform API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",