@k-msg/provider 0.27.1 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aligo/aligo.helpers.d.ts +9 -24
- package/dist/aligo/aligo.shared.helpers.d.ts +22 -0
- package/dist/aligo/aligo.template.helpers.d.ts +2 -0
- package/dist/aligo/index.js +3 -3
- package/dist/aligo/index.mjs +3 -3
- package/dist/aligo/provider.d.ts +3 -28
- package/dist/aligo/provider.send.d.ts +38 -0
- package/dist/aligo/provider.template.d.ts +26 -0
- package/dist/aligo/send.d.ts +5 -0
- package/dist/aligo/send.js +5 -0
- package/dist/aligo/send.mjs +5 -0
- package/dist/aligo/template.d.ts +6 -0
- package/dist/aligo/template.js +5 -0
- package/dist/aligo/template.mjs +5 -0
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/dist/iwinv/index.js +2 -2
- package/dist/iwinv/index.mjs +2 -2
- package/dist/iwinv/provider.d.ts +3 -14
- package/dist/iwinv/provider.send.d.ts +24 -0
- package/dist/iwinv/send.d.ts +5 -0
- package/dist/iwinv/send.js +4 -0
- package/dist/iwinv/send.mjs +4 -0
- package/dist/iwinv/template.d.ts +24 -0
- package/dist/iwinv/template.js +4 -0
- package/dist/iwinv/template.mjs +4 -0
- package/package.json +25 -5
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{KMsgError as Ye,KMsgErrorCode as Je}from"@k-msg/core";var pe="https://alimtalk.bizservice.iwinv.kr",Ce="https://sms.bizservice.iwinv.kr";import{fail as h,KMsgError as A,KMsgErrorCode as U,ok as ie}from"@k-msg/core";import{validateTemplatePayload as ke}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 Ge(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 re(e){return Ge(new TextEncoder().encode(e))}function Oe(e){let t=e.sendEndpoint||"/api/v2/send/";return t.startsWith("/")?t:`/${t}`}function P(e){let n={AUTH:re(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 xe(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 me(e){switch(typeof e==="string"?e.trim().toUpperCase():""){case"Y":return"APPROVED";case"I":return"INSPECTION";case"R":return"REJECTED";default:return"PENDING"}}function fe(e,t){return new Date(e.getTime()+t*24*60*60*1000)}function ge(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 se(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 ye(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 ae(e){let t=await e.text(),n=M(t);return Y(n,{code:L(n)??e.status,message:t||String(n||"")})}function _e(e,t){return new A(e.code,e.message,{providerId:t,...e.details??{}})}async function Ie(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=ke(r,{requireName:!0,requireContent:!0});if(s.isFailure)return h(_e(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 ae(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 ie({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 be(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 oe({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(_e(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 ae(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 oe({providerId:t,config:n,code:p,ctx:a});if(b.isSuccess)return b;return ie({...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 Se(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 ae(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 ie(void 0)}catch(o){return h(new A(U.NETWORK_ERROR,o instanceof Error?o.message:String(o),{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={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 ae(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 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=me(m.status),b=Z(m.createDate)??new Date;return ie({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 Ne(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=xe(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 ae(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:"",T=typeof g.templateContent==="string"?g.templateContent:"",y=me(g.status),D=Z(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 ie(u)}catch(c){return h(new A(U.NETWORK_ERROR,c instanceof Error?c.message:String(c),{providerId:t}))}}import{fail as $,KMsgError as k,KMsgErrorCode as _,ok as je,readRuntimeEnv as B}from"@k-msg/core";var Me={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 Pe(e){return Me[e]}function wt(){return Object.values(Me)}import{fail as K,KMsgError as q,KMsgErrorCode as H,ok as ne}from"@k-msg/core";import{KMsgErrorCode as de}from"@k-msg/core";function Q(e){return e.replace(/[^0-9]/g,"")}function W(){return Ce}function G(e){if(e.smsApiKey&&e.smsAuthKey)return re(`${e.smsApiKey}&${e.smsAuthKey}`);let t=e.smsAuthKey||e.smsApiKey;if(!t)return"";return re(`${e.apiKey}&${t}`)}function ee(e){return G(e).length>0}function we(e){if(typeof e==="number"&&Number.isFinite(e))return e.toString();if(typeof e==="string")return e.trim();return""}function Te(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 Ee(e,t){if(e==="14"||e==="15"||e==="202"||e==="206")return de.AUTHENTICATION_FAILED;if(e==="50")return de.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 de.INVALID_REQUEST;if(!t)return de.NETWORK_ERROR;return de.PROVIDER_ERROR}function Re(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=se(fe(r.requestedAt,-1)),c=se(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=M(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 K(new q(V(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,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=fe(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:ge(p),endDate:ge(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=`${W()}/api/history/`;try{let u=await fetch(w,{method:"POST",headers:m,body:JSON.stringify(f)}),g=await u.text(),S=M(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 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 Ae}from"@k-msg/core";import{fail as Ue,KMsgError as Ke,KMsgErrorCode as qe,ok as he}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 ve(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 he({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 he({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 he(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=ve(e.filename)==="image/png"?".png":ve(e.filename)==="image/gif"?".gif":ve(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?se(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)||"",w=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??(w?"Y":"N"),T=(typeof r.providerOptions?.resendCallback==="string"?Q(r.providerOptions.resendCallback):"")||w;if(l==="Y"&&!T)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,...T?{resendCallback:T}:{},...D??C?{resendType:D??C}:{},...E?{resendTitle:E}:{},...j?{resendContent:j}:{}},te=`${n.baseUrl}${Oe(n)}`;try{let N=await fetch(te,{method:"POST",headers:P(n),body:JSON.stringify(z)}),ue=await N.text(),X=M(ue),F=x(X)?X:{code:L(X)??N.status,message:ue||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 Ae({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 Xe(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=Re(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",ye(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(),T=M(b),y=x(T)?T:{resultCode:T},D=y.resultCode??y.code,C=we(D),E=typeof y.message==="string"&&y.message.length>0?y.message:Te(C,"MMS send failed");if(!(l.ok&&C==="0"))return v(new R(Ee(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 Ae({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 Xe({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=Re(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=ye(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=`${W()}/api/v2/send/`;try{let u=await fetch(w,{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,T=we(b),y=typeof l.message==="string"&&l.message.length>0?l.message:Te(T,"SMS send failed");if(!(u.ok&&T==="0"))return v(new R(Ee(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 Ae({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 Ze(e){return{...e,baseUrl:pe,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}function De(){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 ce{id="iwinv";name="IWINV Messaging Provider";supportedTypes;config;getOnboardingSpec(){let e=Pe(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=Ze(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 k(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,w=typeof m==="number"?m:typeof m==="string"?Number(m):NaN;if(!Number.isFinite(w))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:w,currency:"KRW",raw:i})}catch(a){return $(new k(_.NETWORK_ERROR,a instanceof Error?a.message:String(a),{providerId:this.id}))}}}var Xt=(e)=>new ce(e),et=()=>{let e=De();if(!e.apiKey)throw new k(_.INVALID_REQUEST,"IWINV_API_KEY environment variable is required",{providerId:"iwinv"});return new ce(e)};class tt{static create(e){return new ce(e)}static createDefault(){return et()}}function nt(e){return{...e,baseUrl:pe,sendEndpoint:e.sendEndpoint||"/api/v2/send/"}}class le{id="iwinv";config;constructor(e){if(!e||typeof e!=="object")throw new Ye(Je.INVALID_REQUEST,"IWINVTemplateProvider requires a config object",{providerId:this.id});if(!e.apiKey||e.apiKey.length===0)throw new Ye(Je.INVALID_REQUEST,"IWINVTemplateProvider requires `apiKey` configuration",{providerId:this.id});this.config=nt(e)}async createTemplate(e){return Ie({providerId:this.id,config:this.config,input:e})}async updateTemplate(e,t,n){return be({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 oe({providerId:this.id,config:this.config,code:e,ctx:t})}async listTemplates(e,t){return Ne({providerId:this.id,config:this.config,query:e,ctx:t})}}var sn=(e)=>new le(e),rt=()=>{let e=De();return new le(e)};class st{static create(e){return new le(e)}static createDefault(){return rt()}}export{be as updateTemplate,Ne as listTemplates,oe as getTemplate,Se as deleteTemplate,Ie as createTemplate,sn as createIWINVTemplateProvider,rt as createDefaultIWINVTemplateProvider,st as IWINVTemplateProviderFactory,le as IWINVTemplateProvider};
|
|
2
|
+
|
|
3
|
+
//# debugId=B5D54A4A417ABEDE64756E2164756E21
|
|
4
|
+
//# sourceMappingURL=template.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k-msg/provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"packageManager": "bun@1.3.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Complete provider system with adapters and implementations for K-Message platform",
|
|
@@ -19,11 +19,31 @@
|
|
|
19
19
|
"import": "./dist/aligo/index.mjs",
|
|
20
20
|
"require": "./dist/aligo/index.js"
|
|
21
21
|
},
|
|
22
|
+
"./aligo/send": {
|
|
23
|
+
"types": "./dist/aligo/send.d.ts",
|
|
24
|
+
"import": "./dist/aligo/send.mjs",
|
|
25
|
+
"require": "./dist/aligo/send.js"
|
|
26
|
+
},
|
|
27
|
+
"./aligo/template": {
|
|
28
|
+
"types": "./dist/aligo/template.d.ts",
|
|
29
|
+
"import": "./dist/aligo/template.mjs",
|
|
30
|
+
"require": "./dist/aligo/template.js"
|
|
31
|
+
},
|
|
22
32
|
"./iwinv": {
|
|
23
33
|
"types": "./dist/iwinv/index.d.ts",
|
|
24
34
|
"import": "./dist/iwinv/index.mjs",
|
|
25
35
|
"require": "./dist/iwinv/index.js"
|
|
26
36
|
},
|
|
37
|
+
"./iwinv/send": {
|
|
38
|
+
"types": "./dist/iwinv/send.d.ts",
|
|
39
|
+
"import": "./dist/iwinv/send.mjs",
|
|
40
|
+
"require": "./dist/iwinv/send.js"
|
|
41
|
+
},
|
|
42
|
+
"./iwinv/template": {
|
|
43
|
+
"types": "./dist/iwinv/template.d.ts",
|
|
44
|
+
"import": "./dist/iwinv/template.mjs",
|
|
45
|
+
"require": "./dist/iwinv/template.js"
|
|
46
|
+
},
|
|
27
47
|
"./solapi": {
|
|
28
48
|
"types": "./dist/solapi/index.d.ts",
|
|
29
49
|
"import": "./dist/solapi/index.mjs",
|
|
@@ -35,8 +55,8 @@
|
|
|
35
55
|
},
|
|
36
56
|
"scripts": {
|
|
37
57
|
"build": "bun run clean && bun run build:esm && bun run build:cjs && bun run build:types",
|
|
38
|
-
"build:esm": "bun build ./src/index.ts ./src/aligo/index.ts ./src/iwinv/index.ts ./src/solapi/index.ts --outdir ./dist --format esm --minify --sourcemap --entry-naming '[dir]/[name].mjs' --external 'bun:test' --external 'solapi' --external '@k-msg/*'",
|
|
39
|
-
"build:cjs": "bun build ./src/index.ts ./src/aligo/index.ts ./src/iwinv/index.ts ./src/solapi/index.ts --outdir ./dist --format cjs --minify --sourcemap --entry-naming '[dir]/[name].js' --external 'bun:test' --external 'solapi' --external '@k-msg/*'",
|
|
58
|
+
"build:esm": "bun build ./src/index.ts ./src/aligo/index.ts ./src/aligo/send.ts ./src/aligo/template.ts ./src/iwinv/index.ts ./src/iwinv/send.ts ./src/iwinv/template.ts ./src/solapi/index.ts --outdir ./dist --format esm --minify --sourcemap --entry-naming '[dir]/[name].mjs' --external 'bun:test' --external 'solapi' --external '@k-msg/*'",
|
|
59
|
+
"build:cjs": "bun build ./src/index.ts ./src/aligo/index.ts ./src/aligo/send.ts ./src/aligo/template.ts ./src/iwinv/index.ts ./src/iwinv/send.ts ./src/iwinv/template.ts ./src/solapi/index.ts --outdir ./dist --format cjs --minify --sourcemap --entry-naming '[dir]/[name].js' --external 'bun:test' --external 'solapi' --external '@k-msg/*'",
|
|
40
60
|
"build:types": "tsc",
|
|
41
61
|
"dev": "tsc --watch",
|
|
42
62
|
"test": "bun run test:unit",
|
|
@@ -51,8 +71,8 @@
|
|
|
51
71
|
"publish": "bun publish --access public"
|
|
52
72
|
},
|
|
53
73
|
"dependencies": {
|
|
54
|
-
"@k-msg/core": "0.
|
|
55
|
-
"@k-msg/template": "0.
|
|
74
|
+
"@k-msg/core": "0.28.0",
|
|
75
|
+
"@k-msg/template": "0.28.0"
|
|
56
76
|
},
|
|
57
77
|
"devDependencies": {
|
|
58
78
|
"@types/bun": "^1.3.9",
|