@k-msg/core 0.8.0 → 0.10.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/index.js CHANGED
@@ -42,5 +42,5 @@ ${r.error.stack}`;return n}colorizeLevel(r){if(!this.config.enableColors)return
42
42
  ${o.join(`
43
43
  `)}`)}throw i}}static getDefaults(){return At.parse({})}}var q4={logger:{level:"DEBUG",enableColors:!0,enableJson:!1},server:{enableDocs:!0}},X4={logger:{level:"INFO",enableColors:!1,enableJson:!0},server:{enableDocs:!1},security:{apiKeyRequired:!0,rateLimitEnabled:!0,maxRequestsPerMinute:1000,enableCors:!0}};function K4(r,i){return At.parse({...r,...i,server:{...r.server,...i.server},logger:{...r.logger,...i.logger},providers:{...r.providers,...i.providers},features:{...r.features,...i.features},security:{...r.security,...i.security}})}function H4(r,i){switch(r){case"iwinv":return El.parse(i);case"sms":return jl.parse(i);default:throw Error(`Unknown provider: ${r}`)}}var Er;((b)=>{b.INVALID_REQUEST="INVALID_REQUEST";b.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";b.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";b.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";b.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";b.NETWORK_ERROR="NETWORK_ERROR";b.NETWORK_TIMEOUT="NETWORK_TIMEOUT";b.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";b.PROVIDER_ERROR="PROVIDER_ERROR";b.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";b.UNKNOWN_ERROR="UNKNOWN_ERROR"})(Er||={});class V extends Error{code;details;constructor(r,i,o){super(i);if(this.name="KMsgError",this.code=r,this.details=o,Error.captureStackTrace)Error.captureStackTrace(this,V)}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details}}}var Al={isRetryable:(r)=>{if(r instanceof V)return["NETWORK_ERROR","RATE_LIMIT_EXCEEDED","PROVIDER_ERROR"].includes(r.code);return!1}};class qc{config;startTime=Date.now();services=new Map;lastCheck=new Map;constructor(r={}){this.config=r}registerService(r,i){this.services.set(r,i)}unregisterService(r){return this.lastCheck.delete(r),this.services.delete(r)}clearServices(){this.services.clear(),this.lastCheck.clear()}async checkHealth(){let r=Date.now(),i={},o=!0;for(let[e,n]of this.services)try{let t=await Promise.race([n(),this.timeoutPromise(this.config.timeout||5000)]);if(i[e]={...t,lastCheck:new Date,latency:Date.now()-r},this.lastCheck.set(e,i[e]),!t.healthy)o=!1}catch(t){let v={healthy:!1,error:t instanceof Error?t.message:"Unknown error",lastCheck:new Date,latency:Date.now()-r};i[e]=v,this.lastCheck.set(e,v),o=!1}return{healthy:o,timestamp:new Date,uptime:Date.now()-this.startTime,services:i,...this.config.includeMetrics&&{metrics:{totalServices:this.services.size,healthyServices:Object.values(i).filter((e)=>e.healthy).length,averageLatency:this.calculateAverageLatency(i)}}}}getLastKnownStatus(){let r={},i=!0;for(let[o,e]of this.lastCheck)if(r[o]=e,!e.healthy)i=!1;return{healthy:i,timestamp:new Date,uptime:Date.now()-this.startTime,services:r}}async timeoutPromise(r){return new Promise((i,o)=>{setTimeout(()=>o(Error(`Health check timeout after ${r}ms`)),r)})}calculateAverageLatency(r){let i=Object.values(r).map((o)=>o.latency).filter((o)=>typeof o==="number");return i.length>0?i.reduce((o,e)=>o+e,0)/i.length:0}}class Xc{static database(){return async()=>{return{healthy:!0}}}static external(r,i=5000){return async()=>{let o=Date.now();try{let e=await fetch(r,{signal:AbortSignal.timeout(i)});return{healthy:e.ok,latency:Date.now()-o,...e.ok?{}:{error:`HTTP ${e.status}`}}}catch(e){return{healthy:!1,latency:Date.now()-o,error:e instanceof Error?e.message:"Unknown error"}}}}static memory(r=500){return async()=>{let o=process.memoryUsage().heapUsed/1024/1024;return{healthy:o<r,...o>=r?{error:`Memory usage ${o.toFixed(1)}MB exceeds limit ${r}MB`}:{}}}}}class Z{static defaultOptions={maxAttempts:3,initialDelay:1000,maxDelay:30000,backoffMultiplier:2,jitter:!0,retryCondition:(r)=>Al.isRetryable(r)};static async execute(r,i={}){let o={...Z.defaultOptions,...i},e,n=o.initialDelay;for(let t=1;t<=o.maxAttempts;t++)try{return await r()}catch(v){if(e=v,t===o.maxAttempts||!o.retryCondition(e,t))throw e;let u=o.jitter?n+Math.random()*n*0.1:n;o.onRetry?.(e,t),await new Promise((l)=>setTimeout(l,u)),n=Math.min(n*o.backoffMultiplier,o.maxDelay)}throw e}static createRetryableFunction(r,i={}){return async(...o)=>{return Z.execute(()=>r(...o),i)}}}class zt{static async execute(r,i,o={}){let e={concurrency:5,retryOptions:{maxAttempts:3,initialDelay:1000,maxDelay:1e4,backoffMultiplier:2,jitter:!0},failFast:!1,...o},n=Date.now(),t=[],v=[],u=0,l=Z.createRetryableFunction(i,e.retryOptions),$=zt.createBatches(r,e.concurrency);for(let b of $){let S=b.map(async(O)=>{try{let j=await l(O);t.push({item:O,result:j})}catch(j){if(v.push({item:O,error:j}),e.failFast)throw new V("MESSAGE_SEND_FAILED",`Bulk operation failed fast after ${v.length} failures`,{totalItems:r.length,failedCount:v.length})}finally{u++,e.onProgress?.(u,r.length,v.length)}});if(await Promise.allSettled(S),e.failFast&&v.length>0)break}let c=Date.now()-n;return{successful:t,failed:v,summary:{total:r.length,successful:t.length,failed:v.length,duration:c}}}static createBatches(r,i){let o=[];for(let e=0;e<r.length;e+=i)o.push(r.slice(e,e+i));return o}}class Mn{options;state="CLOSED";failureCount=0;lastFailureTime=0;nextAttemptTime=0;constructor(r){this.options=r}async execute(r){let i=Date.now();switch(this.state){case"OPEN":if(i<this.nextAttemptTime)throw new V("NETWORK_SERVICE_UNAVAILABLE","Circuit breaker is OPEN",{state:this.state,nextAttemptTime:this.nextAttemptTime});this.state="HALF_OPEN",this.options.onHalfOpen?.();break;case"HALF_OPEN":break;case"CLOSED":break}try{let o=await Promise.race([r(),new Promise((e,n)=>setTimeout(()=>n(new V("NETWORK_TIMEOUT","Circuit breaker timeout",{timeout:this.options.timeout})),this.options.timeout))]);if(this.state==="HALF_OPEN")this.state="CLOSED",this.failureCount=0,this.options.onClose?.();return o}catch(o){throw this.recordFailure(),o}}recordFailure(){if(this.failureCount++,this.lastFailureTime=Date.now(),this.failureCount>=this.options.failureThreshold)this.state="OPEN",this.nextAttemptTime=this.lastFailureTime+this.options.resetTimeout,this.options.onOpen?.()}getState(){return this.state}getFailureCount(){return this.failureCount}reset(){this.state="CLOSED",this.failureCount=0,this.lastFailureTime=0,this.nextAttemptTime=0}}class Fn{maxRequests;windowMs;requests=[];constructor(r,i){this.maxRequests=r;this.windowMs=i}async acquire(){let r=Date.now();if(this.requests=this.requests.filter((i)=>r-i<this.windowMs),this.requests.length>=this.maxRequests){let i=Math.min(...this.requests),o=this.windowMs-(r-i);if(o>0)return await new Promise((e)=>setTimeout(e,o)),this.acquire()}this.requests.push(r)}canMakeRequest(){let r=Date.now();return this.requests=this.requests.filter((i)=>r-i<this.windowMs),this.requests.length<this.maxRequests}getRemainingRequests(){let r=Date.now();return this.requests=this.requests.filter((i)=>r-i<this.windowMs),Math.max(0,this.maxRequests-this.requests.length)}}var Kc={createResilientFunction(r,i={}){let o,e;if(i.circuitBreaker)o=new Mn(i.circuitBreaker);if(i.rateLimiter)e=new Fn(i.rateLimiter.maxRequests,i.rateLimiter.windowMs);return async(...n)=>{if(e)await e.acquire();let t=async()=>{let v=async()=>{if(i.timeout)return Promise.race([r(...n),new Promise((u,l)=>setTimeout(()=>l(new V("NETWORK_TIMEOUT","Operation timed out",{timeout:i.timeout})),i.timeout))]);return r(...n)};if(o)return o.execute(v);return v()};try{return await Z.execute(t,i.retryOptions)}catch(v){if(i.fallback)return console.warn("Primary operation failed, using fallback:",v),i.fallback(...n);throw v}}}};class Tl{fallbackStrategies=new Map;registerFallback(r,i){this.fallbackStrategies.set(r,i)}async executeWithFallback(r,i,o={}){let e=o.timeout||1e4;try{return await Promise.race([Z.execute(i,o.retryOptions),new Promise((t,v)=>setTimeout(()=>v(new V("NETWORK_TIMEOUT",`Operation ${r} timed out`,{operationName:r,timeout:e})),e))])}catch(n){console.warn(`Primary operation ${r} failed, attempting fallback:`,n);let t=this.fallbackStrategies.get(r);if(t)try{return await t()}catch(v){throw new V("UNKNOWN_ERROR",`Both primary and fallback operations failed for ${r}`,{operationName:r,primaryError:n.message,fallbackError:v.message,cause:n})}throw n}}}class zl{services;healthStatus=new Map;lastCheck=new Map;checkInterval;intervalId;constructor(r,i=30000){this.services=r;this.checkInterval=i}start(){this.intervalId=setInterval(()=>{this.checkAllServices()},this.checkInterval),this.checkAllServices()}stop(){if(this.intervalId)clearInterval(this.intervalId),this.intervalId=void 0}async checkAllServices(){let r=Array.from(this.services.entries()).map(async([i,o])=>{try{let e=await o(),n=this.healthStatus.get(i);if(this.healthStatus.set(i,e),this.lastCheck.set(i,Date.now()),n!==void 0&&n!==e)console.log(`Service ${i} status changed: ${n?"healthy":"unhealthy"} -> ${e?"healthy":"unhealthy"}`)}catch(e){this.healthStatus.set(i,!1),this.lastCheck.set(i,Date.now()),console.error(`Health check failed for ${i}:`,e)}});await Promise.allSettled(r)}getServiceHealth(r){return this.healthStatus.get(r)}getAllHealth(){return Object.fromEntries(this.healthStatus)}isServiceHealthy(r){return this.healthStatus.get(r)===!0}getLastCheckTime(r){return this.lastCheck.get(r)}}var Yn=(r)=>({isSuccess:!0,isFailure:!1,value:r}),Qn=(r)=>({isSuccess:!1,isFailure:!0,error:r}),M4={map(r,i){if(r.isSuccess)return Yn(i(r.value));return r},flatMap(r,i){if(r.isSuccess)return i(r.value);return r},mapError(r,i){if(r.isFailure)return Qn(i(r.error));return r},unwrap(r){if(r.isSuccess)return r.value;throw r.error},unwrapOr(r,i){if(r.isSuccess)return r.value;return i},unwrapOrElse(r,i){if(r.isSuccess)return r.value;return i(r.error)},match(r,i){if(r.isSuccess)return i.ok(r.value);return i.fail(r.error)},async fromPromise(r){try{let i=await r;return Yn(i)}catch(i){return Qn(i)}},isOk(r){return r.isSuccess},isFail(r){return r.isFailure}};var Bn=require("bun:test");class Hc{id;name;supportedTypes;constructor(r="mock",i="Mock Provider"){this.id=r,this.name=i,this.supportedTypes=["ALIMTALK","FRIENDTALK","SMS","LMS","MMS","NSA","VOICE","FAX","RCS_SMS","RCS_LMS","RCS_MMS","RCS_TPL","RCS_ITPL","RCS_LTPL"]}async healthCheck(){return{healthy:!0,issues:[]}}async send(r){if(r.to==="01000000000")return Qn(new V("INVALID_REQUEST","Invalid phone number"));return Yn({messageId:r.messageId||`mock_${Date.now()}`,providerId:this.id,providerMessageId:`mock_${Date.now()}`,status:"SENT",type:r.type,to:r.to})}}var F4={assertKMsgError:(r,i)=>{Bn.expect(r).toBeInstanceOf(V),Bn.expect(r.code).toBe(i)},assertSuccess:(r)=>{if(Bn.expect(r.isSuccess).toBe(!0),r.isSuccess)return r.value;throw Error("Expected success but got failure")},assertFailure:(r)=>{if(Bn.expect(r.isFailure).toBe(!0),r.isFailure)return r.error;throw Error("Expected failure but got success")}};
44
44
 
45
- //# debugId=C956A481D492CE4464756E2164756E21
45
+ //# debugId=A60491C805444B0964756E2164756E21
46
46
  //# sourceMappingURL=index.js.map