@apostlejs/whatsapp 0.0.5 → 0.0.7
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 +1 -1
- package/dist/index.d.cts +10 -4
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
@@ -1 +1 @@
|
|
1
|
-
"use strict";var e=require("zod");function t(e){return e&&e.__esModule?e:{default:e}}var a=t(require("node:crypto")),n=Object.defineProperty,r=(e,t)=>{for(var a in t)n(e,a,{get:t[a],enumerable:!0})},o={};r(o,{endpoints:()=>c,flowAction:()=>p,flowCanSendMessageStatus:()=>w,flowCategory:()=>d,flowMediaData:()=>u,flowMetadata:()=>f,flowScreen:()=>m,flowStatus:()=>y,flowValidationError:()=>_,flowsEndpoints:()=>s,messagesEndpoints:()=>i,wabaEndpoints:()=>l});var s={create:{url:"/{waba_id}/flows",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},updateMetadata:{url:"/{flow_id}",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},readMany:{url:"/{waba_id}/flows",method:"get",response:null},delete:{url:"/{flow_id}",method:"delete",response:null},read:{url:"/{flow_id}",method:"get",request:{query:null},response:null},updateJson:{url:"/{flow_id}/assets",method:"post",request:{body:null},response:null},getPreview:{url:"/{flow_id}?fields=preview.invalidate(false)",method:"get",response:null},publish:{url:"/{flow_id}/publish",method:"post",response:null}},i={send:{url:"/{number_id}/messages",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null}},l={updateEncryption:{url:"/{number_id}/whatsapp_business_encryption",method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},request:{body:null}},registerNumber:{url:"/{number_id}/register",method:"post",headers:{"Content-Type":"application/json"},request:{body:null}}},c={flows:s,messages:i,waba:l},p=e.z.enum(["INIT","BACK","data_exchange","navigate","ping"]),d=e.z.enum(["SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY","OTHER"]),u=e.z.object({media_id:e.z.string(),cdn_url:e.z.string(),file_name:e.z.string(),encryption_metadata:e.z.object({encrypted_hash:e.z.string(),iv:e.z.string(),encryption_key:e.z.string(),hmac_key:e.z.string(),plaintext_hash:e.z.string()})}),f=e.z.object({name:e.z.string(),categories:e.z.array(d),application_id:e.z.string().optional(),endpoint_uri:e.z.string().optional()}),m=e.z.union([e.z.literal("SUCCESS"),e.z.string()]),y=e.z.enum(["DRAFT","PUBLISHED","DEPRECATED","BLOCKED","THROTTLED"]),w=e.z.enum(["AVAILABLE","LIMITED","BLOCKED"]),_=e.z.object({error:e.z.string(),error_type:e.z.string(),message:e.z.string(),line_start:e.z.number(),line_end:e.z.number(),column_start:e.z.number(),column_end:e.z.number()}),g={};r(g,{actions:()=>j,flows:()=>R,parsers:()=>K,security:()=>G,toGraphLanguageTag:()=>z,utils:()=>q});var h={};r(h,{create:()=>A,delete:()=>C,get:()=>N,getMany:()=>O,getPreview:()=>T,publish:()=>x,updateJson:()=>P,updateMetadata:()=>I});var b={};r(b,{settings:()=>E});var v={},E={setup:e=>{Object.assign(v,e)},get:e=>{const t=v[e]??process.env[e];if(!t)throw new Error(`Missing environment variable: ${e}`);return t}};async function S(e,t,a){const n=`https://graph.facebook.com/v${E.get("GRAPH_API_VERSION")}`,r={Authorization:`Bearer ${E.get("META_APP_ACCESS_TOKEN")}`};let o=e.url;const s={...r,...e.headers,...t.headers},i=new URLSearchParams(t.query).toString();"/"===o[0]&&(o=o.slice(1)),o=`${n}/${o}`,i&&(o=`${o}?${i}`);const l={waba_id:E.get("WHATSAPP_ACCOUNT_ID"),number_id:E.get("WHATSAPP_NUMBER_ID"),...t.params};for(const e in l)o=o.replace(`{${e}}`,l[e]);const c=t.body;let p;if(c&&a?.asFormData){const e=new FormData;for(const t in c)e.append(t,c[t]);p=e}else c&&a?.asUrlEncoded?p=new URLSearchParams(c).toString():c&&(p=JSON.stringify(c));return await fetch(o,{method:e.method,headers:s,body:p}).then((e=>e.json())).then((e=>{if("error"in e)throw{response:{data:e.error}};return e})).catch((async e=>{const t=e.response.data.message,a=e.response.data.error_data?.details||"",n=t.match(/^\(#\d+\)/),r=n?n[0]:"",o=t.replace(/^\(#\d+\)\s*/,""),s=a.startsWith(o)?`${r} ${a}`:`${t}: ${a}`;throw e.response.data.message=s,e.response.data}))}async function A(e){const t=c.flows.create;return await S(t,{body:{name:e.name,categories:e.categories,clone_flow_id:e.clone_flow_id,endpoint_uri:e.endpoint_uri,publish:e.publish,flow_json:JSON.stringify(e.flow_json,null,2)}})}async function I(e,t){const a=c.flows.updateMetadata;return await S(a,{body:t,params:{flow_id:e}})}async function P(e,t){const a=c.flows.updateJson,n={name:"flow.json",asset_type:"FLOW_JSON",file:new Blob([JSON.stringify(t,null,2)],{type:"application/json"})};return await S(a,{params:{flow_id:e},body:n},{asFormData:!0})}async function T(e,t){const a=c.flows.getPreview,{preview:n}=await S(a,{params:{flow_id:e}}),r=n.preview_url.replaceAll("\\",""),o=Object.entries(t??{}).reduce(((e,[t,a])=>(e[t]="flow_action_payload"===t?encodeURIComponent(JSON.stringify(a)):a.toString(),e)),{});return`${r}&${new URLSearchParams(o).toString()}`}async function C(e){const t=c.flows.delete;return await S(t,{params:{flow_id:e}})}async function N(e,t){const a=c.flows.read;return await S(a,{params:{flow_id:e},query:{fields:t?.fields.join(",")??""}})}async function O(){const e=c.flows.readMany;return await S(e,{})}async function x(e){const t=c.flows.publish;return await S(t,{params:{flow_id:e}})}var B=e=>e.split("?")[0],R={createToken:({flow_name:e,flow_parameters:t,chatId:a})=>{const n=new URLSearchParams({chat_id:a});if(n.set("flow_identifier",crypto.randomUUID()),t)for(const[e,a]of Object.entries(t))n.set(e,a.toString());return`${e}?${decodeURIComponent(n.toString())}`},getName:B,destructureFlowToken:e=>{const t=B(e);let a=e.split("?")?.[1];"&"===a?.[0]&&(a=a.slice(1));const n=new URLSearchParams(a),r=n.get("chat_id")||n.get("chatId"),o=n.get("flow_identifier")||n.get("flowIdentifier"),s={};for(const[e,t]of n.entries())"chat_id"!==e&&"chatId"!==e&&"flow_identifier"!==e&&"flowIdentifier"!==e&&(s[e]=t);return{paramsString:a,flowName:t,chatId:r,flowIdentifier:o,flowParameters:s}}},U={"ar-SA":"ar","bn-BD":"bn","bn-IN":"bn","cs-CZ":"cs","da-DK":"da","de-AT":"de","de-CH":"de","de-DE":"de","el-GR":"el","en-AU":"en","en-CA":"en","en-GB":"en_GB","en-IE":"en","en-IN":"en","en-NZ":"en","en-ZA":"en","en-US":"en_US","es-AR":"es_AR","es-CL":"es","es-CO":"es","es-ES":"es_ES","es-MX":"es_MX","es-US":"es","fi-FI":"fi","fr-BE":"fr","fr-CA":"fr","fr-CH":"fr","fr-FR":"fr","he-IL":"he","hi-IN":"hi","hu-HU":"hu","id-ID":"id","it-CH":"it","it-IT":"it","ja-JP":"ja","ko-KR":"ko","nl-BE":"nl","nl-NL":"nl","no-NO":"nb","pl-PL":"pl","pt-PT":"pt_PT","pt-BR":"pt_BR","ro-RO":"ro","ru-RU":"ru","sk-SK":"sk","sv-SE":"sv","ta-IN":"ta","ta-LK":"ta","th-TH":"th","tr-TR":"tr","zh-CN":"zh_CN","zh-HK":"zh_HK","zh-TW":"zh_TW"},z=e=>{const t=U[e];return void 0===t?"en":t},M=e=>{const t={to:e.to,messaging_product:"whatsapp",recipient_type:"individual"};return e.reply&&(t.context={message_id:e.reply}),e.showUrlPreviewImage&&(t.preview_url=e.showUrlPreviewImage),t},D={flow:e=>{if("flow"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{flow:n,...r}=t,o=M(a);n.mode||(n.mode=E.get("WHATSAPP_FLOWS_MODE"));const s=R.createToken({chatId:o.to,flow_name:n.name,flow_parameters:n.parameters});return{type:"interactive",...o,interactive:{...r,type:"flow",action:{name:"flow",parameters:{flow_name:n.name,flow_token:s,flow_message_version:"3",flow_cta:n.button,flow_action:n.action??"navigate",mode:n.mode,...n.payload&&{flow_action_payload:{...n.payload,screen:n.payload.screen.toUpperCase()}}}}}}},text:e=>{if("text"!==e.message.type)throw new Error("Invalid type");const{message:{text:t},...a}=e,n={type:"text",text:{body:t},...M(a)};return e.message.previewUrl&&n.text&&(n.text.preview_url=e.message.previewUrl),n},list:e=>{if("list"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{list:n,type:r,...o}=t;return{...M(a),type:"interactive",interactive:{...o,type:r,action:n}}},button:e=>{if("button"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{buttons:n,type:r,...o}=t;return{...M(a),type:"interactive",interactive:{...o,type:r,action:{buttons:n.map((e=>({reply:{id:e.id,title:e.text},type:"reply"})))}}}},template:e=>{if("template"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...a},...n}=e,r={...M(n),type:t,template:{...a,language:{code:z(a.language)}}};return r.template&&(r.template.namespace=process.env.WHATSAPP_MESSAGE_NAMESPACE),r},media:e=>{if("media"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...a},...n}=e,r=Object.entries(a)[0],[o,{ref:s,...i}]=r,l=i,c=M(n);return Number.isNaN(Number(s))?l.link=s:l.id=s,{type:o,[o]:l,...c}},contact:e=>{if("contact"!==e.message.type)throw new Error("Invalid type");const{message:{contacts:t},...a}=e;return{type:"contacts",contacts:t,...M(a)}}};function k(e){const{encrypted_aes_key:t,encrypted_flow_data:n,initial_vector:r}=e,o=a.default.createPrivateKey({key:E.get("WHATSAPP_ACCOUNT_ENCRYPTION_PRIVATE_KEY"),passphrase:E.get("WHATSAPP_ACCOUNT_ENCRYPTION_PASSPHRASE")}),s=a.default.privateDecrypt({key:o,padding:a.default.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},Buffer.from(t,"base64")),i=Buffer.from(n,"base64"),l=Buffer.from(r,"base64"),c=i.subarray(0,-16),p=i.subarray(-16),d=a.default.createDecipheriv("aes-128-gcm",s,l);d.setAuthTag(p);const u=Buffer.concat([d.update(c),d.final()]).toString("utf-8");return{payload:JSON.parse(u),encryptionMetadata:{aesKeyBuffer:s,initialVectorBuffer:l}}}function L(e){const t=new URL(e.url).searchParams,a=t.get("hub.verify_token"),n=t.get("hub.challenge");return!(!a||!n)&&a===E.get("WHATSAPP_WEBHOOK_KEY")&&n}async function H(e,t){const n=e.headers.get("x-hub-signature-256");if(!n)return!1;const r=n.replace("sha256=",""),o=a.default.createHmac("sha256",E.get("WHATSAPP_WEBHOOK_KEY")).update(t,"utf-8").digest("hex");return!!a.default.timingSafeEqual(Buffer.from(r),Buffer.from(o))}var K={toGraph:{sendMessage:e=>D[e.message.type](e),flowResponse:(e,t)=>{if(!t.data)throw new Error("Missing data in flow response");if(!t.screen)throw new Error("Missing screen in flow response");if(t.screen=t.screen.toUpperCase(),"SUCCESS"===t.screen){const a=t.data??{};t.data={extension_message_response:{params:{flow_token:e,...a}}}}return t}},toSDK:{webhook:async function(e){if("GET"===e.method){const t=L(e);if(!t)throw new Error("Invalid health check hub");return{type:"healthCheck",payload:t}}const t=await e.text(),a=JSON.parse(t);if("entry"in a){if(!H(e,t))throw new Error("Invalid application webhook signature");const r=a.entry.flatMap((e=>e.changes)).filter((e=>"messages"===e.field)).flatMap((e=>e.value.messages)).filter(Boolean).map((e=>function(e){const t=e.from,a={id:e.id,type:e.type,timestamp:e.timestamp,metadata:{forwarded:e.context?.forwarded,frequentlyForwarded:e.context?.frequently_forwarded}},n=function(e){if(!(e.audio||e.document||e.video||e.image))return null;const t=e.audio?.id??e.document?.id??e.image?.id??e.video?.id,a=e.audio?.mime_type??e.document?.mime_type??e.image?.mime_type??e.video?.mime_type,n=["audio","document","image","video"].find((t=>e[t])),r=e.image?.sha256??e.document?.sha256??e.video?.sha256;return{id:t,type:n,caption:e.document?.caption??e.image?.caption??e.video?.caption??null,mime_type:a,sha256:r,filename:e.document?.filename??e.video?.filename}}(e),r=function(e){return e.text?.body??e.button?.text??e.interactive?.button_reply?.title??e.interactive?.list_reply?.title??e.document?.caption??null}(e),o=function(e){return e.interactive?{...e.interactive?.button_reply||e.button?{button:{id:e.interactive?.button_reply?.id??null,title:e.button?.text??e.interactive.button_reply?.title,payload:e.button?.payload??null}}:{},...e.interactive.list_reply?{selectedOption:{id:e.interactive.list_reply.id,title:e.interactive.list_reply.title,description:e.interactive.list_reply.description}}:{},...e.interactive.nfm_reply?{flowResponse:JSON.parse(e.interactive.nfm_reply.response_json)}:{}}:null}(e);return{...a,...o&&{interaction:o},...n&&{media:n},text:r,chatId:t}}(e)));return{type:"application",payload:{messageReceived:(n=r,n.length?n:void 0)}}}var n;if("encrypted_flow_data"in a)return{type:"flowExchange",payload:{...k(a),pingResponse:{data:{status:"active"}}}};throw new Error("Unrecognized event")}}},j={messages:{send:async function(e){const t=K.toGraph.sendMessage(e),a=c.messages.send;return await S(a,{body:t})}},flows:{...h},waba:{registerNumber:async function({dataRegion:e,pin:t}){const a=c.waba.registerNumber,n={messaging_product:"whatsapp",pin:t};return e&&(n.data_localization_region=e),await S(a,{body:n},{asUrlEncoded:!0})},encryption:{upload:async function(e){const t=c.waba.updateEncryption,a={business_public_key:e};return await S(t,{body:a},{asUrlEncoded:!0})}}}};async function W(e){return await fetch(e).then((async e=>{const t=await e.arrayBuffer();return Buffer.from(t)}))}var G={verifyHub:L,verifySignature:H,generateWabaEncryption:async function(){const e=a.default.randomUUID(),{publicKey:t,privateKey:n}=a.default.generateKeyPairSync("rsa",{modulusLength:2048,publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem",cipher:"aes-256-cbc",passphrase:e}});return{passphrase:e,publicKey:t,privateKey:n}},decryptFlowBody:k,encryptFlowResponse:function(e,t){const n=[];for(const e of Buffer.from(t.initialVectorBuffer).entries())n.push(~e[1]);const r=a.default.createCipheriv("aes-128-gcm",Buffer.from(t.aesKeyBuffer),Buffer.from(n));return Buffer.concat([r.update(JSON.stringify(e),"utf-8"),r.final(),r.getAuthTag()]).toString("base64")},decryptFlowMedia:async function(e){const t=[];for(const n of e){let{cdn_url:e,encryption_metadata:r}=n;if("EXAMPLE_DATA__CDN_URL_WILL_COME_IN_THIS_FIELD"===e){e="https://picsum.photos/seed/picsum/200";const a=await W(e);t.push(a);continue}const o=await W(e),{iv:s,encryption_key:i,hmac_key:l,encrypted_hash:c,plaintext_hash:p}=r,d={iv:Buffer.from(s,"base64"),encryption_key:Buffer.from(i,"base64"),hmac_key:Buffer.from(l,"base64")};if(a.default.createHash("sha256").update(o).digest("base64")!==c)throw new Error("Encrypted hash validation failed");const u=o.subarray(0,o.length-10),f=o.subarray(-10);if(!a.default.createHmac("sha256",d.hmac_key).update(Buffer.concat([d.iv,u])).digest().subarray(0,10).equals(f))throw new Error("HMAC validation failed");const m=a.default.createDecipheriv("aes-256-cbc",d.encryption_key,d.iv),y=m.update(u),w=Buffer.concat([y,m.final()]);if(a.default.createHash("sha256").update(w).digest("base64")!==p)throw new Error("Decrypted media hash validation failed");t.push(w)}return t}},q={flows:R},$=null;exports.actions=j,exports.createWhatsapp=()=>$||($=(()=>{const{settings:e}=b,{actions:t,flows:a,parsers:n,security:r,utils:s,toGraphLanguageTag:i}=g,{endpoints:l}=o;return{settings:e,sdk:{actions:t,flows:a,parsers:n,security:r,utils:s,toGraphLanguageTag:i},graph:{endpoints:l}}})()),exports.endpoints=c,exports.flowAction=p,exports.flowCanSendMessageStatus=w,exports.flowCategory=d,exports.flowMediaData=u,exports.flowMetadata=f,exports.flowScreen=m,exports.flowStatus=y,exports.flowValidationError=_,exports.flows=R,exports.flowsEndpoints=s,exports.messagesEndpoints=i,exports.parsers=K,exports.security=G,exports.toGraphLanguageTag=z,exports.utils=q,exports.wabaEndpoints=l;
|
1
|
+
"use strict";var e=require("zod");function t(e){return e&&e.__esModule?e:{default:e}}var a=t(require("node:crypto")),r=Object.defineProperty,n=(e,t)=>{for(var a in t)r(e,a,{get:t[a],enumerable:!0})},o={};n(o,{WhatsappErrorCode:()=>h,endpoints:()=>c,flowAction:()=>d,flowCanSendMessageStatus:()=>g,flowCategory:()=>p,flowMediaData:()=>u,flowMetadata:()=>f,flowScreen:()=>m,flowStatus:()=>y,flowValidationError:()=>w,flowsEndpoints:()=>i,messagesEndpoints:()=>s,wabaEndpoints:()=>l});var i={create:{url:"/{waba_id}/flows",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},updateMetadata:{url:"/{flow_id}",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},readMany:{url:"/{waba_id}/flows",method:"get",response:null},delete:{url:"/{flow_id}",method:"delete",response:null},read:{url:"/{flow_id}",method:"get",request:{query:null},response:null},updateJson:{url:"/{flow_id}/assets",method:"post",request:{body:null},response:null},getPreview:{url:"/{flow_id}?fields=preview.invalidate(false)",method:"get",response:null},publish:{url:"/{flow_id}/publish",method:"post",response:null}},s={send:{url:"/{number_id}/messages",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null}},l={updateEncryption:{url:"/{number_id}/whatsapp_business_encryption",method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},request:{body:null}},registerNumber:{url:"/{number_id}/register",method:"post",headers:{"Content-Type":"application/json"},request:{body:null}}},c={flows:i,messages:s,waba:l},d=e.z.enum(["INIT","BACK","data_exchange","navigate","ping"]),p=e.z.enum(["SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY","OTHER"]),u=e.z.object({media_id:e.z.string(),cdn_url:e.z.string(),file_name:e.z.string(),encryption_metadata:e.z.object({encrypted_hash:e.z.string(),iv:e.z.string(),encryption_key:e.z.string(),hmac_key:e.z.string(),plaintext_hash:e.z.string()})}),f=e.z.object({name:e.z.string(),categories:e.z.array(p),application_id:e.z.string().optional(),endpoint_uri:e.z.string().optional()}),m=e.z.union([e.z.literal("SUCCESS"),e.z.string()]),y=e.z.enum(["DRAFT","PUBLISHED","DEPRECATED","BLOCKED","THROTTLED"]),g=e.z.enum(["AVAILABLE","LIMITED","BLOCKED"]),w=e.z.object({error:e.z.string(),error_type:e.z.string(),message:e.z.string(),line_start:e.z.number(),line_end:e.z.number(),column_start:e.z.number(),column_end:e.z.number()}),h=(e=>(e[e.e0AuthException=0]="e0AuthException",e[e.e3ApiMethod=3]="e3ApiMethod",e[e.e10PermissionDenied=10]="e10PermissionDenied",e[e.e190AccessTokenExpired=190]="e190AccessTokenExpired",e[e.e2xxApiPermission=200]="e2xxApiPermission",e[e.e368TemporarilyBlockedForPolicyViolations=368]="e368TemporarilyBlockedForPolicyViolations",e[e.e130497BusinessAccountRestrictedByCountry=130497]="e130497BusinessAccountRestrictedByCountry",e[e.e131031AccountLocked=131031]="e131031AccountLocked",e[e.e1ApiUnknown=1]="e1ApiUnknown",e[e.e2ApiService=2]="e2ApiService",e[e.e33ParameterValueNotValid=33]="e33ParameterValueNotValid",e[e.e100InvalidParameter=100]="e100InvalidParameter",e[e.e130472UserNumberPartOfExperiment=130472]="e130472UserNumberPartOfExperiment",e[e.e131000SomethingWentWrong=131e3]="e131000SomethingWentWrong",e[e.e131005AccessDenied=131005]="e131005AccessDenied",e[e.e131008RequiredParameterMissing=131008]="e131008RequiredParameterMissing",e[e.e131009ParameterValueNotValid=131009]="e131009ParameterValueNotValid",e[e.e131016ServiceUnavailable=131016]="e131016ServiceUnavailable",e[e.e131021RecipientCannotBeSender=131021]="e131021RecipientCannotBeSender",e[e.e131026MessageUndeliverable=131026]="e131026MessageUndeliverable",e[e.e131030RecipientNotAllowedInList=131030]="e131030RecipientNotAllowedInList",e[e.e131037DisplayNameApprovalNeeded=131037]="e131037DisplayNameApprovalNeeded",e[e.e131042BusinessEligibilityPaymentIssue=131042]="e131042BusinessEligibilityPaymentIssue",e[e.e131045IncorrectCertificate=131045]="e131045IncorrectCertificate",e[e.e131047ReEngagementMessage=131047]="e131047ReEngagementMessage",e[e.e131049MetaChoseNotToDeliver=131049]="e131049MetaChoseNotToDeliver",e[e.e131050UserStoppedMarketingMessages=131050]="e131050UserStoppedMarketingMessages",e[e.e131051UnsupportedMessageType=131051]="e131051UnsupportedMessageType",e[e.e131052MediaDownloadError=131052]="e131052MediaDownloadError",e[e.e131053MediaUploadError=131053]="e131053MediaUploadError",e[e.e131057AccountInMaintenanceMode=131057]="e131057AccountInMaintenanceMode",e[e.e132000TemplateParamCountMismatch=132e3]="e132000TemplateParamCountMismatch",e[e.e132001TemplateDoesNotExist=132001]="e132001TemplateDoesNotExist",e[e.e132005TemplateHydratedTextTooLong=132005]="e132005TemplateHydratedTextTooLong",e[e.e132007TemplateFormatCharacterPolicyViolated=132007]="e132007TemplateFormatCharacterPolicyViolated",e[e.e132012TemplateParameterFormatMismatch=132012]="e132012TemplateParameterFormatMismatch",e[e.e132015TemplateIsPaused=132015]="e132015TemplateIsPaused",e[e.e132016TemplateIsDisabled=132016]="e132016TemplateIsDisabled",e[e.e132068FlowIsBlocked=132068]="e132068FlowIsBlocked",e[e.e132069FlowIsThrottled=132069]="e132069FlowIsThrottled",e[e.e133000IncompleteDeregistration=133e3]="e133000IncompleteDeregistration",e[e.e133004ServerTemporarilyUnavailable=133004]="e133004ServerTemporarilyUnavailable",e[e.e133005TwoStepVerificationPinMismatch=133005]="e133005TwoStepVerificationPinMismatch",e[e.e133006PhoneNumberReVerificationNeeded=133006]="e133006PhoneNumberReVerificationNeeded",e[e.e133008TooManyTwoStepVerificationPinGuesses=133008]="e133008TooManyTwoStepVerificationPinGuesses",e[e.e133009TwoStepVerificationPinGuessedTooFast=133009]="e133009TwoStepVerificationPinGuessedTooFast",e[e.e133010PhoneNumberNotRegistered=133010]="e133010PhoneNumberNotRegistered",e[e.e133015PhoneNumberDeletionPending=133015]="e133015PhoneNumberDeletionPending",e[e.e134011PaymentsTermsNotAccepted=134011]="e134011PaymentsTermsNotAccepted",e[e.e135000GenericUserError=135e3]="e135000GenericUserError",e[e.e2593107SynchronizationRequestLimitExceeded=2593107]="e2593107SynchronizationRequestLimitExceeded",e[e.e2593108SynchronizationRequestOutsideTimeWindow=2593108]="e2593108SynchronizationRequestOutsideTimeWindow",e[e.e4ApiTooManyCalls=4]="e4ApiTooManyCalls",e[e.e80007RateLimitIssues=80007]="e80007RateLimitIssues",e[e.e130429RateLimitHit=130429]="e130429RateLimitHit",e[e.e131048SpamRateLimitHit=131048]="e131048SpamRateLimitHit",e[e.e131056BusinessConsumerPairRateLimitHit=131056]="e131056BusinessConsumerPairRateLimitHit",e[e.e133016AccountRegisterDeregisterRateLimitExceeded=133016]="e133016AccountRegisterDeregisterRateLimitExceeded",e))(h||{}),_={};n(_,{actions:()=>F,flows:()=>B,parsers:()=>V,security:()=>j,toGraphLanguageTag:()=>O,utils:()=>G});var b={};n(b,{create:()=>P,delete:()=>R,get:()=>C,getMany:()=>M,getPreview:()=>I,publish:()=>x,updateJson:()=>N,updateMetadata:()=>A});var v={};n(v,{settings:()=>S});var E={},S={setup:e=>{Object.assign(E,e)},get:e=>{const t=E[e]??process.env[e];if(!t)throw new Error(`Missing environment variable: ${e}`);return t}};async function T(e,t,a){const r=`https://graph.facebook.com/v${S.get("GRAPH_API_VERSION")}`,n={Authorization:`Bearer ${S.get("META_APP_ACCESS_TOKEN")}`};let o=e.url;const i={...n,...e.headers,...t.headers},s=new URLSearchParams(t.query).toString();"/"===o[0]&&(o=o.slice(1)),o=`${r}/${o}`,s&&(o=`${o}?${s}`);const l={waba_id:S.get("WHATSAPP_ACCOUNT_ID"),number_id:S.get("WHATSAPP_NUMBER_ID"),...t.params};for(const e in l)o=o.replace(`{${e}}`,l[e]);const c=t.body;let d;if(c&&a?.asFormData){const e=new FormData;for(const t in c)e.append(t,c[t]);d=e}else c&&a?.asUrlEncoded?d=new URLSearchParams(c).toString():c&&(d=JSON.stringify(c));return await fetch(o,{method:e.method,headers:i,body:d}).then((e=>e.json())).then((e=>{if("error"in e)throw{response:{data:e.error}};return e})).catch((async e=>{const t=e.response.data.message,a=e.response.data.error_data?.details||"",r=t.match(/^\(#\d+\)/),n=r?r[0]:"",o=t.replace(/^\(#\d+\)\s*/,""),i=a.startsWith(o)?`${n} ${a}`:`${t}: ${a}`;throw e.response.data.message=i,e.response.data}))}async function P(e){const t=c.flows.create,a=e.flow_json?JSON.stringify(e.flow_json,null,2):void 0;return await T(t,{body:{name:e.name,categories:e.categories,clone_flow_id:e.clone_flow_id,endpoint_uri:e.endpoint_uri,publish:e.publish,flow_json:a}})}async function A(e,t){const a=c.flows.updateMetadata;return await T(a,{body:t,params:{flow_id:e}})}async function N(e,t){const a=c.flows.updateJson,r={name:"flow.json",asset_type:"FLOW_JSON",file:new Blob([JSON.stringify(t,null,2)],{type:"application/json"})};return await T(a,{params:{flow_id:e},body:r},{asFormData:!0}).catch((e=>{if(e.error_user_msg.startsWith("Flow JSON has been saved"))return{success:!0,validation_errors:[]};throw e}))}async function I(e,t){const a=c.flows.getPreview,{preview:r}=await T(a,{params:{flow_id:e}}),n=r.preview_url.replaceAll("\\",""),o=Object.entries(t??{}).reduce(((e,[t,a])=>(e[t]="flow_action_payload"===t?encodeURIComponent(JSON.stringify(a)):a.toString(),e)),{});return`${n}&${new URLSearchParams(o).toString()}`}async function R(e){const t=c.flows.delete;return await T(t,{params:{flow_id:e}})}async function C(e,t){const a=c.flows.read;return await T(a,{params:{flow_id:e},query:{fields:t?.fields.join(",")??""}})}async function M(){const e=c.flows.readMany;return await T(e,{})}async function x(e){const t=c.flows.publish;return await T(t,{params:{flow_id:e}})}var U=e=>e.split("?")[0],B={createToken:({flow_name:e,flow_parameters:t,chatId:a})=>{const r=new URLSearchParams({chat_id:a});if(r.set("flow_identifier",crypto.randomUUID()),t)for(const[e,a]of Object.entries(t))r.set(e,a.toString());return`${e}?${decodeURIComponent(r.toString())}`},getName:U,destructureFlowToken:e=>{const t=U(e);let a=e.split("?")?.[1];"&"===a?.[0]&&(a=a.slice(1));const r=new URLSearchParams(a),n=r.get("chat_id")||r.get("chatId"),o=r.get("flow_identifier")||r.get("flowIdentifier"),i={};for(const[e,t]of r.entries())"chat_id"!==e&&"chatId"!==e&&"flow_identifier"!==e&&"flowIdentifier"!==e&&(i[e]=t);return{paramsString:a,flowName:t,chatId:n,flowIdentifier:o,flowParameters:i}}},D={"ar-SA":"ar","bn-BD":"bn","bn-IN":"bn","cs-CZ":"cs","da-DK":"da","de-AT":"de","de-CH":"de","de-DE":"de","el-GR":"el","en-AU":"en","en-CA":"en","en-GB":"en_GB","en-IE":"en","en-IN":"en","en-NZ":"en","en-ZA":"en","en-US":"en_US","es-AR":"es_AR","es-CL":"es","es-CO":"es","es-ES":"es_ES","es-MX":"es_MX","es-US":"es","fi-FI":"fi","fr-BE":"fr","fr-CA":"fr","fr-CH":"fr","fr-FR":"fr","he-IL":"he","hi-IN":"hi","hu-HU":"hu","id-ID":"id","it-CH":"it","it-IT":"it","ja-JP":"ja","ko-KR":"ko","nl-BE":"nl","nl-NL":"nl","no-NO":"nb","pl-PL":"pl","pt-PT":"pt_PT","pt-BR":"pt_BR","ro-RO":"ro","ru-RU":"ru","sk-SK":"sk","sv-SE":"sv","ta-IN":"ta","ta-LK":"ta","th-TH":"th","tr-TR":"tr","zh-CN":"zh_CN","zh-HK":"zh_HK","zh-TW":"zh_TW"},O=e=>{const t=D[e];return void 0===t?"en":t},L=e=>{const t={to:e.to,messaging_product:"whatsapp",recipient_type:"individual"};return e.reply&&(t.context={message_id:e.reply}),e.showUrlPreviewImage&&(t.preview_url=e.showUrlPreviewImage),t},z={flow:e=>{if("flow"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{flow:r,...n}=t,o=L(a);r.mode||(r.mode=S.get("WHATSAPP_FLOWS_MODE"));const i=B.createToken({chatId:o.to,flow_name:r.name,flow_parameters:r.parameters});return{type:"interactive",...o,interactive:{...n,type:"flow",action:{name:"flow",parameters:{flow_name:r.name,flow_token:i,flow_message_version:"3",flow_cta:r.button,flow_action:r.action??"navigate",mode:r.mode,...r.payload&&{flow_action_payload:{...r.payload,screen:r.payload.screen.toUpperCase()}}}}}}},text:e=>{if("text"!==e.message.type)throw new Error("Invalid type");const{message:{text:t},...a}=e,r={type:"text",text:{body:t},...L(a)};return e.message.previewUrl&&r.text&&(r.text.preview_url=e.message.previewUrl),r},list:e=>{if("list"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{list:r,type:n,...o}=t;return{...L(a),type:"interactive",interactive:{...o,type:n,action:r}}},button:e=>{if("button"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{buttons:r,type:n,...o}=t;return{...L(a),type:"interactive",interactive:{...o,type:n,action:{buttons:r.map((e=>({reply:{id:e.id,title:e.text},type:"reply"})))}}}},template:e=>{if("template"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...a},...r}=e,n={...L(r),type:t,template:{...a,language:{code:O(a.language)}}};return n.template&&(n.template.namespace=process.env.WHATSAPP_MESSAGE_NAMESPACE),n},media:e=>{if("media"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...a},...r}=e,n=Object.entries(a)[0],[o,{ref:i,...s}]=n,l=s,c=L(r);return Number.isNaN(Number(i))?l.link=i:l.id=i,{type:o,[o]:l,...c}},contact:e=>{if("contact"!==e.message.type)throw new Error("Invalid type");const{message:{contacts:t},...a}=e;return{type:"contacts",contacts:t,...L(a)}}};function k(e){const{encrypted_aes_key:t,encrypted_flow_data:r,initial_vector:n}=e,o=a.default.createPrivateKey({key:S.get("WHATSAPP_ACCOUNT_ENCRYPTION_PRIVATE_KEY"),passphrase:S.get("WHATSAPP_ACCOUNT_ENCRYPTION_PASSPHRASE")}),i=a.default.privateDecrypt({key:o,padding:a.default.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},Buffer.from(t,"base64")),s=Buffer.from(r,"base64"),l=Buffer.from(n,"base64"),c=s.subarray(0,-16),d=s.subarray(-16),p=a.default.createDecipheriv("aes-128-gcm",i,l);p.setAuthTag(d);const u=Buffer.concat([p.update(c),p.final()]).toString("utf-8");return{payload:JSON.parse(u),encryptionMetadata:{aesKeyBuffer:i,initialVectorBuffer:l}}}function H(e){const t=new URL(e.url).searchParams,a=t.get("hub.verify_token"),r=t.get("hub.challenge");return!(!a||!r)&&a===S.get("WHATSAPP_WEBHOOK_KEY")&&r}async function K(e,t){const r=e.headers.get("x-hub-signature-256");if(!r)return!1;const n=r.replace("sha256=",""),o=a.default.createHmac("sha256",S.get("WHATSAPP_WEBHOOK_KEY")).update(t,"utf-8").digest("hex");return!!a.default.timingSafeEqual(Buffer.from(n),Buffer.from(o))}var V={toGraph:{sendMessage:e=>z[e.message.type](e),flowResponse:(e,t)=>{if(!t.data)throw new Error("Missing data in flow response");if(!t.screen)throw new Error("Missing screen in flow response");if(t.screen=t.screen.toUpperCase(),"SUCCESS"===t.screen){const a=t.data??{};t.data={extension_message_response:{params:{flow_token:e,...a}}}}return t}},toSDK:{webhook:async function(e){if("GET"===e.method){const t=H(e);if(!t)throw new Error("Invalid health check hub");return{type:"healthCheck",payload:t}}const t=await e.text(),a=JSON.parse(t);if("entry"in a){if(!K(e,t))throw new Error("Invalid application webhook signature");const n=a.entry.flatMap((e=>e.changes)).filter((e=>"messages"===e.field)).flatMap((e=>e.value.messages)).filter(Boolean).map((e=>function(e){const t=e.from,a={id:e.id,type:e.type,timestamp:e.timestamp,metadata:{forwarded:e.context?.forwarded,frequentlyForwarded:e.context?.frequently_forwarded}},r=function(e){if(!(e.audio||e.document||e.video||e.image))return null;const t=e.audio?.id??e.document?.id??e.image?.id??e.video?.id,a=e.audio?.mime_type??e.document?.mime_type??e.image?.mime_type??e.video?.mime_type,r=["audio","document","image","video"].find((t=>e[t])),n=e.image?.sha256??e.document?.sha256??e.video?.sha256;return{id:t,type:r,caption:e.document?.caption??e.image?.caption??e.video?.caption??null,mime_type:a,sha256:n,filename:e.document?.filename??e.video?.filename}}(e),n=function(e){return e.text?.body??e.button?.text??e.interactive?.button_reply?.title??e.interactive?.list_reply?.title??e.document?.caption??null}(e),o=function(e){return e.interactive?{...e.interactive?.button_reply||e.button?{button:{id:e.interactive?.button_reply?.id??null,title:e.button?.text??e.interactive.button_reply?.title,payload:e.button?.payload??null}}:{},...e.interactive.list_reply?{selectedOption:{id:e.interactive.list_reply.id,title:e.interactive.list_reply.title,description:e.interactive.list_reply.description}}:{},...e.interactive.nfm_reply?{flowResponse:JSON.parse(e.interactive.nfm_reply.response_json)}:{}}:null}(e);return{...a,...o&&{interaction:o},...r&&{media:r},text:n,chatId:t}}(e)));return{type:"application",payload:{messageReceived:(r=n,r.length?r:void 0)}}}var r;if("encrypted_flow_data"in a)return{type:"flowExchange",payload:{...k(a),pingResponse:{data:{status:"active"}}}};throw new Error("Unrecognized event")}}},F={messages:{send:async function(e){const t=V.toGraph.sendMessage(e),a=c.messages.send;return await T(a,{body:t})}},flows:{...b},waba:{registerNumber:async function({dataRegion:e,pin:t}){const a=c.waba.registerNumber,r={messaging_product:"whatsapp",pin:t};return e&&(r.data_localization_region=e),await T(a,{body:r},{asUrlEncoded:!0})},encryption:{upload:async function(e){const t=c.waba.updateEncryption,a={business_public_key:e};return await T(t,{body:a},{asUrlEncoded:!0})}}}};async function W(e){return await fetch(e).then((async e=>{const t=await e.arrayBuffer();return Buffer.from(t)}))}var j={verifyHub:H,verifySignature:K,generateWabaEncryption:async function(){const e=a.default.randomUUID(),{publicKey:t,privateKey:r}=a.default.generateKeyPairSync("rsa",{modulusLength:2048,publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem",cipher:"aes-256-cbc",passphrase:e}});return{passphrase:e,publicKey:t,privateKey:r}},decryptFlowBody:k,encryptFlowResponse:function(e,t){const r=[];for(const e of Buffer.from(t.initialVectorBuffer).entries())r.push(~e[1]);const n=a.default.createCipheriv("aes-128-gcm",Buffer.from(t.aesKeyBuffer),Buffer.from(r));return Buffer.concat([n.update(JSON.stringify(e),"utf-8"),n.final(),n.getAuthTag()]).toString("base64")},decryptFlowMedia:async function(e){const t=[];for(const r of e){let{cdn_url:e,encryption_metadata:n}=r;if("EXAMPLE_DATA__CDN_URL_WILL_COME_IN_THIS_FIELD"===e){e="https://picsum.photos/seed/picsum/200";const a=await W(e);t.push(a);continue}const o=await W(e),{iv:i,encryption_key:s,hmac_key:l,encrypted_hash:c,plaintext_hash:d}=n,p={iv:Buffer.from(i,"base64"),encryption_key:Buffer.from(s,"base64"),hmac_key:Buffer.from(l,"base64")};if(a.default.createHash("sha256").update(o).digest("base64")!==c)throw new Error("Encrypted hash validation failed");const u=o.subarray(0,o.length-10),f=o.subarray(-10);if(!a.default.createHmac("sha256",p.hmac_key).update(Buffer.concat([p.iv,u])).digest().subarray(0,10).equals(f))throw new Error("HMAC validation failed");const m=a.default.createDecipheriv("aes-256-cbc",p.encryption_key,p.iv),y=m.update(u),g=Buffer.concat([y,m.final()]);if(a.default.createHash("sha256").update(g).digest("base64")!==d)throw new Error("Decrypted media hash validation failed");t.push(g)}return t}},G={flows:B},q=null;exports.WhatsappErrorCode=h,exports.actions=F,exports.createWhatsapp=()=>q||(q=(()=>{const{settings:e}=v,{actions:t,flows:a,parsers:r,security:n,utils:i,toGraphLanguageTag:s}=_,{endpoints:l}=o;return{settings:e,sdk:{actions:t,flows:a,parsers:r,security:n,utils:i,toGraphLanguageTag:s},graph:{endpoints:l}}})()),exports.endpoints=c,exports.flowAction=d,exports.flowCanSendMessageStatus=g,exports.flowCategory=p,exports.flowMediaData=u,exports.flowMetadata=f,exports.flowScreen=m,exports.flowStatus=y,exports.flowValidationError=w,exports.flows=B,exports.flowsEndpoints=i,exports.messagesEndpoints=s,exports.parsers=V,exports.security=j,exports.toGraphLanguageTag=O,exports.utils=G,exports.wabaEndpoints=l;
|
package/dist/index.d.cts
CHANGED
@@ -2004,10 +2004,13 @@ declare const actions: {
|
|
2004
2004
|
};
|
2005
2005
|
flows: {
|
2006
2006
|
create(body: Omit<WhatsappCreateFlowRequestBody, "flow_json"> & {
|
2007
|
-
flow_json
|
2007
|
+
flow_json?: Record<string, AnyType>;
|
2008
2008
|
}): Promise<WhatsappCreateFlowResponse>;
|
2009
2009
|
updateMetadata(flow_id: string, body: WhatsappFlowUpdateMetadataRequestBody): Promise<WhatsappFlowUpdateMetadataResponse>;
|
2010
|
-
updateJson(flow_id: string, json: Record<string, AnyType>): Promise<WhatsappUpdateFlowJsonResponse
|
2010
|
+
updateJson(flow_id: string, json: Record<string, AnyType>): Promise<WhatsappUpdateFlowJsonResponse | {
|
2011
|
+
success: true;
|
2012
|
+
validation_errors: never[];
|
2013
|
+
}>;
|
2011
2014
|
getPreview(flow_id: string, query?: WhatsappGetFlowWebPreviewPageRequestQuery): Promise<string>;
|
2012
2015
|
get(flow_id: string, query?: {
|
2013
2016
|
fields: Array<keyof WhatsappGetFlowsRequestResponse>;
|
@@ -2108,10 +2111,13 @@ declare const createWhatsapp: () => {
|
|
2108
2111
|
};
|
2109
2112
|
flows: {
|
2110
2113
|
create(body: Omit<WhatsappCreateFlowRequestBody, "flow_json"> & {
|
2111
|
-
flow_json
|
2114
|
+
flow_json?: Record<string, AnyType>;
|
2112
2115
|
}): Promise<WhatsappCreateFlowResponse>;
|
2113
2116
|
updateMetadata(flow_id: string, body: WhatsappFlowUpdateMetadataRequestBody): Promise<WhatsappFlowUpdateMetadataResponse>;
|
2114
|
-
updateJson(flow_id: string, json: Record<string, AnyType>): Promise<WhatsappUpdateFlowJsonResponse
|
2117
|
+
updateJson(flow_id: string, json: Record<string, AnyType>): Promise<WhatsappUpdateFlowJsonResponse | {
|
2118
|
+
success: true;
|
2119
|
+
validation_errors: never[];
|
2120
|
+
}>;
|
2115
2121
|
getPreview(flow_id: string, query?: WhatsappGetFlowWebPreviewPageRequestQuery): Promise<string>;
|
2116
2122
|
get(flow_id: string, query?: {
|
2117
2123
|
fields: Array<keyof WhatsappGetFlowsRequestResponse>;
|
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"publishConfig": {
|
5
5
|
"access": "public"
|
6
6
|
},
|
7
|
-
"version": "0.0.
|
7
|
+
"version": "0.0.7",
|
8
8
|
"type": "module",
|
9
9
|
"files": [
|
10
10
|
"dist"
|
@@ -23,7 +23,7 @@
|
|
23
23
|
},
|
24
24
|
"devDependencies": {
|
25
25
|
"@types/node": "^22.9.1",
|
26
|
-
"barrelsmith": "0.0.
|
26
|
+
"barrelsmith": "0.0.7",
|
27
27
|
"concurrently": "9.1.1",
|
28
28
|
"dotenv": "^16.5.0",
|
29
29
|
"terser": "^5.39.0",
|