@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 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=f;exports.MessageValidationError=d;exports.Messenger=M;exports.MessengerAPIError=c;exports.MessengerConfigError=m;exports.MessengerNetworkError=l;exports.MessengerTimeoutError=u;exports.ModerationAPI=_;exports.ProfileAPI=E;exports.SendAPI=T;exports.TEMPLATE_LIMITS=i;exports.TemplateValidationError=n;exports.TemplatesAPI=y;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var R="v23.0",b="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},A={TEXT_MESSAGE_MAX_CHARS:2e3},v={IMAGE_MAX_SIZE:8*1024*1024,OTHER_MAX_SIZE:25*1024*1024,VIDEO_TIMEOUT:75,OTHER_TIMEOUT:10},i={GENERIC_ELEMENTS_MAX:10,GENERIC_TITLE_MAX_CHARS:80,GENERIC_SUBTITLE_MAX_CHARS:80,BUTTON_TEXT_MAX_CHARS:640,BUTTONS_MAX_COUNT:3,BUTTON_TITLE_MAX_CHARS:20,POSTBACK_PAYLOAD_MAX_CHARS:1e3,MEDIA_ELEMENTS_COUNT:1,MEDIA_BUTTONS_MAX_COUNT:3};var m=class extends Error{code;type;subcode;fbtrace_id;statusCode;response;constructor(e,s,r){super(e.message),this.name="MessengerAPIError",this.code=e.code,this.type=e.type,this.subcode=e.error_subcode,this.fbtrace_id=e.fbtrace_id,this.statusCode=s,this.response=r;}},l=class extends Error{cause;constructor(e,s){super(e),this.name="MessengerNetworkError",this.cause=s;}},T=class extends Error{timeout;constructor(e){super(`Request timed out after ${e}ms`),this.name="MessengerTimeoutError",this.timeout=e;}},c=class extends Error{constructor(e){super(e),this.name="MessengerConfigError";}};var f=class{config;constructor(e){this.config={accessToken:e.accessToken,version:e.version,baseUrl:e.baseUrl||b,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query,e.accessToken),r;for(let n=0;n<=this.config.maxRetries;n++)try{let a=await this.makeRequest(s,e);return await this.handleResponse(a)}catch(a){if(r=a,a instanceof m&&a.statusCode>=400&&a.statusCode<500||n===this.config.maxRetries)throw a;await this.delay(1e3*(n+1));}throw r||new Error("Unknown error occurred")}buildUrl(e,s,r){let n=new URL(`${this.config.baseUrl}/${this.config.version}${e}`),a=r||this.config.accessToken;if(!a)throw new Error("Access token is required. Provide it in constructor or method options.");return n.searchParams.append("access_token",a),s&&Object.entries(s).forEach(([M,U])=>{n.searchParams.append(M,String(U));}),n.toString()}async makeRequest(e,s){let r=new AbortController,n=setTimeout(()=>r.abort(),this.config.timeout);try{let a={method:s.method,headers:{"Content-Type":"application/json"},signal:r.signal};return s.body&&(a.body=JSON.stringify(s.body)),await fetch(e,a)}catch(a){throw a instanceof Error?a.name==="AbortError"?new T(this.config.timeout):new l(`Network request failed: ${a.message}`,a):a}finally{clearTimeout(n);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let n=await e.json();throw new m(n.error,e.status,n)}else {let n=await e.text();throw new m({message:n||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,n)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var u=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function w(t){if(!t||t.trim()==="")throw new u("Text message cannot be empty");if(t.length>A.TEXT_MESSAGE_MAX_CHARS)throw new u(`Text message cannot exceed ${A.TEXT_MESSAGE_MAX_CHARS} characters`)}var d=class{constructor(e){this.httpClient=e;}async message(e,s){return e.message?.text&&w(e.message.text),this.httpClient.request({method:"POST",path:p.MESSAGES,body:e,accessToken:s?.accessToken})}async action(e,s,r){return this.httpClient.request({method:"POST",path:p.MESSAGES,body:{recipient:{id:e},messaging_type:"RESPONSE",sender_action:s},accessToken:r?.accessToken})}async typingOn(e,s){return this.action(e,"typing_on",s)}async typingOff(e,s){return this.action(e,"typing_off",s)}async markSeen(e,s){return this.action(e,"mark_seen",s)}async attachment(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{attachment_id:e.attachment_id}}}},s)}async attachmentFromUrl(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{url:e.url}}}},s)}};var h=class{constructor(e){this.httpClient=e;}async upload(e,s){let r={message:{attachment:{type:e.type,payload:{url:e.url,is_reusable:e.is_reusable??true}}}};return this.httpClient.request({method:"POST",path:p.MESSAGE_ATTACHMENTS,body:r,accessToken:s?.accessToken})}};var g=class{constructor(e){this.httpClient=e;}async moderate(e,s){return this.httpClient.request({method:"POST",path:p.MODERATE_CONVERSATIONS,body:e,accessToken:s?.accessToken})}async blockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user"]},s)}async unblockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unblock_user"]},s)}async banUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["ban_user"]},s)}async unbanUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unban_user"]},s)}async moveToSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["move_to_spam"]},s)}async blockAndSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user","move_to_spam"]},s)}};var o=class extends Error{constructor(e){super(e),this.name="TemplateValidationError";}};function C(t){if(t.length===0)throw new o("Generic template must have at least 1 element");if(t.length>i.GENERIC_ELEMENTS_MAX)throw new o(`Generic template cannot have more than ${i.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{G(e,s);});}function G(t,e){if(!t.title||t.title.trim()==="")throw new o(`Element ${e}: title is required`);if(t.title.length>i.GENERIC_TITLE_MAX_CHARS)throw new o(`Element ${e}: title cannot exceed ${i.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>i.GENERIC_SUBTITLE_MAX_CHARS)throw new o(`Element ${e}: subtitle cannot exceed ${i.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!_(t.image_url))throw new o(`Element ${e}: image_url must be HTTPS`);if(t.buttons&&P(t.buttons,`Element ${e}`),!!!(t.subtitle||t.image_url||t.default_action||t.buttons&&t.buttons.length>0))throw new o(`Element ${e}: must have at least one additional property beyond title`)}function O(t,e){if(!t||t.trim()==="")throw new o("Button template text is required");if(t.length>i.BUTTON_TEXT_MAX_CHARS)throw new o(`Button template text cannot exceed ${i.BUTTON_TEXT_MAX_CHARS} characters`);if(e.length===0)throw new o("Button template must have at least 1 button");P(e,"Button template");}function I(t){if(!t.media_type)throw new o("Media template element must have media_type");if(!t.url&&!t.attachment_id)throw new o("Media template element must have either url or attachment_id");if(t.url&&t.attachment_id)throw new o("Media template element cannot have both url and attachment_id");if(t.url&&!_(t.url))throw new o("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>i.MEDIA_BUTTONS_MAX_COUNT)throw new o(`Media template cannot have more than ${i.MEDIA_BUTTONS_MAX_COUNT} buttons`);P(t.buttons,"Media template");}}function P(t,e){if(t.length>i.BUTTONS_MAX_COUNT)throw new o(`${e} cannot have more than ${i.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{H(s,`${e} button ${r}`);});}function H(t,e){if(!t.type)throw new o(`${e}: type is required`);if(t.type!=="account_unlink"&&(!t.title||t.title.trim()===""))throw new o(`${e}: title is required for ${t.type} buttons`);if(t.title&&t.title.length>i.BUTTON_TITLE_MAX_CHARS)throw new o(`${e}: title cannot exceed ${i.BUTTON_TITLE_MAX_CHARS} characters`);switch(t.type){case "web_url":if(!t.url)throw new o(`${e}: url is required for web_url buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for web_url buttons`);break;case "postback":if(!t.payload)throw new o(`${e}: payload is required for postback buttons`);if(t.payload.length>i.POSTBACK_PAYLOAD_MAX_CHARS)throw new o(`${e}: payload cannot exceed ${i.POSTBACK_PAYLOAD_MAX_CHARS} characters`);break;case "phone_number":if(!t.payload)throw new o(`${e}: payload is required for phone_number buttons`);if(!t.payload.startsWith("+"))throw new o(`${e}: phone_number payload must start with + (e.g., +1234567890)`);break;case "game_play":break;case "account_link":if(!t.url)throw new o(`${e}: url is required for account_link buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for account_link buttons`);break;}if(t.type==="web_url"&&t.messenger_extensions&&t.fallback_url&&!_(t.fallback_url))throw new o(`${e}: fallback_url must be HTTPS`)}function _(t){try{return new URL(t).protocol==="https:"}catch{return false}}var y=class{constructor(e){this.httpClient=e;}async generic(e,s){C(e.elements);let r={template_type:"generic",elements:e.elements,image_aspect_ratio:e.image_aspect_ratio},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async button(e,s){O(e.text,e.buttons);let r={template_type:"button",text:e.text,buttons:e.buttons},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async media(e,s){I(e.element);let r={template_type:"media",elements:[e.element]},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async product(e,s){let r={template_type:"product",elements:e.elements},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}};var E=class{constructor(e){this.httpClient=e;}async get(e,s){let{psid:r,fields:n=["first_name","last_name"]}=e,a=new URLSearchParams({fields:n.join(",")});return this.httpClient.request({method:"GET",path:`/${r}?${a.toString()}`,body:void 0,accessToken:s?.accessToken})}async getBasic(e,s){return this.get({psid:e,fields:["first_name","last_name","profile_pic"]},s)}async getFull(e,s){return this.get({psid:e,fields:["id","name","first_name","last_name","profile_pic","locale","timezone","gender"]},s)}async getName(e,s){return this.get({psid:e,fields:["first_name","last_name"]},s)}async getProfilePicture(e,s){return this.get({psid:e,fields:["profile_pic"]},s)}};var S=class{send;attachments;moderation;templates;profile;httpClient;constructor(e={}){this.validateConfig(e);let s={accessToken:e.accessToken,version:e.version||R,baseUrl:e.baseUrl,timeout:e.timeout,maxRetries:e.maxRetries};this.httpClient=new f(s),this.send=new d(this.httpClient),this.attachments=new h(this.httpClient),this.moderation=new g(this.httpClient),this.templates=new y(this.httpClient),this.profile=new E(this.httpClient);}validateConfig(e){if(e.accessToken!==void 0&&(typeof e.accessToken!="string"||e.accessToken.trim()===""))throw new c("Access token must be a non-empty string");if(e.version&&typeof e.version!="string")throw new c("API version must be a string");if(e.timeout&&(typeof e.timeout!="number"||e.timeout<=0))throw new c("Timeout must be a positive number");if(e.maxRetries&&(typeof e.maxRetries!="number"||e.maxRetries<0))throw new c("Max retries must be a non-negative number")}};
2
+ exports.ATTACHMENT_LIMITS=v;exports.AttachmentsAPI=h;exports.MESSAGE_LIMITS=A;exports.MessageValidationError=u;exports.Messenger=S;exports.MessengerAPIError=m;exports.MessengerConfigError=c;exports.MessengerNetworkError=l;exports.MessengerTimeoutError=T;exports.ModerationAPI=g;exports.ProfileAPI=E;exports.SendAPI=d;exports.TEMPLATE_LIMITS=i;exports.TemplateValidationError=o;exports.TemplatesAPI=y;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/core/errors.ts","../src/core/http-client.ts","../src/utils/message-validators.ts","../src/resources/send.ts","../src/resources/attachments.ts","../src/resources/moderation.ts","../src/utils/validators.ts","../src/resources/templates.ts","../src/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: string;
2
+ accessToken?: string;
3
3
  version: string;
4
4
  baseUrl?: string;
5
5
  timeout?: number;
6
6
  maxRetries?: number;
7
7
  }
8
+ interface APIOptions {
9
+ accessToken?: string;
10
+ }
8
11
  interface RequestOptions {
9
12
  method: 'GET' | 'POST' | 'DELETE';
10
13
  path: string;
11
14
  body?: any;
12
15
  query?: Record<string, string | number | boolean>;
16
+ accessToken?: string;
13
17
  }
14
18
  declare class HTTPClient {
15
19
  private readonly config;
@@ -97,11 +101,11 @@ interface AttachmentUploadResponse {
97
101
  declare class SendAPI {
98
102
  private httpClient;
99
103
  constructor(httpClient: HTTPClient);
100
- message(request: SendMessageRequest): Promise<SendMessageResponse>;
101
- action(recipientId: string, action: SenderAction): Promise<SendMessageResponse>;
102
- typingOn(recipientId: string): Promise<SendMessageResponse>;
103
- typingOff(recipientId: string): Promise<SendMessageResponse>;
104
- markSeen(recipientId: string): Promise<SendMessageResponse>;
104
+ message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse>;
105
+ action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse>;
106
+ typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
107
+ typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
108
+ markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
105
109
  /**
106
110
  * Send an attachment using a previously uploaded attachment_id
107
111
  */
@@ -110,7 +114,7 @@ declare class SendAPI {
110
114
  type: AttachmentType;
111
115
  attachment_id: string;
112
116
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
113
- }): Promise<SendMessageResponse>;
117
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
114
118
  /**
115
119
  * Upload and send an attachment from URL in a single request
116
120
  */
@@ -119,13 +123,13 @@ declare class SendAPI {
119
123
  type: AttachmentType;
120
124
  url: string;
121
125
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
122
- }): Promise<SendMessageResponse>;
126
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
123
127
  }
124
128
 
125
129
  declare class AttachmentsAPI {
126
130
  private httpClient;
127
131
  constructor(httpClient: HTTPClient);
128
- upload(request: AttachmentUploadRequest): Promise<AttachmentUploadResponse>;
132
+ upload(request: AttachmentUploadRequest, options?: APIOptions): Promise<AttachmentUploadResponse>;
129
133
  }
130
134
 
131
135
  interface UserId {
@@ -147,35 +151,35 @@ declare class ModerationAPI {
147
151
  * Moderate conversations with specified actions
148
152
  * Up to 10 user IDs and up to 2 actions per request
149
153
  */
150
- moderate(request: ModerateConversationsRequest): Promise<ModerateConversationsResponse>;
154
+ moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse>;
151
155
  /**
152
156
  * Block a user from messaging the page
153
157
  * Prevents messaging but user can still interact with page content on Facebook
154
158
  */
155
- blockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
159
+ blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
156
160
  /**
157
161
  * Unblock a user to allow messaging again
158
162
  */
159
- unblockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
163
+ unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
160
164
  /**
161
165
  * Ban a user from both messaging and Facebook interactions
162
166
  * More restrictive than blocking - prevents all interactions
163
167
  * Note: Cannot ban user who was unbanned in last 48 hours
164
168
  */
165
- banUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
169
+ banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
166
170
  /**
167
171
  * Unban a user to restore all interactions
168
172
  * Note: Banned user cannot be unblocked, they must be unbanned first
169
173
  */
170
- unbanUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
174
+ unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
171
175
  /**
172
176
  * Move conversation to spam folder in Meta Business Suite Inbox
173
177
  */
174
- moveToSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
178
+ moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
175
179
  /**
176
180
  * Block user and move to spam (common moderation action)
177
181
  */
178
- blockAndSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
182
+ blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
179
183
  }
180
184
 
181
185
  interface Button {
@@ -246,7 +250,7 @@ declare class TemplatesAPI {
246
250
  image_aspect_ratio?: 'horizontal' | 'square';
247
251
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
248
252
  tag?: string;
249
- }): Promise<SendMessageResponse>;
253
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
250
254
  button(options: {
251
255
  recipient: Recipient;
252
256
  text: string;
@@ -254,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: string;
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: MessengerConfig);
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: string;
2
+ accessToken?: string;
3
3
  version: string;
4
4
  baseUrl?: string;
5
5
  timeout?: number;
6
6
  maxRetries?: number;
7
7
  }
8
+ interface APIOptions {
9
+ accessToken?: string;
10
+ }
8
11
  interface RequestOptions {
9
12
  method: 'GET' | 'POST' | 'DELETE';
10
13
  path: string;
11
14
  body?: any;
12
15
  query?: Record<string, string | number | boolean>;
16
+ accessToken?: string;
13
17
  }
14
18
  declare class HTTPClient {
15
19
  private readonly config;
@@ -97,11 +101,11 @@ interface AttachmentUploadResponse {
97
101
  declare class SendAPI {
98
102
  private httpClient;
99
103
  constructor(httpClient: HTTPClient);
100
- message(request: SendMessageRequest): Promise<SendMessageResponse>;
101
- action(recipientId: string, action: SenderAction): Promise<SendMessageResponse>;
102
- typingOn(recipientId: string): Promise<SendMessageResponse>;
103
- typingOff(recipientId: string): Promise<SendMessageResponse>;
104
- markSeen(recipientId: string): Promise<SendMessageResponse>;
104
+ message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse>;
105
+ action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse>;
106
+ typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
107
+ typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
108
+ markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse>;
105
109
  /**
106
110
  * Send an attachment using a previously uploaded attachment_id
107
111
  */
@@ -110,7 +114,7 @@ declare class SendAPI {
110
114
  type: AttachmentType;
111
115
  attachment_id: string;
112
116
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
113
- }): Promise<SendMessageResponse>;
117
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
114
118
  /**
115
119
  * Upload and send an attachment from URL in a single request
116
120
  */
@@ -119,13 +123,13 @@ declare class SendAPI {
119
123
  type: AttachmentType;
120
124
  url: string;
121
125
  messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';
122
- }): Promise<SendMessageResponse>;
126
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
123
127
  }
124
128
 
125
129
  declare class AttachmentsAPI {
126
130
  private httpClient;
127
131
  constructor(httpClient: HTTPClient);
128
- upload(request: AttachmentUploadRequest): Promise<AttachmentUploadResponse>;
132
+ upload(request: AttachmentUploadRequest, options?: APIOptions): Promise<AttachmentUploadResponse>;
129
133
  }
130
134
 
131
135
  interface UserId {
@@ -147,35 +151,35 @@ declare class ModerationAPI {
147
151
  * Moderate conversations with specified actions
148
152
  * Up to 10 user IDs and up to 2 actions per request
149
153
  */
150
- moderate(request: ModerateConversationsRequest): Promise<ModerateConversationsResponse>;
154
+ moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse>;
151
155
  /**
152
156
  * Block a user from messaging the page
153
157
  * Prevents messaging but user can still interact with page content on Facebook
154
158
  */
155
- blockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
159
+ blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
156
160
  /**
157
161
  * Unblock a user to allow messaging again
158
162
  */
159
- unblockUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
163
+ unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
160
164
  /**
161
165
  * Ban a user from both messaging and Facebook interactions
162
166
  * More restrictive than blocking - prevents all interactions
163
167
  * Note: Cannot ban user who was unbanned in last 48 hours
164
168
  */
165
- banUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
169
+ banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
166
170
  /**
167
171
  * Unban a user to restore all interactions
168
172
  * Note: Banned user cannot be unblocked, they must be unbanned first
169
173
  */
170
- unbanUser(userIds: string | string[]): Promise<ModerateConversationsResponse>;
174
+ unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
171
175
  /**
172
176
  * Move conversation to spam folder in Meta Business Suite Inbox
173
177
  */
174
- moveToSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
178
+ moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
175
179
  /**
176
180
  * Block user and move to spam (common moderation action)
177
181
  */
178
- blockAndSpam(userIds: string | string[]): Promise<ModerateConversationsResponse>;
182
+ blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse>;
179
183
  }
180
184
 
181
185
  interface Button {
@@ -246,7 +250,7 @@ declare class TemplatesAPI {
246
250
  image_aspect_ratio?: 'horizontal' | 'square';
247
251
  notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';
248
252
  tag?: string;
249
- }): Promise<SendMessageResponse>;
253
+ }, apiOptions?: APIOptions): Promise<SendMessageResponse>;
250
254
  button(options: {
251
255
  recipient: Recipient;
252
256
  text: string;
@@ -254,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: string;
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: MessengerConfig);
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,f as MESSAGE_LIMITS,d as MessageValidationError,M as Messenger,c as MessengerAPIError,m as MessengerConfigError,l as MessengerNetworkError,u as MessengerTimeoutError,_ as ModerationAPI,E as ProfileAPI,T as SendAPI,i as TEMPLATE_LIMITS,n as TemplateValidationError,y as TemplatesAPI};//# sourceMappingURL=index.js.map
1
+ var R="v23.0",b="https://graph.facebook.com";var p={MESSAGES:"/me/messages",MESSAGE_ATTACHMENTS:"/me/message_attachments",MODERATE_CONVERSATIONS:"/me/moderate_conversations"},A={TEXT_MESSAGE_MAX_CHARS:2e3},v={IMAGE_MAX_SIZE:8*1024*1024,OTHER_MAX_SIZE:25*1024*1024,VIDEO_TIMEOUT:75,OTHER_TIMEOUT:10},i={GENERIC_ELEMENTS_MAX:10,GENERIC_TITLE_MAX_CHARS:80,GENERIC_SUBTITLE_MAX_CHARS:80,BUTTON_TEXT_MAX_CHARS:640,BUTTONS_MAX_COUNT:3,BUTTON_TITLE_MAX_CHARS:20,POSTBACK_PAYLOAD_MAX_CHARS:1e3,MEDIA_ELEMENTS_COUNT:1,MEDIA_BUTTONS_MAX_COUNT:3};var m=class extends Error{code;type;subcode;fbtrace_id;statusCode;response;constructor(e,s,r){super(e.message),this.name="MessengerAPIError",this.code=e.code,this.type=e.type,this.subcode=e.error_subcode,this.fbtrace_id=e.fbtrace_id,this.statusCode=s,this.response=r;}},l=class extends Error{cause;constructor(e,s){super(e),this.name="MessengerNetworkError",this.cause=s;}},T=class extends Error{timeout;constructor(e){super(`Request timed out after ${e}ms`),this.name="MessengerTimeoutError",this.timeout=e;}},c=class extends Error{constructor(e){super(e),this.name="MessengerConfigError";}};var f=class{config;constructor(e){this.config={accessToken:e.accessToken,version:e.version,baseUrl:e.baseUrl||b,timeout:e.timeout||3e4,maxRetries:e.maxRetries||3};}async request(e){let s=this.buildUrl(e.path,e.query,e.accessToken),r;for(let n=0;n<=this.config.maxRetries;n++)try{let a=await this.makeRequest(s,e);return await this.handleResponse(a)}catch(a){if(r=a,a instanceof m&&a.statusCode>=400&&a.statusCode<500||n===this.config.maxRetries)throw a;await this.delay(1e3*(n+1));}throw r||new Error("Unknown error occurred")}buildUrl(e,s,r){let n=new URL(`${this.config.baseUrl}/${this.config.version}${e}`),a=r||this.config.accessToken;if(!a)throw new Error("Access token is required. Provide it in constructor or method options.");return n.searchParams.append("access_token",a),s&&Object.entries(s).forEach(([M,U])=>{n.searchParams.append(M,String(U));}),n.toString()}async makeRequest(e,s){let r=new AbortController,n=setTimeout(()=>r.abort(),this.config.timeout);try{let a={method:s.method,headers:{"Content-Type":"application/json"},signal:r.signal};return s.body&&(a.body=JSON.stringify(s.body)),await fetch(e,a)}catch(a){throw a instanceof Error?a.name==="AbortError"?new T(this.config.timeout):new l(`Network request failed: ${a.message}`,a):a}finally{clearTimeout(n);}}async handleResponse(e){let r=e.headers.get("content-type")?.includes("application/json");if(!e.ok)if(r){let n=await e.json();throw new m(n.error,e.status,n)}else {let n=await e.text();throw new m({message:n||`HTTP ${e.status} ${e.statusText}`,type:"http_error",code:e.status,fbtrace_id:""},e.status,n)}return r?await e.json():await e.text()}delay(e){return new Promise(s=>setTimeout(s,e))}};var u=class extends Error{constructor(e){super(e),this.name="MessageValidationError";}};function w(t){if(!t||t.trim()==="")throw new u("Text message cannot be empty");if(t.length>A.TEXT_MESSAGE_MAX_CHARS)throw new u(`Text message cannot exceed ${A.TEXT_MESSAGE_MAX_CHARS} characters`)}var d=class{constructor(e){this.httpClient=e;}async message(e,s){return e.message?.text&&w(e.message.text),this.httpClient.request({method:"POST",path:p.MESSAGES,body:e,accessToken:s?.accessToken})}async action(e,s,r){return this.httpClient.request({method:"POST",path:p.MESSAGES,body:{recipient:{id:e},messaging_type:"RESPONSE",sender_action:s},accessToken:r?.accessToken})}async typingOn(e,s){return this.action(e,"typing_on",s)}async typingOff(e,s){return this.action(e,"typing_off",s)}async markSeen(e,s){return this.action(e,"mark_seen",s)}async attachment(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{attachment_id:e.attachment_id}}}},s)}async attachmentFromUrl(e,s){return this.message({recipient:e.recipient,messaging_type:e.messaging_type??"RESPONSE",message:{attachment:{type:e.type,payload:{url:e.url}}}},s)}};var h=class{constructor(e){this.httpClient=e;}async upload(e,s){let r={message:{attachment:{type:e.type,payload:{url:e.url,is_reusable:e.is_reusable??true}}}};return this.httpClient.request({method:"POST",path:p.MESSAGE_ATTACHMENTS,body:r,accessToken:s?.accessToken})}};var g=class{constructor(e){this.httpClient=e;}async moderate(e,s){return this.httpClient.request({method:"POST",path:p.MODERATE_CONVERSATIONS,body:e,accessToken:s?.accessToken})}async blockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user"]},s)}async unblockUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unblock_user"]},s)}async banUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["ban_user"]},s)}async unbanUser(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["unban_user"]},s)}async moveToSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["move_to_spam"]},s)}async blockAndSpam(e,s){let r=Array.isArray(e)?e.map(n=>({id:n})):[{id:e}];return this.moderate({user_ids:r,actions:["block_user","move_to_spam"]},s)}};var o=class extends Error{constructor(e){super(e),this.name="TemplateValidationError";}};function C(t){if(t.length===0)throw new o("Generic template must have at least 1 element");if(t.length>i.GENERIC_ELEMENTS_MAX)throw new o(`Generic template cannot have more than ${i.GENERIC_ELEMENTS_MAX} elements`);t.forEach((e,s)=>{G(e,s);});}function G(t,e){if(!t.title||t.title.trim()==="")throw new o(`Element ${e}: title is required`);if(t.title.length>i.GENERIC_TITLE_MAX_CHARS)throw new o(`Element ${e}: title cannot exceed ${i.GENERIC_TITLE_MAX_CHARS} characters`);if(t.subtitle&&t.subtitle.length>i.GENERIC_SUBTITLE_MAX_CHARS)throw new o(`Element ${e}: subtitle cannot exceed ${i.GENERIC_SUBTITLE_MAX_CHARS} characters`);if(t.image_url&&!_(t.image_url))throw new o(`Element ${e}: image_url must be HTTPS`);if(t.buttons&&P(t.buttons,`Element ${e}`),!!!(t.subtitle||t.image_url||t.default_action||t.buttons&&t.buttons.length>0))throw new o(`Element ${e}: must have at least one additional property beyond title`)}function O(t,e){if(!t||t.trim()==="")throw new o("Button template text is required");if(t.length>i.BUTTON_TEXT_MAX_CHARS)throw new o(`Button template text cannot exceed ${i.BUTTON_TEXT_MAX_CHARS} characters`);if(e.length===0)throw new o("Button template must have at least 1 button");P(e,"Button template");}function I(t){if(!t.media_type)throw new o("Media template element must have media_type");if(!t.url&&!t.attachment_id)throw new o("Media template element must have either url or attachment_id");if(t.url&&t.attachment_id)throw new o("Media template element cannot have both url and attachment_id");if(t.url&&!_(t.url))throw new o("Media template url must be HTTPS");if(t.buttons){if(t.buttons.length>i.MEDIA_BUTTONS_MAX_COUNT)throw new o(`Media template cannot have more than ${i.MEDIA_BUTTONS_MAX_COUNT} buttons`);P(t.buttons,"Media template");}}function P(t,e){if(t.length>i.BUTTONS_MAX_COUNT)throw new o(`${e} cannot have more than ${i.BUTTONS_MAX_COUNT} buttons`);t.forEach((s,r)=>{H(s,`${e} button ${r}`);});}function H(t,e){if(!t.type)throw new o(`${e}: type is required`);if(t.type!=="account_unlink"&&(!t.title||t.title.trim()===""))throw new o(`${e}: title is required for ${t.type} buttons`);if(t.title&&t.title.length>i.BUTTON_TITLE_MAX_CHARS)throw new o(`${e}: title cannot exceed ${i.BUTTON_TITLE_MAX_CHARS} characters`);switch(t.type){case "web_url":if(!t.url)throw new o(`${e}: url is required for web_url buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for web_url buttons`);break;case "postback":if(!t.payload)throw new o(`${e}: payload is required for postback buttons`);if(t.payload.length>i.POSTBACK_PAYLOAD_MAX_CHARS)throw new o(`${e}: payload cannot exceed ${i.POSTBACK_PAYLOAD_MAX_CHARS} characters`);break;case "phone_number":if(!t.payload)throw new o(`${e}: payload is required for phone_number buttons`);if(!t.payload.startsWith("+"))throw new o(`${e}: phone_number payload must start with + (e.g., +1234567890)`);break;case "game_play":break;case "account_link":if(!t.url)throw new o(`${e}: url is required for account_link buttons`);if(!_(t.url))throw new o(`${e}: url must be HTTPS for account_link buttons`);break;}if(t.type==="web_url"&&t.messenger_extensions&&t.fallback_url&&!_(t.fallback_url))throw new o(`${e}: fallback_url must be HTTPS`)}function _(t){try{return new URL(t).protocol==="https:"}catch{return false}}var y=class{constructor(e){this.httpClient=e;}async generic(e,s){C(e.elements);let r={template_type:"generic",elements:e.elements,image_aspect_ratio:e.image_aspect_ratio},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async button(e,s){O(e.text,e.buttons);let r={template_type:"button",text:e.text,buttons:e.buttons},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async media(e,s){I(e.element);let r={template_type:"media",elements:[e.element]},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}async product(e,s){let r={template_type:"product",elements:e.elements},n={recipient:e.recipient,messaging_type:e.messaging_type||"UPDATE",message:{attachment:{type:"template",payload:r}},notification_type:e.notification_type,tag:e.tag};return this.httpClient.request({method:"POST",path:p.MESSAGES,body:n,accessToken:s?.accessToken})}};var E=class{constructor(e){this.httpClient=e;}async get(e,s){let{psid:r,fields:n=["first_name","last_name"]}=e,a=new URLSearchParams({fields:n.join(",")});return this.httpClient.request({method:"GET",path:`/${r}?${a.toString()}`,body:void 0,accessToken:s?.accessToken})}async getBasic(e,s){return this.get({psid:e,fields:["first_name","last_name","profile_pic"]},s)}async getFull(e,s){return this.get({psid:e,fields:["id","name","first_name","last_name","profile_pic","locale","timezone","gender"]},s)}async getName(e,s){return this.get({psid:e,fields:["first_name","last_name"]},s)}async getProfilePicture(e,s){return this.get({psid:e,fields:["profile_pic"]},s)}};var S=class{send;attachments;moderation;templates;profile;httpClient;constructor(e={}){this.validateConfig(e);let s={accessToken:e.accessToken,version:e.version||R,baseUrl:e.baseUrl,timeout:e.timeout,maxRetries:e.maxRetries};this.httpClient=new f(s),this.send=new d(this.httpClient),this.attachments=new h(this.httpClient),this.moderation=new g(this.httpClient),this.templates=new y(this.httpClient),this.profile=new E(this.httpClient);}validateConfig(e){if(e.accessToken!==void 0&&(typeof e.accessToken!="string"||e.accessToken.trim()===""))throw new c("Access token must be a non-empty string");if(e.version&&typeof e.version!="string")throw new c("API version must be a string");if(e.timeout&&(typeof e.timeout!="number"||e.timeout<=0))throw new c("Timeout must be a positive number");if(e.maxRetries&&(typeof e.maxRetries!="number"||e.maxRetries<0))throw new c("Max retries must be a non-negative number")}};
2
+ export{v as ATTACHMENT_LIMITS,h as AttachmentsAPI,A as MESSAGE_LIMITS,u as MessageValidationError,S as Messenger,m as MessengerAPIError,c as MessengerConfigError,l as MessengerNetworkError,T as MessengerTimeoutError,g as ModerationAPI,E as ProfileAPI,d as SendAPI,i as TEMPLATE_LIMITS,o as TemplateValidationError,y as TemplatesAPI};//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/core/errors.ts","../src/core/http-client.ts","../src/utils/message-validators.ts","../src/resources/send.ts","../src/resources/attachments.ts","../src/resources/moderation.ts","../src/utils/validators.ts","../src/resources/templates.ts","../src/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":"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","file":"index.js","sourcesContent":["export const DEFAULT_API_VERSION = 'v23.0';\nexport const BASE_URL = 'https://graph.facebook.com';\nexport const DEFAULT_TIMEOUT = 30000; // 30 seconds\nexport const MAX_RETRY_ATTEMPTS = 3;\nexport const RETRY_DELAY_MS = 1000;\n\nexport const API_ENDPOINTS = {\n MESSAGES: '/me/messages',\n MESSAGE_ATTACHMENTS: '/me/message_attachments',\n MODERATE_CONVERSATIONS: '/me/moderate_conversations',\n USER_PROFILE: '', // Dynamic endpoint: /{PSID}\n} as const;\n\n// Validation constants\nexport const MESSAGE_LIMITS = {\n // Text messages\n TEXT_MESSAGE_MAX_CHARS: 2000,\n} as const;\n\nexport const ATTACHMENT_LIMITS = {\n // File size limits in bytes\n IMAGE_MAX_SIZE: 8 * 1024 * 1024, // 8MB\n OTHER_MAX_SIZE: 25 * 1024 * 1024, // 25MB (video, audio, file)\n \n // Timeout limits in seconds\n VIDEO_TIMEOUT: 75,\n OTHER_TIMEOUT: 10,\n} as const;\n\nexport const TEMPLATE_LIMITS = {\n // Generic Template\n GENERIC_ELEMENTS_MAX: 10,\n GENERIC_TITLE_MAX_CHARS: 80,\n GENERIC_SUBTITLE_MAX_CHARS: 80,\n \n // Button Template \n BUTTON_TEXT_MAX_CHARS: 640,\n BUTTONS_MAX_COUNT: 3,\n BUTTON_TITLE_MAX_CHARS: 20,\n \n // All Templates\n POSTBACK_PAYLOAD_MAX_CHARS: 1000,\n \n // Media Template\n MEDIA_ELEMENTS_COUNT: 1, // Exactly 1 element required\n MEDIA_BUTTONS_MAX_COUNT: 3,\n} as const;","import type { MessengerError } from '../types/responses.js';\n\nexport class MessengerAPIError extends Error {\n public readonly code: number;\n public readonly type: string;\n public readonly subcode?: number;\n public readonly fbtrace_id?: string;\n public readonly statusCode: number;\n public readonly response?: any;\n\n constructor(error: MessengerError, statusCode: number, response?: any) {\n super(error.message);\n this.name = 'MessengerAPIError';\n this.code = error.code;\n this.type = error.type;\n this.subcode = error.error_subcode;\n this.fbtrace_id = error.fbtrace_id;\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\nexport class MessengerNetworkError extends Error {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'MessengerNetworkError';\n this.cause = cause;\n }\n}\n\nexport class MessengerTimeoutError extends Error {\n public readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Request timed out after ${timeout}ms`);\n this.name = 'MessengerTimeoutError';\n this.timeout = timeout;\n }\n}\n\nexport class MessengerConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessengerConfigError';\n }\n}","import { BASE_URL, DEFAULT_TIMEOUT, MAX_RETRY_ATTEMPTS, RETRY_DELAY_MS } from './constants.js';\nimport { MessengerAPIError, MessengerNetworkError, MessengerTimeoutError } from './errors.js';\nimport type { ErrorResponse } from '../types/responses.js';\n\nexport interface ClientConfig {\n accessToken?: string;\n version: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport interface APIOptions {\n accessToken?: string;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'DELETE';\n path: string;\n body?: any;\n query?: Record<string, string | number | boolean>;\n accessToken?: string;\n}\n\nexport class HTTPClient {\n private readonly config: Required<Omit<ClientConfig, 'accessToken'>> & { accessToken?: string };\n\n constructor(config: ClientConfig) {\n this.config = {\n accessToken: config.accessToken,\n version: config.version,\n baseUrl: config.baseUrl || BASE_URL,\n timeout: config.timeout || DEFAULT_TIMEOUT,\n maxRetries: config.maxRetries || MAX_RETRY_ATTEMPTS,\n };\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n const url = this.buildUrl(options.path, options.query, options.accessToken);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await this.makeRequest(url, options);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Don't retry on client errors (4xx)\n if (\n error instanceof MessengerAPIError &&\n error.statusCode >= 400 &&\n error.statusCode < 500\n ) {\n throw error;\n }\n\n // Don't retry on timeout for the last attempt\n if (attempt === this.config.maxRetries) {\n throw error;\n }\n\n // Wait before retrying\n await this.delay(RETRY_DELAY_MS * (attempt + 1));\n }\n }\n\n throw lastError || new Error('Unknown error occurred');\n }\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean>,\n accessTokenOverride?: string,\n ): string {\n const url = new URL(`${this.config.baseUrl}/${this.config.version}${path}`);\n\n // Use override token if provided, otherwise use config token\n const accessToken = accessTokenOverride || this.config.accessToken;\n\n if (!accessToken) {\n throw new Error('Access token is required. Provide it in constructor or method options.');\n }\n\n url.searchParams.append('access_token', accessToken);\n\n // Add additional query parameters\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n return url.toString();\n }\n\n private async makeRequest(url: string, options: RequestOptions): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers: {\n 'Content-Type': 'application/json',\n },\n signal: controller.signal,\n };\n\n if (options.body) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } catch (error) {\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new MessengerTimeoutError(this.config.timeout);\n }\n throw new MessengerNetworkError(`Network request failed: ${error.message}`, error);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type');\n const isJson = contentType?.includes('application/json');\n\n if (!response.ok) {\n if (isJson) {\n const errorData = (await response.json()) as ErrorResponse;\n throw new MessengerAPIError(errorData.error, response.status, errorData);\n } else {\n const text = await response.text();\n throw new MessengerAPIError(\n {\n message: text || `HTTP ${response.status} ${response.statusText}`,\n type: 'http_error',\n code: response.status,\n fbtrace_id: '',\n },\n response.status,\n text,\n );\n }\n }\n\n if (isJson) {\n return (await response.json()) as T;\n }\n\n // For non-JSON responses, return the text\n return (await response.text()) as unknown as T;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { MESSAGE_LIMITS } from '../core/constants.js';\n\nexport class MessageValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessageValidationError';\n }\n}\n\nexport function validateTextMessage(text: string): void {\n if (!text || text.trim() === '') {\n throw new MessageValidationError('Text message cannot be empty');\n }\n\n if (text.length > MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS) {\n throw new MessageValidationError(\n `Text message cannot exceed ${MESSAGE_LIMITS.TEXT_MESSAGE_MAX_CHARS} characters`\n );\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { SendMessageRequest, SenderAction, Recipient } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport type { AttachmentType } from '../types/attachments.js';\nimport { validateTextMessage } from '../utils/message-validators.js';\n\nexport class SendAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async message(request: SendMessageRequest, options?: APIOptions): Promise<SendMessageResponse> {\n // Validate text message length if present\n if (request.message?.text) {\n validateTextMessage(request.message.text);\n }\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: options?.accessToken,\n });\n }\n\n async action(recipientId: string, action: SenderAction, options?: APIOptions): Promise<SendMessageResponse> {\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: {\n recipient: { id: recipientId },\n messaging_type: 'RESPONSE',\n sender_action: action,\n },\n accessToken: options?.accessToken,\n });\n }\n\n async typingOn(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_on', options);\n }\n\n async typingOff(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'typing_off', options);\n }\n\n async markSeen(recipientId: string, options?: APIOptions): Promise<SendMessageResponse> {\n return this.action(recipientId, 'mark_seen', options);\n }\n\n // Convenience methods for sending attachments\n\n /**\n * Send an attachment using a previously uploaded attachment_id\n */\n async attachment(options: {\n recipient: Recipient;\n type: AttachmentType;\n attachment_id: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n attachment_id: options.attachment_id,\n },\n },\n },\n }, apiOptions);\n }\n\n /**\n * Upload and send an attachment from URL in a single request\n */\n async attachmentFromUrl(options: {\n recipient: Recipient;\n type: AttachmentType;\n url: string;\n messaging_type?: 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG';\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n return this.message({\n recipient: options.recipient,\n messaging_type: options.messaging_type ?? 'RESPONSE',\n message: {\n attachment: {\n type: options.type,\n payload: {\n url: options.url,\n },\n },\n },\n }, apiOptions);\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { AttachmentUploadRequest, AttachmentUploadResponse } from '../types/attachments.js';\n\nexport class AttachmentsAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async upload(\n request: AttachmentUploadRequest,\n options?: APIOptions,\n ): Promise<AttachmentUploadResponse> {\n // Format according to official API - no message wrapper needed\n const body = {\n message: {\n attachment: {\n type: request.type,\n payload: {\n url: request.url,\n is_reusable: request.is_reusable ?? true,\n },\n },\n },\n };\n\n return this.httpClient.request<AttachmentUploadResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGE_ATTACHMENTS,\n body,\n accessToken: options?.accessToken,\n });\n }\n}\n","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { \n ModerateConversationsRequest,\n ModerateConversationsResponse\n} from '../types/moderation.js';\n\nexport class ModerationAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Moderate conversations with specified actions\n * Up to 10 user IDs and up to 2 actions per request\n */\n async moderate(request: ModerateConversationsRequest, options?: APIOptions): Promise<ModerateConversationsResponse> {\n return this.httpClient.request<ModerateConversationsResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MODERATE_CONVERSATIONS,\n body: request,\n accessToken: options?.accessToken,\n });\n }\n\n /**\n * Block a user from messaging the page\n * Prevents messaging but user can still interact with page content on Facebook\n */\n async blockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds) \n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user'],\n }, options);\n }\n\n /**\n * Unblock a user to allow messaging again\n */\n async unblockUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unblock_user'],\n }, options);\n }\n\n /**\n * Ban a user from both messaging and Facebook interactions\n * More restrictive than blocking - prevents all interactions\n * Note: Cannot ban user who was unbanned in last 48 hours\n */\n async banUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['ban_user'],\n }, options);\n }\n\n /**\n * Unban a user to restore all interactions\n * Note: Banned user cannot be unblocked, they must be unbanned first\n */\n async unbanUser(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['unban_user'],\n }, options);\n }\n\n /**\n * Move conversation to spam folder in Meta Business Suite Inbox\n */\n async moveToSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['move_to_spam'],\n }, options);\n }\n\n /**\n * Block user and move to spam (common moderation action)\n */\n async blockAndSpam(userIds: string | string[], options?: APIOptions): Promise<ModerateConversationsResponse> {\n const user_ids = Array.isArray(userIds)\n ? userIds.map(id => ({ id }))\n : [{ id: userIds }];\n\n return this.moderate({\n user_ids,\n actions: ['block_user', 'move_to_spam'],\n }, options);\n }\n}","import { TEMPLATE_LIMITS } from '../core/constants.js';\nimport type { Button, GenericTemplateElement, MediaTemplateElement } from '../types/templates.js';\n\nexport class TemplateValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TemplateValidationError';\n }\n}\n\nexport function validateGenericTemplate(elements: GenericTemplateElement[]): void {\n if (elements.length === 0) {\n throw new TemplateValidationError('Generic template must have at least 1 element');\n }\n\n if (elements.length > TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX) {\n throw new TemplateValidationError(\n `Generic template cannot have more than ${TEMPLATE_LIMITS.GENERIC_ELEMENTS_MAX} elements`\n );\n }\n\n elements.forEach((element, index) => {\n validateGenericElement(element, index);\n });\n}\n\nexport function validateGenericElement(element: GenericTemplateElement, index: number): void {\n if (!element.title || element.title.trim() === '') {\n throw new TemplateValidationError(`Element ${index}: title is required`);\n }\n\n if (element.title.length > TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: title cannot exceed ${TEMPLATE_LIMITS.GENERIC_TITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.subtitle && element.subtitle.length > TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `Element ${index}: subtitle cannot exceed ${TEMPLATE_LIMITS.GENERIC_SUBTITLE_MAX_CHARS} characters`\n );\n }\n\n if (element.image_url && !isHttpsUrl(element.image_url)) {\n throw new TemplateValidationError(`Element ${index}: image_url must be HTTPS`);\n }\n\n if (element.buttons) {\n validateButtons(element.buttons, `Element ${index}`);\n }\n\n // Validate that element has at least one property beyond title\n const hasAdditionalProperty = !!(\n element.subtitle ||\n element.image_url ||\n element.default_action ||\n (element.buttons && element.buttons.length > 0)\n );\n\n if (!hasAdditionalProperty) {\n throw new TemplateValidationError(\n `Element ${index}: must have at least one additional property beyond title`\n );\n }\n}\n\nexport function validateButtonTemplate(text: string, buttons: Button[]): void {\n if (!text || text.trim() === '') {\n throw new TemplateValidationError('Button template text is required');\n }\n\n if (text.length > TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS) {\n throw new TemplateValidationError(\n `Button template text cannot exceed ${TEMPLATE_LIMITS.BUTTON_TEXT_MAX_CHARS} characters`\n );\n }\n\n if (buttons.length === 0) {\n throw new TemplateValidationError('Button template must have at least 1 button');\n }\n\n validateButtons(buttons, 'Button template');\n}\n\nexport function validateMediaTemplate(element: MediaTemplateElement): void {\n if (!element.media_type) {\n throw new TemplateValidationError('Media template element must have media_type');\n }\n\n if (!element.url && !element.attachment_id) {\n throw new TemplateValidationError('Media template element must have either url or attachment_id');\n }\n\n if (element.url && element.attachment_id) {\n throw new TemplateValidationError(\n 'Media template element cannot have both url and attachment_id'\n );\n }\n\n if (element.url && !isHttpsUrl(element.url)) {\n throw new TemplateValidationError('Media template url must be HTTPS');\n }\n\n if (element.buttons) {\n if (element.buttons.length > TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `Media template cannot have more than ${TEMPLATE_LIMITS.MEDIA_BUTTONS_MAX_COUNT} buttons`\n );\n }\n validateButtons(element.buttons, 'Media template');\n }\n}\n\nexport function validateButtons(buttons: Button[], context: string): void {\n if (buttons.length > TEMPLATE_LIMITS.BUTTONS_MAX_COUNT) {\n throw new TemplateValidationError(\n `${context} cannot have more than ${TEMPLATE_LIMITS.BUTTONS_MAX_COUNT} buttons`\n );\n }\n\n buttons.forEach((button, index) => {\n validateButton(button, `${context} button ${index}`);\n });\n}\n\nexport function validateButton(button: Button, context: string): void {\n if (!button.type) {\n throw new TemplateValidationError(`${context}: type is required`);\n }\n\n // Title is required for most button types (not for account_unlink)\n if (button.type !== 'account_unlink' && (!button.title || button.title.trim() === '')) {\n throw new TemplateValidationError(`${context}: title is required for ${button.type} buttons`);\n }\n\n if (button.title && button.title.length > TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: title cannot exceed ${TEMPLATE_LIMITS.BUTTON_TITLE_MAX_CHARS} characters`\n );\n }\n\n // Type-specific validations\n switch (button.type) {\n case 'web_url':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for web_url buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for web_url buttons`);\n }\n break;\n\n case 'postback':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for postback buttons`);\n }\n if (button.payload.length > TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS) {\n throw new TemplateValidationError(\n `${context}: payload cannot exceed ${TEMPLATE_LIMITS.POSTBACK_PAYLOAD_MAX_CHARS} characters`\n );\n }\n break;\n\n case 'phone_number':\n if (!button.payload) {\n throw new TemplateValidationError(`${context}: payload is required for phone_number buttons`);\n }\n // Basic phone number validation (starts with +)\n if (!button.payload.startsWith('+')) {\n throw new TemplateValidationError(\n `${context}: phone_number payload must start with + (e.g., +1234567890)`\n );\n }\n break;\n\n case 'game_play':\n // game_play buttons may have optional game_metadata\n break;\n\n case 'account_link':\n if (!button.url) {\n throw new TemplateValidationError(`${context}: url is required for account_link buttons`);\n }\n if (!isHttpsUrl(button.url)) {\n throw new TemplateValidationError(`${context}: url must be HTTPS for account_link buttons`);\n }\n break;\n\n case 'account_unlink':\n // account_unlink buttons don't require additional properties\n break;\n }\n\n // Validate webview properties for web_url buttons\n if (button.type === 'web_url' && button.messenger_extensions && button.fallback_url) {\n if (!isHttpsUrl(button.fallback_url)) {\n throw new TemplateValidationError(`${context}: fallback_url must be HTTPS`);\n }\n }\n}\n\nfunction isHttpsUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.protocol === 'https:';\n } catch {\n return false;\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport { API_ENDPOINTS } from '../core/constants.js';\nimport type { Recipient, SendMessageRequest, MessagingType } from '../types/messages.js';\nimport type { SendMessageResponse } from '../types/responses.js';\nimport { validateGenericTemplate, validateButtonTemplate, validateMediaTemplate } from '../utils/validators.js';\nimport type {\n GenericTemplatePayload,\n ButtonTemplatePayload,\n MediaTemplatePayload,\n ProductTemplatePayload,\n GenericTemplateElement,\n Button,\n MediaTemplateElement,\n ProductTemplateElement,\n} from '../types/templates.js';\n\nexport class TemplatesAPI {\n constructor(private httpClient: HTTPClient) {}\n\n async generic(options: {\n recipient: Recipient;\n elements: GenericTemplateElement[];\n messaging_type?: MessagingType;\n image_aspect_ratio?: 'horizontal' | 'square';\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateGenericTemplate(options.elements);\n\n const payload: GenericTemplatePayload = {\n template_type: 'generic',\n elements: options.elements,\n image_aspect_ratio: options.image_aspect_ratio,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async button(options: {\n recipient: Recipient;\n text: string;\n buttons: Button[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateButtonTemplate(options.text, options.buttons);\n\n const payload: ButtonTemplatePayload = {\n template_type: 'button',\n text: options.text,\n buttons: options.buttons,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async media(options: {\n recipient: Recipient;\n element: MediaTemplateElement;\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n // Validate template\n validateMediaTemplate(options.element);\n\n const payload: MediaTemplatePayload = {\n template_type: 'media',\n elements: [options.element],\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n\n async product(options: {\n recipient: Recipient;\n elements: ProductTemplateElement[];\n messaging_type?: MessagingType;\n notification_type?: 'REGULAR' | 'SILENT_PUSH' | 'NO_PUSH';\n tag?: string;\n }, apiOptions?: APIOptions): Promise<SendMessageResponse> {\n const payload: ProductTemplatePayload = {\n template_type: 'product',\n elements: options.elements,\n };\n\n const request: SendMessageRequest = {\n recipient: options.recipient,\n messaging_type: options.messaging_type || 'UPDATE',\n message: {\n attachment: {\n type: 'template',\n payload,\n },\n },\n notification_type: options.notification_type,\n tag: options.tag,\n };\n\n return this.httpClient.request<SendMessageResponse>({\n method: 'POST',\n path: API_ENDPOINTS.MESSAGES,\n body: request,\n accessToken: apiOptions?.accessToken,\n });\n }\n}","import type { HTTPClient, APIOptions } from '../core/http-client.js';\nimport type { \n GetProfileRequest,\n UserProfile\n} from '../types/profile.js';\n\nexport class ProfileAPI {\n constructor(private httpClient: HTTPClient) {}\n\n /**\n * Get user profile information using PSID\n * Requires \"Advanced User Profile Access\" feature\n */\n async get(request: GetProfileRequest, options?: APIOptions): Promise<UserProfile> {\n const { psid, fields = ['first_name', 'last_name'] } = request;\n \n const queryParams = new URLSearchParams({\n fields: fields.join(','),\n });\n\n return this.httpClient.request<UserProfile>({\n method: 'GET',\n path: `/${psid}?${queryParams.toString()}`,\n body: undefined,\n accessToken: options?.accessToken,\n });\n }\n\n /**\n * Get user profile with default fields (first_name, last_name, profile_pic)\n */\n async getBasic(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name', 'profile_pic'],\n }, options);\n }\n\n /**\n * Get comprehensive user profile with all available fields\n */\n async getFull(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['id', 'name', 'first_name', 'last_name', 'profile_pic', 'locale', 'timezone', 'gender'],\n }, options);\n }\n\n /**\n * Get user's name (first_name and last_name)\n */\n async getName(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['first_name', 'last_name'],\n }, options);\n }\n\n /**\n * Get user's profile picture URL\n */\n async getProfilePicture(psid: string, options?: APIOptions): Promise<UserProfile> {\n return this.get({\n psid,\n fields: ['profile_pic'],\n }, options);\n }\n}","import { HTTPClient, type ClientConfig } from './core/http-client.js';\nimport { DEFAULT_API_VERSION } from './core/constants.js';\nimport { MessengerConfigError } from './core/errors.js';\nimport { SendAPI } from './resources/send.js';\nimport { AttachmentsAPI } from './resources/attachments.js';\nimport { ModerationAPI } from './resources/moderation.js';\nimport { TemplatesAPI } from './resources/templates.js';\nimport { ProfileAPI } from './resources/profile.js';\n\nexport interface MessengerConfig {\n accessToken?: string;\n version?: string;\n baseUrl?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\nexport class Messenger {\n public readonly send: SendAPI;\n public readonly attachments: AttachmentsAPI;\n public readonly moderation: ModerationAPI;\n public readonly templates: TemplatesAPI;\n public readonly profile: ProfileAPI;\n\n private readonly httpClient: HTTPClient;\n\n constructor(config: MessengerConfig = {}) {\n this.validateConfig(config);\n\n const clientConfig: ClientConfig = {\n accessToken: config.accessToken,\n version: config.version || DEFAULT_API_VERSION,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n };\n\n this.httpClient = new HTTPClient(clientConfig);\n\n // Initialize API resources\n this.send = new SendAPI(this.httpClient);\n this.attachments = new AttachmentsAPI(this.httpClient);\n this.moderation = new ModerationAPI(this.httpClient);\n this.templates = new TemplatesAPI(this.httpClient);\n this.profile = new ProfileAPI(this.httpClient);\n }\n\n private validateConfig(config: MessengerConfig): void {\n if (config.accessToken !== undefined) {\n if (typeof config.accessToken !== 'string' || config.accessToken.trim() === '') {\n throw new MessengerConfigError('Access token must be a non-empty string');\n }\n }\n\n if (config.version && typeof config.version !== 'string') {\n throw new MessengerConfigError('API version must be a string');\n }\n\n if (config.timeout && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new MessengerConfigError('Timeout must be a positive number');\n }\n\n if (config.maxRetries && (typeof config.maxRetries !== 'number' || config.maxRetries < 0)) {\n throw new MessengerConfigError('Max retries must be a non-negative number');\n }\n }\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warriorteam/messenger-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "TypeScript SDK for Facebook Messenger Platform API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",