@k-msg/provider 0.27.1 → 0.27.2

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.
@@ -1,4 +1,4 @@
1
- import{fail as W,KMsgError as k,KMsgErrorCode as _,ok as Be,readRuntimeEnv as $}from"@k-msg/core";var Te={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 ve(e){return Te[e]}function Ge(){return Object.values(Te)}function x(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function V(e){if(!e)return{};try{return JSON.parse(e)}catch{return e}}function Y(e,t){return x(e)?e:t}import{KMsgErrorCode as J}from"@k-msg/core";function Qe(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 se(e){return Qe(new TextEncoder().encode(e))}function Ee(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function P(e){let n={AUTH:se(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 M(e){switch(e){case 201:case 206:case 401:case 403:return J.AUTHENTICATION_FAILED;case 429:return J.RATE_LIMIT_EXCEEDED;case 519:return J.INSUFFICIENT_BALANCE;case 404:case 501:return J.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 J.INVALID_REQUEST;case 518:return J.PROVIDER_ERROR;default:if(e>=500)return J.PROVIDER_ERROR;return J.INVALID_REQUEST}}function L(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 Re(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 le(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}var he="https://alimtalk.bizservice.iwinv.kr",Ae="https://sms.bizservice.iwinv.kr";import{fail as U,KMsgError as K,KMsgErrorCode as H,ok as ne}from"@k-msg/core";import{KMsgErrorCode as oe}from"@k-msg/core";function B(e){return e.replace(/[^0-9]/g,"")}function Q(){return Ae}function G(e){if(e.smsApiKey&&e.smsAuthKey)return se(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return se(`${e.apiKey}&${t}`)}function Z(e){return G(e).length>0}function ue(e){if(typeof e==="number"&&Number.isFinite(e))return e.toString();if(typeof e==="string")return e.trim();return""}function me(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 fe(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return oe.AUTHENTICATION_FAILED;if(e==="50")return oe.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 oe.INVALID_REQUEST;if(!t)return oe.NETWORK_ERROR;return oe.PROVIDER_ERROR}function ge(e,t){if(t&&t.trim().length>0)return t.trim();return e.slice(0,20)}function De(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 ye(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function Ie(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function ee(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]),o=Number(n[5]),i=Number(n[6]);if(!Number.isFinite(r)||!Number.isFinite(s)||!Number.isFinite(a)||!Number.isFinite(p)||!Number.isFinite(o)||!Number.isFinite(i))return;let c=new Date(r,s-1,a,p,o,i);if(Number.isNaN(c.getTime()))return;return c}function ie(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 be(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 Ce(e){let{providerId:t,config:n,query:r}=e,s=r.providerMessageId.trim();if(!s)return U(new K(H.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let a=B(r.to);if(!a)return U(new K(H.INVALID_REQUEST,"to is required",{providerId:t}));let p=Number(s),o=Number.isFinite(p)?p:void 0,i=ie(ye(r.requestedAt,-1)),c=ie(new Date),f={pageNum:1,pageSize:15,phone:a,startDate:i,endDate:c,...o!==void 0?{seqNo:o}:{},...r.scheduledAt instanceof Date&&!Number.isNaN(r.scheduledAt.getTime())?{reserve:"Y"}:{}},I=`${n.baseUrl}/api/history/`;try{let d=await fetch(I,{method:"POST",headers:P(n),body:JSON.stringify(f)}),m=await d.text(),w=V(m),u=Y(w,{}),g=u.code,S=typeof g==="number"?g:void 0,l=typeof u.message==="string"&&u.message.length>0?u.message:"IWINV history query failed";if(!d.ok||S!==200)return U(new K(M(S??L(w)??d.status),l,{providerId:t,originalCode:g??d.status}));let b=u.list,T=Array.isArray(b)?b:[];if(T.length===0)return ne(null);let y=(()=>{if(o===void 0)return T[0];return T.find((N)=>x(N)&&N.seqNo===o)??T[0]})();if(!x(y))return ne(null);let D=typeof y.statusCode==="string"?y.statusCode:void 0,C=typeof y.statusCodeName==="string"?y.statusCodeName:void 0,v=ee(y.sendDate),j=ee(y.receiveDate),z=D==="OK"||typeof C==="string"&&C.includes("성공");return ne({providerId:t,providerMessageId:s,status:z?"DELIVERED":v?"FAILED":"PENDING",statusCode:D,statusMessage:C,sentAt:v,deliveredAt:z?j||v:void 0,failedAt:!z&&v?v:void 0,raw:y})}catch(d){return U(new K(H.NETWORK_ERROR,d instanceof Error?d.message:String(d),{providerId:t}))}}async function Oe(e){let{providerId:t,config:n,query:r}=e;if(!Z(n))return U(new K(H.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));if(!n.smsCompanyId||n.smsCompanyId.length===0)return U(new K(H.INVALID_REQUEST,"smsCompanyId required for history (config.smsCompanyId)",{providerId:t}));let s=r.providerMessageId.trim();if(!s)return U(new K(H.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let a=B(r.to);if(!a)return U(new K(H.INVALID_REQUEST,"to is required",{providerId:t}));let p=ye(r.requestedAt,-1),o=new Date;if(o.getTime()-p.getTime()>7776000000)return U(new K(H.INVALID_REQUEST,"SMS history date range must be within 90 days",{providerId:t}));let f={version:"1.0",companyid:n.smsCompanyId,startDate:Ie(p),endDate:Ie(o),requestNo:s,pageNum:1,pageSize:15,phone:a},d={"Content-Type":"application/json;charset=UTF-8",secret:G(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)d["X-Forwarded-For"]=n.xForwardedFor;let m=n.extraHeaders&&typeof n.extraHeaders==="object"?{...d,...n.extraHeaders}:d,w=`${Q()}/api/history/`;try{let u=await fetch(w,{method:"POST",headers:m,body:JSON.stringify(f)}),g=await u.text(),S=V(g),l=Y(S,{}),b=l.resultCode,T=typeof b==="number"?b:typeof b==="string"?Number(b):NaN,y=typeof l.message==="string"&&l.message.length>0?l.message:"IWINV SMS history query failed";if(!u.ok||T!==0)return U(new K(H.PROVIDER_ERROR,y,{providerId:t,originalCode:b??u.status}));let D=l.list,C=Array.isArray(D)?D:[];if(C.length===0)return ne(null);let v=(()=>{return C.find((X)=>{if(!x(X))return!1;let F=X.requestNo;return F!==void 0&&F!==null?String(F)===s:!1})??C[0]})();if(!x(v))return ne(null);let j=typeof v.sendStatusCode==="string"?v.sendStatusCode:void 0,z=typeof v.sendStatusMsg==="string"?v.sendStatusMsg:typeof v.sendStatus==="string"?v.sendStatus:void 0,te=ee(v.sendDate),N=De(j,z);return ne({providerId:t,providerMessageId:s,status:N,statusCode:j,statusMessage:z,sentAt:te,deliveredAt:N==="DELIVERED"?te:void 0,failedAt:N==="FAILED"?te:void 0,raw:v})}catch(u){return U(new K(H.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}import{fail as R,KMsgError as E,KMsgErrorCode as O,ok as we}from"@k-msg/core";import{fail as xe,KMsgError as ke,KMsgErrorCode as _e,ok as Se}from"@k-msg/core";function Ve(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 Ne(e){switch(Ve(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 Pe(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 Se({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 Se({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 xe(new ke(_e.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 xe(new ke(_e.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"imageUrl"}));return Se(void 0)}async function Me(e){if("blob"in e){let a=e.contentType||e.blob.type||"application/octet-stream",p=e.filename||"image",o=e.contentType&&e.contentType!==e.blob.type?new Blob([await e.blob.arrayBuffer()],{type:a}):e.blob;return{blob:o,filename:p,contentType:a,size:o.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 Fe(e){if(Ve(e.filename).length>0)return e.filename;let n=Ne(e.filename)==="image/png"?".png":Ne(e.filename)==="image/gif"?".gif":Ne(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 Le(e){let{providerId:t,config:n,options:r}=e,s=r.templateId;if(!s||s.length===0)return R(new E(O.INVALID_REQUEST,"templateId is required for ALIMTALK",{providerId:t}));let a=r.options?.scheduledAt,p=a instanceof Date&&!Number.isNaN(a.getTime()),o=p?"Y":"N",i=p?ie(a):void 0,c=B(r.to);if(!c)return R(new E(O.INVALID_REQUEST,"to is required",{providerId:t}));let f=r.providerOptions?.templateParam,I=Array.isArray(f)?f.map((N)=>N===null||N===void 0?"":String(N)):Object.values(r.variables||{}).map((N)=>N===null||N===void 0?"":String(N)),d=r.failover,m=(typeof r.from==="string"&&r.from.length>0?r.from:n.senderNumber||n.smsSenderNumber)||"",w=m?B(m):"",u=typeof r.providerOptions?.reSend==="string"?r.providerOptions.reSend.trim().toUpperCase():"",g=u==="Y"||u==="N"?u:void 0,S=d?.enabled===!0?"Y":d?.enabled===!1?"N":void 0,l=g??S??(w?"Y":"N"),T=(typeof r.providerOptions?.resendCallback==="string"?B(r.providerOptions.resendCallback):"")||w;if(l==="Y"&&!T)return R(new E(O.INVALID_REQUEST,"resendCallback is required when reSend is 'Y' (options.from or providerOptions.resendCallback)",{providerId:t}));let y=typeof r.providerOptions?.resendType==="string"?r.providerOptions.resendType.trim().toUpperCase():"",D=y==="Y"||y==="N"?y:void 0;if(typeof r.providerOptions?.resendType==="string"&&r.providerOptions.resendType.length>0&&!D)return R(new E(O.INVALID_REQUEST,"resendType must be 'Y' or 'N'",{providerId:t}));let C=d?.fallbackChannel==="lms"?"Y":d?.fallbackChannel==="sms"?"N":void 0,v=typeof r.providerOptions?.resendTitle==="string"&&r.providerOptions.resendTitle.trim().length>0?r.providerOptions.resendTitle.trim():typeof d?.fallbackTitle==="string"&&d.fallbackTitle.trim().length>0?d.fallbackTitle.trim():void 0,j=typeof r.providerOptions?.resendContent==="string"&&r.providerOptions.resendContent.trim().length>0?r.providerOptions.resendContent.trim():typeof d?.fallbackContent==="string"&&d.fallbackContent.trim().length>0?d.fallbackContent.trim():void 0,z={templateCode:s,reserve:o,...i?{sendDate:i}:{},list:[{phone:c,templateParam:I.length>0?I:void 0}],reSend:l,...T?{resendCallback:T}:{},...D??C?{resendType:D??C}:{},...v?{resendTitle:v}:{},...j?{resendContent:j}:{}},te=`${n.baseUrl}${Ee(n)}`;try{let N=await fetch(te,{method:"POST",headers:P(n),body:JSON.stringify(z)}),ce=await N.text(),X=V(ce),F=x(X)?X:{code:L(X)??N.status,message:ce||String(X||"")};if(!N.ok||F.code!==200)return R(new E(M(F.code),F.message||"IWINV send failed",{providerId:t,originalCode:F.code}));return we({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:typeof F.seqNo==="number"?String(F.seqNo):void 0,status:p?"PENDING":"SENT",type:r.type,to:r.to,raw:F})}catch(N){return R(new E(O.NETWORK_ERROR,N instanceof Error?N.message:String(N),{providerId:t}))}}async function je(e){let{providerId:t,config:n,options:r,to:s,from:a,text:p,scheduledAtValid:o,scheduledAt:i}=e;if(r.type!=="MMS")return R(new E(O.INVALID_REQUEST,"IWINVProvider: MMS handler called with non-MMS options",{providerId:t,type:r.type}));let c=ge(p,r.subject),f=Pe(r,t);if(f.isFailure)return f;let I=f.value;if(!I)return R(new E(O.INVALID_REQUEST,"image is required for MMS; caller must provide options.media.image.blob or bytes",{providerId:t}));let d;try{d=await Me(I)}catch(l){return R(l instanceof E?l:new E(O.NETWORK_ERROR,l instanceof Error?l.message:String(l),{providerId:t}))}if(d.size>102400)return R(new E(O.INVALID_REQUEST,"MMS image must be <= 100KB",{providerId:t,bytes:d.size}));let m=new FormData;if(m.append("version","1.0"),m.append("from",a),m.append("to",s),m.append("title",c),m.append("text",p),o&&i)m.append("date",be(i));m.append("image",d.blob,Fe(d));let u={secret:G(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)u["X-Forwarded-For"]=n.xForwardedFor;let g={...u};if(n.extraHeaders&&typeof n.extraHeaders==="object")for(let[l,b]of Object.entries(n.extraHeaders)){if(l.toLowerCase()==="content-type")continue;g[l]=b}let S=`${Q()}/api/v2/send/`;try{let l=await fetch(S,{method:"POST",headers:g,body:m}),b=await l.text(),T=V(b),y=x(T)?T:{resultCode:T},D=y.resultCode??y.code,C=ue(D),v=typeof y.message==="string"&&y.message.length>0?y.message:me(C,"MMS send failed");if(!(l.ok&&C==="0"))return R(new E(fe(C,l.ok),v,{providerId:t,originalCode:D}));let z=typeof y.requestNo==="string"&&y.requestNo.length>0?y.requestNo:typeof y.msgid==="string"&&y.msgid.length>0?y.msgid:void 0;return we({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:z,status:o?"PENDING":"SENT",type:r.type,to:r.to,raw:y})}catch(l){return R(new E(O.NETWORK_ERROR,l instanceof Error?l.message:String(l),{providerId:t}))}}async function Ue(e){let{providerId:t,config:n,options:r}=e;if(!Z(n))return R(new E(O.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));let s=B(r.to);if(!s)return R(new E(O.INVALID_REQUEST,"to is required",{providerId:t}));let a=r.text;if(!a||a.trim().length===0)return R(new E(O.INVALID_REQUEST,"text is required for SMS/LMS/MMS",{providerId:t}));let p=(typeof r.from==="string"&&r.from.length>0?r.from:n.smsSenderNumber||n.senderNumber)||"",o=p?B(p):"";if(!o)return R(new E(O.INVALID_REQUEST,"from is required for SMS/LMS/MMS (options.from or config.smsSenderNumber)",{providerId:t}));let i=r.options?.scheduledAt,c=i instanceof Date&&!Number.isNaN(i.getTime());if(r.type==="MMS")return await je({providerId:t,config:n,options:r,to:s,from:o,text:a,scheduledAtValid:c,scheduledAt:c?i:void 0});let f={version:"1.0",from:o,to:[s],text:a};if(r.type==="LMS")f.title=ge(a,r.subject);else{let u=typeof r.providerOptions?.msgType==="string"&&r.providerOptions.msgType.trim().length>0?r.providerOptions.msgType.trim():void 0;f.msgType=u||r.type}if(c)f.date=be(i);let d={"Content-Type":"application/json;charset=UTF-8",secret:G(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)d["X-Forwarded-For"]=n.xForwardedFor;let m=n.extraHeaders&&typeof n.extraHeaders==="object"?{...d,...n.extraHeaders}:d,w=`${Q()}/api/v2/send/`;try{let u=await fetch(w,{method:"POST",headers:m,body:JSON.stringify(f)}),g=await u.text(),S=V(g),l=x(S)?S:{resultCode:S},b=l.resultCode??l.code,T=ue(b),y=typeof l.message==="string"&&l.message.length>0?l.message:me(T,"SMS send failed");if(!(u.ok&&T==="0"))return R(new E(fe(T,u.ok),y,{providerId:t,originalCode:b}));let C=typeof l.requestNo==="string"&&l.requestNo.length>0?l.requestNo:typeof l.msgid==="string"&&l.msgid.length>0?l.msgid:void 0;return we({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:C,status:c?"PENDING":"SENT",type:r.type,to:r.to,raw:l})}catch(u){return R(new E(O.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}import{fail as h,KMsgError as A,KMsgErrorCode as q,ok as ae}from"@k-msg/core";import{validateTemplatePayload as Ke}from"@k-msg/template";async function de(e){let t=await e.text(),n=V(t);return Y(n,{code:L(n)??e.status,message:t||String(n||"")})}function qe(e,t){return new A(e.code,e.message,{providerId:t,...e.details??{}})}async function ze(e){let{providerId:t,config:n,input:r}=e;if(!r||typeof r!=="object")return h(new A(q.INVALID_REQUEST,"Template input is required",{providerId:t}));let s=Ke(r,{requireName:!0,requireContent:!0});if(s.isFailure)return h(qe(s.error,t));let a=`${n.baseUrl}/api/template/add/`,p={templateName:s.value.name??r.name,templateContent:s.value.content??r.content,...s.value.buttons?{buttons:s.value.buttons}:{}};try{let o=await fetch(a,{method:"POST",headers:P(n),body:JSON.stringify(p)}),i=await de(o),c=L(i.code)??o.status,f=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV template create failed";if(!o.ok||c!==200)return h(new A(M(c),f,{providerId:t,originalCode:c}));let I=i.templateCode,d=typeof I==="string"&&I.trim().length>0?I.trim():"";if(!d)return h(new A(q.PROVIDER_ERROR,"IWINV template create did not return templateCode",{providerId:t,raw:i}));let m=new Date;return ae({id:d,code:d,name:s.value.name??r.name,content:s.value.content??r.content,category:r.category,status:"INSPECTION",buttons:s.value.buttons,variables:r.variables,createdAt:m,updatedAt:m})}catch(o){return h(new A(q.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function He(e){let{providerId:t,config:n,code:r,patch:s,ctx:a}=e,p=typeof r==="string"?r.trim():"";if(!p)return h(new A(q.INVALID_REQUEST,"code is required",{providerId:t}));let o=await pe({providerId:t,config:n,code:p,ctx:a});if(o.isFailure)return o;let i=o.value,c=typeof s.name==="string"&&s.name.trim().length>0?s.name.trim():i.name,f=typeof s.content==="string"&&s.content.trim().length>0?s.content:i.content,I=s.buttons!==void 0?s.buttons:i.buttons,d=Ke({name:c,content:f,buttons:I},{requireName:!0,requireContent:!0});if(d.isFailure)return h(qe(d.error,t));let m=`${n.baseUrl}/api/template/modify/`,w={templateCode:p,templateName:d.value.name??c,templateContent:d.value.content??f,...d.value.buttons?{buttons:d.value.buttons}:{}};try{let u=await fetch(m,{method:"POST",headers:P(n),body:JSON.stringify(w)}),g=await de(u),S=L(g.code)??u.status,l=typeof g.message==="string"&&g.message.length>0?g.message:"IWINV template update failed";if(!u.ok||S!==200)return h(new A(M(S),l,{providerId:t,originalCode:S}));let b=await pe({providerId:t,config:n,code:p,ctx:a});if(b.isSuccess)return b;return ae({...i,name:d.value.name??c,content:d.value.content??f,...s.category!==void 0?{category:s.category}:{},...s.variables!==void 0?{variables:s.variables}:{},...s.buttons!==void 0?{buttons:d.value.buttons}:{},updatedAt:new Date})}catch(u){return h(new A(q.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}async function We(e){let{providerId:t,config:n,code:r}=e,s=typeof r==="string"?r.trim():"";if(!s)return h(new A(q.INVALID_REQUEST,"code is required",{providerId:t}));let a=`${n.baseUrl}/api/template/delete/`,p={templateCode:s};try{let o=await fetch(a,{method:"POST",headers:P(n),body:JSON.stringify(p)}),i=await de(o),c=L(i.code)??o.status,f=typeof i.message==="string"&&i.message.length>0?i.message:typeof i.messgae==="string"&&i.messgae.length>0?i.messgae:"IWINV template delete failed";if(!o.ok||c!==200)return h(new A(M(c),f,{providerId:t,originalCode:c}));return ae(void 0)}catch(o){return h(new A(q.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function pe(e){let{providerId:t,config:n,code:r}=e,s=typeof r==="string"?r.trim():"";if(!s)return h(new A(q.INVALID_REQUEST,"code is required",{providerId:t}));let a={pageNum:"1",pageSize:"15",templateCode:s},p=`${n.baseUrl}/api/template/`;try{let o=await fetch(p,{method:"POST",headers:P(n),body:JSON.stringify(a)}),i=await de(o),c=L(i.code)??o.status,f=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV template get failed";if(!o.ok||c!==200)return h(new A(M(c),f,{providerId:t,originalCode:c}));let I=i.list,m=(Array.isArray(I)?I:[]).find(x);if(!m)return h(new A(q.TEMPLATE_NOT_FOUND,"Template not found",{providerId:t,templateCode:s}));let w=m.templateCode,u=typeof w==="string"?w:String(w??""),g=typeof m.templateName==="string"?m.templateName:"",S=typeof m.templateContent==="string"?m.templateContent:"",l=le(m.status),b=ee(m.createDate)??new Date;return ae({id:u,code:u,name:g,content:S,status:l,buttons:Array.isArray(m.buttons)?m.buttons:void 0,createdAt:b,updatedAt:b})}catch(o){return h(new A(q.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function $e(e){let{providerId:t,config:n,query:r}=e,s=typeof r?.page==="number"&&r.page>0?Math.floor(r.page):1,a=typeof r?.limit==="number"&&r.limit>0?Math.floor(r.limit):15,p=Re(r?.status),o={pageNum:String(s),pageSize:String(a),...p?{templateStatus:p}:{}},i=`${n.baseUrl}/api/template/`;try{let c=await fetch(i,{method:"POST",headers:P(n),body:JSON.stringify(o)}),f=await de(c),I=L(f.code)??c.status,d=typeof f.message==="string"&&f.message.length>0?f.message:"IWINV template list failed";if(!c.ok||I!==200)return h(new A(M(I),d,{providerId:t,originalCode:I}));let m=f.list,u=(Array.isArray(m)?m:[]).filter(x).map((g)=>{let S=g.templateCode,l=typeof S==="string"?S:String(S??""),b=typeof g.templateName==="string"?g.templateName:"",T=typeof g.templateContent==="string"?g.templateContent:"",y=le(g.status),D=ee(g.createDate)??new Date;return{id:l,code:l,name:b,content:T,status:y,buttons:Array.isArray(g.buttons)?g.buttons:void 0,createdAt:D,updatedAt:D}}).filter((g)=>g.code.length>0);return ae(u)}catch(c){return h(new A(q.NETWORK_ERROR,c instanceof Error?c.message:String(c),{providerId:t}))}}class re{id="iwinv";name="IWINV Messaging Provider";supportedTypes;config;getOnboardingSpec(){let e=ve(this.id);if(!e)throw new k(_.INVALID_REQUEST,`Onboarding spec missing for provider: ${this.id}`,{providerId:this.id});return e}constructor(e){if(!e||typeof e!=="object")throw new k(_.INVALID_REQUEST,"IWINVProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new k(_.INVALID_REQUEST,"IWINVProvider requires `apiKey` configuration",{providerId:this.id});this.config={...e,baseUrl:he,sendEndpoint:e.sendEndpoint||"/api/v2/send/"};let t=["ALIMTALK"];if(Z(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(Z(this.config))try{new URL(Q())}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:Q()}}}catch(n){return t.push(n instanceof Error?n.message:String(n)),{healthy:!1,issues:t,latencyMs:Date.now()-e}}}async send(e){let t=e.messageId||crypto.randomUUID(),n={...e,messageId:t};switch(n.type){case"ALIMTALK":return Le({providerId:this.id,config:this.config,options:n});case"SMS":case"LMS":case"MMS":return Ue({providerId:this.id,config:this.config,options:n});default:return W(new k(_.INVALID_REQUEST,`IWINVProvider does not support type ${n.type}`,{providerId:this.id,type:n.type}))}}async getDeliveryStatus(e){switch(e.type){case"ALIMTALK":return Ce({providerId:this.id,config:this.config,query:e});case"SMS":case"LMS":case"MMS":return Oe({providerId:this.id,config:this.config,query:e});default:return W(new k(_.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 W(new k(_.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:P(this.config),body:JSON.stringify({})}),r=await n.text(),s=V(r),a=Y(s,{}),p=a.code,o=typeof p==="string"?Number(p):void 0,i=typeof p==="number"?p:typeof o==="number"&&Number.isFinite(o)?o:void 0,c=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV AlimTalk charge query failed";if(!n.ok||i!==200)return W(new k(M(i??n.status),c,{providerId:this.id,originalCode:p??n.status}));let f=a.charge,I=typeof f==="number"?f:typeof f==="string"?Number(f):NaN;if(!Number.isFinite(I))return W(new k(_.PROVIDER_ERROR,"Invalid charge value from IWINV AlimTalk charge API",{providerId:this.id,raw:a}));return Be({providerId:this.id,channel:e,amount:I,currency:"KRW",raw:a})}catch(n){return W(new k(_.NETWORK_ERROR,n instanceof Error?n.message:String(n),{providerId:this.id}))}}async getSmsBalance(e){if(!this.config.smsApiKey||!this.config.smsAuthKey)return W(new k(_.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:G(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=`${Q()}/api/charge/`;try{let a=await fetch(s,{method:"POST",headers:r,body:JSON.stringify({version:"1.0"})}),p=await a.text(),o=V(p),i=Y(o,{}),c=i.code??i.resultCode,f=typeof c==="string"?Number(c):void 0,I=typeof c==="number"?c:typeof f==="number"&&Number.isFinite(f)?f:NaN,d=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV SMS charge query failed";if(!a.ok||I!==0)return W(new k(_.PROVIDER_ERROR,d,{providerId:this.id,originalCode:c??a.status}));let m=i.charge,w=typeof m==="number"?m:typeof m==="string"?Number(m):NaN;if(!Number.isFinite(w))return W(new k(_.PROVIDER_ERROR,"Invalid charge value from IWINV SMS charge API",{providerId:this.id,raw:i}));return Be({providerId:this.id,channel:e,amount:w,currency:"KRW",raw:i})}catch(a){return W(new k(_.NETWORK_ERROR,a instanceof Error?a.message:String(a),{providerId:this.id}))}}async createTemplate(e,t){return ze({providerId:this.id,config:this.config,input:e})}async updateTemplate(e,t,n){return He({providerId:this.id,config:this.config,code:e,patch:t,ctx:n})}async deleteTemplate(e,t){return We({providerId:this.id,config:this.config,code:e})}async getTemplate(e,t){return pe({providerId:this.id,config:this.config,code:e,ctx:t})}async listTemplates(e,t){return $e({providerId:this.id,config:this.config,query:e,ctx:t})}}var $t=(e)=>new re(e),Ye=()=>{let e={apiKey:$("IWINV_API_KEY")||"",smsApiKey:$("IWINV_SMS_API_KEY"),smsAuthKey:$("IWINV_SMS_AUTH_KEY"),smsCompanyId:$("IWINV_SMS_COMPANY_ID"),senderNumber:$("IWINV_SENDER_NUMBER")||$("IWINV_SMS_SENDER_NUMBER"),smsSenderNumber:$("IWINV_SMS_SENDER_NUMBER"),sendEndpoint:$("IWINV_SEND_ENDPOINT")||"/api/v2/send/",xForwardedFor:$("IWINV_X_FORWARDED_FOR"),debug:$("NODE_ENV")==="development"};if(!e.apiKey)throw new k(_.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new re(e)};class Je{static create(e){return new re(e)}static createDefault(){return Ye()}}function Bt(){}var jt={SUCCESS:200,AUTH_FAILED:201,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500};export{re as default,jt as IWINV_STATUS_CODES,re as IWINVProvider};
1
+ import{fail as h,KMsgError as A,KMsgErrorCode as U,ok as ae}from"@k-msg/core";import{validateTemplatePayload as ve}from"@k-msg/template/send";function x(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function M(e){if(!e)return{};try{return JSON.parse(e)}catch{return e}}function Y(e,t){return x(e)?e:t}import{KMsgErrorCode as J}from"@k-msg/core";function Ye(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 oe(e){return Ye(new TextEncoder().encode(e))}function Re(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function P(e){let n={AUTH:oe(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 V(e){switch(e){case 201:case 206:case 401:case 403:return J.AUTHENTICATION_FAILED;case 429:return J.RATE_LIMIT_EXCEEDED;case 519:return J.INSUFFICIENT_BALANCE;case 404:case 501:return J.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 J.INVALID_REQUEST;case 518:return J.PROVIDER_ERROR;default:if(e>=500)return J.PROVIDER_ERROR;return J.INVALID_REQUEST}}function L(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 he(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 ue(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}function me(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function fe(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function Z(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]),o=Number(n[5]),i=Number(n[6]);if(!Number.isFinite(r)||!Number.isFinite(s)||!Number.isFinite(a)||!Number.isFinite(p)||!Number.isFinite(o)||!Number.isFinite(i))return;let c=new Date(r,s-1,a,p,o,i);if(Number.isNaN(c.getTime()))return;return c}function ie(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 ge(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 de(e){let t=await e.text(),n=M(t);return Y(n,{code:L(n)??e.status,message:t||String(n||"")})}function Ae(e,t){return new A(e.code,e.message,{providerId:t,...e.details??{}})}async function De(e){let{providerId:t,config:n,input:r}=e;if(!r||typeof r!=="object")return h(new A(U.INVALID_REQUEST,"Template input is required",{providerId:t}));let s=ve(r,{requireName:!0,requireContent:!0});if(s.isFailure)return h(Ae(s.error,t));let a=`${n.baseUrl}/api/template/add/`,p={templateName:s.value.name??r.name,templateContent:s.value.content??r.content,...s.value.buttons?{buttons:s.value.buttons}:{}};try{let o=await fetch(a,{method:"POST",headers:P(n),body:JSON.stringify(p)}),i=await de(o),c=L(i.code)??o.status,f=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV template create failed";if(!o.ok||c!==200)return h(new A(V(c),f,{providerId:t,originalCode:c}));let I=i.templateCode,d=typeof I==="string"&&I.trim().length>0?I.trim():"";if(!d)return h(new A(U.PROVIDER_ERROR,"IWINV template create did not return templateCode",{providerId:t,raw:i}));let m=new Date;return ae({id:d,code:d,name:s.value.name??r.name,content:s.value.content??r.content,category:r.category,status:"INSPECTION",buttons:s.value.buttons,variables:r.variables,createdAt:m,updatedAt:m})}catch(o){return h(new A(U.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function Ce(e){let{providerId:t,config:n,code:r,patch:s,ctx:a}=e,p=typeof r==="string"?r.trim():"";if(!p)return h(new A(U.INVALID_REQUEST,"code is required",{providerId:t}));let o=await ce({providerId:t,config:n,code:p,ctx:a});if(o.isFailure)return o;let i=o.value,c=typeof s.name==="string"&&s.name.trim().length>0?s.name.trim():i.name,f=typeof s.content==="string"&&s.content.trim().length>0?s.content:i.content,I=s.buttons!==void 0?s.buttons:i.buttons,d=ve({name:c,content:f,buttons:I},{requireName:!0,requireContent:!0});if(d.isFailure)return h(Ae(d.error,t));let m=`${n.baseUrl}/api/template/modify/`,T={templateCode:p,templateName:d.value.name??c,templateContent:d.value.content??f,...d.value.buttons?{buttons:d.value.buttons}:{}};try{let u=await fetch(m,{method:"POST",headers:P(n),body:JSON.stringify(T)}),g=await de(u),S=L(g.code)??u.status,l=typeof g.message==="string"&&g.message.length>0?g.message:"IWINV template update failed";if(!u.ok||S!==200)return h(new A(V(S),l,{providerId:t,originalCode:S}));let b=await ce({providerId:t,config:n,code:p,ctx:a});if(b.isSuccess)return b;return ae({...i,name:d.value.name??c,content:d.value.content??f,...s.category!==void 0?{category:s.category}:{},...s.variables!==void 0?{variables:s.variables}:{},...s.buttons!==void 0?{buttons:d.value.buttons}:{},updatedAt:new Date})}catch(u){return h(new A(U.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}async function Oe(e){let{providerId:t,config:n,code:r}=e,s=typeof r==="string"?r.trim():"";if(!s)return h(new A(U.INVALID_REQUEST,"code is required",{providerId:t}));let a=`${n.baseUrl}/api/template/delete/`,p={templateCode:s};try{let o=await fetch(a,{method:"POST",headers:P(n),body:JSON.stringify(p)}),i=await de(o),c=L(i.code)??o.status,f=typeof i.message==="string"&&i.message.length>0?i.message:typeof i.messgae==="string"&&i.messgae.length>0?i.messgae:"IWINV template delete failed";if(!o.ok||c!==200)return h(new A(V(c),f,{providerId:t,originalCode:c}));return ae(void 0)}catch(o){return h(new A(U.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function ce(e){let{providerId:t,config:n,code:r}=e,s=typeof r==="string"?r.trim():"";if(!s)return h(new A(U.INVALID_REQUEST,"code is required",{providerId:t}));let a={pageNum:"1",pageSize:"15",templateCode:s},p=`${n.baseUrl}/api/template/`;try{let o=await fetch(p,{method:"POST",headers:P(n),body:JSON.stringify(a)}),i=await de(o),c=L(i.code)??o.status,f=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV template get failed";if(!o.ok||c!==200)return h(new A(V(c),f,{providerId:t,originalCode:c}));let I=i.list,m=(Array.isArray(I)?I:[]).find(x);if(!m)return h(new A(U.TEMPLATE_NOT_FOUND,"Template not found",{providerId:t,templateCode:s}));let T=m.templateCode,u=typeof T==="string"?T:String(T??""),g=typeof m.templateName==="string"?m.templateName:"",S=typeof m.templateContent==="string"?m.templateContent:"",l=ue(m.status),b=Z(m.createDate)??new Date;return ae({id:u,code:u,name:g,content:S,status:l,buttons:Array.isArray(m.buttons)?m.buttons:void 0,createdAt:b,updatedAt:b})}catch(o){return h(new A(U.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function xe(e){let{providerId:t,config:n,query:r}=e,s=typeof r?.page==="number"&&r.page>0?Math.floor(r.page):1,a=typeof r?.limit==="number"&&r.limit>0?Math.floor(r.limit):15,p=he(r?.status),o={pageNum:String(s),pageSize:String(a),...p?{templateStatus:p}:{}},i=`${n.baseUrl}/api/template/`;try{let c=await fetch(i,{method:"POST",headers:P(n),body:JSON.stringify(o)}),f=await de(c),I=L(f.code)??c.status,d=typeof f.message==="string"&&f.message.length>0?f.message:"IWINV template list failed";if(!c.ok||I!==200)return h(new A(V(I),d,{providerId:t,originalCode:I}));let m=f.list,u=(Array.isArray(m)?m:[]).filter(x).map((g)=>{let S=g.templateCode,l=typeof S==="string"?S:String(S??""),b=typeof g.templateName==="string"?g.templateName:"",w=typeof g.templateContent==="string"?g.templateContent:"",y=ue(g.status),D=Z(g.createDate)??new Date;return{id:l,code:l,name:b,content:w,status:y,buttons:Array.isArray(g.buttons)?g.buttons:void 0,createdAt:D,updatedAt:D}}).filter((g)=>g.code.length>0);return ae(u)}catch(c){return h(new A(U.NETWORK_ERROR,c instanceof Error?c.message:String(c),{providerId:t}))}}import{fail as $,KMsgError as _,KMsgErrorCode as k,ok as je,readRuntimeEnv as B}from"@k-msg/core";var _e={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 ke(e){return _e[e]}function It(){return Object.values(_e)}var Me="https://alimtalk.bizservice.iwinv.kr",Pe="https://sms.bizservice.iwinv.kr";import{fail as K,KMsgError as q,KMsgErrorCode as H,ok as ne}from"@k-msg/core";import{KMsgErrorCode as pe}from"@k-msg/core";function Q(e){return e.replace(/[^0-9]/g,"")}function W(){return Pe}function G(e){if(e.smsApiKey&&e.smsAuthKey)return oe(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return oe(`${e.apiKey}&${t}`)}function ee(e){return G(e).length>0}function ye(e){if(typeof e==="number"&&Number.isFinite(e))return e.toString();if(typeof e==="string")return e.trim();return""}function Ie(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 be(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return pe.AUTHENTICATION_FAILED;if(e==="50")return pe.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 pe.INVALID_REQUEST;if(!t)return pe.NETWORK_ERROR;return pe.PROVIDER_ERROR}function Se(e,t){if(t&&t.trim().length>0)return t.trim();return e.slice(0,20)}function Ve(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"}async function Fe(e){let{providerId:t,config:n,query:r}=e,s=r.providerMessageId.trim();if(!s)return K(new q(H.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let a=Q(r.to);if(!a)return K(new q(H.INVALID_REQUEST,"to is required",{providerId:t}));let p=Number(s),o=Number.isFinite(p)?p:void 0,i=ie(me(r.requestedAt,-1)),c=ie(new Date),f={pageNum:1,pageSize:15,phone:a,startDate:i,endDate:c,...o!==void 0?{seqNo:o}:{},...r.scheduledAt instanceof Date&&!Number.isNaN(r.scheduledAt.getTime())?{reserve:"Y"}:{}},I=`${n.baseUrl}/api/history/`;try{let d=await fetch(I,{method:"POST",headers:P(n),body:JSON.stringify(f)}),m=await d.text(),T=M(m),u=Y(T,{}),g=u.code,S=typeof g==="number"?g:void 0,l=typeof u.message==="string"&&u.message.length>0?u.message:"IWINV history query failed";if(!d.ok||S!==200)return K(new q(V(S??L(T)??d.status),l,{providerId:t,originalCode:g??d.status}));let b=u.list,w=Array.isArray(b)?b:[];if(w.length===0)return ne(null);let y=(()=>{if(o===void 0)return w[0];return w.find((N)=>x(N)&&N.seqNo===o)??w[0]})();if(!x(y))return ne(null);let D=typeof y.statusCode==="string"?y.statusCode:void 0,C=typeof y.statusCodeName==="string"?y.statusCodeName:void 0,E=Z(y.sendDate),j=Z(y.receiveDate),z=D==="OK"||typeof C==="string"&&C.includes("성공");return ne({providerId:t,providerMessageId:s,status:z?"DELIVERED":E?"FAILED":"PENDING",statusCode:D,statusMessage:C,sentAt:E,deliveredAt:z?j||E:void 0,failedAt:!z&&E?E:void 0,raw:y})}catch(d){return K(new q(H.NETWORK_ERROR,d instanceof Error?d.message:String(d),{providerId:t}))}}async function Le(e){let{providerId:t,config:n,query:r}=e;if(!ee(n))return K(new q(H.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));if(!n.smsCompanyId||n.smsCompanyId.length===0)return K(new q(H.INVALID_REQUEST,"smsCompanyId required for history (config.smsCompanyId)",{providerId:t}));let s=r.providerMessageId.trim();if(!s)return K(new q(H.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let a=Q(r.to);if(!a)return K(new q(H.INVALID_REQUEST,"to is required",{providerId:t}));let p=me(r.requestedAt,-1),o=new Date;if(o.getTime()-p.getTime()>7776000000)return K(new q(H.INVALID_REQUEST,"SMS history date range must be within 90 days",{providerId:t}));let f={version:"1.0",companyid:n.smsCompanyId,startDate:fe(p),endDate:fe(o),requestNo:s,pageNum:1,pageSize:15,phone:a},d={"Content-Type":"application/json;charset=UTF-8",secret:G(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)d["X-Forwarded-For"]=n.xForwardedFor;let m=n.extraHeaders&&typeof n.extraHeaders==="object"?{...d,...n.extraHeaders}:d,T=`${W()}/api/history/`;try{let u=await fetch(T,{method:"POST",headers:m,body:JSON.stringify(f)}),g=await u.text(),S=M(g),l=Y(S,{}),b=l.resultCode,w=typeof b==="number"?b:typeof b==="string"?Number(b):NaN,y=typeof l.message==="string"&&l.message.length>0?l.message:"IWINV SMS history query failed";if(!u.ok||w!==0)return K(new q(H.PROVIDER_ERROR,y,{providerId:t,originalCode:b??u.status}));let D=l.list,C=Array.isArray(D)?D:[];if(C.length===0)return ne(null);let E=(()=>{return C.find((X)=>{if(!x(X))return!1;let F=X.requestNo;return F!==void 0&&F!==null?String(F)===s:!1})??C[0]})();if(!x(E))return ne(null);let j=typeof E.sendStatusCode==="string"?E.sendStatusCode:void 0,z=typeof E.sendStatusMsg==="string"?E.sendStatusMsg:typeof E.sendStatus==="string"?E.sendStatus:void 0,te=Z(E.sendDate),N=Ve(j,z);return ne({providerId:t,providerMessageId:s,status:N,statusCode:j,statusMessage:z,sentAt:te,deliveredAt:N==="DELIVERED"?te:void 0,failedAt:N==="FAILED"?te:void 0,raw:E})}catch(u){return K(new q(H.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}import{fail as v,KMsgError as R,KMsgErrorCode as O,ok as we}from"@k-msg/core";import{fail as Ue,KMsgError as Ke,KMsgErrorCode as qe,ok as Ne}from"@k-msg/core";function ze(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 Te(e){switch(ze(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 He(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 Ne({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 Ne({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 Ue(new Ke(qe.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 Ue(new Ke(qe.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"imageUrl"}));return Ne(void 0)}async function $e(e){if("blob"in e){let a=e.contentType||e.blob.type||"application/octet-stream",p=e.filename||"image",o=e.contentType&&e.contentType!==e.blob.type?new Blob([await e.blob.arrayBuffer()],{type:a}):e.blob;return{blob:o,filename:p,contentType:a,size:o.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 Be(e){if(ze(e.filename).length>0)return e.filename;let n=Te(e.filename)==="image/png"?".png":Te(e.filename)==="image/gif"?".gif":Te(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 Qe(e){let{providerId:t,config:n,options:r}=e,s=r.templateId;if(!s||s.length===0)return v(new R(O.INVALID_REQUEST,"templateId is required for ALIMTALK",{providerId:t}));let a=r.options?.scheduledAt,p=a instanceof Date&&!Number.isNaN(a.getTime()),o=p?"Y":"N",i=p?ie(a):void 0,c=Q(r.to);if(!c)return v(new R(O.INVALID_REQUEST,"to is required",{providerId:t}));let f=r.providerOptions?.templateParam,I=Array.isArray(f)?f.map((N)=>N===null||N===void 0?"":String(N)):Object.values(r.variables||{}).map((N)=>N===null||N===void 0?"":String(N)),d=r.failover,m=(typeof r.from==="string"&&r.from.length>0?r.from:n.senderNumber||n.smsSenderNumber)||"",T=m?Q(m):"",u=typeof r.providerOptions?.reSend==="string"?r.providerOptions.reSend.trim().toUpperCase():"",g=u==="Y"||u==="N"?u:void 0,S=d?.enabled===!0?"Y":d?.enabled===!1?"N":void 0,l=g??S??(T?"Y":"N"),w=(typeof r.providerOptions?.resendCallback==="string"?Q(r.providerOptions.resendCallback):"")||T;if(l==="Y"&&!w)return v(new R(O.INVALID_REQUEST,"resendCallback is required when reSend is 'Y' (options.from or providerOptions.resendCallback)",{providerId:t}));let y=typeof r.providerOptions?.resendType==="string"?r.providerOptions.resendType.trim().toUpperCase():"",D=y==="Y"||y==="N"?y:void 0;if(typeof r.providerOptions?.resendType==="string"&&r.providerOptions.resendType.length>0&&!D)return v(new R(O.INVALID_REQUEST,"resendType must be 'Y' or 'N'",{providerId:t}));let C=d?.fallbackChannel==="lms"?"Y":d?.fallbackChannel==="sms"?"N":void 0,E=typeof r.providerOptions?.resendTitle==="string"&&r.providerOptions.resendTitle.trim().length>0?r.providerOptions.resendTitle.trim():typeof d?.fallbackTitle==="string"&&d.fallbackTitle.trim().length>0?d.fallbackTitle.trim():void 0,j=typeof r.providerOptions?.resendContent==="string"&&r.providerOptions.resendContent.trim().length>0?r.providerOptions.resendContent.trim():typeof d?.fallbackContent==="string"&&d.fallbackContent.trim().length>0?d.fallbackContent.trim():void 0,z={templateCode:s,reserve:o,...i?{sendDate:i}:{},list:[{phone:c,templateParam:I.length>0?I:void 0}],reSend:l,...w?{resendCallback:w}:{},...D??C?{resendType:D??C}:{},...E?{resendTitle:E}:{},...j?{resendContent:j}:{}},te=`${n.baseUrl}${Re(n)}`;try{let N=await fetch(te,{method:"POST",headers:P(n),body:JSON.stringify(z)}),le=await N.text(),X=M(le),F=x(X)?X:{code:L(X)??N.status,message:le||String(X||"")};if(!N.ok||F.code!==200)return v(new R(V(F.code),F.message||"IWINV send failed",{providerId:t,originalCode:F.code}));return we({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:typeof F.seqNo==="number"?String(F.seqNo):void 0,status:p?"PENDING":"SENT",type:r.type,to:r.to,raw:F})}catch(N){return v(new R(O.NETWORK_ERROR,N instanceof Error?N.message:String(N),{providerId:t}))}}async function Je(e){let{providerId:t,config:n,options:r,to:s,from:a,text:p,scheduledAtValid:o,scheduledAt:i}=e;if(r.type!=="MMS")return v(new R(O.INVALID_REQUEST,"IWINVProvider: MMS handler called with non-MMS options",{providerId:t,type:r.type}));let c=Se(p,r.subject),f=He(r,t);if(f.isFailure)return f;let I=f.value;if(!I)return v(new R(O.INVALID_REQUEST,"image is required for MMS; caller must provide options.media.image.blob or bytes",{providerId:t}));let d;try{d=await $e(I)}catch(l){return v(l instanceof R?l:new R(O.NETWORK_ERROR,l instanceof Error?l.message:String(l),{providerId:t}))}if(d.size>102400)return v(new R(O.INVALID_REQUEST,"MMS image must be <= 100KB",{providerId:t,bytes:d.size}));let m=new FormData;if(m.append("version","1.0"),m.append("from",a),m.append("to",s),m.append("title",c),m.append("text",p),o&&i)m.append("date",ge(i));m.append("image",d.blob,Be(d));let u={secret:G(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)u["X-Forwarded-For"]=n.xForwardedFor;let g={...u};if(n.extraHeaders&&typeof n.extraHeaders==="object")for(let[l,b]of Object.entries(n.extraHeaders)){if(l.toLowerCase()==="content-type")continue;g[l]=b}let S=`${W()}/api/v2/send/`;try{let l=await fetch(S,{method:"POST",headers:g,body:m}),b=await l.text(),w=M(b),y=x(w)?w:{resultCode:w},D=y.resultCode??y.code,C=ye(D),E=typeof y.message==="string"&&y.message.length>0?y.message:Ie(C,"MMS send failed");if(!(l.ok&&C==="0"))return v(new R(be(C,l.ok),E,{providerId:t,originalCode:D}));let z=typeof y.requestNo==="string"&&y.requestNo.length>0?y.requestNo:typeof y.msgid==="string"&&y.msgid.length>0?y.msgid:void 0;return we({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:z,status:o?"PENDING":"SENT",type:r.type,to:r.to,raw:y})}catch(l){return v(new R(O.NETWORK_ERROR,l instanceof Error?l.message:String(l),{providerId:t}))}}async function We(e){let{providerId:t,config:n,options:r}=e;if(!ee(n))return v(new R(O.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));let s=Q(r.to);if(!s)return v(new R(O.INVALID_REQUEST,"to is required",{providerId:t}));let a=r.text;if(!a||a.trim().length===0)return v(new R(O.INVALID_REQUEST,"text is required for SMS/LMS/MMS",{providerId:t}));let p=(typeof r.from==="string"&&r.from.length>0?r.from:n.smsSenderNumber||n.senderNumber)||"",o=p?Q(p):"";if(!o)return v(new R(O.INVALID_REQUEST,"from is required for SMS/LMS/MMS (options.from or config.smsSenderNumber)",{providerId:t}));let i=r.options?.scheduledAt,c=i instanceof Date&&!Number.isNaN(i.getTime());if(r.type==="MMS")return await Je({providerId:t,config:n,options:r,to:s,from:o,text:a,scheduledAtValid:c,scheduledAt:c?i:void 0});let f={version:"1.0",from:o,to:[s],text:a};if(r.type==="LMS")f.title=Se(a,r.subject);else{let u=typeof r.providerOptions?.msgType==="string"&&r.providerOptions.msgType.trim().length>0?r.providerOptions.msgType.trim():void 0;f.msgType=u||r.type}if(c)f.date=ge(i);let d={"Content-Type":"application/json;charset=UTF-8",secret:G(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)d["X-Forwarded-For"]=n.xForwardedFor;let m=n.extraHeaders&&typeof n.extraHeaders==="object"?{...d,...n.extraHeaders}:d,T=`${W()}/api/v2/send/`;try{let u=await fetch(T,{method:"POST",headers:m,body:JSON.stringify(f)}),g=await u.text(),S=M(g),l=x(S)?S:{resultCode:S},b=l.resultCode??l.code,w=ye(b),y=typeof l.message==="string"&&l.message.length>0?l.message:Ie(w,"SMS send failed");if(!(u.ok&&w==="0"))return v(new R(be(w,u.ok),y,{providerId:t,originalCode:b}));let C=typeof l.requestNo==="string"&&l.requestNo.length>0?l.requestNo:typeof l.msgid==="string"&&l.msgid.length>0?l.msgid:void 0;return we({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:C,status:c?"PENDING":"SENT",type:r.type,to:r.to,raw:l})}catch(u){return v(new R(O.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}function Ge(e){return{...e,baseUrl:Me,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}function Ee(){return{apiKey:B("IWINV_API_KEY")||"",smsApiKey:B("IWINV_SMS_API_KEY"),smsAuthKey:B("IWINV_SMS_AUTH_KEY"),smsCompanyId:B("IWINV_SMS_COMPANY_ID"),senderNumber:B("IWINV_SENDER_NUMBER")||B("IWINV_SMS_SENDER_NUMBER"),smsSenderNumber:B("IWINV_SMS_SENDER_NUMBER"),sendEndpoint:B("IWINV_SEND_ENDPOINT")||"/api/v2/send/",xForwardedFor:B("IWINV_X_FORWARDED_FOR"),debug:B("NODE_ENV")==="development"}}class re{id="iwinv";name="IWINV Messaging Provider";supportedTypes;config;getOnboardingSpec(){let e=ke(this.id);if(!e)throw new _(k.INVALID_REQUEST,`Onboarding spec missing for provider: ${this.id}`,{providerId:this.id});return e}constructor(e){if(!e||typeof e!=="object")throw new _(k.INVALID_REQUEST,"IWINVProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new _(k.INVALID_REQUEST,"IWINVProvider requires `apiKey` configuration",{providerId:this.id});this.config=Ge(e);let t=["ALIMTALK"];if(ee(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(ee(this.config))try{new URL(W())}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:W()}}}catch(n){return t.push(n instanceof Error?n.message:String(n)),{healthy:!1,issues:t,latencyMs:Date.now()-e}}}async send(e){let t=e.messageId||crypto.randomUUID(),n={...e,messageId:t};switch(n.type){case"ALIMTALK":return Qe({providerId:this.id,config:this.config,options:n});case"SMS":case"LMS":case"MMS":return We({providerId:this.id,config:this.config,options:n});default:return $(new _(k.INVALID_REQUEST,`IWINVProvider does not support type ${n.type}`,{providerId:this.id,type:n.type}))}}async getDeliveryStatus(e){switch(e.type){case"ALIMTALK":return Fe({providerId:this.id,config:this.config,query:e});case"SMS":case"LMS":case"MMS":return Le({providerId:this.id,config:this.config,query:e});default:return $(new _(k.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 $(new _(k.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:P(this.config),body:JSON.stringify({})}),r=await n.text(),s=M(r),a=Y(s,{}),p=a.code,o=typeof p==="string"?Number(p):void 0,i=typeof p==="number"?p:typeof o==="number"&&Number.isFinite(o)?o:void 0,c=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV AlimTalk charge query failed";if(!n.ok||i!==200)return $(new _(V(i??n.status),c,{providerId:this.id,originalCode:p??n.status}));let f=a.charge,I=typeof f==="number"?f:typeof f==="string"?Number(f):NaN;if(!Number.isFinite(I))return $(new _(k.PROVIDER_ERROR,"Invalid charge value from IWINV AlimTalk charge API",{providerId:this.id,raw:a}));return je({providerId:this.id,channel:e,amount:I,currency:"KRW",raw:a})}catch(n){return $(new _(k.NETWORK_ERROR,n instanceof Error?n.message:String(n),{providerId:this.id}))}}async getSmsBalance(e){if(!this.config.smsApiKey||!this.config.smsAuthKey)return $(new _(k.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:G(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=`${W()}/api/charge/`;try{let a=await fetch(s,{method:"POST",headers:r,body:JSON.stringify({version:"1.0"})}),p=await a.text(),o=M(p),i=Y(o,{}),c=i.code??i.resultCode,f=typeof c==="string"?Number(c):void 0,I=typeof c==="number"?c:typeof f==="number"&&Number.isFinite(f)?f:NaN,d=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV SMS charge query failed";if(!a.ok||I!==0)return $(new _(k.PROVIDER_ERROR,d,{providerId:this.id,originalCode:c??a.status}));let m=i.charge,T=typeof m==="number"?m:typeof m==="string"?Number(m):NaN;if(!Number.isFinite(T))return $(new _(k.PROVIDER_ERROR,"Invalid charge value from IWINV SMS charge API",{providerId:this.id,raw:i}));return je({providerId:this.id,channel:e,amount:T,currency:"KRW",raw:i})}catch(a){return $(new _(k.NETWORK_ERROR,a instanceof Error?a.message:String(a),{providerId:this.id}))}}}var Yt=(e)=>new re(e),Xe=()=>{let e=Ee();if(!e.apiKey)throw new _(k.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new re(e)};class Ze{static create(e){return new re(e)}static createDefault(){return Xe()}}class se extends re{async createTemplate(e,t){return De({providerId:this.id,config:this.config,input:e})}async updateTemplate(e,t,n){return Ce({providerId:this.id,config:this.config,code:e,patch:t,ctx:n})}async deleteTemplate(e,t){return Oe({providerId:this.id,config:this.config,code:e})}async getTemplate(e,t){return ce({providerId:this.id,config:this.config,code:e,ctx:t})}async listTemplates(e,t){return xe({providerId:this.id,config:this.config,query:e,ctx:t})}}var Zt=(e)=>new se(e),et=()=>{let e=Ee();return new se(e)};class tt{static create(e){return new se(e)}static createDefault(){return et()}}function en(){}var nn={SUCCESS:200,AUTH_FAILED:201,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500};export{se as default,nn as IWINV_STATUS_CODES,se as IWINVProvider};
2
2
 
3
- //# debugId=8130AFA80FD809DC64756E2164756E21
3
+ //# debugId=7718AD18800CF29264756E2164756E21
4
4
  //# sourceMappingURL=index.mjs.map
@@ -1,18 +1,7 @@
1
- import { type BalanceProvider, type BalanceQuery, type BalanceResult, type DeliveryStatusQuery, type DeliveryStatusResult, KMsgError, type MessageType, type Provider, type ProviderHealthStatus, type Result, type SendOptions, type SendResult, type Template, type TemplateContext, type TemplateCreateInput, type TemplateProvider, type TemplateUpdateInput } from "@k-msg/core";
1
+ import type { KMsgError, Result, Template, TemplateContext, TemplateCreateInput, TemplateProvider, TemplateUpdateInput } from "@k-msg/core";
2
+ import { IWINVSendProvider } from "./provider.send";
2
3
  import type { IWINVConfig } from "./types/iwinv";
3
- export declare class IWINVProvider implements Provider, BalanceProvider, TemplateProvider {
4
- readonly id = "iwinv";
5
- readonly name = "IWINV Messaging Provider";
6
- readonly supportedTypes: readonly MessageType[];
7
- private readonly config;
8
- getOnboardingSpec(): import("@k-msg/core").ProviderOnboardingSpec;
9
- constructor(config: IWINVConfig);
10
- healthCheck(): Promise<ProviderHealthStatus>;
11
- send(options: SendOptions): Promise<Result<SendResult, KMsgError>>;
12
- getDeliveryStatus(query: DeliveryStatusQuery): Promise<Result<DeliveryStatusResult | null, KMsgError>>;
13
- getBalance(query?: BalanceQuery): Promise<Result<BalanceResult, KMsgError>>;
14
- private getAlimTalkBalance;
15
- private getSmsBalance;
4
+ export declare class IWINVProvider extends IWINVSendProvider implements TemplateProvider {
16
5
  createTemplate(input: TemplateCreateInput, _ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
17
6
  updateTemplate(code: string, patch: TemplateUpdateInput, ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
18
7
  deleteTemplate(code: string, _ctx?: TemplateContext): Promise<Result<void, KMsgError>>;
@@ -0,0 +1,24 @@
1
+ import { type BalanceProvider, type BalanceQuery, type BalanceResult, type DeliveryStatusQuery, type DeliveryStatusResult, KMsgError, type MessageType, type Provider, type ProviderHealthStatus, type Result, type SendOptions, type SendResult } from "@k-msg/core";
2
+ import type { NormalizedIwinvConfig } from "./iwinv.internal.types";
3
+ import type { IWINVConfig } from "./types/iwinv";
4
+ export declare function resolveDefaultIWINVConfig(): IWINVConfig;
5
+ export declare class IWINVSendProvider implements Provider, BalanceProvider {
6
+ readonly id = "iwinv";
7
+ readonly name = "IWINV Messaging Provider";
8
+ readonly supportedTypes: readonly MessageType[];
9
+ protected readonly config: NormalizedIwinvConfig;
10
+ getOnboardingSpec(): import("@k-msg/core").ProviderOnboardingSpec;
11
+ constructor(config: IWINVConfig);
12
+ healthCheck(): Promise<ProviderHealthStatus>;
13
+ send(options: SendOptions): Promise<Result<SendResult, KMsgError>>;
14
+ getDeliveryStatus(query: DeliveryStatusQuery): Promise<Result<DeliveryStatusResult | null, KMsgError>>;
15
+ getBalance(query?: BalanceQuery): Promise<Result<BalanceResult, KMsgError>>;
16
+ private getAlimTalkBalance;
17
+ private getSmsBalance;
18
+ }
19
+ export declare const createIWINVSendProvider: (config: IWINVConfig) => IWINVSendProvider;
20
+ export declare const createDefaultIWINVSendProvider: () => IWINVSendProvider;
21
+ export declare class IWINVSendProviderFactory {
22
+ static create(config: IWINVConfig): IWINVSendProvider;
23
+ static createDefault(): IWINVSendProvider;
24
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * IWINV send/status/balance focused entrypoint.
3
+ */
4
+ export { createDefaultIWINVSendProvider, createIWINVSendProvider, IWINVSendProvider as default, IWINVSendProvider, IWINVSendProviderFactory, } from "./provider.send";
5
+ export * from "./types/iwinv";
@@ -0,0 +1,4 @@
1
+ var{defineProperty:X,getOwnPropertyNames:ve,getOwnPropertyDescriptor:Ae}=Object,Re=Object.prototype.hasOwnProperty;var pe=new WeakMap,De=(e)=>{var t=pe.get(e),n;if(t)return t;if(t=X({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")ve(e).map((r)=>!Re.call(t,r)&&X(t,r,{get:()=>e[r],enumerable:!(n=Ae(e,r))||n.enumerable}));return pe.set(e,t),t};var Oe=(e,t)=>{for(var n in t)X(e,n,{get:t[n],enumerable:!0,configurable:!0,set:(r)=>t[n]=()=>r})};var Fe={};Oe(Fe,{default:()=>q,createIWINVSendProvider:()=>Ee,createDefaultIWINVSendProvider:()=>ae,IWINV_STATUS_CODES:()=>Ve,IWINVSendProviderFactory:()=>de,IWINVSendProvider:()=>q});module.exports=De(Fe);var i=require("@k-msg/core");var ce={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 le(e){return ce[e]}function Me(){return Object.values(ce)}function _(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function C(e){if(!e)return{};try{return JSON.parse(e)}catch{return e}}function B(e,t){return _(e)?e:t}var V=require("@k-msg/core");function xe(e){let t="",n=0;while(n<e.length){let r=e[n++]??0,o=e[n++]??0,a=e[n++]??0,l=r<<16|o<<8|a;t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l>>18&63],t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l>>12&63],t+=n-2<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l>>6&63]:"=",t+=n-1<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l&63]:"="}return t}function Q(e){return xe(new TextEncoder().encode(e))}function ue(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function K(e){let n={AUTH:Q(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 $(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 Y(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 Ke(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 $e(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}var me="https://alimtalk.bizservice.iwinv.kr",fe="https://sms.bizservice.iwinv.kr";var d=require("@k-msg/core");var W=require("@k-msg/core");function F(e){return e.replace(/[^0-9]/g,"")}function P(){return fe}function L(e){if(e.smsApiKey&&e.smsAuthKey)return Q(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return Q(`${e.apiKey}&${t}`)}function H(e){return L(e).length>0}function Z(e){if(typeof e==="number"&&Number.isFinite(e))return e.toString();if(typeof e==="string")return e.trim();return""}function ee(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 te(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return W.KMsgErrorCode.AUTHENTICATION_FAILED;if(e==="50")return W.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 W.KMsgErrorCode.INVALID_REQUEST;if(!t)return W.KMsgErrorCode.NETWORK_ERROR;return W.KMsgErrorCode.PROVIDER_ERROR}function ne(e,t){if(t&&t.trim().length>0)return t.trim();return e.slice(0,20)}function ge(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 re(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function se(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function G(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]),o=Number(n[2]),a=Number(n[3]),l=Number(n[4]),f=Number(n[5]),g=Number(n[6]);if(!Number.isFinite(r)||!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(l)||!Number.isFinite(f)||!Number.isFinite(g))return;let I=new Date(r,o-1,a,l,f,g);if(Number.isNaN(I.getTime()))return;return I}function j(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 ie(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 ye(e){let{providerId:t,config:n,query:r}=e,o=r.providerMessageId.trim();if(!o)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let a=F(r.to);if(!a)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let l=Number(o),f=Number.isFinite(l)?l:void 0,g=j(re(r.requestedAt,-1)),I=j(new Date),y={pageNum:1,pageSize:15,phone:a,startDate:g,endDate:I,...f!==void 0?{seqNo:f}:{},...r.scheduledAt instanceof Date&&!Number.isNaN(r.scheduledAt.getTime())?{reserve:"Y"}:{}},E=`${n.baseUrl}/api/history/`;try{let c=await fetch(E,{method:"POST",headers:K(n),body:JSON.stringify(y)}),S=await c.text(),v=C(S),u=B(v,{}),D=u.code,O=typeof D==="number"?D:void 0,p=typeof u.message==="string"&&u.message.length>0?u.message:"IWINV history query failed";if(!c.ok||O!==200)return d.fail(new d.KMsgError($(O??Y(v)??c.status),p,{providerId:t,originalCode:D??c.status}));let w=u.list,T=Array.isArray(w)?w:[];if(T.length===0)return d.ok(null);let m=(()=>{if(f===void 0)return T[0];return T.find((b)=>_(b)&&b.seqNo===f)??T[0]})();if(!_(m))return d.ok(null);let A=typeof m.statusCode==="string"?m.statusCode:void 0,h=typeof m.statusCodeName==="string"?m.statusCodeName:void 0,N=G(m.sendDate),M=G(m.receiveDate),k=A==="OK"||typeof h==="string"&&h.includes("성공");return d.ok({providerId:t,providerMessageId:o,status:k?"DELIVERED":N?"FAILED":"PENDING",statusCode:A,statusMessage:h,sentAt:N,deliveredAt:k?M||N:void 0,failedAt:!k&&N?N:void 0,raw:m})}catch(c){return d.fail(new d.KMsgError(d.KMsgErrorCode.NETWORK_ERROR,c instanceof Error?c.message:String(c),{providerId:t}))}}async function Ie(e){let{providerId:t,config:n,query:r}=e;if(!H(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 o=r.providerMessageId.trim();if(!o)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let a=F(r.to);if(!a)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let l=re(r.requestedAt,-1),f=new Date;if(f.getTime()-l.getTime()>7776000000)return d.fail(new d.KMsgError(d.KMsgErrorCode.INVALID_REQUEST,"SMS history date range must be within 90 days",{providerId:t}));let y={version:"1.0",companyid:n.smsCompanyId,startDate:se(l),endDate:se(f),requestNo:o,pageNum:1,pageSize:15,phone:a},c={"Content-Type":"application/json;charset=UTF-8",secret:L(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,v=`${P()}/api/history/`;try{let u=await fetch(v,{method:"POST",headers:S,body:JSON.stringify(y)}),D=await u.text(),O=C(D),p=B(O,{}),w=p.resultCode,T=typeof w==="number"?w:typeof w==="string"?Number(w):NaN,m=typeof p.message==="string"&&p.message.length>0?p.message:"IWINV SMS history query failed";if(!u.ok||T!==0)return d.fail(new d.KMsgError(d.KMsgErrorCode.PROVIDER_ERROR,m,{providerId:t,originalCode:w??u.status}));let A=p.list,h=Array.isArray(A)?A:[];if(h.length===0)return d.ok(null);let N=(()=>{return h.find((U)=>{if(!_(U))return!1;let x=U.requestNo;return x!==void 0&&x!==null?String(x)===o:!1})??h[0]})();if(!_(N))return d.ok(null);let M=typeof N.sendStatusCode==="string"?N.sendStatusCode:void 0,k=typeof N.sendStatusMsg==="string"?N.sendStatusMsg:typeof N.sendStatus==="string"?N.sendStatus:void 0,z=G(N.sendDate),b=ge(M,k);return d.ok({providerId:t,providerMessageId:o,status:b,statusCode:M,statusMessage:k,sentAt:z,deliveredAt:b==="DELIVERED"?z:void 0,failedAt:b==="FAILED"?z:void 0,raw:N})}catch(u){return d.fail(new d.KMsgError(d.KMsgErrorCode.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}var s=require("@k-msg/core");var R=require("@k-msg/core");function Se(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 oe(e){switch(Se(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 be(e,t){let n=e&&typeof e==="object"?e:{},o=(n.media&&typeof n.media==="object"?n.media:void 0)?.image;if(o&&typeof o==="object"){if(o.bytes instanceof Uint8Array)return R.ok({bytes:o.bytes,filename:typeof o.filename==="string"?o.filename:void 0,contentType:typeof o.contentType==="string"?o.contentType:void 0});if(o.blob instanceof Blob)return R.ok({blob:o.blob,filename:typeof o.filename==="string"?o.filename:void 0,contentType:typeof o.contentType==="string"?o.contentType:void 0});if(typeof o.ref==="string"&&o.ref.trim().length>0)return R.fail(new R.KMsgError(R.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 R.fail(new R.KMsgError(R.KMsgErrorCode.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"imageUrl"}));return R.ok(void 0)}async function Ne(e){if("blob"in e){let a=e.contentType||e.blob.type||"application/octet-stream",l=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:l,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}),o=e.filename||"image";return{blob:r,filename:o,contentType:t,size:r.size}}function Te(e){if(Se(e.filename).length>0)return e.filename;let n=oe(e.filename)==="image/png"?".png":oe(e.filename)==="image/gif"?".gif":oe(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 we(e){let{providerId:t,config:n,options:r}=e,o=r.templateId;if(!o||o.length===0)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"templateId is required for ALIMTALK",{providerId:t}));let a=r.options?.scheduledAt,l=a instanceof Date&&!Number.isNaN(a.getTime()),f=l?"Y":"N",g=l?j(a):void 0,I=F(r.to);if(!I)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let y=r.providerOptions?.templateParam,E=Array.isArray(y)?y.map((b)=>b===null||b===void 0?"":String(b)):Object.values(r.variables||{}).map((b)=>b===null||b===void 0?"":String(b)),c=r.failover,S=(typeof r.from==="string"&&r.from.length>0?r.from:n.senderNumber||n.smsSenderNumber)||"",v=S?F(S):"",u=typeof r.providerOptions?.reSend==="string"?r.providerOptions.reSend.trim().toUpperCase():"",D=u==="Y"||u==="N"?u:void 0,O=c?.enabled===!0?"Y":c?.enabled===!1?"N":void 0,p=D??O??(v?"Y":"N"),T=(typeof r.providerOptions?.resendCallback==="string"?F(r.providerOptions.resendCallback):"")||v;if(p==="Y"&&!T)return s.fail(new s.KMsgError(s.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():"",A=m==="Y"||m==="N"?m:void 0;if(typeof r.providerOptions?.resendType==="string"&&r.providerOptions.resendType.length>0&&!A)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"resendType must be 'Y' or 'N'",{providerId:t}));let h=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,M=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,k={templateCode:o,reserve:f,...g?{sendDate:g}:{},list:[{phone:I,templateParam:E.length>0?E:void 0}],reSend:p,...T?{resendCallback:T}:{},...A??h?{resendType:A??h}:{},...N?{resendTitle:N}:{},...M?{resendContent:M}:{}},z=`${n.baseUrl}${ue(n)}`;try{let b=await fetch(z,{method:"POST",headers:K(n),body:JSON.stringify(k)}),J=await b.text(),U=C(J),x=_(U)?U:{code:Y(U)??b.status,message:J||String(U||"")};if(!b.ok||x.code!==200)return s.fail(new s.KMsgError($(x.code),x.message||"IWINV send failed",{providerId:t,originalCode:x.code}));return s.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:typeof x.seqNo==="number"?String(x.seqNo):void 0,status:l?"PENDING":"SENT",type:r.type,to:r.to,raw:x})}catch(b){return s.fail(new s.KMsgError(s.KMsgErrorCode.NETWORK_ERROR,b instanceof Error?b.message:String(b),{providerId:t}))}}async function _e(e){let{providerId:t,config:n,options:r,to:o,from:a,text:l,scheduledAtValid:f,scheduledAt:g}=e;if(r.type!=="MMS")return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"IWINVProvider: MMS handler called with non-MMS options",{providerId:t,type:r.type}));let I=ne(l,r.subject),y=be(r,t);if(y.isFailure)return y;let E=y.value;if(!E)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"image is required for MMS; caller must provide options.media.image.blob or bytes",{providerId:t}));let c;try{c=await Ne(E)}catch(p){return s.fail(p instanceof s.KMsgError?p:new s.KMsgError(s.KMsgErrorCode.NETWORK_ERROR,p instanceof Error?p.message:String(p),{providerId:t}))}if(c.size>102400)return s.fail(new s.KMsgError(s.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",o),S.append("title",I),S.append("text",l),f&&g)S.append("date",ie(g));S.append("image",c.blob,Te(c));let u={secret:L(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)u["X-Forwarded-For"]=n.xForwardedFor;let D={...u};if(n.extraHeaders&&typeof n.extraHeaders==="object")for(let[p,w]of Object.entries(n.extraHeaders)){if(p.toLowerCase()==="content-type")continue;D[p]=w}let O=`${P()}/api/v2/send/`;try{let p=await fetch(O,{method:"POST",headers:D,body:S}),w=await p.text(),T=C(w),m=_(T)?T:{resultCode:T},A=m.resultCode??m.code,h=Z(A),N=typeof m.message==="string"&&m.message.length>0?m.message:ee(h,"MMS send failed");if(!(p.ok&&h==="0"))return s.fail(new s.KMsgError(te(h,p.ok),N,{providerId:t,originalCode:A}));let k=typeof m.requestNo==="string"&&m.requestNo.length>0?m.requestNo:typeof m.msgid==="string"&&m.msgid.length>0?m.msgid:void 0;return s.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:k,status:f?"PENDING":"SENT",type:r.type,to:r.to,raw:m})}catch(p){return s.fail(new s.KMsgError(s.KMsgErrorCode.NETWORK_ERROR,p instanceof Error?p.message:String(p),{providerId:t}))}}async function he(e){let{providerId:t,config:n,options:r}=e;if(!H(n))return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));let o=F(r.to);if(!o)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let a=r.text;if(!a||a.trim().length===0)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"text is required for SMS/LMS/MMS",{providerId:t}));let l=(typeof r.from==="string"&&r.from.length>0?r.from:n.smsSenderNumber||n.senderNumber)||"",f=l?F(l):"";if(!f)return s.fail(new s.KMsgError(s.KMsgErrorCode.INVALID_REQUEST,"from is required for SMS/LMS/MMS (options.from or config.smsSenderNumber)",{providerId:t}));let g=r.options?.scheduledAt,I=g instanceof Date&&!Number.isNaN(g.getTime());if(r.type==="MMS")return await _e({providerId:t,config:n,options:r,to:o,from:f,text:a,scheduledAtValid:I,scheduledAt:I?g:void 0});let y={version:"1.0",from:f,to:[o],text:a};if(r.type==="LMS")y.title=ne(a,r.subject);else{let u=typeof r.providerOptions?.msgType==="string"&&r.providerOptions.msgType.trim().length>0?r.providerOptions.msgType.trim():void 0;y.msgType=u||r.type}if(I)y.date=ie(g);let c={"Content-Type":"application/json;charset=UTF-8",secret:L(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,v=`${P()}/api/v2/send/`;try{let u=await fetch(v,{method:"POST",headers:S,body:JSON.stringify(y)}),D=await u.text(),O=C(D),p=_(O)?O:{resultCode:O},w=p.resultCode??p.code,T=Z(w),m=typeof p.message==="string"&&p.message.length>0?p.message:ee(T,"SMS send failed");if(!(u.ok&&T==="0"))return s.fail(new s.KMsgError(te(T,u.ok),m,{providerId:t,originalCode:w}));let h=typeof p.requestNo==="string"&&p.requestNo.length>0?p.requestNo:typeof p.msgid==="string"&&p.msgid.length>0?p.msgid:void 0;return s.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:h,status:I?"PENDING":"SENT",type:r.type,to:r.to,raw:p})}catch(u){return s.fail(new s.KMsgError(s.KMsgErrorCode.NETWORK_ERROR,u instanceof Error?u.message:String(u),{providerId:t}))}}function ke(e){return{...e,baseUrl:me,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}function Ce(){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 q{id="iwinv";name="IWINV Messaging Provider";supportedTypes;config;getOnboardingSpec(){let e=le(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=ke(e);let t=["ALIMTALK"];if(H(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(H(this.config))try{new URL(P())}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:P()}}}catch(n){return t.push(n instanceof Error?n.message:String(n)),{healthy:!1,issues:t,latencyMs:Date.now()-e}}}async send(e){let t=e.messageId||crypto.randomUUID(),n={...e,messageId:t};switch(n.type){case"ALIMTALK":return we({providerId:this.id,config:this.config,options:n});case"SMS":case"LMS":case"MMS":return he({providerId:this.id,config:this.config,options:n});default:return i.fail(new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,`IWINVProvider does not support type ${n.type}`,{providerId:this.id,type:n.type}))}}async getDeliveryStatus(e){switch(e.type){case"ALIMTALK":return ye({providerId:this.id,config:this.config,query:e});case"SMS":case"LMS":case"MMS":return Ie({providerId:this.id,config:this.config,query:e});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:K(this.config),body:JSON.stringify({})}),r=await n.text(),o=C(r),a=B(o,{}),l=a.code,f=typeof l==="string"?Number(l):void 0,g=typeof l==="number"?l:typeof f==="number"&&Number.isFinite(f)?f:void 0,I=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV AlimTalk charge query failed";if(!n.ok||g!==200)return i.fail(new i.KMsgError($(g??n.status),I,{providerId:this.id,originalCode:l??n.status}));let y=a.charge,E=typeof y==="number"?y:typeof y==="string"?Number(y):NaN;if(!Number.isFinite(E))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:E,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:L(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,o=`${P()}/api/charge/`;try{let a=await fetch(o,{method:"POST",headers:r,body:JSON.stringify({version:"1.0"})}),l=await a.text(),f=C(l),g=B(f,{}),I=g.code??g.resultCode,y=typeof I==="string"?Number(I):void 0,E=typeof I==="number"?I:typeof y==="number"&&Number.isFinite(y)?y:NaN,c=typeof g.message==="string"&&g.message.length>0?g.message:"IWINV SMS charge query failed";if(!a.ok||E!==0)return i.fail(new i.KMsgError(i.KMsgErrorCode.PROVIDER_ERROR,c,{providerId:this.id,originalCode:I??a.status}));let S=g.charge,v=typeof S==="number"?S:typeof S==="string"?Number(S):NaN;if(!Number.isFinite(v))return i.fail(new i.KMsgError(i.KMsgErrorCode.PROVIDER_ERROR,"Invalid charge value from IWINV SMS charge API",{providerId:this.id,raw:g}));return i.ok({providerId:this.id,channel:e,amount:v,currency:"KRW",raw:g})}catch(a){return i.fail(new i.KMsgError(i.KMsgErrorCode.NETWORK_ERROR,a instanceof Error?a.message:String(a),{providerId:this.id}))}}}var Ee=(e)=>new q(e),ae=()=>{let e=Ce();if(!e.apiKey)throw new i.KMsgError(i.KMsgErrorCode.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new q(e)};class de{static create(e){return new q(e)}static createDefault(){return ae()}}var Ve={SUCCESS:200,AUTH_FAILED:201,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500};
2
+
3
+ //# debugId=7E73414A84680AC364756E2164756E21
4
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1,4 @@
1
+ import{fail as L,KMsgError as v,KMsgErrorCode as D,ok as ke,readRuntimeEnv as U}from"@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 He(){return Object.values(ge)}function k(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function P(e){if(!e)return{};try{return JSON.parse(e)}catch{return e}}function j(e,t){return k(e)?e:t}import{KMsgErrorCode as B}from"@k-msg/core";function Fe(e){let t="",n=0;while(n<e.length){let r=e[n++]??0,s=e[n++]??0,i=e[n++]??0,d=r<<16|s<<8|i;t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>18&63],t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>12&63],t+=n-2<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>6&63]:"=",t+=n-1<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d&63]:"="}return t}function Z(e){return Fe(new TextEncoder().encode(e))}function Ie(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function Y(e){let n={AUTH:Z(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 G(e){switch(e){case 201:case 206:case 401:case 403:return B.AUTHENTICATION_FAILED;case 429:return B.RATE_LIMIT_EXCEEDED;case 519:return B.INSUFFICIENT_BALANCE;case 404:case 501:return B.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 B.INVALID_REQUEST;case 518:return B.PROVIDER_ERROR;default:if(e>=500)return B.PROVIDER_ERROR;return B.INVALID_REQUEST}}function ne(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 je(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 Ye(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}var Se="https://alimtalk.bizservice.iwinv.kr",be="https://sms.bizservice.iwinv.kr";import{fail as C,KMsgError as V,KMsgErrorCode as M,ok as J}from"@k-msg/core";import{KMsgErrorCode as ee}from"@k-msg/core";function H(e){return e.replace(/[^0-9]/g,"")}function q(){return be}function K(e){if(e.smsApiKey&&e.smsAuthKey)return Z(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return Z(`${e.apiKey}&${t}`)}function W(e){return K(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 ae(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return ee.AUTHENTICATION_FAILED;if(e==="50")return ee.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 ee.INVALID_REQUEST;if(!t)return ee.NETWORK_ERROR;return ee.PROVIDER_ERROR}function de(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 pe(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function ce(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function re(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]),i=Number(n[3]),d=Number(n[4]),l=Number(n[5]),u=Number(n[6]);if(!Number.isFinite(r)||!Number.isFinite(s)||!Number.isFinite(i)||!Number.isFinite(d)||!Number.isFinite(l)||!Number.isFinite(u))return;let f=new Date(r,s-1,i,d,l,u);if(Number.isNaN(f.getTime()))return;return f}function te(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 le(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}=e,s=r.providerMessageId.trim();if(!s)return C(new V(M.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let i=H(r.to);if(!i)return C(new V(M.INVALID_REQUEST,"to is required",{providerId:t}));let d=Number(s),l=Number.isFinite(d)?d:void 0,u=te(pe(r.requestedAt,-1)),f=te(new Date),m={pageNum:1,pageSize:15,phone:i,startDate:u,endDate:f,...l!==void 0?{seqNo:l}:{},...r.scheduledAt instanceof Date&&!Number.isNaN(r.scheduledAt.getTime())?{reserve:"Y"}:{}},E=`${n.baseUrl}/api/history/`;try{let a=await fetch(E,{method:"POST",headers:Y(n),body:JSON.stringify(m)}),g=await a.text(),A=P(g),p=j(A,{}),O=p.code,x=typeof O==="number"?O:void 0,o=typeof p.message==="string"&&p.message.length>0?p.message:"IWINV history query failed";if(!a.ok||x!==200)return C(new V(G(x??ne(A)??a.status),o,{providerId:t,originalCode:O??a.status}));let T=p.list,b=Array.isArray(T)?T:[];if(b.length===0)return J(null);let c=(()=>{if(l===void 0)return b[0];return b.find((y)=>k(y)&&y.seqNo===l)??b[0]})();if(!k(c))return J(null);let R=typeof c.statusCode==="string"?c.statusCode:void 0,w=typeof c.statusCodeName==="string"?c.statusCodeName:void 0,I=re(c.sendDate),z=re(c.receiveDate),F=R==="OK"||typeof w==="string"&&w.includes("성공");return J({providerId:t,providerMessageId:s,status:F?"DELIVERED":I?"FAILED":"PENDING",statusCode:R,statusMessage:w,sentAt:I,deliveredAt:F?z||I:void 0,failedAt:!F&&I?I:void 0,raw:c})}catch(a){return C(new V(M.NETWORK_ERROR,a instanceof Error?a.message:String(a),{providerId:t}))}}async function we(e){let{providerId:t,config:n,query:r}=e;if(!W(n))return C(new V(M.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));if(!n.smsCompanyId||n.smsCompanyId.length===0)return C(new V(M.INVALID_REQUEST,"smsCompanyId required for history (config.smsCompanyId)",{providerId:t}));let s=r.providerMessageId.trim();if(!s)return C(new V(M.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let i=H(r.to);if(!i)return C(new V(M.INVALID_REQUEST,"to is required",{providerId:t}));let d=pe(r.requestedAt,-1),l=new Date;if(l.getTime()-d.getTime()>7776000000)return C(new V(M.INVALID_REQUEST,"SMS history date range must be within 90 days",{providerId:t}));let m={version:"1.0",companyid:n.smsCompanyId,startDate:ce(d),endDate:ce(l),requestNo:s,pageNum:1,pageSize:15,phone:i},a={"Content-Type":"application/json;charset=UTF-8",secret:K(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)a["X-Forwarded-For"]=n.xForwardedFor;let g=n.extraHeaders&&typeof n.extraHeaders==="object"?{...a,...n.extraHeaders}:a,A=`${q()}/api/history/`;try{let p=await fetch(A,{method:"POST",headers:g,body:JSON.stringify(m)}),O=await p.text(),x=P(O),o=j(x,{}),T=o.resultCode,b=typeof T==="number"?T:typeof T==="string"?Number(T):NaN,c=typeof o.message==="string"&&o.message.length>0?o.message:"IWINV SMS history query failed";if(!p.ok||b!==0)return C(new V(M.PROVIDER_ERROR,c,{providerId:t,originalCode:T??p.status}));let R=o.list,w=Array.isArray(R)?R:[];if(w.length===0)return J(null);let I=(()=>{return w.find(($)=>{if(!k($))return!1;let _=$.requestNo;return _!==void 0&&_!==null?String(_)===s:!1})??w[0]})();if(!k(I))return J(null);let z=typeof I.sendStatusCode==="string"?I.sendStatusCode:void 0,F=typeof I.sendStatusMsg==="string"?I.sendStatusMsg:typeof I.sendStatus==="string"?I.sendStatus:void 0,Q=re(I.sendDate),y=Ne(z,F);return J({providerId:t,providerMessageId:s,status:y,statusCode:z,statusMessage:F,sentAt:Q,deliveredAt:y==="DELIVERED"?Q:void 0,failedAt:y==="FAILED"?Q:void 0,raw:I})}catch(p){return C(new V(M.NETWORK_ERROR,p instanceof Error?p.message:String(p),{providerId:t}))}}import{fail as N,KMsgError as S,KMsgErrorCode as h,ok as fe}from"@k-msg/core";import{fail as he,KMsgError as Ee,KMsgErrorCode as ve,ok as ue}from"@k-msg/core";function Ae(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 me(e){switch(Ae(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 Re(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 ue({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 ue({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 he(new Ee(ve.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"media.image.ref"}))}let i=n.imageUrl;if(typeof i==="string"&&i.trim().length>0)return he(new Ee(ve.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"imageUrl"}));return ue(void 0)}async function De(e){if("blob"in e){let i=e.contentType||e.blob.type||"application/octet-stream",d=e.filename||"image",l=e.contentType&&e.contentType!==e.blob.type?new Blob([await e.blob.arrayBuffer()],{type:i}):e.blob;return{blob:l,filename:d,contentType:i,size:l.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 Oe(e){if(Ae(e.filename).length>0)return e.filename;let n=me(e.filename)==="image/png"?".png":me(e.filename)==="image/gif"?".gif":me(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 xe(e){let{providerId:t,config:n,options:r}=e,s=r.templateId;if(!s||s.length===0)return N(new S(h.INVALID_REQUEST,"templateId is required for ALIMTALK",{providerId:t}));let i=r.options?.scheduledAt,d=i instanceof Date&&!Number.isNaN(i.getTime()),l=d?"Y":"N",u=d?te(i):void 0,f=H(r.to);if(!f)return N(new S(h.INVALID_REQUEST,"to is required",{providerId:t}));let m=r.providerOptions?.templateParam,E=Array.isArray(m)?m.map((y)=>y===null||y===void 0?"":String(y)):Object.values(r.variables||{}).map((y)=>y===null||y===void 0?"":String(y)),a=r.failover,g=(typeof r.from==="string"&&r.from.length>0?r.from:n.senderNumber||n.smsSenderNumber)||"",A=g?H(g):"",p=typeof r.providerOptions?.reSend==="string"?r.providerOptions.reSend.trim().toUpperCase():"",O=p==="Y"||p==="N"?p:void 0,x=a?.enabled===!0?"Y":a?.enabled===!1?"N":void 0,o=O??x??(A?"Y":"N"),b=(typeof r.providerOptions?.resendCallback==="string"?H(r.providerOptions.resendCallback):"")||A;if(o==="Y"&&!b)return N(new S(h.INVALID_REQUEST,"resendCallback is required when reSend is 'Y' (options.from or providerOptions.resendCallback)",{providerId:t}));let c=typeof r.providerOptions?.resendType==="string"?r.providerOptions.resendType.trim().toUpperCase():"",R=c==="Y"||c==="N"?c:void 0;if(typeof r.providerOptions?.resendType==="string"&&r.providerOptions.resendType.length>0&&!R)return N(new S(h.INVALID_REQUEST,"resendType must be 'Y' or 'N'",{providerId:t}));let w=a?.fallbackChannel==="lms"?"Y":a?.fallbackChannel==="sms"?"N":void 0,I=typeof r.providerOptions?.resendTitle==="string"&&r.providerOptions.resendTitle.trim().length>0?r.providerOptions.resendTitle.trim():typeof a?.fallbackTitle==="string"&&a.fallbackTitle.trim().length>0?a.fallbackTitle.trim():void 0,z=typeof r.providerOptions?.resendContent==="string"&&r.providerOptions.resendContent.trim().length>0?r.providerOptions.resendContent.trim():typeof a?.fallbackContent==="string"&&a.fallbackContent.trim().length>0?a.fallbackContent.trim():void 0,F={templateCode:s,reserve:l,...u?{sendDate:u}:{},list:[{phone:f,templateParam:E.length>0?E:void 0}],reSend:o,...b?{resendCallback:b}:{},...R??w?{resendType:R??w}:{},...I?{resendTitle:I}:{},...z?{resendContent:z}:{}},Q=`${n.baseUrl}${Ie(n)}`;try{let y=await fetch(Q,{method:"POST",headers:Y(n),body:JSON.stringify(F)}),se=await y.text(),$=P(se),_=k($)?$:{code:ne($)??y.status,message:se||String($||"")};if(!y.ok||_.code!==200)return N(new S(G(_.code),_.message||"IWINV send failed",{providerId:t,originalCode:_.code}));return fe({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:typeof _.seqNo==="number"?String(_.seqNo):void 0,status:d?"PENDING":"SENT",type:r.type,to:r.to,raw:_})}catch(y){return N(new S(h.NETWORK_ERROR,y instanceof Error?y.message:String(y),{providerId:t}))}}async function Pe(e){let{providerId:t,config:n,options:r,to:s,from:i,text:d,scheduledAtValid:l,scheduledAt:u}=e;if(r.type!=="MMS")return N(new S(h.INVALID_REQUEST,"IWINVProvider: MMS handler called with non-MMS options",{providerId:t,type:r.type}));let f=de(d,r.subject),m=Re(r,t);if(m.isFailure)return m;let E=m.value;if(!E)return N(new S(h.INVALID_REQUEST,"image is required for MMS; caller must provide options.media.image.blob or bytes",{providerId:t}));let a;try{a=await De(E)}catch(o){return N(o instanceof S?o:new S(h.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}if(a.size>102400)return N(new S(h.INVALID_REQUEST,"MMS image must be <= 100KB",{providerId:t,bytes:a.size}));let g=new FormData;if(g.append("version","1.0"),g.append("from",i),g.append("to",s),g.append("title",f),g.append("text",d),l&&u)g.append("date",le(u));g.append("image",a.blob,Oe(a));let p={secret:K(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)p["X-Forwarded-For"]=n.xForwardedFor;let O={...p};if(n.extraHeaders&&typeof n.extraHeaders==="object")for(let[o,T]of Object.entries(n.extraHeaders)){if(o.toLowerCase()==="content-type")continue;O[o]=T}let x=`${q()}/api/v2/send/`;try{let o=await fetch(x,{method:"POST",headers:O,body:g}),T=await o.text(),b=P(T),c=k(b)?b:{resultCode:b},R=c.resultCode??c.code,w=ie(R),I=typeof c.message==="string"&&c.message.length>0?c.message:oe(w,"MMS send failed");if(!(o.ok&&w==="0"))return N(new S(ae(w,o.ok),I,{providerId:t,originalCode:R}));let F=typeof c.requestNo==="string"&&c.requestNo.length>0?c.requestNo:typeof c.msgid==="string"&&c.msgid.length>0?c.msgid:void 0;return fe({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:F,status:l?"PENDING":"SENT",type:r.type,to:r.to,raw:c})}catch(o){return N(new S(h.NETWORK_ERROR,o instanceof Error?o.message:String(o),{providerId:t}))}}async function _e(e){let{providerId:t,config:n,options:r}=e;if(!W(n))return N(new S(h.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));let s=H(r.to);if(!s)return N(new S(h.INVALID_REQUEST,"to is required",{providerId:t}));let i=r.text;if(!i||i.trim().length===0)return N(new S(h.INVALID_REQUEST,"text is required for SMS/LMS/MMS",{providerId:t}));let d=(typeof r.from==="string"&&r.from.length>0?r.from:n.smsSenderNumber||n.senderNumber)||"",l=d?H(d):"";if(!l)return N(new S(h.INVALID_REQUEST,"from is required for SMS/LMS/MMS (options.from or config.smsSenderNumber)",{providerId:t}));let u=r.options?.scheduledAt,f=u instanceof Date&&!Number.isNaN(u.getTime());if(r.type==="MMS")return await Pe({providerId:t,config:n,options:r,to:s,from:l,text:i,scheduledAtValid:f,scheduledAt:f?u:void 0});let m={version:"1.0",from:l,to:[s],text:i};if(r.type==="LMS")m.title=de(i,r.subject);else{let p=typeof r.providerOptions?.msgType==="string"&&r.providerOptions.msgType.trim().length>0?r.providerOptions.msgType.trim():void 0;m.msgType=p||r.type}if(f)m.date=le(u);let a={"Content-Type":"application/json;charset=UTF-8",secret:K(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)a["X-Forwarded-For"]=n.xForwardedFor;let g=n.extraHeaders&&typeof n.extraHeaders==="object"?{...a,...n.extraHeaders}:a,A=`${q()}/api/v2/send/`;try{let p=await fetch(A,{method:"POST",headers:g,body:JSON.stringify(m)}),O=await p.text(),x=P(O),o=k(x)?x:{resultCode:x},T=o.resultCode??o.code,b=ie(T),c=typeof o.message==="string"&&o.message.length>0?o.message:oe(b,"SMS send failed");if(!(p.ok&&b==="0"))return N(new S(ae(b,p.ok),c,{providerId:t,originalCode:T}));let w=typeof o.requestNo==="string"&&o.requestNo.length>0?o.requestNo:typeof o.msgid==="string"&&o.msgid.length>0?o.msgid:void 0;return fe({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:w,status:f?"PENDING":"SENT",type:r.type,to:r.to,raw:o})}catch(p){return N(new S(h.NETWORK_ERROR,p instanceof Error?p.message:String(p),{providerId:t}))}}function Me(e){return{...e,baseUrl:Se,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}function Le(){return{apiKey:U("IWINV_API_KEY")||"",smsApiKey:U("IWINV_SMS_API_KEY"),smsAuthKey:U("IWINV_SMS_AUTH_KEY"),smsCompanyId:U("IWINV_SMS_COMPANY_ID"),senderNumber:U("IWINV_SENDER_NUMBER")||U("IWINV_SMS_SENDER_NUMBER"),smsSenderNumber:U("IWINV_SMS_SENDER_NUMBER"),sendEndpoint:U("IWINV_SEND_ENDPOINT")||"/api/v2/send/",xForwardedFor:U("IWINV_X_FORWARDED_FOR"),debug:U("NODE_ENV")==="development"}}class X{id="iwinv";name="IWINV Messaging Provider";supportedTypes;config;getOnboardingSpec(){let e=ye(this.id);if(!e)throw new v(D.INVALID_REQUEST,`Onboarding spec missing for provider: ${this.id}`,{providerId:this.id});return e}constructor(e){if(!e||typeof e!=="object")throw new v(D.INVALID_REQUEST,"IWINVProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new v(D.INVALID_REQUEST,"IWINVProvider requires `apiKey` configuration",{providerId:this.id});this.config=Me(e);let t=["ALIMTALK"];if(W(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(W(this.config))try{new URL(q())}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:q()}}}catch(n){return t.push(n instanceof Error?n.message:String(n)),{healthy:!1,issues:t,latencyMs:Date.now()-e}}}async send(e){let t=e.messageId||crypto.randomUUID(),n={...e,messageId:t};switch(n.type){case"ALIMTALK":return xe({providerId:this.id,config:this.config,options:n});case"SMS":case"LMS":case"MMS":return _e({providerId:this.id,config:this.config,options:n});default:return L(new v(D.INVALID_REQUEST,`IWINVProvider does not support type ${n.type}`,{providerId:this.id,type:n.type}))}}async getDeliveryStatus(e){switch(e.type){case"ALIMTALK":return Te({providerId:this.id,config:this.config,query:e});case"SMS":case"LMS":case"MMS":return we({providerId:this.id,config:this.config,query:e});default:return L(new v(D.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 L(new v(D.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:Y(this.config),body:JSON.stringify({})}),r=await n.text(),s=P(r),i=j(s,{}),d=i.code,l=typeof d==="string"?Number(d):void 0,u=typeof d==="number"?d:typeof l==="number"&&Number.isFinite(l)?l:void 0,f=typeof i.message==="string"&&i.message.length>0?i.message:"IWINV AlimTalk charge query failed";if(!n.ok||u!==200)return L(new v(G(u??n.status),f,{providerId:this.id,originalCode:d??n.status}));let m=i.charge,E=typeof m==="number"?m:typeof m==="string"?Number(m):NaN;if(!Number.isFinite(E))return L(new v(D.PROVIDER_ERROR,"Invalid charge value from IWINV AlimTalk charge API",{providerId:this.id,raw:i}));return ke({providerId:this.id,channel:e,amount:E,currency:"KRW",raw:i})}catch(n){return L(new v(D.NETWORK_ERROR,n instanceof Error?n.message:String(n),{providerId:this.id}))}}async getSmsBalance(e){if(!this.config.smsApiKey||!this.config.smsAuthKey)return L(new v(D.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:K(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=`${q()}/api/charge/`;try{let i=await fetch(s,{method:"POST",headers:r,body:JSON.stringify({version:"1.0"})}),d=await i.text(),l=P(d),u=j(l,{}),f=u.code??u.resultCode,m=typeof f==="string"?Number(f):void 0,E=typeof f==="number"?f:typeof m==="number"&&Number.isFinite(m)?m:NaN,a=typeof u.message==="string"&&u.message.length>0?u.message:"IWINV SMS charge query failed";if(!i.ok||E!==0)return L(new v(D.PROVIDER_ERROR,a,{providerId:this.id,originalCode:f??i.status}));let g=u.charge,A=typeof g==="number"?g:typeof g==="string"?Number(g):NaN;if(!Number.isFinite(A))return L(new v(D.PROVIDER_ERROR,"Invalid charge value from IWINV SMS charge API",{providerId:this.id,raw:u}));return ke({providerId:this.id,channel:e,amount:A,currency:"KRW",raw:u})}catch(i){return L(new v(D.NETWORK_ERROR,i instanceof Error?i.message:String(i),{providerId:this.id}))}}}var Ue=(e)=>new X(e),Ce=()=>{let e=Le();if(!e.apiKey)throw new v(D.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new X(e)};class Ve{static create(e){return new X(e)}static createDefault(){return Ce()}}var Ot={SUCCESS:200,AUTH_FAILED:201,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500};export{X as default,Ue as createIWINVSendProvider,Ce as createDefaultIWINVSendProvider,Ot as IWINV_STATUS_CODES,Ve as IWINVSendProviderFactory,X as IWINVSendProvider};
2
+
3
+ //# debugId=0C4F408936EF3E2A64756E2164756E21
4
+ //# sourceMappingURL=send.mjs.map
@@ -0,0 +1,24 @@
1
+ import { KMsgError, type Result, type Template, type TemplateContext, type TemplateCreateInput, type TemplateProvider, type TemplateUpdateInput } from "@k-msg/core";
2
+ import type { IWINVConfig } from "./types/iwinv";
3
+ export declare class IWINVTemplateProvider implements TemplateProvider {
4
+ readonly id = "iwinv";
5
+ private readonly config;
6
+ constructor(config: IWINVConfig);
7
+ createTemplate(input: TemplateCreateInput): Promise<Result<Template, KMsgError>>;
8
+ updateTemplate(code: string, patch: TemplateUpdateInput, ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
9
+ deleteTemplate(code: string): Promise<Result<void, KMsgError>>;
10
+ getTemplate(code: string, ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
11
+ listTemplates(params?: {
12
+ status?: string;
13
+ page?: number;
14
+ limit?: number;
15
+ }, ctx?: TemplateContext): Promise<Result<Template[], KMsgError>>;
16
+ }
17
+ export declare const createIWINVTemplateProvider: (config: IWINVConfig) => IWINVTemplateProvider;
18
+ export declare const createDefaultIWINVTemplateProvider: () => IWINVTemplateProvider;
19
+ export declare class IWINVTemplateProviderFactory {
20
+ static create(config: IWINVConfig): IWINVTemplateProvider;
21
+ static createDefault(): IWINVTemplateProvider;
22
+ }
23
+ export { createTemplate, deleteTemplate, getTemplate, listTemplates, updateTemplate, } from "./iwinv.template";
24
+ export type { IWINVConfig } from "./types/iwinv";
@@ -0,0 +1,4 @@
1
+ var{defineProperty:de,getOwnPropertyNames:Le,getOwnPropertyDescriptor:Ue}=Object,Ke=Object.prototype.hasOwnProperty;var Ne=new WeakMap,qe=(e)=>{var t=Ne.get(e),n;if(t)return t;if(t=de({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")Le(e).map((r)=>!Ke.call(t,r)&&de(t,r,{get:()=>e[r],enumerable:!(n=Ue(e,r))||n.enumerable}));return Ne.set(e,t),t};var ze=(e,t)=>{for(var n in t)de(e,n,{get:t[n],enumerable:!0,configurable:!0,set:(r)=>t[n]=()=>r})};var Je={};ze(Je,{updateTemplate:()=>re,listTemplates:()=>oe,getTemplate:()=>j,deleteTemplate:()=>se,createTemplate:()=>ne,createIWINVTemplateProvider:()=>Ye,createDefaultIWINVTemplateProvider:()=>Ve,IWINVTemplateProviderFactory:()=>Fe,IWINVTemplateProvider:()=>ee});module.exports=qe(Je);var J=require("@k-msg/core");var te="https://alimtalk.bizservice.iwinv.kr",we="https://sms.bizservice.iwinv.kr";var p=require("@k-msg/core"),me=require("@k-msg/template/send");function O(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function k(e){if(!e)return{};try{return JSON.parse(e)}catch{return e}}function z(e,t){return O(e)?e:t}var L=require("@k-msg/core");function He(e){let t="",n=0;while(n<e.length){let r=e[n++]??0,s=e[n++]??0,d=e[n++]??0,u=r<<16|s<<8|d;t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u>>18&63],t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u>>12&63],t+=n-2<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u>>6&63]:"=",t+=n-1<e.length?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u&63]:"="}return t}function G(e){return He(new TextEncoder().encode(e))}function Te(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function _(e){let n={AUTH:G(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 M(e){switch(e){case 201:case 206:case 401:case 403:return L.KMsgErrorCode.AUTHENTICATION_FAILED;case 429:return L.KMsgErrorCode.RATE_LIMIT_EXCEEDED;case 519:return L.KMsgErrorCode.INSUFFICIENT_BALANCE;case 404:case 501:return L.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 L.KMsgErrorCode.INVALID_REQUEST;case 518:return L.KMsgErrorCode.PROVIDER_ERROR;default:if(e>=500)return L.KMsgErrorCode.PROVIDER_ERROR;return L.KMsgErrorCode.INVALID_REQUEST}}function V(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 Ee(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 pe(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}function ce(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function le(e){let t=(n)=>n.toString().padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function B(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]),d=Number(n[3]),u=Number(n[4]),i=Number(n[5]),a=Number(n[6]);if(!Number.isFinite(r)||!Number.isFinite(s)||!Number.isFinite(d)||!Number.isFinite(u)||!Number.isFinite(i)||!Number.isFinite(a))return;let m=new Date(r,s-1,d,u,i,a);if(Number.isNaN(m.getTime()))return;return m}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 ue(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 Z(e){let t=await e.text(),n=k(t);return z(n,{code:V(n)??e.status,message:t||String(n||"")})}function Re(e,t){return new p.KMsgError(e.code,e.message,{providerId:t,...e.details??{}})}async function ne(e){let{providerId:t,config:n,input:r}=e;if(!r||typeof r!=="object")return p.fail(new p.KMsgError(p.KMsgErrorCode.INVALID_REQUEST,"Template input is required",{providerId:t}));let s=me.validateTemplatePayload(r,{requireName:!0,requireContent:!0});if(s.isFailure)return p.fail(Re(s.error,t));let d=`${n.baseUrl}/api/template/add/`,u={templateName:s.value.name??r.name,templateContent:s.value.content??r.content,...s.value.buttons?{buttons:s.value.buttons}:{}};try{let i=await fetch(d,{method:"POST",headers:_(n),body:JSON.stringify(u)}),a=await Z(i),m=V(a.code)??i.status,b=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV template create failed";if(!i.ok||m!==200)return p.fail(new p.KMsgError(M(m),b,{providerId:t,originalCode:m}));let w=a.templateCode,l=typeof w==="string"&&w.trim().length>0?w.trim():"";if(!l)return p.fail(new p.KMsgError(p.KMsgErrorCode.PROVIDER_ERROR,"IWINV template create did not return templateCode",{providerId:t,raw:a}));let I=new Date;return p.ok({id:l,code:l,name:s.value.name??r.name,content:s.value.content??r.content,category:r.category,status:"INSPECTION",buttons:s.value.buttons,variables:r.variables,createdAt:I,updatedAt:I})}catch(i){return p.fail(new p.KMsgError(p.KMsgErrorCode.NETWORK_ERROR,i instanceof Error?i.message:String(i),{providerId:t}))}}async function re(e){let{providerId:t,config:n,code:r,patch:s,ctx:d}=e,u=typeof r==="string"?r.trim():"";if(!u)return p.fail(new p.KMsgError(p.KMsgErrorCode.INVALID_REQUEST,"code is required",{providerId:t}));let i=await j({providerId:t,config:n,code:u,ctx:d});if(i.isFailure)return i;let a=i.value,m=typeof s.name==="string"&&s.name.trim().length>0?s.name.trim():a.name,b=typeof s.content==="string"&&s.content.trim().length>0?s.content:a.content,w=s.buttons!==void 0?s.buttons:a.buttons,l=me.validateTemplatePayload({name:m,content:b,buttons:w},{requireName:!0,requireContent:!0});if(l.isFailure)return p.fail(Re(l.error,t));let I=`${n.baseUrl}/api/template/modify/`,h={templateCode:u,templateName:l.value.name??m,templateContent:l.value.content??b,...l.value.buttons?{buttons:l.value.buttons}:{}};try{let g=await fetch(I,{method:"POST",headers:_(n),body:JSON.stringify(h)}),S=await Z(g),E=V(S.code)??g.status,f=typeof S.message==="string"&&S.message.length>0?S.message:"IWINV template update failed";if(!g.ok||E!==200)return p.fail(new p.KMsgError(M(E),f,{providerId:t,originalCode:E}));let T=await j({providerId:t,config:n,code:u,ctx:d});if(T.isSuccess)return T;return p.ok({...a,name:l.value.name??m,content:l.value.content??b,...s.category!==void 0?{category:s.category}:{},...s.variables!==void 0?{variables:s.variables}:{},...s.buttons!==void 0?{buttons:l.value.buttons}:{},updatedAt:new Date})}catch(g){return p.fail(new p.KMsgError(p.KMsgErrorCode.NETWORK_ERROR,g instanceof Error?g.message:String(g),{providerId:t}))}}async function se(e){let{providerId:t,config:n,code:r}=e,s=typeof r==="string"?r.trim():"";if(!s)return p.fail(new p.KMsgError(p.KMsgErrorCode.INVALID_REQUEST,"code is required",{providerId:t}));let d=`${n.baseUrl}/api/template/delete/`,u={templateCode:s};try{let i=await fetch(d,{method:"POST",headers:_(n),body:JSON.stringify(u)}),a=await Z(i),m=V(a.code)??i.status,b=typeof a.message==="string"&&a.message.length>0?a.message:typeof a.messgae==="string"&&a.messgae.length>0?a.messgae:"IWINV template delete failed";if(!i.ok||m!==200)return p.fail(new p.KMsgError(M(m),b,{providerId:t,originalCode:m}));return p.ok(void 0)}catch(i){return p.fail(new p.KMsgError(p.KMsgErrorCode.NETWORK_ERROR,i instanceof Error?i.message:String(i),{providerId:t}))}}async function j(e){let{providerId:t,config:n,code:r}=e,s=typeof r==="string"?r.trim():"";if(!s)return p.fail(new p.KMsgError(p.KMsgErrorCode.INVALID_REQUEST,"code is required",{providerId:t}));let d={pageNum:"1",pageSize:"15",templateCode:s},u=`${n.baseUrl}/api/template/`;try{let i=await fetch(u,{method:"POST",headers:_(n),body:JSON.stringify(d)}),a=await Z(i),m=V(a.code)??i.status,b=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV template get failed";if(!i.ok||m!==200)return p.fail(new p.KMsgError(M(m),b,{providerId:t,originalCode:m}));let w=a.list,I=(Array.isArray(w)?w:[]).find(O);if(!I)return p.fail(new p.KMsgError(p.KMsgErrorCode.TEMPLATE_NOT_FOUND,"Template not found",{providerId:t,templateCode:s}));let h=I.templateCode,g=typeof h==="string"?h:String(h??""),S=typeof I.templateName==="string"?I.templateName:"",E=typeof I.templateContent==="string"?I.templateContent:"",f=pe(I.status),T=B(I.createDate)??new Date;return p.ok({id:g,code:g,name:S,content:E,status:f,buttons:Array.isArray(I.buttons)?I.buttons:void 0,createdAt:T,updatedAt:T})}catch(i){return p.fail(new p.KMsgError(p.KMsgErrorCode.NETWORK_ERROR,i instanceof Error?i.message:String(i),{providerId:t}))}}async function oe(e){let{providerId:t,config:n,query:r}=e,s=typeof r?.page==="number"&&r.page>0?Math.floor(r.page):1,d=typeof r?.limit==="number"&&r.limit>0?Math.floor(r.limit):15,u=Ee(r?.status),i={pageNum:String(s),pageSize:String(d),...u?{templateStatus:u}:{}},a=`${n.baseUrl}/api/template/`;try{let m=await fetch(a,{method:"POST",headers:_(n),body:JSON.stringify(i)}),b=await Z(m),w=V(b.code)??m.status,l=typeof b.message==="string"&&b.message.length>0?b.message:"IWINV template list failed";if(!m.ok||w!==200)return p.fail(new p.KMsgError(M(w),l,{providerId:t,originalCode:w}));let I=b.list,g=(Array.isArray(I)?I:[]).filter(O).map((S)=>{let E=S.templateCode,f=typeof E==="string"?E:String(E??""),T=typeof S.templateName==="string"?S.templateName:"",v=typeof S.templateContent==="string"?S.templateContent:"",N=pe(S.status),D=B(S.createDate)??new Date;return{id:f,code:f,name:T,content:v,status:N,buttons:Array.isArray(S.buttons)?S.buttons:void 0,createdAt:D,updatedAt:D}}).filter((S)=>S.code.length>0);return p.ok(g)}catch(m){return p.fail(new p.KMsgError(p.KMsgErrorCode.NETWORK_ERROR,m instanceof Error?m.message:String(m),{providerId:t}))}}var c=require("@k-msg/core");var he={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 ve(e){return he[e]}function lt(){return Object.values(he)}var y=require("@k-msg/core");var Y=require("@k-msg/core");function U(e){return e.replace(/[^0-9]/g,"")}function K(){return we}function H(e){if(e.smsApiKey&&e.smsAuthKey)return G(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return G(`${e.apiKey}&${t}`)}function Q(e){return H(e).length>0}function fe(e){if(typeof e==="number"&&Number.isFinite(e))return e.toString();if(typeof e==="string")return e.trim();return""}function ge(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 ye(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return Y.KMsgErrorCode.AUTHENTICATION_FAILED;if(e==="50")return Y.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 Y.KMsgErrorCode.INVALID_REQUEST;if(!t)return Y.KMsgErrorCode.NETWORK_ERROR;return Y.KMsgErrorCode.PROVIDER_ERROR}function Ie(e,t){if(t&&t.trim().length>0)return t.trim();return e.slice(0,20)}function Ae(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"}async function De(e){let{providerId:t,config:n,query:r}=e,s=r.providerMessageId.trim();if(!s)return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let d=U(r.to);if(!d)return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let u=Number(s),i=Number.isFinite(u)?u:void 0,a=X(ce(r.requestedAt,-1)),m=X(new Date),b={pageNum:1,pageSize:15,phone:d,startDate:a,endDate:m,...i!==void 0?{seqNo:i}:{},...r.scheduledAt instanceof Date&&!Number.isNaN(r.scheduledAt.getTime())?{reserve:"Y"}:{}},w=`${n.baseUrl}/api/history/`;try{let l=await fetch(w,{method:"POST",headers:_(n),body:JSON.stringify(b)}),I=await l.text(),h=k(I),g=z(h,{}),S=g.code,E=typeof S==="number"?S:void 0,f=typeof g.message==="string"&&g.message.length>0?g.message:"IWINV history query failed";if(!l.ok||E!==200)return y.fail(new y.KMsgError(M(E??V(h)??l.status),f,{providerId:t,originalCode:S??l.status}));let T=g.list,v=Array.isArray(T)?T:[];if(v.length===0)return y.ok(null);let N=(()=>{if(i===void 0)return v[0];return v.find((R)=>O(R)&&R.seqNo===i)??v[0]})();if(!O(N))return y.ok(null);let D=typeof N.statusCode==="string"?N.statusCode:void 0,C=typeof N.statusCodeName==="string"?N.statusCodeName:void 0,A=B(N.sendDate),q=B(N.receiveDate),F=D==="OK"||typeof C==="string"&&C.includes("성공");return y.ok({providerId:t,providerMessageId:s,status:F?"DELIVERED":A?"FAILED":"PENDING",statusCode:D,statusMessage:C,sentAt:A,deliveredAt:F?q||A:void 0,failedAt:!F&&A?A:void 0,raw:N})}catch(l){return y.fail(new y.KMsgError(y.KMsgErrorCode.NETWORK_ERROR,l instanceof Error?l.message:String(l),{providerId:t}))}}async function Ce(e){let{providerId:t,config:n,query:r}=e;if(!Q(n))return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));if(!n.smsCompanyId||n.smsCompanyId.length===0)return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"smsCompanyId required for history (config.smsCompanyId)",{providerId:t}));let s=r.providerMessageId.trim();if(!s)return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"providerMessageId is required",{providerId:t}));let d=U(r.to);if(!d)return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let u=ce(r.requestedAt,-1),i=new Date;if(i.getTime()-u.getTime()>7776000000)return y.fail(new y.KMsgError(y.KMsgErrorCode.INVALID_REQUEST,"SMS history date range must be within 90 days",{providerId:t}));let b={version:"1.0",companyid:n.smsCompanyId,startDate:le(u),endDate:le(i),requestNo:s,pageNum:1,pageSize:15,phone:d},l={"Content-Type":"application/json;charset=UTF-8",secret:H(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)l["X-Forwarded-For"]=n.xForwardedFor;let I=n.extraHeaders&&typeof n.extraHeaders==="object"?{...l,...n.extraHeaders}:l,h=`${K()}/api/history/`;try{let g=await fetch(h,{method:"POST",headers:I,body:JSON.stringify(b)}),S=await g.text(),E=k(S),f=z(E,{}),T=f.resultCode,v=typeof T==="number"?T:typeof T==="string"?Number(T):NaN,N=typeof f.message==="string"&&f.message.length>0?f.message:"IWINV SMS history query failed";if(!g.ok||v!==0)return y.fail(new y.KMsgError(y.KMsgErrorCode.PROVIDER_ERROR,N,{providerId:t,originalCode:T??g.status}));let D=f.list,C=Array.isArray(D)?D:[];if(C.length===0)return y.ok(null);let A=(()=>{return C.find(($)=>{if(!O($))return!1;let P=$.requestNo;return P!==void 0&&P!==null?String(P)===s:!1})??C[0]})();if(!O(A))return y.ok(null);let q=typeof A.sendStatusCode==="string"?A.sendStatusCode:void 0,F=typeof A.sendStatusMsg==="string"?A.sendStatusMsg:typeof A.sendStatus==="string"?A.sendStatus:void 0,W=B(A.sendDate),R=Ae(q,F);return y.ok({providerId:t,providerMessageId:s,status:R,statusCode:q,statusMessage:F,sentAt:W,deliveredAt:R==="DELIVERED"?W:void 0,failedAt:R==="FAILED"?W:void 0,raw:A})}catch(g){return y.fail(new y.KMsgError(y.KMsgErrorCode.NETWORK_ERROR,g instanceof Error?g.message:String(g),{providerId:t}))}}var o=require("@k-msg/core");var x=require("@k-msg/core");function Oe(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 be(e){switch(Oe(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 xe(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 x.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 x.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 x.fail(new x.KMsgError(x.KMsgErrorCode.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"media.image.ref"}))}let d=n.imageUrl;if(typeof d==="string"&&d.trim().length>0)return x.fail(new x.KMsgError(x.KMsgErrorCode.INVALID_REQUEST,"IWINV MMS caller must provide blob/bytes in options.media.image",{providerId:t,field:"imageUrl"}));return x.ok(void 0)}async function ke(e){if("blob"in e){let d=e.contentType||e.blob.type||"application/octet-stream",u=e.filename||"image",i=e.contentType&&e.contentType!==e.blob.type?new Blob([await e.blob.arrayBuffer()],{type:d}):e.blob;return{blob:i,filename:u,contentType:d,size:i.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 _e(e){if(Oe(e.filename).length>0)return e.filename;let n=be(e.filename)==="image/png"?".png":be(e.filename)==="image/gif"?".gif":be(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 Me(e){let{providerId:t,config:n,options:r}=e,s=r.templateId;if(!s||s.length===0)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"templateId is required for ALIMTALK",{providerId:t}));let d=r.options?.scheduledAt,u=d instanceof Date&&!Number.isNaN(d.getTime()),i=u?"Y":"N",a=u?X(d):void 0,m=U(r.to);if(!m)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let b=r.providerOptions?.templateParam,w=Array.isArray(b)?b.map((R)=>R===null||R===void 0?"":String(R)):Object.values(r.variables||{}).map((R)=>R===null||R===void 0?"":String(R)),l=r.failover,I=(typeof r.from==="string"&&r.from.length>0?r.from:n.senderNumber||n.smsSenderNumber)||"",h=I?U(I):"",g=typeof r.providerOptions?.reSend==="string"?r.providerOptions.reSend.trim().toUpperCase():"",S=g==="Y"||g==="N"?g:void 0,E=l?.enabled===!0?"Y":l?.enabled===!1?"N":void 0,f=S??E??(h?"Y":"N"),v=(typeof r.providerOptions?.resendCallback==="string"?U(r.providerOptions.resendCallback):"")||h;if(f==="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 N=typeof r.providerOptions?.resendType==="string"?r.providerOptions.resendType.trim().toUpperCase():"",D=N==="Y"||N==="N"?N:void 0;if(typeof r.providerOptions?.resendType==="string"&&r.providerOptions.resendType.length>0&&!D)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"resendType must be 'Y' or 'N'",{providerId:t}));let C=l?.fallbackChannel==="lms"?"Y":l?.fallbackChannel==="sms"?"N":void 0,A=typeof r.providerOptions?.resendTitle==="string"&&r.providerOptions.resendTitle.trim().length>0?r.providerOptions.resendTitle.trim():typeof l?.fallbackTitle==="string"&&l.fallbackTitle.trim().length>0?l.fallbackTitle.trim():void 0,q=typeof r.providerOptions?.resendContent==="string"&&r.providerOptions.resendContent.trim().length>0?r.providerOptions.resendContent.trim():typeof l?.fallbackContent==="string"&&l.fallbackContent.trim().length>0?l.fallbackContent.trim():void 0,F={templateCode:s,reserve:i,...a?{sendDate:a}:{},list:[{phone:m,templateParam:w.length>0?w:void 0}],reSend:f,...v?{resendCallback:v}:{},...D??C?{resendType:D??C}:{},...A?{resendTitle:A}:{},...q?{resendContent:q}:{}},W=`${n.baseUrl}${Te(n)}`;try{let R=await fetch(W,{method:"POST",headers:_(n),body:JSON.stringify(F)}),ae=await R.text(),$=k(ae),P=O($)?$:{code:V($)??R.status,message:ae||String($||"")};if(!R.ok||P.code!==200)return o.fail(new o.KMsgError(M(P.code),P.message||"IWINV send failed",{providerId:t,originalCode:P.code}));return o.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:typeof P.seqNo==="number"?String(P.seqNo):void 0,status:u?"PENDING":"SENT",type:r.type,to:r.to,raw:P})}catch(R){return o.fail(new o.KMsgError(o.KMsgErrorCode.NETWORK_ERROR,R instanceof Error?R.message:String(R),{providerId:t}))}}async function $e(e){let{providerId:t,config:n,options:r,to:s,from:d,text:u,scheduledAtValid:i,scheduledAt:a}=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 m=Ie(u,r.subject),b=xe(r,t);if(b.isFailure)return b;let w=b.value;if(!w)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 l;try{l=await ke(w)}catch(f){return o.fail(f instanceof o.KMsgError?f:new o.KMsgError(o.KMsgErrorCode.NETWORK_ERROR,f instanceof Error?f.message:String(f),{providerId:t}))}if(l.size>102400)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"MMS image must be <= 100KB",{providerId:t,bytes:l.size}));let I=new FormData;if(I.append("version","1.0"),I.append("from",d),I.append("to",s),I.append("title",m),I.append("text",u),i&&a)I.append("date",ue(a));I.append("image",l.blob,_e(l));let g={secret:H(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)g["X-Forwarded-For"]=n.xForwardedFor;let S={...g};if(n.extraHeaders&&typeof n.extraHeaders==="object")for(let[f,T]of Object.entries(n.extraHeaders)){if(f.toLowerCase()==="content-type")continue;S[f]=T}let E=`${K()}/api/v2/send/`;try{let f=await fetch(E,{method:"POST",headers:S,body:I}),T=await f.text(),v=k(T),N=O(v)?v:{resultCode:v},D=N.resultCode??N.code,C=fe(D),A=typeof N.message==="string"&&N.message.length>0?N.message:ge(C,"MMS send failed");if(!(f.ok&&C==="0"))return o.fail(new o.KMsgError(ye(C,f.ok),A,{providerId:t,originalCode:D}));let F=typeof N.requestNo==="string"&&N.requestNo.length>0?N.requestNo:typeof N.msgid==="string"&&N.msgid.length>0?N.msgid:void 0;return o.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:F,status:i?"PENDING":"SENT",type:r.type,to:r.to,raw:N})}catch(f){return o.fail(new o.KMsgError(o.KMsgErrorCode.NETWORK_ERROR,f instanceof Error?f.message:String(f),{providerId:t}))}}async function Pe(e){let{providerId:t,config:n,options:r}=e;if(!Q(n))return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"SMS v2 configuration missing (smsApiKey/smsAuthKey)",{providerId:t}));let s=U(r.to);if(!s)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"to is required",{providerId:t}));let d=r.text;if(!d||d.trim().length===0)return o.fail(new o.KMsgError(o.KMsgErrorCode.INVALID_REQUEST,"text is required for SMS/LMS/MMS",{providerId:t}));let u=(typeof r.from==="string"&&r.from.length>0?r.from:n.smsSenderNumber||n.senderNumber)||"",i=u?U(u):"";if(!i)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 a=r.options?.scheduledAt,m=a instanceof Date&&!Number.isNaN(a.getTime());if(r.type==="MMS")return await $e({providerId:t,config:n,options:r,to:s,from:i,text:d,scheduledAtValid:m,scheduledAt:m?a:void 0});let b={version:"1.0",from:i,to:[s],text:d};if(r.type==="LMS")b.title=Ie(d,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(m)b.date=ue(a);let l={"Content-Type":"application/json;charset=UTF-8",secret:H(n)};if(typeof n.xForwardedFor==="string"&&n.xForwardedFor.length>0)l["X-Forwarded-For"]=n.xForwardedFor;let I=n.extraHeaders&&typeof n.extraHeaders==="object"?{...l,...n.extraHeaders}:l,h=`${K()}/api/v2/send/`;try{let g=await fetch(h,{method:"POST",headers:I,body:JSON.stringify(b)}),S=await g.text(),E=k(S),f=O(E)?E:{resultCode:E},T=f.resultCode??f.code,v=fe(T),N=typeof f.message==="string"&&f.message.length>0?f.message:ge(v,"SMS send failed");if(!(g.ok&&v==="0"))return o.fail(new o.KMsgError(ye(v,g.ok),N,{providerId:t,originalCode:T}));let C=typeof f.requestNo==="string"&&f.requestNo.length>0?f.requestNo:typeof f.msgid==="string"&&f.msgid.length>0?f.msgid:void 0;return o.ok({messageId:r.messageId||crypto.randomUUID(),providerId:t,providerMessageId:C,status:m?"PENDING":"SENT",type:r.type,to:r.to,raw:f})}catch(g){return o.fail(new o.KMsgError(o.KMsgErrorCode.NETWORK_ERROR,g instanceof Error?g.message:String(g),{providerId:t}))}}function Be(e){return{...e,baseUrl:te,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}function Se(){return{apiKey:c.readRuntimeEnv("IWINV_API_KEY")||"",smsApiKey:c.readRuntimeEnv("IWINV_SMS_API_KEY"),smsAuthKey:c.readRuntimeEnv("IWINV_SMS_AUTH_KEY"),smsCompanyId:c.readRuntimeEnv("IWINV_SMS_COMPANY_ID"),senderNumber:c.readRuntimeEnv("IWINV_SENDER_NUMBER")||c.readRuntimeEnv("IWINV_SMS_SENDER_NUMBER"),smsSenderNumber:c.readRuntimeEnv("IWINV_SMS_SENDER_NUMBER"),sendEndpoint:c.readRuntimeEnv("IWINV_SEND_ENDPOINT")||"/api/v2/send/",xForwardedFor:c.readRuntimeEnv("IWINV_X_FORWARDED_FOR"),debug:c.readRuntimeEnv("NODE_ENV")==="development"}}class ie{id="iwinv";name="IWINV Messaging Provider";supportedTypes;config;getOnboardingSpec(){let e=ve(this.id);if(!e)throw new c.KMsgError(c.KMsgErrorCode.INVALID_REQUEST,`Onboarding spec missing for provider: ${this.id}`,{providerId:this.id});return e}constructor(e){if(!e||typeof e!=="object")throw new c.KMsgError(c.KMsgErrorCode.INVALID_REQUEST,"IWINVProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new c.KMsgError(c.KMsgErrorCode.INVALID_REQUEST,"IWINVProvider requires `apiKey` configuration",{providerId:this.id});this.config=Be(e);let t=["ALIMTALK"];if(Q(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(Q(this.config))try{new URL(K())}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:K()}}}catch(n){return t.push(n instanceof Error?n.message:String(n)),{healthy:!1,issues:t,latencyMs:Date.now()-e}}}async send(e){let t=e.messageId||crypto.randomUUID(),n={...e,messageId:t};switch(n.type){case"ALIMTALK":return Me({providerId:this.id,config:this.config,options:n});case"SMS":case"LMS":case"MMS":return Pe({providerId:this.id,config:this.config,options:n});default:return c.fail(new c.KMsgError(c.KMsgErrorCode.INVALID_REQUEST,`IWINVProvider does not support type ${n.type}`,{providerId:this.id,type:n.type}))}}async getDeliveryStatus(e){switch(e.type){case"ALIMTALK":return De({providerId:this.id,config:this.config,query:e});case"SMS":case"LMS":case"MMS":return Ce({providerId:this.id,config:this.config,query:e});default:return c.fail(new c.KMsgError(c.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 c.fail(new c.KMsgError(c.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:_(this.config),body:JSON.stringify({})}),r=await n.text(),s=k(r),d=z(s,{}),u=d.code,i=typeof u==="string"?Number(u):void 0,a=typeof u==="number"?u:typeof i==="number"&&Number.isFinite(i)?i:void 0,m=typeof d.message==="string"&&d.message.length>0?d.message:"IWINV AlimTalk charge query failed";if(!n.ok||a!==200)return c.fail(new c.KMsgError(M(a??n.status),m,{providerId:this.id,originalCode:u??n.status}));let b=d.charge,w=typeof b==="number"?b:typeof b==="string"?Number(b):NaN;if(!Number.isFinite(w))return c.fail(new c.KMsgError(c.KMsgErrorCode.PROVIDER_ERROR,"Invalid charge value from IWINV AlimTalk charge API",{providerId:this.id,raw:d}));return c.ok({providerId:this.id,channel:e,amount:w,currency:"KRW",raw:d})}catch(n){return c.fail(new c.KMsgError(c.KMsgErrorCode.NETWORK_ERROR,n instanceof Error?n.message:String(n),{providerId:this.id}))}}async getSmsBalance(e){if(!this.config.smsApiKey||!this.config.smsAuthKey)return c.fail(new c.KMsgError(c.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=`${K()}/api/charge/`;try{let d=await fetch(s,{method:"POST",headers:r,body:JSON.stringify({version:"1.0"})}),u=await d.text(),i=k(u),a=z(i,{}),m=a.code??a.resultCode,b=typeof m==="string"?Number(m):void 0,w=typeof m==="number"?m:typeof b==="number"&&Number.isFinite(b)?b:NaN,l=typeof a.message==="string"&&a.message.length>0?a.message:"IWINV SMS charge query failed";if(!d.ok||w!==0)return c.fail(new c.KMsgError(c.KMsgErrorCode.PROVIDER_ERROR,l,{providerId:this.id,originalCode:m??d.status}));let I=a.charge,h=typeof I==="number"?I:typeof I==="string"?Number(I):NaN;if(!Number.isFinite(h))return c.fail(new c.KMsgError(c.KMsgErrorCode.PROVIDER_ERROR,"Invalid charge value from IWINV SMS charge API",{providerId:this.id,raw:a}));return c.ok({providerId:this.id,channel:e,amount:h,currency:"KRW",raw:a})}catch(d){return c.fail(new c.KMsgError(c.KMsgErrorCode.NETWORK_ERROR,d instanceof Error?d.message:String(d),{providerId:this.id}))}}}var Ft=(e)=>new ie(e),Qe=()=>{let e=Se();if(!e.apiKey)throw new c.KMsgError(c.KMsgErrorCode.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new ie(e)};class We{static create(e){return new ie(e)}static createDefault(){return Qe()}}function je(e){return{...e,baseUrl:te,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}class ee{id="iwinv";config;constructor(e){if(!e||typeof e!=="object")throw new J.KMsgError(J.KMsgErrorCode.INVALID_REQUEST,"IWINVTemplateProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new J.KMsgError(J.KMsgErrorCode.INVALID_REQUEST,"IWINVTemplateProvider requires `apiKey` configuration",{providerId:this.id});this.config=je(e)}async createTemplate(e){return ne({providerId:this.id,config:this.config,input:e})}async updateTemplate(e,t,n){return re({providerId:this.id,config:this.config,code:e,patch:t,ctx:n})}async deleteTemplate(e){return se({providerId:this.id,config:this.config,code:e})}async getTemplate(e,t){return j({providerId:this.id,config:this.config,code:e,ctx:t})}async listTemplates(e,t){return oe({providerId:this.id,config:this.config,query:e,ctx:t})}}var Ye=(e)=>new ee(e),Ve=()=>{let e=Se();return new ee(e)};class Fe{static create(e){return new ee(e)}static createDefault(){return Ve()}}
2
+
3
+ //# debugId=3F055302FDE0283664756E2164756E21
4
+ //# sourceMappingURL=template.js.map