@k-msg/webhook 0.30.0 → 0.31.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.
@@ -26,12 +26,16 @@ export declare class RetryManager {
26
26
  calculateNextRetry(attemptNumber: number): Date;
27
27
  /**
28
28
  * 재시도 가능 여부 확인
29
+ *
30
+ * Applies the global `maxRetries` budget and, when an `error` is given, the
31
+ * error-type policy of `isRetryableError`. Per-endpoint budgets are enforced
32
+ * by the delivery loop, which calls `shouldRetryStatus`/`isRetryableError`.
29
33
  */
30
34
  shouldRetry(attemptNumber: number, error?: Error): boolean;
31
35
  /**
32
36
  * 재시도 가능한 에러인지 판단
33
37
  */
34
- private isRetryableError;
38
+ isRetryableError(error: Error): boolean;
35
39
  /**
36
40
  * HTTP 상태 코드별 재시도 정책
37
41
  */
@@ -1,5 +1,10 @@
1
1
  import type { WebhookDelivery, WebhookEndpoint } from "../types/webhook.types";
2
2
  import type { WebhookDeliveryListOptions, WebhookDeliveryStore, WebhookEndpointStore, WebhookPersistence } from "./types";
3
+ /** Whether a delivery comes after the cursor in the newest-first order. */
4
+ export declare function isBeforeDeliveryCursor(delivery: WebhookDelivery, cursor: {
5
+ createdAt: Date;
6
+ id: string;
7
+ }): boolean;
3
8
  export declare class InMemoryWebhookEndpointStore implements WebhookEndpointStore {
4
9
  private readonly endpoints;
5
10
  add(endpoint: WebhookEndpoint): Promise<void>;
@@ -11,6 +16,7 @@ export declare class InMemoryWebhookEndpointStore implements WebhookEndpointStor
11
16
  export declare class InMemoryWebhookDeliveryStore implements WebhookDeliveryStore {
12
17
  private readonly deliveries;
13
18
  add(delivery: WebhookDelivery): Promise<void>;
19
+ replace(delivery: WebhookDelivery): Promise<void>;
14
20
  list(options?: WebhookDeliveryListOptions): Promise<WebhookDelivery[]>;
15
21
  }
16
22
  export declare function createInMemoryWebhookPersistence(): WebhookPersistence;
@@ -5,7 +5,17 @@ export interface WebhookDeliveryListOptions {
5
5
  endpointId?: string;
6
6
  eventType?: WebhookEvent["type"];
7
7
  status?: WebhookDelivery["status"];
8
+ /** Caps the deliveries returned; the built-in stores return 100 when unset. */
8
9
  limit?: number;
10
+ /**
11
+ * Returns only deliveries that come after this one in the newest-first
12
+ * order: older, or equally old with a smaller id. Pass the last delivery of
13
+ * a page to read the next one.
14
+ */
15
+ before?: {
16
+ createdAt: Date;
17
+ id: string;
18
+ };
9
19
  }
10
20
  export interface WebhookEndpointStore {
11
21
  add(endpoint: WebhookEndpoint): Promise<void>;
@@ -15,8 +25,15 @@ export interface WebhookEndpointStore {
15
25
  list(): Promise<WebhookEndpoint[]>;
16
26
  }
17
27
  export interface WebhookDeliveryStore {
28
+ /** Stores a new delivery; ids are unique, so use replace() to overwrite. */
18
29
  add(delivery: WebhookDelivery): Promise<void>;
19
30
  list(options?: WebhookDeliveryListOptions): Promise<WebhookDelivery[]>;
31
+ /**
32
+ * Overwrites the stored delivery with the same id. Optional; the tenant
33
+ * migration needs it to re-encrypt stored payloads, and the built-in
34
+ * stores implement it.
35
+ */
36
+ replace?(delivery: WebhookDelivery): Promise<void>;
20
37
  }
21
38
  export interface WebhookPersistence {
22
39
  endpointStore: WebhookEndpointStore;
@@ -32,6 +49,19 @@ export interface WebhookRuntimeFieldCryptoOptions {
32
49
  tenantId?: string;
33
50
  endpoint?: FieldCryptoConfig;
34
51
  delivery?: FieldCryptoConfig;
52
+ /**
53
+ * Also reads secrets and payloads written before ciphertext was bound to
54
+ * `tenantId`, which are otherwise rejected. Set it only while migrating
55
+ * them with `migrateFieldCryptoToTenant()`, then remove it: a tenant-less
56
+ * value copied from another tenant's row with the same id would decrypt.
57
+ */
58
+ acceptLegacyAad?: boolean;
59
+ }
60
+ export interface WebhookTenantMigrationResult {
61
+ /** Endpoints whose secret was re-encrypted with the tenant. */
62
+ endpoints: number;
63
+ /** Deliveries whose payload was re-encrypted with the tenant. */
64
+ deliveries: number;
35
65
  }
36
66
  export type WebhookEndpointInput = Omit<WebhookEndpoint, "id" | "createdAt" | "updatedAt" | "status"> & {
37
67
  id?: string;
@@ -63,5 +93,17 @@ export interface WebhookRuntime {
63
93
  emitSync(event: WebhookEvent): Promise<WebhookDelivery[]>;
64
94
  flush(): Promise<void>;
65
95
  listDeliveries(options?: WebhookDeliveryListOptions): Promise<WebhookDelivery[]>;
96
+ /**
97
+ * Re-encrypts stored endpoint secrets and delivery payloads written before
98
+ * ciphertext was bound to `fieldCrypto.tenantId`. Run it once every
99
+ * instance is upgraded; endpoint writes through this runtime wait until it
100
+ * finishes. See `migrateWebhookFieldCryptoToTenant`.
101
+ */
102
+ migrateFieldCryptoToTenant(): Promise<WebhookTenantMigrationResult>;
103
+ /**
104
+ * Stops the batch timer, delivers the queued events, waits for endpoint
105
+ * writes already queued, and closes the persistence. Endpoint changes
106
+ * requested after it starts are rejected.
107
+ */
66
108
  shutdown(): Promise<void>;
67
109
  }
@@ -1,7 +1,7 @@
1
1
  import { type HttpClient } from "../services/webhook.dispatcher";
2
2
  import { type WebhookDelivery, type WebhookEndpoint, type WebhookEvent, type WebhookTestResult } from "../types/webhook.types";
3
3
  import { resolveEndpointValidationOptions } from "./endpoint-validation";
4
- import type { WebhookDeliveryListOptions, WebhookEndpointInput, WebhookRuntime, WebhookRuntimeConfig, WebhookRuntimeSecurityOptions, WebhookRuntimeTestPayload } from "./types";
4
+ import type { WebhookDeliveryListOptions, WebhookEndpointInput, WebhookRuntime, WebhookRuntimeConfig, WebhookRuntimeSecurityOptions, WebhookRuntimeTestPayload, WebhookTenantMigrationResult } from "./types";
5
5
  export declare class WebhookRuntimeService implements WebhookRuntime {
6
6
  private readonly config;
7
7
  private readonly dispatcher;
@@ -9,14 +9,19 @@ export declare class WebhookRuntimeService implements WebhookRuntime {
9
9
  private readonly deliveryStore;
10
10
  private readonly securityOptions;
11
11
  private readonly persistence;
12
+ private readonly fieldCrypto;
12
13
  private readonly eventQueue;
13
14
  private batchProcessor;
14
15
  private initPromise;
15
- private processing;
16
+ private activeBatch;
17
+ private endpointWrites;
18
+ private shuttingDown;
16
19
  constructor(config: WebhookRuntimeConfig);
17
20
  addEndpoint(input: WebhookEndpointInput): Promise<WebhookEndpoint>;
18
21
  addEndpoints(inputs: readonly WebhookEndpointInput[]): Promise<WebhookEndpoint[]>;
22
+ private insertEndpoint;
19
23
  updateEndpoint(endpointId: string, updates: Partial<WebhookEndpointInput>): Promise<WebhookEndpoint>;
24
+ private applyEndpointUpdate;
20
25
  removeEndpoint(endpointId: string): Promise<void>;
21
26
  getEndpoint(endpointId: string): Promise<WebhookEndpoint | null>;
22
27
  listEndpoints(): Promise<WebhookEndpoint[]>;
@@ -25,11 +30,22 @@ export declare class WebhookRuntimeService implements WebhookRuntime {
25
30
  emitSync(event: WebhookEvent): Promise<WebhookDelivery[]>;
26
31
  flush(): Promise<void>;
27
32
  listDeliveries(options?: WebhookDeliveryListOptions): Promise<WebhookDelivery[]>;
33
+ /**
34
+ * Re-encrypts stored endpoint secrets and delivery payloads written before
35
+ * ciphertext was bound to `fieldCrypto.tenantId`, returning how many of
36
+ * each it rewrote. Run it once every instance is upgraded, then remove
37
+ * `fieldCrypto.acceptLegacyAad` if it was set to keep them readable in
38
+ * the meantime. Endpoint writes through this runtime wait until it
39
+ * finishes. See `migrateWebhookFieldCryptoToTenant`.
40
+ */
41
+ migrateFieldCryptoToTenant(): Promise<WebhookTenantMigrationResult>;
28
42
  shutdown(): Promise<void>;
29
43
  private resolvePersistence;
44
+ private writeEndpoints;
30
45
  private ensureInitialized;
31
46
  private validateEvent;
32
47
  private processBatch;
48
+ private dispatchBatch;
33
49
  private getMatchingEndpoints;
34
50
  private createProbeEvent;
35
51
  private generateEndpointId;
@@ -1,4 +1,4 @@
1
- import { type FieldCryptoConfig } from "@k-msg/core";
1
+ import type { FieldCryptoConfig } from "@k-msg/core";
2
2
  import type { WebhookDelivery, WebhookEndpoint, WebhookEventType } from "../types/webhook.types";
3
3
  export interface WebhookRegistryCryptoOptions {
4
4
  tenantId?: string;
@@ -0,0 +1,13 @@
1
+ var{defineProperty:De,getOwnPropertyNames:rn,getOwnPropertyDescriptor:nn}=Object,on=Object.prototype.hasOwnProperty;function sn(e){return this[e]}var an=(e)=>{var t=(St??=new WeakMap).get(e),r;if(t)return t;if(t=De({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function"){for(var n of rn(e))if(!on.call(t,n))De(t,n,{get:sn.bind(e,n),enumerable:!(r=nn(e,n))||r.enumerable})}return St.set(e,t),t},St;var cn=(e)=>e;function un(e,t){this[e]=cn.bind(null,t)}var ln=(e,t)=>{for(var r in t)De(e,r,{get:t[r],enumerable:!0,configurable:!0,set:un.bind(t,r)})};var Do={};ln(Do,{BatchDispatcher:()=>Me,DefaultHttpClient:()=>ze,DeliveryStore:()=>He,EndpointManager:()=>dt,EventStore:()=>pt,LoadBalancer:()=>We,MockHttpClient:()=>gt,QueueManager:()=>Ke,RetryManager:()=>se,SecurityManager:()=>de,WebhookDispatcher:()=>yt,WebhookRegistry:()=>At});module.exports=an(Do);class A{listenersMap=new Map;on(e,t){let r=this.listenersMap.get(e)??new Set;return r.add(t),this.listenersMap.set(e,r),this}addListener(e,t){return this.on(e,t)}off(e,t){let r=this.listenersMap.get(e);if(!r)return this;if(r.delete(t),r.size===0)this.listenersMap.delete(e);return this}removeListener(e,t){return this.off(e,t)}once(e,t){let r=(...n)=>{this.off(e,r),t(...n)};return this.on(e,r)}emit(e,...t){let r=this.listenersMap.get(e);if(!r||r.size===0)return!1;for(let n of[...r])n(...t);return!0}removeAllListeners(e){if(e)return this.listenersMap.delete(e),this;return this.listenersMap.clear(),this}}class Me extends A{config;pendingJobs=new Map;activeBatches=new Map;batchProcessor=null;defaultConfig={maxBatchSize:100,batchTimeoutMs:5000,maxConcurrentBatches:10,enablePrioritization:!0,priorityLevels:3};constructor(e={}){super();this.config={...this.defaultConfig,...e},this.startBatchProcessor()}async addJob(e){let t=e.endpoint.id;if(!this.pendingJobs.has(t))this.pendingJobs.set(t,[]);let r=this.pendingJobs.get(t);if(this.config.enablePrioritization)this.insertJobByPriority(r,e);else r.push(e);if(r.length>=this.config.maxBatchSize)await this.processBatchForEndpoint(t);this.emit("jobAdded",{endpointId:t,jobId:e.id,queueSize:r.length})}async processBatchForEndpoint(e){let t=this.pendingJobs.get(e);if(!t||t.length===0)return null;if(this.activeBatches.size>=this.config.maxConcurrentBatches)return this.emit("batchSkipped",{endpointId:e,reason:"max_concurrent_batches"}),null;let r=t.splice(0,this.config.maxBatchSize),n=this.createBatch(e,r);this.activeBatches.set(n.id,n);try{this.emit("batchStarted",{batchId:n.id,endpointId:e,jobCount:r.length}),await this.executeBatch(n,r),n.status="completed",this.emit("batchCompleted",{batchId:n.id,endpointId:e,success:!0})}catch(o){n.status="failed",this.emit("batchFailed",{batchId:n.id,endpointId:e,error:o instanceof Error?o.message:"Unknown error"}),this.requeueFailedJobs(r)}finally{this.activeBatches.delete(n.id)}return n}async processAllBatches(){let e=[],t=Array.from(this.pendingJobs.keys());for(let r of t){let n=await this.processBatchForEndpoint(r);if(n)e.push(n)}return e}getBatchStats(){let e=Array.from(this.pendingJobs.keys()),t=e.reduce((r,n)=>r+(this.pendingJobs.get(n)?.length||0),0);return{pendingJobsCount:t,activeBatchesCount:this.activeBatches.size,endpointsWithPendingJobs:e.length,averageQueueSize:e.length>0?t/e.length:0}}getPendingJobCount(e){return this.pendingJobs.get(e)?.length||0}startBatchProcessor(){this.batchProcessor=setInterval(()=>{this.processAllBatches().catch((e)=>{this.emit("processorError",e)})},this.config.batchTimeoutMs)}insertJobByPriority(e,t){let r=0;for(let n=0;n<e.length;n++){if(e[n].priority<=t.priority){r=n;break}r=n+1}e.splice(r,0,t)}createBatch(e,t){return{id:`batch_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,endpointId:e,events:t.map((r)=>r.event),createdAt:new Date,scheduledAt:new Date,status:"processing"}}async executeBatch(e,t){if(!t[0]?.endpoint)throw Error("No endpoint found for batch");let n=t.map((o)=>this.executeJob(o));try{let o=await Promise.allSettled(n),i=o.filter((a)=>a.status==="fulfilled").length,s=o.length-i;if(this.emit("batchExecuted",{batchId:e.id,endpointId:e.endpointId,total:o.length,successful:i,failed:s}),s>0)throw Error(`Batch partially failed: ${s}/${o.length} jobs failed`)}catch(o){throw this.emit("batchExecutionError",{batchId:e.id,endpointId:e.endpointId,error:o instanceof Error?o.message:"Unknown error"}),o}}async executeJob(e){let t={id:`delivery_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,endpointId:e.endpoint.id,eventId:e.event.id,url:e.endpoint.url,httpMethod:"POST",headers:{"Content-Type":"application/json"},payload:JSON.stringify(e.event),attempts:[],status:"pending",createdAt:new Date},r=Math.random()>0.1;return t.attempts.push({attemptNumber:1,timestamp:new Date,httpStatus:r?200:500,responseBody:r?"OK":"Internal Server Error",error:r?void 0:"Server error",latencyMs:Math.floor(Math.random()*1000)+100}),t.status=r?"success":"failed",t.completedAt=new Date,t}requeueFailedJobs(e){for(let t of e)if(t.attempts++,t.attempts<t.maxAttempts){let o=1000*2**(t.attempts-1);t.nextRetryAt=new Date(Date.now()+o),t.scheduledAt=t.nextRetryAt,setTimeout(()=>{this.addJob(t).catch((i)=>{this.emit("requeueError",{jobId:t.id,error:i instanceof Error?i.message:"Unknown error"})})},o)}else this.emit("jobExhausted",{jobId:t.id,endpointId:t.endpoint.id,attempts:t.attempts})}async shutdown(){if(this.batchProcessor)clearInterval(this.batchProcessor),this.batchProcessor=null;let e=30000,t=Date.now();while(this.activeBatches.size>0&&Date.now()-t<e)await new Promise((r)=>setTimeout(r,100));this.emit("shutdown",{pendingJobs:this.getBatchStats().pendingJobsCount,activeBatches:this.activeBatches.size})}}var Fe;((y)=>{y.INVALID_REQUEST="INVALID_REQUEST";y.AUTHENTICATION_FAILED="AUTHENTICATION_FAILED";y.INSUFFICIENT_BALANCE="INSUFFICIENT_BALANCE";y.TEMPLATE_NOT_FOUND="TEMPLATE_NOT_FOUND";y.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";y.NETWORK_ERROR="NETWORK_ERROR";y.NETWORK_TIMEOUT="NETWORK_TIMEOUT";y.NETWORK_SERVICE_UNAVAILABLE="NETWORK_SERVICE_UNAVAILABLE";y.REQUEST_ABORTED="REQUEST_ABORTED";y.PROVIDER_ERROR="PROVIDER_ERROR";y.MESSAGE_SEND_FAILED="MESSAGE_SEND_FAILED";y.CRYPTO_CONFIG_ERROR="CRYPTO_CONFIG_ERROR";y.CRYPTO_ENCRYPT_FAILED="CRYPTO_ENCRYPT_FAILED";y.CRYPTO_DECRYPT_FAILED="CRYPTO_DECRYPT_FAILED";y.CRYPTO_HASH_FAILED="CRYPTO_HASH_FAILED";y.CRYPTO_POLICY_VIOLATION="CRYPTO_POLICY_VIOLATION";y.UNKNOWN_ERROR="UNKNOWN_ERROR"})(Fe||={});var dn={["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"}},Oo=new Set(Object.values(Fe));var Te=(e)=>{if(typeof e!=="number"||Number.isNaN(e)||!Number.isFinite(e))return;return Math.trunc(e)};class me extends Error{code;details;providerErrorCode;providerErrorText;httpStatus;requestId;retryAfterMs;attempt;causeChain;constructor(e,t,r,n={}){super(t);if(this.name="KMsgError",this.code=e,this.details=r,this.providerErrorCode=n.providerErrorCode,this.providerErrorText=n.providerErrorText,this.httpStatus=Te(n.httpStatus),this.requestId=typeof n.requestId==="string"?n.requestId:void 0,this.retryAfterMs=Te(n.retryAfterMs),this.attempt=Te(n.attempt),Array.isArray(n.causeChain))this.causeChain=n.causeChain;else if(n.causeChain!==void 0)this.causeChain=[n.causeChain];let o=Error.captureStackTrace;if(o)o(this,me)}getLocalizedMessage(e="ko"){let t=dn[this.code];if(t?.[e])return t[e];return this.message}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,providerErrorCode:this.providerErrorCode,providerErrorText:this.providerErrorText,httpStatus:this.httpStatus,requestId:this.requestId,retryAfterMs:this.retryAfterMs,attempt:this.attempt,causeChain:this.causeChain}}}function pn(e){switch(e){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 _ extends me{kind;fieldPath;failMode;openFallback;constructor(e,t,r,n={}){super(pn(e),t,r,n);this.name="FieldCryptoError",this.kind=e,this.fieldPath=typeof n.fieldPath==="string"?n.fieldPath:void 0,this.failMode=n.failMode,this.openFallback=n.openFallback}toJSON(){return{...super.toJSON(),kind:this.kind,fieldPath:this.fieldPath,failMode:this.failMode,openFallback:this.openFallback}}}function Ze(e){return typeof e==="function"}function $t(e){if(typeof e!=="string")return;let t=e.trim();return t.length>0?t:void 0}function Rt(e,t,r){let n=e.fields[t];if(n)return n;if(t.startsWith("metadata.")){let o=e.fields["metadata.*"];if(o)return o}return r}var fn=["closed","open"],zt=["masked","plaintext","null"];function ge(e){return e.failMode==="open"?"open":"closed"}function Oe(e){let t=e.openFallback;return t!==void 0&&zt.includes(t)?t:"masked"}function hn(e,t={}){let r=[];if(!e||typeof e!=="object")return{valid:!1,issues:[{message:"fieldCrypto config must be an object",rule:"fieldCrypto.config.object",hint:"Provide a valid FieldCryptoConfig object"}]};if(!e.provider||typeof e.provider!=="object")r.push({message:"fieldCrypto provider is required",rule:"fieldCrypto.provider.required",path:"provider",hint:"Set provider with encrypt/decrypt/hash methods"});else{if(!Ze(e.provider.encrypt))r.push({message:"provider.encrypt must be a function",rule:"fieldCrypto.provider.encrypt.required",path:"provider.encrypt"});if(!Ze(e.provider.decrypt))r.push({message:"provider.decrypt must be a function",rule:"fieldCrypto.provider.decrypt.required",path:"provider.decrypt"});if(!Ze(e.provider.hash))r.push({message:"provider.hash must be a function",rule:"fieldCrypto.provider.hash.required",path:"provider.hash"})}if(!e.fields||typeof e.fields!=="object")r.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 i=Object.entries(e.fields);if(i.length===0)r.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[s,a]of i){if(!$t(s))r.push({message:"field path must be a non-empty string",rule:"fieldCrypto.fields.path.non_empty",path:"fields"});if(a!=="plain"&&a!=="encrypt"&&a!=="encrypt+hash"&&a!=="mask")r.push({message:`unsupported field mode: ${String(a)}`,rule:"fieldCrypto.fields.mode.supported",path:`fields.${s}`})}}if(e.failMode!==void 0&&!fn.includes(e.failMode))r.push({message:`unsupported failMode: ${String(e.failMode)}`,rule:"fieldCrypto.fail_mode.supported",path:"failMode",hint:'Use "closed" (default) or "open"'});if(e.openFallback!==void 0&&!zt.includes(e.openFallback))r.push({message:`unsupported openFallback: ${String(e.openFallback)}`,rule:"fieldCrypto.open_fallback.supported",path:"openFallback",hint:'Use "masked" (default), "null", or "plaintext"'});let n=ge(e),o=Oe(e);if(n==="open"&&o==="plaintext"&&e.unsafeAllowPlaintextStorage!==!0)r.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(e.aadFields)){if(e.aadFields.length===0)r.push({message:"aadFields must not be empty when provided",rule:"fieldCrypto.aad_fields.non_empty",path:"aadFields"});for(let i=0;i<e.aadFields.length;i+=1){let s=e.aadFields[i];if(!$t(s))r.push({message:"aadFields cannot include empty key",rule:"fieldCrypto.aad_fields.no_empty_key",path:`aadFields[${i}]`})}}if(t.secureMode&&!t.compatPlainColumns){let i=Rt(e,"to","encrypt+hash"),s=Rt(e,"from","encrypt+hash");if(i==="plain")r.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(s==="plain")r.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:r.length===0,issues:r}}function Le(e,t={}){let r=hn(e,t);if(r.valid)return;let n=r.issues[0];if(!n)throw new _("config","fieldCrypto config validation failed",{rule:"fieldCrypto.config.invalid",issues:r.issues});throw new _("config",n.message,{rule:n.rule,path:n.path,hint:n.hint,issues:r.issues},{fieldPath:n.path})}function mn(e){if(typeof e==="string")return e;return JSON.stringify(e)}function gn(e){if(!e||typeof e!=="object")return!1;let t=e;return typeof t.v==="number"&&typeof t.alg==="string"&&typeof t.kid==="string"&&typeof t.iv==="string"&&typeof t.tag==="string"&&typeof t.ct==="string"}function It(e=3,t=2){return(r)=>{let n=String(r??"");if(n.length<=e+t)return"*".repeat(Math.max(0,n.length));let o=n.slice(0,e),i=n.slice(-t);return`${o}${"*".repeat(n.length-e-t)}${i}`}}function yn(e){let t=gn(e);if(t&&e.v===1&&e.alg==="A256GCM")return;let r=e&&typeof e==="object"?e:{};throw new _("policy","ciphertext envelope must be v1 A256GCM with string kid, iv, tag, and ct",{rule:"fieldCrypto.envelope.v1",shapeValid:t,v:r.v,alg:r.alg})}function Dt(e){if(typeof e==="string")return e;yn(e);let{v:t,alg:r,kid:n,iv:o,tag:i,ct:s}=e;return mn({v:t,alg:r,kid:n,iv:o,tag:i,ct:s})}var bn=["to","from","phone","phoneNumber","recipient","sender","secret","apiKey","apiSecret","authorization","auth","token","password","payload","message","content","text"],te=String.raw`\w.[\]"'-`,xn=new RegExp(String.raw`^[${te}]*(?:(?:secret|password|passwd|passphrase|token|credential|private[-_.]?key|api[-_.]?key)[${te}]*|auth(?:orization)?(?:[.[\]"'][${te}]*)?)$`,"i");function Tt(e){return xn.test(e.replace(/\s+/g,"_"))}function vn(e){if(Tt(e))return!0;let t=e.toLowerCase();return bn.some((r)=>t.includes(r.toLowerCase()))}function Ft(e){let t=e.trim();if(t.length<=4)return"***";if(t.includes("@")){let[o,i]=t.split("@");return`${o.slice(0,2)}${"*".repeat(Math.max(1,o.length-2))}@${i}`}let r=t.slice(0,3),n=t.slice(-2);return`${r}${"*".repeat(Math.max(1,t.length-5))}${n}`}var _n=new RegExp([String.raw`(?:\+82[-.\s]?(?:\(0\)[-.\s]?|0)?|0)(?:1[016789]|2|70|80|50\d|[3-6]\d)[-.\s]?\d{3,4}[-.\s]?\d{4}`,String.raw`\(0\d{1,2}\)[-.\s]?\d{3,4}[-.\s]?\d{4}`,String.raw`1[5-9]\d{2}[-\s]\d{4}`].map((e)=>String.raw`(?<![\w+])${e}(?!\w)`).join("|"),"g"),En=/(\b[a-z][\w+.-]{0,31}:\/\/[^\s/:@]*):[^\s/?#]*@/gi,wn=[String.raw`"(?:\\.|[^"\\\n])*"?`,String.raw`'(?:\\.|[^'\\\n])*'?`,String.raw`\\"(?:\\\\(?:\\.|[^\\\n])|\\[^"\\\n]|[^\\\n])*(?:\\")?`,String.raw`\\'(?:\\\\(?:\\.|[^\\\n])|\\[^'\\\n]|[^\\\n])*(?:\\')?`],kn=new RegExp(String.raw`(?<![${te}])((?:["']?(?:api|private)[ \t]+)?[${te}]+)((?:\\?["'])?\s*[:=]\s*)`,"gi"),Mt=new RegExp(String.raw`${wn.join("|")}|((?:Bearer|Basic)\s+)?[^\s"',;&]+`,"iy");function Cn(e){let t="",r=0;for(let n of e.matchAll(kn)){let[o,i=""]=n;if(n.index<r||!Tt(i))continue;let s=n.index+o.length;Mt.lastIndex=s;let a=Mt.exec(e);if(!a)continue;let l=/^\\?["']/.exec(a[0])?.[0];t+=e.slice(r,s),t+=l?`${l}[REDACTED]${l}`:`${a[1]??""}[REDACTED]`,r=s+a[0].length}return t+e.slice(r)}function ye(e){return Cn(e.replace(En,"$1:[REDACTED]@").replace(_n,(t)=>Ft(t)))}function Ne(e,t){if(t===void 0||t===null)return t;if(vn(e)){if(typeof t==="string")return Ft(t);if(typeof t==="number"||typeof t==="boolean")return"***";if(Array.isArray(t))return"[REDACTED]";if(typeof t==="object")return"[REDACTED]"}if(Array.isArray(t))return t.map((r)=>Ne(e,r));if(typeof t==="object"){let r={};for(let[n,o]of Object.entries(t))r[n]=Ne(n,o);return r}if(typeof t==="string")return ye(t);return t}function An(e){let t={};for(let[r,n]of Object.entries(e))t[r]=Ne(r,n);return t}class Ue{config;context;constructor(e={},t={}){this.context=e,this.config={level:"INFO",enableConsole:!0,enableJson:!1,enableColors:!0,...t}}shouldLog(e){let t=["DEBUG","INFO","WARN","ERROR"];return t.indexOf(e)>=t.indexOf(this.config.level)}formatMessage(e){let t=An(e.context),r=ye(e.message),n=e.error&&{name:e.error.name,message:ye(e.error.message),stack:e.error.stack?ye(e.error.stack):void 0};if(this.config.enableJson)return JSON.stringify({level:e.level,message:r,timestamp:e.timestamp.toISOString(),context:t,...n&&{error:n},...e.duration&&{duration:e.duration}});let o=e.timestamp.toISOString(),i=this.config.enableColors?this.colorizeLevel(e.level):e.level,s=Object.keys(t).length>0?` [${Object.entries(t).map(([l,c])=>`${l}=${c}`).join(", ")}]`:"",a=`${o} ${i}${s}: ${r}`;if(e.duration!==void 0)a+=` (${e.duration}ms)`;if(n)a+=`
2
+ ${n.stack??`${n.name}: ${n.message}`}`;return a}colorizeLevel(e){if(!this.config.enableColors)return e;return`${{["DEBUG"]:"\x1B[36m",["INFO"]:"\x1B[32m",["WARN"]:"\x1B[33m",["ERROR"]:"\x1B[31m"}[e]}${e}\x1B[0m`}writeLog(e){if(!this.shouldLog(e.level))return;let t=this.formatMessage(e);if(this.config.enableConsole)(e.level==="ERROR"?console.error:e.level==="WARN"?console.warn:console.log)(t);if(this.config.enableFile&&this.config.filePath);}debug(e,t={}){this.writeLog({level:"DEBUG",message:e,timestamp:new Date,context:{...this.context,...t}})}info(e,t={}){this.writeLog({level:"INFO",message:e,timestamp:new Date,context:{...this.context,...t}})}warn(e,t={},r){this.writeLog({level:"WARN",message:e,timestamp:new Date,context:{...this.context,...t},error:r})}error(e,t={},r){this.writeLog({level:"ERROR",message:e,timestamp:new Date,context:{...this.context,...t},error:r})}child(e){return new Ue({...this.context,...e},this.config)}time(e){let t=Date.now();return()=>{let r=Date.now()-t;this.info(`${e} completed`,{duration:r})}}async measure(e,t,r={}){let n=Date.now(),o={...r,operation:e};this.debug(`Starting ${e}`,o);try{let i=await t(),s=Date.now()-n;return this.info(`Completed ${e}`,{...o,duration:s}),i}catch(i){let s=Date.now()-n;throw this.error(`Failed ${e}`,{...o,duration:s},i instanceof Error?i:Error(String(i))),i}}}var Be;function Pn(e,t){return new Ue(e,t)}function W(){if(!Be)Be=Pn();return Be}var Y={debug:(e,t)=>W().debug(e,t),info:(e,t)=>W().info(e,t),warn:(e,t,r)=>W().warn(e,t,r),error:(e,t,r)=>W().error(e,t,r),child:(e)=>W().child(e),time:(e)=>W().time(e),measure:(e,t,r)=>W().measure(e,t,r)};class We extends A{config;endpointHealth=new Map;endpoints=new Map;circuitBreakers=new Map;connectionCounts=new Map;roundRobinIndex=0;healthCheckInterval=null;defaultConfig={strategy:"round-robin",healthCheckInterval:30000,healthCheckTimeoutMs:5000,weights:{}};constructor(e={}){super();this.config={...this.defaultConfig,...e},this.startHealthChecks()}async registerEndpoint(e){let t={endpointId:e.id,isHealthy:!0,consecutiveFailures:0,lastHealthCheckAt:new Date,averageResponseTime:0,activeConnections:0};this.endpointHealth.set(e.id,t),this.endpoints.set(e.id,e),this.connectionCounts.set(e.id,0),await this.checkEndpointHealth(e),this.emit("endpointRegistered",{endpointId:e.id,isHealthy:t.isHealthy})}async unregisterEndpoint(e){this.endpointHealth.delete(e),this.endpoints.delete(e),this.circuitBreakers.delete(e),this.connectionCounts.delete(e),this.emit("endpointUnregistered",{endpointId:e})}async selectEndpoint(e){let t=e.filter((n)=>{let o=this.endpointHealth.get(n.id),i=this.circuitBreakers.get(n.id);return o?.isHealthy&&n.status==="active"&&i?.state!=="open"});if(t.length===0){let n=this.tryHalfOpenEndpoint(e);if(n)return n;return this.emit("noHealthyEndpoints",{totalEndpoints:e.length}),null}let r;switch(this.config.strategy){case"round-robin":r=this.selectRoundRobin(t);break;case"least-connections":r=this.selectLeastConnections(t);break;case"weighted":r=this.selectWeighted(t);break;case"random":r=this.selectRandom(t);break;default:r=t[0]}return this.incrementConnections(r.id),this.emit("endpointSelected",{endpointId:r.id,strategy:this.config.strategy,availableEndpoints:t.length}),r}async onRequestComplete(e,t,r){this.decrementConnections(e);let n=this.endpointHealth.get(e);if(n){if(n.averageResponseTime===0)n.averageResponseTime=r;else n.averageResponseTime=n.averageResponseTime*0.8+r*0.2;if(t){n.consecutiveFailures=0,n.isHealthy=!0;let o=this.circuitBreakers.get(e);if(o){if(o.state==="half-open")o.state="closed",o.failureCount=0,this.emit("circuitBreakerClosed",{endpointId:e})}}else{if(n.consecutiveFailures++,n.consecutiveFailures>=3)n.isHealthy=!1,this.emit("endpointUnhealthy",{endpointId:e,consecutiveFailures:n.consecutiveFailures});this.updateCircuitBreaker(e,!1)}}this.emit("requestCompleted",{endpointId:e,success:t,responseTime:r,averageResponseTime:n?.averageResponseTime})}getEndpointHealth(e){return this.endpointHealth.get(e)||null}getAllEndpointHealth(){return Array.from(this.endpointHealth.values())}getStats(){let e=Array.from(this.endpointHealth.values()),t=Array.from(this.connectionCounts.values()).reduce((o,i)=>o+i,0),r=Array.from(this.circuitBreakers.values()).filter((o)=>o.state==="open").length,n=e.length>0?e.reduce((o,i)=>o+i.averageResponseTime,0)/e.length:0;return{totalEndpoints:e.length,healthyEndpoints:e.filter((o)=>o.isHealthy).length,activeConnections:t,circuitBreakersOpen:r,averageResponseTime:n}}selectRoundRobin(e){let t=e[this.roundRobinIndex%e.length];return this.roundRobinIndex=(this.roundRobinIndex+1)%e.length,t}selectLeastConnections(e){return e.reduce((t,r)=>{let n=this.connectionCounts.get(t.id)||0;return(this.connectionCounts.get(r.id)||0)<n?r:t})}selectWeighted(e){let t=this.config.weights||{},r=e.reduce((o,i)=>o+(t[i.id]||1),0),n=Math.random()*r;for(let o of e){let i=t[o.id]||1;if(n-=i,n<=0)return o}return e[0]}selectRandom(e){let t=Math.floor(Math.random()*e.length);return e[t]}tryHalfOpenEndpoint(e){let t=new Date;for(let r of e){let n=this.circuitBreakers.get(r.id);if(n?.state==="open"&&n.nextRetryTime&&t>=n.nextRetryTime)return n.state="half-open",this.emit("circuitBreakerHalfOpen",{endpointId:r.id}),r}return null}updateCircuitBreaker(e,t){let r=this.circuitBreakers.get(e);if(!r)r={endpointId:e,state:"closed",failureCount:0},this.circuitBreakers.set(e,r);if(!t){if(r.failureCount++,r.lastFailureTime=new Date,r.failureCount>=5&&r.state==="closed")r.state="open",r.nextRetryTime=new Date(Date.now()+60000),this.emit("circuitBreakerOpened",{endpointId:e,failureCount:r.failureCount,nextRetryTime:r.nextRetryTime})}}incrementConnections(e){let t=this.connectionCounts.get(e)||0;this.connectionCounts.set(e,t+1);let r=this.endpointHealth.get(e);if(r)r.activeConnections=t+1}decrementConnections(e){let t=this.connectionCounts.get(e)||0,r=Math.max(0,t-1);this.connectionCounts.set(e,r);let n=this.endpointHealth.get(e);if(n)n.activeConnections=r}async checkEndpointHealth(e){let t=Date.now();try{let r=await fetch(e.url,{method:"HEAD",signal:AbortSignal.timeout(this.config.healthCheckTimeoutMs)}),n=Date.now()-t,o=r.ok;await this.onRequestComplete(e.id,o,n),this.emit("healthCheckCompleted",{endpointId:e.id,success:o,responseTime:n,httpStatus:r.status})}catch(r){let n=Date.now()-t;await this.onRequestComplete(e.id,!1,n),this.emit("healthCheckFailed",{endpointId:e.id,error:r instanceof Error?r.message:"Unknown error",responseTime:n})}}startHealthChecks(){this.healthCheckInterval=setInterval(()=>{this.checkAllEndpoints().catch((e)=>{Y.error("Webhook endpoint health check failed",void 0,e instanceof Error?e:Error(String(e)))})},this.config.healthCheckInterval)}async checkAllEndpoints(){let e=Array.from(this.endpoints.values());for(let t of e)await this.checkEndpointHealth(t)}async shutdown(){if(this.healthCheckInterval)clearInterval(this.healthCheckInterval),this.healthCheckInterval=null;this.emit("shutdown",{totalEndpoints:this.endpointHealth.size,activeConnections:Array.from(this.connectionCounts.values()).reduce((e,t)=>e+t,0)})}}function w(e){if(!e)throw Error("File storage requires `fileAdapter`. Provide a runtime-specific adapter (Node fs, Worker KV/R2, etc.).");return e}function je(e,t){let r=e.replace(/[\\/]+$/,""),n=t.replace(/^[\\/]+/,"");if(!r)return n;return`${r}/${n}`}function T(e){if(typeof e!=="object"||e===null)return!1;let t=e;return t.code==="ENOENT"||t.name==="NotFoundError"}class Ke extends A{config;queues=new Map;highPriorityQueue=[];mediumPriorityQueue=[];lowPriorityQueue=[];delayedJobs=new Map;ttlCleanupInterval=null;totalJobs=0;defaultConfig={maxQueueSize:1e4,persistToDisk:!1,compressionEnabled:!1,ttlMs:86400000};constructor(e={}){super();if(this.config={...this.defaultConfig,...e},this.queues.set("high",this.highPriorityQueue),this.queues.set("medium",this.mediumPriorityQueue),this.queues.set("low",this.lowPriorityQueue),this.config.persistToDisk&&this.config.diskPath)this.loadFromDisk().catch((t)=>{this.emit("diskLoadError",t)});this.startTTLCleanup()}async enqueue(e){if(this.totalJobs>=this.config.maxQueueSize)return this.emit("queueFull",{totalJobs:this.totalJobs,maxSize:this.config.maxQueueSize}),!1;if(e.scheduledAt>new Date)return await this.scheduleDelayedJob(e),!0;let t=this.getQueueName(e.priority),r=this.queues.get(t);if(!r)throw Error(`Invalid queue name: ${t}`);if(r.push(e),this.totalJobs++,this.emit("jobEnqueued",{jobId:e.id,priority:e.priority,queueName:t,totalJobs:this.totalJobs}),this.config.persistToDisk)await this.saveToDisk().catch((n)=>{this.emit("diskSaveError",n)});return!0}async dequeue(){for(let[e,t]of this.queues.entries())if(t.length>0){let r=t.shift();if(this.totalJobs--,this.emit("jobDequeued",{jobId:r.id,queueName:e,totalJobs:this.totalJobs}),this.config.persistToDisk)await this.saveToDisk().catch((n)=>{this.emit("diskSaveError",n)});return r}return null}async dequeueFromPriority(e){let t=this.getQueueName(e),r=this.queues.get(t);if(!r||r.length===0)return null;let n=r.shift();return this.totalJobs--,this.emit("jobDequeued",{jobId:n.id,queueName:t,totalJobs:this.totalJobs}),n}peek(){for(let e of this.queues.values())if(e.length>0)return e[0];return null}async removeJob(e){for(let[r,n]of this.queues.entries()){let o=n.findIndex((i)=>i.id===e);if(o!==-1){if(n.splice(o,1),this.totalJobs--,this.emit("jobRemoved",{jobId:e,queueName:r,totalJobs:this.totalJobs}),this.config.persistToDisk)await this.saveToDisk().catch((i)=>{this.emit("diskSaveError",i)});return!0}}let t=this.delayedJobs.get(e);if(t)return clearTimeout(t),this.delayedJobs.delete(e),this.emit("delayedJobCanceled",{jobId:e}),!0;return!1}getStats(){return{totalJobs:this.totalJobs,highPriorityJobs:this.highPriorityQueue.length,mediumPriorityJobs:this.mediumPriorityQueue.length,lowPriorityJobs:this.lowPriorityQueue.length,delayedJobs:this.delayedJobs.size,queueUtilization:this.totalJobs/this.config.maxQueueSize*100}}async clear(){for(let e of this.queues.values())e.length=0;for(let e of this.delayedJobs.values())clearTimeout(e);if(this.delayedJobs.clear(),this.totalJobs=0,this.emit("queueCleared"),this.config.persistToDisk)await this.saveToDisk().catch((e)=>{this.emit("diskSaveError",e)})}async cleanupExpiredJobs(){let e=new Date,t=0;for(let[r,n]of this.queues.entries())for(let o=n.length-1;o>=0;o--){let i=n[o],s=e.getTime()-i.createdAt.getTime();if(s>this.config.ttlMs)n.splice(o,1),this.totalJobs--,t++,this.emit("jobExpired",{jobId:i.id,queueName:r,age:s})}if(t>0){if(this.emit("expiredJobsCleanup",{removedCount:t,totalJobs:this.totalJobs}),this.config.persistToDisk)await this.saveToDisk().catch((r)=>{this.emit("diskSaveError",r)})}return t}getQueueName(e){if(e>=8)return"high";if(e>=5)return"medium";return"low"}async scheduleDelayedJob(e){let t=e.scheduledAt.getTime()-Date.now(),r=setTimeout(()=>{this.activateDelayedJob(e).catch((n)=>{Y.error("Failed to activate delayed webhook job",{jobId:e.id},n instanceof Error?n:Error(String(n)))})},t);this.delayedJobs.set(e.id,r),this.emit("jobScheduled",{jobId:e.id,scheduledAt:e.scheduledAt,delay:t})}async activateDelayedJob(e){if(this.delayedJobs.delete(e.id),await this.enqueue({...e,scheduledAt:new Date}))this.emit("delayedJobActivated",{jobId:e.id})}startTTLCleanup(){if(this.ttlCleanupInterval)clearInterval(this.ttlCleanupInterval);this.ttlCleanupInterval=setInterval(()=>{this.cleanupExpiredJobs().catch((e)=>{this.emit("cleanupError",e)})},300000)}async saveToDisk(){if(!this.config.diskPath)return;try{let e=w(this.config.fileAdapter),t={queues:{high:this.highPriorityQueue,medium:this.mediumPriorityQueue,low:this.lowPriorityQueue},totalJobs:this.totalJobs,timestamp:new Date().toISOString()},r=JSON.stringify(t,null,2),n=je(this.config.diskPath,"webhook-queue.json");await e.ensureDirForFile(n),await e.writeFile(n,r),this.emit("diskSaved",{filePath:n,totalJobs:this.totalJobs})}catch(e){throw this.emit("diskSaveError",e),e}}async loadFromDisk(){if(!this.config.diskPath)return;try{let e=w(this.config.fileAdapter),t=je(this.config.diskPath,"webhook-queue.json"),r=await e.readFile(t),n=JSON.parse(r);this.highPriorityQueue.length=0,this.mediumPriorityQueue.length=0,this.lowPriorityQueue.length=0,this.highPriorityQueue.push(...n.queues.high||[]),this.mediumPriorityQueue.push(...n.queues.medium||[]),this.lowPriorityQueue.push(...n.queues.low||[]),this.totalJobs=n.totalJobs||0,this.emit("diskLoaded",{filePath:t,totalJobs:this.totalJobs,timestamp:n.timestamp})}catch(e){if(!T(e))this.emit("diskLoadError",e)}}async shutdown(){if(this.ttlCleanupInterval)clearInterval(this.ttlCleanupInterval),this.ttlCleanupInterval=null;for(let e of this.delayedJobs.values())clearTimeout(e);if(this.delayedJobs.clear(),this.config.persistToDisk)await this.saveToDisk().catch((e)=>{this.emit("diskSaveError",e)});this.emit("shutdown",{totalJobs:this.totalJobs})}}class He extends A{config;deliveries=new Map;indexByEndpoint=new Map;indexByStatus=new Map;indexByDate=new Map;cleanupInterval=null;defaultConfig={type:"memory",retentionDays:30,enableCompression:!1,maxMemoryUsage:104857600};constructor(e={}){super();if(this.config={...this.defaultConfig,...e},this.initializeIndexes(),this.startCleanupTask(),this.config.type==="file"&&this.config.filePath)this.loadFromFile().catch((t)=>{this.emit("loadError",t)})}async saveDelivery(e){let t=this.deliveries.get(e.id);if(t)this.removeFromIndexes(t);if(this.config.type==="memory"&&this.config.maxMemoryUsage)await this.checkMemoryUsage();if(this.deliveries.set(e.id,e),this.addToIndexes(e),this.config.type==="file")await this.appendToFile(e);this.emit("deliverySaved",{deliveryId:e.id,endpointId:e.endpointId,status:e.status})}async getDelivery(e){return this.deliveries.get(e)||null}async searchDeliveries(e={},t={page:1,limit:100}){let r=null;if(e.endpointId){let c=this.indexByEndpoint.get(e.endpointId);r=c?new Set(c):new Set}if(e.status){let c=this.indexByStatus.get(e.status);if(r)r=new Set(Array.from(r).filter((u)=>c?.has(u)));else r=c?new Set(c):new Set}if(e.createdAfter||e.createdBefore){let c=this.getDeliveryIdsByDateRange(e.createdAfter,e.createdBefore);if(r)r=new Set(Array.from(r).filter((u)=>c.has(u)));else r=c}if(!r)r=new Set(this.deliveries.keys());let n=Array.from(r).map((c)=>this.deliveries.get(c)).filter((c)=>this.matchesFilter(c,e));n.sort((c,u)=>{if(t.sortBy==="createdAt"||!t.sortBy){let h=u.createdAt.getTime()-c.createdAt.getTime();return t.sortOrder==="asc"?-h:h}let p=this.getFieldValue(c,t.sortBy),d=this.getFieldValue(u,t.sortBy),f=0;if(p<d)f=-1;else if(p>d)f=1;return t.sortOrder==="desc"?-f:f});let o=n.length,i=Math.ceil(o/t.limit),s=(t.page-1)*t.limit,a=s+t.limit;return{items:n.slice(s,a),totalCount:o,page:t.page,totalPages:i,hasNext:t.page<i,hasPrevious:t.page>1}}async getDeliveriesByEndpoint(e,t=100){let r=this.indexByEndpoint.get(e);if(!r)return[];return Array.from(r).map((n)=>this.deliveries.get(n)).sort((n,o)=>o.createdAt.getTime()-n.createdAt.getTime()).slice(0,t)}async getFailedDeliveries(e,t=100){let r={status:"failed",endpointId:e};return(await this.searchDeliveries(r,{page:1,limit:t})).items}async getDeliveryStats(e,t){let r={endpointId:e,createdAfter:t?.start,createdBefore:t?.end},o=(await this.searchDeliveries(r,{page:1,limit:1e4})).items,i=o.filter((f)=>f.status==="success"),s=o.filter((f)=>f.status==="failed"),a=o.filter((f)=>f.status==="pending"),l=o.filter((f)=>f.status==="exhausted"),c=o.filter((f)=>f.completedAt),u=c.reduce((f,h)=>{let g=h.attempts[h.attempts.length-1];return f+(g?.latencyMs||0)},0),p=c.length>0?u/c.length:0,d={};for(let f of[...s,...l]){let h=f.attempts[f.attempts.length-1];if(h?.error)d[h.error]=(d[h.error]||0)+1;else if(h?.httpStatus){let g=`HTTP ${h.httpStatus}`;d[g]=(d[g]||0)+1}}return{totalDeliveries:o.length,successfulDeliveries:i.length,failedDeliveries:s.length,pendingDeliveries:a.length,exhaustedDeliveries:l.length,averageLatency:p,successRate:o.length>0?i.length/o.length*100:0,errorBreakdown:d}}async cleanupOldDeliveries(){if(!this.config.retentionDays)return 0;let e=new Date;e.setDate(e.getDate()-this.config.retentionDays);let t=Array.from(this.deliveries.values()).filter((r)=>r.createdAt<e);for(let r of t)this.removeFromIndexes(r),this.deliveries.delete(r.id);if(t.length>0){if(this.emit("oldDeliveriesCleanup",{removedCount:t.length,cutoffDate:e}),this.config.type==="file")await this.saveToFile()}return t.length}getStorageStats(){let e=this.estimateMemoryUsage();return{totalDeliveries:this.deliveries.size,memoryUsage:e,indexSizes:{byEndpoint:this.indexByEndpoint.size,byStatus:this.indexByStatus.size,byDate:this.indexByDate.size}}}initializeIndexes(){let e=["pending","success","failed","exhausted"];for(let t of e)this.indexByStatus.set(t,new Set)}addToIndexes(e){if(!this.indexByEndpoint.has(e.endpointId))this.indexByEndpoint.set(e.endpointId,new Set);this.indexByEndpoint.get(e.endpointId).add(e.id);let t=this.indexByStatus.get(e.status);if(t)t.add(e.id);let r=e.createdAt.toISOString().split("T")[0];if(!this.indexByDate.has(r))this.indexByDate.set(r,new Set);this.indexByDate.get(r).add(e.id)}removeFromIndexes(e){let t=this.indexByEndpoint.get(e.endpointId);if(t){if(t.delete(e.id),t.size===0)this.indexByEndpoint.delete(e.endpointId)}let r=this.indexByStatus.get(e.status);if(r)r.delete(e.id);let n=e.createdAt.toISOString().split("T")[0],o=this.indexByDate.get(n);if(o){if(o.delete(e.id),o.size===0)this.indexByDate.delete(n)}}getDeliveryIdsByDateRange(e,t){let r=new Set;for(let[n,o]of this.indexByDate.entries()){let i=new Date(n);if(e&&i<e)continue;if(t&&i>t)continue;o.forEach((s)=>{r.add(s)})}return r}matchesFilter(e,t){if(t.eventId&&e.eventId!==t.eventId)return!1;if(t.httpStatusCode&&t.httpStatusCode.length>0){let r=e.attempts[e.attempts.length-1];if(!r?.httpStatus||!t.httpStatusCode.includes(r.httpStatus))return!1}if(t.hasError!==void 0){let r=e.attempts.some((n)=>n.error);if(t.hasError!==r)return!1}if(t.completedAfter&&(!e.completedAt||e.completedAt<t.completedAfter))return!1;if(t.completedBefore&&(!e.completedAt||e.completedAt>t.completedBefore))return!1;return!0}getFieldValue(e,t){return t.split(".").reduce((r,n)=>r?.[n],e)}estimateMemoryUsage(){let e=0;for(let t of this.deliveries.values())e+=JSON.stringify(t).length*2;return e}async checkMemoryUsage(){if(!this.config.maxMemoryUsage)return;let e=this.estimateMemoryUsage();if(e>this.config.maxMemoryUsage){let t=Array.from(this.deliveries.values()).sort((o,i)=>o.createdAt.getTime()-i.createdAt.getTime()),r=0,n=this.config.maxMemoryUsage*0.8;for(let o of t){if(this.estimateMemoryUsage()<=n)break;this.removeFromIndexes(o),this.deliveries.delete(o.id),r++}if(r>0)this.emit("memoryCleanup",{removedCount:r,previousUsage:e,currentUsage:this.estimateMemoryUsage()})}}startCleanupTask(){this.cleanupInterval=setInterval(()=>{this.cleanupOldDeliveries().then(()=>this.checkMemoryUsage()).catch((e)=>{this.emit("cleanupError",e)})},3600000)}async appendToFile(e){if(!this.config.filePath)return;try{let t=w(this.config.fileAdapter),r=JSON.stringify(e)+`
3
+ `;await t.ensureDirForFile(this.config.filePath),await t.appendFile(this.config.filePath,r)}catch(t){this.emit("appendError",t)}}async loadFromFile(){if(!this.config.filePath)return;try{let r=(await w(this.config.fileAdapter).readFile(this.config.filePath)).trim().split(`
4
+ `).filter((n)=>n.trim());for(let n of r)try{let o=JSON.parse(n),i={...o,createdAt:new Date(o.createdAt),completedAt:o.completedAt?new Date(o.completedAt):void 0,nextRetryAt:o.nextRetryAt?new Date(o.nextRetryAt):void 0,attempts:o.attempts.map((s)=>({...s,timestamp:new Date(s.timestamp)}))};this.deliveries.set(i.id,i),this.addToIndexes(i)}catch(o){this.emit("parseError",{line:n,error:o})}this.emit("dataLoaded",{filePath:this.config.filePath,deliveryCount:this.deliveries.size})}catch(e){if(!T(e))this.emit("loadError",e)}}async saveToFile(){if(!this.config.filePath)return;try{let e=w(this.config.fileAdapter),t=Array.from(this.deliveries.values()).map((r)=>JSON.stringify(r)).join(`
5
+ `);await e.ensureDirForFile(this.config.filePath),await e.writeFile(this.config.filePath,t+`
6
+ `),this.emit("dataSaved",{filePath:this.config.filePath,deliveryCount:this.deliveries.size})}catch(e){throw this.emit("saveError",e),e}}async shutdown(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;if(this.config.type==="file")await this.saveToFile().catch((e)=>{this.emit("saveError",e)});this.emit("shutdown",{deliveryCount:this.deliveries.size})}}function Ve(e){let t=Object.values(e).filter((n)=>typeof n==="number");return Object.entries(e).filter(([n,o])=>t.indexOf(+n)===-1).map(([n,o])=>o)}function Zt(e,t){if(typeof t==="bigint")return t.toString();return t}class Ot{constructor(e){this._getter=e,this._value=void 0}get value(){let e=this._getter;if(e!==void 0)this._value=e(),this._getter=void 0;return this._value}}function Lt(e){return new Ot(e)}function Bt(e){let t=e.startsWith("^")?1:0,r=e.endsWith("$")?e.length-1:e.length;return e.slice(t,r)}function Nt(e,t,r){Object.defineProperty(e,t,{value:r,writable:!0,enumerable:!0,configurable:!0})}var qe="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function be(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Ut(e){if(be(e)===!1)return!1;let t=e.constructor;if(t===void 0)return!0;if(typeof t!=="function")return!0;let r=t.prototype;if(be(r)===!1)return!1;if(Object.prototype.hasOwnProperty.call(r,"isPrototypeOf")===!1)return!1;return!0}var Wt=new Set(["string","number","symbol"]);function jt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function xe(e,t,r){let n=new e._zod.constr(t??e._zod.def);if(!t||r?.parent)n._zod.parent=e;return n}function E(e){let t=e;if(!t)return{};if(typeof t==="string")return{error:()=>t};if(t?.message!==void 0){if(t?.error!==void 0)throw Error("Cannot specify both `message` and `error` params");t.error=t.message}if(delete t.message,typeof t.error==="string")return{...t,error:()=>t.error};return t}function Kt(e){return Object.keys(e).filter((t)=>e[t]._zod.optin!==void 0&&e[t]._zod.optout==="optional")}function Z(e,t=0){if(e.aborted===!0)return!0;for(let r=t;r<e.issues.length;r++)if(e.issues[r]?.continue!==!0)return!0;return!1}function Ht(e,t=0){if(e.aborted===!0)return!0;for(let r=t;r<e.issues.length;r++)if(e.issues[r]?.continue===!1)return!0;return!1}function K(e,t){return t.map((r)=>{var n;return(n=r).path??(n.path=[]),r.path.unshift(e),r})}function re(e){return typeof e==="string"?e:e?.message}function Ge(e,t,r){var n;for(let o=t;o<e.length;o++)(n=e[o]).schema??(n.schema=r)}function O(e,t,r){var n;let o=e.inst?._zod?.traits;if(o?.has("$ZodType"))if(o.has("$ZodCheck"))(n=e).schema??(n.schema=e.inst);else e.schema=e.inst;let i=e.schema!==e.inst?e.schema?._zod.def?.error:void 0,s=e.message?e.message:re(e.inst?._zod.def?.error?.(e))??re(i?.(e))??re(t?.error?.(e))??re(r.customError?.(e))??re(r.localeError?.(e))??"Invalid input",a={};for(let l of Object.keys(e)){if(l==="inst"||l==="schema"||l==="continue"||l==="input"||l==="__proto__")continue;a[l]=e[l]}if(a.path??(a.path=[]),a.message=s,t?.reportInput)a.input=e.input;return a}function Jt(e,t){for(let r in t){let n=Object.getOwnPropertyDescriptor(t,r);if(n.get)Object.defineProperty(e,r,{...n,enumerable:!1});else Sn(e,r,n.value)}}function j(e,t,r,n=!0){return Object.defineProperty(e,t,{configurable:!0,writable:!0,enumerable:n,value:r}),r}function Vt(e,t,r){return j(e,t,r,!1)}function Sn(e,t,r){Object.defineProperty(e,t,{configurable:!0,get(){return this==null?r:j(this,t,r.bind(this))},set(n){j(this,t,n)}})}function $n(e,t){let r=Object.getPrototypeOf(e);return t in r?void 0:r}var Je,F=!1,Rn={configurable:!0,get(){F=!0;return}};function R(e,t,r){let n=Object.getPrototypeOf(e._zod);if(t in n&&Je!==e._zod){Je=void 0;return}Je=e._zod,Object.defineProperty(n,t,{configurable:!0,get(){Object.defineProperty(this,t,Rn);let o=F;F=!1;try{let i=r(this);if(F)delete this[t];else Object.defineProperty(this,t,{configurable:!0,writable:!0,value:i});return F=F||o,i}catch(i){throw delete this[t],F=F||o,i}},set(o){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:o})}})}function qt(e,t,r,n){let o=$n(e,t);if(!o)return;Object.defineProperty(o,t,{configurable:!0,get(){let i={configurable:!0,writable:!0,enumerable:n,value:void 0};return Object.defineProperty(this,t,i),i.value=r(this),Object.defineProperty(this,t,i),i.value},set(i){Object.defineProperty(this,t,{configurable:!0,writable:!0,enumerable:n,value:i})}})}var Gt;var Ye={value:void 0,enumerable:!1},Yt="captureStackTrace"in Error?Error:null;function zn(e){let t=Yt;if(t){let r=t.stackTraceLimit;if(typeof r==="number"){try{t.stackTraceLimit=0}catch{return Yt=null,new e}try{return new e}finally{t.stackTraceLimit=r}}}return new e}function m(e,t,r,n){let o={};function i(d){this.def=d,this.constr=p,this.traits=new Set}i.prototype=o;let s=r,a=s&&new WeakSet;function l(d,f){if(!d._zod){Ye.value=new i(f);try{Object.defineProperty(d,"_zod",Ye)}finally{Ye.value=void 0}}else if(d._zod.traits.has(e))return;if(d._zod.traits.add(e),t(d,f),a){let g=Object.getPrototypeOf(d),C=d._zod.constr.prototype,y=g;while(y&&y!==C)y=Object.getPrototypeOf(y);let G=y??g;if(!a.has(G))a.add(G),Jt(G,s)}let h=p.prototype;for(let g in h){if(!Object.prototype.hasOwnProperty.call(h,g))continue;if(!(g in d))d[g]=h[g].bind(d)}}let c=n?.Parent??Object;class u extends c{}Object.defineProperty(u,"name",{value:e});function p(d){let f=n?.Parent?zn(u):this;l(f,d);let h=f._zod.deferred;if(h){for(let C of h)C();f._zod.deferred=void 0}let g=globalThis.__zod_globalConfig?.postProcessor;if(g)g(f);return f}return Object.defineProperty(p,"init",{value:l}),Object.defineProperty(p,Symbol.hasInstance,{value:(d)=>{if(n?.Parent&&d instanceof n.Parent)return!0;return d?._zod?.traits?.has(e)}}),Object.defineProperty(p,"name",{value:e}),p}class I extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class Xe extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`);this.name="ZodEncodeError"}}(Gt=globalThis).__zod_globalConfig??(Gt.__zod_globalConfig={});var H=globalThis.__zod_globalConfig;function L(e){if(e)Object.assign(H,e);return H}function In(){let e=this._zod;return e.message??(e.message=JSON.stringify(e.def,Zt,2)),e.message}function Dn(e){this._zod.message=e}var Mn={get:In,set:Dn,enumerable:!0,configurable:!0},et={value:void 0,enumerable:!1},Xt=new WeakSet([Object.prototype,Error.prototype]),Qt=(e,t)=>{e.name="$ZodError",et.value=t,Object.defineProperty(e,"issues",et),et.value=void 0,Object.defineProperty(e,"message",Mn);let r=Object.getPrototypeOf(e);if(!Xt.has(r))Xt.add(r),Object.defineProperty(r,"toString",{configurable:!0,enumerable:!1,get(){let n=()=>this.message;return Object.defineProperty(this,"toString",{value:n,configurable:!0,writable:!0}),n},set(n){Object.defineProperty(this,"toString",{value:n,configurable:!0,writable:!0})}})},si=m("$ZodError",Qt),ne=m("$ZodError",Qt,void 0,{Parent:Error});var Fn=(e)=>{let t=(r,n,o,i)=>{let s=o?{...o,async:!1}:{async:!1},a=r._zod.run({value:n,issues:[]},s);if(a instanceof Promise)throw new I;if(a.issues.length){let l=new(i?.Err??e)(a.issues.map((c)=>O(c,s,L())));throw qe(l,i?.callee??t),l}return a.value};return t},tt=Fn(ne),Zn=(e)=>{let t=async(r,n,o,i)=>{let s=o?{...o,async:!0}:{async:!0},a=r._zod.run({value:n,issues:[]},s);if(a instanceof Promise)a=await a;if(a.issues.length){let l=new(i?.Err??e)(a.issues.map((c)=>O(c,s,L())));throw qe(l,i?.callee??t),l}return a.value};return t},rt=Zn(ne),On=(e)=>(t,r,n)=>{let o=n?{...n,async:!1}:{async:!1},i=t._zod.run({value:r,issues:[]},o);if(i instanceof Promise)throw new I;return i.issues.length?er(e,i.issues,o):{success:!0,data:i.value}},nt=On(ne);function er(e,t,r){let n;return{success:!1,get error(){if(!n)n=new e(t.map((o)=>O(o,r,L()))),t=void 0,r=void 0;return n},set error(o){n=o,t=void 0,r=void 0}}}var Ln=(e)=>async(t,r,n)=>{let o=n?{...n,async:!0}:{async:!0},i=t._zod.run({value:r,issues:[]},o);if(i instanceof Promise)i=await i;return i.issues.length?er(e,i.issues,o):{success:!0,data:i.value}},ot=Ln(ne);var tr=/^https?$/;var rr=/^[\s\S]{0,}$/;var it=/^-?\d+(?:\.\d+)?$/,nr=/^(?:true|false)$/i;var Q=m("$ZodCheck",(e,t)=>{var r;e._zod??(e._zod={}),e._zod.def=t,(r=e._zod).onattach??(r.onattach=[])});var ve={number:"number",bigint:"bigint",object:"date"},ir=m("$ZodCheckLessThan",(e,t)=>{Q.init(e,t);let r=ve[typeof t.value];e._zod.check=(n)=>{if(t.inclusive?n.value<=t.value:n.value<t.value)return;n.issues.push({origin:ve[typeof n.value]??r,code:"too_big",maximum:typeof t.value==="object"?t.value.getTime():t.value,input:n.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),sr=m("$ZodCheckGreaterThan",(e,t)=>{Q.init(e,t);let r=ve[typeof t.value];e._zod.check=(n)=>{if(t.inclusive?n.value>=t.value:n.value>t.value)return;n.issues.push({origin:ve[typeof n.value]??r,code:"too_small",minimum:typeof t.value==="object"?t.value.getTime():t.value,input:n.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}});var ar=m("$ZodCheckStringFormat",(e,t)=>{var r,n;if(Q.init(e,t),t.pattern)(r=e._zod).check??(r.check=(o)=>{if(t.pattern.lastIndex=0,t.pattern.test(o.value))return;o.issues.push({origin:"string",code:"invalid_format",format:t.format,input:o.value,...t.pattern?{pattern:t.pattern.toString()}:{},inst:e,continue:!t.abort})});else(n=e._zod).check??(n.check=()=>{})});var ur={major:4,minor:6,patch:5};var k=m("$ZodType",(e,t)=>{var r;e??(e={}),e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=ur;let n=e._zod.def.checks,o=e._zod.traits.has("$ZodCheck")?[e,...n??[]]:n?.length?[...n]:[];for(let i of o)for(let s of i._zod.onattach)s(e);if(o.length===0)(r=e._zod).deferred??(r.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{let i=(a,l,c)=>{if(a.memo)return a;let u=Z(a),p;for(let d of l){if(d._zod.def.when){if(Ht(a))continue;if(!d._zod.def.when(a))continue}else if(u)continue;let f=a.issues.length,h=d._zod.check(a);if(h instanceof Promise&&c?.async===!1)throw new I;if(p||h instanceof Promise)p=(p??Promise.resolve()).then(async()=>{if(await h,a.issues.length===f)return;if(Ge(a.issues,f,e),!u)u=Z(a,f)});else{if(a.issues.length===f)continue;if(Ge(a.issues,f,e),!u)u=Z(a,f)}}if(p)return p.then(()=>a);return a},s=(a,l,c)=>{if(Z(a))return a.aborted=!0,a;let u=i(l,o,c);if(u instanceof Promise){if(c.async===!1)throw new I;return u.then((p)=>e._zod.parse(p,c))}return e._zod.parse(u,c)};e._zod.run=(a,l)=>{if(l.skipChecks)return e._zod.parse(a,l);if(l.direction==="backward"){let u=e._zod.parse({value:a.value,issues:[]},{...l,skipChecks:!0});if(u instanceof Promise)return u.then((p)=>s(p,a,l));return s(u,a,l)}let c=e._zod.parse(a,l);if(c instanceof Promise){if(l.async===!1)throw new I;return c.then((u)=>i(u,o,l))}return i(c,o,l)}}},{get "~standard"(){return Vt(this,"~standard",Un(this))},set "~standard"(e){j(this,"~standard",e)}}),fr=(e,t)=>e.issues.length?{issues:e.issues.map((r)=>O(r,t,L()))}:{value:e.value};async function Nn(e,t){let r={async:!0};return fr(await e._zod.run({value:t,issues:[]},r),r)}function Un(e){return{validate:(t)=>{let r={async:!1};try{let n=e._zod.run({value:t,issues:[]},r);if(!(n instanceof Promise))return fr(n,r)}catch(n){}return Nn(e,t)},vendor:"zod",version:1}}var st=m("$ZodString",(e,t)=>{k.init(e,t),e._zod.pattern=t.pattern??rr,e._zod.parse=(r,n)=>{if(t.coerce)try{r.value=String(r.value)}catch(o){}if(typeof r.value==="string")return r;return r.issues.push({expected:"string",code:"invalid_type",input:r.value,inst:e}),r}}),at=m("$ZodStringFormat",(e,t)=>{ar.init(e,t),st.init(e,t)});var hr=1,Ee=2;function Wn(e){try{if(typeof URL<"u"&&typeof URL.canParse==="function")return URL.canParse(e);return new URL(e),!0}catch{return!1}}function jn(e,t){if(!("normalize"in t)&&!("hostname"in t)&&!("protocol"in t))return Wn(e)||Ee;return Kn(e,t)}function Kn(e,t){if(!t.normalize&&t.protocol?.source===tr.source&&!/^https?:\/\//i.test(e))return hr;try{if(typeof URL<"u"){let r=URL;if(typeof r.parse==="function")return r.parse(e)??Ee}return new URL(e)}catch{return Ee}}var Hn=/[\t\n\r]/g;function lr(e){return e.replace(Hn,"")}function Jn(e,t){return t.lastIndex=0,t.test(e.hostname)}function Vn(e,t){return t.lastIndex=0,t.test(e.protocol.endsWith(":")?e.protocol.slice(0,-1):e.protocol)}var mr=m("$ZodURL",(e,t)=>{at.init(e,t),e._zod.check=(r)=>{try{let n=r.value.trim(),o=jn(n,t);if(o===hr){r.issues.push({code:"invalid_format",format:"url",note:"Invalid URL format",input:r.value,inst:e,continue:!t.abort});return}if(o===Ee){r.issues.push({code:"invalid_format",format:"url",input:r.value,inst:e,continue:!t.abort});return}if(o===!0){r.value=lr(n);return}if(t.hostname&&!Jn(o,t.hostname))r.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:t.hostname.source,input:r.value,inst:e,continue:!t.abort});if(t.protocol&&!Vn(o,t.protocol))r.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:t.protocol.source,input:r.value,inst:e,continue:!t.abort});r.value=t.normalize?o.href:lr(n);return}catch(n){r.issues.push({code:"invalid_format",format:"url",input:r.value,inst:e,continue:!t.abort})}}});var gr=m("$ZodNumber",(e,t)=>{k.init(e,t),e._zod.pattern=it,e._zod.parse=(r,n)=>{if(t.coerce)try{r.value=Number(r.value)}catch(s){}let o=r.value;if(typeof o==="number"&&!Number.isNaN(o)&&Number.isFinite(o))return r;let i=typeof o==="number"?Number.isNaN(o)?"NaN":!Number.isFinite(o)?String(o):void 0:void 0;return r.issues.push({expected:"number",code:"invalid_type",input:o,inst:e,...i?{received:i}:{}}),r}});var yr=m("$ZodBoolean",(e,t)=>{k.init(e,t),e._zod.pattern=nr,e._zod.parse=(r,n)=>{if(t.coerce)try{r.value=Boolean(r.value)}catch(i){}let o=r.value;if(typeof o==="boolean")return r;return r.issues.push({expected:"boolean",code:"invalid_type",input:o,inst:e}),r}});var br=m("$ZodAny",(e,t)=>{k.init(e,t),e._zod.parse=(r)=>r});var xr=m("$ZodDate",(e,t)=>{k.init(e,t),e._zod.parse=(r,n)=>{if(t.coerce)try{r.value=new Date(r.value)}catch(a){}let o=r.value,i=o instanceof Date;if(i&&!Number.isNaN(o.getTime()))return r;return r.issues.push({expected:"date",code:"invalid_type",input:o,...i?{received:"Invalid Date"}:{},inst:e}),r}});function dr(e,t,r){if(e.issues.length)t.issues.push(...K(r,e.issues));t.value[r]=e.value}var vr=m("$ZodArray",(e,t)=>{k.init(e,t);let r=H.memoizer;r?.attach(e),e._zod.parse=(n,o)=>{let i=n.value;if(!Array.isArray(i))return n.issues.push({expected:"array",code:"invalid_type",input:i,inst:e}),n;n.value=r?r.alloc(e,n,Array(i.length),o):Array(i.length);let s=[],a=o?.abortEarly;for(let l=0;l<i.length;l++){let c=i[l],u=t.element._zod.run({value:c,issues:[]},o);if(u instanceof Promise)s.push(u.then((p)=>dr(p,n,l)));else if(dr(u,n,l),a&&u.issues.length!==0&&Z(u))break}if(s.length)return Promise.all(s).then(()=>n);return n}});function we(e,t,r,n,o,i){let s=r in n,a=i==="optional";if(!s&&a&&o==="optional")return;if(e.issues.length){if(o!==void 0&&a&&!s)return;t.issues.push(...K(r,e.issues))}if(!s&&o===void 0){if(!e.issues.length)t.issues.push({code:"invalid_type",expected:"nonoptional",input:void 0,path:[r]});return}if(e.value===void 0){if(s||o==="defaulted"&&!a)t.value[r]=void 0}else t.value[r]=e.value}var qn=[];function Gn(e){let t=Object.keys(e.shape),r=Object.getOwnPropertySymbols(e.shape),n=r.length?r:qn,o=n.length?[...t,...n]:t;for(let s of o)if(!e.shape?.[s]?._zod?.traits?.has("$ZodType"))throw Error(`Invalid element at key "${String(s)}": expected a Zod schema`);let i=Kt(e.shape);return{...e,allKeys:o,symbolKeys:n,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(i)}}function Yn(e,t,r,n,o,i,s){let a=[],l=o.keySet,c=o.catchall._zod,u=c.def.type,{optin:p,optout:d}=c,f=0;for(let h in t){if(s&&r.issues.length!==f){if(Z(r,f))break;f=r.issues.length}if(l.has(h))continue;if(h==="__proto__"){if(u==="never")a.push(h);continue}if(u==="never"){a.push(h);continue}let g=c.run({value:t[h],issues:[]},n);if(g instanceof Promise)e.push(g.then((C)=>we(C,r,h,t,p,d)));else we(g,r,h,t,p,d)}if(a.length)r.issues.push({code:"unrecognized_keys",keys:a,input:t,inst:i,continue:!0});if(!e.length)return r;return Promise.all(e).then(()=>r)}var _r=m("$ZodObject",(e,t)=>{k.init(e,t);let r=Object.getOwnPropertyDescriptor(t,"shape"),n=r?.get?r.get.raw:t.shape??{};if(n){let c=()=>{let u={...n};return Object.defineProperty(t,"shape",{value:u}),c.raw=u,u};c.raw=n,Object.defineProperty(t,"shape",{get:c})}let o=Lt(()=>Gn(t));R(e,"propValues",(c)=>{let u=c.def.shape,p={};for(let d in u){let f=u[d]._zod;if(f.values){if(!Object.prototype.hasOwnProperty.call(p,d))Nt(p,d,new Set);for(let h of f.values)p[d].add(h);if(f.optin!==void 0)p[d].add(void 0)}}return p});let i=be,s=t.catchall,a,l=H.memoizer;l?.attach(e),e._zod.parse=(c,u)=>{a??(a=o.value);let p=c.value;if(!i(p))return c.issues.push({expected:"object",code:"invalid_type",input:p,inst:e}),c;c.value=l?l.alloc(e,c,{},u):{};let d=[],f=a.shape,h=u?.abortEarly,g=c.issues.length;for(let C of a.allKeys){if(h&&c.issues.length!==g){if(Z(c,g))break;g=c.issues.length}if(C==="__proto__")continue;let y=f[C],G=y._zod.optin,Pt=y._zod.optout,v=y._zod.run({value:p[C],issues:[]},u);if(v instanceof Promise)d.push(v.then((tn)=>we(tn,c,C,p,G,Pt)));else we(v,c,C,p,G,Pt)}if(!s)return d.length?Promise.all(d).then(()=>c):c;return Yn(d,p,c,u,o.value,e,h===!0)}});var Er=m("$ZodRecord",(e,t)=>{k.init(e,t);let r=H.memoizer;r?.attach(e),e._zod.parse=(n,o)=>{let i=n.value;if(!Ut(i))return n.issues.push({expected:"record",code:"invalid_type",input:i,inst:e}),n;let s=[],a=t.keyType._zod.values;if(a&&!t.partial){n.value=r?r.alloc(e,n,{},o):{};let l=new Set;for(let u of a)if(typeof u==="string"||typeof u==="number"||typeof u==="symbol"){if(l.add(typeof u==="number"?u.toString():u),u==="__proto__")continue;let p=t.keyType._zod.run({value:u,issues:[]},o);if(p instanceof Promise)throw Error("Async schemas not supported in object keys currently");if(p.issues.length){n.issues.push({code:"invalid_key",origin:"record",issues:p.issues.map((h)=>O(h,o,L())),input:u,path:[u],inst:e});continue}let d=p.value;if(d==="__proto__")continue;let f=t.valueType._zod.run({value:i[u],issues:[]},o);if(f instanceof Promise)s.push(f.then((h)=>{if(h.issues.length)n.issues.push(...K(u,h.issues));n.value[d]=h.value}));else{if(f.issues.length)n.issues.push(...K(u,f.issues));n.value[d]=f.value}}let c;for(let u in i)if(!l.has(u))if(t.mode==="loose"){if(u==="__proto__")continue;n.value[u]=i[u]}else c=c??[],c.push(u);if(c&&c.length>0)n.issues.push({code:"unrecognized_keys",input:i,inst:e,keys:c,continue:!0})}else{n.value=r?r.alloc(e,n,{},o):{};let l;for(let c of Reflect.ownKeys(i)){if(c==="__proto__")continue;if(!Object.prototype.propertyIsEnumerable.call(i,c))continue;let u=t.keyType._zod.run({value:c,issues:[]},o);if(u instanceof Promise)throw Error("Async schemas not supported in object keys currently");if(typeof c==="string"&&it.test(c)&&u.issues.length){let h=t.keyType._zod.run({value:Number(c),issues:[]},o);if(h instanceof Promise)throw Error("Async schemas not supported in object keys currently");if(h.issues.length===0)u=h}if(u.issues.length){if(t.mode==="loose")n.value[c]=i[c];else if(a)l=l??[],l.push(c);else n.issues.push({code:"invalid_key",origin:"record",issues:u.issues.map((h)=>O(h,o,L())),input:c,path:[c],inst:e});continue}let d=u.value;if(d==="__proto__")continue;let f=t.valueType._zod.run({value:i[c],issues:[]},o);if(f instanceof Promise)s.push(f.then((h)=>{if(h.issues.length)n.issues.push(...K(c,h.issues));n.value[d]=h.value}));else{if(f.issues.length)n.issues.push(...K(c,f.issues));n.value[d]=f.value}}if(l&&l.length>0)n.issues.push({code:"unrecognized_keys",input:i,inst:e,keys:l,continue:!0})}if(s.length)return Promise.all(s).then(()=>n);return n}});var wr=m("$ZodEnum",(e,t)=>{k.init(e,t);let r=Ve(t.entries),n=new Set(r);e._zod.values=n,R(e,"pattern",(o)=>{let i=Ve(o.def.entries).filter((s)=>Wt.has(typeof s));return new RegExp(i.length?`^(${i.map((s)=>jt(s.toString())).join("|")})$`:"^[^\\s\\S]$")}),e._zod.parse=(o,i)=>{let s=o.value;if(n.has(s))return o;return o.issues.push({code:"invalid_value",values:r,input:s,inst:e}),o}});var kr=m("$ZodTransform",(e,t)=>{k.init(e,t),e._zod.optin="optional",H.memoizer?.guard(e),e._zod.parse=(r,n)=>{if(n.direction==="backward")throw new Xe(e.constructor.name);let o=t.transform(r.value,r);if(n.async)return(o instanceof Promise?o:Promise.resolve(o)).then((s)=>(r.value=s,r));if(o instanceof Promise)throw new I;return r.value=o,r}});function pr(e,t){return e.value=t.issues.length?void 0:t.value,e}var Cr=m("$ZodOptional",(e,t)=>{k.init(e,t),R(e,"optin",(r)=>r.def.innerType._zod.optin==="defaulted"?"defaulted":"optional"),e._zod.optout="optional",R(e,"values",(r)=>{let n=r.def.innerType._zod.values;return n?new Set([...n,void 0]):void 0}),R(e,"pattern",(r)=>{let n=r.def.innerType._zod.pattern;return n?new RegExp(`^(${Bt(n.source)})?$`):void 0}),e._zod.parse=(r,n)=>{if(r.value===void 0){if(t.innerType._zod.optin!=="defaulted")return r;let o=t.innerType._zod.run({value:r.value,issues:[]},n);if(o instanceof Promise)return o.then((i)=>pr(r,i));return pr(r,o)}return t.innerType._zod.run(r,n)}});var Ar=m("$ZodPipe",(e,t)=>{k.init(e,t),R(e,"values",(r)=>r.def.in._zod.values),R(e,"optin",(r)=>r.def.in._zod.optin),R(e,"optout",(r)=>r.def.out._zod.optout),R(e,"propValues",(r)=>r.def.in._zod.propValues),e._zod.parse=(r,n)=>{if(n.direction==="backward"){let i=t.out._zod.run(r,n);if(i instanceof Promise)return i.then((s)=>_e(s,t.in,n));return _e(i,t.in,n)}let o=t.in._zod.run(r,n);if(o instanceof Promise)return o.then((i)=>_e(i,t.out,n));return _e(o,t.out,n)}});function _e(e,t,r){if(e.issues.some((n)=>n.code!=="unrecognized_keys"))return e.aborted=!0,e;return t._zod.run({value:e.value,issues:e.issues},r)}function Pr(e){if(e.checks)e.checks=[...e.checks];return e}function Sr(e,t){return new e(Pr({type:"string",...E(t)}))}function $r(e,t){return new e({type:"string",format:"url",check:"string_format",abort:!1,...E(t)})}function Rr(e,t){return new e(Pr({type:"number",checks:[],...E(t)}))}function zr(e,t){return new e({type:"boolean",...E(t)})}function Ir(e){return new e({type:"any"})}function Dr(e,t){return new e({type:"date",...E(t)})}function ke(e,t){return new ir({check:"less_than",...E(t),value:e,inclusive:!0})}function oe(e,t){return new sr({check:"greater_than",...E(t),value:e,inclusive:!0})}var P=m("ZodMiniType",(e,t)=>{if(!e._zod)throw Error("Uninitialized schema in ZodMiniType.");k.init(e,t),e.def=t,e.type=t.type},{get with(){return this.check},set with(e){j(this,"with",e)},parse(e,t){return tt(this,e,t,{callee:this.parse})},parseAsync(e,t){return rt(this,e,t,{callee:this.parseAsync})},safeParse(e,t){return nt(this,e,t)},safeParseAsync(e,t){return ot(this,e,t)},check(...e){let t=this.def;return this.clone({...t,checks:[...t.checks??[],...e.map((r)=>typeof r==="function"?{_zod:{check:r,def:{check:"custom"},onattach:[]}}:r)]},{parent:!0})},clone(e,t){return xe(this,e,t)},brand(){return this},register(e,t){return e.add(this,t),this},apply(e,...t){return t.length===0?e(this):e(this,...t)}}),Tr=m("ZodMiniString",(e,t)=>{st.init(e,t),P.init(e,t)});function b(e){return Sr(Tr,e)}var eo=m("ZodMiniStringFormat",(e,t)=>{at.init(e,t),Tr.init(e,t)});var to=m("ZodMiniURL",(e,t)=>{mr.init(e,t),eo.init(e,t)});function Fr(e){return $r(to,e)}var ro=m("ZodMiniNumber",(e,t)=>{gr.init(e,t),P.init(e,t)});function J(e){return Rr(ro,e)}var no=m("ZodMiniBoolean",(e,t)=>{yr.init(e,t),P.init(e,t)});function oo(e){return zr(no,e)}var io=m("ZodMiniAny",(e,t)=>{br.init(e,t),P.init(e,t)});function so(){return Ir(io)}var ao=m("ZodMiniDate",(e,t)=>{xr.init(e,t),P.init(e,t)});function B(e){return Dr(ao,e)}var co=m("ZodMiniArray",(e,t)=>{vr.init(e,t),P.init(e,t)});function ie(e,t){return new co({type:"array",element:e,...E(t)})}var uo=m("ZodMiniObject",(e,t)=>{_r.init(e,t),P.init(e,t),qt(e,"shape",(r)=>r._zod.def.shape,!1)});function V(e,t){let r={type:"object",shape:e??{},...E(t)};return new uo(r)}var Mr=m("ZodMiniRecord",(e,t)=>{Er.init(e,t),P.init(e,t)});function ct(e,t,r){if(!t||!t._zod)return new Mr({type:"record",keyType:b(),valueType:e,...E(t)});return new Mr({type:"record",keyType:e,valueType:t,...E(r)})}var Zr=m("ZodMiniEnum",(e,t)=>{wr.init(e,t),P.init(e,t),e.options=[...e._zod.values]});function ut(e,t){let r=Array.isArray(e)?Object.fromEntries(e.map((n)=>[n,n])):e;return new Zr({type:"enum",entries:r,...E(t)})}function lt(e,t){return new Zr({type:"enum",entries:e,...E(t)})}var lo=m("ZodMiniTransform",(e,t)=>{kr.init(e,t),P.init(e,t)});function po(e){return new lo({type:"transform",transform:e})}var fo=m("ZodMiniOptional",(e,t)=>{Cr.init(e,t),P.init(e,t)});function x(e){return new fo({type:"optional",innerType:e})}var ho=m("ZodMiniPipe",(e,t)=>{Ar.init(e,t),P.init(e,t)});function mo(e,t){return new ho({type:"pipe",in:e,out:t})}var D;((v)=>{v.MESSAGE_SENT="message.sent";v.MESSAGE_DELIVERED="message.delivered";v.MESSAGE_FAILED="message.failed";v.MESSAGE_CLICKED="message.clicked";v.MESSAGE_READ="message.read";v.TEMPLATE_CREATED="template.created";v.TEMPLATE_APPROVED="template.approved";v.TEMPLATE_REJECTED="template.rejected";v.TEMPLATE_UPDATED="template.updated";v.TEMPLATE_DELETED="template.deleted";v.CHANNEL_CREATED="channel.created";v.CHANNEL_VERIFIED="channel.verified";v.SENDER_NUMBER_ADDED="sender_number.added";v.SENDER_NUMBER_VERIFIED="sender_number.verified";v.QUOTA_WARNING="system.quota_warning";v.QUOTA_EXCEEDED="system.quota_exceeded";v.PROVIDER_ERROR="system.provider_error";v.SYSTEM_MAINTENANCE="system.maintenance";v.ANOMALY_DETECTED="analytics.anomaly_detected";v.THRESHOLD_EXCEEDED="analytics.threshold_exceeded"})(D||={});var yo=V({providerId:x(b()),channelId:x(b()),templateId:x(b()),messageId:x(b()),userId:x(b()),organizationId:x(b()),correlationId:x(b()),retryCount:x(J())}),bo=V({maxRetries:J().check(oe(0),ke(10)),retryDelayMs:J().check(oe(1000)),backoffMultiplier:J().check(oe(1),ke(5))}),xo=V({providerId:x(ie(b())),channelId:x(ie(b())),templateId:x(ie(b()))}),vo=V({attemptNumber:J(),timestamp:B(),httpStatus:x(J()),responseBody:x(b()),responseHeaders:x(ct(b(),b())),error:x(b()),latencyMs:J()}),su=V({id:b(),type:lt(D),timestamp:mo(po((e)=>{if(e instanceof Date)return e;if(typeof e==="string"||typeof e==="number")return new Date(e);return e}),B()),data:so(),metadata:yo,version:b()}),au=V({id:b(),url:Fr(),name:x(b()),description:x(b()),active:oo(),events:ie(lt(D)),headers:x(ct(b(),b())),secret:x(b()),retryConfig:x(bo),filters:x(xo),createdAt:B(),updatedAt:B(),lastTriggeredAt:x(B()),status:ut(["active","inactive","error","suspended"])}),cu=V({id:b(),endpointId:b(),eventId:b(),eventType:x(lt(D)),url:Fr(),httpMethod:ut(["POST","PUT","PATCH"]),headers:ct(b(),b()),payload:b(),attempts:ie(vo),status:ut(["pending","success","failed","exhausted"]),createdAt:B(),completedAt:x(B()),nextRetryAt:x(B())});class dt extends A{config;endpoints=new Map;indexByUrl=new Map;indexByEvent=new Map;indexByStatus=new Map;defaultConfig={type:"memory",retentionDays:90};constructor(e={}){super();if(this.config={...this.defaultConfig,...e},this.initializeIndexes(),this.config.type==="file"&&this.config.filePath)this.loadFromFile().catch((t)=>{this.emit("loadError",t)})}async addEndpoint(e){if(this.indexByUrl.has(e.url)){if(this.indexByUrl.get(e.url)!==e.id)throw Error(`Endpoint with URL ${e.url} already exists with different ID`)}let t=this.endpoints.get(e.id);if(t)this.removeFromIndexes(t);if(this.endpoints.set(e.id,e),this.addToIndexes(e),this.config.type==="file")await this.saveToFile();this.emit("endpointAdded",{endpointId:e.id,url:e.url})}async updateEndpoint(e,t){let r=this.endpoints.get(e);if(!r)throw Error(`Endpoint ${e} not found`);if(t.url&&t.url!==r.url){if(this.indexByUrl.has(t.url)){if(this.indexByUrl.get(t.url)!==e)throw Error(`Endpoint with URL ${t.url} already exists`)}}this.removeFromIndexes(r);let n={...r,...t,updatedAt:new Date};if(this.endpoints.set(e,n),this.addToIndexes(n),this.config.type==="file")await this.saveToFile();return this.emit("endpointUpdated",{endpointId:e,changes:Object.keys(t),oldUrl:r.url,newUrl:n.url}),n}async removeEndpoint(e){let t=this.endpoints.get(e);if(!t)return!1;if(this.removeFromIndexes(t),this.endpoints.delete(e),this.config.type==="file")await this.saveToFile();return this.emit("endpointRemoved",{endpointId:e,url:t.url}),!0}async getEndpoint(e){return this.endpoints.get(e)||null}async getEndpointByUrl(e){let t=this.indexByUrl.get(e);return t?this.endpoints.get(t)||null:null}async searchEndpoints(e={},t={page:1,limit:100}){let r=null;if(e.status){let c=this.indexByStatus.get(e.status);r=c?new Set(c):new Set}if(e.events&&e.events.length>0){let c=new Set;for(let u of e.events){let p=this.indexByEvent.get(u);if(p)p.forEach((d)=>{c.add(d)})}if(r)r=new Set(Array.from(r).filter((u)=>c.has(u)));else r=c}if(!r)r=new Set(this.endpoints.keys());let n=Array.from(r).map((c)=>this.endpoints.get(c)).filter((c)=>this.matchesFilter(c,e));if(t.sortBy)n.sort((c,u)=>{let p=this.getFieldValue(c,t.sortBy),d=this.getFieldValue(u,t.sortBy),f=0;if(p<d)f=-1;else if(p>d)f=1;return t.sortOrder==="desc"?-f:f});let o=n.length,i=Math.ceil(o/t.limit),s=(t.page-1)*t.limit,a=s+t.limit;return{items:n.slice(s,a),totalCount:o,page:t.page,totalPages:i,hasNext:t.page<i,hasPrevious:t.page>1}}async getActiveEndpointsForEvent(e){let t=this.indexByEvent.get(e);if(!t)return[];return Array.from(t).map((r)=>this.endpoints.get(r)).filter((r)=>r.status==="active")}getStats(){let e=this.endpoints.size,t=this.indexByStatus.get("active")?.size||0,r=this.indexByStatus.get("inactive")?.size||0,n=this.indexByStatus.get("error")?.size||0,o=this.indexByStatus.get("suspended")?.size||0,i={};for(let[s,a]of this.indexByEvent.entries())i[s]=a.size;return{totalEndpoints:e,activeEndpoints:t,inactiveEndpoints:r,errorEndpoints:n,suspendedEndpoints:o,eventSubscriptions:i}}async cleanupExpiredEndpoints(){if(!this.config.retentionDays)return 0;let e=new Date;e.setDate(e.getDate()-this.config.retentionDays);let t=Array.from(this.endpoints.values()).filter((r)=>r.status==="inactive"&&(!r.lastTriggeredAt||r.lastTriggeredAt<e));for(let r of t)await this.removeEndpoint(r.id);if(t.length>0)this.emit("expiredEndpointsCleanup",{removedCount:t.length,cutoffDate:e});return t.length}initializeIndexes(){let e=Object.values(D);for(let r of e)this.indexByEvent.set(r,new Set);let t=["active","inactive","error","suspended"];for(let r of t)this.indexByStatus.set(r,new Set)}addToIndexes(e){this.indexByUrl.set(e.url,e.id);let t=this.indexByStatus.get(e.status);if(t)t.add(e.id);for(let r of e.events){let n=this.indexByEvent.get(r);if(n)n.add(e.id)}}removeFromIndexes(e){this.indexByUrl.delete(e.url);let t=this.indexByStatus.get(e.status);if(t)t.delete(e.id);for(let r of e.events){let n=this.indexByEvent.get(r);if(n)n.delete(e.id)}}matchesFilter(e,t){if(t.providerId&&t.providerId.length>0){if(!t.providerId.some((n)=>e.filters?.providerId?.includes(n)))return!1}if(t.channelId&&t.channelId.length>0){if(!t.channelId.some((n)=>e.filters?.channelId?.includes(n)))return!1}if(t.createdAfter&&e.createdAt<t.createdAfter)return!1;if(t.createdBefore&&e.createdAt>t.createdBefore)return!1;if(t.lastTriggeredAfter&&(!e.lastTriggeredAt||e.lastTriggeredAt<t.lastTriggeredAfter))return!1;if(t.lastTriggeredBefore&&(!e.lastTriggeredAt||e.lastTriggeredAt>t.lastTriggeredBefore))return!1;return!0}getFieldValue(e,t){return t.split(".").reduce((r,n)=>r?.[n],e)}async loadFromFile(){if(!this.config.filePath)return;try{let t=await w(this.config.fileAdapter).readFile(this.config.filePath),r=JSON.parse(t);for(let n of r.endpoints||[]){let o={...n,createdAt:new Date(n.createdAt),updatedAt:new Date(n.updatedAt),lastTriggeredAt:n.lastTriggeredAt?new Date(n.lastTriggeredAt):void 0};this.endpoints.set(o.id,o),this.addToIndexes(o)}this.emit("dataLoaded",{filePath:this.config.filePath,endpointCount:this.endpoints.size})}catch(e){if(!T(e))this.emit("loadError",e)}}async saveToFile(){if(!this.config.filePath)return;try{let e=w(this.config.fileAdapter),t={endpoints:Array.from(this.endpoints.values()),savedAt:new Date().toISOString()},r=JSON.stringify(t,null,2);await e.ensureDirForFile(this.config.filePath),await e.writeFile(this.config.filePath,r),this.emit("dataSaved",{filePath:this.config.filePath,endpointCount:this.endpoints.size})}catch(e){throw this.emit("saveError",e),e}}async shutdown(){if(this.config.type==="file")await this.saveToFile().catch((e)=>{this.emit("saveError",e)});this.emit("shutdown",{endpointCount:this.endpoints.size})}}class pt extends A{config;events=new Map;indexByType=new Map;indexByDate=new Map;indexByProvider=new Map;indexByChannel=new Map;cleanupInterval=null;defaultConfig={type:"memory",retentionDays:7,enableCompression:!1,maxMemoryUsage:52428800};constructor(e={}){super();if(this.config={...this.defaultConfig,...e},this.initializeIndexes(),this.startCleanupTask(),this.config.type==="file"&&this.config.filePath)this.loadFromFile().catch((t)=>{this.emit("loadError",t)})}async saveEvent(e){if(this.events.has(e.id)){this.emit("duplicateEvent",{eventId:e.id});return}if(this.config.type==="memory"&&this.config.maxMemoryUsage)await this.checkMemoryUsage();if(this.events.set(e.id,e),this.addToIndexes(e),this.config.type==="file")await this.appendToFile(e);this.emit("eventSaved",{eventId:e.id,type:e.type,providerId:e.metadata.providerId})}async getEvent(e){return this.events.get(e)||null}async searchEvents(e={},t={page:1,limit:100}){let r=null;if(e.type&&e.type.length>0){let c=new Set;for(let u of e.type){let p=this.indexByType.get(u);if(p)p.forEach((d)=>{c.add(d)})}r=c}if(e.providerId&&e.providerId.length>0){let c=new Set;for(let u of e.providerId){let p=this.indexByProvider.get(u);if(p)p.forEach((d)=>{c.add(d)})}if(r)r=new Set(Array.from(r).filter((u)=>c.has(u)));else r=c}if(e.channelId&&e.channelId.length>0){let c=new Set;for(let u of e.channelId){let p=this.indexByChannel.get(u);if(p)p.forEach((d)=>{c.add(d)})}if(r)r=new Set(Array.from(r).filter((u)=>c.has(u)));else r=c}if(e.createdAfter||e.createdBefore){let c=this.getEventIdsByDateRange(e.createdAfter,e.createdBefore);if(r)r=new Set(Array.from(r).filter((u)=>c.has(u)));else r=c}if(!r)r=new Set(this.events.keys());let n=Array.from(r).map((c)=>this.events.get(c)).filter((c)=>this.matchesFilter(c,e));n.sort((c,u)=>{if(t.sortBy==="timestamp"||!t.sortBy){let h=u.timestamp.getTime()-c.timestamp.getTime();return t.sortOrder==="asc"?-h:h}let p=this.getFieldValue(c,t.sortBy),d=this.getFieldValue(u,t.sortBy),f=0;if(p<d)f=-1;else if(p>d)f=1;return t.sortOrder==="desc"?-f:f});let o=n.length,i=Math.ceil(o/t.limit),s=(t.page-1)*t.limit,a=s+t.limit;return{items:n.slice(s,a),totalCount:o,page:t.page,totalPages:i,hasNext:t.page<i,hasPrevious:t.page>1}}async getEventsByType(e,t=100){let r=this.indexByType.get(e);if(!r)return[];return Array.from(r).map((n)=>this.events.get(n)).sort((n,o)=>o.timestamp.getTime()-n.timestamp.getTime()).slice(0,t)}async getEventStats(e){let t={createdAfter:e?.start,createdBefore:e?.end},n=(await this.searchEvents(t,{page:1,limit:1e4})).items,o={};for(let l of Object.values(D))o[l]=0;let i={},s={},a={};for(let l of n){if(o[l.type]++,l.metadata.providerId)i[l.metadata.providerId]=(i[l.metadata.providerId]||0)+1;if(l.metadata.channelId)s[l.metadata.channelId]=(s[l.metadata.channelId]||0)+1;let c=l.timestamp.toISOString().substring(0,13);a[c]=(a[c]||0)+1}return{totalEvents:n.length,eventsByType:o,eventsByProvider:i,eventsByChannel:s,eventsPerHour:a}}async cleanupOldEvents(){if(!this.config.retentionDays)return 0;let e=new Date;e.setDate(e.getDate()-this.config.retentionDays);let t=Array.from(this.events.values()).filter((r)=>r.timestamp<e);for(let r of t)this.removeFromIndexes(r),this.events.delete(r.id);if(t.length>0){if(this.emit("oldEventsCleanup",{removedCount:t.length,cutoffDate:e}),this.config.type==="file")await this.saveToFile()}return t.length}async cleanupDuplicateEvents(){let e=new Map;for(let r of this.events.values()){let n=this.generateContentKey(r);if(!e.has(n))e.set(n,[]);e.get(n).push(r)}let t=0;for(let[r,n]of e.entries())if(n.length>1){n.sort((o,i)=>i.timestamp.getTime()-o.timestamp.getTime());for(let o=1;o<n.length;o++){let i=n[o];this.removeFromIndexes(i),this.events.delete(i.id),t++}}if(t>0){if(this.emit("duplicateEventsCleanup",{removedCount:t}),this.config.type==="file")await this.saveToFile()}return t}getStorageStats(){let e=this.estimateMemoryUsage();return{totalEvents:this.events.size,memoryUsage:e,indexSizes:{byType:this.indexByType.size,byDate:this.indexByDate.size,byProvider:this.indexByProvider.size,byChannel:this.indexByChannel.size}}}initializeIndexes(){let e=Object.values(D);for(let t of e)this.indexByType.set(t,new Set)}addToIndexes(e){let t=this.indexByType.get(e.type);if(t)t.add(e.id);let r=e.timestamp.toISOString().split("T")[0];if(!this.indexByDate.has(r))this.indexByDate.set(r,new Set);if(this.indexByDate.get(r).add(e.id),e.metadata.providerId){if(!this.indexByProvider.has(e.metadata.providerId))this.indexByProvider.set(e.metadata.providerId,new Set);this.indexByProvider.get(e.metadata.providerId).add(e.id)}if(e.metadata.channelId){if(!this.indexByChannel.has(e.metadata.channelId))this.indexByChannel.set(e.metadata.channelId,new Set);this.indexByChannel.get(e.metadata.channelId).add(e.id)}}removeFromIndexes(e){let t=this.indexByType.get(e.type);if(t)t.delete(e.id);let r=e.timestamp.toISOString().split("T")[0],n=this.indexByDate.get(r);if(n){if(n.delete(e.id),n.size===0)this.indexByDate.delete(r)}if(e.metadata.providerId){let o=this.indexByProvider.get(e.metadata.providerId);if(o){if(o.delete(e.id),o.size===0)this.indexByProvider.delete(e.metadata.providerId)}}if(e.metadata.channelId){let o=this.indexByChannel.get(e.metadata.channelId);if(o){if(o.delete(e.id),o.size===0)this.indexByChannel.delete(e.metadata.channelId)}}}getEventIdsByDateRange(e,t){let r=new Set;for(let[n,o]of this.indexByDate.entries()){let i=new Date(n);if(e&&i<e)continue;if(t&&i>t)continue;o.forEach((s)=>{r.add(s)})}return r}matchesFilter(e,t){if(t.templateId&&t.templateId.length>0){if(!e.metadata.templateId||!t.templateId.includes(e.metadata.templateId))return!1}if(t.messageId&&t.messageId.length>0){if(!e.metadata.messageId||!t.messageId.includes(e.metadata.messageId))return!1}if(t.userId&&t.userId.length>0){if(!e.metadata.userId||!t.userId.includes(e.metadata.userId))return!1}if(t.organizationId&&t.organizationId.length>0){if(!e.metadata.organizationId||!t.organizationId.includes(e.metadata.organizationId))return!1}return!0}getFieldValue(e,t){return t.split(".").reduce((r,n)=>r?.[n],e)}estimateMemoryUsage(){let e=0;for(let t of this.events.values())e+=JSON.stringify(t).length*2;return e}async checkMemoryUsage(){if(!this.config.maxMemoryUsage)return;let e=this.estimateMemoryUsage();if(e>this.config.maxMemoryUsage){let t=Array.from(this.events.values()).sort((o,i)=>o.timestamp.getTime()-i.timestamp.getTime()),r=0,n=this.config.maxMemoryUsage*0.8;for(let o of t){if(this.estimateMemoryUsage()<=n)break;this.removeFromIndexes(o),this.events.delete(o.id),r++}if(r>0)this.emit("memoryCleanup",{removedCount:r,previousUsage:e,currentUsage:this.estimateMemoryUsage()})}}generateContentKey(e){return`${e.type}_${e.metadata.messageId||""}_${e.metadata.templateId||""}_${JSON.stringify(e.data)}`}startCleanupTask(){this.cleanupInterval=setInterval(()=>{this.cleanupOldEvents().then(()=>this.cleanupDuplicateEvents()).catch((e)=>{this.emit("cleanupError",e)})},3600000)}async appendToFile(e){if(!this.config.filePath)return;try{let t=w(this.config.fileAdapter),r=JSON.stringify(e)+`
7
+ `;await t.ensureDirForFile(this.config.filePath),await t.appendFile(this.config.filePath,r)}catch(t){this.emit("appendError",t)}}async loadFromFile(){if(!this.config.filePath)return;try{let r=(await w(this.config.fileAdapter).readFile(this.config.filePath)).trim().split(`
8
+ `).filter((n)=>n.trim());for(let n of r)try{let o=JSON.parse(n),i={...o,timestamp:new Date(o.timestamp)};this.events.set(i.id,i),this.addToIndexes(i)}catch(o){this.emit("parseError",{line:n,error:o})}this.emit("dataLoaded",{filePath:this.config.filePath,eventCount:this.events.size})}catch(e){if(!T(e))this.emit("loadError",e)}}async saveToFile(){if(!this.config.filePath)return;try{let e=w(this.config.fileAdapter),t=Array.from(this.events.values()).map((r)=>JSON.stringify(r)).join(`
9
+ `);await e.ensureDirForFile(this.config.filePath),await e.writeFile(this.config.filePath,t+`
10
+ `),this.emit("dataSaved",{filePath:this.config.filePath,eventCount:this.events.size})}catch(e){throw this.emit("saveError",e),e}}async shutdown(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;if(this.config.type==="file")await this.saveToFile().catch((e)=>{this.emit("saveError",e)});this.emit("shutdown",{eventCount:this.events.size})}}class se{config;constructor(e){this.config={maxRetries:e.maxRetries,baseDelayMs:e.retryDelayMs,maxDelayMs:e.maxDelayMs||300000,backoffMultiplier:e.backoffMultiplier||2,jitter:e.jitter!==!1}}calculateNextRetry(e){if(e>=this.config.maxRetries)throw Error(`Maximum retry attempts (${this.config.maxRetries}) exceeded`);let t=this.config.baseDelayMs*this.config.backoffMultiplier**e;if(t=Math.min(t,this.config.maxDelayMs),this.config.jitter)t=t*(0.5+Math.random()*0.5);return new Date(Date.now()+t)}shouldRetry(e,t){if(e>=this.config.maxRetries)return!1;if(t)return this.isRetryableError(t);return!0}isRetryableError(e){let t=e.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused","socket hang up"].some((n)=>t.includes(n))}shouldRetryStatus(e){if(e>=400&&e<500)return[408,429].includes(e);if(e>=500)return!0;return!1}calculateRetryStats(e){if(e.length===0)return{totalAttempts:0,successfulAttempts:0,failedAttempts:0,averageDelayMs:0,totalTimeMs:0};let t=e.filter((s)=>s.success).length,r=e.length-t,n=0;for(let s=1;s<e.length;s++)n+=e[s].timestamp.getTime()-e[s-1].timestamp.getTime();let o=e.length>1?n/(e.length-1):0,i=e.length>0?e[e.length-1].timestamp.getTime()-e[0].timestamp.getTime():0;return{totalAttempts:e.length,successfulAttempts:t,failedAttempts:r,averageDelayMs:o,totalTimeMs:i}}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}getBackoffDelay(e){let t=this.config.baseDelayMs*this.config.backoffMultiplier**e;return Math.min(t,this.config.maxDelayMs)}}/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function _o(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function Or(e){if(!Number.isSafeInteger(e)||e<0)throw Error("positive integer expected, got "+e)}function q(e,...t){if(!_o(e))throw Error("Uint8Array expected");if(t.length>0&&!t.includes(e.length))throw Error("Uint8Array expected of length "+t+", got length="+e.length)}function Lr(e){if(typeof e!=="function"||typeof e.create!=="function")throw Error("Hash should be wrapped by utils.createHasher");Or(e.outputLen),Or(e.blockLen)}function ee(e,t=!0){if(e.destroyed)throw Error("Hash instance has been destroyed");if(t&&e.finished)throw Error("Hash#digest() has already been called")}function Br(e,t){q(e);let r=t.outputLen;if(e.length<r)throw Error("digestInto() expects output buffer of length at least "+r)}function z(...e){for(let t=0;t<e.length;t++)e[t].fill(0)}function Ce(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function S(e,t){return e<<32-t|e>>>t}function Ae(e,t){return e<<t|e>>>32-t>>>0}var Eo=(()=>typeof Uint8Array.from([]).toHex==="function"&&typeof Uint8Array.fromHex==="function")(),wo=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function ft(e){if(q(e),Eo)return e.toHex();let t="";for(let r=0;r<e.length;r++)t+=wo[e[r]];return t}function ko(e){if(typeof e!=="string")throw Error("string expected");return new Uint8Array(new TextEncoder().encode(e))}function ae(e){if(typeof e==="string")e=ko(e);return q(e),e}class ce{}function Pe(e){let t=(n)=>e().update(ae(n)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class ht extends ce{constructor(e,t){super();this.finished=!1,this.destroyed=!1,Lr(e);let r=ae(t);if(this.iHash=e.create(),typeof this.iHash.update!=="function")throw Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let n=this.blockLen,o=new Uint8Array(n);o.set(r.length>n?e.create().update(r).digest():r);for(let i=0;i<o.length;i++)o[i]^=54;this.iHash.update(o),this.oHash=e.create();for(let i=0;i<o.length;i++)o[i]^=106;this.oHash.update(o),z(o)}update(e){return ee(this),this.iHash.update(e),this}digestInto(e){ee(this),q(e,this.outputLen),this.finished=!0,this.iHash.digestInto(e),this.oHash.update(e),this.oHash.digestInto(e),this.destroy()}digest(){let e=new Uint8Array(this.oHash.outputLen);return this.digestInto(e),e}_cloneInto(e){e||(e=Object.create(Object.getPrototypeOf(this),{}));let{oHash:t,iHash:r,finished:n,destroyed:o,blockLen:i,outputLen:s}=this;return e=e,e.finished=n,e.destroyed=o,e.blockLen=i,e.outputLen=s,e.oHash=t._cloneInto(e.oHash),e.iHash=r._cloneInto(e.iHash),e}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}}var Se=(e,t,r)=>new ht(e,t).update(r).digest();Se.create=(e,t)=>new ht(e,t);function Co(e,t,r,n){if(typeof e.setBigUint64==="function")return e.setBigUint64(t,r,n);let o=BigInt(32),i=BigInt(4294967295),s=Number(r>>o&i),a=Number(r&i),l=n?4:0,c=n?0:4;e.setUint32(t+l,s,n),e.setUint32(t+c,a,n)}function $e(e,t,r){return e&t^~e&r}function Re(e,t,r){return e&t^e&r^t&r}class ue extends ce{constructor(e,t,r,n){super();this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.buffer=new Uint8Array(e),this.view=Ce(this.buffer)}update(e){ee(this),e=ae(e),q(e);let{view:t,buffer:r,blockLen:n}=this,o=e.length;for(let i=0;i<o;){let s=Math.min(n-this.pos,o-i);if(s===n){let a=Ce(e);for(;n<=o-i;i+=n)this.process(a,i);continue}if(r.set(e.subarray(i,i+s),this.pos),this.pos+=s,i+=s,this.pos===n)this.process(t,0),this.pos=0}return this.length+=e.length,this.roundClean(),this}digestInto(e){ee(this),Br(e,this),this.finished=!0;let{buffer:t,view:r,blockLen:n,isLE:o}=this,{pos:i}=this;if(t[i++]=128,z(this.buffer.subarray(i)),this.padOffset>n-i)this.process(r,0),i=0;for(let u=i;u<n;u++)t[u]=0;Co(r,n-8,BigInt(this.length*8),o),this.process(r,0);let s=Ce(e),a=this.outputLen;if(a%4)throw Error("_sha2: outputLen should be aligned to 32bit");let l=a/4,c=this.get();if(l>c.length)throw Error("_sha2: outputLen bigger than state");for(let u=0;u<l;u++)s.setUint32(4*u,c[u],o)}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());let{blockLen:t,buffer:r,length:n,finished:o,destroyed:i,pos:s}=this;if(e.destroyed=i,e.finished=o,e.length=n,e.pos=s,n%t)e.buffer.set(r);return e}clone(){return this._cloneInto()}}var M=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var le=Uint32Array.from([1732584193,4023233417,2562383102,271733878,3285377520]),N=new Uint32Array(80);class mt extends ue{constructor(){super(64,20,8,!1);this.A=le[0]|0,this.B=le[1]|0,this.C=le[2]|0,this.D=le[3]|0,this.E=le[4]|0}get(){let{A:e,B:t,C:r,D:n,E:o}=this;return[e,t,r,n,o]}set(e,t,r,n,o){this.A=e|0,this.B=t|0,this.C=r|0,this.D=n|0,this.E=o|0}process(e,t){for(let a=0;a<16;a++,t+=4)N[a]=e.getUint32(t,!1);for(let a=16;a<80;a++)N[a]=Ae(N[a-3]^N[a-8]^N[a-14]^N[a-16],1);let{A:r,B:n,C:o,D:i,E:s}=this;for(let a=0;a<80;a++){let l,c;if(a<20)l=$e(n,o,i),c=1518500249;else if(a<40)l=n^o^i,c=1859775393;else if(a<60)l=Re(n,o,i),c=2400959708;else l=n^o^i,c=3395469782;let u=Ae(r,5)+l+s+c+N[a]|0;s=i,i=o,o=Ae(n,30),n=r,r=u}r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,i=i+this.D|0,s=s+this.E|0,this.set(r,n,o,i,s)}roundClean(){z(N)}destroy(){this.set(0,0,0,0,0),z(this.buffer)}}var Nr=Pe(()=>new mt);var Ur=Nr;var Ao=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),U=new Uint32Array(64);class Wr extends ue{constructor(e=32){super(64,e,8,!1);this.A=M[0]|0,this.B=M[1]|0,this.C=M[2]|0,this.D=M[3]|0,this.E=M[4]|0,this.F=M[5]|0,this.G=M[6]|0,this.H=M[7]|0}get(){let{A:e,B:t,C:r,D:n,E:o,F:i,G:s,H:a}=this;return[e,t,r,n,o,i,s,a]}set(e,t,r,n,o,i,s,a){this.A=e|0,this.B=t|0,this.C=r|0,this.D=n|0,this.E=o|0,this.F=i|0,this.G=s|0,this.H=a|0}process(e,t){for(let u=0;u<16;u++,t+=4)U[u]=e.getUint32(t,!1);for(let u=16;u<64;u++){let p=U[u-15],d=U[u-2],f=S(p,7)^S(p,18)^p>>>3,h=S(d,17)^S(d,19)^d>>>10;U[u]=h+U[u-7]+f+U[u-16]|0}let{A:r,B:n,C:o,D:i,E:s,F:a,G:l,H:c}=this;for(let u=0;u<64;u++){let p=S(s,6)^S(s,11)^S(s,25),d=c+p+$e(s,a,l)+Ao[u]+U[u]|0,h=(S(r,2)^S(r,13)^S(r,22))+Re(r,n,o)|0;c=l,l=a,a=s,s=i+d|0,i=o,o=n,n=r,r=d+h|0}r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,i=i+this.D|0,s=s+this.E|0,a=a+this.F|0,l=l+this.G|0,c=c+this.H|0,this.set(r,n,o,i,s,a,l,c)}roundClean(){z(U)}destroy(){this.set(0,0,0,0,0,0,0,0),z(this.buffer)}}var jr=Pe(()=>new Wr);class de{config;encoder=new TextEncoder;constructor(e){this.config={algorithm:e.algorithm||"sha256",header:e.signatureHeader||"X-Webhook-Signature",prefix:e.signaturePrefix||"sha256="}}createSignedPayload(e,t){return`${t}.${e}`}generateSignature(e,t){let r=this.generateSignatureDigest(e,t);return this.config.prefix?`${this.config.prefix}${r}`:r}generateSignatureWithTimestamp(e,t,r){return this.generateSignature(this.createSignedPayload(e,t),r)}verifySignature(e,t,r){try{let n=this.generateSignature(e,r);return this.constantTimeCompare(t,n)}catch(n){return Y.error("Signature verification failed",void 0,n instanceof Error?n:Error(String(n))),!1}}verifySignatureWithTimestamp(e,t,r,n){return this.verifySignature(this.createSignedPayload(e,t),r,n)}extractSignature(e){let t=this.config.header.toLowerCase();for(let[r,n]of Object.entries(e))if(r.toLowerCase()===t)return n;return null}createSecurityHeaders(e,t){let r=Math.floor(Date.now()/1000).toString(),n=this.generateSignatureWithTimestamp(e,r,t);return{[this.config.header]:n,"X-Webhook-Timestamp":r,"X-Webhook-ID":this.generateWebhookId(),"User-Agent":"K-Message-Webhook/1.0"}}verifyTimestamp(e,t=300){try{let r=(()=>{if(/^[0-9]+$/.test(e.trim()))return parseInt(e,10);let i=new Date(e);if(Number.isNaN(i.getTime()))return NaN;return Math.floor(i.getTime()/1000)})(),n=Math.floor(Date.now()/1000);return Math.abs(n-r)<=t}catch{return!1}}generateWebhookId(){let e=new Uint8Array(16);if(globalThis.crypto?.getRandomValues)globalThis.crypto.getRandomValues(e);else for(let t=0;t<e.length;t++)e[t]=Math.floor(Math.random()*256);return`wh_${ft(e)}`}generateSignatureDigest(e,t){let r=this.encoder.encode(t),n=this.encoder.encode(e),o=this.config.algorithm==="sha1"?Se(Ur,r,n):Se(jr,r,n);return ft(o)}constantTimeCompare(e,t){if(e.length!==t.length)return!1;let r=0;for(let n=0;n<e.length;n++)r|=e.charCodeAt(n)^t.charCodeAt(n);return r===0}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}}class ze{async fetch(e,t){return fetch(e,t)}}class gt{responses=new Map;defaultResponse=new Response(JSON.stringify({status:"ok"}),{status:200,statusText:"OK",headers:{"content-type":"application/json"}});setMockResponse(e,t){this.responses.set(e,t)}setDefaultResponse(e){this.defaultResponse=e}async fetch(e,t){let r=this.responses.get(e);if(r)return r;return this.defaultResponse}}class yt{config;httpClient;securityManager;retryManager;constructor(e,t){this.config=e,this.httpClient=t||new ze,this.securityManager=new de(e),this.retryManager=new se(e)}async dispatch(e,t){let r=JSON.stringify(e),n=(()=>{if(e.timestamp instanceof Date)return e.timestamp;let s=new Date(e.timestamp);return Number.isNaN(s.getTime())?new Date:s})(),o=Math.floor(n.getTime()/1000).toString(),i={id:this.generateDeliveryId(),endpointId:t.id,eventId:e.id,eventType:e.type,url:t.url,httpMethod:"POST",headers:this.buildHeaders(t,e,r,o),payload:r,attempts:[],status:"pending",createdAt:new Date};return await this.executeDelivery(i,t),i}async executeDelivery(e,t){let r=t.retryConfig?.maxRetries??this.config.maxRetries;for(let n=1;n<=r+1;n++){let o=await this.makeHttpRequest(e,t,n);if(e.attempts.push(o),o.httpStatus&&o.httpStatus>=200&&o.httpStatus<300){e.status="success",e.completedAt=new Date;return}if(!(n<=r&&this.shouldRetryAttempt(o))){e.status="failed",e.completedAt=new Date;return}let s=this.calculateRetryDelay(n,t);e.nextRetryAt=new Date(Date.now()+s),await this.sleep(s)}e.status="exhausted",e.completedAt=new Date}shouldRetryAttempt(e){if(typeof e.httpStatus==="number")return this.retryManager.shouldRetryStatus(e.httpStatus);if(e.error)return this.retryManager.isRetryableError(Error(e.error));return!0}async makeHttpRequest(e,t,r){let n=Date.now(),o={attemptNumber:r,timestamp:new Date,latencyMs:0};try{let i=await this.httpClient.fetch(e.url,{method:e.httpMethod,headers:e.headers,body:e.payload,redirect:"manual",signal:AbortSignal.timeout(this.config.timeoutMs)});o.httpStatus=i.status,o.responseBody=await i.text();let s={};if(i.headers.forEach((a,l)=>{s[l]=a}),o.responseHeaders=s,o.latencyMs=Date.now()-n,!i.ok)o.error=`HTTP ${i.status}: ${i.statusText}`}catch(i){o.latencyMs=Date.now()-n,o.error=i instanceof Error?i.message:"Unknown error"}return o}buildHeaders(e,t,r,n){let o={"Content-Type":"application/json","X-Webhook-ID":t.id,"X-Webhook-Event":t.type,"X-Webhook-Timestamp":n,"User-Agent":"K-Message-Webhook/1.0"};if(e.headers)Object.assign(o,e.headers);if(this.config.enableSecurity){let i=(typeof e.secret==="string"&&e.secret.length>0?e.secret:typeof this.config.secretKey==="string"&&this.config.secretKey.length>0?this.config.secretKey:void 0)||void 0;if(i){let s=this.securityManager.generateSignatureWithTimestamp(r,n,i),a=this.securityManager.getConfig().header;o[a]=s}}return o}calculateRetryDelay(e,t){let r=t.retryConfig?.retryDelayMs||this.config.retryDelayMs,n=t.retryConfig?.backoffMultiplier||this.config.backoffMultiplier||2,o=r*n**e;if(typeof this.config.maxDelayMs==="number")o=Math.min(o,this.config.maxDelayMs);if(this.config.jitter!==!1)o=o*(0.5+Math.random()*0.5);return Math.max(0,Math.floor(o))}sleep(e){return new Promise((t)=>setTimeout(t,e))}generateDeliveryId(){return`delivery_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}async shutdown(){}}function Po(e,t){return t.updatedAt.getTime()-e.updatedAt.getTime()}function So(e,t){let r=t.createdAt.getTime()-e.createdAt.getTime();if(r!==0)return r;if(e.id<t.id)return 1;if(e.id>t.id)return-1;return 0}function bt(e,t){let r=e.createdAt.getTime(),n=t.createdAt.getTime();return r<n||r===n&&e.id<t.id}function $o(e,t){if(t.endpointId&&e.endpointId!==t.endpointId)return!1;if(t.eventType&&e.eventType!==t.eventType)return!1;if(t.before&&!bt(e,t.before))return!1;if(t.status&&e.status!==t.status)return!1;return!0}class Kr{endpoints=new Map;async add(e){this.endpoints.set(e.id,e)}async update(e,t){if(!this.endpoints.has(e))throw Error(`Webhook endpoint ${e} not found`);this.endpoints.set(e,t)}async remove(e){this.endpoints.delete(e)}async get(e){return this.endpoints.get(e)??null}async list(){return Array.from(this.endpoints.values()).sort(Po)}}class Hr{deliveries=new Map;async add(e){this.deliveries.set(e.id,e)}async replace(e){this.deliveries.set(e.id,e)}async list(e={}){let t=Array.from(this.deliveries.values()).filter((n)=>$o(n,e)).sort(So),r=typeof e.limit==="number"&&Number.isFinite(e.limit)?Math.max(0,Math.floor(e.limit)):100;return t.slice(0,r)}}function ju(){return{endpointStore:new Kr,deliveryStore:new Hr}}function xt(e){if(typeof e!=="string")return;let t=e.trim();return t.length>0?t:void 0}function Gr(e,t){let r=Oe(e);if(r==="plaintext"){if(!e.unsafeAllowPlaintextStorage)throw new _("policy","openFallback=plaintext requires unsafeAllowPlaintextStorage=true",{rule:"fieldCrypto.fail_open.plaintext_guard",path:"openFallback"},{fieldPath:"openFallback",failMode:"open",openFallback:"plaintext"});return t}if(r==="null")return"";return It()(t)}function Yr(e,t,r){if(e instanceof _){if(e.fieldPath)return e;return new _(e.kind,e.message,e.details,{providerErrorCode:e.providerErrorCode,providerErrorText:e.providerErrorText,httpStatus:e.httpStatus,requestId:e.requestId,retryAfterMs:e.retryAfterMs,attempt:e.attempt,openFallback:e.openFallback,fieldPath:t,failMode:"closed",causeChain:[e]})}return new _(r,`Field crypto ${r} failed for ${t}`,{cause:e instanceof Error?e.message:String(e)},{fieldPath:t,failMode:"closed",causeChain:[e]})}function vt(e,t){return t?{...e,tenantId:t}:e}async function Xr(e,t){let r=xt(t.value);if(!r)return;if(!e||e.enabled===!1)return r;let n=ge(e),o=e.keyResolver;try{let i={tenantId:t.tenantId,tableName:t.aad.tableName,fieldPath:t.path,messageId:t.aad.messageId,providerId:t.aad.providerId},s=o?await o.resolveEncryptKey(i):void 0,a=xt(s?.kid),l=await e.provider.encrypt({value:r,path:t.path,aad:vt(t.aad,t.tenantId),...a?{kid:a}:{}});return Dt(l.ciphertext)}catch(i){if(n==="closed")throw Yr(i,t.path,"encrypt");return Gr(e,r)}}async function _t(e,t){let r=xt(t.value);if(!r)return;if(!e||e.enabled===!1)return r;let n=ge(e);try{let o={tenantId:t.tenantId,tableName:t.aad.tableName,fieldPath:t.path,messageId:t.aad.messageId,providerId:t.aad.providerId},i=e.keyResolver?.resolveDecryptKeys?await e.keyResolver.resolveDecryptKeys({...o,ciphertext:r}):void 0,s=(a)=>e.provider.decrypt({ciphertext:r,path:t.path,aad:a,...Array.isArray(i)&&i.length>0?{candidateKids:i}:{}});if(!t.tenantId)return await s(t.aad);if(!t.acceptLegacyAad)return await s(vt(t.aad,t.tenantId));try{return await s(vt(t.aad,t.tenantId))}catch(a){try{return await s(t.aad)}catch(l){throw AggregateError([a,l],"decrypt failed with both the tenant-bound and the legacy AAD")}}}catch(o){if(n==="closed")throw Yr(o,t.path,"decrypt");return Gr(e,r)}}var Ro=["encrypt","encrypt+hash"];function Jr(e,t){if(e.enabled===!1)return;let r=e.fields[t];if(r!==void 0&&Ro.includes(r))return;throw new _("config",r===void 0?`webhook storage always encrypts ${t}; set fields.${t} to "encrypt" or "encrypt+hash"`:`webhook storage always encrypts ${t}; fields.${t} must be "encrypt" or "encrypt+hash", not "${r}"`,{rule:"fieldCrypto.webhook.encrypt_only",path:`fields.${t}`},{fieldPath:`fields.${t}`})}function Et(e){if(!e)return;if(e.endpoint)Le(e.endpoint),Jr(e.endpoint,"secret");if(e.delivery)Le(e.delivery),Jr(e.delivery,"payload")}function wt(e,t){if(t===void 0)return e;if(t)return{...e,secret:t};let r={...e};return delete r.secret,r}function kt(e){return{tableName:"webhook_endpoint",messageId:e.id}}function Ct(e){return{tableName:"webhook_delivery",messageId:e.id,providerId:e.endpointId}}async function pe(e,t){let r=await Xr(t?.endpoint,{value:e.secret,path:"secret",aad:kt(e),tenantId:t?.tenantId});return wt(e,r)}async function fe(e,t){let r=await _t(t?.endpoint,{value:e.secret,path:"secret",aad:kt(e),tenantId:t?.tenantId,acceptLegacyAad:t?.acceptLegacyAad});return wt(e,r)}async function he(e,t){let r=await Xr(t?.delivery,{value:e.payload,path:"payload",aad:Ct(e),tenantId:t?.tenantId});return{...e,payload:r??e.payload}}async function Ie(e,t){let r=await _t(t?.delivery,{value:e.payload,path:"payload",aad:Ct(e),tenantId:t?.tenantId,acceptLegacyAad:t?.acceptLegacyAad});return{...e,payload:r??e.payload}}function Vu(e,t){if(!t?.endpoint)return e;return{async add(r){await e.add(await pe(r,t))},async update(r,n){await e.update(r,await pe(n,t))},async remove(r){await e.remove(r)},async get(r){let n=await e.get(r);if(!n)return null;return await fe(n,t)},async list(){let r=await e.list();return await Promise.all(r.map((n)=>fe(n,t)))}}}function qu(e,t){if(!t?.delivery)return e;let r=e.replace?.bind(e);return{async add(n){await e.add(await he(n,t))},async list(n){let o=await e.list(n);return await Promise.all(o.map((i)=>Ie(i,t)))},...r?{async replace(n){await r(await he(n,t))}}:{}}}var zo=200,Vr=3;function qr(e){return e?{...e,failMode:"closed"}:void 0}async function Qr(e,t){try{return await _t(e,t),!0}catch{return!1}}async function en(e,t,r,n){try{return await e()}catch(o){throw new _("decrypt",`Cannot migrate webhook ${t} ${r}: its ${n} could not be read with the tenant-bound or the legacy AAD (see causeChain)`,{recordId:r},{fieldPath:n,failMode:"closed",causeChain:[o]})}}async function Io(e,t,r,n){let o={...n,acceptLegacyAad:!0};for(let i=1;;i+=1){let s=await e.get(t);if(!s)return!1;let a={value:s.secret,path:"secret",aad:kt(s),tenantId:n.tenantId};if(await Qr(r,a))return!1;let l=await en(()=>fe(s,o),"endpoint",t,"secret"),{secret:c}=await pe(l,n),u=await e.get(t);if(!u)return!1;if(u.secret===s.secret)return await e.update(t,wt(u,c)),!0;if(i===Vr)throw new _("config",`Cannot migrate webhook endpoint ${t}: its secret changed during each of ${Vr} attempts; pause endpoint updates and run the migration again`,{rule:"fieldCrypto.webhook.tenant_migration",path:"secret"},{fieldPath:"secret"})}}async function Gu(e,t){Et(t);let r=t.tenantId;if(typeof r!=="string"||r.trim().length===0)throw new _("config","migrating webhook ciphertext to the tenant requires fieldCrypto.tenantId",{rule:"fieldCrypto.webhook.tenant_migration",path:"tenantId"},{fieldPath:"tenantId"});let n=e.deliveryStore,o=n.replace?.bind(n);if(t.delivery!==void 0&&t.delivery.enabled!==!1&&!o)throw new _("config","migrating webhook deliveries needs a delivery store with replace(); the built-in stores implement it",{rule:"fieldCrypto.webhook.tenant_migration",path:"deliveryStore"},{fieldPath:"deliveryStore"});let s={tenantId:r,endpoint:qr(t.endpoint),delivery:qr(t.delivery)},a={...s,acceptLegacyAad:!0},l={endpoints:0,deliveries:0},c=s.endpoint;if(c&&c.enabled!==!1){let p=e.endpointStore;for(let{id:d}of await p.list())if(await Io(p,d,c,s))l.endpoints+=1}let u=s.delivery;if(o&&u&&u.enabled!==!1){let p;for(;;){let d=await n.list({limit:zo,...p?{before:p}:{}}),f=d[0],h=d.at(-1);if(!f||!h)break;if(p&&!bt(f,p))throw new _("config","migrating webhook deliveries needs a delivery store whose list() honors the `before` cursor; the built-in stores do",{rule:"fieldCrypto.webhook.tenant_migration",path:"deliveryStore"},{fieldPath:"deliveryStore"});for(let g of d){let C={value:g.payload,path:"payload",aad:Ct(g),tenantId:r};if(await Qr(u,C))continue;let y=await en(()=>Ie(g,a),"delivery",g.id,"payload");await o(await he(y,s)),l.deliveries+=1}p={createdAt:h.createdAt,id:h.id}}}return l}class At{endpoints=new Map;deliveries=new Map;options;constructor(e={}){this.options=e,this.validateCryptoOptions(this.options.fieldCrypto)}async addEndpoint(e){this.endpoints.set(e.id,await this.protectEndpoint(e))}async updateEndpoint(e,t){if(!this.endpoints.has(e))throw Error(`Endpoint ${e} not found`);this.endpoints.set(e,await this.protectEndpoint(t))}async removeEndpoint(e){this.endpoints.delete(e)}async getEndpoint(e){let t=this.endpoints.get(e);if(!t)return null;return await this.revealEndpoint(t)}async listEndpoints(){return await Promise.all(Array.from(this.endpoints.values()).map((e)=>this.revealEndpoint(e)))}async addDelivery(e){this.deliveries.set(e.id,await this.protectDelivery(e))}async getDeliveries(e,t,r,n,o=100){let i=Array.from(this.deliveries.values());if(e)i=i.filter((a)=>a.endpointId===e);if(t)i=i.filter((a)=>a.createdAt>=t.start&&a.createdAt<=t.end);if(r)i=i.filter((a)=>a.eventType===r);if(n)i=i.filter((a)=>a.status===n);let s=i.sort((a,l)=>l.createdAt.getTime()-a.createdAt.getTime()).slice(0,o);return await Promise.all(s.map((a)=>this.revealDelivery(a)))}async getFailedDeliveries(e,t){return(await this.getDeliveries(e,void 0,t,void 0,1000)).filter((n)=>n.status==="failed"||n.status==="exhausted")}protectEndpoint(e){return pe(e,this.options.fieldCrypto)}revealEndpoint(e){return fe(e,this.options.fieldCrypto)}protectDelivery(e){return he(e,this.options.fieldCrypto)}revealDelivery(e){return Ie(e,this.options.fieldCrypto)}validateCryptoOptions(e){Et(e)}}
11
+
12
+ //# debugId=497E5A41AB74DF7064756E2164756E21
13
+ //# sourceMappingURL=index.cjs.map