@warriorteam/messenger-sdk 1.1.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/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -27
- package/dist/index.d.ts +31 -27
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var R="v23.0",P="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},f={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 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||P,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query),r;for(let o=0;o<=this.config.maxRetries;o++)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||o===this.config.maxRetries)throw a;await this.delay(1e3*(o+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(([o,a])=>{r.searchParams.append(o,String(a));}),r.toString()}async makeRequest(e,s){let r=new AbortController,o=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(o);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let o=await e.json();throw new c(o.error,e.status,o)}else {let o=await e.text();throw new c({message:o||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,o)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var d=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function b(t){if(!t||t.trim()==="")throw new d("Text message cannot be empty");if(t.length>f.TEXT_MESSAGE_MAX_CHARS)throw new d(`Text message cannot exceed ${f.TEXT_MESSAGE_MAX_CHARS} characters`)}var T=class{constructor(e){this.httpClient=e;}async message(e){return e.message?.text&&b(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 h=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 _=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 w(t){if(t.length===0)throw new n("Generic template must have at least 1 element");if(t.length>i.GENERIC_ELEMENTS_MAX)throw new n(`Generic template cannot have more than ${i.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{x(e,s);});}function x(t,e){if(!t.title||t.title.trim()==="")throw new n(`Element ${e}: title is required`);if(t.title.length>i.GENERIC_TITLE_MAX_CHARS)throw new n(`Element ${e}: title cannot exceed ${i.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>i.GENERIC_SUBTITLE_MAX_CHARS)throw new n(`Element ${e}: subtitle cannot exceed ${i.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!g(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 C(t,e){if(!t||t.trim()==="")throw new n("Button template text is required");if(t.length>i.BUTTON_TEXT_MAX_CHARS)throw new n(`Button template text cannot exceed ${i.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 U(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&&!g(t.url))throw new n("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>i.MEDIA_BUTTONS_MAX_COUNT)throw new n(`Media template cannot have more than ${i.MEDIA_BUTTONS_MAX_COUNT} buttons`);A(t.buttons,"Media template");}}function A(t,e){if(t.length>i.BUTTONS_MAX_COUNT)throw new n(`${e} cannot have more than ${i.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{G(s,`${e} button ${r}`);});}function G(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>i.BUTTON_TITLE_MAX_CHARS)throw new n(`${e}: title cannot exceed ${i.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(!g(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>i.POSTBACK_PAYLOAD_MAX_CHARS)throw new n(`${e}: payload cannot exceed ${i.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(!g(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&&!g(t.fallback_url))throw new n(`${e}: fallback_url must be HTTPS`)}function g(t){try{return new URL(t).protocol==="https:"}catch{return false}}var y=class{constructor(e){this.httpClient=e;}async generic(e){w(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){C(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){U(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 E=class{constructor(e){this.httpClient=e;}async get(e){let{psid:s,fields:r=["first_name","last_name"]}=e,o=new URLSearchParams({fields:r.join(",")});return this.httpClient.request({method:"GET",path:`/${s}?${o.toString()}`,body:void 0})}async getBasic(e){return this.get({psid:e,fields:["first_name","last_name","profile_pic"]})}async getFull(e){return this.get({psid:e,fields:["id","name","first_name","last_name","profile_pic","locale","timezone","gender"]})}async getName(e){return this.get({psid:e,fields:["first_name","last_name"]})}async getProfilePicture(e){return this.get({psid:e,fields:["profile_pic"]})}};var M=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 S(s),this.send=new T(this.httpClient),this.attachments=new h(this.httpClient),this.moderation=new _(this.httpClient),this.templates=new y(this.httpClient),this.profile=new E(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=v;exports.AttachmentsAPI=h;exports.MESSAGE_LIMITS=
|
|
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
|
package/dist/index.cjs.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/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","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","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 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 type { HTTPClient } 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): 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 });\n }\n\n /**\n * Get user profile with default fields (first_name, last_name, profile_pic)\n */\n async getBasic(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name', 'profile_pic'],\n });\n }\n\n /**\n * Get comprehensive user profile with all available fields\n */\n async getFull(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['id', 'name', 'first_name', 'last_name', 'profile_pic', 'locale', 'timezone', 'gender'],\n });\n }\n\n /**\n * Get user's name (first_name and last_name)\n */\n async getName(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name'],\n });\n }\n\n /**\n * Get user's profile picture URL\n */\n async getProfilePicture(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['profile_pic'],\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';\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) {\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
|
|
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,21 +258,21 @@ 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>;
|
|
272
276
|
}
|
|
273
277
|
|
|
274
278
|
type ProfileField = 'id' | 'name' | 'first_name' | 'last_name' | 'profile_pic' | 'locale' | 'timezone' | 'gender';
|
|
@@ -294,27 +298,27 @@ declare class ProfileAPI {
|
|
|
294
298
|
* Get user profile information using PSID
|
|
295
299
|
* Requires "Advanced User Profile Access" feature
|
|
296
300
|
*/
|
|
297
|
-
get(request: GetProfileRequest): Promise<UserProfile>;
|
|
301
|
+
get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile>;
|
|
298
302
|
/**
|
|
299
303
|
* Get user profile with default fields (first_name, last_name, profile_pic)
|
|
300
304
|
*/
|
|
301
|
-
getBasic(psid: string): Promise<UserProfile>;
|
|
305
|
+
getBasic(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
302
306
|
/**
|
|
303
307
|
* Get comprehensive user profile with all available fields
|
|
304
308
|
*/
|
|
305
|
-
getFull(psid: string): Promise<UserProfile>;
|
|
309
|
+
getFull(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
306
310
|
/**
|
|
307
311
|
* Get user's name (first_name and last_name)
|
|
308
312
|
*/
|
|
309
|
-
getName(psid: string): Promise<UserProfile>;
|
|
313
|
+
getName(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
310
314
|
/**
|
|
311
315
|
* Get user's profile picture URL
|
|
312
316
|
*/
|
|
313
|
-
getProfilePicture(psid: string): Promise<UserProfile>;
|
|
317
|
+
getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
314
318
|
}
|
|
315
319
|
|
|
316
320
|
interface MessengerConfig {
|
|
317
|
-
accessToken
|
|
321
|
+
accessToken?: string;
|
|
318
322
|
version?: string;
|
|
319
323
|
baseUrl?: string;
|
|
320
324
|
timeout?: number;
|
|
@@ -327,7 +331,7 @@ declare class Messenger {
|
|
|
327
331
|
readonly templates: TemplatesAPI;
|
|
328
332
|
readonly profile: ProfileAPI;
|
|
329
333
|
private readonly httpClient;
|
|
330
|
-
constructor(config
|
|
334
|
+
constructor(config?: MessengerConfig);
|
|
331
335
|
private validateConfig;
|
|
332
336
|
}
|
|
333
337
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
interface ClientConfig {
|
|
2
|
-
accessToken
|
|
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,21 +258,21 @@ 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>;
|
|
272
276
|
}
|
|
273
277
|
|
|
274
278
|
type ProfileField = 'id' | 'name' | 'first_name' | 'last_name' | 'profile_pic' | 'locale' | 'timezone' | 'gender';
|
|
@@ -294,27 +298,27 @@ declare class ProfileAPI {
|
|
|
294
298
|
* Get user profile information using PSID
|
|
295
299
|
* Requires "Advanced User Profile Access" feature
|
|
296
300
|
*/
|
|
297
|
-
get(request: GetProfileRequest): Promise<UserProfile>;
|
|
301
|
+
get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile>;
|
|
298
302
|
/**
|
|
299
303
|
* Get user profile with default fields (first_name, last_name, profile_pic)
|
|
300
304
|
*/
|
|
301
|
-
getBasic(psid: string): Promise<UserProfile>;
|
|
305
|
+
getBasic(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
302
306
|
/**
|
|
303
307
|
* Get comprehensive user profile with all available fields
|
|
304
308
|
*/
|
|
305
|
-
getFull(psid: string): Promise<UserProfile>;
|
|
309
|
+
getFull(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
306
310
|
/**
|
|
307
311
|
* Get user's name (first_name and last_name)
|
|
308
312
|
*/
|
|
309
|
-
getName(psid: string): Promise<UserProfile>;
|
|
313
|
+
getName(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
310
314
|
/**
|
|
311
315
|
* Get user's profile picture URL
|
|
312
316
|
*/
|
|
313
|
-
getProfilePicture(psid: string): Promise<UserProfile>;
|
|
317
|
+
getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile>;
|
|
314
318
|
}
|
|
315
319
|
|
|
316
320
|
interface MessengerConfig {
|
|
317
|
-
accessToken
|
|
321
|
+
accessToken?: string;
|
|
318
322
|
version?: string;
|
|
319
323
|
baseUrl?: string;
|
|
320
324
|
timeout?: number;
|
|
@@ -327,7 +331,7 @@ declare class Messenger {
|
|
|
327
331
|
readonly templates: TemplatesAPI;
|
|
328
332
|
readonly profile: ProfileAPI;
|
|
329
333
|
private readonly httpClient;
|
|
330
|
-
constructor(config
|
|
334
|
+
constructor(config?: MessengerConfig);
|
|
331
335
|
private validateConfig;
|
|
332
336
|
}
|
|
333
337
|
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var R="v23.0",P="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},f={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 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||P,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query),r;for(let o=0;o<=this.config.maxRetries;o++)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||o===this.config.maxRetries)throw a;await this.delay(1e3*(o+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(([o,a])=>{r.searchParams.append(o,String(a));}),r.toString()}async makeRequest(e,s){let r=new AbortController,o=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(o);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let o=await e.json();throw new c(o.error,e.status,o)}else {let o=await e.text();throw new c({message:o||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,o)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var d=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function b(t){if(!t||t.trim()==="")throw new d("Text message cannot be empty");if(t.length>f.TEXT_MESSAGE_MAX_CHARS)throw new d(`Text message cannot exceed ${f.TEXT_MESSAGE_MAX_CHARS} characters`)}var T=class{constructor(e){this.httpClient=e;}async message(e){return e.message?.text&&b(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 h=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 _=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 w(t){if(t.length===0)throw new n("Generic template must have at least 1 element");if(t.length>i.GENERIC_ELEMENTS_MAX)throw new n(`Generic template cannot have more than ${i.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{x(e,s);});}function x(t,e){if(!t.title||t.title.trim()==="")throw new n(`Element ${e}: title is required`);if(t.title.length>i.GENERIC_TITLE_MAX_CHARS)throw new n(`Element ${e}: title cannot exceed ${i.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>i.GENERIC_SUBTITLE_MAX_CHARS)throw new n(`Element ${e}: subtitle cannot exceed ${i.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!g(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 C(t,e){if(!t||t.trim()==="")throw new n("Button template text is required");if(t.length>i.BUTTON_TEXT_MAX_CHARS)throw new n(`Button template text cannot exceed ${i.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 U(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&&!g(t.url))throw new n("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>i.MEDIA_BUTTONS_MAX_COUNT)throw new n(`Media template cannot have more than ${i.MEDIA_BUTTONS_MAX_COUNT} buttons`);A(t.buttons,"Media template");}}function A(t,e){if(t.length>i.BUTTONS_MAX_COUNT)throw new n(`${e} cannot have more than ${i.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{G(s,`${e} button ${r}`);});}function G(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>i.BUTTON_TITLE_MAX_CHARS)throw new n(`${e}: title cannot exceed ${i.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(!g(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>i.POSTBACK_PAYLOAD_MAX_CHARS)throw new n(`${e}: payload cannot exceed ${i.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(!g(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&&!g(t.fallback_url))throw new n(`${e}: fallback_url must be HTTPS`)}function g(t){try{return new URL(t).protocol==="https:"}catch{return false}}var y=class{constructor(e){this.httpClient=e;}async generic(e){w(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){C(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){U(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 E=class{constructor(e){this.httpClient=e;}async get(e){let{psid:s,fields:r=["first_name","last_name"]}=e,o=new URLSearchParams({fields:r.join(",")});return this.httpClient.request({method:"GET",path:`/${s}?${o.toString()}`,body:void 0})}async getBasic(e){return this.get({psid:e,fields:["first_name","last_name","profile_pic"]})}async getFull(e){return this.get({psid:e,fields:["id","name","first_name","last_name","profile_pic","locale","timezone","gender"]})}async getName(e){return this.get({psid:e,fields:["first_name","last_name"]})}async getProfilePicture(e){return this.get({psid:e,fields:["profile_pic"]})}};var M=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 S(s),this.send=new T(this.httpClient),this.attachments=new h(this.httpClient),this.moderation=new _(this.httpClient),this.templates=new y(this.httpClient),this.profile=new E(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{v as ATTACHMENT_LIMITS,h as AttachmentsAPI,
|
|
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/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","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","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 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 type { HTTPClient } 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): 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 });\n }\n\n /**\n * Get user profile with default fields (first_name, last_name, profile_pic)\n */\n async getBasic(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name', 'profile_pic'],\n });\n }\n\n /**\n * Get comprehensive user profile with all available fields\n */\n async getFull(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['id', 'name', 'first_name', 'last_name', 'profile_pic', 'locale', 'timezone', 'gender'],\n });\n }\n\n /**\n * Get user's name (first_name and last_name)\n */\n async getName(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name'],\n });\n }\n\n /**\n * Get user's profile picture URL\n */\n async getProfilePicture(psid: string): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['profile_pic'],\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';\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) {\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":"AAAO,IAAMA,CAAAA,CAAsB,OAAA,CACtBC,CAAAA,CAAW,4BAAA,CAKjB,IAAMC,CAAAA,CAAgB,CAC3B,QAAA,CAAU,cAAA,CACV,mBAAA,CAAqB,yBAAA,CACrB,sBAAA,CAAwB,4BAE1B,CAAA,CAGaC,CAAAA,CAAiB,CAE5B,sBAAA,CAAwB,GAC1B,CAAA,CAEaC,CAAAA,CAAoB,CAE/B,cAAA,CAAgB,CAAA,CAAI,IAAA,CAAO,IAAA,CAC3B,cAAA,CAAgB,GAAK,IAAA,CAAO,IAAA,CAG5B,aAAA,CAAe,EAAA,CACf,aAAA,CAAe,EACjB,CAAA,CAEaC,CAAAA,CAAkB,CAE7B,oBAAA,CAAsB,EAAA,CACtB,uBAAA,CAAyB,EAAA,CACzB,0BAAA,CAA4B,EAAA,CAG5B,qBAAA,CAAuB,IACvB,iBAAA,CAAmB,CAAA,CACnB,sBAAA,CAAwB,EAAA,CAGxB,0BAAA,CAA4B,GAAA,CAG5B,oBAAA,CAAsB,CAAA,CACtB,uBAAA,CAAyB,CAC3B,EC5CO,IAAMC,CAAAA,CAAN,cAAgC,KAAM,CAC3B,KACA,IAAA,CACA,OAAA,CACA,UAAA,CACA,UAAA,CACA,QAAA,CAEhB,WAAA,CAAYC,CAAAA,CAAuBC,CAAAA,CAAoBC,CAAAA,CAAgB,CACrE,KAAA,CAAMF,CAAAA,CAAM,OAAO,CAAA,CACnB,IAAA,CAAK,IAAA,CAAO,mBAAA,CACZ,IAAA,CAAK,IAAA,CAAOA,CAAAA,CAAM,IAAA,CAClB,IAAA,CAAK,IAAA,CAAOA,CAAAA,CAAM,IAAA,CAClB,IAAA,CAAK,OAAA,CAAUA,CAAAA,CAAM,aAAA,CACrB,IAAA,CAAK,UAAA,CAAaA,CAAAA,CAAM,WACxB,IAAA,CAAK,UAAA,CAAaC,CAAAA,CAClB,IAAA,CAAK,QAAA,CAAWC,EAClB,CACF,CAAA,CAEaC,CAAAA,CAAN,cAAoC,KAAM,CAC/B,KAAA,CAEhB,WAAA,CAAYC,CAAAA,CAAiBC,CAAAA,CAAe,CAC1C,KAAA,CAAMD,CAAO,CAAA,CACb,IAAA,CAAK,IAAA,CAAO,uBAAA,CACZ,IAAA,CAAK,KAAA,CAAQC,EACf,CACF,CAAA,CAEaC,CAAAA,CAAN,cAAoC,KAAM,CAC/B,OAAA,CAEhB,YAAYC,CAAAA,CAAiB,CAC3B,KAAA,CAAM,CAAA,wBAAA,EAA2BA,CAAO,CAAA,EAAA,CAAI,CAAA,CAC5C,IAAA,CAAK,IAAA,CAAO,uBAAA,CACZ,IAAA,CAAK,OAAA,CAAUA,EACjB,CACF,CAAA,CAEaC,CAAAA,CAAN,cAAmC,KAAM,CAC9C,WAAA,CAAYJ,CAAAA,CAAiB,CAC3B,KAAA,CAAMA,CAAO,CAAA,CACb,IAAA,CAAK,IAAA,CAAO,uBACd,CACF,ECvBO,IAAMK,CAAAA,CAAN,KAAiB,CACL,MAAA,CAEjB,WAAA,CAAYC,CAAAA,CAAsB,CAChC,IAAA,CAAK,MAAA,CAAS,CACZ,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,OAAA,CAASA,CAAAA,CAAO,OAAA,CAChB,OAAA,CAASA,CAAAA,CAAO,SAAWhB,CAAAA,CAC3B,OAAA,CAASgB,CAAAA,CAAO,OAAA,EAAW,GAAA,CAC3B,UAAA,CAAYA,CAAAA,CAAO,UAAA,EAAc,CACnC,EACF,CAEA,MAAM,OAAA,CAAWC,CAAAA,CAAqC,CACpD,IAAMC,EAAM,IAAA,CAAK,QAAA,CAASD,CAAAA,CAAQ,IAAA,CAAMA,CAAAA,CAAQ,KAAA,CAAOA,CAAAA,CAAQ,WAAW,CAAA,CACtEE,CAAAA,CAEJ,IAAA,IAASC,CAAAA,CAAU,CAAA,CAAGA,CAAAA,EAAW,IAAA,CAAK,MAAA,CAAO,WAAYA,CAAAA,EAAAA,CACvD,GAAI,CACF,IAAMZ,CAAAA,CAAW,MAAM,IAAA,CAAK,WAAA,CAAYU,CAAAA,CAAKD,CAAO,CAAA,CACpD,OAAO,MAAM,IAAA,CAAK,cAAA,CAAkBT,CAAQ,CAC9C,CAAA,MAASF,CAAAA,CAAO,CAad,GAZAa,CAAAA,CAAYb,CAAAA,CAIVA,CAAAA,YAAiBD,CAAAA,EACjBC,CAAAA,CAAM,UAAA,EAAc,GAAA,EACpBA,CAAAA,CAAM,UAAA,CAAa,GAAA,EAMjBc,CAAAA,GAAY,IAAA,CAAK,OAAO,UAAA,CAC1B,MAAMd,CAAAA,CAIR,MAAM,IAAA,CAAK,KAAA,CAAM,GAAA,EAAkBc,CAAAA,CAAU,CAAA,CAAE,EACjD,CAGF,MAAMD,CAAAA,EAAa,IAAI,KAAA,CAAM,wBAAwB,CACvD,CAEQ,QAAA,CACNE,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACQ,CACR,IAAML,CAAAA,CAAM,IAAI,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAGG,CAAI,CAAA,CAAE,CAAA,CAGpEG,CAAAA,CAAcD,CAAAA,EAAuB,IAAA,CAAK,MAAA,CAAO,WAAA,CAEvD,GAAI,CAACC,CAAAA,CACH,MAAM,IAAI,MAAM,wEAAwE,CAAA,CAG1F,OAAAN,CAAAA,CAAI,YAAA,CAAa,MAAA,CAAO,cAAA,CAAgBM,CAAW,CAAA,CAG/CF,CAAAA,EACF,MAAA,CAAO,OAAA,CAAQA,CAAK,CAAA,CAAE,OAAA,CAAQ,CAAC,CAACG,CAAAA,CAAKC,CAAK,CAAA,GAAM,CAC9CR,CAAAA,CAAI,YAAA,CAAa,MAAA,CAAOO,CAAAA,CAAK,MAAA,CAAOC,CAAK,CAAC,EAC5C,CAAC,CAAA,CAGIR,CAAAA,CAAI,QAAA,EACb,CAEA,MAAc,WAAA,CAAYA,CAAAA,CAAaD,CAAAA,CAA4C,CACjF,IAAMU,CAAAA,CAAa,IAAI,eAAA,CACjBC,CAAAA,CAAY,UAAA,CAAW,IAAMD,CAAAA,CAAW,KAAA,EAAM,CAAG,KAAK,MAAA,CAAO,OAAO,CAAA,CAE1E,GAAI,CACF,IAAME,CAAAA,CAA4B,CAChC,MAAA,CAAQZ,CAAAA,CAAQ,MAAA,CAChB,OAAA,CAAS,CACP,cAAA,CAAgB,kBAClB,CAAA,CACA,OAAQU,CAAAA,CAAW,MACrB,CAAA,CAEA,OAAIV,CAAAA,CAAQ,IAAA,GACVY,CAAAA,CAAa,IAAA,CAAO,IAAA,CAAK,SAAA,CAAUZ,CAAAA,CAAQ,IAAI,CAAA,CAAA,CAGhC,MAAM,KAAA,CAAMC,CAAAA,CAAKW,CAAY,CAEhD,CAAA,MAASvB,CAAAA,CAAO,CACd,MAAIA,CAAAA,YAAiB,KAAA,CACfA,CAAAA,CAAM,IAAA,GAAS,YAAA,CACX,IAAIM,CAAAA,CAAsB,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAE/C,IAAIH,CAAAA,CAAsB,CAAA,wBAAA,EAA2BH,CAAAA,CAAM,OAAO,CAAA,CAAA,CAAIA,CAAK,CAAA,CAE7EA,CACR,CAAA,OAAE,CACA,YAAA,CAAasB,CAAS,EACxB,CACF,CAEA,MAAc,cAAA,CAAkBpB,CAAAA,CAAgC,CAE9D,IAAMsB,CAAAA,CADctB,CAAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,EAC3B,QAAA,CAAS,kBAAkB,CAAA,CAEvD,GAAI,CAACA,CAAAA,CAAS,GACZ,GAAIsB,CAAAA,CAAQ,CACV,IAAMC,CAAAA,CAAa,MAAMvB,CAAAA,CAAS,IAAA,EAAK,CACvC,MAAM,IAAIH,CAAAA,CAAkB0B,CAAAA,CAAU,KAAA,CAAOvB,CAAAA,CAAS,MAAA,CAAQuB,CAAS,CACzE,CAAA,KAAO,CACL,IAAMC,CAAAA,CAAO,MAAMxB,CAAAA,CAAS,IAAA,EAAK,CACjC,MAAM,IAAIH,CAAAA,CACR,CACE,OAAA,CAAS2B,CAAAA,EAAQ,CAAA,KAAA,EAAQxB,EAAS,MAAM,CAAA,CAAA,EAAIA,CAAAA,CAAS,UAAU,CAAA,CAAA,CAC/D,IAAA,CAAM,YAAA,CACN,IAAA,CAAMA,CAAAA,CAAS,MAAA,CACf,UAAA,CAAY,EACd,CAAA,CACAA,CAAAA,CAAS,MAAA,CACTwB,CACF,CACF,CAGF,OAAIF,CAAAA,CACM,MAAMtB,CAAAA,CAAS,IAAA,EAAK,CAItB,MAAMA,CAAAA,CAAS,IAAA,EACzB,CAEQ,KAAA,CAAMyB,CAAAA,CAA2B,CACvC,OAAO,IAAI,OAAA,CAASC,CAAAA,EAAY,UAAA,CAAWA,CAAAA,CAASD,CAAE,CAAC,CACzD,CACF,CAAA,CChKO,IAAME,CAAAA,CAAN,cAAqC,KAAM,CAChD,WAAA,CAAYzB,CAAAA,CAAiB,CAC3B,KAAA,CAAMA,CAAO,CAAA,CACb,IAAA,CAAK,IAAA,CAAO,yBACd,CACF,EAEO,SAAS0B,CAAAA,CAAoBJ,CAAAA,CAAoB,CACtD,GAAI,CAACA,CAAAA,EAAQA,CAAAA,CAAK,MAAK,GAAM,EAAA,CAC3B,MAAM,IAAIG,CAAAA,CAAuB,8BAA8B,CAAA,CAGjE,GAAIH,CAAAA,CAAK,MAAA,CAAS9B,CAAAA,CAAe,sBAAA,CAC/B,MAAM,IAAIiC,CAAAA,CACR,CAAA,2BAAA,EAA8BjC,CAAAA,CAAe,sBAAsB,CAAA,WAAA,CACrE,CAEJ,CCZO,IAAMmC,CAAAA,CAAN,KAAc,CACnB,WAAA,CAAoBC,CAAAA,CAAwB,CAAxB,IAAA,CAAA,UAAA,CAAAA,EAAyB,CAE7C,MAAM,QAAQC,CAAAA,CAA6BtB,CAAAA,CAAoD,CAE7F,OAAIsB,CAAAA,CAAQ,OAAA,EAAS,IAAA,EACnBH,CAAAA,CAAoBG,CAAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA,CAGnC,IAAA,CAAK,UAAA,CAAW,OAAA,CAA6B,CAClD,OAAQ,MAAA,CACR,IAAA,CAAMtC,CAAAA,CAAc,QAAA,CACpB,IAAA,CAAMsC,CAAAA,CACN,WAAA,CAAatB,CAAAA,EAAS,WACxB,CAAC,CACH,CAEA,MAAM,MAAA,CAAOuB,CAAAA,CAAqBC,CAAAA,CAAsBxB,EAAoD,CAC1G,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAA6B,CAClD,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMhB,CAAAA,CAAc,QAAA,CACpB,IAAA,CAAM,CACJ,SAAA,CAAW,CAAE,EAAA,CAAIuC,CAAY,CAAA,CAC7B,cAAA,CAAgB,UAAA,CAChB,aAAA,CAAeC,CACjB,CAAA,CACA,WAAA,CAAaxB,CAAAA,EAAS,WACxB,CAAC,CACH,CAEA,MAAM,QAAA,CAASuB,CAAAA,CAAqBvB,CAAAA,CAAoD,CACtF,OAAO,IAAA,CAAK,MAAA,CAAOuB,CAAAA,CAAa,WAAA,CAAavB,CAAO,CACtD,CAEA,MAAM,SAAA,CAAUuB,CAAAA,CAAqBvB,CAAAA,CAAoD,CACvF,OAAO,IAAA,CAAK,MAAA,CAAOuB,EAAa,YAAA,CAAcvB,CAAO,CACvD,CAEA,MAAM,QAAA,CAASuB,CAAAA,CAAqBvB,CAAAA,CAAoD,CACtF,OAAO,IAAA,CAAK,MAAA,CAAOuB,CAAAA,CAAa,WAAA,CAAavB,CAAO,CACtD,CAOA,MAAM,UAAA,CAAWA,CAAAA,CAKdyB,CAAAA,CAAuD,CACxD,OAAO,IAAA,CAAK,OAAA,CAAQ,CAClB,SAAA,CAAWzB,CAAAA,CAAQ,SAAA,CACnB,cAAA,CAAgBA,CAAAA,CAAQ,cAAA,EAAkB,UAAA,CAC1C,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAMA,CAAAA,CAAQ,IAAA,CACd,OAAA,CAAS,CACP,aAAA,CAAeA,CAAAA,CAAQ,aACzB,CACF,CACF,CACF,CAAA,CAAGyB,CAAU,CACf,CAKA,MAAM,iBAAA,CAAkBzB,CAAAA,CAKrByB,CAAAA,CAAuD,CACxD,OAAO,IAAA,CAAK,OAAA,CAAQ,CAClB,SAAA,CAAWzB,CAAAA,CAAQ,SAAA,CACnB,cAAA,CAAgBA,CAAAA,CAAQ,gBAAkB,UAAA,CAC1C,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAMA,CAAAA,CAAQ,IAAA,CACd,OAAA,CAAS,CACP,GAAA,CAAKA,CAAAA,CAAQ,GACf,CACF,CACF,CACF,EAAGyB,CAAU,CACf,CACF,EC5FO,IAAMC,CAAAA,CAAN,KAAqB,CAC1B,WAAA,CAAoBL,CAAAA,CAAwB,CAAxB,IAAA,CAAA,UAAA,CAAAA,EAAyB,CAE7C,MAAM,MAAA,CACJC,EACAtB,CAAAA,CACmC,CAEnC,IAAM2B,CAAAA,CAAO,CACX,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAML,CAAAA,CAAQ,IAAA,CACd,OAAA,CAAS,CACP,GAAA,CAAKA,CAAAA,CAAQ,IACb,WAAA,CAAaA,CAAAA,CAAQ,WAAA,EAAe,IACtC,CACF,CACF,CACF,CAAA,CAEA,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAAkC,CACvD,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMtC,EAAc,mBAAA,CACpB,IAAA,CAAA2C,CAAAA,CACA,WAAA,CAAa3B,CAAAA,EAAS,WACxB,CAAC,CACH,CACF,ECxBO,IAAM4B,CAAAA,CAAN,KAAoB,CACzB,WAAA,CAAoBP,CAAAA,CAAwB,CAAxB,IAAA,CAAA,UAAA,CAAAA,EAAyB,CAM7C,MAAM,QAAA,CAASC,CAAAA,CAAuCtB,CAAAA,CAA8D,CAClH,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAAuC,CAC5D,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMhB,CAAAA,CAAc,sBAAA,CACpB,IAAA,CAAMsC,CAAAA,CACN,WAAA,CAAatB,CAAAA,EAAS,WACxB,CAAC,CACH,CAMA,MAAM,SAAA,CAAU6B,CAAAA,CAA4B7B,CAAAA,CAA8D,CACxG,IAAM8B,EAAW,KAAA,CAAM,OAAA,CAAQD,CAAO,CAAA,CAClCA,CAAAA,CAAQ,GAAA,CAAIE,CAAAA,GAAO,CAAE,EAAA,CAAAA,CAAG,CAAA,CAAE,CAAA,CAC1B,CAAC,CAAE,EAAA,CAAIF,CAAQ,CAAC,CAAA,CAEpB,OAAO,IAAA,CAAK,QAAA,CAAS,CACnB,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAS,CAAC,YAAY,CACxB,CAAA,CAAG9B,CAAO,CACZ,CAKA,MAAM,YAAY6B,CAAAA,CAA4B7B,CAAAA,CAA8D,CAC1G,IAAM8B,CAAAA,CAAW,KAAA,CAAM,OAAA,CAAQD,CAAO,CAAA,CAClCA,CAAAA,CAAQ,GAAA,CAAIE,CAAAA,GAAO,CAAE,EAAA,CAAAA,CAAG,CAAA,CAAE,EAC1B,CAAC,CAAE,EAAA,CAAIF,CAAQ,CAAC,CAAA,CAEpB,OAAO,IAAA,CAAK,QAAA,CAAS,CACnB,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAS,CAAC,cAAc,CAC1B,EAAG9B,CAAO,CACZ,CAOA,MAAM,OAAA,CAAQ6B,CAAAA,CAA4B7B,CAAAA,CAA8D,CACtG,IAAM8B,CAAAA,CAAW,KAAA,CAAM,OAAA,CAAQD,CAAO,CAAA,CAClCA,CAAAA,CAAQ,GAAA,CAAIE,IAAO,CAAE,EAAA,CAAAA,CAAG,CAAA,CAAE,CAAA,CAC1B,CAAC,CAAE,EAAA,CAAIF,CAAQ,CAAC,CAAA,CAEpB,OAAO,IAAA,CAAK,QAAA,CAAS,CACnB,QAAA,CAAAC,EACA,OAAA,CAAS,CAAC,UAAU,CACtB,CAAA,CAAG9B,CAAO,CACZ,CAMA,MAAM,SAAA,CAAU6B,CAAAA,CAA4B7B,CAAAA,CAA8D,CACxG,IAAM8B,CAAAA,CAAW,KAAA,CAAM,OAAA,CAAQD,CAAO,CAAA,CAClCA,CAAAA,CAAQ,GAAA,CAAIE,CAAAA,GAAO,CAAE,EAAA,CAAAA,CAAG,CAAA,CAAE,CAAA,CAC1B,CAAC,CAAE,EAAA,CAAIF,CAAQ,CAAC,EAEpB,OAAO,IAAA,CAAK,QAAA,CAAS,CACnB,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAS,CAAC,YAAY,CACxB,CAAA,CAAG9B,CAAO,CACZ,CAKA,MAAM,UAAA,CAAW6B,EAA4B7B,CAAAA,CAA8D,CACzG,IAAM8B,CAAAA,CAAW,KAAA,CAAM,OAAA,CAAQD,CAAO,CAAA,CAClCA,CAAAA,CAAQ,GAAA,CAAIE,CAAAA,GAAO,CAAE,EAAA,CAAAA,CAAG,CAAA,CAAE,CAAA,CAC1B,CAAC,CAAE,EAAA,CAAIF,CAAQ,CAAC,CAAA,CAEpB,OAAO,IAAA,CAAK,QAAA,CAAS,CACnB,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAS,CAAC,cAAc,CAC1B,CAAA,CAAG9B,CAAO,CACZ,CAKA,MAAM,YAAA,CAAa6B,CAAAA,CAA4B7B,CAAAA,CAA8D,CAC3G,IAAM8B,CAAAA,CAAW,KAAA,CAAM,OAAA,CAAQD,CAAO,CAAA,CAClCA,CAAAA,CAAQ,GAAA,CAAIE,CAAAA,GAAO,CAAE,EAAA,CAAAA,CAAG,CAAA,CAAE,CAAA,CAC1B,CAAC,CAAE,EAAA,CAAIF,CAAQ,CAAC,CAAA,CAEpB,OAAO,IAAA,CAAK,QAAA,CAAS,CACnB,QAAA,CAAAC,CAAAA,CACA,QAAS,CAAC,YAAA,CAAc,cAAc,CACxC,CAAA,CAAG9B,CAAO,CACZ,CACF,EC3GO,IAAMgC,CAAAA,CAAN,cAAsC,KAAM,CACjD,WAAA,CAAYvC,CAAAA,CAAiB,CAC3B,KAAA,CAAMA,CAAO,CAAA,CACb,IAAA,CAAK,IAAA,CAAO,0BACd,CACF,EAEO,SAASwC,CAAAA,CAAwBC,CAAAA,CAA0C,CAChF,GAAIA,CAAAA,CAAS,MAAA,GAAW,CAAA,CACtB,MAAM,IAAIF,CAAAA,CAAwB,+CAA+C,CAAA,CAGnF,GAAIE,CAAAA,CAAS,MAAA,CAAS/C,CAAAA,CAAgB,oBAAA,CACpC,MAAM,IAAI6C,CAAAA,CACR,CAAA,uCAAA,EAA0C7C,CAAAA,CAAgB,oBAAoB,WAChF,CAAA,CAGF+C,CAAAA,CAAS,OAAA,CAAQ,CAACC,CAAAA,CAASC,CAAAA,GAAU,CACnCC,CAAAA,CAAuBF,CAAAA,CAASC,CAAK,EACvC,CAAC,EACH,CAEO,SAASC,CAAAA,CAAuBF,EAAiCC,CAAAA,CAAqB,CAC3F,GAAI,CAACD,CAAAA,CAAQ,KAAA,EAASA,CAAAA,CAAQ,KAAA,CAAM,IAAA,EAAK,GAAM,EAAA,CAC7C,MAAM,IAAIH,CAAAA,CAAwB,CAAA,QAAA,EAAWI,CAAK,qBAAqB,CAAA,CAGzE,GAAID,CAAAA,CAAQ,KAAA,CAAM,MAAA,CAAShD,CAAAA,CAAgB,uBAAA,CACzC,MAAM,IAAI6C,CAAAA,CACR,CAAA,QAAA,EAAWI,CAAK,CAAA,sBAAA,EAAyBjD,CAAAA,CAAgB,uBAAuB,CAAA,WAAA,CAClF,EAGF,GAAIgD,CAAAA,CAAQ,QAAA,EAAYA,CAAAA,CAAQ,QAAA,CAAS,MAAA,CAAShD,CAAAA,CAAgB,0BAAA,CAChE,MAAM,IAAI6C,CAAAA,CACR,CAAA,QAAA,EAAWI,CAAK,CAAA,yBAAA,EAA4BjD,CAAAA,CAAgB,0BAA0B,aACxF,CAAA,CAGF,GAAIgD,CAAAA,CAAQ,SAAA,EAAa,CAACG,CAAAA,CAAWH,CAAAA,CAAQ,SAAS,CAAA,CACpD,MAAM,IAAIH,CAAAA,CAAwB,CAAA,QAAA,EAAWI,CAAK,CAAA,yBAAA,CAA2B,CAAA,CAe/E,GAZID,CAAAA,CAAQ,OAAA,EACVI,CAAAA,CAAgBJ,CAAAA,CAAQ,OAAA,CAAS,CAAA,QAAA,EAAWC,CAAK,CAAA,CAAE,CAAA,CAWjD,CAP0B,CAAC,EAC7BD,CAAAA,CAAQ,QAAA,EACRA,CAAAA,CAAQ,SAAA,EACRA,EAAQ,cAAA,EACPA,CAAAA,CAAQ,OAAA,EAAWA,CAAAA,CAAQ,OAAA,CAAQ,MAAA,CAAS,CAAA,CAAA,CAI7C,MAAM,IAAIH,CAAAA,CACR,CAAA,QAAA,EAAWI,CAAK,CAAA,yDAAA,CAClB,CAEJ,CAEO,SAASI,CAAAA,CAAuBzB,CAAAA,CAAc0B,CAAAA,CAAyB,CAC5E,GAAI,CAAC1B,CAAAA,EAAQA,CAAAA,CAAK,IAAA,EAAK,GAAM,EAAA,CAC3B,MAAM,IAAIiB,CAAAA,CAAwB,kCAAkC,CAAA,CAGtE,GAAIjB,CAAAA,CAAK,MAAA,CAAS5B,CAAAA,CAAgB,qBAAA,CAChC,MAAM,IAAI6C,CAAAA,CACR,CAAA,mCAAA,EAAsC7C,CAAAA,CAAgB,qBAAqB,CAAA,WAAA,CAC7E,CAAA,CAGF,GAAIsD,CAAAA,CAAQ,MAAA,GAAW,CAAA,CACrB,MAAM,IAAIT,CAAAA,CAAwB,6CAA6C,CAAA,CAGjFO,CAAAA,CAAgBE,CAAAA,CAAS,iBAAiB,EAC5C,CAEO,SAASC,CAAAA,CAAsBP,CAAAA,CAAqC,CACzE,GAAI,CAACA,CAAAA,CAAQ,WACX,MAAM,IAAIH,CAAAA,CAAwB,6CAA6C,CAAA,CAGjF,GAAI,CAACG,CAAAA,CAAQ,GAAA,EAAO,CAACA,CAAAA,CAAQ,aAAA,CAC3B,MAAM,IAAIH,CAAAA,CAAwB,8DAA8D,EAGlG,GAAIG,CAAAA,CAAQ,GAAA,EAAOA,CAAAA,CAAQ,aAAA,CACzB,MAAM,IAAIH,CAAAA,CACR,+DACF,CAAA,CAGF,GAAIG,CAAAA,CAAQ,GAAA,EAAO,CAACG,CAAAA,CAAWH,CAAAA,CAAQ,GAAG,CAAA,CACxC,MAAM,IAAIH,CAAAA,CAAwB,kCAAkC,CAAA,CAGtE,GAAIG,CAAAA,CAAQ,OAAA,CAAS,CACnB,GAAIA,CAAAA,CAAQ,OAAA,CAAQ,MAAA,CAAShD,CAAAA,CAAgB,uBAAA,CAC3C,MAAM,IAAI6C,CAAAA,CACR,CAAA,qCAAA,EAAwC7C,CAAAA,CAAgB,uBAAuB,CAAA,QAAA,CACjF,CAAA,CAEFoD,CAAAA,CAAgBJ,CAAAA,CAAQ,OAAA,CAAS,gBAAgB,EACnD,CACF,CAEO,SAASI,CAAAA,CAAgBE,EAAmBE,CAAAA,CAAuB,CACxE,GAAIF,CAAAA,CAAQ,MAAA,CAAStD,CAAAA,CAAgB,iBAAA,CACnC,MAAM,IAAI6C,CAAAA,CACR,CAAA,EAAGW,CAAO,CAAA,uBAAA,EAA0BxD,CAAAA,CAAgB,iBAAiB,CAAA,QAAA,CACvE,CAAA,CAGFsD,CAAAA,CAAQ,OAAA,CAAQ,CAACG,CAAAA,CAAQR,CAAAA,GAAU,CACjCS,CAAAA,CAAeD,CAAAA,CAAQ,CAAA,EAAGD,CAAO,CAAA,QAAA,EAAWP,CAAK,CAAA,CAAE,EACrD,CAAC,EACH,CAEO,SAASS,CAAAA,CAAeD,CAAAA,CAAgBD,CAAAA,CAAuB,CACpE,GAAI,CAACC,CAAAA,CAAO,IAAA,CACV,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,kBAAA,CAAoB,EAIlE,GAAIC,CAAAA,CAAO,IAAA,GAAS,gBAAA,GAAqB,CAACA,CAAAA,CAAO,KAAA,EAASA,CAAAA,CAAO,KAAA,CAAM,IAAA,EAAK,GAAM,EAAA,CAAA,CAChF,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,wBAAA,EAA2BC,CAAAA,CAAO,IAAI,CAAA,QAAA,CAAU,CAAA,CAG9F,GAAIA,CAAAA,CAAO,KAAA,EAASA,CAAAA,CAAO,KAAA,CAAM,MAAA,CAASzD,CAAAA,CAAgB,sBAAA,CACxD,MAAM,IAAI6C,CAAAA,CACR,GAAGW,CAAO,CAAA,sBAAA,EAAyBxD,CAAAA,CAAgB,sBAAsB,CAAA,WAAA,CAC3E,CAAA,CAIF,OAAQyD,CAAAA,CAAO,IAAA,EACb,KAAK,SAAA,CACH,GAAI,CAACA,CAAAA,CAAO,GAAA,CACV,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,qCAAA,CAAuC,CAAA,CAErF,GAAI,CAACL,CAAAA,CAAWM,CAAAA,CAAO,GAAG,CAAA,CACxB,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,uCAAA,CAAyC,CAAA,CAEvF,MAEF,KAAK,UAAA,CACH,GAAI,CAACC,CAAAA,CAAO,OAAA,CACV,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,0CAAA,CAA4C,CAAA,CAE1F,GAAIC,CAAAA,CAAO,OAAA,CAAQ,MAAA,CAASzD,CAAAA,CAAgB,0BAAA,CAC1C,MAAM,IAAI6C,CAAAA,CACR,CAAA,EAAGW,CAAO,CAAA,wBAAA,EAA2BxD,CAAAA,CAAgB,0BAA0B,CAAA,WAAA,CACjF,CAAA,CAEF,MAEF,KAAK,cAAA,CACH,GAAI,CAACyD,CAAAA,CAAO,OAAA,CACV,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,8CAAA,CAAgD,CAAA,CAG9F,GAAI,CAACC,CAAAA,CAAO,QAAQ,UAAA,CAAW,GAAG,CAAA,CAChC,MAAM,IAAIZ,CAAAA,CACR,CAAA,EAAGW,CAAO,CAAA,4DAAA,CACZ,CAAA,CAEF,MAEF,KAAK,WAAA,CAEH,MAEF,KAAK,cAAA,CACH,GAAI,CAACC,CAAAA,CAAO,GAAA,CACV,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,0CAAA,CAA4C,CAAA,CAE1F,GAAI,CAACL,CAAAA,CAAWM,CAAAA,CAAO,GAAG,CAAA,CACxB,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,4CAAA,CAA8C,CAAA,CAE5F,MAKJ,CAGA,GAAIC,CAAAA,CAAO,IAAA,GAAS,SAAA,EAAaA,CAAAA,CAAO,sBAAwBA,CAAAA,CAAO,YAAA,EACjE,CAACN,CAAAA,CAAWM,CAAAA,CAAO,YAAY,CAAA,CACjC,MAAM,IAAIZ,CAAAA,CAAwB,CAAA,EAAGW,CAAO,CAAA,4BAAA,CAA8B,CAGhF,CAEA,SAASL,EAAWrC,CAAAA,CAAsB,CACxC,GAAI,CAEF,OADkB,IAAI,GAAA,CAAIA,CAAG,CAAA,CACZ,QAAA,GAAa,QAChC,CAAA,KAAQ,CACN,OAAO,MACT,CACF,CChMO,IAAM6C,CAAAA,CAAN,KAAmB,CACxB,WAAA,CAAoBzB,CAAAA,CAAwB,CAAxB,IAAA,CAAA,UAAA,CAAAA,EAAyB,CAE7C,MAAM,OAAA,CAAQrB,CAAAA,CAOXyB,CAAAA,CAAuD,CAExDQ,CAAAA,CAAwBjC,EAAQ,QAAQ,CAAA,CAExC,IAAM+C,CAAAA,CAAkC,CACtC,aAAA,CAAe,SAAA,CACf,QAAA,CAAU/C,CAAAA,CAAQ,QAAA,CAClB,kBAAA,CAAoBA,CAAAA,CAAQ,kBAC9B,CAAA,CAEMsB,CAAAA,CAA8B,CAClC,SAAA,CAAWtB,CAAAA,CAAQ,SAAA,CACnB,cAAA,CAAgBA,CAAAA,CAAQ,cAAA,EAAkB,QAAA,CAC1C,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAM,UAAA,CACN,OAAA,CAAA+C,CACF,CACF,EACA,iBAAA,CAAmB/C,CAAAA,CAAQ,iBAAA,CAC3B,GAAA,CAAKA,CAAAA,CAAQ,GACf,CAAA,CAEA,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAA6B,CAClD,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMhB,CAAAA,CAAc,SACpB,IAAA,CAAMsC,CAAAA,CACN,WAAA,CAAaG,CAAAA,EAAY,WAC3B,CAAC,CACH,CAEA,MAAM,MAAA,CAAOzB,CAAAA,CAOVyB,CAAAA,CAAuD,CAExDe,CAAAA,CAAuBxC,CAAAA,CAAQ,IAAA,CAAMA,EAAQ,OAAO,CAAA,CAEpD,IAAM+C,CAAAA,CAAiC,CACrC,aAAA,CAAe,QAAA,CACf,IAAA,CAAM/C,CAAAA,CAAQ,IAAA,CACd,OAAA,CAASA,CAAAA,CAAQ,OACnB,CAAA,CAEMsB,CAAAA,CAA8B,CAClC,UAAWtB,CAAAA,CAAQ,SAAA,CACnB,cAAA,CAAgBA,CAAAA,CAAQ,cAAA,EAAkB,QAAA,CAC1C,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAM,UAAA,CACN,OAAA,CAAA+C,CACF,CACF,CAAA,CACA,kBAAmB/C,CAAAA,CAAQ,iBAAA,CAC3B,GAAA,CAAKA,CAAAA,CAAQ,GACf,CAAA,CAEA,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAA6B,CAClD,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMhB,CAAAA,CAAc,QAAA,CACpB,KAAMsC,CAAAA,CACN,WAAA,CAAaG,CAAAA,EAAY,WAC3B,CAAC,CACH,CAEA,MAAM,KAAA,CAAMzB,CAAAA,CAMTyB,CAAAA,CAAuD,CAExDiB,CAAAA,CAAsB1C,CAAAA,CAAQ,OAAO,CAAA,CAErC,IAAM+C,CAAAA,CAAgC,CACpC,aAAA,CAAe,OAAA,CACf,QAAA,CAAU,CAAC/C,CAAAA,CAAQ,OAAO,CAC5B,CAAA,CAEMsB,CAAAA,CAA8B,CAClC,SAAA,CAAWtB,CAAAA,CAAQ,SAAA,CACnB,cAAA,CAAgBA,CAAAA,CAAQ,cAAA,EAAkB,QAAA,CAC1C,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAM,UAAA,CACN,OAAA,CAAA+C,CACF,CACF,CAAA,CACA,iBAAA,CAAmB/C,CAAAA,CAAQ,iBAAA,CAC3B,IAAKA,CAAAA,CAAQ,GACf,CAAA,CAEA,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAA6B,CAClD,MAAA,CAAQ,MAAA,CACR,IAAA,CAAMhB,CAAAA,CAAc,QAAA,CACpB,IAAA,CAAMsC,CAAAA,CACN,WAAA,CAAaG,GAAY,WAC3B,CAAC,CACH,CAEA,MAAM,OAAA,CAAQzB,CAAAA,CAMXyB,CAAAA,CAAuD,CACxD,IAAMsB,CAAAA,CAAkC,CACtC,aAAA,CAAe,SAAA,CACf,QAAA,CAAU/C,CAAAA,CAAQ,QACpB,CAAA,CAEMsB,CAAAA,CAA8B,CAClC,SAAA,CAAWtB,CAAAA,CAAQ,SAAA,CACnB,cAAA,CAAgBA,CAAAA,CAAQ,cAAA,EAAkB,QAAA,CAC1C,OAAA,CAAS,CACP,UAAA,CAAY,CACV,IAAA,CAAM,UAAA,CACN,QAAA+C,CACF,CACF,CAAA,CACA,iBAAA,CAAmB/C,CAAAA,CAAQ,iBAAA,CAC3B,GAAA,CAAKA,CAAAA,CAAQ,GACf,CAAA,CAEA,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAA6B,CAClD,MAAA,CAAQ,OACR,IAAA,CAAMhB,CAAAA,CAAc,QAAA,CACpB,IAAA,CAAMsC,CAAAA,CACN,WAAA,CAAaG,CAAAA,EAAY,WAC3B,CAAC,CACH,CACF,EC7JO,IAAMuB,CAAAA,CAAN,KAAiB,CACtB,YAAoB3B,CAAAA,CAAwB,CAAxB,IAAA,CAAA,UAAA,CAAAA,EAAyB,CAM7C,MAAM,GAAA,CAAIC,CAAAA,CAA4BtB,CAAAA,CAA4C,CAChF,GAAM,CAAE,IAAA,CAAAiD,CAAAA,CAAM,MAAA,CAAAC,CAAAA,CAAS,CAAC,YAAA,CAAc,WAAW,CAAE,CAAA,CAAI5B,CAAAA,CAEjD6B,CAAAA,CAAc,IAAI,eAAA,CAAgB,CACtC,MAAA,CAAQD,CAAAA,CAAO,IAAA,CAAK,GAAG,CACzB,CAAC,CAAA,CAED,OAAO,IAAA,CAAK,UAAA,CAAW,OAAA,CAAqB,CAC1C,MAAA,CAAQ,KAAA,CACR,IAAA,CAAM,CAAA,CAAA,EAAID,CAAI,CAAA,CAAA,EAAIE,CAAAA,CAAY,QAAA,EAAU,CAAA,CAAA,CACxC,IAAA,CAAM,OACN,WAAA,CAAanD,CAAAA,EAAS,WACxB,CAAC,CACH,CAKA,MAAM,QAAA,CAASiD,CAAAA,CAAcjD,CAAAA,CAA4C,CACvE,OAAO,IAAA,CAAK,GAAA,CAAI,CACd,IAAA,CAAAiD,EACA,MAAA,CAAQ,CAAC,YAAA,CAAc,WAAA,CAAa,aAAa,CACnD,CAAA,CAAGjD,CAAO,CACZ,CAKA,MAAM,OAAA,CAAQiD,CAAAA,CAAcjD,CAAAA,CAA4C,CACtE,OAAO,KAAK,GAAA,CAAI,CACd,IAAA,CAAAiD,CAAAA,CACA,MAAA,CAAQ,CAAC,IAAA,CAAM,MAAA,CAAQ,YAAA,CAAc,WAAA,CAAa,aAAA,CAAe,QAAA,CAAU,UAAA,CAAY,QAAQ,CACjG,CAAA,CAAGjD,CAAO,CACZ,CAKA,MAAM,OAAA,CAAQiD,CAAAA,CAAcjD,CAAAA,CAA4C,CACtE,OAAO,IAAA,CAAK,GAAA,CAAI,CACd,IAAA,CAAAiD,CAAAA,CACA,MAAA,CAAQ,CAAC,YAAA,CAAc,WAAW,CACpC,CAAA,CAAGjD,CAAO,CACZ,CAKA,MAAM,iBAAA,CAAkBiD,CAAAA,CAAcjD,CAAAA,CAA4C,CAChF,OAAO,IAAA,CAAK,GAAA,CAAI,CACd,IAAA,CAAAiD,CAAAA,CACA,OAAQ,CAAC,aAAa,CACxB,CAAA,CAAGjD,CAAO,CACZ,CACF,EClDO,IAAMoD,CAAAA,CAAN,KAAgB,CACL,IAAA,CACA,WAAA,CACA,UAAA,CACA,SAAA,CACA,QAEC,UAAA,CAEjB,WAAA,CAAYrD,CAAAA,CAA0B,EAAC,CAAG,CACxC,IAAA,CAAK,cAAA,CAAeA,CAAM,CAAA,CAE1B,IAAMsD,CAAAA,CAA6B,CACjC,WAAA,CAAatD,CAAAA,CAAO,WAAA,CACpB,OAAA,CAASA,CAAAA,CAAO,OAAA,EAAWjB,CAAAA,CAC3B,OAAA,CAASiB,CAAAA,CAAO,OAAA,CAChB,OAAA,CAASA,CAAAA,CAAO,OAAA,CAChB,UAAA,CAAYA,CAAAA,CAAO,UACrB,CAAA,CAEA,IAAA,CAAK,UAAA,CAAa,IAAID,CAAAA,CAAWuD,CAAY,CAAA,CAG7C,IAAA,CAAK,IAAA,CAAO,IAAIjC,CAAAA,CAAQ,IAAA,CAAK,UAAU,CAAA,CACvC,IAAA,CAAK,WAAA,CAAc,IAAIM,CAAAA,CAAe,IAAA,CAAK,UAAU,EACrD,IAAA,CAAK,UAAA,CAAa,IAAIE,CAAAA,CAAc,IAAA,CAAK,UAAU,CAAA,CACnD,IAAA,CAAK,SAAA,CAAY,IAAIkB,CAAAA,CAAa,IAAA,CAAK,UAAU,CAAA,CACjD,IAAA,CAAK,OAAA,CAAU,IAAIE,CAAAA,CAAW,IAAA,CAAK,UAAU,EAC/C,CAEQ,cAAA,CAAejD,CAAAA,CAA+B,CACpD,GAAIA,CAAAA,CAAO,WAAA,GAAgB,MAAA,GACrB,OAAOA,CAAAA,CAAO,WAAA,EAAgB,QAAA,EAAYA,EAAO,WAAA,CAAY,IAAA,EAAK,GAAM,EAAA,CAAA,CAC1E,MAAM,IAAIF,CAAAA,CAAqB,yCAAyC,CAAA,CAI5E,GAAIE,CAAAA,CAAO,OAAA,EAAW,OAAOA,CAAAA,CAAO,OAAA,EAAY,QAAA,CAC9C,MAAM,IAAIF,CAAAA,CAAqB,8BAA8B,CAAA,CAG/D,GAAIE,CAAAA,CAAO,OAAA,GAAY,OAAOA,CAAAA,CAAO,OAAA,EAAY,QAAA,EAAYA,CAAAA,CAAO,OAAA,EAAW,CAAA,CAAA,CAC7E,MAAM,IAAIF,EAAqB,mCAAmC,CAAA,CAGpE,GAAIE,CAAAA,CAAO,UAAA,GAAe,OAAOA,CAAAA,CAAO,UAAA,EAAe,QAAA,EAAYA,CAAAA,CAAO,UAAA,CAAa,CAAA,CAAA,CACrF,MAAM,IAAIF,CAAAA,CAAqB,2CAA2C,CAE9E,CACF","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}"]}
|