UNPKG

@k-msg/provider

Version:

Complete provider system with adapters and implementations for K-Message platform

5 lines (3 loc) 29.5 kB
var{defineProperty:re,getOwnPropertyNames:ke,getOwnPropertyDescriptor:Oe}=Object,Pe=Object.prototype.hasOwnProperty;var fe=new WeakMap,Ce=(e)=>{var t=fe.get(e),n;if(t)return t;if(t=re({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")ke(e).map((r)=>!Pe.call(t,r)&&re(t,r,{get:()=>e[r],enumerable:!(n=Oe(e,r))||n.enumerable}));return fe.set(e,t),t};var _e=(e,t)=>{for(var n in t)re(e,n,{get:t[n],enumerable:!0,configurable:!0,set:(r)=>t[n]=()=>r})};var Be={};_e(Be,{default:()=>$,createIWINVSendProvider:()=>xe,createDefaultIWINVSendProvider:()=>le,IWINV_STATUS_CODES:()=>ze,IWINVSendProviderFactory:()=>me,IWINVSendProvider:()=>$});module.exports=Ce(Be);var i=require("@k-msg/core");var ge={iwinv:{providerId:"iwinv",providerName:"IWINV Messaging Provider",channelOnboarding:"manual",templateLifecycleApi:"available",plusIdPolicy:"optional",plusIdInference:"unsupported",liveTestSupport:"supported",checks:[{id:"channel_registered_in_console",title:"Kakao channel is registered in IWINV console",description:"IWINV channel onboarding is manual. Confirm channel registration and approval in console.",kind:"manual",severity:"blocker",scopes:["doctor","preflight"]},{id:"iwinv_config_required",title:"IWINV config has required keys",kind:"config",severity:"blocker",scopes:["doctor","preflight"],configKeys:["apiKey"]},{id:"template_capability_available",title:"Template lifecycle APIs are available",kind:"capability",severity:"warning",scopes:["doctor","preflight"],capabilityMethods:["listTemplates","getTemplate","createTemplate","updateTemplate","deleteTemplate"]},{id:"template_list_probe",title:"Template list API probe",kind:"api_probe",severity:"warning",scopes:["doctor","preflight"],probeOperation:"list_templates"}],notes:["Channel add/auth is not available via IWINV public API in current integration.","Template APIs are available and can be probed."]},aligo:{providerId:"aligo",providerName:"Aligo Smart SMS",channelOnboarding:"api",templateLifecycleApi:"available",plusIdPolicy:"required_if_no_inference",plusIdInference:"supported",liveTestSupport:"supported",checks:[{id:"aligo_config_required",title:"Aligo config has required keys",kind:"config",severity:"blocker",scopes:["doctor","preflight"],configKeys:["apiKey","userId"]},{id:"channel_api_capability_available",title:"Kakao channel APIs are available",kind:"capability",severity:"warning",scopes:["doctor","preflight"],capabilityMethods:["listKakaoChannels","requestKakaoChannelAuth","addKakaoChannel"]},{id:"channel_list_probe",title:"Kakao channel list API probe",kind:"api_probe",severity:"warning",scopes:["doctor","preflight"],probeOperation:"list_kakao_channels"},{id:"template_list_probe",title:"Template list API probe",kind:"api_probe",severity:"warning",scopes:["doctor","preflight"],probeOperation:"list_templates"}]},solapi:{providerId:"solapi",providerName:"SOLAPI Messaging Provider",channelOnboarding:"none",templateLifecycleApi:"unavailable",plusIdPolicy:"required_if_no_inference",plusIdInference:"unsupported",liveTestSupport:"partial",checks:[{id:"solapi_config_required",title:"SOLAPI config has required keys",kind:"config",severity:"blocker",scopes:["doctor","preflight"],configKeys:["apiKey","apiSecret"]}],notes:["SOLAPI ALIMTALK requires kakao profileId/pfId, but plusId inference is not available in current integration."]},mock:{providerId:"mock",providerName:"Mock Provider",channelOnboarding:"api",templateLifecycleApi:"available",plusIdPolicy:"optional",plusIdInference:"supported",liveTestSupport:"none",checks:[{id:"mock_template_capability_available",title:"Mock template APIs are available",kind:"capability",severity:"info",scopes:["doctor","preflight"],capabilityMethods:["listTemplates","getTemplate","createTemplate"]}]}};function ye(e){return ge[e]}function Qe(){return Object.values(ge)}function O(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function _(e){if(!e)return{};try{return JSON.parse(e)}catch{return e}}function W(e,t){return O(e)?e:t}var V=require("@k-msg/core");function Me(e){let t="",n=0;while(n<e.length){let r=e[n++]??0,s=e[n++]??0,a=e[n++]??0,p=r<<16|s<<8|a;t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[p>>18&63],t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[p>>12&63],t+=n-2<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[p>>6&63]:"=",t+=n-1<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[p&63]:"="}return t}function J(e){return Me(new TextEncoder().encode(e))}function Ie(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function j(e){let n={AUTH:J(e.apiKey),"Content-Type":"application/json;charset=UTF-8"};if(typeof e.xForwardedFor==="string"&&e.xForwardedFor.length>0)n["X-Forwarded-For"]=e.xForwardedFor;if(e.extraHeaders&&typeof e.extraHeaders==="object")return{...n,...e.extraHeaders};return n}function Y(e){switch(e){case 201:case 206:case 401:case 403:return V.KMsgErrorCode.AUTHENTICATION_FAILED;case 429:return V.KMsgErrorCode.RATE_LIMIT_EXCEEDED;case 519:return V.KMsgErrorCode.INSUFFICIENT_BALANCE;case 404:case 501:return V.KMsgErrorCode.TEMPLATE_NOT_FOUND;case 502:case 503:case 504:case 505:case 506:case 507:case 508:case 509:case 510:case 511:case 512:case 513:case 514:case 515:case 516:case 517:case 540:return V.KMsgErrorCode.INVALID_REQUEST;case 518:return V.KMsgErrorCode.PROVIDER_ERROR;default:if(e>=500)return V.KMsgErrorCode.PROVIDER_ERROR;return V.KMsgErrorCode.INVALID_REQUEST}}function Z(e){if(typeof e==="number"&&Number.isFinite(e))return e;if(typeof e==="string"){let t=e.trim();if(t.length===0)return;let n=Number(t);if(Number.isFinite(n))return n}return}function Ze(e){if(typeof e!=="string")return;let t=e.trim().toUpperCase();if(!t)return;switch(t){case"Y":case"APPROVED":return"Y";case"I":case"INSPECTION":return"I";case"R":case"REJECTED":return"R";case"PENDING":return"I";default:return}}function et(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}var be="https://alimtalk.bizservice.iwinv.kr",Se="https://sms.bizservice.iwinv.kr";var d=require("@k-msg/core");var M=require("@k-msg/core");function Ve(e){if(typeof DOMException<"u"&&e instanceof DOMException&&e.name==="TimeoutError")return!0;return typeof e==="object"&&e!==null&&"code"in e&&e.code===M.KMsgErrorCode.NETWORK_TIMEOUT}function Fe(e){return typeof DOMException<"u"&&e instanceof DOMException&&e.name==="AbortError"}function Le(e){if(e instanceof Error)return e.message;if(typeof e==="string"&&e.length>0)return e;return"Provider request aborted"}function Ue(e,t,n){if(!t?.aborted)return;if(e instanceof M.KMsgError)return e;let r=t.reason??e,s=Fe(r)?e:r;return new M.KMsgError(Ve(r)?M.KMsgErrorCode.NETWORK_TIMEOUT:M.KMsgErrorCode.REQUEST_ABORTED,Le(s),{providerId:n})}function ee(e,t){if(e instanceof M.KMsgError)return e;return new M.KMsgError(M.KMsgErrorCode.NETWORK_ERROR,e instanceof Error?e.message:String(e),{providerId:t})}function q(e,t,n){return Ue(e,t,n)??ee(e,n)}async function z(e,t,n,r){let s=e?.fetch??globalThis.fetch;if(typeof s!=="function")throw ee(Error("No fetch implementation is available; provide ProviderRequestContext.fetch or use a runtime with native fetch support"),r);try{return await s(t,{...n,signal:e?.signal})}catch(a){throw q(a,e?.signal,r)}}var G=require("@k-msg/core");function F(e){return e.replace(/[^0-9]/g,"")}function L(){return Se}function H(e){if(e.smsApiKey&&e.smsAuthKey)return J(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return J(`${e.apiKey}&${t}`)}function B(e){return H(e).length>0}function ie(e){if(typeof e==="number"&&Number.isFinite(e))return e.toString();if(typeof e==="string")return e.trim();return""}function oe(e,t){return{"0":"전송 성공","1":"메시지가 전송되지 않았습니다.","11":"운영 중인 서비스가 아닙니다.","12":"요금제 충전 중입니다. 잠시 후 다시 시도해 보시기 바랍니다.","13":"등록되지 않은 발신번호입니다.","14":"인증 요청이 올바르지 않습니다.","15":"등록하지 않은 IP에서는 발송되지 않습니다.","21":"장문 메시지는 2000 Bytes까지만 입력이 가능합니다.","22":"제목 입력 가능 문자가 올바르지 않습니다.","23":"제목은 40 Byte까지만 입력이 가능합니다.","31":"파일 업로드는 100KB까지 가능합니다.","32":"허용되지 않는 파일 확장자입니다.","33":"이미지 업로드에 실패했습니다.","41":"수신 번호를 입력하여 주세요.","42":"예약 전송 가능 시간이 아닙니다.","43":"날짜와 시간 표현 형식에 맞춰 입력하여 주십시오.","44":"최대 1000건 전송 가능합니다.","50":"SMS 자동 충전 한도를 초과하였습니다.","202":"SMS API 인증 실패 또는 SMS 서비스 권한이 없습니다.","206":"등록하지 않은 IP에서는 발송되지 않습니다."}[e]||t}function se(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return G.KMsgErrorCode.AUTHENTICATION_FAILED;if(e==="50")return G.KMsgErrorCode.INSUFFICIENT_BALANCE;if(e==="13"||e==="21"||e==="22"||e==="23"||e==="31"||e==="32"||e==="33"||e==="41"||e==="42"||e==="43"||e==="44")return G.KMsgErrorCode.INVALID_REQUEST;if(!t)return G.KMsgErrorCode.NETWORK_ERROR;return G.KMsgErrorCode.PROVIDER_ERROR}function ae(e,t){if(t&&t.trim().length>0)return t.trim();return e.slice(0,20)}function Ne(e,t){if(e==="06")return"DELIVERED";if(e==="1000")return"DELIVERED";if(typeof t==="string"){if(t.includes("전송 성공"))return"DELIVERED";if(t.includes("대기")||t.includes("처리중"))return"PENDING"}if(e==="00"||e==="01")return"PENDING";if(!e&&!t)return"UNKNOWN";return"FAILED"}function de(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function pe(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function te(e){if(typeof e!=="string")return;let t=e.trim();if(!t)return;let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})$/.exec(t);if(!n)return;let r=Number(n[1]),s=Number(n[2]),a=Number(n[3]),p=Number(n[4]),f=Number(n[5]),l=Number(n[6]);if(!Number.isFinite(r)||!Number.isFinite(s)||!Number.isFinite(a)||!Number.isFinite(p)||!Number.isFinite(f)||!Number.isFinite(l))return;let y=new Date(r,s-1,a,p,f,l);if(Number.isNaN(y.getTime()))return;return y}function X(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function ce(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}async function Te(e){let{providerId:t,config:n,query:r,context:s}=e,a=r.providerMessageId.trim();if(!a)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let p=F(r.to);if(!p)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let f=Number(a),l=Number.isFinite(f)?f:void 0,y=X(de(r.requestedAt,-1)),I=X(new Date),b={pageNum:1,pageSize:15,phone:p,startDate:y,endDate:I,...l!==void 0?{seqNo:l}:{},...r.scheduledAt instanceof Date&&!Number.isNaN(r.scheduledAt.getTime())?{reserve:"Y"}:{}},x=`${n.baseUrl}/api/history/`;try{let c=await z(s,x,{method:"POST",headers:j(n),body:JSON.stringify(b)},t),S=await c.text(),P=_(S),g=W(P,{}),R=g.code,D=typeof R==="number"?R:void 0,u=typeof g.message==="string"&&g.message.length>0?g.message:"IWINV history query failed";if(!c.ok||D!==200)return d.fail(new d.KMsgError(Y(D??Z(P)??c.status),u,{providerId:t,originalCode:R??c.status}));let h=g.list,v=Array.isArray(h)?h:[];if(v.length===0)return d.ok(null);let m=(()=>{if(l===void 0)return v[0];return v.find((T)=>O(T)&&T.seqNo===l)??v[0]})();if(!O(m))return d.ok(null);let E=typeof m.statusCode==="string"?m.statusCode:void 0,w=typeof m.statusCodeName==="string"?m.statusCodeName:void 0,N=te(m.sendDate),U=te(m.receiveDate),C=E==="OK"||typeof w==="string"&&w.includes("성공");return d.ok({providerId:t,providerMessageId:a,status:C?"DELIVERED":N?"FAILED":"PENDING",statusCode:E,statusMessage:w,sentAt:N,deliveredAt:C?U||N:void 0,failedAt:!C&&N?N:void 0,raw:m})}catch(c){return d.fail(q(c,s?.signal,t))}}async function ve(e){let{providerId:t,config:n,query:r,context:s}=e;if(!B(n))return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));if(!n.smsCompanyId||n.smsCompanyId.length===0)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"smsCompanyId required for history (config.smsCompanyId)",{providerId:t}));let a=r.providerMessageId.trim();if(!a)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let p=F(r.to);if(!p)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let f=de(r.requestedAt,-1),l=new Date;if(l.getTime()-f.getTime()>7776000000)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"SMS history date range must be within 90 days",{providerId:t}));let b={version:"1.0",companyid:n.smsCompanyId,startDate:pe(f),endDate:pe(l),requestNo:a,pageNum:1,pageSize:15,phone:p},c={"Content-Type":"application/json;charset=UTF-8",secret:H(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)c["X-Forwarded-For"]=n.xForwardedFor;let S=n.extraHeaders&&typeof n.extraHeaders==="object"?{...c,...n.extraHeaders}:c,P=`${L()}/api/history/`;try{let g=await z(s,P,{method:"POST",headers:S,body:JSON.stringify(b)},t),R=await g.text(),D=_(R),u=W(D,{}),h=u.resultCode,v=typeof h==="number"?h:typeof h==="string"?Number(h):NaN,m=typeof u.message==="string"&&u.message.length>0?u.message:"IWINV SMS history query failed";if(!g.ok||v!==0)return d.fail(new d.KMsgError(d.KMsgErrorCode.PROVIDER_ERROR,m,{providerId:t,originalCode:h??g.status}));let E=u.list,w=Array.isArray(E)?E:[];if(w.length===0)return d.ok(null);let N=(()=>{return w.find((K)=>{if(!O(K))return!1;let k=K.requestNo;return k!==void 0&&k!==null?String(k)===a:!1})??w[0]})();if(!O(N))return d.ok(null);let U=typeof N.sendStatusCode==="string"?N.sendStatusCode:void 0,C=typeof N.sendStatusMsg==="string"?N.sendStatusMsg:typeof N.sendStatus==="string"?N.sendStatus:void 0,Q=te(N.sendDate),T=Ne(U,C);return d.ok({providerId:t,providerMessageId:a,status:T,statusCode:U,statusMessage:C,sentAt:Q,deliveredAt:T==="DELIVERED"?Q:void 0,failedAt:T==="FAILED"?Q:void 0,raw:N})}catch(g){return d.fail(q(g,s?.signal,t))}}var o=require("@k-msg/core");var A=require("@k-msg/core");function he(e){let t=e.split(/[?#]/,1)[0]??e,n=t.lastIndexOf(".");if(n<=0||n===t.length-1)return"";return t.slice(n).toLowerCase()}function ue(e){switch(he(e)){case".jpg":case".jpeg":return"image/jpeg";case".png":return"image/png";case".gif":return"image/gif";case".webp":return"image/webp";default:return}}function we(e,t){let n=e&&typeof e==="object"?e:{},s=(n.media&&typeof n.media==="object"?n.media:void 0)?.image;if(s&&typeof s==="object"){if(s.bytes instanceof Uint8Array)return A.ok({bytes:s.bytes,filename:typeof s.filename==="string"?s.filename:void 0,contentType:typeof s.contentType==="string"?s.contentType:void 0});if(s.blob instanceof Blob)return A.ok({blob:s.blob,filename:typeof s.filename==="string"?s.filename:void 0,contentType:typeof s.contentType==="string"?s.contentType:void 0});if(typeof s.ref==="string"&&s.ref.trim().length>0)return A.fail(new A.KMsgError(A.KMsgErrorCode.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"media.image.ref"}))}let a=n.imageUrl;if(typeof a==="string"&&a.trim().length>0)return A.fail(new A.KMsgError(A.KMsgErrorCode.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"imageUrl"}));return A.ok(void 0)}async function Ee(e){if("blob"in e){let a=e.contentType||e.blob.type||"application/octet-stream",p=e.filename||"image",f=e.contentType&&e.contentType!==e.blob.type?new Blob([await e.blob.arrayBuffer()],{type:a}):e.blob;return{blob:f,filename:p,contentType:a,size:f.size}}let t=e.contentType||"application/octet-stream",n=new Uint8Array(e.bytes.byteLength);n.set(e.bytes);let r=new Blob([n],{type:t}),s=e.filename||"image";return{blob:r,filename:s,contentType:t,size:r.size}}function Ae(e){if(he(e.filename).length>0)return e.filename;let n=ue(e.filename)==="image/png"?".png":ue(e.filename)==="image/gif"?".gif":ue(e.filename)==="image/webp"?".webp":e.contentType==="image/png"?".png":e.contentType==="image/gif"?".gif":e.contentType==="image/webp"?".webp":".jpg";return`${e.filename}${n}`}async function Re(e){let{providerId:t,config:n,options:r,context:s}=e,a=r.templateId;if(!a||a.length===0)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"templateId is required for ALIMTALK",{providerId:t}));let p=r.options?.scheduledAt,f=p instanceof Date&&!Number.isNaN(p.getTime()),l=f?"Y":"N",y=f?X(p):void 0,I=F(r.to);if(!I)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let b=r.providerOptions?.templateParam,x=Array.isArray(b)?b.map((T)=>T===null||T===void 0?"":String(T)):Object.values(r.variables||{}).map((T)=>T===null||T===void 0?"":String(T)),c=r.failover,S=(typeof r.from==="string"&&r.from.length>0?r.from:n.senderNumber||n.smsSenderNumber)||"",P=S?F(S):"",g=typeof r.providerOptions?.reSend==="string"?r.providerOptions.reSend.trim().toUpperCase():"",R=g==="Y"||g==="N"?g:void 0,D=c?.enabled===!0?"Y":c?.enabled===!1?"N":void 0,u=R??D??(P?"Y":"N"),v=(typeof r.providerOptions?.resendCallback==="string"?F(r.providerOptions.resendCallback):"")||P;if(u==="Y"&&!v)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"resendCallback is required when reSend is 'Y' (options.from or providerOptions.resendCallback)",{providerId:t}));let m=typeof r.providerOptions?.resendType==="string"?r.providerOptions.resendType.trim().toUpperCase():"",E=m==="Y"||m==="N"?m:void 0;if(typeof r.providerOptions?.resendType==="string"&&r.providerOptions.resendType.length>0&&!E)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"resendType must be 'Y' or 'N'",{providerId:t}));let w=c?.fallbackChannel==="lms"?"Y":c?.fallbackChannel==="sms"?"N":void 0,N=typeof r.providerOptions?.resendTitle==="string"&&r.providerOptions.resendTitle.trim().length>0?r.providerOptions.resendTitle.trim():typeof c?.fallbackTitle==="string"&&c.fallbackTitle.trim().length>0?c.fallbackTitle.trim():void 0,U=typeof r.providerOptions?.resendContent==="string"&&r.providerOptions.resendContent.trim().length>0?r.providerOptions.resendContent.trim():typeof c?.fallbackContent==="string"&&c.fallbackContent.trim().length>0?c.fallbackContent.trim():void 0,C={templateCode:a,reserve:l,...y?{sendDate:y}:{},list:[{phone:I,templateParam:x.length>0?x:void 0}],reSend:u,...v?{resendCallback:v}:{},...E??w?{resendType:E??w}:{},...N?{resendTitle:N}:{},...U?{resendContent:U}:{}},Q=`${n.baseUrl}${Ie(n)}`;try{let T=await z(s,Q,{method:"POST",headers:j(n),body:JSON.stringify(C)},t),ne=await T.text(),K=_(ne),k=O(K)?K:{code:Z(K)??T.status,message:ne||String(K||"")};if(!T.ok||k.code!==200)return o.fail(new o.KMsgError(Y(k.code),k.message||"IWINV send failed",{providerId:t,originalCode:k.code}));return o.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:typeof k.seqNo==="number"?String(k.seqNo):void 0,status:f?"PENDING":"SENT",type:r.type,to:r.to,raw:k})}catch(T){return o.fail(q(T,s?.signal,t))}}async function qe(e){let{providerId:t,config:n,options:r,to:s,from:a,text:p,scheduledAtValid:f,scheduledAt:l,context:y}=e;if(r.type!=="MMS")return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"IWINVProvider: MMS handler called with non-MMS options",{providerId:t,type:r.type}));let I=ae(p,r.subject),b=we(r,t);if(b.isFailure)return b;let x=b.value;if(!x)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"image is required for MMS; caller must provide options.media.image.blob or bytes",{providerId:t}));let c;try{c=await Ee(x)}catch(u){return o.fail(ee(u,t))}if(c.size>102400)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"MMS image must be <= 100KB",{providerId:t,bytes:c.size}));let S=new FormData;if(S.append("version","1.0"),S.append("from",a),S.append("to",s),S.append("title",I),S.append("text",p),f&&l)S.append("date",ce(l));S.append("image",c.blob,Ae(c));let g={secret:H(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)g["X-Forwarded-For"]=n.xForwardedFor;let R={...g};if(n.extraHeaders&&typeof n.extraHeaders==="object")for(let[u,h]of Object.entries(n.extraHeaders)){if(u.toLowerCase()==="content-type")continue;R[u]=h}let D=`${L()}/api/v2/send/`;try{let u=await z(y,D,{method:"POST",headers:R,body:S},t),h=await u.text(),v=_(h),m=O(v)?v:{resultCode:v},E=m.resultCode??m.code,w=ie(E),N=typeof m.message==="string"&&m.message.length>0?m.message:oe(w,"MMS send failed");if(!(u.ok&&w==="0"))return o.fail(new o.KMsgError(se(w,u.ok),N,{providerId:t,originalCode:E}));let C=typeof m.requestNo==="string"&&m.requestNo.length>0?m.requestNo:typeof m.msgid==="string"&&m.msgid.length>0?m.msgid:void 0;return o.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:C,status:f?"PENDING":"SENT",type:r.type,to:r.to,raw:m})}catch(u){return o.fail(q(u,y?.signal,t))}}async function De(e){let{providerId:t,config:n,options:r,context:s}=e;if(!B(n))return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));let a=F(r.to);if(!a)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let p=r.text;if(!p||p.trim().length===0)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"text is required for SMS/LMS/MMS",{providerId:t}));let f=(typeof r.from==="string"&&r.from.length>0?r.from:n.smsSenderNumber||n.senderNumber)||"",l=f?F(f):"";if(!l)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"from is required for SMS/LMS/MMS (options.from or config.smsSenderNumber)",{providerId:t}));let y=r.options?.scheduledAt,I=y instanceof Date&&!Number.isNaN(y.getTime());if(r.type==="MMS")return await qe({providerId:t,config:n,options:r,to:a,from:l,text:p,scheduledAtValid:I,scheduledAt:I?y:void 0,context:s});let b={version:"1.0",from:l,to:[a],text:p};if(r.type==="LMS")b.title=ae(p,r.subject);else{let g=typeof r.providerOptions?.msgType==="string"&&r.providerOptions.msgType.trim().length>0?r.providerOptions.msgType.trim():void 0;b.msgType=g||r.type}if(I)b.date=ce(y);let c={"Content-Type":"application/json;charset=UTF-8",secret:H(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)c["X-Forwarded-For"]=n.xForwardedFor;let S=n.extraHeaders&&typeof n.extraHeaders==="object"?{...c,...n.extraHeaders}:c,P=`${L()}/api/v2/send/`;try{let g=await z(s,P,{method:"POST",headers:S,body:JSON.stringify(b)},t),R=await g.text(),D=_(R),u=O(D)?D:{resultCode:D},h=u.resultCode??u.code,v=ie(h),m=typeof u.message==="string"&&u.message.length>0?u.message:oe(v,"SMS send failed");if(!(g.ok&&v==="0"))return o.fail(new o.KMsgError(se(v,g.ok),m,{providerId:t,originalCode:h}));let w=typeof u.requestNo==="string"&&u.requestNo.length>0?u.requestNo:typeof u.msgid==="string"&&u.msgid.length>0?u.msgid:void 0;return o.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:w,status:I?"PENDING":"SENT",type:r.type,to:r.to,raw:u})}catch(g){return o.fail(q(g,s?.signal,t))}}function He(e){return{...e,baseUrl:be,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}function Ke(){return{apiKey:i.readRuntimeEnv("IWINV_API_KEY")||"",smsApiKey:i.readRuntimeEnv("IWINV_SMS_API_KEY"),smsAuthKey:i.readRuntimeEnv("IWINV_SMS_AUTH_KEY"),smsCompanyId:i.readRuntimeEnv("IWINV_SMS_COMPANY_ID"),senderNumber:i.readRuntimeEnv("IWINV_SENDER_NUMBER")||i.readRuntimeEnv("IWINV_SMS_SENDER_NUMBER"),smsSenderNumber:i.readRuntimeEnv("IWINV_SMS_SENDER_NUMBER"),sendEndpoint:i.readRuntimeEnv("IWINV_SEND_ENDPOINT")||"/api/v2/send/",xForwardedFor:i.readRuntimeEnv("IWINV_X_FORWARDED_FOR"),debug:i.readRuntimeEnv("NODE_ENV")==="development"}}class ${id="iwinv";name="IWINV Messaging Provider";supportedTypes;transportCapabilities={abortSignal:"supported",injectableFetch:"supported"};config;getOnboardingSpec(){let e=ye(this.id);if(!e)throw new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,`Onboarding spec missing for provider: ${this.id}`,{providerId:this.id});return e}constructor(e){if(!e||typeof e!=="object")throw new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,"IWINVProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,"IWINVProvider requires `apiKey` configuration",{providerId:this.id});this.config=He(e);let t=["ALIMTALK"];if(B(this.config))t.push("SMS","LMS","MMS");this.supportedTypes=t}async healthCheck(){let e=Date.now(),t=[];try{try{new URL(this.config.baseUrl)}catch{t.push("Invalid baseUrl")}if(B(this.config))try{new URL(L())}catch{t.push("Invalid smsBaseUrl")}return{healthy:t.length===0,issues:t,latencyMs:Date.now()-e,data:{provider:this.id,baseUrl:this.config.baseUrl,smsBaseUrl:L()}}}catch(n){return t.push(n instanceof Error?n.message:String(n)),{healthy:!1,issues:t,latencyMs:Date.now()-e}}}async send(e,t){let n=e.messageId||crypto.randomUUID(),r={...e,messageId:n};switch(r.type){case"ALIMTALK":return Re({providerId:this.id,config:this.config,options:r,context:t});case"SMS":case"LMS":case"MMS":return De({providerId:this.id,config:this.config,options:r,context:t});default:return i.fail(new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,`IWINVProvider does not support type ${r.type}`,{providerId:this.id,type:r.type}))}}async getDeliveryStatus(e,t){switch(e.type){case"ALIMTALK":return Te({providerId:this.id,config:this.config,query:e,context:t});case"SMS":case"LMS":case"MMS":return ve({providerId:this.id,config:this.config,query:e,context:t});default:return i.fail(new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,`IWINVProvider does not support type ${e.type}`,{providerId:this.id,type:e.type}))}}async getBalance(e){let t=e?.channel??"ALIMTALK";switch(t){case"ALIMTALK":return this.getAlimTalkBalance(t);case"SMS":case"LMS":case"MMS":return this.getSmsBalance(t);default:return i.fail(new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,`IWINVProvider does not support balance query for type ${t}`,{providerId:this.id,type:t}))}}async getAlimTalkBalance(e){let t=`${this.config.baseUrl}/api/charge/`;try{let n=await fetch(t,{method:"POST",headers:j(this.config),body:JSON.stringify({})}),r=await n.text(),s=_(r),a=W(s,{}),p=a.code,f=typeof p==="string"?Number(p):void 0,l=typeof p==="number"?p:typeof f==="number"&&Number.isFinite(f)?f:void 0,y=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV AlimTalk charge query failed";if(!n.ok||l!==200)return i.fail(new i.KMsgError(Y(l??n.status),y,{providerId:this.id,originalCode:p??n.status}));let I=a.charge,b=typeof I==="number"?I:typeof I==="string"?Number(I):NaN;if(!Number.isFinite(b))return i.fail(new i.KMsgError(i.KMsgErrorCode.PROVIDER_ERROR,"Invalid charge value from IWINV AlimTalk charge API",{providerId:this.id,raw:a}));return i.ok({providerId:this.id,channel:e,amount:b,currency:"KRW",raw:a})}catch(n){return i.fail(new i.KMsgError(i.KMsgErrorCode.NETWORK_ERROR,n instanceof Error?n.message:String(n),{providerId:this.id}))}}async getSmsBalance(e){if(!this.config.smsApiKey||!this.config.smsAuthKey)return i.fail(new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,"smsApiKey and smsAuthKey are required for SMS/LMS/MMS balance query",{providerId:this.id}));let n={"Content-Type":"application/json;charset=UTF-8",secret:H(this.config)};if(typeof this.config.xForwardedFor==="string"&&this.config.xForwardedFor.length>0)n["X-Forwarded-For"]=this.config.xForwardedFor;let r=this.config.extraHeaders&&typeof this.config.extraHeaders==="object"?{...n,...this.config.extraHeaders}:n,s=`${L()}/api/charge/`;try{let a=await fetch(s,{method:"POST",headers:r,body:JSON.stringify({version:"1.0"})}),p=await a.text(),f=_(p),l=W(f,{}),y=l.code??l.resultCode,I=typeof y==="string"?Number(y):void 0,b=typeof y==="number"?y:typeof I==="number"&&Number.isFinite(I)?I:NaN,x=typeof l.message==="string"&&l.message.length>0?l.message:"IWINV SMS charge query failed";if(!a.ok||b!==0)return i.fail(new i.KMsgError(i.KMsgErrorCode.PROVIDER_ERROR,x,{providerId:this.id,originalCode:y??a.status}));let c=l.charge,S=typeof c==="number"?c:typeof c==="string"?Number(c):NaN;if(!Number.isFinite(S))return i.fail(new i.KMsgError(i.KMsgErrorCode.PROVIDER_ERROR,"Invalid charge value from IWINV SMS charge API",{providerId:this.id,raw:l}));return i.ok({providerId:this.id,channel:e,amount:S,currency:"KRW",raw:l})}catch(a){return i.fail(new i.KMsgError(i.KMsgErrorCode.NETWORK_ERROR,a instanceof Error?a.message:String(a),{providerId:this.id}))}}}var xe=(e)=>new $(e),le=()=>{let e=Ke();if(!e.apiKey)throw new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new $(e)};class me{static create(e){return new $(e)}static createDefault(){return le()}}var ze={SUCCESS:200,AUTH_FAILED:201,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500}; //# debugId=FD017B53993C4AF564756E2164756E21 //# sourceMappingURL=send.js.map