@k-msg/core 0.29.8 → 0.30.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/README.md +37 -0
- package/dist/errors.d.ts +15 -2
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/dist/provider.d.ts +32 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -22,6 +22,43 @@ npm install @k-msg/core
|
|
|
22
22
|
bun add @k-msg/core
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Retry policy from JSON
|
|
26
|
+
|
|
27
|
+
Use the core parser for environment-backed provider policies instead of
|
|
28
|
+
reimplementing status and retry-delay normalization in each application:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import {
|
|
32
|
+
normalizeProviderError,
|
|
33
|
+
parseErrorRetryPolicyFromJson,
|
|
34
|
+
} from "@k-msg/core";
|
|
35
|
+
|
|
36
|
+
const policy = parseErrorRetryPolicyFromJson(
|
|
37
|
+
JSON.stringify({
|
|
38
|
+
retryableCodes: ["NETWORK_TIMEOUT"],
|
|
39
|
+
nonRetryableStatuses: ["400"],
|
|
40
|
+
retryableStatuses: ["429", "503"],
|
|
41
|
+
retryAfterMs: {
|
|
42
|
+
defaultMs: 1_000,
|
|
43
|
+
byCode: { VENDOR_BUSY: 2_000 },
|
|
44
|
+
byStatus: { "429": 3_000 },
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
{ mode: "compat" },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const normalized = normalizeProviderError(providerError, {
|
|
51
|
+
mode: "compat",
|
|
52
|
+
policy: policy ?? undefined,
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Policy keys are trimmed and normalized case-insensitively. In conflicts,
|
|
57
|
+
explicit non-retryable entries win. Declarative retry delays resolve in this
|
|
58
|
+
order: direct error metadata, provider error code, canonical `KMsgErrorCode`,
|
|
59
|
+
HTTP status, then `defaultMs`. Existing function-based `retryAfterMs(error)`
|
|
60
|
+
resolvers remain supported as overrides.
|
|
61
|
+
|
|
25
62
|
## Example: Implement a Provider
|
|
26
63
|
|
|
27
64
|
```ts
|
package/dist/errors.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare enum KMsgErrorCode {
|
|
|
8
8
|
NETWORK_ERROR = "NETWORK_ERROR",
|
|
9
9
|
NETWORK_TIMEOUT = "NETWORK_TIMEOUT",
|
|
10
10
|
NETWORK_SERVICE_UNAVAILABLE = "NETWORK_SERVICE_UNAVAILABLE",
|
|
11
|
+
REQUEST_ABORTED = "REQUEST_ABORTED",
|
|
11
12
|
PROVIDER_ERROR = "PROVIDER_ERROR",
|
|
12
13
|
MESSAGE_SEND_FAILED = "MESSAGE_SEND_FAILED",
|
|
13
14
|
CRYPTO_CONFIG_ERROR = "CRYPTO_CONFIG_ERROR",
|
|
@@ -19,6 +20,14 @@ export declare enum KMsgErrorCode {
|
|
|
19
20
|
}
|
|
20
21
|
export type RetryPolicyErrorCode = KMsgErrorCode;
|
|
21
22
|
export type ProviderRetryHint = "retryable" | "non_retryable";
|
|
23
|
+
export interface RetryAfterPolicy {
|
|
24
|
+
/** Fallback delay when no code or status mapping matches. */
|
|
25
|
+
defaultMs?: number;
|
|
26
|
+
/** Delays keyed by provider error code or canonical KMsgErrorCode. */
|
|
27
|
+
byCode?: Readonly<Record<string, number>>;
|
|
28
|
+
/** Delays keyed by normalized HTTP status. */
|
|
29
|
+
byStatus?: Readonly<Record<string, number>>;
|
|
30
|
+
}
|
|
22
31
|
export interface KMsgErrorMetadata {
|
|
23
32
|
providerErrorCode?: string;
|
|
24
33
|
providerErrorText?: string;
|
|
@@ -31,6 +40,10 @@ export interface KMsgErrorMetadata {
|
|
|
31
40
|
export interface ErrorRetryPolicy {
|
|
32
41
|
retryableCodes?: readonly KMsgErrorCode[];
|
|
33
42
|
nonRetryableCodes?: readonly KMsgErrorCode[];
|
|
43
|
+
/** Explicit retryable HTTP statuses, normalized case-insensitively. */
|
|
44
|
+
retryableStatuses?: readonly string[];
|
|
45
|
+
/** Explicit non-retryable HTTP statuses; wins on conflicts. */
|
|
46
|
+
nonRetryableStatuses?: readonly string[];
|
|
34
47
|
classifyByStatusCode?: (status: number) => ProviderRetryHint;
|
|
35
48
|
classifyByMessage?: (message: string) => ProviderRetryHint | undefined;
|
|
36
49
|
/**
|
|
@@ -38,9 +51,9 @@ export interface ErrorRetryPolicy {
|
|
|
38
51
|
*/
|
|
39
52
|
fallback?: ProviderRetryHint;
|
|
40
53
|
/**
|
|
41
|
-
* Optional custom retry delay
|
|
54
|
+
* Optional custom retry delay resolver or declarative mapping.
|
|
42
55
|
*/
|
|
43
|
-
retryAfterMs?: (error: KMsgError) => number | undefined;
|
|
56
|
+
retryAfterMs?: RetryAfterPolicy | ((error: KMsgError) => number | undefined);
|
|
44
57
|
}
|
|
45
58
|
export type ErrorRetryPolicyMode = "safe" | "compat";
|
|
46
59
|
export interface ErrorRetryPolicyIssue {
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var{defineProperty:V,getOwnPropertyNames:Et,getOwnPropertyDescriptor:xt}=Object,Mt=Object.prototype.hasOwnProperty;function vt(t){return this[t]}var _t=(t)=>{var n=(pt??=new WeakMap).get(t),e;if(n)return n;if(n=V({},"__esModule",{value:!0}),t&&typeof t==="object"||typeof t==="function"){for(var i of Et(t))if(!Mt.call(n,i))V(n,i,{get:vt.bind(t,i),enumerable:!(e=xt(t,i))||e.enumerable})}return pt.set(t,n),n},pt;var Nt=(t)=>t;function It(t,n){this[t]=Nt.bind(null,n)}var Ut=(t,n)=>{for(var e in n)V(t,e,{get:n[e],enumerable:!0,configurable:!0,set:It.bind(n,e)})};var vn={};Ut(vn,{validateFieldCryptoConfig:()=>Pt,validateErrorRetryPolicy:()=>gt,toCiphertextEnvelopeString:()=>ln,setGlobalLogger:()=>Fn,selectActiveKidByRollout:()=>N,resolveFieldMode:()=>L,readRuntimeEnv:()=>Sn,parseErrorRetryPolicyFromJson:()=>Gt,ok:()=>it,normalizeRetryAfterMs:()=>x,normalizeProviderError:()=>Yt,normalizePhoneForHash:()=>bt,normalizeMessageStatus:()=>Mn,normalizeErrorRetryPolicy:()=>Kt,loggerMiddleware:()=>Pn,logger:()=>An,isTerminalDeliveryStatus:()=>mn,isPollableDeliveryStatus:()=>Tn,isKMsgTerminalStatus:()=>kn,isKMsgMessageType:()=>En,isKMsgDeliveryStatus:()=>Dn,isCryptoEnvelope:()=>cn,getRuntimeEnvSource:()=>Dt,getRolloutKnownKids:()=>W,getPollableStatuses:()=>On,getLogger:()=>k,fail:()=>st,createVaultTransitKeyResolver:()=>pn,createStaticKeyResolver:()=>Q,createRollingKeyResolver:()=>nn,createRefreshableKeyResolver:()=>v,createNoopFieldCryptoProvider:()=>dn,createLogger:()=>tt,createEnvKeyResolver:()=>rn,createDefaultMasker:()=>X,createAwsKmsKeyResolver:()=>en,createAesGcmFieldCryptoProvider:()=>an,assertFieldCryptoConfig:()=>yn,RetryHandler:()=>T,Result:()=>wn,RateLimiter:()=>et,QUEUED_MESSAGE_STATUS:()=>Rt,Logger:()=>$,LogLevel:()=>ut,KNOWN_MESSAGE_STATUSES:()=>xn,KMsgErrorCode:()=>R,KMsgError:()=>K,KMSG_TERMINAL_STATUSES:()=>mt,KMSG_POLLABLE_STATUSES:()=>rt,KMSG_MESSAGE_TYPES:()=>Ot,KMSG_DELIVERY_STATUSES:()=>kt,FieldCryptoError:()=>M,ErrorUtils:()=>O,CircuitBreaker:()=>nt,BulkOperationHandler:()=>H});module.exports=_t(vn);var R;((l)=>{l.INVALID_REQUEST="INVALID_REQUEST";l.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";l.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";l.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";l.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";l.NETWORK_ERROR="NETWORK_ERROR";l.NETWORK_TIMEOUT="NETWORK_TIMEOUT";l.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";l.PROVIDER_ERROR="PROVIDER_ERROR";l.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";l.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";l.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";l.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";l.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";l.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";l.UNKNOWN_ERROR="UNKNOWN_ERROR"})(R||={});var Bt={["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"}},qt=new Set(Object.values(R)),yt=new Set(["NETWORK_ERROR","RATE_LIMIT_EXCEEDED","NETWORK_TIMEOUT","NETWORK_SERVICE_UNAVAILABLE","PROVIDER_ERROR","UNKNOWN_ERROR"]),ft=new Set(["INVALID_REQUEST","AUTHENTICATION_FAILED","INSUFFICIENT_BALANCE","TEMPLATE_NOT_FOUND","MESSAGE_SEND_FAILED","CRYPTO_CONFIG_ERROR","CRYPTO_ENCRYPT_FAILED","CRYPTO_DECRYPT_FAILED","CRYPTO_HASH_FAILED","CRYPTO_POLICY_VIOLATION"]),P=(t)=>{if(typeof t!=="number"||Number.isNaN(t)||!Number.isFinite(t))return;return Math.trunc(t)},x=(t)=>{let n=P(t);if(n===void 0||n<0)return;return n},G=(t)=>{if(typeof t!=="string")return;return t.toLowerCase().trim()},$t=(t)=>{if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0},w=(t)=>{return typeof t==="object"&&t!==null&&!Array.isArray(t)},u=(t,n)=>{for(let e of n)if(e in t)return t[e];return},Ht=(t)=>{return t.length>0?t:"$"},lt=(t)=>{return t==="compat"?"compat":"safe"},ot=(t)=>{if(t>=500)return"retryable";if(t===408||t===425||t===429)return"retryable";return"non_retryable"},ct=(t)=>{let n=t.toLowerCase();if(n.includes("timeout")||n.includes("temporar")||n.includes("network")||n.includes("retry"))return"retryable";return};class K extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(t,n,e,i={}){super(n);if(this.name="KMsgError",this.code=t,this.details=e,this.providerErrorCode=i.providerErrorCode,this.providerErrorText=i.providerErrorText,this.httpStatus=P(i.httpStatus),this.requestId=typeof i.requestId==="string"?i.requestId:void 0,this.retryAfterMs=P(i.retryAfterMs),this.attempt=P(i.attempt),Array.isArray(i.causeChain))this.causeChain=i.causeChain;else if(i.causeChain!==void 0)this.causeChain=[i.causeChain];let r=Error.captureStackTrace;if(r)r(this,K)}getLocalizedMessage(t="ko"){let n=Bt[this.code];if(n?.[t])return n[t];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}}}var D=(t,n)=>{let e=P(t);if(e!==void 0)return e;if(n==="compat"&&typeof t==="string"){let i=Number(t.trim());if(Number.isFinite(i))return Math.trunc(i)}return},J=(t,n)=>{let e=$t(t);if(e)return e;if(n==="compat"&&(typeof t==="number"||typeof t==="boolean"))return String(t);return},ht=(t)=>{if(typeof t!=="string")return;let n=t.trim().toUpperCase();if(!qt.has(n))return;return n},m=(t,n)=>{t.push({...n,path:Ht(n.path)})},at=(t,n,e,i)=>{if(t===void 0)return[];let r=(()=>{if(Array.isArray(t))return t;if(e==="compat"&&typeof t==="string")return t.split(",").map((f)=>f.trim()).filter((f)=>f.length>0);return m(i,{code:"invalid_type",message:"expected array of KMsgErrorCode values",path:n}),[]})(),s=[],p=new Set;for(let f=0;f<r.length;f+=1){let y=r[f],o=ht(typeof y==="string"?y:e==="compat"?String(y):y);if(!o){m(i,{code:"unknown_code",message:`unknown retry policy code: ${String(y)}`,path:`${n}[${f}]`});continue}if(p.has(o)){m(i,{code:"duplicate_code",message:`duplicate retry policy code: ${o}`,path:`${n}[${f}]`});continue}p.add(o),s.push(o)}return s},Vt=(t,n,e)=>{if(t===void 0)return;if(typeof t==="string"){let i=t.trim().toLowerCase();if(i==="retryable")return"retryable";if(i==="non_retryable"||i==="non-retryable")return"non_retryable"}if(n==="compat"&&typeof t==="boolean")return t?"retryable":"non_retryable";m(e,{code:"invalid_fallback",message:`invalid fallback value: ${String(t)}`,path:"fallback"});return};function gt(t,n={}){let e=lt(n.mode),i=[];if(!w(t))return m(i,{code:"invalid_root",message:"retry policy must be an object",path:"$"}),{policy:null,issues:i};let r=new Set(["retryableCodes","nonRetryableCodes","fallback"]);for(let d of Object.keys(t)){if(r.has(d))continue;m(i,{code:"unknown_field",message:`unknown retry policy field: ${d}`,path:d})}let s=at(t.retryableCodes,"retryableCodes",e,i),p=at(t.nonRetryableCodes,"nonRetryableCodes",e,i),f=Vt(t.fallback,e,i),y=new Set(s),o=new Set(p);for(let d of y){if(!o.has(d))continue;y.delete(d),m(i,{code:"conflicting_code",message:`code '${d}' is both retryable and nonRetryable; nonRetryable wins`,path:"retryableCodes"})}let a={...y.size>0?{retryableCodes:Array.from(y)}:{},...o.size>0?{nonRetryableCodes:Array.from(o)}:{},...f?{fallback:f}:{}};return{policy:a.retryableCodes!==void 0||a.nonRetryableCodes!==void 0||a.fallback!==void 0?a:null,issues:i}}function Kt(t,n={}){return gt(t,n).policy}function Gt(t,n={}){if(typeof t!=="string"||t.trim().length===0)return null;try{let e=JSON.parse(t);return Kt(e,n)}catch{return null}}var dt=(t,n)=>{let e=t.response;if(!w(e))return;return D(u(e,["status","statusCode","httpStatus"]),n)},Jt=(t,n)=>{if(t instanceof K&&Array.isArray(t.causeChain))return t.causeChain.slice();if(w(t)){let s=t.causeChain;if(Array.isArray(s))return s.slice();let p=t.details;if(n==="compat"&&w(p)){let f=p.causeChain;if(Array.isArray(f))return f.slice();if(f!==void 0)return[f]}}let e=[],i=new Set,r=t;for(let s=0;s<8;s+=1){if(!w(r))break;let p=r.cause;if(p===void 0||i.has(p))break;i.add(p),e.push(p),r=p}return e.length>0?e:void 0},Wt=(t)=>{if(t instanceof Error&&typeof t.message==="string")return t.message;if(w(t)&&typeof t.message==="string")return t.message;return typeof t==="string"?t:"Unknown error"};function Yt(t,n={}){let e=lt(n.mode),r=n.defaultCode??"UNKNOWN_ERROR",s={code:"fallback",classification:n.policy?"policy":"fallback"},p,f,y,o,a,h,d,A=(c)=>{if(c.providerErrorCode!==void 0)p=c.providerErrorCode,s.providerErrorCode="metadata";if(c.providerErrorText!==void 0)f=c.providerErrorText,s.providerErrorText="metadata";if(c.httpStatus!==void 0)y=c.httpStatus,s.httpStatus="metadata";if(c.requestId!==void 0)o=c.requestId,s.requestId="metadata";if(c.retryAfterMs!==void 0)a=x(c.retryAfterMs),s.retryAfterMs="metadata";if(c.attempt!==void 0)h=D(c.attempt,e),s.attempt="metadata";if(Array.isArray(c.causeChain))d=c.causeChain.slice(),s.causeChain="metadata"},C=(c,F)=>{if(p===void 0){let g=J(u(c,["providerErrorCode","errorCode","resultCode"]),e);if(g!==void 0)p=g,s.providerErrorCode=F}if(f===void 0){let g=J(u(c,["providerErrorText","errorMessage","msg","message"]),e);if(g!==void 0)f=g,s.providerErrorText=F}if(y===void 0){let g=D(u(c,["httpStatus","statusCode","status"]),e)??dt(c,e);if(g!==void 0)y=g,s.httpStatus=F==="details"?"details":"http"}if(o===void 0){let g=J(u(c,["requestId","request_id","reqId","traceId"]),e);if(g!==void 0)o=g,s.requestId=F}if(a===void 0){let g=x(D(u(c,["retryAfterMs","retry_after_ms","retryAfter"]),e));if(g!==void 0)a=g,s.retryAfterMs=F}if(h===void 0){let g=D(c.attempt,e);if(g!==void 0&&g>0)h=g,s.attempt=F}};if(t instanceof K){if(r=t.code,s.code="input",A(t),e==="compat"&&w(t.details))C(t.details,"details")}else if(w(t)){let c=ht(u(t,["code","errorCode","resultCode"]));if(c!==void 0)r=c,s.code="input";else if(y===void 0){let F=D(u(t,["httpStatus","statusCode","status"]),e)??dt(t,e);if(F!==void 0&&F>=500)r="PROVIDER_ERROR",s.code="http"}if(C(t,"input"),e==="compat"&&w(t.details))C(t.details,"details")}if(d===void 0){let c=Jt(t,e);if(c!==void 0)d=c,s.causeChain="input"}if(n.attempt!==void 0&&D(n.attempt,e)!==void 0){let c=D(n.attempt,e);if(c!==void 0&&c>0)h=c,s.attempt="input"}let b=new K(r,Wt(t),void 0,{providerErrorCode:p,providerErrorText:f,httpStatus:y,requestId:o,retryAfterMs:a,attempt:h,causeChain:d}),l=O.classifyForRetry(b,n.policy);return{code:r,classification:l,...p!==void 0?{providerErrorCode:p}:{},...f!==void 0?{providerErrorText:f}:{},...y!==void 0?{httpStatus:y}:{},...o!==void 0?{requestId:o}:{},...a!==void 0?{retryAfterMs:a}:{},...h!==void 0?{attempt:h}:{},...d!==void 0?{causeChain:d}:{},sources:s}}var O={isRetryable(t,n={}){return O.classifyForRetry(t,n)==="retryable"},classifyForRetry(t,n={}){if(t instanceof K){if(new Set(n.retryableCodes??Array.from(yt)).has(t.code))return"retryable";if(new Set(n.nonRetryableCodes??Array.from(ft)).has(t.code))return"non_retryable";if(t.httpStatus!==void 0)return ot(t.httpStatus);let y=ct(t.message);if(y)return y;if(n.classifyByMessage&&t.message){let o=n.classifyByMessage(t.message);if(o)return o}if(n.fallback)return n.fallback;return"non_retryable"}let e=t&&typeof t==="object"?t:void 0,i=G(e?.status)??G(e?.statusCode)??G(e?.code),r=P(e?.status)??P(e?.statusCode)??P(e?.httpStatus);if(typeof i==="string"&&i.startsWith("5"))return"retryable";if(r!==void 0){if(n.classifyByStatusCode)return n.classifyByStatusCode(r);return ot(r)}let s=typeof e?.message==="string"?ct(e.message):void 0;if(s)return s;if(n.classifyByMessage&&typeof e?.message==="string"){let p=n.classifyByMessage(e.message);if(p)return p}return n.fallback??"non_retryable"},resolveRetryAfterMs(t,n){if(n?.retryAfterMs){let e=n.retryAfterMs(t),i=x(e);if(i!==void 0)return i}if(t.retryAfterMs!==void 0)return x(t.retryAfterMs);if(t.code==="RATE_LIMIT_EXCEEDED"&&t.retryAfterMs===void 0)return;return},isUnknownStatus:(t)=>{if(t===void 0||Number.isNaN(t)||!Number.isFinite(t))return!1;return t<500},toRetryMetadata(t){return{providerErrorCode:t.providerErrorCode,providerErrorText:t.providerErrorText,httpStatus:t.httpStatus,requestId:t.requestId,retryAfterMs:t.retryAfterMs,attempt:t.attempt,causeChain:t.causeChain}},withAttempt(t,n){return new K(t.code,t.message,t.details,{...O.toRetryMetadata(t),attempt:P(n)})},DEFAULT_RETRYABLE_ERROR_CODES:yt,DEFAULT_NON_RETRYABLE_ERROR_CODES:ft};function jt(t){switch(t){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 M extends K{kind;fieldPath;failMode;openFallback;constructor(t,n,e,i={}){super(jt(t),n,e,i);this.name="FieldCryptoError",this.kind=t,this.fieldPath=typeof i.fieldPath==="string"?i.fieldPath:void 0,this.failMode=i.failMode,this.openFallback=i.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}var Qt=["tenantId","providerId","messageId"];function _(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Zt(t){if(typeof t!=="number"||!Number.isFinite(t))return;if(t<=0||t>100)return;return t}function Ct(t){let n=[];for(let e of t){let i=_(e.kid),r=Zt(e.percentage);if(!i||r===void 0)continue;n.push({kid:i,percentage:r})}return n}function Lt(t,n,e){let i=n.map((r)=>{let s=t[r];return typeof s==="string"?s:""}).join("|");return`${e}::${i}`}function Xt(t){let n=2166136261;for(let e=0;e<t.length;e+=1)n^=t.charCodeAt(e),n=n*16777619>>>0;return n>>>0}function zt(t,n){let e=0;for(let i of t)if(e+=i.percentage,n<e)return i.kid;return}function N(t,n,e){let i=Ct(n.buckets),r=_(n.defaultKid)??_(e);if(i.length===0)return r;let s=_(n.seed)??"kmsg-rollout-v1",p=n.stickyFields??Qt,f=Lt(t,p,s),y=Xt(f)%100;return zt(i,y)??r}function W(t){return Ct(t.buckets).map((n)=>n.kid)}function E(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Y(t){if(!Array.isArray(t))return[];return t.map((n)=>E(n)).filter((n)=>Boolean(n))}function j(t){let n=[],e=new Set;for(let i of t){let r=E(i);if(!r||e.has(r))continue;e.add(r),n.push(r)}return n}function tn(t){return E(t.providerId)??"default"}function Q(t){let n=E(t.activeKid)??"default",e=j([n,...Y(t.decryptKids)]);return{async resolveEncryptKey(){return{kid:n}},async resolveDecryptKeys(){return e}}}function v(t){let n=typeof t.cacheTtlMs==="number"&&t.cacheTtlMs>=0?Math.trunc(t.cacheTtlMs):30000,e=E(t.fallback?.activeKid),i=Y(t.fallback?.decryptKids),r;async function s(p){let f=Date.now();if(r&&f<r.expiresAt)return r.value;let y=await t.provider.loadKeySet(p),o=E(y.activeKid)??e??tn(p),a=j([o,...Y(y.decryptKids),...i]),h={activeKid:o,decryptKids:a,refreshedAt:Date.now()};return r={value:h,expiresAt:Date.now()+n},h}return{async resolveEncryptKey(p){return{kid:(await s(p)).activeKid}},async resolveDecryptKeys(p){let f=await s(p);return f.decryptKids??[f.activeKid]}}}function nn(t,n){return{async resolveEncryptKey(e){let i=await t.resolveEncryptKey(e);return{kid:N(e,n,i.kid)??i.kid}},async resolveDecryptKeys(e){let i=await t.resolveEncryptKey(e),r=t.resolveDecryptKeys?await t.resolveDecryptKeys(e):[i.kid],s=N(e,n,i.kid),p=W(n);return j([...s?[s]:[],i.kid,...r??[],...p])}}}function en(t){return v({provider:{async loadKeySet(e){return t.client.getKeyState({...e,...t.keyAlias?{keyAlias:t.keyAlias}:{},...t.region?{region:t.region}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function I(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Ft(t,n){return I(t[n])}function sn(t,n){if(!t)return[];return t.split(n).map((e)=>I(e)).filter((e)=>Boolean(e))}function rn(t={}){let n=globalThis.process?.env,e=t.env??n??{},i=I(t.delimiter)??",",r=t.activeKidEnv??"KMSG_ACTIVE_KID",s=t.decryptKidsEnv??"KMSG_DECRYPT_KIDS",p=Ft(e,r)??I(t.fallbackActiveKid)??"default",f=[p,...sn(Ft(e,s),i),...t.fallbackDecryptKids??[]];return Q({activeKid:p,decryptKids:f})}function pn(t){return v({provider:{async loadKeySet(e){return t.client.getKeyState({...e,...t.mountPath?{mountPath:t.mountPath}:{},...t.keyName?{keyName:t.keyName}:{},...t.namespace?{namespace:t.namespace}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function Z(t){return typeof t==="function"}function At(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function L(t,n,e){let i=t.fields[n];if(i)return i;if(n.startsWith("metadata.")){let r=t.fields["metadata.*"];if(r)return r}return e}function Pt(t,n={}){let e=[];if(!t||typeof t!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!t.provider||typeof t.provider!=="object")e.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!Z(t.provider.encrypt))e.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!Z(t.provider.decrypt))e.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!Z(t.provider.hash))e.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!t.fields||typeof t.fields!=="object")e.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 s=Object.entries(t.fields);if(s.length===0)e.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[p,f]of s){if(!At(p))e.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(f!=="plain"&&f!=="encrypt"&&f!=="encrypt+hash"&&f!=="mask")e.push({message:`unsupported field mode: ${String(f)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${p}`})}}let i=t.failMode??"closed",r=t.openFallback??"masked";if(i==="open"&&r==="plaintext"&&t.unsafeAllowPlaintextStorage!==!0)e.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(t.aadFields)){if(t.aadFields.length===0)e.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let s=0;s<t.aadFields.length;s+=1){let p=t.aadFields[s];if(!At(p))e.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${s}]`})}}if(n.secureMode&&!n.compatPlainColumns){let s=L(t,"to","encrypt+hash"),p=L(t,"from","encrypt+hash");if(s==="plain")e.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(p==="plain")e.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:e.length===0,issues:e}}function yn(t,n={}){let e=Pt(t,n);if(e.valid)return;let i=e.issues[0];if(!i)throw new M("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:e.issues});throw new M("config",i.message,{rule:i.rule,path:i.path,hint:i.hint,issues:e.issues},{fieldPath:i.path})}function U(t){let n=t instanceof Uint8Array?t:new Uint8Array(t),e=typeof globalThis<"u"?globalThis.Buffer:void 0;return(e?e.from(n).toString("base64"):btoa(String.fromCharCode(...n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function B(t){let n=t.replace(/-/g,"+").replace(/_/g,"/"),e=n.length%4===0?n:`${n}${"=".repeat(4-n.length%4)}`,i=typeof globalThis<"u"?globalThis.Buffer:void 0;if(i)return new Uint8Array(i.from(e,"base64"));let r=atob(e),s=new Uint8Array(r.length);for(let p=0;p<r.length;p+=1)s[p]=r.charCodeAt(p);return s}function wt(t,n){if(t instanceof Uint8Array)return t;if(t instanceof ArrayBuffer)return new Uint8Array(t);if(n==="base64url")return B(t);return new TextEncoder().encode(t)}function fn(t){let n=t instanceof Uint8Array?t:new Uint8Array(t);return Array.from(n).map((e)=>e.toString(16).padStart(2,"0")).join("")}function S(t){let n=new Uint8Array(t.byteLength);return n.set(t),n.buffer}function St(t){let n=JSON.parse(t);if(!n||typeof n!=="object"||typeof n.v!=="number"||typeof n.alg!=="string"||typeof n.kid!=="string"||typeof n.iv!=="string"||typeof n.tag!=="string"||typeof n.ct!=="string")throw Error("Invalid ciphertext envelope");return n}function on(t){if(typeof t==="string")return t;return JSON.stringify(t)}function cn(t){if(!t||typeof t!=="object")return!1;let n=t;return typeof n.v==="number"&&typeof n.alg==="string"&&typeof n.kid==="string"&&typeof n.iv==="string"&&typeof n.tag==="string"&&typeof n.ct==="string"}function bt(t){let n=String(t??"").trim();if(n.length===0)return"";let e=n.startsWith("+"),i=n.replace(/\D/g,"");return e?`+${i}`:i}function X(t=3,n=2){return(e)=>{let i=String(e??"");if(i.length<=t+n)return"*".repeat(Math.max(0,i.length));let r=i.slice(0,t),s=i.slice(-n);return`${r}${"*".repeat(i.length-t-n)}${s}`}}function an(t){let n=t.algorithm??"A256GCM",e=t.keyEncoding??"base64url",i=t.hashKeyEncoding??e,r=new Map,s=new Map,p=(y)=>{let o=r.get(y);if(o)return o;let a=t.keys[y];if(!a)throw Error(`Unknown encryption key id: ${y}`);let h=wt(a,e),d=crypto.subtle.importKey("raw",S(h),"AES-GCM",!1,["encrypt","decrypt"]);return r.set(y,d),d},f=(y)=>{let o=s.get(y);if(o)return o;let a=t.hashKeys?.[y]??t.keys[y];if(!a)throw Error(`Unknown hash key id: ${y}`);let h=wt(a,i),d=crypto.subtle.importKey("raw",S(h),{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return s.set(y,d),d};return{async encrypt(y){let o=y.kid??t.activeKid,a=await p(o),h=crypto.getRandomValues(new Uint8Array(12)),d=new TextEncoder().encode(JSON.stringify(y.aad??{})),A=new TextEncoder().encode(y.value),C=await crypto.subtle.encrypt({name:"AES-GCM",iv:S(h),additionalData:S(d),tagLength:128},a,S(A)),b=new Uint8Array(C),l=b.slice(b.length-16),c=b.slice(0,b.length-16);return{ciphertext:{v:1,alg:n,kid:o,iv:U(h),tag:U(l),ct:U(c)},kid:o}},async decrypt(y){let o=St(y.ciphertext),a=y.candidateKids&&y.candidateKids.length>0?y.candidateKids:[o.kid],h=B(o.iv),d=B(o.tag),A=B(o.ct),C=new Uint8Array(A.length+d.length);C.set(A,0),C.set(d,A.length);let b=new TextEncoder().encode(JSON.stringify(y.aad??{})),l;for(let c of a)try{let F=await p(c),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:S(h),additionalData:S(b),tagLength:128},F,S(C));return new TextDecoder().decode(new Uint8Array(g))}catch(F){l=F}throw Error(`Failed to decrypt ciphertext: ${l instanceof Error?l.message:String(l??"unknown")}`)},async hash(y){let o=y.kid??t.activeKid,a=await f(o),h=await crypto.subtle.sign("HMAC",a,S(new TextEncoder().encode(y.value)));return fn(h)},mask(y){return X()(y.value)}}}function dn(){return{encrypt(t){return{ciphertext:JSON.stringify({v:1,alg:"NOOP",kid:"noop",iv:"",tag:"",ct:t.value})}},decrypt(t){try{return St(t.ciphertext).ct}catch{return t.ciphertext}},hash(t){let n=bt(t.value);return U(new TextEncoder().encode(n))},mask(t){return X()(t.value)}}}function ln(t){return on(t)}var ut;((r)=>{r.DEBUG="DEBUG";r.INFO="INFO";r.WARN="WARN";r.ERROR="ERROR"})(ut||={});var hn=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function gn(t){let n=t.toLowerCase();return hn.some((e)=>n.includes(e.toLowerCase()))}function Kn(t){let n=t.trim();if(n.length<=4)return"***";if(n.includes("@")){let[r,s]=n.split("@");return`${r.slice(0,2)}${"*".repeat(Math.max(1,r.length-2))}@${s}`}let e=n.slice(0,3),i=n.slice(-2);return`${e}${"*".repeat(Math.max(1,n.length-5))}${i}`}function z(t,n){if(n===void 0||n===null)return n;if(gn(t)){if(typeof n==="string")return Kn(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((e)=>z(t,e));if(typeof n==="object"){let e={};for(let[i,r]of Object.entries(n))e[i]=z(i,r);return e}return n}function Cn(t){let n={};for(let[e,i]of Object.entries(t))n[e]=z(e,i);return n}class ${config;context;constructor(t={},n={}){this.context=t,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(t){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(t)>=n.indexOf(this.config.level)}formatMessage(t){let n=Cn(t.context);if(this.config.enableJson)return JSON.stringify({level:t.level,message:t.message,timestamp:t.timestamp.toISOString(),context:n,...t.error&&{error:{name:t.error.name,message:t.error.message,stack:t.error.stack}},...t.duration&&{duration:t.duration}});let e=t.timestamp.toISOString(),i=this.config.enableColors?this.colorizeLevel(t.level):t.level,r=Object.keys(n).length>0?` [${Object.entries(n).map(([p,f])=>`${p}=${f}`).join(", ")}]`:"",s=`${e} ${i}${r}: ${t.message}`;if(t.duration!==void 0)s+=` (${t.duration}ms)`;if(t.error)s+=`
|
|
2
|
-
${t.error.stack}`;return s}colorizeLevel(t){if(!this.config.enableColors)return t;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[t]}${t}\x1B[0m`}writeLog(t){if(!this.shouldLog(t.level))return;let n=this.formatMessage(t);if(this.config.enableConsole)(t.level==="ERROR"?console.error:t.level==="WARN"?console.warn:console.log)(n);if(this.config.enableFile&&this.config.filePath);}debug(t,n={}){this.writeLog({level:"DEBUG",message:t,timestamp:new Date,context:{...this.context,...n}})}info(t,n={}){this.writeLog({level:"INFO",message:t,timestamp:new Date,context:{...this.context,...n}})}warn(t,n={},
|
|
1
|
+
var{defineProperty:V,getOwnPropertyNames:Gt,getOwnPropertyDescriptor:Jt}=Object,Wt=Object.prototype.hasOwnProperty;var yt=new WeakMap,Yt=(t)=>{var n=yt.get(t),i;if(n)return n;if(n=V({},"__esModule",{value:!0}),t&&typeof t==="object"||typeof t==="function")Gt(t).map((e)=>!Wt.call(n,e)&&V(n,e,{get:()=>t[e],enumerable:!(i=Jt(t,e))||i.enumerable}));return yt.set(t,n),n};var Vt=(t,n)=>{for(var i in n)V(t,i,{get:n[i],enumerable:!0,configurable:!0,set:(e)=>n[i]=()=>e})};var Wn={};Vt(Wn,{validateFieldCryptoConfig:()=>Rt,validateErrorRetryPolicy:()=>Ot,toCiphertextEnvelopeString:()=>Dn,setGlobalLogger:()=>kn,selectActiveKidByRollout:()=>$,resolveFieldMode:()=>z,readRuntimeEnv:()=>Mn,parseErrorRetryPolicyFromJson:()=>zt,ok:()=>st,normalizeRetryAfterMs:()=>k,normalizeProviderError:()=>en,normalizePhoneForHash:()=>Nt,normalizeMessageStatus:()=>Jn,normalizeErrorRetryPolicy:()=>bt,loggerMiddleware:()=>xn,logger:()=>En,isTerminalDeliveryStatus:()=>qn,isPollableDeliveryStatus:()=>Bn,isKMsgTerminalStatus:()=>Un,isKMsgMessageType:()=>mn,isKMsgDeliveryStatus:()=>In,isCryptoEnvelope:()=>wn,getRuntimeEnvSource:()=>Ut,getRolloutKnownKids:()=>Z,getPollableStatuses:()=>$n,getLogger:()=>R,fail:()=>ft,createVaultTransitKeyResolver:()=>Fn,createStaticKeyResolver:()=>v,createRollingKeyResolver:()=>dn,createRefreshableKeyResolver:()=>q,createNoopFieldCryptoProvider:()=>Pn,createLogger:()=>it,createEnvKeyResolver:()=>gn,createDefaultMasker:()=>tt,createAwsKmsKeyResolver:()=>on,createAesGcmFieldCryptoProvider:()=>An,assertFieldCryptoConfig:()=>Cn,RetryHandler:()=>M,Result:()=>Rn,RateLimiter:()=>pt,QUEUED_MESSAGE_STATUS:()=>mt,Logger:()=>W,LogLevel:()=>It,KNOWN_MESSAGE_STATUSES:()=>Gn,KMsgErrorCode:()=>N,KMsgError:()=>w,KMSG_TERMINAL_STATUSES:()=>Bt,KMSG_POLLABLE_STATUSES:()=>rt,KMSG_MESSAGE_TYPES:()=>Ht,KMSG_DELIVERY_STATUSES:()=>qt,FieldCryptoError:()=>U,ErrorUtils:()=>_,CircuitBreaker:()=>et,BulkOperationHandler:()=>Y});module.exports=Yt(Wn);var N;((o)=>{o.INVALID_REQUEST="INVALID_REQUEST";o.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";o.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";o.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";o.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";o.NETWORK_ERROR="NETWORK_ERROR";o.NETWORK_TIMEOUT="NETWORK_TIMEOUT";o.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";o.REQUEST_ABORTED="REQUEST_ABORTED";o.PROVIDER_ERROR="PROVIDER_ERROR";o.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";o.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";o.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";o.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";o.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";o.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";o.UNKNOWN_ERROR="UNKNOWN_ERROR"})(N||={});var jt={["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"},["REQUEST_ABORTED"]:{ko:"요청이 취소되었습니다",en:"Request aborted"},["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"}},Qt=new Set(Object.values(N)),ct=new Set(["NETWORK_ERROR","RATE_LIMIT_EXCEEDED","NETWORK_TIMEOUT","NETWORK_SERVICE_UNAVAILABLE","PROVIDER_ERROR","UNKNOWN_ERROR"]),ht=new Set(["INVALID_REQUEST","AUTHENTICATION_FAILED","INSUFFICIENT_BALANCE","TEMPLATE_NOT_FOUND","MESSAGE_SEND_FAILED","REQUEST_ABORTED","CRYPTO_CONFIG_ERROR","CRYPTO_ENCRYPT_FAILED","CRYPTO_DECRYPT_FAILED","CRYPTO_HASH_FAILED","CRYPTO_POLICY_VIOLATION"]),S=(t)=>{if(typeof t!=="number"||Number.isNaN(t)||!Number.isFinite(t))return;return Math.trunc(t)},k=(t)=>{let n=S(t);if(n===void 0||n<0)return;return n},Zt=(t)=>{if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0},j=(t)=>{return typeof t==="string"?t.toLowerCase().trim():void 0},T=(t,n="safe")=>{if(typeof t==="string"){let i=t.trim().toUpperCase();return i.length>0?i:void 0}if(n==="compat"&&(typeof t==="number"||typeof t==="boolean"))return String(t).toUpperCase();return},dt=(t,n)=>t?.some((i)=>T(i)===n)??!1,Xt=(t,n)=>{if(n.nonRetryableCodes?.includes(t))return"non_retryable";if(n.retryableCodes?.includes(t))return"retryable";return},ot=(t,n)=>{let i=T(t,"compat");if(!i)return;if(dt(n.nonRetryableStatuses,i))return"non_retryable";if(dt(n.retryableStatuses,i))return"retryable";return},O=(t)=>{return typeof t==="object"&&t!==null&&!Array.isArray(t)},x=(t,n)=>{for(let i of n)if(i in t)return t[i];return},Lt=(t)=>{return t.length>0?t:"$"},At=(t)=>{return t==="compat"?"compat":"safe"},at=(t)=>{if(t>=500)return"retryable";if(t===408||t===425||t===429)return"retryable";return"non_retryable"},gt=(t)=>{let n=t.toLowerCase();if(n.includes("timeout")||n.includes("temporar")||n.includes("network")||n.includes("retry"))return"retryable";return};class w extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(t,n,i,e={}){super(n);if(this.name="KMsgError",this.code=t,this.details=i,this.providerErrorCode=e.providerErrorCode,this.providerErrorText=e.providerErrorText,this.httpStatus=S(e.httpStatus),this.requestId=typeof e.requestId==="string"?e.requestId:void 0,this.retryAfterMs=S(e.retryAfterMs),this.attempt=S(e.attempt),Array.isArray(e.causeChain))this.causeChain=e.causeChain;else if(e.causeChain!==void 0)this.causeChain=[e.causeChain];let p=Error.captureStackTrace;if(p)p(this,w)}getLocalizedMessage(t="ko"){let n=jt[this.code];if(n?.[t])return n[t];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}}}var b=(t,n)=>{let i=S(t);if(i!==void 0)return i;if(n==="compat"&&typeof t==="string"){let e=Number(t.trim());if(Number.isFinite(e))return Math.trunc(e)}return},Q=(t,n)=>{let i=Zt(t);if(i)return i;if(n==="compat"&&(typeof t==="number"||typeof t==="boolean"))return String(t);return},Pt=(t)=>{if(typeof t!=="string")return;let n=t.trim().toUpperCase();if(!Qt.has(n))return;return n},A=(t,n)=>{t.push({...n,path:Lt(n.path)})},Dt=(t,n,i,e,p)=>{if(t===void 0)return[];let s=(()=>{if(Array.isArray(t))return t;if(i==="compat"&&typeof t==="string")return t.split(",").map((r)=>r.trim()).filter((r)=>r.length>0);return A(e,{code:"invalid_type",message:`expected array of ${p.label} values`,path:n}),[]})(),f=[],y=new Set;for(let r=0;r<s.length;r+=1){let c=s[r],h=p.normalize(c);if(!h){A(e,{code:p.label==="code"?"unknown_code":"invalid_status",message:`invalid retry policy ${p.label}: ${String(c)}`,path:`${n}[${r}]`});continue}if(y.has(h)){A(e,{code:p.label==="code"?"duplicate_code":"duplicate_status",message:`duplicate retry policy ${p.label}: ${h}`,path:`${n}[${r}]`});continue}y.add(h),f.push(h)}return f},Ft=(t,n,i,e)=>Dt(t,n,i,e,{label:"code",normalize:(p)=>Pt(T(p,i))}),Ct=(t,n,i,e)=>Dt(t,n,i,e,{label:"status",normalize:(p)=>T(p,i)}),Tt=(t,n,i,e)=>{if(t===void 0)return;let p=k(b(t,i));if(p!==void 0)return p;A(e,{code:"invalid_retry_after",message:`invalid retry delay: ${String(t)}`,path:n});return},Kt=(t,n,i,e)=>{if(t===void 0)return;if(!O(t)){A(e,{code:"invalid_type",message:"expected retry delay map",path:n});return}let p={},s=new Set;for(let[f,y]of Object.entries(t)){let r=T(f,"safe"),c=`${n}.${f}`;if(!r){A(e,{code:"invalid_key",message:"retry delay map key must not be empty",path:c});continue}if(s.has(r)){A(e,{code:"duplicate_key",message:`duplicate retry delay map key: ${r}`,path:c});continue}let h=Tt(y,c,i,e);if(h===void 0)continue;s.add(r),p[r]=h}return Object.keys(p).length>0?p:void 0},vt=(t,n,i)=>{if(t===void 0)return;if(typeof t==="function")return t;if(!O(t)){A(i,{code:"invalid_type",message:"expected retry delay resolver or policy object",path:"retryAfterMs"});return}let e=new Set(["defaultMs","byCode","byStatus"]);for(let y of Object.keys(t)){if(e.has(y))continue;A(i,{code:"unknown_field",message:`unknown retry-after policy field: ${y}`,path:`retryAfterMs.${y}`})}let p=Tt(t.defaultMs,"retryAfterMs.defaultMs",n,i),s=Kt(t.byCode,"retryAfterMs.byCode",n,i),f=Kt(t.byStatus,"retryAfterMs.byStatus",n,i);if(p===void 0&&s===void 0&&f===void 0)return;return{...p!==void 0?{defaultMs:p}:{},...s!==void 0?{byCode:s}:{},...f!==void 0?{byStatus:f}:{}}},ut=(t,n,i)=>{if(t===void 0)return;if(typeof t==="string"){let e=t.trim().toLowerCase();if(e==="retryable")return"retryable";if(e==="non_retryable"||e==="non-retryable")return"non_retryable"}if(n==="compat"&&typeof t==="boolean")return t?"retryable":"non_retryable";A(i,{code:"invalid_fallback",message:`invalid fallback value: ${String(t)}`,path:"fallback"});return};function Ot(t,n={}){let i=At(n.mode),e=[];if(!O(t))return A(e,{code:"invalid_root",message:"retry policy must be an object",path:"$"}),{policy:null,issues:e};let p=new Set(["retryableCodes","nonRetryableCodes","retryableStatuses","nonRetryableStatuses","fallback","retryAfterMs"]);for(let o of Object.keys(t)){if(p.has(o))continue;A(e,{code:"unknown_field",message:`unknown retry policy field: ${o}`,path:o})}let s=Ft(t.retryableCodes,"retryableCodes",i,e),f=Ft(t.nonRetryableCodes,"nonRetryableCodes",i,e),y=Ct(t.retryableStatuses,"retryableStatuses",i,e),r=Ct(t.nonRetryableStatuses,"nonRetryableStatuses",i,e),c=ut(t.fallback,i,e),h=vt(t.retryAfterMs,i,e),a=new Set(s),g=new Set(f);for(let o of a){if(!g.has(o))continue;a.delete(o),A(e,{code:"conflicting_code",message:`code '${o}' is both retryable and nonRetryable; nonRetryable wins`,path:"retryableCodes"})}let F=new Set(y),K=new Set(r);for(let o of F){if(!K.has(o))continue;F.delete(o),A(e,{code:"conflicting_status",message:`status '${o}' is both retryable and nonRetryable; nonRetryable wins`,path:"retryableStatuses"})}let l={...a.size>0?{retryableCodes:Array.from(a)}:{},...g.size>0?{nonRetryableCodes:Array.from(g)}:{},...F.size>0?{retryableStatuses:Array.from(F)}:{},...K.size>0?{nonRetryableStatuses:Array.from(K)}:{},...c?{fallback:c}:{},...h?{retryAfterMs:h}:{}};return{policy:l.retryableCodes!==void 0||l.nonRetryableCodes!==void 0||l.retryableStatuses!==void 0||l.nonRetryableStatuses!==void 0||l.fallback!==void 0||l.retryAfterMs!==void 0?l:null,issues:e}}function bt(t,n={}){return Ot(t,n).policy}function zt(t,n={}){if(typeof t!=="string"||t.trim().length===0)return null;try{let i=JSON.parse(t);return bt(i,n)}catch{return null}}var lt=(t,n)=>{let i=t.response;if(!O(i))return;return b(x(i,["status","statusCode","httpStatus"]),n)},tn=(t,n)=>{if(t instanceof w&&Array.isArray(t.causeChain))return t.causeChain.slice();if(O(t)){let s=t.causeChain;if(Array.isArray(s))return s.slice();let f=t.details;if(n==="compat"&&O(f)){let y=f.causeChain;if(Array.isArray(y))return y.slice();if(y!==void 0)return[y]}}let i=[],e=new Set,p=t;for(let s=0;s<8;s+=1){if(!O(p))break;let f=p.cause;if(f===void 0||e.has(f))break;e.add(f),i.push(f),p=f}return i.length>0?i:void 0},nn=(t)=>{if(t instanceof Error&&typeof t.message==="string")return t.message;if(O(t)&&typeof t.message==="string")return t.message;return typeof t==="string"?t:"Unknown error"},wt=(t,n)=>{let i=T(n,"compat");if(!t||!i)return;if(Object.prototype.hasOwnProperty.call(t,i))return k(t[i]);for(let[e,p]of Object.entries(t)){if(T(e)!==i)continue;return k(p)}return},St=(t,n)=>{let i=n?.retryAfterMs;if(typeof i==="function"){let y=k(i(t));if(y!==void 0)return{value:y,source:"policy"}}let e=k(t.retryAfterMs);if(e!==void 0)return{value:e,source:"input"};if(!i||typeof i==="function")return{};let p=[t.providerErrorCode,t.code];for(let y of p){let r=wt(i.byCode,y);if(r!==void 0)return{value:r,source:"policy"}}let s=wt(i.byStatus,t.httpStatus);if(s!==void 0)return{value:s,source:"policy"};let f=k(i.defaultMs);return f!==void 0?{value:f,source:"policy"}:{}};function en(t,n={}){let i=At(n.mode),p=n.defaultCode??"UNKNOWN_ERROR",s={code:"fallback",classification:n.policy?"policy":"fallback"},f,y,r,c,h,a,g,F=(d)=>{if(d.providerErrorCode!==void 0)f=d.providerErrorCode,s.providerErrorCode="metadata";if(d.providerErrorText!==void 0)y=d.providerErrorText,s.providerErrorText="metadata";if(d.httpStatus!==void 0)r=d.httpStatus,s.httpStatus="metadata";if(d.requestId!==void 0)c=d.requestId,s.requestId="metadata";if(d.retryAfterMs!==void 0)h=k(d.retryAfterMs),s.retryAfterMs="metadata";if(d.attempt!==void 0)a=b(d.attempt,i),s.attempt="metadata";if(Array.isArray(d.causeChain))g=d.causeChain.slice(),s.causeChain="metadata"},K=(d,D)=>{if(f===void 0){let C=Q(x(d,["providerErrorCode","errorCode","resultCode"]),i);if(C!==void 0)f=C,s.providerErrorCode=D}if(y===void 0){let C=Q(x(d,["providerErrorText","errorMessage","msg","message"]),i);if(C!==void 0)y=C,s.providerErrorText=D}if(r===void 0){let C=b(x(d,["httpStatus","statusCode","status"]),i)??lt(d,i);if(C!==void 0)r=C,s.httpStatus=D==="details"?"details":"http"}if(c===void 0){let C=Q(x(d,["requestId","request_id","reqId","traceId"]),i);if(C!==void 0)c=C,s.requestId=D}if(h===void 0){let C=k(b(x(d,["retryAfterMs","retry_after_ms","retryAfter"]),i));if(C!==void 0)h=C,s.retryAfterMs=D}if(a===void 0){let C=b(d.attempt,i);if(C!==void 0&&C>0)a=C,s.attempt=D}};if(t instanceof w){if(p=t.code,s.code="input",F(t),i==="compat"&&O(t.details))K(t.details,"details")}else if(O(t)){let d=Pt(x(t,["code","errorCode","resultCode"]));if(d!==void 0)p=d,s.code="input";else if(r===void 0){let D=b(x(t,["httpStatus","statusCode","status"]),i)??lt(t,i);if(D!==void 0&&D>=500)p="PROVIDER_ERROR",s.code="http"}if(K(t,"input"),i==="compat"&&O(t.details))K(t.details,"details")}if(g===void 0){let d=tn(t,i);if(d!==void 0)g=d,s.causeChain="input"}if(n.attempt!==void 0&&b(n.attempt,i)!==void 0){let d=b(n.attempt,i);if(d!==void 0&&d>0)a=d,s.attempt="input"}let l=new w(p,nn(t),void 0,{providerErrorCode:f,providerErrorText:y,httpStatus:r,requestId:c,retryAfterMs:h,attempt:a,causeChain:g}),P=St(l,n.policy);if(P.value!==void 0){if(h=P.value,P.source==="policy")s.retryAfterMs="policy"}let o=_.classifyForRetry(l,n.policy);return{code:p,classification:o,...f!==void 0?{providerErrorCode:f}:{},...y!==void 0?{providerErrorText:y}:{},...r!==void 0?{httpStatus:r}:{},...c!==void 0?{requestId:c}:{},...h!==void 0?{retryAfterMs:h}:{},...a!==void 0?{attempt:a}:{},...g!==void 0?{causeChain:g}:{},sources:s}}var _={isRetryable(t,n={}){return _.classifyForRetry(t,n)==="retryable"},classifyForRetry(t,n={}){if(t instanceof w){let r=Xt(t.code,n);if(r)return r;let c=ot(t.httpStatus,n);if(c)return c;if(new Set(n.retryableCodes??Array.from(ct)).has(t.code))return"retryable";if(new Set(n.nonRetryableCodes??Array.from(ht)).has(t.code))return"non_retryable";if(t.httpStatus!==void 0)return at(t.httpStatus);let g=gt(t.message);if(g)return g;if(n.classifyByMessage&&t.message){let F=n.classifyByMessage(t.message);if(F)return F}if(n.fallback)return n.fallback;return"non_retryable"}let i=t&&typeof t==="object"?t:void 0,e=T(i?.status,"compat")??T(i?.statusCode,"compat")??T(i?.httpStatus,"compat")??T(i?.code,"compat"),p=j(i?.status)??j(i?.statusCode)??j(i?.code),s=S(i?.status)??S(i?.statusCode)??S(i?.httpStatus),f=ot(e,n);if(f)return f;if(p?.startsWith("5"))return"retryable";if(s!==void 0){if(n.classifyByStatusCode)return n.classifyByStatusCode(s);return at(s)}let y=typeof i?.message==="string"?gt(i.message):void 0;if(y)return y;if(n.classifyByMessage&&typeof i?.message==="string"){let r=n.classifyByMessage(i.message);if(r)return r}return n.fallback??"non_retryable"},resolveRetryAfterMs(t,n){return St(t,n).value},isUnknownStatus:(t)=>{if(t===void 0||Number.isNaN(t)||!Number.isFinite(t))return!1;return t<500},toRetryMetadata(t){return{providerErrorCode:t.providerErrorCode,providerErrorText:t.providerErrorText,httpStatus:t.httpStatus,requestId:t.requestId,retryAfterMs:t.retryAfterMs,attempt:t.attempt,causeChain:t.causeChain}},withAttempt(t,n){return new w(t.code,t.message,t.details,{..._.toRetryMetadata(t),attempt:S(n)})},DEFAULT_RETRYABLE_ERROR_CODES:ct,DEFAULT_NON_RETRYABLE_ERROR_CODES:ht};function pn(t){switch(t){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 U extends w{kind;fieldPath;failMode;openFallback;constructor(t,n,i,e={}){super(pn(t),n,i,e);this.name="FieldCryptoError",this.kind=t,this.fieldPath=typeof e.fieldPath==="string"?e.fieldPath:void 0,this.failMode=e.failMode,this.openFallback=e.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}var sn=["tenantId","providerId","messageId"];function B(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function fn(t){if(typeof t!=="number"||!Number.isFinite(t))return;if(t<=0||t>100)return;return t}function kt(t){let n=[];for(let i of t){let e=B(i.kid),p=fn(i.percentage);if(!e||p===void 0)continue;n.push({kid:e,percentage:p})}return n}function rn(t,n,i){let e=n.map((p)=>{let s=t[p];return typeof s==="string"?s:""}).join("|");return`${i}::${e}`}function yn(t){let n=2166136261;for(let i=0;i<t.length;i+=1)n^=t.charCodeAt(i),n=n*16777619>>>0;return n>>>0}function cn(t,n){let i=0;for(let e of t)if(i+=e.percentage,n<i)return e.kid;return}function $(t,n,i){let e=kt(n.buckets),p=B(n.defaultKid)??B(i);if(e.length===0)return p;let s=B(n.seed)??"kmsg-rollout-v1",f=n.stickyFields??sn,y=rn(t,f,s),r=yn(y)%100;return cn(e,r)??p}function Z(t){return kt(t.buckets).map((n)=>n.kid)}function I(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function X(t){if(!Array.isArray(t))return[];return t.map((n)=>I(n)).filter((n)=>Boolean(n))}function L(t){let n=[],i=new Set;for(let e of t){let p=I(e);if(!p||i.has(p))continue;i.add(p),n.push(p)}return n}function hn(t){return I(t.providerId)??"default"}function v(t){let n=I(t.activeKid)??"default",i=L([n,...X(t.decryptKids)]);return{async resolveEncryptKey(){return{kid:n}},async resolveDecryptKeys(){return i}}}function q(t){let n=typeof t.cacheTtlMs==="number"&&t.cacheTtlMs>=0?Math.trunc(t.cacheTtlMs):30000,i=I(t.fallback?.activeKid),e=X(t.fallback?.decryptKids),p;async function s(f){let y=Date.now();if(p&&y<p.expiresAt)return p.value;let r=await t.provider.loadKeySet(f),c=I(r.activeKid)??i??hn(f),h=L([c,...X(r.decryptKids),...e]),a={activeKid:c,decryptKids:h,refreshedAt:Date.now()};return p={value:a,expiresAt:Date.now()+n},a}return{async resolveEncryptKey(f){return{kid:(await s(f)).activeKid}},async resolveDecryptKeys(f){let y=await s(f);return y.decryptKids??[y.activeKid]}}}function dn(t,n){return{async resolveEncryptKey(i){let e=await t.resolveEncryptKey(i);return{kid:$(i,n,e.kid)??e.kid}},async resolveDecryptKeys(i){let e=await t.resolveEncryptKey(i),p=t.resolveDecryptKeys?await t.resolveDecryptKeys(i):[e.kid],s=$(i,n,e.kid),f=Z(n);return L([...s?[s]:[],e.kid,...p??[],...f])}}}function on(t){return q({provider:{async loadKeySet(i){return t.client.getKeyState({...i,...t.keyAlias?{keyAlias:t.keyAlias}:{},...t.region?{region:t.region}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function H(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Et(t,n){return H(t[n])}function an(t,n){if(!t)return[];return t.split(n).map((i)=>H(i)).filter((i)=>Boolean(i))}function gn(t={}){let n=globalThis.process?.env,i=t.env??n??{},e=H(t.delimiter)??",",p=t.activeKidEnv??"KMSG_ACTIVE_KID",s=t.decryptKidsEnv??"KMSG_DECRYPT_KIDS",f=Et(i,p)??H(t.fallbackActiveKid)??"default",y=[f,...an(Et(i,s),e),...t.fallbackDecryptKids??[]];return v({activeKid:f,decryptKids:y})}function Fn(t){return q({provider:{async loadKeySet(i){return t.client.getKeyState({...i,...t.mountPath?{mountPath:t.mountPath}:{},...t.keyName?{keyName:t.keyName}:{},...t.namespace?{namespace:t.namespace}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function u(t){return typeof t==="function"}function xt(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function z(t,n,i){let e=t.fields[n];if(e)return e;if(n.startsWith("metadata.")){let p=t.fields["metadata.*"];if(p)return p}return i}function Rt(t,n={}){let i=[];if(!t||typeof t!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!t.provider||typeof t.provider!=="object")i.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!u(t.provider.encrypt))i.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!u(t.provider.decrypt))i.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!u(t.provider.hash))i.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!t.fields||typeof t.fields!=="object")i.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 s=Object.entries(t.fields);if(s.length===0)i.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[f,y]of s){if(!xt(f))i.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(y!=="plain"&&y!=="encrypt"&&y!=="encrypt+hash"&&y!=="mask")i.push({message:`unsupported field mode: ${String(y)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${f}`})}}let e=t.failMode??"closed",p=t.openFallback??"masked";if(e==="open"&&p==="plaintext"&&t.unsafeAllowPlaintextStorage!==!0)i.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(t.aadFields)){if(t.aadFields.length===0)i.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let s=0;s<t.aadFields.length;s+=1){let f=t.aadFields[s];if(!xt(f))i.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${s}]`})}}if(n.secureMode&&!n.compatPlainColumns){let s=z(t,"to","encrypt+hash"),f=z(t,"from","encrypt+hash");if(s==="plain")i.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(f==="plain")i.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:i.length===0,issues:i}}function Cn(t,n={}){let i=Rt(t,n);if(i.valid)return;let e=i.issues[0];if(!e)throw new U("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:i.issues});throw new U("config",e.message,{rule:e.rule,path:e.path,hint:e.hint,issues:i.issues},{fieldPath:e.path})}function m(t){let n=t instanceof Uint8Array?t:new Uint8Array(t),i=typeof globalThis<"u"?globalThis.Buffer:void 0;return(i?i.from(n).toString("base64"):btoa(String.fromCharCode(...n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function G(t){let n=t.replace(/-/g,"+").replace(/_/g,"/"),i=n.length%4===0?n:`${n}${"=".repeat(4-n.length%4)}`,e=typeof globalThis<"u"?globalThis.Buffer:void 0;if(e)return new Uint8Array(e.from(i,"base64"));let p=atob(i),s=new Uint8Array(p.length);for(let f=0;f<p.length;f+=1)s[f]=p.charCodeAt(f);return s}function Mt(t,n){if(t instanceof Uint8Array)return t;if(t instanceof ArrayBuffer)return new Uint8Array(t);if(n==="base64url")return G(t);return new TextEncoder().encode(t)}function Kn(t){let n=t instanceof Uint8Array?t:new Uint8Array(t);return Array.from(n).map((i)=>i.toString(16).padStart(2,"0")).join("")}function E(t){let n=new Uint8Array(t.byteLength);return n.set(t),n.buffer}function _t(t){let n=JSON.parse(t);if(!n||typeof n!=="object"||typeof n.v!=="number"||typeof n.alg!=="string"||typeof n.kid!=="string"||typeof n.iv!=="string"||typeof n.tag!=="string"||typeof n.ct!=="string")throw Error("Invalid ciphertext envelope");return n}function ln(t){if(typeof t==="string")return t;return JSON.stringify(t)}function wn(t){if(!t||typeof t!=="object")return!1;let n=t;return typeof n.v==="number"&&typeof n.alg==="string"&&typeof n.kid==="string"&&typeof n.iv==="string"&&typeof n.tag==="string"&&typeof n.ct==="string"}function Nt(t){let n=String(t??"").trim();if(n.length===0)return"";let i=n.startsWith("+"),e=n.replace(/\D/g,"");return i?`+${e}`:e}function tt(t=3,n=2){return(i)=>{let e=String(i??"");if(e.length<=t+n)return"*".repeat(Math.max(0,e.length));let p=e.slice(0,t),s=e.slice(-n);return`${p}${"*".repeat(e.length-t-n)}${s}`}}function An(t){let n=t.algorithm??"A256GCM",i=t.keyEncoding??"base64url",e=t.hashKeyEncoding??i,p=new Map,s=new Map,f=(r)=>{let c=p.get(r);if(c)return c;let h=t.keys[r];if(!h)throw Error(`Unknown encryption key id: ${r}`);let a=Mt(h,i),g=crypto.subtle.importKey("raw",E(a),"AES-GCM",!1,["encrypt","decrypt"]);return p.set(r,g),g},y=(r)=>{let c=s.get(r);if(c)return c;let h=t.hashKeys?.[r]??t.keys[r];if(!h)throw Error(`Unknown hash key id: ${r}`);let a=Mt(h,e),g=crypto.subtle.importKey("raw",E(a),{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return s.set(r,g),g};return{async encrypt(r){let c=r.kid??t.activeKid,h=await f(c),a=crypto.getRandomValues(new Uint8Array(12)),g=new TextEncoder().encode(JSON.stringify(r.aad??{})),F=new TextEncoder().encode(r.value),K=await crypto.subtle.encrypt({name:"AES-GCM",iv:E(a),additionalData:E(g),tagLength:128},h,E(F)),l=new Uint8Array(K),P=l.slice(l.length-16),o=l.slice(0,l.length-16);return{ciphertext:{v:1,alg:n,kid:c,iv:m(a),tag:m(P),ct:m(o)},kid:c}},async decrypt(r){let c=_t(r.ciphertext),h=r.candidateKids&&r.candidateKids.length>0?r.candidateKids:[c.kid],a=G(c.iv),g=G(c.tag),F=G(c.ct),K=new Uint8Array(F.length+g.length);K.set(F,0),K.set(g,F.length);let l=new TextEncoder().encode(JSON.stringify(r.aad??{})),P;for(let o of h)try{let d=await f(o),D=await crypto.subtle.decrypt({name:"AES-GCM",iv:E(a),additionalData:E(l),tagLength:128},d,E(K));return new TextDecoder().decode(new Uint8Array(D))}catch(d){P=d}throw Error(`Failed to decrypt ciphertext: ${P instanceof Error?P.message:String(P??"unknown")}`)},async hash(r){let c=r.kid??t.activeKid,h=await y(c),a=await crypto.subtle.sign("HMAC",h,E(new TextEncoder().encode(r.value)));return Kn(a)},mask(r){return tt()(r.value)}}}function Pn(){return{encrypt(t){return{ciphertext:JSON.stringify({v:1,alg:"NOOP",kid:"noop",iv:"",tag:"",ct:t.value})}},decrypt(t){try{return _t(t.ciphertext).ct}catch{return t.ciphertext}},hash(t){let n=Nt(t.value);return m(new TextEncoder().encode(n))},mask(t){return tt()(t.value)}}}function Dn(t){return ln(t)}var It;((p)=>{p.DEBUG="DEBUG";p.INFO="INFO";p.WARN="WARN";p.ERROR="ERROR"})(It||={});var Tn=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function On(t){let n=t.toLowerCase();return Tn.some((i)=>n.includes(i.toLowerCase()))}function bn(t){let n=t.trim();if(n.length<=4)return"***";if(n.includes("@")){let[p,s]=n.split("@");return`${p.slice(0,2)}${"*".repeat(Math.max(1,p.length-2))}@${s}`}let i=n.slice(0,3),e=n.slice(-2);return`${i}${"*".repeat(Math.max(1,n.length-5))}${e}`}function nt(t,n){if(n===void 0||n===null)return n;if(On(t)){if(typeof n==="string")return bn(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((i)=>nt(t,i));if(typeof n==="object"){let i={};for(let[e,p]of Object.entries(n))i[e]=nt(e,p);return i}return n}function Sn(t){let n={};for(let[i,e]of Object.entries(t))n[i]=nt(i,e);return n}class W{config;context;constructor(t={},n={}){this.context=t,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(t){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(t)>=n.indexOf(this.config.level)}formatMessage(t){let n=Sn(t.context);if(this.config.enableJson)return JSON.stringify({level:t.level,message:t.message,timestamp:t.timestamp.toISOString(),context:n,...t.error&&{error:{name:t.error.name,message:t.error.message,stack:t.error.stack}},...t.duration&&{duration:t.duration}});let i=t.timestamp.toISOString(),e=this.config.enableColors?this.colorizeLevel(t.level):t.level,p=Object.keys(n).length>0?` [${Object.entries(n).map(([f,y])=>`${f}=${y}`).join(", ")}]`:"",s=`${i} ${e}${p}: ${t.message}`;if(t.duration!==void 0)s+=` (${t.duration}ms)`;if(t.error)s+=`
|
|
2
|
+
${t.error.stack}`;return s}colorizeLevel(t){if(!this.config.enableColors)return t;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[t]}${t}\x1B[0m`}writeLog(t){if(!this.shouldLog(t.level))return;let n=this.formatMessage(t);if(this.config.enableConsole)(t.level==="ERROR"?console.error:t.level==="WARN"?console.warn:console.log)(n);if(this.config.enableFile&&this.config.filePath);}debug(t,n={}){this.writeLog({level:"DEBUG",message:t,timestamp:new Date,context:{...this.context,...n}})}info(t,n={}){this.writeLog({level:"INFO",message:t,timestamp:new Date,context:{...this.context,...n}})}warn(t,n={},i){this.writeLog({level:"WARN",message:t,timestamp:new Date,context:{...this.context,...n},error:i})}error(t,n={},i){this.writeLog({level:"ERROR",message:t,timestamp:new Date,context:{...this.context,...n},error:i})}child(t){return new W({...this.context,...t},this.config)}time(t){let n=Date.now();return()=>{let i=Date.now()-n;this.info(`${t} completed`,{duration:i})}}async measure(t,n,i={}){let e=Date.now(),p={...i,operation:t};this.debug(`Starting ${t}`,p);try{let s=await n(),f=Date.now()-e;return this.info(`Completed ${t}`,{...p,duration:f}),s}catch(s){let f=Date.now()-e;throw this.error(`Failed ${t}`,{...p,duration:f},s instanceof Error?s:Error(String(s))),s}}}var J;function it(t,n){return new W(t,n)}function R(){if(!J)J=it();return J}function kn(t){J=t}var En={debug:(t,n)=>R().debug(t,n),info:(t,n)=>R().info(t,n),warn:(t,n,i)=>R().warn(t,n,i),error:(t,n,i)=>R().error(t,n,i),child:(t)=>R().child(t),time:(t)=>R().time(t),measure:(t,n,i)=>R().measure(t,n,i)};function xn(t){let n=it({},t);return async(i,e)=>{let p=Date.now(),f={requestId:Math.random().toString(36).substring(7),method:i.req.method,path:i.req.path,userAgent:i.req.header("user-agent")||"unknown"};n.info("Request started",f);try{await e();let y=Date.now()-p;n.info("Request completed",{...f,status:i.res.status,duration:y})}catch(y){let r=Date.now()-p;throw n.error("Request failed",{...f,duration:r},y instanceof Error?y:Error(String(y))),y}}}class M{static defaultOptions={maxAttempts:3,initialDelay:1000,maxDelay:30000,backoffMultiplier:2,jitter:!0,retryCondition:(t)=>_.isRetryable(t)};static async execute(t,n={}){let i={...M.defaultOptions,...n},e,p=i.initialDelay;for(let s=1;s<=i.maxAttempts;s++)try{return await t()}catch(f){if(e=f,s===i.maxAttempts||!i.retryCondition(e,s))throw e;let y=i.jitter?p+Math.random()*p*0.1:p;i.onRetry?.(e,s),await new Promise((r)=>setTimeout(r,y)),p=Math.min(p*i.backoffMultiplier,i.maxDelay)}throw e}static createRetryableFunction(t,n={}){return async(...i)=>{return M.execute(()=>t(...i),n)}}}class Y{static async execute(t,n,i={}){let e={concurrency:5,retryOptions:{maxAttempts:3,initialDelay:1000,maxDelay:1e4,backoffMultiplier:2,jitter:!0},failFast:!1,...i},p=Date.now(),s=[],f=[],y=0,r=M.createRetryableFunction(n,e.retryOptions),c=Y.createBatches(t,e.concurrency);for(let a of c){let g=a.map(async(F)=>{try{let K=await r(F);s.push({item:F,result:K})}catch(K){if(f.push({item:F,error:K}),e.failFast)throw new w("MESSAGE_SEND_FAILED",`Bulk operation failed fast after ${f.length} failures`,{totalItems:t.length,failedCount:f.length})}finally{y++,e.onProgress?.(y,t.length,f.length)}});if(await Promise.allSettled(g),e.failFast&&f.length>0)break}let h=Date.now()-p;return{successful:s,failed:f,summary:{total:t.length,successful:s.length,failed:f.length,duration:h}}}static createBatches(t,n){let i=[];for(let e=0;e<t.length;e+=n)i.push(t.slice(e,e+n));return i}}class et{options;state="CLOSED";failureCount=0;lastFailureTime=0;nextAttemptTime=0;constructor(t){this.options=t}async execute(t){let n=Date.now();switch(this.state){case"OPEN":if(n<this.nextAttemptTime)throw new w("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 i=await Promise.race([t(),new Promise((e,p)=>setTimeout(()=>p(new w("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 i}catch(i){throw this.recordFailure(),i}}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 pt{maxRequests;windowMs;requests=[];constructor(t,n){this.maxRequests=t;this.windowMs=n}async acquire(){let t=Date.now();if(this.requests=this.requests.filter((n)=>t-n<this.windowMs),this.requests.length>=this.maxRequests){let n=Math.min(...this.requests),i=this.windowMs-(t-n);if(i>0)return await new Promise((e)=>setTimeout(e,i)),this.acquire()}this.requests.push(t)}canMakeRequest(){let t=Date.now();return this.requests=this.requests.filter((n)=>t-n<this.windowMs),this.requests.length<this.maxRequests}getRemainingRequests(){let t=Date.now();return this.requests=this.requests.filter((n)=>t-n<this.windowMs),Math.max(0,this.maxRequests-this.requests.length)}}var st=(t)=>({isSuccess:!0,isFailure:!1,value:t}),ft=(t)=>({isSuccess:!1,isFailure:!0,error:t}),Rn={map(t,n){if(t.isSuccess)return st(n(t.value));return t},flatMap(t,n){if(t.isSuccess)return n(t.value);return t},mapError(t,n){if(t.isFailure)return ft(n(t.error));return t},unwrap(t){if(t.isSuccess)return t.value;throw t.error},unwrapOr(t,n){if(t.isSuccess)return t.value;return n},unwrapOrElse(t,n){if(t.isSuccess)return t.value;return n(t.error)},match(t,n){if(t.isSuccess)return n.ok(t.value);return n.fail(t.error)},async fromPromise(t){try{let n=await t;return st(n)}catch(n){return ft(n)}},isOk(t){return t.isSuccess},isFail(t){return t.isFailure},tap(t,n){return n(t),t},tapOk(t,n){if(t.isSuccess)n(t.value);return t},tapErr(t,n){if(t.isFailure)n(t.error);return t},expect(t,n){if(t.isSuccess)return t.value;throw Error(n,{cause:t.error})}};function Ut(){let t=globalThis;return t.__K_MSG_ENV__??t.__ENV__??t.process?.env??{}}function Mn(t){let n=Ut()[t];if(typeof n==="string")return n;if(n===void 0)return;return String(n)}var qt=["PENDING","SENT","DELIVERED","FAILED","CANCELLED","UNKNOWN"],Bt=["DELIVERED","FAILED","CANCELLED","UNKNOWN"],rt=["PENDING","SENT"],_n=new Set(qt),$t=new Set(Bt),Nn=new Set(rt);function In(t){return _n.has(t)}function Un(t){return $t.has(t)}function qn(t){return $t.has(t)}function Bn(t){return Nn.has(t)}function $n(){return rt}var Ht=["ALIMTALK","FRIENDTALK","SMS","LMS","MMS","NSA","VOICE","FAX","RCS_SMS","RCS_LMS","RCS_MMS","RCS_TPL","RCS_ITPL","RCS_LTPL"],Hn=new Set(Ht);function mn(t){return Hn.has(t)}var Gn=["PENDING","SENT","FAILED"],mt="PENDING",Jn=(t)=>{let n=typeof t==="string"?t.trim().toUpperCase():"";if(n==="PENDING"||n==="SENT"||n==="FAILED")return n;return mt};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=191B06DF7D93335864756E2164756E21
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var E;((l)=>{l.INVALID_REQUEST="INVALID_REQUEST";l.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";l.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";l.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";l.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";l.NETWORK_ERROR="NETWORK_ERROR";l.NETWORK_TIMEOUT="NETWORK_TIMEOUT";l.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";l.PROVIDER_ERROR="PROVIDER_ERROR";l.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";l.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";l.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";l.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";l.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";l.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";l.UNKNOWN_ERROR="UNKNOWN_ERROR"})(E||={});var At={["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"}},Pt=new Set(Object.values(E)),Q=new Set(["NETWORK_ERROR","RATE_LIMIT_EXCEEDED","NETWORK_TIMEOUT","NETWORK_SERVICE_UNAVAILABLE","PROVIDER_ERROR","UNKNOWN_ERROR"]),Z=new Set(["INVALID_REQUEST","AUTHENTICATION_FAILED","INSUFFICIENT_BALANCE","TEMPLATE_NOT_FOUND","MESSAGE_SEND_FAILED","CRYPTO_CONFIG_ERROR","CRYPTO_ENCRYPT_FAILED","CRYPTO_DECRYPT_FAILED","CRYPTO_HASH_FAILED","CRYPTO_POLICY_VIOLATION"]),P=(t)=>{if(typeof t!=="number"||Number.isNaN(t)||!Number.isFinite(t))return;return Math.trunc(t)},x=(t)=>{let n=P(t);if(n===void 0||n<0)return;return n},q=(t)=>{if(typeof t!=="string")return;return t.toLowerCase().trim()},wt=(t)=>{if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0},w=(t)=>{return typeof t==="object"&&t!==null&&!Array.isArray(t)},u=(t,n)=>{for(let e of n)if(e in t)return t[e];return},St=(t)=>{return t.length>0?t:"$"},nt=(t)=>{return t==="compat"?"compat":"safe"},L=(t)=>{if(t>=500)return"retryable";if(t===408||t===425||t===429)return"retryable";return"non_retryable"},X=(t)=>{let n=t.toLowerCase();if(n.includes("timeout")||n.includes("temporar")||n.includes("network")||n.includes("retry"))return"retryable";return};class K extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(t,n,e,i={}){super(n);if(this.name="KMsgError",this.code=t,this.details=e,this.providerErrorCode=i.providerErrorCode,this.providerErrorText=i.providerErrorText,this.httpStatus=P(i.httpStatus),this.requestId=typeof i.requestId==="string"?i.requestId:void 0,this.retryAfterMs=P(i.retryAfterMs),this.attempt=P(i.attempt),Array.isArray(i.causeChain))this.causeChain=i.causeChain;else if(i.causeChain!==void 0)this.causeChain=[i.causeChain];let r=Error.captureStackTrace;if(r)r(this,K)}getLocalizedMessage(t="ko"){let n=At[this.code];if(n?.[t])return n[t];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}}}var D=(t,n)=>{let e=P(t);if(e!==void 0)return e;if(n==="compat"&&typeof t==="string"){let i=Number(t.trim());if(Number.isFinite(i))return Math.trunc(i)}return},$=(t,n)=>{let e=wt(t);if(e)return e;if(n==="compat"&&(typeof t==="number"||typeof t==="boolean"))return String(t);return},et=(t)=>{if(typeof t!=="string")return;let n=t.trim().toUpperCase();if(!Pt.has(n))return;return n},k=(t,n)=>{t.push({...n,path:St(n.path)})},z=(t,n,e,i)=>{if(t===void 0)return[];let r=(()=>{if(Array.isArray(t))return t;if(e==="compat"&&typeof t==="string")return t.split(",").map((f)=>f.trim()).filter((f)=>f.length>0);return k(i,{code:"invalid_type",message:"expected array of KMsgErrorCode values",path:n}),[]})(),s=[],p=new Set;for(let f=0;f<r.length;f+=1){let y=r[f],o=et(typeof y==="string"?y:e==="compat"?String(y):y);if(!o){k(i,{code:"unknown_code",message:`unknown retry policy code: ${String(y)}`,path:`${n}[${f}]`});continue}if(p.has(o)){k(i,{code:"duplicate_code",message:`duplicate retry policy code: ${o}`,path:`${n}[${f}]`});continue}p.add(o),s.push(o)}return s},bt=(t,n,e)=>{if(t===void 0)return;if(typeof t==="string"){let i=t.trim().toLowerCase();if(i==="retryable")return"retryable";if(i==="non_retryable"||i==="non-retryable")return"non_retryable"}if(n==="compat"&&typeof t==="boolean")return t?"retryable":"non_retryable";k(e,{code:"invalid_fallback",message:`invalid fallback value: ${String(t)}`,path:"fallback"});return};function ut(t,n={}){let e=nt(n.mode),i=[];if(!w(t))return k(i,{code:"invalid_root",message:"retry policy must be an object",path:"$"}),{policy:null,issues:i};let r=new Set(["retryableCodes","nonRetryableCodes","fallback"]);for(let d of Object.keys(t)){if(r.has(d))continue;k(i,{code:"unknown_field",message:`unknown retry policy field: ${d}`,path:d})}let s=z(t.retryableCodes,"retryableCodes",e,i),p=z(t.nonRetryableCodes,"nonRetryableCodes",e,i),f=bt(t.fallback,e,i),y=new Set(s),o=new Set(p);for(let d of y){if(!o.has(d))continue;y.delete(d),k(i,{code:"conflicting_code",message:`code '${d}' is both retryable and nonRetryable; nonRetryable wins`,path:"retryableCodes"})}let a={...y.size>0?{retryableCodes:Array.from(y)}:{},...o.size>0?{nonRetryableCodes:Array.from(o)}:{},...f?{fallback:f}:{}};return{policy:a.retryableCodes!==void 0||a.nonRetryableCodes!==void 0||a.fallback!==void 0?a:null,issues:i}}function Dt(t,n={}){return ut(t,n).policy}function zt(t,n={}){if(typeof t!=="string"||t.trim().length===0)return null;try{let e=JSON.parse(t);return Dt(e,n)}catch{return null}}var tt=(t,n)=>{let e=t.response;if(!w(e))return;return D(u(e,["status","statusCode","httpStatus"]),n)},kt=(t,n)=>{if(t instanceof K&&Array.isArray(t.causeChain))return t.causeChain.slice();if(w(t)){let s=t.causeChain;if(Array.isArray(s))return s.slice();let p=t.details;if(n==="compat"&&w(p)){let f=p.causeChain;if(Array.isArray(f))return f.slice();if(f!==void 0)return[f]}}let e=[],i=new Set,r=t;for(let s=0;s<8;s+=1){if(!w(r))break;let p=r.cause;if(p===void 0||i.has(p))break;i.add(p),e.push(p),r=p}return e.length>0?e:void 0},mt=(t)=>{if(t instanceof Error&&typeof t.message==="string")return t.message;if(w(t)&&typeof t.message==="string")return t.message;return typeof t==="string"?t:"Unknown error"};function tn(t,n={}){let e=nt(n.mode),r=n.defaultCode??"UNKNOWN_ERROR",s={code:"fallback",classification:n.policy?"policy":"fallback"},p,f,y,o,a,h,d,A=(c)=>{if(c.providerErrorCode!==void 0)p=c.providerErrorCode,s.providerErrorCode="metadata";if(c.providerErrorText!==void 0)f=c.providerErrorText,s.providerErrorText="metadata";if(c.httpStatus!==void 0)y=c.httpStatus,s.httpStatus="metadata";if(c.requestId!==void 0)o=c.requestId,s.requestId="metadata";if(c.retryAfterMs!==void 0)a=x(c.retryAfterMs),s.retryAfterMs="metadata";if(c.attempt!==void 0)h=D(c.attempt,e),s.attempt="metadata";if(Array.isArray(c.causeChain))d=c.causeChain.slice(),s.causeChain="metadata"},C=(c,F)=>{if(p===void 0){let g=$(u(c,["providerErrorCode","errorCode","resultCode"]),e);if(g!==void 0)p=g,s.providerErrorCode=F}if(f===void 0){let g=$(u(c,["providerErrorText","errorMessage","msg","message"]),e);if(g!==void 0)f=g,s.providerErrorText=F}if(y===void 0){let g=D(u(c,["httpStatus","statusCode","status"]),e)??tt(c,e);if(g!==void 0)y=g,s.httpStatus=F==="details"?"details":"http"}if(o===void 0){let g=$(u(c,["requestId","request_id","reqId","traceId"]),e);if(g!==void 0)o=g,s.requestId=F}if(a===void 0){let g=x(D(u(c,["retryAfterMs","retry_after_ms","retryAfter"]),e));if(g!==void 0)a=g,s.retryAfterMs=F}if(h===void 0){let g=D(c.attempt,e);if(g!==void 0&&g>0)h=g,s.attempt=F}};if(t instanceof K){if(r=t.code,s.code="input",A(t),e==="compat"&&w(t.details))C(t.details,"details")}else if(w(t)){let c=et(u(t,["code","errorCode","resultCode"]));if(c!==void 0)r=c,s.code="input";else if(y===void 0){let F=D(u(t,["httpStatus","statusCode","status"]),e)??tt(t,e);if(F!==void 0&&F>=500)r="PROVIDER_ERROR",s.code="http"}if(C(t,"input"),e==="compat"&&w(t.details))C(t.details,"details")}if(d===void 0){let c=kt(t,e);if(c!==void 0)d=c,s.causeChain="input"}if(n.attempt!==void 0&&D(n.attempt,e)!==void 0){let c=D(n.attempt,e);if(c!==void 0&&c>0)h=c,s.attempt="input"}let b=new K(r,mt(t),void 0,{providerErrorCode:p,providerErrorText:f,httpStatus:y,requestId:o,retryAfterMs:a,attempt:h,causeChain:d}),l=R.classifyForRetry(b,n.policy);return{code:r,classification:l,...p!==void 0?{providerErrorCode:p}:{},...f!==void 0?{providerErrorText:f}:{},...y!==void 0?{httpStatus:y}:{},...o!==void 0?{requestId:o}:{},...a!==void 0?{retryAfterMs:a}:{},...h!==void 0?{attempt:h}:{},...d!==void 0?{causeChain:d}:{},sources:s}}var R={isRetryable(t,n={}){return R.classifyForRetry(t,n)==="retryable"},classifyForRetry(t,n={}){if(t instanceof K){if(new Set(n.retryableCodes??Array.from(Q)).has(t.code))return"retryable";if(new Set(n.nonRetryableCodes??Array.from(Z)).has(t.code))return"non_retryable";if(t.httpStatus!==void 0)return L(t.httpStatus);let y=X(t.message);if(y)return y;if(n.classifyByMessage&&t.message){let o=n.classifyByMessage(t.message);if(o)return o}if(n.fallback)return n.fallback;return"non_retryable"}let e=t&&typeof t==="object"?t:void 0,i=q(e?.status)??q(e?.statusCode)??q(e?.code),r=P(e?.status)??P(e?.statusCode)??P(e?.httpStatus);if(typeof i==="string"&&i.startsWith("5"))return"retryable";if(r!==void 0){if(n.classifyByStatusCode)return n.classifyByStatusCode(r);return L(r)}let s=typeof e?.message==="string"?X(e.message):void 0;if(s)return s;if(n.classifyByMessage&&typeof e?.message==="string"){let p=n.classifyByMessage(e.message);if(p)return p}return n.fallback??"non_retryable"},resolveRetryAfterMs(t,n){if(n?.retryAfterMs){let e=n.retryAfterMs(t),i=x(e);if(i!==void 0)return i}if(t.retryAfterMs!==void 0)return x(t.retryAfterMs);if(t.code==="RATE_LIMIT_EXCEEDED"&&t.retryAfterMs===void 0)return;return},isUnknownStatus:(t)=>{if(t===void 0||Number.isNaN(t)||!Number.isFinite(t))return!1;return t<500},toRetryMetadata(t){return{providerErrorCode:t.providerErrorCode,providerErrorText:t.providerErrorText,httpStatus:t.httpStatus,requestId:t.requestId,retryAfterMs:t.retryAfterMs,attempt:t.attempt,causeChain:t.causeChain}},withAttempt(t,n){return new K(t.code,t.message,t.details,{...R.toRetryMetadata(t),attempt:P(n)})},DEFAULT_RETRYABLE_ERROR_CODES:Q,DEFAULT_NON_RETRYABLE_ERROR_CODES:Z};function Tt(t){switch(t){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 M extends K{kind;fieldPath;failMode;openFallback;constructor(t,n,e,i={}){super(Tt(t),n,e,i);this.name="FieldCryptoError",this.kind=t,this.fieldPath=typeof i.fieldPath==="string"?i.fieldPath:void 0,this.failMode=i.failMode,this.openFallback=i.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}var Ot=["tenantId","providerId","messageId"];function v(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Rt(t){if(typeof t!=="number"||!Number.isFinite(t))return;if(t<=0||t>100)return;return t}function it(t){let n=[];for(let e of t){let i=v(e.kid),r=Rt(e.percentage);if(!i||r===void 0)continue;n.push({kid:i,percentage:r})}return n}function Et(t,n,e){let i=n.map((r)=>{let s=t[r];return typeof s==="string"?s:""}).join("|");return`${e}::${i}`}function xt(t){let n=2166136261;for(let e=0;e<t.length;e+=1)n^=t.charCodeAt(e),n=n*16777619>>>0;return n>>>0}function Mt(t,n){let e=0;for(let i of t)if(e+=i.percentage,n<e)return i.kid;return}function H(t,n,e){let i=it(n.buckets),r=v(n.defaultKid)??v(e);if(i.length===0)return r;let s=v(n.seed)??"kmsg-rollout-v1",p=n.stickyFields??Ot,f=Et(t,p,s),y=xt(f)%100;return Mt(i,y)??r}function st(t){return it(t.buckets).map((n)=>n.kid)}function T(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function V(t){if(!Array.isArray(t))return[];return t.map((n)=>T(n)).filter((n)=>Boolean(n))}function G(t){let n=[],e=new Set;for(let i of t){let r=T(i);if(!r||e.has(r))continue;e.add(r),n.push(r)}return n}function vt(t){return T(t.providerId)??"default"}function rt(t){let n=T(t.activeKid)??"default",e=G([n,...V(t.decryptKids)]);return{async resolveEncryptKey(){return{kid:n}},async resolveDecryptKeys(){return e}}}function _(t){let n=typeof t.cacheTtlMs==="number"&&t.cacheTtlMs>=0?Math.trunc(t.cacheTtlMs):30000,e=T(t.fallback?.activeKid),i=V(t.fallback?.decryptKids),r;async function s(p){let f=Date.now();if(r&&f<r.expiresAt)return r.value;let y=await t.provider.loadKeySet(p),o=T(y.activeKid)??e??vt(p),a=G([o,...V(y.decryptKids),...i]),h={activeKid:o,decryptKids:a,refreshedAt:Date.now()};return r={value:h,expiresAt:Date.now()+n},h}return{async resolveEncryptKey(p){return{kid:(await s(p)).activeKid}},async resolveDecryptKeys(p){let f=await s(p);return f.decryptKids??[f.activeKid]}}}function yn(t,n){return{async resolveEncryptKey(e){let i=await t.resolveEncryptKey(e);return{kid:H(e,n,i.kid)??i.kid}},async resolveDecryptKeys(e){let i=await t.resolveEncryptKey(e),r=t.resolveDecryptKeys?await t.resolveDecryptKeys(e):[i.kid],s=H(e,n,i.kid),p=st(n);return G([...s?[s]:[],i.kid,...r??[],...p])}}}function cn(t){return _({provider:{async loadKeySet(e){return t.client.getKeyState({...e,...t.keyAlias?{keyAlias:t.keyAlias}:{},...t.region?{region:t.region}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function N(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function pt(t,n){return N(t[n])}function _t(t,n){if(!t)return[];return t.split(n).map((e)=>N(e)).filter((e)=>Boolean(e))}function ln(t={}){let n=globalThis.process?.env,e=t.env??n??{},i=N(t.delimiter)??",",r=t.activeKidEnv??"KMSG_ACTIVE_KID",s=t.decryptKidsEnv??"KMSG_DECRYPT_KIDS",p=pt(e,r)??N(t.fallbackActiveKid)??"default",f=[p,..._t(pt(e,s),i),...t.fallbackDecryptKids??[]];return rt({activeKid:p,decryptKids:f})}function Kn(t){return _({provider:{async loadKeySet(e){return t.client.getKeyState({...e,...t.mountPath?{mountPath:t.mountPath}:{},...t.keyName?{keyName:t.keyName}:{},...t.namespace?{namespace:t.namespace}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function J(t){return typeof t==="function"}function yt(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function ft(t,n,e){let i=t.fields[n];if(i)return i;if(n.startsWith("metadata.")){let r=t.fields["metadata.*"];if(r)return r}return e}function Nt(t,n={}){let e=[];if(!t||typeof t!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!t.provider||typeof t.provider!=="object")e.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!J(t.provider.encrypt))e.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!J(t.provider.decrypt))e.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!J(t.provider.hash))e.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!t.fields||typeof t.fields!=="object")e.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 s=Object.entries(t.fields);if(s.length===0)e.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[p,f]of s){if(!yt(p))e.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(f!=="plain"&&f!=="encrypt"&&f!=="encrypt+hash"&&f!=="mask")e.push({message:`unsupported field mode: ${String(f)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${p}`})}}let i=t.failMode??"closed",r=t.openFallback??"masked";if(i==="open"&&r==="plaintext"&&t.unsafeAllowPlaintextStorage!==!0)e.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(t.aadFields)){if(t.aadFields.length===0)e.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let s=0;s<t.aadFields.length;s+=1){let p=t.aadFields[s];if(!yt(p))e.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${s}]`})}}if(n.secureMode&&!n.compatPlainColumns){let s=ft(t,"to","encrypt+hash"),p=ft(t,"from","encrypt+hash");if(s==="plain")e.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(p==="plain")e.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:e.length===0,issues:e}}function An(t,n={}){let e=Nt(t,n);if(e.valid)return;let i=e.issues[0];if(!i)throw new M("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:e.issues});throw new M("config",i.message,{rule:i.rule,path:i.path,hint:i.hint,issues:e.issues},{fieldPath:i.path})}function I(t){let n=t instanceof Uint8Array?t:new Uint8Array(t),e=typeof globalThis<"u"?globalThis.Buffer:void 0;return(e?e.from(n).toString("base64"):btoa(String.fromCharCode(...n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function U(t){let n=t.replace(/-/g,"+").replace(/_/g,"/"),e=n.length%4===0?n:`${n}${"=".repeat(4-n.length%4)}`,i=typeof globalThis<"u"?globalThis.Buffer:void 0;if(i)return new Uint8Array(i.from(e,"base64"));let r=atob(e),s=new Uint8Array(r.length);for(let p=0;p<r.length;p+=1)s[p]=r.charCodeAt(p);return s}function ot(t,n){if(t instanceof Uint8Array)return t;if(t instanceof ArrayBuffer)return new Uint8Array(t);if(n==="base64url")return U(t);return new TextEncoder().encode(t)}function It(t){let n=t instanceof Uint8Array?t:new Uint8Array(t);return Array.from(n).map((e)=>e.toString(16).padStart(2,"0")).join("")}function S(t){let n=new Uint8Array(t.byteLength);return n.set(t),n.buffer}function ct(t){let n=JSON.parse(t);if(!n||typeof n!=="object"||typeof n.v!=="number"||typeof n.alg!=="string"||typeof n.kid!=="string"||typeof n.iv!=="string"||typeof n.tag!=="string"||typeof n.ct!=="string")throw Error("Invalid ciphertext envelope");return n}function Ut(t){if(typeof t==="string")return t;return JSON.stringify(t)}function wn(t){if(!t||typeof t!=="object")return!1;let n=t;return typeof n.v==="number"&&typeof n.alg==="string"&&typeof n.kid==="string"&&typeof n.iv==="string"&&typeof n.tag==="string"&&typeof n.ct==="string"}function Bt(t){let n=String(t??"").trim();if(n.length===0)return"";let e=n.startsWith("+"),i=n.replace(/\D/g,"");return e?`+${i}`:i}function at(t=3,n=2){return(e)=>{let i=String(e??"");if(i.length<=t+n)return"*".repeat(Math.max(0,i.length));let r=i.slice(0,t),s=i.slice(-n);return`${r}${"*".repeat(i.length-t-n)}${s}`}}function Sn(t){let n=t.algorithm??"A256GCM",e=t.keyEncoding??"base64url",i=t.hashKeyEncoding??e,r=new Map,s=new Map,p=(y)=>{let o=r.get(y);if(o)return o;let a=t.keys[y];if(!a)throw Error(`Unknown encryption key id: ${y}`);let h=ot(a,e),d=crypto.subtle.importKey("raw",S(h),"AES-GCM",!1,["encrypt","decrypt"]);return r.set(y,d),d},f=(y)=>{let o=s.get(y);if(o)return o;let a=t.hashKeys?.[y]??t.keys[y];if(!a)throw Error(`Unknown hash key id: ${y}`);let h=ot(a,i),d=crypto.subtle.importKey("raw",S(h),{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return s.set(y,d),d};return{async encrypt(y){let o=y.kid??t.activeKid,a=await p(o),h=crypto.getRandomValues(new Uint8Array(12)),d=new TextEncoder().encode(JSON.stringify(y.aad??{})),A=new TextEncoder().encode(y.value),C=await crypto.subtle.encrypt({name:"AES-GCM",iv:S(h),additionalData:S(d),tagLength:128},a,S(A)),b=new Uint8Array(C),l=b.slice(b.length-16),c=b.slice(0,b.length-16);return{ciphertext:{v:1,alg:n,kid:o,iv:I(h),tag:I(l),ct:I(c)},kid:o}},async decrypt(y){let o=ct(y.ciphertext),a=y.candidateKids&&y.candidateKids.length>0?y.candidateKids:[o.kid],h=U(o.iv),d=U(o.tag),A=U(o.ct),C=new Uint8Array(A.length+d.length);C.set(A,0),C.set(d,A.length);let b=new TextEncoder().encode(JSON.stringify(y.aad??{})),l;for(let c of a)try{let F=await p(c),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:S(h),additionalData:S(b),tagLength:128},F,S(C));return new TextDecoder().decode(new Uint8Array(g))}catch(F){l=F}throw Error(`Failed to decrypt ciphertext: ${l instanceof Error?l.message:String(l??"unknown")}`)},async hash(y){let o=y.kid??t.activeKid,a=await f(o),h=await crypto.subtle.sign("HMAC",a,S(new TextEncoder().encode(y.value)));return It(h)},mask(y){return at()(y.value)}}}function bn(){return{encrypt(t){return{ciphertext:JSON.stringify({v:1,alg:"NOOP",kid:"noop",iv:"",tag:"",ct:t.value})}},decrypt(t){try{return ct(t.ciphertext).ct}catch{return t.ciphertext}},hash(t){let n=Bt(t.value);return I(new TextEncoder().encode(n))},mask(t){return at()(t.value)}}}function un(t){return Ut(t)}var qt;((r)=>{r.DEBUG="DEBUG";r.INFO="INFO";r.WARN="WARN";r.ERROR="ERROR"})(qt||={});var $t=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function Ht(t){let n=t.toLowerCase();return $t.some((e)=>n.includes(e.toLowerCase()))}function Vt(t){let n=t.trim();if(n.length<=4)return"***";if(n.includes("@")){let[r,s]=n.split("@");return`${r.slice(0,2)}${"*".repeat(Math.max(1,r.length-2))}@${s}`}let e=n.slice(0,3),i=n.slice(-2);return`${e}${"*".repeat(Math.max(1,n.length-5))}${i}`}function W(t,n){if(n===void 0||n===null)return n;if(Ht(t)){if(typeof n==="string")return Vt(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((e)=>W(t,e));if(typeof n==="object"){let e={};for(let[i,r]of Object.entries(n))e[i]=W(i,r);return e}return n}function Gt(t){let n={};for(let[e,i]of Object.entries(t))n[e]=W(e,i);return n}class Y{config;context;constructor(t={},n={}){this.context=t,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(t){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(t)>=n.indexOf(this.config.level)}formatMessage(t){let n=Gt(t.context);if(this.config.enableJson)return JSON.stringify({level:t.level,message:t.message,timestamp:t.timestamp.toISOString(),context:n,...t.error&&{error:{name:t.error.name,message:t.error.message,stack:t.error.stack}},...t.duration&&{duration:t.duration}});let e=t.timestamp.toISOString(),i=this.config.enableColors?this.colorizeLevel(t.level):t.level,r=Object.keys(n).length>0?` [${Object.entries(n).map(([p,f])=>`${p}=${f}`).join(", ")}]`:"",s=`${e} ${i}${r}: ${t.message}`;if(t.duration!==void 0)s+=` (${t.duration}ms)`;if(t.error)s+=`
|
|
2
|
-
${t.error.stack}`;return s}colorizeLevel(t){if(!this.config.enableColors)return t;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[t]}${t}\x1B[0m`}writeLog(t){if(!this.shouldLog(t.level))return;let n=this.formatMessage(t);if(this.config.enableConsole)(t.level==="ERROR"?console.error:t.level==="WARN"?console.warn:console.log)(n);if(this.config.enableFile&&this.config.filePath);}debug(t,n={}){this.writeLog({level:"DEBUG",message:t,timestamp:new Date,context:{...this.context,...n}})}info(t,n={}){this.writeLog({level:"INFO",message:t,timestamp:new Date,context:{...this.context,...n}})}warn(t,n={},
|
|
1
|
+
var I;((o)=>{o.INVALID_REQUEST="INVALID_REQUEST";o.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";o.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";o.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";o.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";o.NETWORK_ERROR="NETWORK_ERROR";o.NETWORK_TIMEOUT="NETWORK_TIMEOUT";o.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";o.REQUEST_ABORTED="REQUEST_ABORTED";o.PROVIDER_ERROR="PROVIDER_ERROR";o.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";o.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";o.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";o.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";o.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";o.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";o.UNKNOWN_ERROR="UNKNOWN_ERROR"})(I||={});var xt={["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"},["REQUEST_ABORTED"]:{ko:"요청이 취소되었습니다",en:"Request aborted"},["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"}},Rt=new Set(Object.values(I)),v=new Set(["NETWORK_ERROR","RATE_LIMIT_EXCEEDED","NETWORK_TIMEOUT","NETWORK_SERVICE_UNAVAILABLE","PROVIDER_ERROR","UNKNOWN_ERROR"]),u=new Set(["INVALID_REQUEST","AUTHENTICATION_FAILED","INSUFFICIENT_BALANCE","TEMPLATE_NOT_FOUND","MESSAGE_SEND_FAILED","REQUEST_ABORTED","CRYPTO_CONFIG_ERROR","CRYPTO_ENCRYPT_FAILED","CRYPTO_DECRYPT_FAILED","CRYPTO_HASH_FAILED","CRYPTO_POLICY_VIOLATION"]),S=(t)=>{if(typeof t!=="number"||Number.isNaN(t)||!Number.isFinite(t))return;return Math.trunc(t)},x=(t)=>{let n=S(t);if(n===void 0||n<0)return;return n},Mt=(t)=>{if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0},J=(t)=>{return typeof t==="string"?t.toLowerCase().trim():void 0},T=(t,n="safe")=>{if(typeof t==="string"){let i=t.trim().toUpperCase();return i.length>0?i:void 0}if(n==="compat"&&(typeof t==="number"||typeof t==="boolean"))return String(t).toUpperCase();return},z=(t,n)=>t?.some((i)=>T(i)===n)??!1,_t=(t,n)=>{if(n.nonRetryableCodes?.includes(t))return"non_retryable";if(n.retryableCodes?.includes(t))return"retryable";return},tt=(t,n)=>{let i=T(t,"compat");if(!i)return;if(z(n.nonRetryableStatuses,i))return"non_retryable";if(z(n.retryableStatuses,i))return"retryable";return},O=(t)=>{return typeof t==="object"&&t!==null&&!Array.isArray(t)},E=(t,n)=>{for(let i of n)if(i in t)return t[i];return},Nt=(t)=>{return t.length>0?t:"$"},yt=(t)=>{return t==="compat"?"compat":"safe"},nt=(t)=>{if(t>=500)return"retryable";if(t===408||t===425||t===429)return"retryable";return"non_retryable"},it=(t)=>{let n=t.toLowerCase();if(n.includes("timeout")||n.includes("temporar")||n.includes("network")||n.includes("retry"))return"retryable";return};class A extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(t,n,i,e={}){super(n);if(this.name="KMsgError",this.code=t,this.details=i,this.providerErrorCode=e.providerErrorCode,this.providerErrorText=e.providerErrorText,this.httpStatus=S(e.httpStatus),this.requestId=typeof e.requestId==="string"?e.requestId:void 0,this.retryAfterMs=S(e.retryAfterMs),this.attempt=S(e.attempt),Array.isArray(e.causeChain))this.causeChain=e.causeChain;else if(e.causeChain!==void 0)this.causeChain=[e.causeChain];let p=Error.captureStackTrace;if(p)p(this,A)}getLocalizedMessage(t="ko"){let n=xt[this.code];if(n?.[t])return n[t];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}}}var b=(t,n)=>{let i=S(t);if(i!==void 0)return i;if(n==="compat"&&typeof t==="string"){let e=Number(t.trim());if(Number.isFinite(e))return Math.trunc(e)}return},W=(t,n)=>{let i=Mt(t);if(i)return i;if(n==="compat"&&(typeof t==="number"||typeof t==="boolean"))return String(t);return},ct=(t)=>{if(typeof t!=="string")return;let n=t.trim().toUpperCase();if(!Rt.has(n))return;return n},w=(t,n)=>{t.push({...n,path:Nt(n.path)})},ht=(t,n,i,e,p)=>{if(t===void 0)return[];let s=(()=>{if(Array.isArray(t))return t;if(i==="compat"&&typeof t==="string")return t.split(",").map((r)=>r.trim()).filter((r)=>r.length>0);return w(e,{code:"invalid_type",message:`expected array of ${p.label} values`,path:n}),[]})(),f=[],y=new Set;for(let r=0;r<s.length;r+=1){let c=s[r],h=p.normalize(c);if(!h){w(e,{code:p.label==="code"?"unknown_code":"invalid_status",message:`invalid retry policy ${p.label}: ${String(c)}`,path:`${n}[${r}]`});continue}if(y.has(h)){w(e,{code:p.label==="code"?"duplicate_code":"duplicate_status",message:`duplicate retry policy ${p.label}: ${h}`,path:`${n}[${r}]`});continue}y.add(h),f.push(h)}return f},et=(t,n,i,e)=>ht(t,n,i,e,{label:"code",normalize:(p)=>ct(T(p,i))}),pt=(t,n,i,e)=>ht(t,n,i,e,{label:"status",normalize:(p)=>T(p,i)}),dt=(t,n,i,e)=>{if(t===void 0)return;let p=x(b(t,i));if(p!==void 0)return p;w(e,{code:"invalid_retry_after",message:`invalid retry delay: ${String(t)}`,path:n});return},st=(t,n,i,e)=>{if(t===void 0)return;if(!O(t)){w(e,{code:"invalid_type",message:"expected retry delay map",path:n});return}let p={},s=new Set;for(let[f,y]of Object.entries(t)){let r=T(f,"safe"),c=`${n}.${f}`;if(!r){w(e,{code:"invalid_key",message:"retry delay map key must not be empty",path:c});continue}if(s.has(r)){w(e,{code:"duplicate_key",message:`duplicate retry delay map key: ${r}`,path:c});continue}let h=dt(y,c,i,e);if(h===void 0)continue;s.add(r),p[r]=h}return Object.keys(p).length>0?p:void 0},It=(t,n,i)=>{if(t===void 0)return;if(typeof t==="function")return t;if(!O(t)){w(i,{code:"invalid_type",message:"expected retry delay resolver or policy object",path:"retryAfterMs"});return}let e=new Set(["defaultMs","byCode","byStatus"]);for(let y of Object.keys(t)){if(e.has(y))continue;w(i,{code:"unknown_field",message:`unknown retry-after policy field: ${y}`,path:`retryAfterMs.${y}`})}let p=dt(t.defaultMs,"retryAfterMs.defaultMs",n,i),s=st(t.byCode,"retryAfterMs.byCode",n,i),f=st(t.byStatus,"retryAfterMs.byStatus",n,i);if(p===void 0&&s===void 0&&f===void 0)return;return{...p!==void 0?{defaultMs:p}:{},...s!==void 0?{byCode:s}:{},...f!==void 0?{byStatus:f}:{}}},Ut=(t,n,i)=>{if(t===void 0)return;if(typeof t==="string"){let e=t.trim().toLowerCase();if(e==="retryable")return"retryable";if(e==="non_retryable"||e==="non-retryable")return"non_retryable"}if(n==="compat"&&typeof t==="boolean")return t?"retryable":"non_retryable";w(i,{code:"invalid_fallback",message:`invalid fallback value: ${String(t)}`,path:"fallback"});return};function qt(t,n={}){let i=yt(n.mode),e=[];if(!O(t))return w(e,{code:"invalid_root",message:"retry policy must be an object",path:"$"}),{policy:null,issues:e};let p=new Set(["retryableCodes","nonRetryableCodes","retryableStatuses","nonRetryableStatuses","fallback","retryAfterMs"]);for(let o of Object.keys(t)){if(p.has(o))continue;w(e,{code:"unknown_field",message:`unknown retry policy field: ${o}`,path:o})}let s=et(t.retryableCodes,"retryableCodes",i,e),f=et(t.nonRetryableCodes,"nonRetryableCodes",i,e),y=pt(t.retryableStatuses,"retryableStatuses",i,e),r=pt(t.nonRetryableStatuses,"nonRetryableStatuses",i,e),c=Ut(t.fallback,i,e),h=It(t.retryAfterMs,i,e),a=new Set(s),g=new Set(f);for(let o of a){if(!g.has(o))continue;a.delete(o),w(e,{code:"conflicting_code",message:`code '${o}' is both retryable and nonRetryable; nonRetryable wins`,path:"retryableCodes"})}let F=new Set(y),K=new Set(r);for(let o of F){if(!K.has(o))continue;F.delete(o),w(e,{code:"conflicting_status",message:`status '${o}' is both retryable and nonRetryable; nonRetryable wins`,path:"retryableStatuses"})}let l={...a.size>0?{retryableCodes:Array.from(a)}:{},...g.size>0?{nonRetryableCodes:Array.from(g)}:{},...F.size>0?{retryableStatuses:Array.from(F)}:{},...K.size>0?{nonRetryableStatuses:Array.from(K)}:{},...c?{fallback:c}:{},...h?{retryAfterMs:h}:{}};return{policy:l.retryableCodes!==void 0||l.nonRetryableCodes!==void 0||l.retryableStatuses!==void 0||l.nonRetryableStatuses!==void 0||l.fallback!==void 0||l.retryAfterMs!==void 0?l:null,issues:e}}function Bt(t,n={}){return qt(t,n).policy}function on(t,n={}){if(typeof t!=="string"||t.trim().length===0)return null;try{let i=JSON.parse(t);return Bt(i,n)}catch{return null}}var ft=(t,n)=>{let i=t.response;if(!O(i))return;return b(E(i,["status","statusCode","httpStatus"]),n)},$t=(t,n)=>{if(t instanceof A&&Array.isArray(t.causeChain))return t.causeChain.slice();if(O(t)){let s=t.causeChain;if(Array.isArray(s))return s.slice();let f=t.details;if(n==="compat"&&O(f)){let y=f.causeChain;if(Array.isArray(y))return y.slice();if(y!==void 0)return[y]}}let i=[],e=new Set,p=t;for(let s=0;s<8;s+=1){if(!O(p))break;let f=p.cause;if(f===void 0||e.has(f))break;e.add(f),i.push(f),p=f}return i.length>0?i:void 0},Ht=(t)=>{if(t instanceof Error&&typeof t.message==="string")return t.message;if(O(t)&&typeof t.message==="string")return t.message;return typeof t==="string"?t:"Unknown error"},rt=(t,n)=>{let i=T(n,"compat");if(!t||!i)return;if(Object.prototype.hasOwnProperty.call(t,i))return x(t[i]);for(let[e,p]of Object.entries(t)){if(T(e)!==i)continue;return x(p)}return},ot=(t,n)=>{let i=n?.retryAfterMs;if(typeof i==="function"){let y=x(i(t));if(y!==void 0)return{value:y,source:"policy"}}let e=x(t.retryAfterMs);if(e!==void 0)return{value:e,source:"input"};if(!i||typeof i==="function")return{};let p=[t.providerErrorCode,t.code];for(let y of p){let r=rt(i.byCode,y);if(r!==void 0)return{value:r,source:"policy"}}let s=rt(i.byStatus,t.httpStatus);if(s!==void 0)return{value:s,source:"policy"};let f=x(i.defaultMs);return f!==void 0?{value:f,source:"policy"}:{}};function an(t,n={}){let i=yt(n.mode),p=n.defaultCode??"UNKNOWN_ERROR",s={code:"fallback",classification:n.policy?"policy":"fallback"},f,y,r,c,h,a,g,F=(d)=>{if(d.providerErrorCode!==void 0)f=d.providerErrorCode,s.providerErrorCode="metadata";if(d.providerErrorText!==void 0)y=d.providerErrorText,s.providerErrorText="metadata";if(d.httpStatus!==void 0)r=d.httpStatus,s.httpStatus="metadata";if(d.requestId!==void 0)c=d.requestId,s.requestId="metadata";if(d.retryAfterMs!==void 0)h=x(d.retryAfterMs),s.retryAfterMs="metadata";if(d.attempt!==void 0)a=b(d.attempt,i),s.attempt="metadata";if(Array.isArray(d.causeChain))g=d.causeChain.slice(),s.causeChain="metadata"},K=(d,D)=>{if(f===void 0){let C=W(E(d,["providerErrorCode","errorCode","resultCode"]),i);if(C!==void 0)f=C,s.providerErrorCode=D}if(y===void 0){let C=W(E(d,["providerErrorText","errorMessage","msg","message"]),i);if(C!==void 0)y=C,s.providerErrorText=D}if(r===void 0){let C=b(E(d,["httpStatus","statusCode","status"]),i)??ft(d,i);if(C!==void 0)r=C,s.httpStatus=D==="details"?"details":"http"}if(c===void 0){let C=W(E(d,["requestId","request_id","reqId","traceId"]),i);if(C!==void 0)c=C,s.requestId=D}if(h===void 0){let C=x(b(E(d,["retryAfterMs","retry_after_ms","retryAfter"]),i));if(C!==void 0)h=C,s.retryAfterMs=D}if(a===void 0){let C=b(d.attempt,i);if(C!==void 0&&C>0)a=C,s.attempt=D}};if(t instanceof A){if(p=t.code,s.code="input",F(t),i==="compat"&&O(t.details))K(t.details,"details")}else if(O(t)){let d=ct(E(t,["code","errorCode","resultCode"]));if(d!==void 0)p=d,s.code="input";else if(r===void 0){let D=b(E(t,["httpStatus","statusCode","status"]),i)??ft(t,i);if(D!==void 0&&D>=500)p="PROVIDER_ERROR",s.code="http"}if(K(t,"input"),i==="compat"&&O(t.details))K(t.details,"details")}if(g===void 0){let d=$t(t,i);if(d!==void 0)g=d,s.causeChain="input"}if(n.attempt!==void 0&&b(n.attempt,i)!==void 0){let d=b(n.attempt,i);if(d!==void 0&&d>0)a=d,s.attempt="input"}let l=new A(p,Ht(t),void 0,{providerErrorCode:f,providerErrorText:y,httpStatus:r,requestId:c,retryAfterMs:h,attempt:a,causeChain:g}),P=ot(l,n.policy);if(P.value!==void 0){if(h=P.value,P.source==="policy")s.retryAfterMs="policy"}let o=N.classifyForRetry(l,n.policy);return{code:p,classification:o,...f!==void 0?{providerErrorCode:f}:{},...y!==void 0?{providerErrorText:y}:{},...r!==void 0?{httpStatus:r}:{},...c!==void 0?{requestId:c}:{},...h!==void 0?{retryAfterMs:h}:{},...a!==void 0?{attempt:a}:{},...g!==void 0?{causeChain:g}:{},sources:s}}var N={isRetryable(t,n={}){return N.classifyForRetry(t,n)==="retryable"},classifyForRetry(t,n={}){if(t instanceof A){let r=_t(t.code,n);if(r)return r;let c=tt(t.httpStatus,n);if(c)return c;if(new Set(n.retryableCodes??Array.from(v)).has(t.code))return"retryable";if(new Set(n.nonRetryableCodes??Array.from(u)).has(t.code))return"non_retryable";if(t.httpStatus!==void 0)return nt(t.httpStatus);let g=it(t.message);if(g)return g;if(n.classifyByMessage&&t.message){let F=n.classifyByMessage(t.message);if(F)return F}if(n.fallback)return n.fallback;return"non_retryable"}let i=t&&typeof t==="object"?t:void 0,e=T(i?.status,"compat")??T(i?.statusCode,"compat")??T(i?.httpStatus,"compat")??T(i?.code,"compat"),p=J(i?.status)??J(i?.statusCode)??J(i?.code),s=S(i?.status)??S(i?.statusCode)??S(i?.httpStatus),f=tt(e,n);if(f)return f;if(p?.startsWith("5"))return"retryable";if(s!==void 0){if(n.classifyByStatusCode)return n.classifyByStatusCode(s);return nt(s)}let y=typeof i?.message==="string"?it(i.message):void 0;if(y)return y;if(n.classifyByMessage&&typeof i?.message==="string"){let r=n.classifyByMessage(i.message);if(r)return r}return n.fallback??"non_retryable"},resolveRetryAfterMs(t,n){return ot(t,n).value},isUnknownStatus:(t)=>{if(t===void 0||Number.isNaN(t)||!Number.isFinite(t))return!1;return t<500},toRetryMetadata(t){return{providerErrorCode:t.providerErrorCode,providerErrorText:t.providerErrorText,httpStatus:t.httpStatus,requestId:t.requestId,retryAfterMs:t.retryAfterMs,attempt:t.attempt,causeChain:t.causeChain}},withAttempt(t,n){return new A(t.code,t.message,t.details,{...N.toRetryMetadata(t),attempt:S(n)})},DEFAULT_RETRYABLE_ERROR_CODES:v,DEFAULT_NON_RETRYABLE_ERROR_CODES:u};function mt(t){switch(t){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 U extends A{kind;fieldPath;failMode;openFallback;constructor(t,n,i,e={}){super(mt(t),n,i,e);this.name="FieldCryptoError",this.kind=t,this.fieldPath=typeof e.fieldPath==="string"?e.fieldPath:void 0,this.failMode=e.failMode,this.openFallback=e.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}var Gt=["tenantId","providerId","messageId"];function q(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Jt(t){if(typeof t!=="number"||!Number.isFinite(t))return;if(t<=0||t>100)return;return t}function at(t){let n=[];for(let i of t){let e=q(i.kid),p=Jt(i.percentage);if(!e||p===void 0)continue;n.push({kid:e,percentage:p})}return n}function Wt(t,n,i){let e=n.map((p)=>{let s=t[p];return typeof s==="string"?s:""}).join("|");return`${i}::${e}`}function Yt(t){let n=2166136261;for(let i=0;i<t.length;i+=1)n^=t.charCodeAt(i),n=n*16777619>>>0;return n>>>0}function Vt(t,n){let i=0;for(let e of t)if(i+=e.percentage,n<i)return e.kid;return}function Y(t,n,i){let e=at(n.buckets),p=q(n.defaultKid)??q(i);if(e.length===0)return p;let s=q(n.seed)??"kmsg-rollout-v1",f=n.stickyFields??Gt,y=Wt(t,f,s),r=Yt(y)%100;return Vt(e,r)??p}function gt(t){return at(t.buckets).map((n)=>n.kid)}function M(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function V(t){if(!Array.isArray(t))return[];return t.map((n)=>M(n)).filter((n)=>Boolean(n))}function j(t){let n=[],i=new Set;for(let e of t){let p=M(e);if(!p||i.has(p))continue;i.add(p),n.push(p)}return n}function jt(t){return M(t.providerId)??"default"}function Ft(t){let n=M(t.activeKid)??"default",i=j([n,...V(t.decryptKids)]);return{async resolveEncryptKey(){return{kid:n}},async resolveDecryptKeys(){return i}}}function B(t){let n=typeof t.cacheTtlMs==="number"&&t.cacheTtlMs>=0?Math.trunc(t.cacheTtlMs):30000,i=M(t.fallback?.activeKid),e=V(t.fallback?.decryptKids),p;async function s(f){let y=Date.now();if(p&&y<p.expiresAt)return p.value;let r=await t.provider.loadKeySet(f),c=M(r.activeKid)??i??jt(f),h=j([c,...V(r.decryptKids),...e]),a={activeKid:c,decryptKids:h,refreshedAt:Date.now()};return p={value:a,expiresAt:Date.now()+n},a}return{async resolveEncryptKey(f){return{kid:(await s(f)).activeKid}},async resolveDecryptKeys(f){let y=await s(f);return y.decryptKids??[y.activeKid]}}}function wn(t,n){return{async resolveEncryptKey(i){let e=await t.resolveEncryptKey(i);return{kid:Y(i,n,e.kid)??e.kid}},async resolveDecryptKeys(i){let e=await t.resolveEncryptKey(i),p=t.resolveDecryptKeys?await t.resolveDecryptKeys(i):[e.kid],s=Y(i,n,e.kid),f=gt(n);return j([...s?[s]:[],e.kid,...p??[],...f])}}}function Dn(t){return B({provider:{async loadKeySet(i){return t.client.getKeyState({...i,...t.keyAlias?{keyAlias:t.keyAlias}:{},...t.region?{region:t.region}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function $(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function Ct(t,n){return $(t[n])}function Qt(t,n){if(!t)return[];return t.split(n).map((i)=>$(i)).filter((i)=>Boolean(i))}function bn(t={}){let n=globalThis.process?.env,i=t.env??n??{},e=$(t.delimiter)??",",p=t.activeKidEnv??"KMSG_ACTIVE_KID",s=t.decryptKidsEnv??"KMSG_DECRYPT_KIDS",f=Ct(i,p)??$(t.fallbackActiveKid)??"default",y=[f,...Qt(Ct(i,s),e),...t.fallbackDecryptKids??[]];return Ft({activeKid:f,decryptKids:y})}function En(t){return B({provider:{async loadKeySet(i){return t.client.getKeyState({...i,...t.mountPath?{mountPath:t.mountPath}:{},...t.keyName?{keyName:t.keyName}:{},...t.namespace?{namespace:t.namespace}:{}})}},cacheTtlMs:t.cacheTtlMs,fallback:{activeKid:t.fallbackActiveKid,decryptKids:t.fallbackDecryptKids}})}function Q(t){return typeof t==="function"}function Kt(t){if(typeof t!=="string")return;let n=t.trim();return n.length>0?n:void 0}function lt(t,n,i){let e=t.fields[n];if(e)return e;if(n.startsWith("metadata.")){let p=t.fields["metadata.*"];if(p)return p}return i}function Zt(t,n={}){let i=[];if(!t||typeof t!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!t.provider||typeof t.provider!=="object")i.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!Q(t.provider.encrypt))i.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!Q(t.provider.decrypt))i.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!Q(t.provider.hash))i.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!t.fields||typeof t.fields!=="object")i.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 s=Object.entries(t.fields);if(s.length===0)i.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[f,y]of s){if(!Kt(f))i.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(y!=="plain"&&y!=="encrypt"&&y!=="encrypt+hash"&&y!=="mask")i.push({message:`unsupported field mode: ${String(y)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${f}`})}}let e=t.failMode??"closed",p=t.openFallback??"masked";if(e==="open"&&p==="plaintext"&&t.unsafeAllowPlaintextStorage!==!0)i.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(t.aadFields)){if(t.aadFields.length===0)i.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let s=0;s<t.aadFields.length;s+=1){let f=t.aadFields[s];if(!Kt(f))i.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${s}]`})}}if(n.secureMode&&!n.compatPlainColumns){let s=lt(t,"to","encrypt+hash"),f=lt(t,"from","encrypt+hash");if(s==="plain")i.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(f==="plain")i.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:i.length===0,issues:i}}function Mn(t,n={}){let i=Zt(t,n);if(i.valid)return;let e=i.issues[0];if(!e)throw new U("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:i.issues});throw new U("config",e.message,{rule:e.rule,path:e.path,hint:e.hint,issues:i.issues},{fieldPath:e.path})}function H(t){let n=t instanceof Uint8Array?t:new Uint8Array(t),i=typeof globalThis<"u"?globalThis.Buffer:void 0;return(i?i.from(n).toString("base64"):btoa(String.fromCharCode(...n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function m(t){let n=t.replace(/-/g,"+").replace(/_/g,"/"),i=n.length%4===0?n:`${n}${"=".repeat(4-n.length%4)}`,e=typeof globalThis<"u"?globalThis.Buffer:void 0;if(e)return new Uint8Array(e.from(i,"base64"));let p=atob(i),s=new Uint8Array(p.length);for(let f=0;f<p.length;f+=1)s[f]=p.charCodeAt(f);return s}function wt(t,n){if(t instanceof Uint8Array)return t;if(t instanceof ArrayBuffer)return new Uint8Array(t);if(n==="base64url")return m(t);return new TextEncoder().encode(t)}function Xt(t){let n=t instanceof Uint8Array?t:new Uint8Array(t);return Array.from(n).map((i)=>i.toString(16).padStart(2,"0")).join("")}function k(t){let n=new Uint8Array(t.byteLength);return n.set(t),n.buffer}function At(t){let n=JSON.parse(t);if(!n||typeof n!=="object"||typeof n.v!=="number"||typeof n.alg!=="string"||typeof n.kid!=="string"||typeof n.iv!=="string"||typeof n.tag!=="string"||typeof n.ct!=="string")throw Error("Invalid ciphertext envelope");return n}function Lt(t){if(typeof t==="string")return t;return JSON.stringify(t)}function Nn(t){if(!t||typeof t!=="object")return!1;let n=t;return typeof n.v==="number"&&typeof n.alg==="string"&&typeof n.kid==="string"&&typeof n.iv==="string"&&typeof n.tag==="string"&&typeof n.ct==="string"}function vt(t){let n=String(t??"").trim();if(n.length===0)return"";let i=n.startsWith("+"),e=n.replace(/\D/g,"");return i?`+${e}`:e}function Pt(t=3,n=2){return(i)=>{let e=String(i??"");if(e.length<=t+n)return"*".repeat(Math.max(0,e.length));let p=e.slice(0,t),s=e.slice(-n);return`${p}${"*".repeat(e.length-t-n)}${s}`}}function In(t){let n=t.algorithm??"A256GCM",i=t.keyEncoding??"base64url",e=t.hashKeyEncoding??i,p=new Map,s=new Map,f=(r)=>{let c=p.get(r);if(c)return c;let h=t.keys[r];if(!h)throw Error(`Unknown encryption key id: ${r}`);let a=wt(h,i),g=crypto.subtle.importKey("raw",k(a),"AES-GCM",!1,["encrypt","decrypt"]);return p.set(r,g),g},y=(r)=>{let c=s.get(r);if(c)return c;let h=t.hashKeys?.[r]??t.keys[r];if(!h)throw Error(`Unknown hash key id: ${r}`);let a=wt(h,e),g=crypto.subtle.importKey("raw",k(a),{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return s.set(r,g),g};return{async encrypt(r){let c=r.kid??t.activeKid,h=await f(c),a=crypto.getRandomValues(new Uint8Array(12)),g=new TextEncoder().encode(JSON.stringify(r.aad??{})),F=new TextEncoder().encode(r.value),K=await crypto.subtle.encrypt({name:"AES-GCM",iv:k(a),additionalData:k(g),tagLength:128},h,k(F)),l=new Uint8Array(K),P=l.slice(l.length-16),o=l.slice(0,l.length-16);return{ciphertext:{v:1,alg:n,kid:c,iv:H(a),tag:H(P),ct:H(o)},kid:c}},async decrypt(r){let c=At(r.ciphertext),h=r.candidateKids&&r.candidateKids.length>0?r.candidateKids:[c.kid],a=m(c.iv),g=m(c.tag),F=m(c.ct),K=new Uint8Array(F.length+g.length);K.set(F,0),K.set(g,F.length);let l=new TextEncoder().encode(JSON.stringify(r.aad??{})),P;for(let o of h)try{let d=await f(o),D=await crypto.subtle.decrypt({name:"AES-GCM",iv:k(a),additionalData:k(l),tagLength:128},d,k(K));return new TextDecoder().decode(new Uint8Array(D))}catch(d){P=d}throw Error(`Failed to decrypt ciphertext: ${P instanceof Error?P.message:String(P??"unknown")}`)},async hash(r){let c=r.kid??t.activeKid,h=await y(c),a=await crypto.subtle.sign("HMAC",h,k(new TextEncoder().encode(r.value)));return Xt(a)},mask(r){return Pt()(r.value)}}}function Un(){return{encrypt(t){return{ciphertext:JSON.stringify({v:1,alg:"NOOP",kid:"noop",iv:"",tag:"",ct:t.value})}},decrypt(t){try{return At(t.ciphertext).ct}catch{return t.ciphertext}},hash(t){let n=vt(t.value);return H(new TextEncoder().encode(n))},mask(t){return Pt()(t.value)}}}function qn(t){return Lt(t)}var ut;((p)=>{p.DEBUG="DEBUG";p.INFO="INFO";p.WARN="WARN";p.ERROR="ERROR"})(ut||={});var zt=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"];function tn(t){let n=t.toLowerCase();return zt.some((i)=>n.includes(i.toLowerCase()))}function nn(t){let n=t.trim();if(n.length<=4)return"***";if(n.includes("@")){let[p,s]=n.split("@");return`${p.slice(0,2)}${"*".repeat(Math.max(1,p.length-2))}@${s}`}let i=n.slice(0,3),e=n.slice(-2);return`${i}${"*".repeat(Math.max(1,n.length-5))}${e}`}function Z(t,n){if(n===void 0||n===null)return n;if(tn(t)){if(typeof n==="string")return nn(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((i)=>Z(t,i));if(typeof n==="object"){let i={};for(let[e,p]of Object.entries(n))i[e]=Z(e,p);return i}return n}function en(t){let n={};for(let[i,e]of Object.entries(t))n[i]=Z(i,e);return n}class X{config;context;constructor(t={},n={}){this.context=t,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...n}}shouldLog(t){let n=["DEBUG","INFO","WARN","ERROR"];return n.indexOf(t)>=n.indexOf(this.config.level)}formatMessage(t){let n=en(t.context);if(this.config.enableJson)return JSON.stringify({level:t.level,message:t.message,timestamp:t.timestamp.toISOString(),context:n,...t.error&&{error:{name:t.error.name,message:t.error.message,stack:t.error.stack}},...t.duration&&{duration:t.duration}});let i=t.timestamp.toISOString(),e=this.config.enableColors?this.colorizeLevel(t.level):t.level,p=Object.keys(n).length>0?` [${Object.entries(n).map(([f,y])=>`${f}=${y}`).join(", ")}]`:"",s=`${i} ${e}${p}: ${t.message}`;if(t.duration!==void 0)s+=` (${t.duration}ms)`;if(t.error)s+=`
|
|
2
|
+
${t.error.stack}`;return s}colorizeLevel(t){if(!this.config.enableColors)return t;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[t]}${t}\x1B[0m`}writeLog(t){if(!this.shouldLog(t.level))return;let n=this.formatMessage(t);if(this.config.enableConsole)(t.level==="ERROR"?console.error:t.level==="WARN"?console.warn:console.log)(n);if(this.config.enableFile&&this.config.filePath);}debug(t,n={}){this.writeLog({level:"DEBUG",message:t,timestamp:new Date,context:{...this.context,...n}})}info(t,n={}){this.writeLog({level:"INFO",message:t,timestamp:new Date,context:{...this.context,...n}})}warn(t,n={},i){this.writeLog({level:"WARN",message:t,timestamp:new Date,context:{...this.context,...n},error:i})}error(t,n={},i){this.writeLog({level:"ERROR",message:t,timestamp:new Date,context:{...this.context,...n},error:i})}child(t){return new X({...this.context,...t},this.config)}time(t){let n=Date.now();return()=>{let i=Date.now()-n;this.info(`${t} completed`,{duration:i})}}async measure(t,n,i={}){let e=Date.now(),p={...i,operation:t};this.debug(`Starting ${t}`,p);try{let s=await n(),f=Date.now()-e;return this.info(`Completed ${t}`,{...p,duration:f}),s}catch(s){let f=Date.now()-e;throw this.error(`Failed ${t}`,{...p,duration:f},s instanceof Error?s:Error(String(s))),s}}}var G;function Dt(t,n){return new X(t,n)}function R(){if(!G)G=Dt();return G}function $n(t){G=t}var Hn={debug:(t,n)=>R().debug(t,n),info:(t,n)=>R().info(t,n),warn:(t,n,i)=>R().warn(t,n,i),error:(t,n,i)=>R().error(t,n,i),child:(t)=>R().child(t),time:(t)=>R().time(t),measure:(t,n,i)=>R().measure(t,n,i)};function mn(t){let n=Dt({},t);return async(i,e)=>{let p=Date.now(),f={requestId:Math.random().toString(36).substring(7),method:i.req.method,path:i.req.path,userAgent:i.req.header("user-agent")||"unknown"};n.info("Request started",f);try{await e();let y=Date.now()-p;n.info("Request completed",{...f,status:i.res.status,duration:y})}catch(y){let r=Date.now()-p;throw n.error("Request failed",{...f,duration:r},y instanceof Error?y:Error(String(y))),y}}}class _{static defaultOptions={maxAttempts:3,initialDelay:1000,maxDelay:30000,backoffMultiplier:2,jitter:!0,retryCondition:(t)=>N.isRetryable(t)};static async execute(t,n={}){let i={..._.defaultOptions,...n},e,p=i.initialDelay;for(let s=1;s<=i.maxAttempts;s++)try{return await t()}catch(f){if(e=f,s===i.maxAttempts||!i.retryCondition(e,s))throw e;let y=i.jitter?p+Math.random()*p*0.1:p;i.onRetry?.(e,s),await new Promise((r)=>setTimeout(r,y)),p=Math.min(p*i.backoffMultiplier,i.maxDelay)}throw e}static createRetryableFunction(t,n={}){return async(...i)=>{return _.execute(()=>t(...i),n)}}}class L{static async execute(t,n,i={}){let e={concurrency:5,retryOptions:{maxAttempts:3,initialDelay:1000,maxDelay:1e4,backoffMultiplier:2,jitter:!0},failFast:!1,...i},p=Date.now(),s=[],f=[],y=0,r=_.createRetryableFunction(n,e.retryOptions),c=L.createBatches(t,e.concurrency);for(let a of c){let g=a.map(async(F)=>{try{let K=await r(F);s.push({item:F,result:K})}catch(K){if(f.push({item:F,error:K}),e.failFast)throw new A("MESSAGE_SEND_FAILED",`Bulk operation failed fast after ${f.length} failures`,{totalItems:t.length,failedCount:f.length})}finally{y++,e.onProgress?.(y,t.length,f.length)}});if(await Promise.allSettled(g),e.failFast&&f.length>0)break}let h=Date.now()-p;return{successful:s,failed:f,summary:{total:t.length,successful:s.length,failed:f.length,duration:h}}}static createBatches(t,n){let i=[];for(let e=0;e<t.length;e+=n)i.push(t.slice(e,e+n));return i}}class Tt{options;state="CLOSED";failureCount=0;lastFailureTime=0;nextAttemptTime=0;constructor(t){this.options=t}async execute(t){let n=Date.now();switch(this.state){case"OPEN":if(n<this.nextAttemptTime)throw new A("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 i=await Promise.race([t(),new Promise((e,p)=>setTimeout(()=>p(new A("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 i}catch(i){throw this.recordFailure(),i}}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 Ot{maxRequests;windowMs;requests=[];constructor(t,n){this.maxRequests=t;this.windowMs=n}async acquire(){let t=Date.now();if(this.requests=this.requests.filter((n)=>t-n<this.windowMs),this.requests.length>=this.maxRequests){let n=Math.min(...this.requests),i=this.windowMs-(t-n);if(i>0)return await new Promise((e)=>setTimeout(e,i)),this.acquire()}this.requests.push(t)}canMakeRequest(){let t=Date.now();return this.requests=this.requests.filter((n)=>t-n<this.windowMs),this.requests.length<this.maxRequests}getRemainingRequests(){let t=Date.now();return this.requests=this.requests.filter((n)=>t-n<this.windowMs),Math.max(0,this.maxRequests-this.requests.length)}}var bt=(t)=>({isSuccess:!0,isFailure:!1,value:t}),St=(t)=>({isSuccess:!1,isFailure:!0,error:t}),ni={map(t,n){if(t.isSuccess)return bt(n(t.value));return t},flatMap(t,n){if(t.isSuccess)return n(t.value);return t},mapError(t,n){if(t.isFailure)return St(n(t.error));return t},unwrap(t){if(t.isSuccess)return t.value;throw t.error},unwrapOr(t,n){if(t.isSuccess)return t.value;return n},unwrapOrElse(t,n){if(t.isSuccess)return t.value;return n(t.error)},match(t,n){if(t.isSuccess)return n.ok(t.value);return n.fail(t.error)},async fromPromise(t){try{let n=await t;return bt(n)}catch(n){return St(n)}},isOk(t){return t.isSuccess},isFail(t){return t.isFailure},tap(t,n){return n(t),t},tapOk(t,n){if(t.isSuccess)n(t.value);return t},tapErr(t,n){if(t.isFailure)n(t.error);return t},expect(t,n){if(t.isSuccess)return t.value;throw Error(n,{cause:t.error})}};function pn(){let t=globalThis;return t.__K_MSG_ENV__??t.__ENV__??t.process?.env??{}}function ei(t){let n=pn()[t];if(typeof n==="string")return n;if(n===void 0)return;return String(n)}var sn=["PENDING","SENT","DELIVERED","FAILED","CANCELLED","UNKNOWN"],fn=["DELIVERED","FAILED","CANCELLED","UNKNOWN"],kt=["PENDING","SENT"],rn=new Set(sn),Et=new Set(fn),yn=new Set(kt);function si(t){return rn.has(t)}function fi(t){return Et.has(t)}function ri(t){return Et.has(t)}function yi(t){return yn.has(t)}function ci(){return kt}var cn=["ALIMTALK","FRIENDTALK","SMS","LMS","MMS","NSA","VOICE","FAX","RCS_SMS","RCS_LMS","RCS_MMS","RCS_TPL","RCS_ITPL","RCS_LTPL"],hn=new Set(cn);function di(t){return hn.has(t)}var oi=["PENDING","SENT","FAILED"],dn="PENDING",ai=(t)=>{let n=typeof t==="string"?t.trim().toUpperCase():"";if(n==="PENDING"||n==="SENT"||n==="FAILED")return n;return dn};export{Zt as validateFieldCryptoConfig,qt as validateErrorRetryPolicy,qn as toCiphertextEnvelopeString,$n as setGlobalLogger,Y as selectActiveKidByRollout,lt as resolveFieldMode,ei as readRuntimeEnv,on as parseErrorRetryPolicyFromJson,bt as ok,x as normalizeRetryAfterMs,an as normalizeProviderError,vt as normalizePhoneForHash,ai as normalizeMessageStatus,Bt as normalizeErrorRetryPolicy,mn as loggerMiddleware,Hn as logger,ri as isTerminalDeliveryStatus,yi as isPollableDeliveryStatus,fi as isKMsgTerminalStatus,di as isKMsgMessageType,si as isKMsgDeliveryStatus,Nn as isCryptoEnvelope,pn as getRuntimeEnvSource,gt as getRolloutKnownKids,ci as getPollableStatuses,R as getLogger,St as fail,En as createVaultTransitKeyResolver,Ft as createStaticKeyResolver,wn as createRollingKeyResolver,B as createRefreshableKeyResolver,Un as createNoopFieldCryptoProvider,Dt as createLogger,bn as createEnvKeyResolver,Pt as createDefaultMasker,Dn as createAwsKmsKeyResolver,In as createAesGcmFieldCryptoProvider,Mn as assertFieldCryptoConfig,_ as RetryHandler,ni as Result,Ot as RateLimiter,dn as QUEUED_MESSAGE_STATUS,X as Logger,ut as LogLevel,oi as KNOWN_MESSAGE_STATUSES,I as KMsgErrorCode,A as KMsgError,fn as KMSG_TERMINAL_STATUSES,kt as KMSG_POLLABLE_STATUSES,cn as KMSG_MESSAGE_TYPES,sn as KMSG_DELIVERY_STATUSES,U as FieldCryptoError,N as ErrorUtils,Tt as CircuitBreaker,L as BulkOperationHandler};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=AF5973A70384F7AB64756E2164756E21
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import type { KMsgError } from "./errors";
|
|
2
2
|
import type { Result } from "./result";
|
|
3
3
|
import type { BalanceQuery, BalanceResult, DeliveryStatusQuery, DeliveryStatusResult, KakaoChannel, KakaoChannelCategories, MessageType, ProviderOnboardingSpec, SendOptions, SendResult } from "./types/index";
|
|
4
|
+
/**
|
|
5
|
+
* Fetch implementation used for a single provider operation.
|
|
6
|
+
*
|
|
7
|
+
* Callers can inject a compatible implementation for runtime-specific
|
|
8
|
+
* transports, tracing, or deterministic tests.
|
|
9
|
+
*/
|
|
10
|
+
export type ProviderFetch = typeof globalThis.fetch;
|
|
11
|
+
/**
|
|
12
|
+
* Per-operation transport context passed to provider calls.
|
|
13
|
+
*
|
|
14
|
+
* Providers that use fetch should forward `signal` unchanged to the
|
|
15
|
+
* underlying request and prefer `fetch` over the runtime global when supplied.
|
|
16
|
+
*/
|
|
17
|
+
export interface ProviderRequestContext {
|
|
18
|
+
/** Abort signal for the underlying provider transport. */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
/** Optional fetch implementation for this operation. */
|
|
21
|
+
fetch?: ProviderFetch;
|
|
22
|
+
}
|
|
23
|
+
export type ProviderTransportSupport = "supported" | "unsupported";
|
|
24
|
+
/** Transport features a provider forwards to its underlying operation. */
|
|
25
|
+
export interface ProviderTransportCapabilities {
|
|
26
|
+
abortSignal: ProviderTransportSupport;
|
|
27
|
+
injectableFetch: ProviderTransportSupport;
|
|
28
|
+
}
|
|
4
29
|
/**
|
|
5
30
|
* Represents an AlimTalk template registered with a provider.
|
|
6
31
|
* Templates must be approved by Kakao before use.
|
|
@@ -182,6 +207,11 @@ export interface Provider {
|
|
|
182
207
|
* Messages of unsupported types will be rejected.
|
|
183
208
|
*/
|
|
184
209
|
readonly supportedTypes: readonly MessageType[];
|
|
210
|
+
/**
|
|
211
|
+
* Per-operation transport features supported by this provider.
|
|
212
|
+
* Missing declarations must be treated as unsupported.
|
|
213
|
+
*/
|
|
214
|
+
readonly transportCapabilities?: ProviderTransportCapabilities;
|
|
185
215
|
/**
|
|
186
216
|
* Check if the provider is operational.
|
|
187
217
|
* Used for health monitoring and circuit breaker decisions.
|
|
@@ -191,12 +221,12 @@ export interface Provider {
|
|
|
191
221
|
* Send a message through this provider.
|
|
192
222
|
* @returns Result with SendResult on success, KMsgError on failure.
|
|
193
223
|
*/
|
|
194
|
-
send(params: SendOptions): Promise<Result<SendResult, KMsgError>>;
|
|
224
|
+
send(params: SendOptions, context?: ProviderRequestContext): Promise<Result<SendResult, KMsgError>>;
|
|
195
225
|
/**
|
|
196
226
|
* Query delivery status for a previously sent message.
|
|
197
227
|
* Optional capability - not all providers support this.
|
|
198
228
|
*/
|
|
199
|
-
getDeliveryStatus?(query: DeliveryStatusQuery): Promise<Result<DeliveryStatusResult | null, KMsgError>>;
|
|
229
|
+
getDeliveryStatus?(query: DeliveryStatusQuery, context?: ProviderRequestContext): Promise<Result<DeliveryStatusResult | null, KMsgError>>;
|
|
200
230
|
/**
|
|
201
231
|
* Get the onboarding specification for this provider.
|
|
202
232
|
* Used by tooling to guide provider configuration.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k-msg/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"packageManager": "bun@1.3.
|
|
3
|
+
"version": "0.30.0",
|
|
4
|
+
"packageManager": "bun@1.3.9",
|
|
5
5
|
"description": "Core types and interfaces for K-Message platform",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bun": "^1.3.14",
|
|
43
|
-
"ttsc": "^0.18.
|
|
43
|
+
"ttsc": "^0.18.4",
|
|
44
44
|
"typescript": "^7.0.2"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {},
|