@k-msg/webhook 0.29.5 → 0.29.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +16 -16
- package/dist/index.mjs +16 -16
- package/dist/toolkit/index.js +2 -2
- package/dist/toolkit/index.mjs +2 -2
- package/package.json +3 -3
package/dist/toolkit/index.js
CHANGED
|
@@ -45,8 +45,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
45
45
|
`;await n.ensureDirForFile(this.config.filePath),await n.appendFile(this.config.filePath,$)}catch(n){this.emit("appendError",n)}}async loadFromFile(){if(!this.config.filePath)return;try{let $=(await L(this.config.fileAdapter).readFile(this.config.filePath)).trim().split(`
|
|
46
46
|
`).filter((o)=>o.trim());for(let o of $)try{let i=JSON.parse(o),t={...i,timestamp:new Date(i.timestamp)};this.events.set(t.id,t),this.addToIndexes(t)}catch(i){this.emit("parseError",{line:o,error:i})}this.emit("dataLoaded",{filePath:this.config.filePath,eventCount:this.events.size})}catch(r){if(!d(r))this.emit("loadError",r)}}async saveToFile(){if(!this.config.filePath)return;try{let r=L(this.config.fileAdapter),n=Array.from(this.events.values()).map(($)=>JSON.stringify($)).join(`
|
|
47
47
|
`);await r.ensureDirForFile(this.config.filePath),await r.writeFile(this.config.filePath,n+`
|
|
48
|
-
`),this.emit("dataSaved",{filePath:this.config.filePath,eventCount:this.events.size})}catch(r){throw this.emit("saveError",r),r}}async shutdown(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;if(this.config.type==="file")await this.saveToFile().catch((r)=>{this.emit("saveError",r)});this.emit("shutdown",{eventCount:this.events.size})}}class rn{config;constructor(r){this.config={maxRetries:r.maxRetries,baseDelayMs:r.retryDelayMs,maxDelayMs:r.maxDelayMs||300000,backoffMultiplier:r.backoffMultiplier||2,jitter:r.jitter!==!1}}calculateNextRetry(r){if(r>=this.config.maxRetries)throw Error(`Maximum retry attempts (${this.config.maxRetries}) exceeded`);let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;if(n=Math.min(n,this.config.maxDelayMs),this.config.jitter)n=n*(0.5+Math.random()*0.5);return new Date(Date.now()+n)}shouldRetry(r,n){if(r>=this.config.maxRetries)return!1;if(n)return this.isRetryableError(n);return!0}isRetryableError(r){let n=r.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused","socket hang up"].some((o)=>n.includes(o))}shouldRetryStatus(r){if(r>=400&&r<500)return[408,429].includes(r);if(r>=500)return!0;return!1}calculateRetryStats(r){if(r.length===0)return{totalAttempts:0,successfulAttempts:0,failedAttempts:0,averageDelayMs:0,totalTimeMs:0};let n=r.filter((u)=>u.success).length,$=r.length-n,o=0;for(let u=1;u<r.length;u++)o+=r[u].timestamp.getTime()-r[u-1].timestamp.getTime();let i=r.length>1?o/(r.length-1):0,t=r.length>0?r[r.length-1].timestamp.getTime()-r[0].timestamp.getTime():0;return{totalAttempts:r.length,successfulAttempts:n,failedAttempts:$,averageDelayMs:i,totalTimeMs:t}}updateConfig(r){this.config={...this.config,...r}}getConfig(){return{...this.config}}getBackoffDelay(r){let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;return Math.min(n,this.config.maxDelayMs)}}var Nv;((x)=>{x.INVALID_REQUEST="INVALID_REQUEST";x.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";x.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";x.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";x.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";x.NETWORK_ERROR="NETWORK_ERROR";x.NETWORK_TIMEOUT="NETWORK_TIMEOUT";x.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";x.PROVIDER_ERROR="PROVIDER_ERROR";x.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";x.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";x.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";x.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";x.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";x.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";x.UNKNOWN_ERROR="UNKNOWN_ERROR"})(Nv||={});var Z6={["INVALID_REQUEST"]:{ko:"잘못된 요청입니다",en:"Invalid request"},["AUTHENTICATION_FAILED"]:{ko:"인증에 실패했습니다",en:"Authentication failed"},["INSUFFICIENT_BALANCE"]:{ko:"잔액이 부족합니다",en:"Insufficient balance"},["TEMPLATE_NOT_FOUND"]:{ko:"템플릿을 찾을 수 없습니다",en:"Template not found"},["RATE_LIMIT_EXCEEDED"]:{ko:"요청 한도를 초과했습니다",en:"Rate limit exceeded"},["NETWORK_ERROR"]:{ko:"네트워크 오류가 발생했습니다",en:"Network error"},["NETWORK_TIMEOUT"]:{ko:"네트워크 요청 시간이 초과되었습니다",en:"Network timeout"},["NETWORK_SERVICE_UNAVAILABLE"]:{ko:"서비스를 일시적으로 사용할 수 없습니다",en:"Service temporarily unavailable"},["PROVIDER_ERROR"]:{ko:"제공자 오류가 발생했습니다",en:"Provider error"},["MESSAGE_SEND_FAILED"]:{ko:"메시지 전송에 실패했습니다",en:"Message send failed"},["CRYPTO_CONFIG_ERROR"]:{ko:"암호화 설정 오류가 발생했습니다",en:"Crypto configuration error"},["CRYPTO_ENCRYPT_FAILED"]:{ko:"암호화에 실패했습니다",en:"Encryption failed"},["CRYPTO_DECRYPT_FAILED"]:{ko:"복호화에 실패했습니다",en:"Decryption failed"},["CRYPTO_HASH_FAILED"]:{ko:"해시 생성에 실패했습니다",en:"Hash generation failed"},["CRYPTO_POLICY_VIOLATION"]:{ko:"암호화 정책 위반이 발생했습니다",en:"Crypto policy violation"},["UNKNOWN_ERROR"]:{ko:"알 수 없는 오류가 발생했습니다",en:"Unknown error"}},l_=new Set(Object.values(Nv));var Ov=(r)=>{if(typeof r!=="number"||Number.isNaN(r)||!Number.isFinite(r))return;return Math.trunc(r)};class Mn extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(r,n,$,o={}){super(n);if(this.name="KMsgError",this.code=r,this.details=$,this.providerErrorCode=o.providerErrorCode,this.providerErrorText=o.providerErrorText,this.httpStatus=Ov(o.httpStatus),this.requestId=typeof o.requestId==="string"?o.requestId:void 0,this.retryAfterMs=Ov(o.retryAfterMs),this.attempt=Ov(o.attempt),Array.isArray(o.causeChain))this.causeChain=o.causeChain;else if(o.causeChain!==void 0)this.causeChain=[o.causeChain];if(Error.captureStackTrace)Error.captureStackTrace(this,Mn)}getLocalizedMessage(r="ko"){let n=Z6[this.code];if(n?.[r])return n[r];return this.message}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,providerErrorCode:this.providerErrorCode,providerErrorText:this.providerErrorText,httpStatus:this.httpStatus,requestId:this.requestId,retryAfterMs:this.retryAfterMs,attempt:this.attempt,causeChain:this.causeChain}}}function f6(r){switch(r){case"config":return"CRYPTO_CONFIG_ERROR";case"encrypt":return"CRYPTO_ENCRYPT_FAILED";case"decrypt":return"CRYPTO_DECRYPT_FAILED";case"hash":return"CRYPTO_HASH_FAILED";case"policy":return"CRYPTO_POLICY_VIOLATION"}}class Xr extends Mn{kind;fieldPath;failMode;openFallback;constructor(r,n,$,o={}){super(f6(r),n,$,o);this.name="FieldCryptoError",this.kind=r,this.fieldPath=typeof o.fieldPath==="string"?o.fieldPath:void 0,this.failMode=o.failMode,this.openFallback=o.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}function zv(r){return typeof r==="function"}function Kg(r){if(typeof r!=="string")return;let n=r.trim();return n.length>0?n:void 0}function xg(r,n,$){let o=r.fields[n];if(o)return o;if(n.startsWith("metadata.")){let i=r.fields["metadata.*"];if(i)return i}return $}function H6(r,n={}){let $=[];if(!r||typeof r!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!r.provider||typeof r.provider!=="object")$.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!zv(r.provider.encrypt))$.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!zv(r.provider.decrypt))$.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!zv(r.provider.hash))$.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!r.fields||typeof r.fields!=="object")$.push({message:"fieldCrypto.fields must be an object",rule:"fieldCrypto.fields.object",path:"fields",hint:"Define policies such as to, from, metadata.phoneNumber"});else{let t=Object.entries(r.fields);if(t.length===0)$.push({message:"fieldCrypto.fields must not be empty",rule:"fieldCrypto.fields.non_empty",path:"fields",hint:"Add at least one field mode mapping"});for(let[u,v]of t){if(!Kg(u))$.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(v!=="plain"&&v!=="encrypt"&&v!=="encrypt+hash"&&v!=="mask")$.push({message:`unsupported field mode: ${String(v)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${u}`})}}let o=r.failMode??"closed",i=r.openFallback??"masked";if(o==="open"&&i==="plaintext"&&r.unsafeAllowPlaintextStorage!==!0)$.push({message:"openFallback=plaintext requires unsafeAllowPlaintextStorage=true",rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback",hint:"Use masked/null fallback, or explicitly enable unsafe plaintext"});if(Array.isArray(r.aadFields)){if(r.aadFields.length===0)$.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let t=0;t<r.aadFields.length;t+=1){let u=r.aadFields[t];if(!Kg(u))$.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${t}]`})}}if(n.secureMode&&!n.compatPlainColumns){let t=xg(r,"to","encrypt+hash"),u=xg(r,"from","encrypt+hash");if(t==="plain")$.push({message:"secure mode requires non-plain policy for `to` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.to_non_plain",path:"fields.to",hint:"Use encrypt+hash for lookup fields"});if(u==="plain")$.push({message:"secure mode requires non-plain policy for `from` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.from_non_plain",path:"fields.from",hint:"Use encrypt+hash for lookup fields"})}return{valid:$.length===0,issues:$}}function jv(r,n={}){let $=H6(r,n);if($.valid)return;let o=$.issues[0];if(!o)throw new Xr("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:$.issues});throw new Xr("config",o.message,{rule:o.rule,path:o.path,hint:o.hint,issues:$.issues},{fieldPath:o.path})}function Qg(r=3,n=2){return($)=>{let o=String($??"");if(o.length<=r+n)return"*".repeat(Math.max(0,o.length));let i=o.slice(0,r),t=o.slice(-n);return`${i}${"*".repeat(o.length-r-n)}${t}`}}var e6=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function C6(r){let n=r.toLowerCase();return e6.some(($)=>n.includes($.toLowerCase()))}function h6(r){let n=r.trim();if(n.length<=4)return"***";if(n.includes("@")){let[i,t]=n.split("@");return`${i.slice(0,2)}${"*".repeat(Math.max(1,i.length-2))}@${t}`}let $=n.slice(0,3),o=n.slice(-2);return`${$}${"*".repeat(Math.max(1,n.length-5))}${o}`}function Fv(r,n){if(n===void 0||n===null)return n;if(C6(r)){if(typeof n==="string")return h6(n);if(typeof n==="number"||typeof n==="boolean")return"***";if(Array.isArray(n))return"[REDACTED]";if(typeof n==="object")return"[REDACTED]"}if(Array.isArray(n))return n.map(($)=>Fv(r,$));if(typeof n==="object"){let $={};for(let[o,i]of Object.entries(n))$[o]=Fv(o,i);return $}return n}function y6(r){let n={};for(let[$,o]of Object.entries(r))n[$]=Fv($,o);return n}class Xv{config;context;constructor(r={},n={}){this.context=r,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(r){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(r)>=n.indexOf(this.config.level)}formatMessage(r){let n=y6(r.context);if(this.config.enableJson)return JSON.stringify({level:r.level,message:r.message,timestamp:r.timestamp.toISOString(),context:n,...r.error&&{error:{name:r.error.name,message:r.error.message,stack:r.error.stack}},...r.duration&&{duration:r.duration}});let $=r.timestamp.toISOString(),o=this.config.enableColors?this.colorizeLevel(r.level):r.level,i=Object.keys(n).length>0?` [${Object.entries(n).map(([u,v])=>`${u}=${v}`).join(", ")}]`:"",t=`${$} ${o}${i}: ${r.message}`;if(r.duration!==void 0)t+=` (${r.duration}ms)`;if(r.error)t+=`
|
|
48
|
+
`),this.emit("dataSaved",{filePath:this.config.filePath,eventCount:this.events.size})}catch(r){throw this.emit("saveError",r),r}}async shutdown(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;if(this.config.type==="file")await this.saveToFile().catch((r)=>{this.emit("saveError",r)});this.emit("shutdown",{eventCount:this.events.size})}}class rn{config;constructor(r){this.config={maxRetries:r.maxRetries,baseDelayMs:r.retryDelayMs,maxDelayMs:r.maxDelayMs||300000,backoffMultiplier:r.backoffMultiplier||2,jitter:r.jitter!==!1}}calculateNextRetry(r){if(r>=this.config.maxRetries)throw Error(`Maximum retry attempts (${this.config.maxRetries}) exceeded`);let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;if(n=Math.min(n,this.config.maxDelayMs),this.config.jitter)n=n*(0.5+Math.random()*0.5);return new Date(Date.now()+n)}shouldRetry(r,n){if(r>=this.config.maxRetries)return!1;if(n)return this.isRetryableError(n);return!0}isRetryableError(r){let n=r.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused","socket hang up"].some((o)=>n.includes(o))}shouldRetryStatus(r){if(r>=400&&r<500)return[408,429].includes(r);if(r>=500)return!0;return!1}calculateRetryStats(r){if(r.length===0)return{totalAttempts:0,successfulAttempts:0,failedAttempts:0,averageDelayMs:0,totalTimeMs:0};let n=r.filter((u)=>u.success).length,$=r.length-n,o=0;for(let u=1;u<r.length;u++)o+=r[u].timestamp.getTime()-r[u-1].timestamp.getTime();let i=r.length>1?o/(r.length-1):0,t=r.length>0?r[r.length-1].timestamp.getTime()-r[0].timestamp.getTime():0;return{totalAttempts:r.length,successfulAttempts:n,failedAttempts:$,averageDelayMs:i,totalTimeMs:t}}updateConfig(r){this.config={...this.config,...r}}getConfig(){return{...this.config}}getBackoffDelay(r){let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;return Math.min(n,this.config.maxDelayMs)}}var Nv;((x)=>{x.INVALID_REQUEST="INVALID_REQUEST";x.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";x.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";x.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";x.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";x.NETWORK_ERROR="NETWORK_ERROR";x.NETWORK_TIMEOUT="NETWORK_TIMEOUT";x.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";x.PROVIDER_ERROR="PROVIDER_ERROR";x.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";x.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";x.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";x.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";x.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";x.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";x.UNKNOWN_ERROR="UNKNOWN_ERROR"})(Nv||={});var Z6={["INVALID_REQUEST"]:{ko:"잘못된 요청입니다",en:"Invalid request"},["AUTHENTICATION_FAILED"]:{ko:"인증에 실패했습니다",en:"Authentication failed"},["INSUFFICIENT_BALANCE"]:{ko:"잔액이 부족합니다",en:"Insufficient balance"},["TEMPLATE_NOT_FOUND"]:{ko:"템플릿을 찾을 수 없습니다",en:"Template not found"},["RATE_LIMIT_EXCEEDED"]:{ko:"요청 한도를 초과했습니다",en:"Rate limit exceeded"},["NETWORK_ERROR"]:{ko:"네트워크 오류가 발생했습니다",en:"Network error"},["NETWORK_TIMEOUT"]:{ko:"네트워크 요청 시간이 초과되었습니다",en:"Network timeout"},["NETWORK_SERVICE_UNAVAILABLE"]:{ko:"서비스를 일시적으로 사용할 수 없습니다",en:"Service temporarily unavailable"},["PROVIDER_ERROR"]:{ko:"제공자 오류가 발생했습니다",en:"Provider error"},["MESSAGE_SEND_FAILED"]:{ko:"메시지 전송에 실패했습니다",en:"Message send failed"},["CRYPTO_CONFIG_ERROR"]:{ko:"암호화 설정 오류가 발생했습니다",en:"Crypto configuration error"},["CRYPTO_ENCRYPT_FAILED"]:{ko:"암호화에 실패했습니다",en:"Encryption failed"},["CRYPTO_DECRYPT_FAILED"]:{ko:"복호화에 실패했습니다",en:"Decryption failed"},["CRYPTO_HASH_FAILED"]:{ko:"해시 생성에 실패했습니다",en:"Hash generation failed"},["CRYPTO_POLICY_VIOLATION"]:{ko:"암호화 정책 위반이 발생했습니다",en:"Crypto policy violation"},["UNKNOWN_ERROR"]:{ko:"알 수 없는 오류가 발생했습니다",en:"Unknown error"}},l_=new Set(Object.values(Nv));var Ov=(r)=>{if(typeof r!=="number"||Number.isNaN(r)||!Number.isFinite(r))return;return Math.trunc(r)};class Mn extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(r,n,$,o={}){super(n);if(this.name="KMsgError",this.code=r,this.details=$,this.providerErrorCode=o.providerErrorCode,this.providerErrorText=o.providerErrorText,this.httpStatus=Ov(o.httpStatus),this.requestId=typeof o.requestId==="string"?o.requestId:void 0,this.retryAfterMs=Ov(o.retryAfterMs),this.attempt=Ov(o.attempt),Array.isArray(o.causeChain))this.causeChain=o.causeChain;else if(o.causeChain!==void 0)this.causeChain=[o.causeChain];let i=Error.captureStackTrace;if(i)i(this,Mn)}getLocalizedMessage(r="ko"){let n=Z6[this.code];if(n?.[r])return n[r];return this.message}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,providerErrorCode:this.providerErrorCode,providerErrorText:this.providerErrorText,httpStatus:this.httpStatus,requestId:this.requestId,retryAfterMs:this.retryAfterMs,attempt:this.attempt,causeChain:this.causeChain}}}function f6(r){switch(r){case"config":return"CRYPTO_CONFIG_ERROR";case"encrypt":return"CRYPTO_ENCRYPT_FAILED";case"decrypt":return"CRYPTO_DECRYPT_FAILED";case"hash":return"CRYPTO_HASH_FAILED";case"policy":return"CRYPTO_POLICY_VIOLATION"}}class Xr extends Mn{kind;fieldPath;failMode;openFallback;constructor(r,n,$,o={}){super(f6(r),n,$,o);this.name="FieldCryptoError",this.kind=r,this.fieldPath=typeof o.fieldPath==="string"?o.fieldPath:void 0,this.failMode=o.failMode,this.openFallback=o.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}function zv(r){return typeof r==="function"}function Kg(r){if(typeof r!=="string")return;let n=r.trim();return n.length>0?n:void 0}function xg(r,n,$){let o=r.fields[n];if(o)return o;if(n.startsWith("metadata.")){let i=r.fields["metadata.*"];if(i)return i}return $}function H6(r,n={}){let $=[];if(!r||typeof r!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!r.provider||typeof r.provider!=="object")$.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!zv(r.provider.encrypt))$.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!zv(r.provider.decrypt))$.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!zv(r.provider.hash))$.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!r.fields||typeof r.fields!=="object")$.push({message:"fieldCrypto.fields must be an object",rule:"fieldCrypto.fields.object",path:"fields",hint:"Define policies such as to, from, metadata.phoneNumber"});else{let t=Object.entries(r.fields);if(t.length===0)$.push({message:"fieldCrypto.fields must not be empty",rule:"fieldCrypto.fields.non_empty",path:"fields",hint:"Add at least one field mode mapping"});for(let[u,v]of t){if(!Kg(u))$.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(v!=="plain"&&v!=="encrypt"&&v!=="encrypt+hash"&&v!=="mask")$.push({message:`unsupported field mode: ${String(v)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${u}`})}}let o=r.failMode??"closed",i=r.openFallback??"masked";if(o==="open"&&i==="plaintext"&&r.unsafeAllowPlaintextStorage!==!0)$.push({message:"openFallback=plaintext requires unsafeAllowPlaintextStorage=true",rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback",hint:"Use masked/null fallback, or explicitly enable unsafe plaintext"});if(Array.isArray(r.aadFields)){if(r.aadFields.length===0)$.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let t=0;t<r.aadFields.length;t+=1){let u=r.aadFields[t];if(!Kg(u))$.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${t}]`})}}if(n.secureMode&&!n.compatPlainColumns){let t=xg(r,"to","encrypt+hash"),u=xg(r,"from","encrypt+hash");if(t==="plain")$.push({message:"secure mode requires non-plain policy for `to` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.to_non_plain",path:"fields.to",hint:"Use encrypt+hash for lookup fields"});if(u==="plain")$.push({message:"secure mode requires non-plain policy for `from` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.from_non_plain",path:"fields.from",hint:"Use encrypt+hash for lookup fields"})}return{valid:$.length===0,issues:$}}function jv(r,n={}){let $=H6(r,n);if($.valid)return;let o=$.issues[0];if(!o)throw new Xr("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:$.issues});throw new Xr("config",o.message,{rule:o.rule,path:o.path,hint:o.hint,issues:$.issues},{fieldPath:o.path})}function Qg(r=3,n=2){return($)=>{let o=String($??"");if(o.length<=r+n)return"*".repeat(Math.max(0,o.length));let i=o.slice(0,r),t=o.slice(-n);return`${i}${"*".repeat(o.length-r-n)}${t}`}}var e6=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function C6(r){let n=r.toLowerCase();return e6.some(($)=>n.includes($.toLowerCase()))}function h6(r){let n=r.trim();if(n.length<=4)return"***";if(n.includes("@")){let[i,t]=n.split("@");return`${i.slice(0,2)}${"*".repeat(Math.max(1,i.length-2))}@${t}`}let $=n.slice(0,3),o=n.slice(-2);return`${$}${"*".repeat(Math.max(1,n.length-5))}${o}`}function Fv(r,n){if(n===void 0||n===null)return n;if(C6(r)){if(typeof n==="string")return h6(n);if(typeof n==="number"||typeof n==="boolean")return"***";if(Array.isArray(n))return"[REDACTED]";if(typeof n==="object")return"[REDACTED]"}if(Array.isArray(n))return n.map(($)=>Fv(r,$));if(typeof n==="object"){let $={};for(let[o,i]of Object.entries(n))$[o]=Fv(o,i);return $}return n}function y6(r){let n={};for(let[$,o]of Object.entries(r))n[$]=Fv($,o);return n}class Xv{config;context;constructor(r={},n={}){this.context=r,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(r){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(r)>=n.indexOf(this.config.level)}formatMessage(r){let n=y6(r.context);if(this.config.enableJson)return JSON.stringify({level:r.level,message:r.message,timestamp:r.timestamp.toISOString(),context:n,...r.error&&{error:{name:r.error.name,message:r.error.message,stack:r.error.stack}},...r.duration&&{duration:r.duration}});let $=r.timestamp.toISOString(),o=this.config.enableColors?this.colorizeLevel(r.level):r.level,i=Object.keys(n).length>0?` [${Object.entries(n).map(([u,v])=>`${u}=${v}`).join(", ")}]`:"",t=`${$} ${o}${i}: ${r.message}`;if(r.duration!==void 0)t+=` (${r.duration}ms)`;if(r.error)t+=`
|
|
49
49
|
${r.error.stack}`;return t}colorizeLevel(r){if(!this.config.enableColors)return r;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[r]}${r}\x1B[0m`}writeLog(r){if(!this.shouldLog(r.level))return;let n=this.formatMessage(r);if(this.config.enableConsole)(r.level==="ERROR"?console.error:r.level==="WARN"?console.warn:console.log)(n);if(this.config.enableFile&&this.config.filePath);}debug(r,n={}){this.writeLog({level:"DEBUG",message:r,timestamp:new Date,context:{...this.context,...n}})}info(r,n={}){this.writeLog({level:"INFO",message:r,timestamp:new Date,context:{...this.context,...n}})}warn(r,n={},$){this.writeLog({level:"WARN",message:r,timestamp:new Date,context:{...this.context,...n},error:$})}error(r,n={},$){this.writeLog({level:"ERROR",message:r,timestamp:new Date,context:{...this.context,...n},error:$})}child(r){return new Xv({...this.context,...r},this.config)}time(r){let n=Date.now();return()=>{let $=Date.now()-n;this.info(`${r} completed`,{duration:$})}}async measure(r,n,$={}){let o=Date.now(),i={...$,operation:r};this.debug(`Starting ${r}`,i);try{let t=await n(),u=Date.now()-o;return this.info(`Completed ${r}`,{...i,duration:u}),t}catch(t){let u=Date.now()-o;throw this.error(`Failed ${r}`,{...i,duration:u},t instanceof Error?t:Error(String(t))),t}}}var Jv;function a6(r,n){return new Xv(r,n)}function Ir(){if(!Jv)Jv=a6();return Jv}var qg={debug:(r,n)=>Ir().debug(r,n),info:(r,n)=>Ir().info(r,n),warn:(r,n,$)=>Ir().warn(r,n,$),error:(r,n,$)=>Ir().error(r,n,$),child:(r)=>Ir().child(r),time:(r)=>Ir().time(r),measure:(r,n,$)=>Ir().measure(r,n,$)};/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function d6(r){return r instanceof Uint8Array||ArrayBuffer.isView(r)&&r.constructor.name==="Uint8Array"}function Wg(r){if(!Number.isSafeInteger(r)||r<0)throw Error("positive integer expected, got "+r)}function br(r,...n){if(!d6(r))throw Error("Uint8Array expected");if(n.length>0&&!n.includes(r.length))throw Error("Uint8Array expected of length "+n+", got length="+r.length)}function Lg(r){if(typeof r!=="function"||typeof r.create!=="function")throw Error("Hash should be wrapped by utils.createHasher");Wg(r.outputLen),Wg(r.blockLen)}function Gr(r,n=!0){if(r.destroyed)throw Error("Hash instance has been destroyed");if(n&&r.finished)throw Error("Hash#digest() has already been called")}function Eg(r,n){br(r);let $=n.outputLen;if(r.length<$)throw Error("digestInto() expects output buffer of length at least "+$)}function C(...r){for(let n=0;n<r.length;n++)r[n].fill(0)}function Zn(r){return new DataView(r.buffer,r.byteOffset,r.byteLength)}function Z(r,n){return r<<32-n|r>>>n}function fn(r,n){return r<<n|r>>>32-n>>>0}var p6=(()=>typeof Uint8Array.from([]).toHex==="function"&&typeof Uint8Array.fromHex==="function")(),s6=Array.from({length:256},(r,n)=>n.toString(16).padStart(2,"0"));function Gv(r){if(br(r),p6)return r.toHex();let n="";for(let $=0;$<r.length;$++)n+=s6[r[$]];return n}function rk(r){if(typeof r!=="string")throw Error("string expected");return new Uint8Array(new TextEncoder().encode(r))}function nn(r){if(typeof r==="string")r=rk(r);return br(r),r}class tn{}function Hn(r){let n=(o)=>r().update(nn(o)).digest(),$=r();return n.outputLen=$.outputLen,n.blockLen=$.blockLen,n.create=()=>r(),n}class Yv extends tn{constructor(r,n){super();this.finished=!1,this.destroyed=!1,Lg(r);let $=nn(n);if(this.iHash=r.create(),typeof this.iHash.update!=="function")throw Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let o=this.blockLen,i=new Uint8Array(o);i.set($.length>o?r.create().update($).digest():$);for(let t=0;t<i.length;t++)i[t]^=54;this.iHash.update(i),this.oHash=r.create();for(let t=0;t<i.length;t++)i[t]^=106;this.oHash.update(i),C(i)}update(r){return Gr(this),this.iHash.update(r),this}digestInto(r){Gr(this),br(r,this.outputLen),this.finished=!0,this.iHash.digestInto(r),this.oHash.update(r),this.oHash.digestInto(r),this.destroy()}digest(){let r=new Uint8Array(this.oHash.outputLen);return this.digestInto(r),r}_cloneInto(r){r||(r=Object.create(Object.getPrototypeOf(this),{}));let{oHash:n,iHash:$,finished:o,destroyed:i,blockLen:t,outputLen:u}=this;return r=r,r.finished=o,r.destroyed=i,r.blockLen=t,r.outputLen=u,r.oHash=n._cloneInto(r.oHash),r.iHash=$._cloneInto(r.iHash),r}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}}var en=(r,n,$)=>new Yv(r,n).update($).digest();en.create=(r,n)=>new Yv(r,n);function nk(r,n,$,o){if(typeof r.setBigUint64==="function")return r.setBigUint64(n,$,o);let i=BigInt(32),t=BigInt(4294967295),u=Number($>>i&t),v=Number($&t),g=o?4:0,c=o?0:4;r.setUint32(n+g,u,o),r.setUint32(n+c,v,o)}function Cn(r,n,$){return r&n^~r&$}function hn(r,n,$){return r&n^r&$^n&$}class $n extends tn{constructor(r,n,$,o){super();this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.blockLen=r,this.outputLen=n,this.padOffset=$,this.isLE=o,this.buffer=new Uint8Array(r),this.view=Zn(this.buffer)}update(r){Gr(this),r=nn(r),br(r);let{view:n,buffer:$,blockLen:o}=this,i=r.length;for(let t=0;t<i;){let u=Math.min(o-this.pos,i-t);if(u===o){let v=Zn(r);for(;o<=i-t;t+=o)this.process(v,t);continue}if($.set(r.subarray(t,t+u),this.pos),this.pos+=u,t+=u,this.pos===o)this.process(n,0),this.pos=0}return this.length+=r.length,this.roundClean(),this}digestInto(r){Gr(this),Eg(r,this),this.finished=!0;let{buffer:n,view:$,blockLen:o,isLE:i}=this,{pos:t}=this;if(n[t++]=128,C(this.buffer.subarray(t)),this.padOffset>o-t)this.process($,0),t=0;for(let l=t;l<o;l++)n[l]=0;nk($,o-8,BigInt(this.length*8),i),this.process($,0);let u=Zn(r),v=this.outputLen;if(v%4)throw Error("_sha2: outputLen should be aligned to 32bit");let g=v/4,c=this.get();if(g>c.length)throw Error("_sha2: outputLen bigger than state");for(let l=0;l<g;l++)u.setUint32(4*l,c[l],i)}digest(){let{buffer:r,outputLen:n}=this;this.digestInto(r);let $=r.slice(0,n);return this.destroy(),$}_cloneInto(r){r||(r=new this.constructor),r.set(...this.get());let{blockLen:n,buffer:$,length:o,finished:i,destroyed:t,pos:u}=this;if(r.destroyed=t,r.finished=i,r.length=o,r.pos=u,o%n)r.buffer.set($);return r}clone(){return this._cloneInto()}}var y=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var on=Uint32Array.from([1732584193,4023233417,2562383102,271733878,3285377520]),cr=new Uint32Array(80);class Kv extends $n{constructor(){super(64,20,8,!1);this.A=on[0]|0,this.B=on[1]|0,this.C=on[2]|0,this.D=on[3]|0,this.E=on[4]|0}get(){let{A:r,B:n,C:$,D:o,E:i}=this;return[r,n,$,o,i]}set(r,n,$,o,i){this.A=r|0,this.B=n|0,this.C=$|0,this.D=o|0,this.E=i|0}process(r,n){for(let v=0;v<16;v++,n+=4)cr[v]=r.getUint32(n,!1);for(let v=16;v<80;v++)cr[v]=fn(cr[v-3]^cr[v-8]^cr[v-14]^cr[v-16],1);let{A:$,B:o,C:i,D:t,E:u}=this;for(let v=0;v<80;v++){let g,c;if(v<20)g=Cn(o,i,t),c=1518500249;else if(v<40)g=o^i^t,c=1859775393;else if(v<60)g=hn(o,i,t),c=2400959708;else g=o^i^t,c=3395469782;let l=fn($,5)+g+u+c+cr[v]|0;u=t,t=i,i=fn(o,30),o=$,$=l}$=$+this.A|0,o=o+this.B|0,i=i+this.C|0,t=t+this.D|0,u=u+this.E|0,this.set($,o,i,t,u)}roundClean(){C(cr)}destroy(){this.set(0,0,0,0,0),C(this.buffer)}}var Vg=Hn(()=>new Kv);var Tg=Vg;var ik=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),gr=new Uint32Array(64);class Rg extends $n{constructor(r=32){super(64,r,8,!1);this.A=y[0]|0,this.B=y[1]|0,this.C=y[2]|0,this.D=y[3]|0,this.E=y[4]|0,this.F=y[5]|0,this.G=y[6]|0,this.H=y[7]|0}get(){let{A:r,B:n,C:$,D:o,E:i,F:t,G:u,H:v}=this;return[r,n,$,o,i,t,u,v]}set(r,n,$,o,i,t,u,v){this.A=r|0,this.B=n|0,this.C=$|0,this.D=o|0,this.E=i|0,this.F=t|0,this.G=u|0,this.H=v|0}process(r,n){for(let l=0;l<16;l++,n+=4)gr[l]=r.getUint32(n,!1);for(let l=16;l<64;l++){let k=gr[l-15],b=gr[l-2],_=Z(k,7)^Z(k,18)^k>>>3,O=Z(b,17)^Z(b,19)^b>>>10;gr[l]=O+gr[l-7]+_+gr[l-16]|0}let{A:$,B:o,C:i,D:t,E:u,F:v,G:g,H:c}=this;for(let l=0;l<64;l++){let k=Z(u,6)^Z(u,11)^Z(u,25),b=c+k+Cn(u,v,g)+ik[l]+gr[l]|0,O=(Z($,2)^Z($,13)^Z($,22))+hn($,o,i)|0;c=g,g=v,v=u,u=t+b|0,t=i,i=o,o=$,$=b+O|0}$=$+this.A|0,o=o+this.B|0,i=i+this.C|0,t=t+this.D|0,u=u+this.E|0,v=v+this.F|0,g=g+this.G|0,c=c+this.H|0,this.set($,o,i,t,u,v,g,c)}roundClean(){C(gr)}destroy(){this.set(0,0,0,0,0,0,0,0),C(this.buffer)}}var Ag=Hn(()=>new Rg);class un{config;encoder=new TextEncoder;constructor(r){this.config={algorithm:r.algorithm||"sha256",header:r.signatureHeader||"X-Webhook-Signature",prefix:r.signaturePrefix||"sha256="}}createSignedPayload(r,n){return`${n}.${r}`}generateSignature(r,n){let $=this.generateSignatureDigest(r,n);return this.config.prefix?`${this.config.prefix}${$}`:$}generateSignatureWithTimestamp(r,n,$){return this.generateSignature(this.createSignedPayload(r,n),$)}verifySignature(r,n,$){try{let o=this.generateSignature(r,$);return this.constantTimeCompare(n,o)}catch(o){return qg.error("Signature verification failed",void 0,o instanceof Error?o:Error(String(o))),!1}}verifySignatureWithTimestamp(r,n,$,o){return this.verifySignature(this.createSignedPayload(r,n),$,o)}extractSignature(r){let n=this.config.header.toLowerCase();for(let[$,o]of Object.entries(r))if($.toLowerCase()===n)return o;return null}createSecurityHeaders(r,n){let $=Math.floor(Date.now()/1000).toString(),o=this.generateSignatureWithTimestamp(r,$,n);return{[this.config.header]:o,"X-Webhook-Timestamp":$,"X-Webhook-ID":this.generateWebhookId(),"User-Agent":"K-Message-Webhook/1.0"}}verifyTimestamp(r,n=300){try{let $=(()=>{if(/^[0-9]+$/.test(r.trim()))return parseInt(r,10);let t=new Date(r);if(Number.isNaN(t.getTime()))return NaN;return Math.floor(t.getTime()/1000)})(),o=Math.floor(Date.now()/1000);return Math.abs(o-$)<=n}catch{return!1}}generateWebhookId(){let r=new Uint8Array(16);if(globalThis.crypto?.getRandomValues)globalThis.crypto.getRandomValues(r);else for(let n=0;n<r.length;n++)r[n]=Math.floor(Math.random()*256);return`wh_${Gv(r)}`}generateSignatureDigest(r,n){let $=this.encoder.encode(n),o=this.encoder.encode(r),i=this.config.algorithm==="sha1"?en(Tg,$,o):en(Ag,$,o);return Gv(i)}constantTimeCompare(r,n){if(r.length!==n.length)return!1;let $=0;for(let o=0;o<r.length;o++)$|=r.charCodeAt(o)^n.charCodeAt(o);return $===0}updateConfig(r){this.config={...this.config,...r}}getConfig(){return{...this.config}}}class yn{async fetch(r,n){return fetch(r,n)}}class xv{responses=new Map;defaultResponse=new Response(JSON.stringify({status:"ok"}),{status:200,statusText:"OK",headers:{"content-type":"application/json"}});setMockResponse(r,n){this.responses.set(r,n)}setDefaultResponse(r){this.defaultResponse=r}async fetch(r,n){let $=this.responses.get(r);if($)return $;return this.defaultResponse}}class Qv{config;httpClient;securityManager;retryManager;constructor(r,n){this.config=r,this.httpClient=n||new yn,this.securityManager=new un(r),this.retryManager=new rn(r)}async dispatch(r,n){let $=JSON.stringify(r),o=(()=>{if(r.timestamp instanceof Date)return r.timestamp;let u=new Date(r.timestamp);return Number.isNaN(u.getTime())?new Date:u})(),i=Math.floor(o.getTime()/1000).toString(),t={id:this.generateDeliveryId(),endpointId:n.id,eventId:r.id,eventType:r.type,url:n.url,httpMethod:"POST",headers:this.buildHeaders(n,r,$,i),payload:$,attempts:[],status:"pending",createdAt:new Date};return await this.executeDelivery(t,n),t}async executeDelivery(r,n){let $=n.retryConfig?.maxRetries||this.config.maxRetries;for(let o=1;o<=$+1;o++){let i=await this.makeHttpRequest(r,n,o);if(r.attempts.push(i),i.httpStatus&&i.httpStatus>=200&&i.httpStatus<300){r.status="success",r.completedAt=new Date;return}if(!(o<=$&&this.shouldRetryAttempt(o,i))){r.status="failed",r.completedAt=new Date;return}let u=this.calculateRetryDelay(o,n);r.nextRetryAt=new Date(Date.now()+u),await this.sleep(u)}r.status="exhausted",r.completedAt=new Date}shouldRetryAttempt(r,n){if(typeof n.httpStatus==="number")return this.retryManager.shouldRetryStatus(n.httpStatus);if(n.error)return this.retryManager.shouldRetry(r,Error(n.error));return!0}async makeHttpRequest(r,n,$){let o=Date.now(),i={attemptNumber:$,timestamp:new Date,latencyMs:0};try{let t=await this.httpClient.fetch(r.url,{method:r.httpMethod,headers:r.headers,body:r.payload,signal:AbortSignal.timeout(this.config.timeoutMs)});i.httpStatus=t.status,i.responseBody=await t.text();let u={};if(t.headers.forEach((v,g)=>{u[g]=v}),i.responseHeaders=u,i.latencyMs=Date.now()-o,!t.ok)i.error=`HTTP ${t.status}: ${t.statusText}`}catch(t){i.latencyMs=Date.now()-o,i.error=t instanceof Error?t.message:"Unknown error"}return i}buildHeaders(r,n,$,o){let i={"Content-Type":"application/json","X-Webhook-ID":n.id,"X-Webhook-Event":n.type,"X-Webhook-Timestamp":o,"User-Agent":"K-Message-Webhook/1.0"};if(r.headers)Object.assign(i,r.headers);if(this.config.enableSecurity){let t=(typeof r.secret==="string"&&r.secret.length>0?r.secret:typeof this.config.secretKey==="string"&&this.config.secretKey.length>0?this.config.secretKey:void 0)||void 0;if(t){let u=this.securityManager.generateSignatureWithTimestamp($,o,t),v=this.securityManager.getConfig().header;i[v]=u}}return i}calculateRetryDelay(r,n){let $=n.retryConfig?.retryDelayMs||this.config.retryDelayMs,o=n.retryConfig?.backoffMultiplier||this.config.backoffMultiplier||2,i=$*o**r;if(typeof this.config.maxDelayMs==="number")i=Math.min(i,this.config.maxDelayMs);if(this.config.jitter!==!1)i=i*(0.5+Math.random()*0.5);return Math.max(0,Math.floor(i))}sleep(r){return new Promise((n)=>setTimeout(n,r))}generateDeliveryId(){return`delivery_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}async shutdown(){}}function qv(r){if(typeof r!=="string")return;let n=r.trim();return n.length>0?n:void 0}function Zg(r,n){let $=r.openFallback??"masked";if($==="plaintext"){if(!r.unsafeAllowPlaintextStorage)throw new Xr("policy","openFallback=plaintext requires unsafeAllowPlaintextStorage=true",{rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback"},{fieldPath:"openFallback",failMode:"open",openFallback:"plaintext"});return n}if($==="null")return"";return Qg()(n)}async function Bg(r,n){let $=qv(n.value);if(!$)return;if(!r||r.enabled===!1)return $;let o=r.failMode??"closed",i=r.keyResolver;try{let t={tenantId:n.tenantId,tableName:n.aad.tableName,fieldPath:n.path,messageId:n.aad.messageId,providerId:n.aad.providerId},u=i?qv((await i.resolveEncryptKey(t)).kid):void 0,v=await r.provider.encrypt({value:$,path:n.path,aad:n.aad,...u?{kid:u}:{}});return typeof v.ciphertext==="string"?v.ciphertext:JSON.stringify(v.ciphertext)}catch(t){if(o==="closed")throw t;return Zg(r,$)}}async function Mg(r,n){let $=qv(n.value);if(!$)return;if(!r||r.enabled===!1)return $;let o=r.failMode??"closed";try{let i={tenantId:n.tenantId,tableName:n.aad.tableName,fieldPath:n.path,messageId:n.aad.messageId,providerId:n.aad.providerId},t=r.keyResolver?.resolveDecryptKeys?await r.keyResolver.resolveDecryptKeys({...i,ciphertext:$}):void 0;return await r.provider.decrypt({ciphertext:$,path:n.path,aad:n.aad,...Array.isArray(t)&&t.length>0?{candidateKids:t}:{}})}catch(i){if(o==="closed")throw i;return Zg(r,$)}}class Wv{endpoints=new Map;deliveries=new Map;options;constructor(r={}){this.options=r,this.validateCryptoOptions(this.options.fieldCrypto)}async addEndpoint(r){this.endpoints.set(r.id,await this.protectEndpoint(r))}async updateEndpoint(r,n){if(!this.endpoints.has(r))throw Error(`Endpoint ${r} not found`);this.endpoints.set(r,await this.protectEndpoint(n))}async removeEndpoint(r){this.endpoints.delete(r)}async getEndpoint(r){let n=this.endpoints.get(r);if(!n)return null;return await this.revealEndpoint(n)}async listEndpoints(){return await Promise.all(Array.from(this.endpoints.values()).map((r)=>this.revealEndpoint(r)))}async addDelivery(r){this.deliveries.set(r.id,await this.protectDelivery(r))}async getDeliveries(r,n,$,o,i=100){let t=Array.from(this.deliveries.values());if(r)t=t.filter((v)=>v.endpointId===r);if(n)t=t.filter((v)=>v.createdAt>=n.start&&v.createdAt<=n.end);if($)t=t.filter((v)=>v.eventType===$);if(o)t=t.filter((v)=>v.status===o);let u=t.sort((v,g)=>g.createdAt.getTime()-v.createdAt.getTime()).slice(0,i);return await Promise.all(u.map((v)=>this.revealDelivery(v)))}async getFailedDeliveries(r,n){return(await this.getDeliveries(r,void 0,n,void 0,1000)).filter((o)=>o.status==="failed"||o.status==="exhausted")}async protectEndpoint(r){let n={tableName:"webhook_endpoint",messageId:r.id},$=await Bg(this.options.fieldCrypto?.endpoint,{value:r.secret,path:"secret",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,...$?{secret:$}:{}}}async revealEndpoint(r){let n={tableName:"webhook_endpoint",messageId:r.id},$=await Mg(this.options.fieldCrypto?.endpoint,{value:r.secret,path:"secret",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,...$?{secret:$}:{}}}async protectDelivery(r){let n={tableName:"webhook_delivery",messageId:r.id,providerId:r.endpointId},$=await Bg(this.options.fieldCrypto?.delivery,{value:r.payload,path:"payload",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,payload:$??r.payload}}async revealDelivery(r){let n={tableName:"webhook_delivery",messageId:r.id,providerId:r.endpointId},$=await Mg(this.options.fieldCrypto?.delivery,{value:r.payload,path:"payload",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,payload:$??r.payload}}validateCryptoOptions(r){if(!r)return;if(r.endpoint)jv(r.endpoint);if(r.delivery)jv(r.delivery)}}
|
|
50
50
|
|
|
51
|
-
//# debugId=
|
|
51
|
+
//# debugId=7622B36D207686DA64756E2164756E21
|
|
52
52
|
//# sourceMappingURL=index.js.map
|
package/dist/toolkit/index.mjs
CHANGED
|
@@ -45,8 +45,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
45
45
|
`;await n.ensureDirForFile(this.config.filePath),await n.appendFile(this.config.filePath,$)}catch(n){this.emit("appendError",n)}}async loadFromFile(){if(!this.config.filePath)return;try{let $=(await L(this.config.fileAdapter).readFile(this.config.filePath)).trim().split(`
|
|
46
46
|
`).filter((o)=>o.trim());for(let o of $)try{let i=JSON.parse(o),t={...i,timestamp:new Date(i.timestamp)};this.events.set(t.id,t),this.addToIndexes(t)}catch(i){this.emit("parseError",{line:o,error:i})}this.emit("dataLoaded",{filePath:this.config.filePath,eventCount:this.events.size})}catch(r){if(!a(r))this.emit("loadError",r)}}async saveToFile(){if(!this.config.filePath)return;try{let r=L(this.config.fileAdapter),n=Array.from(this.events.values()).map(($)=>JSON.stringify($)).join(`
|
|
47
47
|
`);await r.ensureDirForFile(this.config.filePath),await r.writeFile(this.config.filePath,n+`
|
|
48
|
-
`),this.emit("dataSaved",{filePath:this.config.filePath,eventCount:this.events.size})}catch(r){throw this.emit("saveError",r),r}}async shutdown(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;if(this.config.type==="file")await this.saveToFile().catch((r)=>{this.emit("saveError",r)});this.emit("shutdown",{eventCount:this.events.size})}}class An{config;constructor(r){this.config={maxRetries:r.maxRetries,baseDelayMs:r.retryDelayMs,maxDelayMs:r.maxDelayMs||300000,backoffMultiplier:r.backoffMultiplier||2,jitter:r.jitter!==!1}}calculateNextRetry(r){if(r>=this.config.maxRetries)throw Error(`Maximum retry attempts (${this.config.maxRetries}) exceeded`);let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;if(n=Math.min(n,this.config.maxDelayMs),this.config.jitter)n=n*(0.5+Math.random()*0.5);return new Date(Date.now()+n)}shouldRetry(r,n){if(r>=this.config.maxRetries)return!1;if(n)return this.isRetryableError(n);return!0}isRetryableError(r){let n=r.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused","socket hang up"].some((o)=>n.includes(o))}shouldRetryStatus(r){if(r>=400&&r<500)return[408,429].includes(r);if(r>=500)return!0;return!1}calculateRetryStats(r){if(r.length===0)return{totalAttempts:0,successfulAttempts:0,failedAttempts:0,averageDelayMs:0,totalTimeMs:0};let n=r.filter((u)=>u.success).length,$=r.length-n,o=0;for(let u=1;u<r.length;u++)o+=r[u].timestamp.getTime()-r[u-1].timestamp.getTime();let i=r.length>1?o/(r.length-1):0,t=r.length>0?r[r.length-1].timestamp.getTime()-r[0].timestamp.getTime():0;return{totalAttempts:r.length,successfulAttempts:n,failedAttempts:$,averageDelayMs:i,totalTimeMs:t}}updateConfig(r){this.config={...this.config,...r}}getConfig(){return{...this.config}}getBackoffDelay(r){let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;return Math.min(n,this.config.maxDelayMs)}}var Iv;((x)=>{x.INVALID_REQUEST="INVALID_REQUEST";x.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";x.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";x.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";x.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";x.NETWORK_ERROR="NETWORK_ERROR";x.NETWORK_TIMEOUT="NETWORK_TIMEOUT";x.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";x.PROVIDER_ERROR="PROVIDER_ERROR";x.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";x.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";x.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";x.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";x.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";x.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";x.UNKNOWN_ERROR="UNKNOWN_ERROR"})(Iv||={});var V6={["INVALID_REQUEST"]:{ko:"잘못된 요청입니다",en:"Invalid request"},["AUTHENTICATION_FAILED"]:{ko:"인증에 실패했습니다",en:"Authentication failed"},["INSUFFICIENT_BALANCE"]:{ko:"잔액이 부족합니다",en:"Insufficient balance"},["TEMPLATE_NOT_FOUND"]:{ko:"템플릿을 찾을 수 없습니다",en:"Template not found"},["RATE_LIMIT_EXCEEDED"]:{ko:"요청 한도를 초과했습니다",en:"Rate limit exceeded"},["NETWORK_ERROR"]:{ko:"네트워크 오류가 발생했습니다",en:"Network error"},["NETWORK_TIMEOUT"]:{ko:"네트워크 요청 시간이 초과되었습니다",en:"Network timeout"},["NETWORK_SERVICE_UNAVAILABLE"]:{ko:"서비스를 일시적으로 사용할 수 없습니다",en:"Service temporarily unavailable"},["PROVIDER_ERROR"]:{ko:"제공자 오류가 발생했습니다",en:"Provider error"},["MESSAGE_SEND_FAILED"]:{ko:"메시지 전송에 실패했습니다",en:"Message send failed"},["CRYPTO_CONFIG_ERROR"]:{ko:"암호화 설정 오류가 발생했습니다",en:"Crypto configuration error"},["CRYPTO_ENCRYPT_FAILED"]:{ko:"암호화에 실패했습니다",en:"Encryption failed"},["CRYPTO_DECRYPT_FAILED"]:{ko:"복호화에 실패했습니다",en:"Decryption failed"},["CRYPTO_HASH_FAILED"]:{ko:"해시 생성에 실패했습니다",en:"Hash generation failed"},["CRYPTO_POLICY_VIOLATION"]:{ko:"암호화 정책 위반이 발생했습니다",en:"Crypto policy violation"},["UNKNOWN_ERROR"]:{ko:"알 수 없는 오류가 발생했습니다",en:"Unknown error"}},t_=new Set(Object.values(Iv));var kv=(r)=>{if(typeof r!=="number"||Number.isNaN(r)||!Number.isFinite(r))return;return Math.trunc(r)};class Bn extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(r,n,$,o={}){super(n);if(this.name="KMsgError",this.code=r,this.details=$,this.providerErrorCode=o.providerErrorCode,this.providerErrorText=o.providerErrorText,this.httpStatus=kv(o.httpStatus),this.requestId=typeof o.requestId==="string"?o.requestId:void 0,this.retryAfterMs=kv(o.retryAfterMs),this.attempt=kv(o.attempt),Array.isArray(o.causeChain))this.causeChain=o.causeChain;else if(o.causeChain!==void 0)this.causeChain=[o.causeChain];if(Error.captureStackTrace)Error.captureStackTrace(this,Bn)}getLocalizedMessage(r="ko"){let n=V6[this.code];if(n?.[r])return n[r];return this.message}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,providerErrorCode:this.providerErrorCode,providerErrorText:this.providerErrorText,httpStatus:this.httpStatus,requestId:this.requestId,retryAfterMs:this.retryAfterMs,attempt:this.attempt,causeChain:this.causeChain}}}function T6(r){switch(r){case"config":return"CRYPTO_CONFIG_ERROR";case"encrypt":return"CRYPTO_ENCRYPT_FAILED";case"decrypt":return"CRYPTO_DECRYPT_FAILED";case"hash":return"CRYPTO_HASH_FAILED";case"policy":return"CRYPTO_POLICY_VIOLATION"}}class Xr extends Bn{kind;fieldPath;failMode;openFallback;constructor(r,n,$,o={}){super(T6(r),n,$,o);this.name="FieldCryptoError",this.kind=r,this.fieldPath=typeof o.fieldPath==="string"?o.fieldPath:void 0,this.failMode=o.failMode,this.openFallback=o.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}function bv(r){return typeof r==="function"}function Jg(r){if(typeof r!=="string")return;let n=r.trim();return n.length>0?n:void 0}function Fg(r,n,$){let o=r.fields[n];if(o)return o;if(n.startsWith("metadata.")){let i=r.fields["metadata.*"];if(i)return i}return $}function R6(r,n={}){let $=[];if(!r||typeof r!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!r.provider||typeof r.provider!=="object")$.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!bv(r.provider.encrypt))$.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!bv(r.provider.decrypt))$.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!bv(r.provider.hash))$.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!r.fields||typeof r.fields!=="object")$.push({message:"fieldCrypto.fields must be an object",rule:"fieldCrypto.fields.object",path:"fields",hint:"Define policies such as to, from, metadata.phoneNumber"});else{let t=Object.entries(r.fields);if(t.length===0)$.push({message:"fieldCrypto.fields must not be empty",rule:"fieldCrypto.fields.non_empty",path:"fields",hint:"Add at least one field mode mapping"});for(let[u,v]of t){if(!Jg(u))$.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(v!=="plain"&&v!=="encrypt"&&v!=="encrypt+hash"&&v!=="mask")$.push({message:`unsupported field mode: ${String(v)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${u}`})}}let o=r.failMode??"closed",i=r.openFallback??"masked";if(o==="open"&&i==="plaintext"&&r.unsafeAllowPlaintextStorage!==!0)$.push({message:"openFallback=plaintext requires unsafeAllowPlaintextStorage=true",rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback",hint:"Use masked/null fallback, or explicitly enable unsafe plaintext"});if(Array.isArray(r.aadFields)){if(r.aadFields.length===0)$.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let t=0;t<r.aadFields.length;t+=1){let u=r.aadFields[t];if(!Jg(u))$.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${t}]`})}}if(n.secureMode&&!n.compatPlainColumns){let t=Fg(r,"to","encrypt+hash"),u=Fg(r,"from","encrypt+hash");if(t==="plain")$.push({message:"secure mode requires non-plain policy for `to` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.to_non_plain",path:"fields.to",hint:"Use encrypt+hash for lookup fields"});if(u==="plain")$.push({message:"secure mode requires non-plain policy for `from` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.from_non_plain",path:"fields.from",hint:"Use encrypt+hash for lookup fields"})}return{valid:$.length===0,issues:$}}function _v(r,n={}){let $=R6(r,n);if($.valid)return;let o=$.issues[0];if(!o)throw new Xr("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:$.issues});throw new Xr("config",o.message,{rule:o.rule,path:o.path,hint:o.hint,issues:$.issues},{fieldPath:o.path})}function Xg(r=3,n=2){return($)=>{let o=String($??"");if(o.length<=r+n)return"*".repeat(Math.max(0,o.length));let i=o.slice(0,r),t=o.slice(-n);return`${i}${"*".repeat(o.length-r-n)}${t}`}}var A6=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function B6(r){let n=r.toLowerCase();return A6.some(($)=>n.includes($.toLowerCase()))}function M6(r){let n=r.trim();if(n.length<=4)return"***";if(n.includes("@")){let[i,t]=n.split("@");return`${i.slice(0,2)}${"*".repeat(Math.max(1,i.length-2))}@${t}`}let $=n.slice(0,3),o=n.slice(-2);return`${$}${"*".repeat(Math.max(1,n.length-5))}${o}`}function Dv(r,n){if(n===void 0||n===null)return n;if(B6(r)){if(typeof n==="string")return M6(n);if(typeof n==="number"||typeof n==="boolean")return"***";if(Array.isArray(n))return"[REDACTED]";if(typeof n==="object")return"[REDACTED]"}if(Array.isArray(n))return n.map(($)=>Dv(r,$));if(typeof n==="object"){let $={};for(let[o,i]of Object.entries(n))$[o]=Dv(o,i);return $}return n}function Z6(r){let n={};for(let[$,o]of Object.entries(r))n[$]=Dv($,o);return n}class Sv{config;context;constructor(r={},n={}){this.context=r,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(r){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(r)>=n.indexOf(this.config.level)}formatMessage(r){let n=Z6(r.context);if(this.config.enableJson)return JSON.stringify({level:r.level,message:r.message,timestamp:r.timestamp.toISOString(),context:n,...r.error&&{error:{name:r.error.name,message:r.error.message,stack:r.error.stack}},...r.duration&&{duration:r.duration}});let $=r.timestamp.toISOString(),o=this.config.enableColors?this.colorizeLevel(r.level):r.level,i=Object.keys(n).length>0?` [${Object.entries(n).map(([u,v])=>`${u}=${v}`).join(", ")}]`:"",t=`${$} ${o}${i}: ${r.message}`;if(r.duration!==void 0)t+=` (${r.duration}ms)`;if(r.error)t+=`
|
|
48
|
+
`),this.emit("dataSaved",{filePath:this.config.filePath,eventCount:this.events.size})}catch(r){throw this.emit("saveError",r),r}}async shutdown(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;if(this.config.type==="file")await this.saveToFile().catch((r)=>{this.emit("saveError",r)});this.emit("shutdown",{eventCount:this.events.size})}}class An{config;constructor(r){this.config={maxRetries:r.maxRetries,baseDelayMs:r.retryDelayMs,maxDelayMs:r.maxDelayMs||300000,backoffMultiplier:r.backoffMultiplier||2,jitter:r.jitter!==!1}}calculateNextRetry(r){if(r>=this.config.maxRetries)throw Error(`Maximum retry attempts (${this.config.maxRetries}) exceeded`);let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;if(n=Math.min(n,this.config.maxDelayMs),this.config.jitter)n=n*(0.5+Math.random()*0.5);return new Date(Date.now()+n)}shouldRetry(r,n){if(r>=this.config.maxRetries)return!1;if(n)return this.isRetryableError(n);return!0}isRetryableError(r){let n=r.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused","socket hang up"].some((o)=>n.includes(o))}shouldRetryStatus(r){if(r>=400&&r<500)return[408,429].includes(r);if(r>=500)return!0;return!1}calculateRetryStats(r){if(r.length===0)return{totalAttempts:0,successfulAttempts:0,failedAttempts:0,averageDelayMs:0,totalTimeMs:0};let n=r.filter((u)=>u.success).length,$=r.length-n,o=0;for(let u=1;u<r.length;u++)o+=r[u].timestamp.getTime()-r[u-1].timestamp.getTime();let i=r.length>1?o/(r.length-1):0,t=r.length>0?r[r.length-1].timestamp.getTime()-r[0].timestamp.getTime():0;return{totalAttempts:r.length,successfulAttempts:n,failedAttempts:$,averageDelayMs:i,totalTimeMs:t}}updateConfig(r){this.config={...this.config,...r}}getConfig(){return{...this.config}}getBackoffDelay(r){let n=this.config.baseDelayMs*this.config.backoffMultiplier**r;return Math.min(n,this.config.maxDelayMs)}}var Iv;((x)=>{x.INVALID_REQUEST="INVALID_REQUEST";x.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";x.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";x.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";x.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";x.NETWORK_ERROR="NETWORK_ERROR";x.NETWORK_TIMEOUT="NETWORK_TIMEOUT";x.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";x.PROVIDER_ERROR="PROVIDER_ERROR";x.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";x.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";x.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";x.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";x.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";x.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";x.UNKNOWN_ERROR="UNKNOWN_ERROR"})(Iv||={});var V6={["INVALID_REQUEST"]:{ko:"잘못된 요청입니다",en:"Invalid request"},["AUTHENTICATION_FAILED"]:{ko:"인증에 실패했습니다",en:"Authentication failed"},["INSUFFICIENT_BALANCE"]:{ko:"잔액이 부족합니다",en:"Insufficient balance"},["TEMPLATE_NOT_FOUND"]:{ko:"템플릿을 찾을 수 없습니다",en:"Template not found"},["RATE_LIMIT_EXCEEDED"]:{ko:"요청 한도를 초과했습니다",en:"Rate limit exceeded"},["NETWORK_ERROR"]:{ko:"네트워크 오류가 발생했습니다",en:"Network error"},["NETWORK_TIMEOUT"]:{ko:"네트워크 요청 시간이 초과되었습니다",en:"Network timeout"},["NETWORK_SERVICE_UNAVAILABLE"]:{ko:"서비스를 일시적으로 사용할 수 없습니다",en:"Service temporarily unavailable"},["PROVIDER_ERROR"]:{ko:"제공자 오류가 발생했습니다",en:"Provider error"},["MESSAGE_SEND_FAILED"]:{ko:"메시지 전송에 실패했습니다",en:"Message send failed"},["CRYPTO_CONFIG_ERROR"]:{ko:"암호화 설정 오류가 발생했습니다",en:"Crypto configuration error"},["CRYPTO_ENCRYPT_FAILED"]:{ko:"암호화에 실패했습니다",en:"Encryption failed"},["CRYPTO_DECRYPT_FAILED"]:{ko:"복호화에 실패했습니다",en:"Decryption failed"},["CRYPTO_HASH_FAILED"]:{ko:"해시 생성에 실패했습니다",en:"Hash generation failed"},["CRYPTO_POLICY_VIOLATION"]:{ko:"암호화 정책 위반이 발생했습니다",en:"Crypto policy violation"},["UNKNOWN_ERROR"]:{ko:"알 수 없는 오류가 발생했습니다",en:"Unknown error"}},t_=new Set(Object.values(Iv));var kv=(r)=>{if(typeof r!=="number"||Number.isNaN(r)||!Number.isFinite(r))return;return Math.trunc(r)};class Bn extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(r,n,$,o={}){super(n);if(this.name="KMsgError",this.code=r,this.details=$,this.providerErrorCode=o.providerErrorCode,this.providerErrorText=o.providerErrorText,this.httpStatus=kv(o.httpStatus),this.requestId=typeof o.requestId==="string"?o.requestId:void 0,this.retryAfterMs=kv(o.retryAfterMs),this.attempt=kv(o.attempt),Array.isArray(o.causeChain))this.causeChain=o.causeChain;else if(o.causeChain!==void 0)this.causeChain=[o.causeChain];let i=Error.captureStackTrace;if(i)i(this,Bn)}getLocalizedMessage(r="ko"){let n=V6[this.code];if(n?.[r])return n[r];return this.message}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,providerErrorCode:this.providerErrorCode,providerErrorText:this.providerErrorText,httpStatus:this.httpStatus,requestId:this.requestId,retryAfterMs:this.retryAfterMs,attempt:this.attempt,causeChain:this.causeChain}}}function T6(r){switch(r){case"config":return"CRYPTO_CONFIG_ERROR";case"encrypt":return"CRYPTO_ENCRYPT_FAILED";case"decrypt":return"CRYPTO_DECRYPT_FAILED";case"hash":return"CRYPTO_HASH_FAILED";case"policy":return"CRYPTO_POLICY_VIOLATION"}}class Xr extends Bn{kind;fieldPath;failMode;openFallback;constructor(r,n,$,o={}){super(T6(r),n,$,o);this.name="FieldCryptoError",this.kind=r,this.fieldPath=typeof o.fieldPath==="string"?o.fieldPath:void 0,this.failMode=o.failMode,this.openFallback=o.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}function bv(r){return typeof r==="function"}function Jg(r){if(typeof r!=="string")return;let n=r.trim();return n.length>0?n:void 0}function Fg(r,n,$){let o=r.fields[n];if(o)return o;if(n.startsWith("metadata.")){let i=r.fields["metadata.*"];if(i)return i}return $}function R6(r,n={}){let $=[];if(!r||typeof r!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!r.provider||typeof r.provider!=="object")$.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!bv(r.provider.encrypt))$.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!bv(r.provider.decrypt))$.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!bv(r.provider.hash))$.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!r.fields||typeof r.fields!=="object")$.push({message:"fieldCrypto.fields must be an object",rule:"fieldCrypto.fields.object",path:"fields",hint:"Define policies such as to, from, metadata.phoneNumber"});else{let t=Object.entries(r.fields);if(t.length===0)$.push({message:"fieldCrypto.fields must not be empty",rule:"fieldCrypto.fields.non_empty",path:"fields",hint:"Add at least one field mode mapping"});for(let[u,v]of t){if(!Jg(u))$.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(v!=="plain"&&v!=="encrypt"&&v!=="encrypt+hash"&&v!=="mask")$.push({message:`unsupported field mode: ${String(v)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${u}`})}}let o=r.failMode??"closed",i=r.openFallback??"masked";if(o==="open"&&i==="plaintext"&&r.unsafeAllowPlaintextStorage!==!0)$.push({message:"openFallback=plaintext requires unsafeAllowPlaintextStorage=true",rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback",hint:"Use masked/null fallback, or explicitly enable unsafe plaintext"});if(Array.isArray(r.aadFields)){if(r.aadFields.length===0)$.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let t=0;t<r.aadFields.length;t+=1){let u=r.aadFields[t];if(!Jg(u))$.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${t}]`})}}if(n.secureMode&&!n.compatPlainColumns){let t=Fg(r,"to","encrypt+hash"),u=Fg(r,"from","encrypt+hash");if(t==="plain")$.push({message:"secure mode requires non-plain policy for `to` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.to_non_plain",path:"fields.to",hint:"Use encrypt+hash for lookup fields"});if(u==="plain")$.push({message:"secure mode requires non-plain policy for `from` when compatPlainColumns=false",rule:"fieldCrypto.secure_mode.from_non_plain",path:"fields.from",hint:"Use encrypt+hash for lookup fields"})}return{valid:$.length===0,issues:$}}function _v(r,n={}){let $=R6(r,n);if($.valid)return;let o=$.issues[0];if(!o)throw new Xr("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:$.issues});throw new Xr("config",o.message,{rule:o.rule,path:o.path,hint:o.hint,issues:$.issues},{fieldPath:o.path})}function Xg(r=3,n=2){return($)=>{let o=String($??"");if(o.length<=r+n)return"*".repeat(Math.max(0,o.length));let i=o.slice(0,r),t=o.slice(-n);return`${i}${"*".repeat(o.length-r-n)}${t}`}}var A6=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function B6(r){let n=r.toLowerCase();return A6.some(($)=>n.includes($.toLowerCase()))}function M6(r){let n=r.trim();if(n.length<=4)return"***";if(n.includes("@")){let[i,t]=n.split("@");return`${i.slice(0,2)}${"*".repeat(Math.max(1,i.length-2))}@${t}`}let $=n.slice(0,3),o=n.slice(-2);return`${$}${"*".repeat(Math.max(1,n.length-5))}${o}`}function Dv(r,n){if(n===void 0||n===null)return n;if(B6(r)){if(typeof n==="string")return M6(n);if(typeof n==="number"||typeof n==="boolean")return"***";if(Array.isArray(n))return"[REDACTED]";if(typeof n==="object")return"[REDACTED]"}if(Array.isArray(n))return n.map(($)=>Dv(r,$));if(typeof n==="object"){let $={};for(let[o,i]of Object.entries(n))$[o]=Dv(o,i);return $}return n}function Z6(r){let n={};for(let[$,o]of Object.entries(r))n[$]=Dv($,o);return n}class Sv{config;context;constructor(r={},n={}){this.context=r,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(r){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(r)>=n.indexOf(this.config.level)}formatMessage(r){let n=Z6(r.context);if(this.config.enableJson)return JSON.stringify({level:r.level,message:r.message,timestamp:r.timestamp.toISOString(),context:n,...r.error&&{error:{name:r.error.name,message:r.error.message,stack:r.error.stack}},...r.duration&&{duration:r.duration}});let $=r.timestamp.toISOString(),o=this.config.enableColors?this.colorizeLevel(r.level):r.level,i=Object.keys(n).length>0?` [${Object.entries(n).map(([u,v])=>`${u}=${v}`).join(", ")}]`:"",t=`${$} ${o}${i}: ${r.message}`;if(r.duration!==void 0)t+=` (${r.duration}ms)`;if(r.error)t+=`
|
|
49
49
|
${r.error.stack}`;return t}colorizeLevel(r){if(!this.config.enableColors)return r;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[r]}${r}\x1B[0m`}writeLog(r){if(!this.shouldLog(r.level))return;let n=this.formatMessage(r);if(this.config.enableConsole)(r.level==="ERROR"?console.error:r.level==="WARN"?console.warn:console.log)(n);if(this.config.enableFile&&this.config.filePath);}debug(r,n={}){this.writeLog({level:"DEBUG",message:r,timestamp:new Date,context:{...this.context,...n}})}info(r,n={}){this.writeLog({level:"INFO",message:r,timestamp:new Date,context:{...this.context,...n}})}warn(r,n={},$){this.writeLog({level:"WARN",message:r,timestamp:new Date,context:{...this.context,...n},error:$})}error(r,n={},$){this.writeLog({level:"ERROR",message:r,timestamp:new Date,context:{...this.context,...n},error:$})}child(r){return new Sv({...this.context,...r},this.config)}time(r){let n=Date.now();return()=>{let $=Date.now()-n;this.info(`${r} completed`,{duration:$})}}async measure(r,n,$={}){let o=Date.now(),i={...$,operation:r};this.debug(`Starting ${r}`,i);try{let t=await n(),u=Date.now()-o;return this.info(`Completed ${r}`,{...i,duration:u}),t}catch(t){let u=Date.now()-o;throw this.error(`Failed ${r}`,{...i,duration:u},t instanceof Error?t:Error(String(t))),t}}}var wv;function f6(r,n){return new Sv(r,n)}function Ir(){if(!wv)wv=f6();return wv}var Gg={debug:(r,n)=>Ir().debug(r,n),info:(r,n)=>Ir().info(r,n),warn:(r,n,$)=>Ir().warn(r,n,$),error:(r,n,$)=>Ir().error(r,n,$),child:(r)=>Ir().child(r),time:(r)=>Ir().time(r),measure:(r,n,$)=>Ir().measure(r,n,$)};/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function H6(r){return r instanceof Uint8Array||ArrayBuffer.isView(r)&&r.constructor.name==="Uint8Array"}function Yg(r){if(!Number.isSafeInteger(r)||r<0)throw Error("positive integer expected, got "+r)}function br(r,...n){if(!H6(r))throw Error("Uint8Array expected");if(n.length>0&&!n.includes(r.length))throw Error("Uint8Array expected of length "+n+", got length="+r.length)}function Kg(r){if(typeof r!=="function"||typeof r.create!=="function")throw Error("Hash should be wrapped by utils.createHasher");Yg(r.outputLen),Yg(r.blockLen)}function Gr(r,n=!0){if(r.destroyed)throw Error("Hash instance has been destroyed");if(n&&r.finished)throw Error("Hash#digest() has already been called")}function xg(r,n){br(r);let $=n.outputLen;if(r.length<$)throw Error("digestInto() expects output buffer of length at least "+$)}function C(...r){for(let n=0;n<r.length;n++)r[n].fill(0)}function Mn(r){return new DataView(r.buffer,r.byteOffset,r.byteLength)}function Z(r,n){return r<<32-n|r>>>n}function Zn(r,n){return r<<n|r>>>32-n>>>0}var e6=(()=>typeof Uint8Array.from([]).toHex==="function"&&typeof Uint8Array.fromHex==="function")(),C6=Array.from({length:256},(r,n)=>n.toString(16).padStart(2,"0"));function Pv(r){if(br(r),e6)return r.toHex();let n="";for(let $=0;$<r.length;$++)n+=C6[r[$]];return n}function h6(r){if(typeof r!=="string")throw Error("string expected");return new Uint8Array(new TextEncoder().encode(r))}function rn(r){if(typeof r==="string")r=h6(r);return br(r),r}class nn{}function fn(r){let n=(o)=>r().update(rn(o)).digest(),$=r();return n.outputLen=$.outputLen,n.blockLen=$.blockLen,n.create=()=>r(),n}class Ov extends nn{constructor(r,n){super();this.finished=!1,this.destroyed=!1,Kg(r);let $=rn(n);if(this.iHash=r.create(),typeof this.iHash.update!=="function")throw Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let o=this.blockLen,i=new Uint8Array(o);i.set($.length>o?r.create().update($).digest():$);for(let t=0;t<i.length;t++)i[t]^=54;this.iHash.update(i),this.oHash=r.create();for(let t=0;t<i.length;t++)i[t]^=106;this.oHash.update(i),C(i)}update(r){return Gr(this),this.iHash.update(r),this}digestInto(r){Gr(this),br(r,this.outputLen),this.finished=!0,this.iHash.digestInto(r),this.oHash.update(r),this.oHash.digestInto(r),this.destroy()}digest(){let r=new Uint8Array(this.oHash.outputLen);return this.digestInto(r),r}_cloneInto(r){r||(r=Object.create(Object.getPrototypeOf(this),{}));let{oHash:n,iHash:$,finished:o,destroyed:i,blockLen:t,outputLen:u}=this;return r=r,r.finished=o,r.destroyed=i,r.blockLen=t,r.outputLen=u,r.oHash=n._cloneInto(r.oHash),r.iHash=$._cloneInto(r.iHash),r}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}}var Hn=(r,n,$)=>new Ov(r,n).update($).digest();Hn.create=(r,n)=>new Ov(r,n);function y6(r,n,$,o){if(typeof r.setBigUint64==="function")return r.setBigUint64(n,$,o);let i=BigInt(32),t=BigInt(4294967295),u=Number($>>i&t),v=Number($&t),g=o?4:0,c=o?0:4;r.setUint32(n+g,u,o),r.setUint32(n+c,v,o)}function en(r,n,$){return r&n^~r&$}function Cn(r,n,$){return r&n^r&$^n&$}class tn extends nn{constructor(r,n,$,o){super();this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.blockLen=r,this.outputLen=n,this.padOffset=$,this.isLE=o,this.buffer=new Uint8Array(r),this.view=Mn(this.buffer)}update(r){Gr(this),r=rn(r),br(r);let{view:n,buffer:$,blockLen:o}=this,i=r.length;for(let t=0;t<i;){let u=Math.min(o-this.pos,i-t);if(u===o){let v=Mn(r);for(;o<=i-t;t+=o)this.process(v,t);continue}if($.set(r.subarray(t,t+u),this.pos),this.pos+=u,t+=u,this.pos===o)this.process(n,0),this.pos=0}return this.length+=r.length,this.roundClean(),this}digestInto(r){Gr(this),xg(r,this),this.finished=!0;let{buffer:n,view:$,blockLen:o,isLE:i}=this,{pos:t}=this;if(n[t++]=128,C(this.buffer.subarray(t)),this.padOffset>o-t)this.process($,0),t=0;for(let l=t;l<o;l++)n[l]=0;y6($,o-8,BigInt(this.length*8),i),this.process($,0);let u=Mn(r),v=this.outputLen;if(v%4)throw Error("_sha2: outputLen should be aligned to 32bit");let g=v/4,c=this.get();if(g>c.length)throw Error("_sha2: outputLen bigger than state");for(let l=0;l<g;l++)u.setUint32(4*l,c[l],i)}digest(){let{buffer:r,outputLen:n}=this;this.digestInto(r);let $=r.slice(0,n);return this.destroy(),$}_cloneInto(r){r||(r=new this.constructor),r.set(...this.get());let{blockLen:n,buffer:$,length:o,finished:i,destroyed:t,pos:u}=this;if(r.destroyed=t,r.finished=i,r.length=o,r.pos=u,o%n)r.buffer.set($);return r}clone(){return this._cloneInto()}}var y=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var $n=Uint32Array.from([1732584193,4023233417,2562383102,271733878,3285377520]),vr=new Uint32Array(80);class Nv extends tn{constructor(){super(64,20,8,!1);this.A=$n[0]|0,this.B=$n[1]|0,this.C=$n[2]|0,this.D=$n[3]|0,this.E=$n[4]|0}get(){let{A:r,B:n,C:$,D:o,E:i}=this;return[r,n,$,o,i]}set(r,n,$,o,i){this.A=r|0,this.B=n|0,this.C=$|0,this.D=o|0,this.E=i|0}process(r,n){for(let v=0;v<16;v++,n+=4)vr[v]=r.getUint32(n,!1);for(let v=16;v<80;v++)vr[v]=Zn(vr[v-3]^vr[v-8]^vr[v-14]^vr[v-16],1);let{A:$,B:o,C:i,D:t,E:u}=this;for(let v=0;v<80;v++){let g,c;if(v<20)g=en(o,i,t),c=1518500249;else if(v<40)g=o^i^t,c=1859775393;else if(v<60)g=Cn(o,i,t),c=2400959708;else g=o^i^t,c=3395469782;let l=Zn($,5)+g+u+c+vr[v]|0;u=t,t=i,i=Zn(o,30),o=$,$=l}$=$+this.A|0,o=o+this.B|0,i=i+this.C|0,t=t+this.D|0,u=u+this.E|0,this.set($,o,i,t,u)}roundClean(){C(vr)}destroy(){this.set(0,0,0,0,0),C(this.buffer)}}var Qg=fn(()=>new Nv);var qg=Qg;var a6=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),cr=new Uint32Array(64);class Wg extends tn{constructor(r=32){super(64,r,8,!1);this.A=y[0]|0,this.B=y[1]|0,this.C=y[2]|0,this.D=y[3]|0,this.E=y[4]|0,this.F=y[5]|0,this.G=y[6]|0,this.H=y[7]|0}get(){let{A:r,B:n,C:$,D:o,E:i,F:t,G:u,H:v}=this;return[r,n,$,o,i,t,u,v]}set(r,n,$,o,i,t,u,v){this.A=r|0,this.B=n|0,this.C=$|0,this.D=o|0,this.E=i|0,this.F=t|0,this.G=u|0,this.H=v|0}process(r,n){for(let l=0;l<16;l++,n+=4)cr[l]=r.getUint32(n,!1);for(let l=16;l<64;l++){let k=cr[l-15],b=cr[l-2],_=Z(k,7)^Z(k,18)^k>>>3,O=Z(b,17)^Z(b,19)^b>>>10;cr[l]=O+cr[l-7]+_+cr[l-16]|0}let{A:$,B:o,C:i,D:t,E:u,F:v,G:g,H:c}=this;for(let l=0;l<64;l++){let k=Z(u,6)^Z(u,11)^Z(u,25),b=c+k+en(u,v,g)+a6[l]+cr[l]|0,O=(Z($,2)^Z($,13)^Z($,22))+Cn($,o,i)|0;c=g,g=v,v=u,u=t+b|0,t=i,i=o,o=$,$=b+O|0}$=$+this.A|0,o=o+this.B|0,i=i+this.C|0,t=t+this.D|0,u=u+this.E|0,v=v+this.F|0,g=g+this.G|0,c=c+this.H|0,this.set($,o,i,t,u,v,g,c)}roundClean(){C(cr)}destroy(){this.set(0,0,0,0,0,0,0,0),C(this.buffer)}}var Lg=fn(()=>new Wg);class hn{config;encoder=new TextEncoder;constructor(r){this.config={algorithm:r.algorithm||"sha256",header:r.signatureHeader||"X-Webhook-Signature",prefix:r.signaturePrefix||"sha256="}}createSignedPayload(r,n){return`${n}.${r}`}generateSignature(r,n){let $=this.generateSignatureDigest(r,n);return this.config.prefix?`${this.config.prefix}${$}`:$}generateSignatureWithTimestamp(r,n,$){return this.generateSignature(this.createSignedPayload(r,n),$)}verifySignature(r,n,$){try{let o=this.generateSignature(r,$);return this.constantTimeCompare(n,o)}catch(o){return Gg.error("Signature verification failed",void 0,o instanceof Error?o:Error(String(o))),!1}}verifySignatureWithTimestamp(r,n,$,o){return this.verifySignature(this.createSignedPayload(r,n),$,o)}extractSignature(r){let n=this.config.header.toLowerCase();for(let[$,o]of Object.entries(r))if($.toLowerCase()===n)return o;return null}createSecurityHeaders(r,n){let $=Math.floor(Date.now()/1000).toString(),o=this.generateSignatureWithTimestamp(r,$,n);return{[this.config.header]:o,"X-Webhook-Timestamp":$,"X-Webhook-ID":this.generateWebhookId(),"User-Agent":"K-Message-Webhook/1.0"}}verifyTimestamp(r,n=300){try{let $=(()=>{if(/^[0-9]+$/.test(r.trim()))return parseInt(r,10);let t=new Date(r);if(Number.isNaN(t.getTime()))return NaN;return Math.floor(t.getTime()/1000)})(),o=Math.floor(Date.now()/1000);return Math.abs(o-$)<=n}catch{return!1}}generateWebhookId(){let r=new Uint8Array(16);if(globalThis.crypto?.getRandomValues)globalThis.crypto.getRandomValues(r);else for(let n=0;n<r.length;n++)r[n]=Math.floor(Math.random()*256);return`wh_${Pv(r)}`}generateSignatureDigest(r,n){let $=this.encoder.encode(n),o=this.encoder.encode(r),i=this.config.algorithm==="sha1"?Hn(qg,$,o):Hn(Lg,$,o);return Pv(i)}constantTimeCompare(r,n){if(r.length!==n.length)return!1;let $=0;for(let o=0;o<r.length;o++)$|=r.charCodeAt(o)^n.charCodeAt(o);return $===0}updateConfig(r){this.config={...this.config,...r}}getConfig(){return{...this.config}}}class zv{async fetch(r,n){return fetch(r,n)}}class Eg{responses=new Map;defaultResponse=new Response(JSON.stringify({status:"ok"}),{status:200,statusText:"OK",headers:{"content-type":"application/json"}});setMockResponse(r,n){this.responses.set(r,n)}setDefaultResponse(r){this.defaultResponse=r}async fetch(r,n){let $=this.responses.get(r);if($)return $;return this.defaultResponse}}class Vg{config;httpClient;securityManager;retryManager;constructor(r,n){this.config=r,this.httpClient=n||new zv,this.securityManager=new hn(r),this.retryManager=new An(r)}async dispatch(r,n){let $=JSON.stringify(r),o=(()=>{if(r.timestamp instanceof Date)return r.timestamp;let u=new Date(r.timestamp);return Number.isNaN(u.getTime())?new Date:u})(),i=Math.floor(o.getTime()/1000).toString(),t={id:this.generateDeliveryId(),endpointId:n.id,eventId:r.id,eventType:r.type,url:n.url,httpMethod:"POST",headers:this.buildHeaders(n,r,$,i),payload:$,attempts:[],status:"pending",createdAt:new Date};return await this.executeDelivery(t,n),t}async executeDelivery(r,n){let $=n.retryConfig?.maxRetries||this.config.maxRetries;for(let o=1;o<=$+1;o++){let i=await this.makeHttpRequest(r,n,o);if(r.attempts.push(i),i.httpStatus&&i.httpStatus>=200&&i.httpStatus<300){r.status="success",r.completedAt=new Date;return}if(!(o<=$&&this.shouldRetryAttempt(o,i))){r.status="failed",r.completedAt=new Date;return}let u=this.calculateRetryDelay(o,n);r.nextRetryAt=new Date(Date.now()+u),await this.sleep(u)}r.status="exhausted",r.completedAt=new Date}shouldRetryAttempt(r,n){if(typeof n.httpStatus==="number")return this.retryManager.shouldRetryStatus(n.httpStatus);if(n.error)return this.retryManager.shouldRetry(r,Error(n.error));return!0}async makeHttpRequest(r,n,$){let o=Date.now(),i={attemptNumber:$,timestamp:new Date,latencyMs:0};try{let t=await this.httpClient.fetch(r.url,{method:r.httpMethod,headers:r.headers,body:r.payload,signal:AbortSignal.timeout(this.config.timeoutMs)});i.httpStatus=t.status,i.responseBody=await t.text();let u={};if(t.headers.forEach((v,g)=>{u[g]=v}),i.responseHeaders=u,i.latencyMs=Date.now()-o,!t.ok)i.error=`HTTP ${t.status}: ${t.statusText}`}catch(t){i.latencyMs=Date.now()-o,i.error=t instanceof Error?t.message:"Unknown error"}return i}buildHeaders(r,n,$,o){let i={"Content-Type":"application/json","X-Webhook-ID":n.id,"X-Webhook-Event":n.type,"X-Webhook-Timestamp":o,"User-Agent":"K-Message-Webhook/1.0"};if(r.headers)Object.assign(i,r.headers);if(this.config.enableSecurity){let t=(typeof r.secret==="string"&&r.secret.length>0?r.secret:typeof this.config.secretKey==="string"&&this.config.secretKey.length>0?this.config.secretKey:void 0)||void 0;if(t){let u=this.securityManager.generateSignatureWithTimestamp($,o,t),v=this.securityManager.getConfig().header;i[v]=u}}return i}calculateRetryDelay(r,n){let $=n.retryConfig?.retryDelayMs||this.config.retryDelayMs,o=n.retryConfig?.backoffMultiplier||this.config.backoffMultiplier||2,i=$*o**r;if(typeof this.config.maxDelayMs==="number")i=Math.min(i,this.config.maxDelayMs);if(this.config.jitter!==!1)i=i*(0.5+Math.random()*0.5);return Math.max(0,Math.floor(i))}sleep(r){return new Promise((n)=>setTimeout(n,r))}generateDeliveryId(){return`delivery_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}async shutdown(){}}function jv(r){if(typeof r!=="string")return;let n=r.trim();return n.length>0?n:void 0}function Ag(r,n){let $=r.openFallback??"masked";if($==="plaintext"){if(!r.unsafeAllowPlaintextStorage)throw new Xr("policy","openFallback=plaintext requires unsafeAllowPlaintextStorage=true",{rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback"},{fieldPath:"openFallback",failMode:"open",openFallback:"plaintext"});return n}if($==="null")return"";return Xg()(n)}async function Tg(r,n){let $=jv(n.value);if(!$)return;if(!r||r.enabled===!1)return $;let o=r.failMode??"closed",i=r.keyResolver;try{let t={tenantId:n.tenantId,tableName:n.aad.tableName,fieldPath:n.path,messageId:n.aad.messageId,providerId:n.aad.providerId},u=i?jv((await i.resolveEncryptKey(t)).kid):void 0,v=await r.provider.encrypt({value:$,path:n.path,aad:n.aad,...u?{kid:u}:{}});return typeof v.ciphertext==="string"?v.ciphertext:JSON.stringify(v.ciphertext)}catch(t){if(o==="closed")throw t;return Ag(r,$)}}async function Rg(r,n){let $=jv(n.value);if(!$)return;if(!r||r.enabled===!1)return $;let o=r.failMode??"closed";try{let i={tenantId:n.tenantId,tableName:n.aad.tableName,fieldPath:n.path,messageId:n.aad.messageId,providerId:n.aad.providerId},t=r.keyResolver?.resolveDecryptKeys?await r.keyResolver.resolveDecryptKeys({...i,ciphertext:$}):void 0;return await r.provider.decrypt({ciphertext:$,path:n.path,aad:n.aad,...Array.isArray(t)&&t.length>0?{candidateKids:t}:{}})}catch(i){if(o==="closed")throw i;return Ag(r,$)}}class Bg{endpoints=new Map;deliveries=new Map;options;constructor(r={}){this.options=r,this.validateCryptoOptions(this.options.fieldCrypto)}async addEndpoint(r){this.endpoints.set(r.id,await this.protectEndpoint(r))}async updateEndpoint(r,n){if(!this.endpoints.has(r))throw Error(`Endpoint ${r} not found`);this.endpoints.set(r,await this.protectEndpoint(n))}async removeEndpoint(r){this.endpoints.delete(r)}async getEndpoint(r){let n=this.endpoints.get(r);if(!n)return null;return await this.revealEndpoint(n)}async listEndpoints(){return await Promise.all(Array.from(this.endpoints.values()).map((r)=>this.revealEndpoint(r)))}async addDelivery(r){this.deliveries.set(r.id,await this.protectDelivery(r))}async getDeliveries(r,n,$,o,i=100){let t=Array.from(this.deliveries.values());if(r)t=t.filter((v)=>v.endpointId===r);if(n)t=t.filter((v)=>v.createdAt>=n.start&&v.createdAt<=n.end);if($)t=t.filter((v)=>v.eventType===$);if(o)t=t.filter((v)=>v.status===o);let u=t.sort((v,g)=>g.createdAt.getTime()-v.createdAt.getTime()).slice(0,i);return await Promise.all(u.map((v)=>this.revealDelivery(v)))}async getFailedDeliveries(r,n){return(await this.getDeliveries(r,void 0,n,void 0,1000)).filter((o)=>o.status==="failed"||o.status==="exhausted")}async protectEndpoint(r){let n={tableName:"webhook_endpoint",messageId:r.id},$=await Tg(this.options.fieldCrypto?.endpoint,{value:r.secret,path:"secret",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,...$?{secret:$}:{}}}async revealEndpoint(r){let n={tableName:"webhook_endpoint",messageId:r.id},$=await Rg(this.options.fieldCrypto?.endpoint,{value:r.secret,path:"secret",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,...$?{secret:$}:{}}}async protectDelivery(r){let n={tableName:"webhook_delivery",messageId:r.id,providerId:r.endpointId},$=await Tg(this.options.fieldCrypto?.delivery,{value:r.payload,path:"payload",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,payload:$??r.payload}}async revealDelivery(r){let n={tableName:"webhook_delivery",messageId:r.id,providerId:r.endpointId},$=await Rg(this.options.fieldCrypto?.delivery,{value:r.payload,path:"payload",aad:n,tenantId:this.options.fieldCrypto?.tenantId});return{...r,payload:$??r.payload}}validateCryptoOptions(r){if(!r)return;if(r.endpoint)_v(r.endpoint);if(r.delivery)_v(r.delivery)}}export{Bg as WebhookRegistry,Vg as WebhookDispatcher,hn as SecurityManager,An as RetryManager,Xv as QueueManager,Eg as MockHttpClient,Fv as LoadBalancer,jg as EventStore,zg as EndpointManager,Gv as DeliveryStore,zv as DefaultHttpClient,Jv as BatchDispatcher};
|
|
50
50
|
|
|
51
|
-
//# debugId=
|
|
51
|
+
//# debugId=D643B82BF32AA42664756E2164756E21
|
|
52
52
|
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k-msg/webhook",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.6",
|
|
4
4
|
"packageManager": "bun@1.3.11",
|
|
5
5
|
"description": "Webhook system for real-time message event notifications",
|
|
6
6
|
"type": "module",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"publish": "bun publish --access public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@k-msg/core": "0.29.
|
|
44
|
+
"@k-msg/core": "0.29.6",
|
|
45
45
|
"@noble/hashes": "^1.8.0",
|
|
46
46
|
"zod": "^4.0.14"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"typescript": "^
|
|
49
|
+
"typescript": "^6.0.2",
|
|
50
50
|
"@types/bun": "^1.3.11"
|
|
51
51
|
},
|
|
52
52
|
"keywords": [
|