notifkit 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -443,6 +443,7 @@ declare const NotificationEnrichedPayloadSchema: z.ZodObject<{
443
443
  channel: "push" | "email" | "sms" | "webhook" | "in-app";
444
444
  priority: "low" | "normal" | "high" | "critical";
445
445
  projectId: string;
446
+ rawEventId: string;
446
447
  recipientId: string;
447
448
  templateVariables: Record<string, unknown>;
448
449
  recipient: {
@@ -463,7 +464,6 @@ declare const NotificationEnrichedPayloadSchema: z.ZodObject<{
463
464
  pushToken?: string | undefined;
464
465
  pushTokens?: string[] | undefined;
465
466
  };
466
- rawEventId: string;
467
467
  aiPrompts?: Record<string, string> | undefined;
468
468
  templateId?: string | undefined;
469
469
  campaignId?: string | undefined;
@@ -473,6 +473,7 @@ declare const NotificationEnrichedPayloadSchema: z.ZodObject<{
473
473
  channel: "push" | "email" | "sms" | "webhook" | "in-app";
474
474
  priority: "low" | "normal" | "high" | "critical";
475
475
  projectId: string;
476
+ rawEventId: string;
476
477
  recipientId: string;
477
478
  templateVariables: Record<string, unknown>;
478
479
  recipient: {
@@ -493,7 +494,6 @@ declare const NotificationEnrichedPayloadSchema: z.ZodObject<{
493
494
  pushTokens?: string[] | undefined;
494
495
  locale?: string | undefined;
495
496
  };
496
- rawEventId: string;
497
497
  aiPrompts?: Record<string, string> | undefined;
498
498
  templateId?: string | undefined;
499
499
  campaignId?: string | undefined;
@@ -702,9 +702,9 @@ declare const NotificationDispatchedPayloadSchema: z.ZodObject<{
702
702
  priority: "low" | "normal" | "high" | "critical";
703
703
  projectId: string;
704
704
  taskId: string;
705
- enrichedEventId: string;
706
705
  recipientId: string;
707
706
  templateVariables: Record<string, unknown>;
707
+ enrichedEventId: string;
708
708
  renderedContent: {
709
709
  content: Record<string, unknown>;
710
710
  attachments?: {
@@ -747,8 +747,8 @@ declare const NotificationDispatchedPayloadSchema: z.ZodObject<{
747
747
  priority: "low" | "normal" | "high" | "critical";
748
748
  projectId: string;
749
749
  taskId: string;
750
- enrichedEventId: string;
751
750
  recipientId: string;
751
+ enrichedEventId: string;
752
752
  renderedContent: {
753
753
  content: Record<string, unknown>;
754
754
  attachments?: {
@@ -993,7 +993,6 @@ declare const NotificationAiPendingPayloadSchema: z.ZodObject<{
993
993
  priority: "low" | "normal" | "high" | "critical";
994
994
  aiPrompts: Record<string, string>;
995
995
  projectId: string;
996
- enrichedEventId: string;
997
996
  recipientId: string;
998
997
  templateVariables: Record<string, unknown>;
999
998
  recipient: {
@@ -1014,6 +1013,7 @@ declare const NotificationAiPendingPayloadSchema: z.ZodObject<{
1014
1013
  pushToken?: string | undefined;
1015
1014
  pushTokens?: string[] | undefined;
1016
1015
  };
1016
+ enrichedEventId: string;
1017
1017
  templateId?: string | undefined;
1018
1018
  scheduledAt?: string | undefined;
1019
1019
  fallbackChain?: ("push" | "email" | "sms" | "webhook" | "in-app")[] | undefined;
@@ -1022,7 +1022,6 @@ declare const NotificationAiPendingPayloadSchema: z.ZodObject<{
1022
1022
  priority: "low" | "normal" | "high" | "critical";
1023
1023
  aiPrompts: Record<string, string>;
1024
1024
  projectId: string;
1025
- enrichedEventId: string;
1026
1025
  recipientId: string;
1027
1026
  templateVariables: Record<string, unknown>;
1028
1027
  recipient: {
@@ -1043,6 +1042,7 @@ declare const NotificationAiPendingPayloadSchema: z.ZodObject<{
1043
1042
  pushTokens?: string[] | undefined;
1044
1043
  locale?: string | undefined;
1045
1044
  };
1045
+ enrichedEventId: string;
1046
1046
  templateId?: string | undefined;
1047
1047
  scheduledAt?: string | undefined;
1048
1048
  fallbackChain?: ("push" | "email" | "sms" | "webhook" | "in-app")[] | undefined;
@@ -9266,7 +9266,13 @@ declare class UserRepository {
9266
9266
  preferences?: Preferences;
9267
9267
  }): Promise<boolean>;
9268
9268
  delete(projectId: string, userId: string): Promise<boolean>;
9269
- list(projectId: string, limit: number, cursor?: string): Promise<{
9269
+ list(projectId: string, limit: number, cursor?: string, filters?: {
9270
+ search?: string;
9271
+ segment?: string;
9272
+ language?: string;
9273
+ timezone?: string;
9274
+ channel?: string;
9275
+ }): Promise<{
9270
9276
  users: UserProfile[];
9271
9277
  nextCursor: string | null;
9272
9278
  }>;
@@ -9789,7 +9795,10 @@ declare class NotifkitClient {
9789
9795
  synced: number;
9790
9796
  }>;
9791
9797
  /** List registered workflow definitions. */
9792
- listWorkflows(): Promise<{
9798
+ listWorkflows(options?: {
9799
+ limit?: number;
9800
+ search?: string;
9801
+ }): Promise<{
9793
9802
  workflows: any[];
9794
9803
  }>;
9795
9804
  /** Get a workflow instance by ID. */
@@ -9804,6 +9813,9 @@ declare class NotifkitClient {
9804
9813
  workflowInstanceId?: string;
9805
9814
  channel?: string;
9806
9815
  status?: string;
9816
+ taskId?: string;
9817
+ campaign?: string;
9818
+ search?: string;
9807
9819
  }): Promise<{
9808
9820
  logs: any[];
9809
9821
  nextCursor: string | null;
@@ -9812,6 +9824,11 @@ declare class NotifkitClient {
9812
9824
  listUsers(options?: {
9813
9825
  limit?: number;
9814
9826
  cursor?: string;
9827
+ search?: string;
9828
+ segment?: string;
9829
+ language?: string;
9830
+ timezone?: string;
9831
+ channel?: string;
9815
9832
  }): Promise<{
9816
9833
  users: any[];
9817
9834
  nextCursor: string | null;
@@ -9853,6 +9870,11 @@ declare class NotifkitClient {
9853
9870
  /** List campaign labels seen in the delivery log, most recent activity first. */
9854
9871
  listCampaigns(options?: {
9855
9872
  limit?: number;
9873
+ search?: string;
9874
+ channel?: string;
9875
+ since?: string | Date;
9876
+ until?: string | Date;
9877
+ minMessages?: number;
9856
9878
  }): Promise<{
9857
9879
  campaigns: {
9858
9880
  campaign: string;
@@ -9874,6 +9896,7 @@ declare class NotifkitClient {
9874
9896
  limit?: number;
9875
9897
  channel?: string;
9876
9898
  reason?: string;
9899
+ target?: string;
9877
9900
  }): Promise<{
9878
9901
  suppressions: any[];
9879
9902
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/index.ts","../src/contracts/common.ts","../src/contracts/metadata.ts","../src/contracts/events/notification-requested.ts","../src/contracts/events/notification-created.ts","../src/contracts/events/notification-enriched.ts","../src/contracts/events/notification-scheduled.ts","../src/contracts/events/notification-dispatched.ts","../src/contracts/events/notification-delivered.ts","../src/contracts/events/notification-failed.ts","../src/contracts/events/notification-skipped.ts","../src/contracts/events/notification-canceled.ts","../src/contracts/events/notification-ai-pending.ts","../src/contracts/registry.ts","../src/contracts/envelope.ts","../src/contracts/streams.ts","../src/contracts/helpers.ts","../src/contracts/sdk.ts","../src/db/schema.ts","../src/db/index.ts","../src/idempotency/index.ts","../src/logger/index.ts","../src/metrics/index.ts","../src/queue/index.ts","../src/rate-limiter/index.ts","../src/redis/index.ts","../src/repositories/index.ts","../src/shared/events.ts","../src/shared/cache.ts","../src/shared/utils.ts","../src/shared/semaphore.ts","../src/shared/batch-processor.ts","../src/shared/circuit-breaker.ts","../src/shared/dataloader.ts","../src/workers/health.ts","../src/workers/index.ts","../src/shared/index.ts","../src/templates/render.ts","../src/templates/cache.ts","../src/templates/index.ts","../src/transport/index.ts","../src/unsubscribe/index.ts","../src/workflows/sdk.ts","../src/workflows/registry.ts","../src/client.ts","../src/server.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/index.ts","../src/contracts/common.ts","../src/contracts/metadata.ts","../src/contracts/events/notification-requested.ts","../src/contracts/events/notification-created.ts","../src/contracts/events/notification-enriched.ts","../src/contracts/events/notification-scheduled.ts","../src/contracts/events/notification-dispatched.ts","../src/contracts/events/notification-delivered.ts","../src/contracts/events/notification-failed.ts","../src/contracts/events/notification-skipped.ts","../src/contracts/events/notification-canceled.ts","../src/contracts/events/notification-ai-pending.ts","../src/contracts/registry.ts","../src/contracts/envelope.ts","../src/contracts/streams.ts","../src/contracts/helpers.ts","../src/contracts/sdk.ts","../src/db/schema.ts","../src/db/index.ts","../src/idempotency/index.ts","../src/logger/index.ts","../src/metrics/index.ts","../src/queue/index.ts","../src/rate-limiter/index.ts","../src/redis/index.ts","../src/repositories/index.ts","../src/shared/events.ts","../src/shared/cache.ts","../src/shared/utils.ts","../src/shared/semaphore.ts","../src/shared/batch-processor.ts","../src/shared/circuit-breaker.ts","../src/shared/dataloader.ts","../src/workers/health.ts","../src/workers/index.ts","../src/shared/index.ts","../src/templates/render.ts","../src/templates/cache.ts","../src/templates/index.ts","../src/transport/index.ts","../src/unsubscribe/index.ts","../src/workflows/sdk.ts","../src/workflows/registry.ts","../src/client.ts","../src/server.ts"],"mappings":";;;;;;;;;iBAOgB,QAAQ;iBAKR,YAAY,gBAAgB,YAC1C,QAAQ,SACR,gBACC,EAAE,OAAO;cAkBC,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6BjB,aAAa,EAAE,aAAa;iBAIxB,gBAAgB,QAAQ;iBAIxB,eAAe,OAAM,OAAO,aAA2B;UAOtD;EACf;EACA;;UAGe;EACf,UAAU;;EAEV;;EAEA;;EAEA;;cAGW;;;;;iBAQG,YAAY,QAAQ;iBAIpB,eAAe;;;cCtGlB,2BAAyB,EAAA;KAC1B,sBAAsB,EAAE,aAAa;cAEpC,4BAA0B,EAAA;KAC3B,uBAAuB,EAAE,aAAa;cAErC,0BAAwB,EAAA;KASzB,qBAAqB,EAAE,aAAa;;;cCfnC,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;KAOpB,gBAAgB,EAAE,aAAa;;;;;;;;;;;cCE9B,0BAAwB,EAAA,+BAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKzB,qBAAqB,EAAE,aAAa;cAEnC,oCAAkC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiBnC,+BAA+B,EAAE,aAAa;;;cChC7C,kCAAgC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAUjC,6BAA6B,EAAE,aAAa;;;cCV3C,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsBvB,mBAAmB,EAAE,aAAa;cAEjC,mCAAiC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAelC,8BAA8B,EAAE,aAAa;;;cCxC5C,oCAAkC,EAAA;;;;;;;;;;;;;;;;KAMnC,+BAA+B,EAAE,aAAa;;;cCJ7C,uBAAqB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAYtB,kBAAkB,EAAE,aAAa;cAEhC,uBAAqB,EAAA;;;;;;;;;;;;;KAKtB,kBAAkB,EAAE,aAAa;cAEhC,qCAAmC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmBpC,gCAAgC,EAAE,aAAa;;;cCzC9C,oCAAkC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAanC,+BAA+B,EAAE,aAAa;;;cCb7C,iCAA+B,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAehC,4BAA4B,EAAE,aAAa;;;cChB1C,kCAAgC,EAAA;;;;;;;;;;;;;;;;KAMjC,6BAA6B,EAAE,aAAa;;;cCN3C,mCAAiC,EAAA;;;;;;;;;;KAIlC,8BAA8B,EAAE,aAAa;;;cCF5C,oCAAkC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAanC,+BAA+B,EAAE,aAAa;;;;;;;;;;;;;;;UCMzC;EACf,0BAA0B;EAC1B,wBAAwB;EACxB,yBAAyB;EACzB,0BAA0B;EAC1B,2BAA2B;EAC3B,0BAA0B;EAC1B,uBAAuB;EACvB,wBAAwB;EACxB,yBAAyB;EACzB,2BAA2B;;KAGjB,uBAAuB;KAEvB,YAAY;EAAO;EAAe,MAAM;;EAAQ;EAAgB,OAAO;;cAEtE;mBACM;EAEjB,OAAO,cAAc,QAAQ;EAO7B,UAAU,eAAe;EAIzB,IAAI;EAIJ;EAIA,aAAa,UAAU,gBAAgB,MAAM,GAAG,mBAAmB,gBAAgB;EAMnF,iBAAiB,UAAU,gBACzB,MAAM,GACN,mBACC,YAAY,gBAAgB;;cAgBpB,UAAQ;;;;;;;cC/ER,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOpB,gBAAgB,EAAE,aAAa;;KAG/B,mBAAmB,UAAU,kBAAkB,KACzD;EAGA,MAAM;EACN,SAAS,gBAAgB;;KAIf,cAAc;cACb,mBAAiB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAClB,sBAAsB;cACrB,2BAAyB,EAAA;;;;;;;;;;;;;;;;;;;;;cC9BzB;;;;;;;;;;;;;;;;cAiBA;cAMA;cAMA;KAKD,qBAAqB,sBAAsB;;;;;;;cAQ1C;;;;;;;;KAQD,wBAAwB,8BAA8B;cAErD;;;;;;;;;KASD,wBAAwB,8BAA8B;;;iBCxDlD,iBACd,cACA,SAAS,yBACT,gBACA,mBACC,KAAK;;;cCDK,kBAAgB,EAAA;;;;;;;;;;KAIjB,aAAa,EAAE,aAAa;cAE3B,mBAAiB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKlB,cAAc,EAAE,aAAa;;cAK5B,sBAAoB,EAAA;KACrB,iBAAiB,EAAE,aAAa;;;;;cAa/B,eAAa,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAUd,eAAe,EAAE,aAAa;;cAG7B,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KASjB,kBAAkB,EAAE,aAAa;;cAGhC,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKjB,kBAAkB,EAAE,aAAa;cAIhC,gBAAc,EAAA;;;;;;;;;;;;;;;;;;;KAUf,gBAAgB,EAAE,aAAa;cAE9B,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAGpB,qBAAqB,EAAE,aAAa;;cAKnC,kBAAgB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAUjB,aAAa,EAAE,aAAa;cA0C3B,qBAAmB,EAAA,WAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgBpB,qBAAqB,EAAE,aAAa;;;;;;;;cASnC,6BAA2B,EAAA,WAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAS5B,sBAAsB,EAAE,aAAa;cAIpC,uBAAqB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKtB,uBAAuB,EAAE,aAAa;cAIrC,mBAAiB,EAAA;;;;;;;;;;KAIlB,mBAAmB,EAAE,aAAa;cAEjC,oBAAkB,EAAA,iCAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmBnB,kBAAkB,EAAE,aAAa;cAEhC,sBAAoB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAIrB,sBAAsB,EAAE,aAAa;cAIpC,qBAAmB,EAAA;;;;;;;;;;;;;KAKpB,qBAAqB,EAAE,aAAa;;;;cCrNnC,2CAAW;cAEX,wCAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAR;;;;;;;;;;;;;;;cASA,qCAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAL;;;;;;;;;;;;;;;;;YAAA;;;;;;;;;;;;;;;cAeA,8CAAc;cAEd,8CAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAd;;;;;;;;;;;;;;;cAUA,4CAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAeZ,4CAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAZ;;;;;;;;;;;;;;;cAmBA,sDAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cActB,oDAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAepB,uDAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAevB,0CAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAeV,yCAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAT;;;;;;;;;;;;;;;cAkBA,2CAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAX;;;;;;;;;;;;;;;;;;;;;;;;cA6DA,4CAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAZ;;;;;;;;;;;;;;;cA6BA,kDAAkB;cAOlB,mDAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAnB;;;;;;;;;;;;;;;cAcA,iDAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAjB;;;;;;;;;;;;;;;;;YAAA;;;;;;;;;;;;;;;cAgBA,6CAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAb;;;;;;;;;;;;;;;cAmBA,+CAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAf;;;;;;;;;;;;;;;;;YAAA;;;;;;;;;;;;;;;cAyBA,8CAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAd;;;;;;;;;;;;;;;cAcA,iDAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAAjB;;;;;;;;;;;;;;;cAQA,2CAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAnB;;;;;;;;;;;;;cACA,2CAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAnB;;;;;;;;;;;;;cAEA,iDAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAzB;;;;;;;;;;;;;cACA,iDAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAzB;;;;;;;;;;;;;cAEA,wCAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAhB;;;;;;;;;;;;;;;;;UAAA;;;;;;;;;;;;;cACA,wCAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAhB;;;;;;;;;;;;;;;;;UAAA;;;;;;;;;;;;;cAEA,+CAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cACvB,+CAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEvB,+CAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAvB;;;;;;;;;;;;;cACA,+CAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAvB;;;;;;;;;;;;;cAEA,yDAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cACjC,yDAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEjC,uDAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAC/B,uDAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAE/B,8CAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAtB;;;;;;;;;;;;;cACA,8CAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAtB;;;;;;;;;;;;;cAEA,+CAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAvB;;;;;;;;;;;;;cACA,+CAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAvB;;;;;;;;;;;;;cAEA,oDAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA5B;;;;;;;;;;;;;;;;;UAAA;;;;;;;;;;;;;cACA,oDAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA5B;;;;;;;;;;;;;;;;;UAAA;;;;;;;;;;;;;cAEA,gDAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAxB;;;;;;;;;;;;;cACA,gDAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAAxB;;;;;;;;;;;;;cAEA,kDAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA1B;;;;;;;;;;;;;;;;;UAAA;;;;;;;;;;;;;cACA,kDAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA1B;;;;;;;;;;;;;;;;;UAAA;;;;;;;;;;;;;cAEA,kDAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA1B;;;;;;;;;;;;;cACA,kDAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA1B;;;;;;;;;;;;;cAEA,oDAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA5B;;;;;;;;;;;;;cACA,oDAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAA5B;;;;;;;;;;;;;;;KC3YD,MAAM,SAAS;KACf,KAAK,0BAA0B;UAE1B;EACf;EACA;EACA;EACA;EACA,SAAS;;UAGM;EACf,KAAK;EACL,IAAI;;;;;;;iBAQU,iBACd,KACA,iBACA,gBACA,oBACA,UACC,kBAAkB;iBAyBC,cAAc,IAAI,KAAE;;;UCxDzB;EACf,OAAO;EACP;EACA;;;;;;;cAQW;mBACM;mBACA;mBACA;EAEL,cAAE,OAAO,WAAW,cAAuB;UAM/C;;EAKF,aAAa,YAAY,4BAA4B;;EAOrD,cAAc,YAAY,4BAA4B;EAKtD,YAAY,aAAa;;EAKzB,OAAO,aAAa;;;;KC5ChB;KAEA,SAAS;UAEJ;EACf;EACA,QAAQ;EACR;EACA,UAAU;;iBAGI,eAAe,MAAM,OAAgB,QAAQ,WAAW,gBAAgB;iBAoCxE,cAAc,QAAQ,QAAQ,oBAAoB;iBAIlD,YAAY,QAAQ,QAAQ,SAAS,0BAA0B;iBAI/D,YAAY,QAAQ,QAAQ,UAAU,0BAA0B;;;cCpDnE;;;;;;;;;iBA6CG,sBAAkB,WAAA;;;UCpCjB;EACf;EACA,OAAO;;EAEP;;UAGe;EACf;EACA;EACA;EACA;;EAEA,QAAQ;;UAiCO;EACf,OAAO;EACP,QAAQ;EACR,SAAS;EACT;;cAGW;mBACM;mBACA;mBACA;mBACA;EAEL,cAAE,OAAO,QAAQ,QAAQ,UAAU;EAOzC,QAAQ,SAAS,KAAK,mCAAmC;UA2BjD;EAsBR,aACJ,UAAU,KAAK,qCACd;IAAU;IAAsB;;;UAkDpB;EACf,OAAO;EACP,QAAQ,aAAa;EACrB,OAAO;EACP;EACA,YAAY;EACZ,SAAS;EACT;EACA;;cAKW;WACF,OAAO;mBACC;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;EAEI,cACV,OACA,QACA,OACA,UACA,WACA,QACA,WACA,WACC;EAYG,eAAe;EAkBd,aAAa,eAAe;EAyF7B,IAAI,8BAA8B,kBAAkB;EAQpD,KAAK,mBAAmB,OAAO,aAAa,kBAAkB;EAiC9D,QAAQ;;UAcC;EACf,OAAO;EACP,QAAQ,aAAa;EACrB,OAAO;EACP;EACA,SAAS;;cAGE;mBACM;mBACA;mBACA;mBACA;mBACA;EAEL,cAAE,OAAO,QAAQ,OAAO,UAAU,UAAU;EAQlD,mBAAmB;;EAanB,kBAAkB,gBAAa,SAAS,aAAa,QAAQ;EAwB7D,UAAU,mBAAmB,iBAAa,QAAQ;;;;UC5bzC;EACf;EACA;EACA;;;;;;UASe;EACf;EACA;;UAQe;EACf;EACA;;;;;;;;;;;;cAaW;mBAaQ;mBAZF;;;;;;;;;mBASA;EAGE,YAAA,OAAO,sBAAsB,QAAQ,mCACpD,SAAgB,UAAkB;;;;;EAShC,IAAI,oBAAoB,QAAQ;EAiCtC,WAAW;EAOX;;UASe;EACf,OAAO;EACP;EACA;;UAGe;;EAEf;;EAEA;;EAEA;;cAaW;mBACM;mBACA;mBACA;EAEL,cAAE,OAAO,YAAgB,eAAmB;;;;;;;;EAalD,MACJ,mBACA,gBACA,mBACA,UAAS,uBACR,QAAQ;;;;UC/JI;EACf;EACA;EACA,SAAS;EACT,eAAe,QAAQ;;cAGZ;WACF,QAAQ;mBAEA;UACT;EAEI,cAAE,KAAK,MAAmB,QAAQ,gBAAgB;EAkCxD,eAAe;EASf,cAAc;;;;UCnCL;EACf;EACA;EACA;EACA;;UAGe,mBAAmB;EAClC;EACA,aAAa;;UAGE;EACf;EACA;EACA,SAAS;EACT;EACA,aAAa;EACb;;UAGe;EACf;EACA;EACA;EACA;;EAEA,YAAY;;KAGF;UAEK;EACf;EACA;EACA;EACA,UAAU;EACV;;UAGe;EACf;EACA;EACA;;cAKW;mBACkB;EAAA,YAAA,IAAI;EAE3B,SAAS,mBAAmB,iBAAiB,QAAQ;EAiBrD,eAAe,mBAAmB,iBAAiB,QAAQ;EAuD3D,iBAAiB,mBAAmB,oBAAoB,QAAQ;EA2EhE,WACJ,mBACA;IACE;IACA;IACA;IACA;IACA;IACA,aAAa;MAEd;EA0FG,eACJ,mBACA,WAAW;IACT;IACA;IACA;IACA;IACA;IACA,aAAa;OAEd;EA8JG,cACJ,mBACA,gBACA;IACE;IACA;IACA;IACA;IACA,cAAc;MAEf;EAsFG,OAAO,mBAAmB,iBAAiB;EAQ3C,KACJ,mBACA,eACA,iBACA;IACE;IACA;IACA;IACA;IACA;MAED;IAAU,OAAO;IAAe;;EA4D7B,mBAAmB,mBAAmB,sBAAsB;EAU5D,iBAAiB,mBAAmB,oBAAoB;;cAmBnD;mBACkB;EAAA,YAAA,IAAI;EAE3B,UAAU,mBAAmB,gBAAgB,oBAAoB;EAMjE,aAAa,mBAAmB,iBAAiB,QAAQ;;cAuBpD;mBACkB;EAAA,YAAA,IAAI;EAE3B,aAAa,mBAAmB,iBAAiB,QAAQ;;EAyCzD,oBACJ,mBACA,oBACC,QAAQ,YAAY;EAqCjB,OACJ,mBACA,gBACA,SAAS,gBACT,gBACA,cAAa,cACZ;EAyCG,WACJ,mBACA,cAAc;IACZ;IACA,SAAS;IACT;IACA,cAAc;OAEf;;;;;;EA0EG,WACJ,mBACA,gBACA,SAAS,gBACT,iBACC;EAsBG,OACJ,mBACA,gBACA,SAAS,gBACT,iBACC;;cAwBQ;mBACkB;EAAA,YAAA,IAAI;EAE3B,SAAS,mBAAmB,aAAa,QAAQ;EAgBjD,KAAK,oBAAoB,QAAQ;EAWjC,WAAW,mBAAmB,sBAAsB;EA6BpD,OAAO,mBAAmB,aAAa;;cAWlC;mBACkB;EAAA,YAAA,IAAI;EAE3B,QAAQ;EAcR,OAAO,aAAa;;;;;EA2BpB,qBACJ,aACC;IAAU;IAA8B;;EAarC,eACJ,YACA;IACE;IACA;IACA;MAED;EASG,aACJ,mBACA,iBACA,+BACC;IAAU;;EAQP,YAAY,oBAAoB;EAYhC,aAAa,mBAAmB,gBAAgB;;cAW3C;mBACkB;EAAA,YAAA,IAAI;EAE3B,gBAAgB,oBAAoB;EAQpC,YAAY,mBAAmB,qBAAqB;EAyBpD,eAAe,mBAAmB,qBAAqB;;cAsBlD;mBACkB;EAAA,YAAA,IAAI;EAE3B,aAAa,oBAAoB;;;;cCltC5B,eAAa;;;cCFb,SAAS,GAAG;UACf;mBACS;mBACA;EAEL,YAAA,kBAAwB;EAKpC,IAAI,KAAK,IAAI;EAeb,IAAI,KAAK,GAAG,OAAO,GAAG;EActB,OAAO,KAAK;EAIZ;;;;iBC3Cc,kBACd;;;;;;;;;;;iBAgBc,gBAAgB;cAKnB;cAcA;;cAcA;;cAQA;;;cC1DA;mBAIkB;UAHrB;UACA;EAEqB,YAAA;EAEvB,WAAW;EAUjB;MAaI;;;;UC7BW,UAAU,GAAG;EAC5B,MAAM;EACN,UAAU,OAAO;EACjB,SAAS;;cAGE,eAAe,GAAG;mBAMV;mBACA;mBACA;UAPX;UACA;UACA;EAGW,YAAA,iBACA,mBACA,UAAU,OAAO,QAAQ,QAAQ;EAGpD,IAAI,MAAM,IAAI,QAAQ;EAkBhB,SAAS;;;;UCnCA;EACf;EACA;;KAGG;cAEQ;UACH;UACA;UACA;;UAEA;mBACS;mBACA;EAEL,YAAA,SAAS;EAKf,QAAQ,GAAG,cAAc,QAAQ,KAAK,QAAQ;UAkC5C;UAKA;EAUR,YAAY;;;;cCtED,WAAW,GAAG;mBAKI;UAJrB;UACA;UACA;EAEqB,YAAA,cAAc,MAAM,QAAQ,SAAS,IAAI;EAEtE,KAAK,KAAK,IAAI,QAAQ;;;;iBCJR,oBACd,qBACA,QAAQ,YACR;EAAS,mBAAmB;EAAkB;GAC9C,QAAQ,QACR,sBACC,OAAO;;;cCDG,0BAA0B;WAC5B;EACG,YAAA;;KAMF;UAEK;EACf,OAAO;EACP;EACA;EACA;EACA;EACA;;UAGe;EACf,UAAU;EACV,gBAAgB;EAChB,QAAQ;EACR;EACA;EACA;;uBAKoB;qBACD,QAAQ;mBAEV;mBACA;mBACA;mBACA;mBACA;UAET;UACA;UACA;UACA;UACA;UACA;UACA;UACA;mBACS;mBACA;UACT;EAEI,cACV,UACA,gBACA,QACA,aACA,oBACA,uBACC;qBAUgB,QAAQ,SAAS,eAAe,mBAAmB;EAEhE,SAAS;UAcD;EAuBR,QAAQ;EAqBR,WAAW;EA+BjB,UAAU;UAaI;UAqEN;UAUA;;;;iBCjQM;iBAIA,MAAM,aAAa;cAItB,iBAAiB;WACnB;EAEG,YAAA,iBAAiB,cAAc,UAAU;;cAO1C,wBAAwB;WAC1B,SAAS;EAEN,YAAA,iBAAiB,SAAS,0BAA0B,UAAU;;;;iBCvB5D,WAAW;;iBAUX,aAAa;iBAMb,YACd,cACA,WAAW,yBACX;;;;;;;;KAmBU;iBAwEI,mBACd;EAAc;sBACd,mBAAmB;EAChB,SAAS;;;;cC9GD;mBAGkB;UAFrB;EAEqB,YAAA,cAAc;EAErC,kBAAkB,mBAAmB,aAAU;EAYrD,WAAW,mBAAmB;EAI9B,cAAc;EAId;;;;UCtBe;EACf;EACA,mBAAmB;EACnB;EACA;EACA;;KAGU,oBAAoB,KAAK,oBAAoB;cAanD;mBACa;;;;;EAMjB,SAAS,mBAAmB,UAAU;;EAKtC,OAAO,KAAK,kBAAkB;EAM9B,IAAI;EAIJ;;cAeW,kBAAgB;iBAEb,eAAe,KAAK,kBAAkB;;;UC3DrC;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,YAAY;;;;;;EAMZ;;;;;;;;EAQA;;EAEA,WAAW;;UAGI;WACN,SAAS;WACT;IAAW;IAAe;;EACnC,KAAK,MAAM,gCAAgC,QAAQ;EAEnD;EACA,iBACE,iBACA,SAAS,kDACN;EACL,gBACE,WACA,kBACA,UAAU,kDACP,QAAQ;;cAKT;mBACa;EAEjB,SAAS,WAAW,WAAW;EAQ/B,IAAI,SAAS,sBAAsB;EAKnC,OAAO,SAAS,sBAAsB;EAKtC;;cAKW,mBAAiB;iBAEd,kBAAkB,WAAW,WAAW;;;;;;;;;;;;;;;;;UClEvC;;EAEf;;EAEA;EACA;;EAEA;;EAEA;;;;;;;;;iBAsBc,qBAAqB,OAAO,kBAAkB;;;;;;;;iBAoB9C,uBAAuB,eAAe,iBAAiB;UAmCtD;EACf,OAAO;EACP;;EAEA;;;;;;;;;;iBAWc,wBAAwB,SAAS,2BAA2B;;;cChH/D,8BAA8B;EAEhC;EACA;EADA,YAAA,iCACA;;UAOM;EACf;IAAQ;;GACP;;UAGc;EACf,MAAM;EACN,OAAO;;;UAIQ;EACf;EACA;EACA;;UAGe;EACf,OAAO,SAAS,sBAAsB,QAAQ;EAC9C,KAAK,mBAAmB;EACxB,aACE,mBACA;IAAY;IAAkB,QAAQ;MACrC;EACH,IAAI,GAAG,cAAc,UAAU,QAAQ,KAAK,IAAI,QAAQ;;;;;;;;;iBAU1C,kBACd,MAAM,qBACN,yBACC;;;;;;;;iBAkCa,uBACd,MAAM,qBACN,wBACA,mBACA,0BACC;;;KC1FE,mBAAmB,KAAK,oBAAoB;cAE3C;UACI;EAER,SAAS,cAAc,SAAS;EAIhC,IAAI,eAAe;;cAKR,kBAAgB;iBAEb,SAAS,cAAc,SAAS;;;UCN/B;EACf;EACA,UAAU;EACV,YAAY;EACZ;;cAGW;mBACM;mBACA;mBACA;EAEL,YAAA,SAAS;UAUP;;EAsBR,cAAc,OAAO,qBAAqB;IAAU;;;EAKpD,QAAQ,OAAO,eAAe;IAAU;;;EAKxC,WAAW,YAAY,OAAO,kBAAkB;IAAU;;;EAK1D,WAAW,aAAa;;EAKxB,WACJ,gBACA,OAAO,kBACN;IAAU;IAAgB;IAAiB;;;EAKxC,cAAc,gBAAgB,iBAAiB,iBAAiB;;EAKhE,OACJ,OAAO,qBACN;IAAU;IAAmB;IAAwB;;;EAKlD,gBACJ,OAAO,uBACN;IAAU;IAAmB;;;EAK1B,eAAe,OAAO,sBAAsB;IAAU;;;EAKtD,YAAY,OAAO,mBAAmB;IAAU;IAAmB;;;EAKnE,QAAQ;IAAU;;;EAUlB,cAAc;IAClB;IACA;MACE;IAAU;;;EASR,YAAY,qBAAqB;;EAKjC,eAAe,qBAAqB;;EAKpC,oBAAoB;IACxB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;MACE;IAAU;IAAa;;;EAqBrB,UAAU;IACd;IACA;IACA;IACA;IACA;IACA;IACA;MACE;IAAU;IAAc;;;EActB,eAAe,aAAa;;EAK5B,gBAAgB,iBAAiB;IAAU;;;EAK3C,gBAAgB;IAAU;;;EAK1B,cAAc,aAAa;;EAK3B,iBACJ,YACA;IAAU;MACT;IAAU;IAAY;IAAgB;;;EAKnC,gBAAgB,aAAa;IAAU;;;EAKvC,iBAAiB,YAAY,gBAAgB;;EAK7C,cAAc,YAAY,OAAO,qBAAqB;IAAU;;;EAKhE,gBAAgB;IAAU;;;EAO1B,cAAc;IAClB;IACA;IACA;IACA,iBAAiB;IACjB,iBAAiB;IACjB;MACE;IACF;MACE;MACA;MACA;MACA;;;;EA0BE,iBAAiB,mBAAmB;IACxC;IACA,QAAQ;IACR,WAAW,eAAe;IAC1B;IACA;;;EAQI,iBAAiB;IACrB;IACA;IACA;IACA;MACE;IAAU;;;EAWR,kBAAkB;IACtB;IACA;IACA;MACE;IAAU;IAAiB;IAAgB;;;EAKzC,kBAAkB,iBAAiB,iBAAiB;;EAUpD,sBAAsB,iBAAiB;IAAU;IAAgB;;;EAKjE,mBAAmB,iBAAiB;IAAU;;;EAK9C,wBAAwB;IAAU;;;EAOlC,QAAQ,aAAa;;EAKrB,eAAe,aAAa;;EAK5B,mBAAmB,aAAa;;EAKhC,sBACJ,YACA,aAAa,sBACZ;IAAU;IAAY;;;EAOnB,iBAAiB;IAAU;;;EAK3B,YAAY,aAAa;;EAOzB,mBAAmB;;EAKnB,oBAAoB;;EAKpB,kBAAkB;IAAU;;;EAK5B,iBAAiB,aAAa;IAAU;IAAkB;;;EAK1D,iBAAiB,aAAa;IAAU;;;;;UClZ/B;EACf;EACA;EACA;EACA;EACA;EACA;EAGA,YAAY;EACZ;EACA,UAAU;EACV;EACA;IACE;;EAEF;IACE;;;cAIS,uBAAuB;UAC1B;UACA;UACA;UACA;UACA;UACA;EAEI,YAAA,SAAS;EA4Bf,SAAK;EA+IL,QAAI"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { $ as childLogger, $t as PUBSUB_CHANNELS, A as ProjectSettingsCache, At as NotificationRequestedPayloadSchema, B as LUA_RELEASE_LOCK, Bt as QuietHoursSchema, C as ProjectRepository, Ct as DeliveryOptionsSchema, D as WorkflowRepository, Dt as NotificationEnrichedPayloadSchema, E as UserRepository, Et as NotificationScheduledPayloadSchema, F as sleep, Ft as CreateWorkflowSchema, G as normaliseTarget, Gt as UpdateUserSchema, H as LUA_SCHEDULER_CLAIM, Ht as TemplateSchema, I as DataLoader, It as IngestEventSchema, J as PendingMessageScanner, Jt as buildStreamEvent, K as LRUCache, Kt as WorkflowNotifyPayloadSchema, L as CircuitBreaker, Lt as InlineUserSchema, M as AppError, Mt as AddContactSchema, N as ValidationError, Nt as AddUserSchema, O as Redis, Ot as RecipientProfileSchema, P as generateId, Pt as ContactChannelSchema, Q as metrics, Qt as OUTBOUND_STREAMS, R as BatchProcessor, Rt as NotifyRequestSchema, S as PreferenceRepository, St as NotificationDeliveredPayloadSchema, T as TemplateRepository, Tt as RenderedContentSchema, U as LUA_SCHEDULER_POLL, Ut as TriggerWorkflowSchema, V as LUA_RENEW_LOCK, Vt as SyncTemplatesSchema, W as getPriorityBucket, Wt as UpdateProjectSchema, X as StreamProducer, Xt as ENRICHED_STREAMS, Y as StreamConsumer, Yt as CONSUMER_GROUPS, Z as getMetricsRegistry, Zt as INBOUND_STREAMS, _ as escapeHeader, _n as setGlobalConfig, a as SuspendExecutionError, an as registry, at as runMigrations, b as renderWithTemplate, bt as NotificationSkippedPayloadSchema, c as BaseWorker, cn as NotificationPrioritySchema, d as buildUnsubscribeHeaders, dn as baseConfigSchema, en as STREAMS, et as createLogger, f as signUnsubscribeToken, fn as getAiConfig, g as TemplateCache, gn as setAiConfig, h as templateRegistry, hn as readBaseConfig, i as workflowRegistry, in as EventRegistry, it as createDatabase, j as UserThrottle, jt as NotificationTargetSchema, k as RedisClient, kt as NotificationCreatedPayloadSchema, l as NonRetryableError, ln as NotificationStatusSchema, m as renderTemplate, mn as parseConfig, n as NotifkitClient, nn as StreamEventMetadataSchema, nt as withRequestId, o as buildStepNotifyPayload, on as EventMetadataSchema, p as verifyUnsubscribeToken, pn as loadEnv, q as globalEmitter, qt as WorkflowStepSchema, r as workflow, rn as StreamEventSchema, rt as IdempotencyGuard, s as resolveStepTarget, sn as NotificationChannelSchema, t as NotifkitServer, tn as EventEnvelopeSchema, tt as withContext, u as startHealthReporter, un as AI_DEFAULTS, v as escapeHtml, vt as NotificationAiPendingPayloadSchema, w as SegmentRepository, wt as NotificationDispatchedPayloadSchema, x as ContactRepository, xt as NotificationFailedPayloadSchema, y as interpolate, yt as NotificationCanceledPayloadSchema, z as AsyncSemaphore, zt as PreferencesSchema } from "./src-DrSN2wCg.mjs";
2
+ import { $ as childLogger, $t as PUBSUB_CHANNELS, A as ProjectSettingsCache, At as NotificationRequestedPayloadSchema, B as LUA_RELEASE_LOCK, Bt as QuietHoursSchema, C as ProjectRepository, Ct as DeliveryOptionsSchema, D as WorkflowRepository, Dt as NotificationEnrichedPayloadSchema, E as UserRepository, Et as NotificationScheduledPayloadSchema, F as sleep, Ft as CreateWorkflowSchema, G as normaliseTarget, Gt as UpdateUserSchema, H as LUA_SCHEDULER_CLAIM, Ht as TemplateSchema, I as DataLoader, It as IngestEventSchema, J as PendingMessageScanner, Jt as buildStreamEvent, K as LRUCache, Kt as WorkflowNotifyPayloadSchema, L as CircuitBreaker, Lt as InlineUserSchema, M as AppError, Mt as AddContactSchema, N as ValidationError, Nt as AddUserSchema, O as Redis, Ot as RecipientProfileSchema, P as generateId, Pt as ContactChannelSchema, Q as metrics, Qt as OUTBOUND_STREAMS, R as BatchProcessor, Rt as NotifyRequestSchema, S as PreferenceRepository, St as NotificationDeliveredPayloadSchema, T as TemplateRepository, Tt as RenderedContentSchema, U as LUA_SCHEDULER_POLL, Ut as TriggerWorkflowSchema, V as LUA_RENEW_LOCK, Vt as SyncTemplatesSchema, W as getPriorityBucket, Wt as UpdateProjectSchema, X as StreamProducer, Xt as ENRICHED_STREAMS, Y as StreamConsumer, Yt as CONSUMER_GROUPS, Z as getMetricsRegistry, Zt as INBOUND_STREAMS, _ as escapeHeader, _n as setGlobalConfig, a as SuspendExecutionError, an as registry, at as runMigrations, b as renderWithTemplate, bt as NotificationSkippedPayloadSchema, c as BaseWorker, cn as NotificationPrioritySchema, d as buildUnsubscribeHeaders, dn as baseConfigSchema, en as STREAMS, et as createLogger, f as signUnsubscribeToken, fn as getAiConfig, g as TemplateCache, gn as setAiConfig, h as templateRegistry, hn as readBaseConfig, i as workflowRegistry, in as EventRegistry, it as createDatabase, j as UserThrottle, jt as NotificationTargetSchema, k as RedisClient, kt as NotificationCreatedPayloadSchema, l as NonRetryableError, ln as NotificationStatusSchema, m as renderTemplate, mn as parseConfig, n as NotifkitClient, nn as StreamEventMetadataSchema, nt as withRequestId, o as buildStepNotifyPayload, on as EventMetadataSchema, p as verifyUnsubscribeToken, pn as loadEnv, q as globalEmitter, qt as WorkflowStepSchema, r as workflow, rn as StreamEventSchema, rt as IdempotencyGuard, s as resolveStepTarget, sn as NotificationChannelSchema, t as NotifkitServer, tn as EventEnvelopeSchema, tt as withContext, u as startHealthReporter, un as AI_DEFAULTS, v as escapeHtml, vt as NotificationAiPendingPayloadSchema, w as SegmentRepository, wt as NotificationDispatchedPayloadSchema, x as ContactRepository, xt as NotificationFailedPayloadSchema, y as interpolate, yt as NotificationCanceledPayloadSchema, z as AsyncSemaphore, zt as PreferencesSchema } from "./src-C-PfEDMY.mjs";
3
3
  //#region src/transport/index.ts
4
4
  var transport_exports = /* @__PURE__ */ __exportAll({
5
5
  registerTransport: () => registerTransport,
@@ -1,4 +1,4 @@
1
- import { J as PendingMessageScanner, Jt as buildStreamEvent, X as StreamProducer, Y as StreamConsumer, Yt as CONSUMER_GROUPS, _t as workflowWaiters, c as BaseWorker, en as STREAMS, et as createLogger, gt as workflowSteps, hn as readBaseConfig, ht as workflowInstances, it as createDatabase, k as RedisClient, pn as loadEnv, st as messageLogs, u as startHealthReporter } from "./src-DrSN2wCg.mjs";
1
+ import { J as PendingMessageScanner, Jt as buildStreamEvent, X as StreamProducer, Y as StreamConsumer, Yt as CONSUMER_GROUPS, _t as workflowWaiters, c as BaseWorker, en as STREAMS, et as createLogger, gt as workflowSteps, hn as readBaseConfig, ht as workflowInstances, it as createDatabase, k as RedisClient, pn as loadEnv, st as messageLogs, u as startHealthReporter } from "./src-C-PfEDMY.mjs";
2
2
  import { and, eq, gt, isNull, or } from "drizzle-orm";
3
3
  //#region src/services/events/main.ts
4
4
  loadEnv();
@@ -231,4 +231,4 @@ async function stopEventWorker() {
231
231
  //#endregion
232
232
  export { startEventWorker, stopEventWorker };
233
233
 
234
- //# sourceMappingURL=main-D-oWWzR3.mjs.map
234
+ //# sourceMappingURL=main-B-jwm8ED.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"main-D-oWWzR3.mjs","names":["sql"],"sources":["../src/services/events/main.ts"],"sourcesContent":["import { loadEnv, readBaseConfig } from \"@/index.js\";\nimport { createLogger } from \"@/index.js\";\nimport { RedisClient } from \"@/index.js\";\nimport {\n StreamConsumer,\n PendingMessageScanner,\n StreamProducer,\n type StreamMessage,\n} from \"@/index.js\";\nimport { BaseWorker } from \"@/index.js\";\nimport { STREAMS, CONSUMER_GROUPS, buildStreamEvent } from \"@/index.js\";\nimport { type StreamName } from \"@/contracts/streams.js\";\nimport { createDatabase } from \"@/db/index.js\";\nimport { workflowWaiters, workflowSteps, workflowInstances, messageLogs } from \"@/db/schema.js\";\nimport { eq, and, or, isNull, gt } from \"drizzle-orm\";\nimport { type WorkerOptions } from \"@/shared/index.js\";\nimport { startHealthReporter } from \"@/workers/index.js\";\n\nloadEnv();\nconst config = readBaseConfig();\nlet logger: ReturnType<typeof createLogger>;\nlet redis: RedisClient;\nlet sql: any;\nlet db: any;\n\nlet consumer: StreamConsumer;\nlet pendingScanner: PendingMessageScanner;\nlet worker: BaseWorker;\nlet healthInterval: NodeJS.Timeout | null = null;\n\nlet workflowProducer: StreamProducer;\n\nexport interface EventWorkerOptions extends WorkerOptions {\n db: any;\n workflowProducer: any;\n}\n\nexport class EventWorker extends BaseWorker {\n private readonly dbConn: any;\n private readonly workflowProducer: any;\n private messageLogBuffer: { log: any; resolve: () => void; reject: (err: any) => void }[] = [];\n private eventBuffer: {\n producer: any;\n event: any;\n resolve: () => void;\n reject: (err: any) => void;\n }[] = [];\n private flushInterval: NodeJS.Timeout | null = null;\n private isFlushing = false;\n\n constructor(options: EventWorkerOptions) {\n super(options);\n this.dbConn = options.db;\n this.workflowProducer = options.workflowProducer;\n this.startFlushInterval();\n }\n\n private startFlushInterval() {\n this.flushInterval = setInterval(() => {\n void this.flushLogs();\n }, config.LOG_FLUSH_INTERVAL_MS);\n }\n\n private async flushLogs() {\n if (this.isFlushing || (this.messageLogBuffer.length === 0 && this.eventBuffer.length === 0))\n return;\n this.isFlushing = true;\n\n const startTime = Date.now();\n const batch = this.messageLogBuffer;\n this.messageLogBuffer = [];\n\n const events = this.eventBuffer;\n this.eventBuffer = [];\n\n try {\n if (batch.length > 0) {\n await this.dbConn\n .insert(messageLogs)\n .values(batch.map((b) => b.log))\n .onConflictDoNothing(); // Idempotent insert\n for (const b of batch) b.resolve();\n\n this.logger.info(\n {\n batchSize: batch.length,\n latencyMs: Date.now() - startTime,\n },\n \"flushed delivery logs to database\",\n );\n }\n\n if (events.length > 0) {\n const byProducer = new Map<any, typeof events>();\n for (const item of events) {\n if (!byProducer.has(item.producer)) byProducer.set(item.producer, []);\n byProducer.get(item.producer)!.push(item);\n }\n for (const [producer, evts] of byProducer) {\n await producer.publishBatch(evts.map((e) => e.event));\n for (const e of evts) e.resolve();\n }\n }\n } catch (error: any) {\n this.logger.error(\n {\n batchSize: batch.length,\n error: error.message,\n },\n \"failed to flush delivery logs — dropping batch\",\n );\n for (const b of batch) b.reject(error);\n for (const e of events) e.reject(error);\n } finally {\n this.isFlushing = false;\n }\n }\n\n override async stop(): Promise<void> {\n if (this.flushInterval) clearInterval(this.flushInterval);\n await super.stop();\n await this.flushLogs();\n }\n\n override async process(message: StreamMessage): Promise<void> {\n const { event } = message;\n const publishPromises: Promise<void>[] = [];\n\n if (\n event.type === \"notification.dispatched\" ||\n event.type === \"notification.delivered\" ||\n event.type === \"notification.failed\"\n ) {\n const payload = event.payload as any;\n if (this.messageLogBuffer.length >= config.LOG_BUFFER_MAX_SIZE) {\n this.logger.warn(\n { dropped: 1, bufferSize: this.messageLogBuffer.length },\n \"log buffer full — dropping oldest delivery log\",\n );\n const dropped = this.messageLogBuffer.shift(); // Drop oldest to apply back-pressure/prevent OOM\n if (dropped) dropped.reject(new Error(\"Dropped due to buffer overflow\"));\n }\n\n const status =\n event.type === \"notification.dispatched\"\n ? \"dispatched\"\n : event.type === \"notification.delivered\"\n ? \"delivered\"\n : \"failed\";\n\n const kind = event.type === \"notification.dispatched\" ? \"dispatched\" : \"attempt\";\n\n publishPromises.push(\n new Promise((resolve, reject) => {\n this.messageLogBuffer.push({\n log: {\n projectId: payload.projectId,\n taskId: payload.taskId,\n providerMessageId: payload.providerMessageId || null,\n channel: payload.channel,\n attempt: payload.attempt || 1,\n kind,\n status,\n templateId: payload.templateId || null,\n workflowInstanceId: payload.workflowInstanceId || null,\n campaignId: payload.campaignId || null,\n },\n resolve,\n reject,\n });\n }),\n );\n await Promise.all(publishPromises);\n return;\n }\n\n if (event.type !== \"event.received\") {\n return;\n }\n\n const payload = event.payload as any;\n const eventName = payload.eventName;\n const eventData = payload.payload;\n const projectId = payload.projectId;\n\n if (!eventName || !projectId) {\n this.logger.warn(\"Missing eventName or projectId in payload\");\n return;\n }\n\n // Find matching waiters\n const now = new Date();\n const waiters = await this.dbConn\n .select()\n .from(workflowWaiters)\n .where(\n and(\n eq(workflowWaiters.eventName, eventName),\n eq(workflowWaiters.projectId, projectId),\n or(isNull(workflowWaiters.expiresAt), gt(workflowWaiters.expiresAt, now)),\n ),\n );\n\n const data: Record<string, any> = eventData && typeof eventData === \"object\" ? eventData : {};\n\n for (const waiter of waiters) {\n // Check match criteria\n let matched = true;\n const criteria = waiter.matchCriteria as Record<string, any>;\n if (criteria && typeof criteria === \"object\") {\n for (const [k, v] of Object.entries(criteria)) {\n // simple dot notation check for a flat object or 1 level deep\n let dataValue = data[k];\n if (k.includes(\".\")) {\n const parts = k.split(\".\");\n dataValue = data;\n for (const p of parts) {\n if (dataValue) dataValue = dataValue[p];\n }\n }\n if (dataValue !== v) {\n matched = false;\n break;\n }\n }\n }\n\n if (matched) {\n this.logger.info(\n { instanceId: waiter.instanceId, eventName },\n \"Event matched a sleeping workflow\",\n );\n\n // The resume event must carry everything WorkflowWorker.process requires\n // (name, instanceId, projectId) or it is dropped and the instance — whose\n // waiter we are about to delete — is stranded forever.\n const instance = (\n await this.dbConn\n .select()\n .from(workflowInstances)\n .where(eq(workflowInstances.id, waiter.instanceId))\n .limit(1)\n )[0];\n\n if (!instance) {\n this.logger.warn(\n { instanceId: waiter.instanceId },\n \"waiter references a missing workflow instance — dropping waiter\",\n );\n await this.dbConn.delete(workflowWaiters).where(eq(workflowWaiters.id, waiter.id));\n continue;\n }\n\n // Find the step that is waiting\n const steps = await this.dbConn\n .select()\n .from(workflowSteps)\n .where(\n and(\n eq(workflowSteps.instanceId, waiter.instanceId),\n eq(workflowSteps.action, \"waitForEvent\"),\n ),\n );\n\n // Get the latest one that has no output\n const pendingStep = steps.find((s: any) => s.output === null);\n\n if (pendingStep) {\n // Update the step with the event payload\n await this.dbConn\n .update(workflowSteps)\n .set({ output: data })\n .where(eq(workflowSteps.id, pendingStep.id));\n }\n\n // Wake up workflow. Publish BEFORE deleting the waiter: a crash after the\n // delete but before the publish would leave the instance unrecoverable,\n // whereas a duplicate resume is idempotent (the instance lock and the\n // replayed step outputs both absorb it).\n publishPromises.push(\n new Promise((resolve, reject) => {\n this.eventBuffer.push({\n producer: this.workflowProducer,\n event: buildStreamEvent(\n \"workflow.resumed\",\n {\n projectId: instance.projectId,\n instanceId: waiter.instanceId,\n name: instance.name,\n input: instance.input ?? {},\n reason: \"event_matched\",\n },\n \"events\",\n event.metadata.traceId,\n ),\n resolve,\n reject,\n });\n }),\n );\n\n // Delete the waiter\n await this.dbConn.delete(workflowWaiters).where(eq(workflowWaiters.id, waiter.id));\n\n // The timer ZSET entry is left to expire: the poll loop re-checks the\n // instance status and drops the entry if it is no longer pending.\n }\n }\n\n await Promise.all(publishPromises);\n }\n}\n\nexport async function startEventWorker() {\n logger = createLogger({ name: \"event-worker\", level: config.LOG_LEVEL });\n redis = new RedisClient({ url: config.REDIS_URL, name: \"events\", logger });\n const dbData = createDatabase({ url: config.DATABASE_URL, applicationName: \"events\", logger });\n sql = dbData.sql;\n db = dbData.db;\n workflowProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.WORKFLOW_INBOUND,\n logger,\n });\n consumer = new StreamConsumer({\n redis: redis.native,\n stream: STREAMS.EVENTS_INBOUND as StreamName,\n group: CONSUMER_GROUPS.EVENTS as any,\n consumer: `events-${process.pid}`,\n dlqStream: STREAMS.DEAD_LETTER,\n batchSize: config.WORKER_CONCURRENCY,\n logger,\n });\n\n pendingScanner = new PendingMessageScanner({\n redis: redis.native,\n stream: STREAMS.EVENTS_INBOUND as StreamName,\n group: CONSUMER_GROUPS.EVENTS as any,\n consumer: `events-${process.pid}`,\n logger,\n });\n\n worker = new EventWorker({\n consumer,\n pendingScanner,\n logger,\n concurrency: config.WORKER_CONCURRENCY,\n db,\n workflowProducer,\n });\n\n healthInterval = startHealthReporter(\"events\", worker, redis, logger);\n\n logger.info(\"event worker starting\");\n await worker.start();\n}\n\nexport async function stopEventWorker(): Promise<void> {\n logger?.info(\"shutdown initiated\");\n if (healthInterval) clearInterval(healthInterval);\n if (worker) await worker.stop();\n if (sql) await sql.end();\n if (redis) await redis.disconnect();\n logger?.info(\"event worker stopped\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"main-B-jwm8ED.mjs","names":["sql"],"sources":["../src/services/events/main.ts"],"sourcesContent":["import { loadEnv, readBaseConfig } from \"@/index.js\";\nimport { createLogger } from \"@/index.js\";\nimport { RedisClient } from \"@/index.js\";\nimport {\n StreamConsumer,\n PendingMessageScanner,\n StreamProducer,\n type StreamMessage,\n} from \"@/index.js\";\nimport { BaseWorker } from \"@/index.js\";\nimport { STREAMS, CONSUMER_GROUPS, buildStreamEvent } from \"@/index.js\";\nimport { type StreamName } from \"@/contracts/streams.js\";\nimport { createDatabase } from \"@/db/index.js\";\nimport { workflowWaiters, workflowSteps, workflowInstances, messageLogs } from \"@/db/schema.js\";\nimport { eq, and, or, isNull, gt } from \"drizzle-orm\";\nimport { type WorkerOptions } from \"@/shared/index.js\";\nimport { startHealthReporter } from \"@/workers/index.js\";\n\nloadEnv();\nconst config = readBaseConfig();\nlet logger: ReturnType<typeof createLogger>;\nlet redis: RedisClient;\nlet sql: any;\nlet db: any;\n\nlet consumer: StreamConsumer;\nlet pendingScanner: PendingMessageScanner;\nlet worker: BaseWorker;\nlet healthInterval: NodeJS.Timeout | null = null;\n\nlet workflowProducer: StreamProducer;\n\nexport interface EventWorkerOptions extends WorkerOptions {\n db: any;\n workflowProducer: any;\n}\n\nexport class EventWorker extends BaseWorker {\n private readonly dbConn: any;\n private readonly workflowProducer: any;\n private messageLogBuffer: { log: any; resolve: () => void; reject: (err: any) => void }[] = [];\n private eventBuffer: {\n producer: any;\n event: any;\n resolve: () => void;\n reject: (err: any) => void;\n }[] = [];\n private flushInterval: NodeJS.Timeout | null = null;\n private isFlushing = false;\n\n constructor(options: EventWorkerOptions) {\n super(options);\n this.dbConn = options.db;\n this.workflowProducer = options.workflowProducer;\n this.startFlushInterval();\n }\n\n private startFlushInterval() {\n this.flushInterval = setInterval(() => {\n void this.flushLogs();\n }, config.LOG_FLUSH_INTERVAL_MS);\n }\n\n private async flushLogs() {\n if (this.isFlushing || (this.messageLogBuffer.length === 0 && this.eventBuffer.length === 0))\n return;\n this.isFlushing = true;\n\n const startTime = Date.now();\n const batch = this.messageLogBuffer;\n this.messageLogBuffer = [];\n\n const events = this.eventBuffer;\n this.eventBuffer = [];\n\n try {\n if (batch.length > 0) {\n await this.dbConn\n .insert(messageLogs)\n .values(batch.map((b) => b.log))\n .onConflictDoNothing(); // Idempotent insert\n for (const b of batch) b.resolve();\n\n this.logger.info(\n {\n batchSize: batch.length,\n latencyMs: Date.now() - startTime,\n },\n \"flushed delivery logs to database\",\n );\n }\n\n if (events.length > 0) {\n const byProducer = new Map<any, typeof events>();\n for (const item of events) {\n if (!byProducer.has(item.producer)) byProducer.set(item.producer, []);\n byProducer.get(item.producer)!.push(item);\n }\n for (const [producer, evts] of byProducer) {\n await producer.publishBatch(evts.map((e) => e.event));\n for (const e of evts) e.resolve();\n }\n }\n } catch (error: any) {\n this.logger.error(\n {\n batchSize: batch.length,\n error: error.message,\n },\n \"failed to flush delivery logs — dropping batch\",\n );\n for (const b of batch) b.reject(error);\n for (const e of events) e.reject(error);\n } finally {\n this.isFlushing = false;\n }\n }\n\n override async stop(): Promise<void> {\n if (this.flushInterval) clearInterval(this.flushInterval);\n await super.stop();\n await this.flushLogs();\n }\n\n override async process(message: StreamMessage): Promise<void> {\n const { event } = message;\n const publishPromises: Promise<void>[] = [];\n\n if (\n event.type === \"notification.dispatched\" ||\n event.type === \"notification.delivered\" ||\n event.type === \"notification.failed\"\n ) {\n const payload = event.payload as any;\n if (this.messageLogBuffer.length >= config.LOG_BUFFER_MAX_SIZE) {\n this.logger.warn(\n { dropped: 1, bufferSize: this.messageLogBuffer.length },\n \"log buffer full — dropping oldest delivery log\",\n );\n const dropped = this.messageLogBuffer.shift(); // Drop oldest to apply back-pressure/prevent OOM\n if (dropped) dropped.reject(new Error(\"Dropped due to buffer overflow\"));\n }\n\n const status =\n event.type === \"notification.dispatched\"\n ? \"dispatched\"\n : event.type === \"notification.delivered\"\n ? \"delivered\"\n : \"failed\";\n\n const kind = event.type === \"notification.dispatched\" ? \"dispatched\" : \"attempt\";\n\n publishPromises.push(\n new Promise((resolve, reject) => {\n this.messageLogBuffer.push({\n log: {\n projectId: payload.projectId,\n taskId: payload.taskId,\n providerMessageId: payload.providerMessageId || null,\n channel: payload.channel,\n attempt: payload.attempt || 1,\n kind,\n status,\n templateId: payload.templateId || null,\n workflowInstanceId: payload.workflowInstanceId || null,\n campaignId: payload.campaignId || null,\n },\n resolve,\n reject,\n });\n }),\n );\n await Promise.all(publishPromises);\n return;\n }\n\n if (event.type !== \"event.received\") {\n return;\n }\n\n const payload = event.payload as any;\n const eventName = payload.eventName;\n const eventData = payload.payload;\n const projectId = payload.projectId;\n\n if (!eventName || !projectId) {\n this.logger.warn(\"Missing eventName or projectId in payload\");\n return;\n }\n\n // Find matching waiters\n const now = new Date();\n const waiters = await this.dbConn\n .select()\n .from(workflowWaiters)\n .where(\n and(\n eq(workflowWaiters.eventName, eventName),\n eq(workflowWaiters.projectId, projectId),\n or(isNull(workflowWaiters.expiresAt), gt(workflowWaiters.expiresAt, now)),\n ),\n );\n\n const data: Record<string, any> = eventData && typeof eventData === \"object\" ? eventData : {};\n\n for (const waiter of waiters) {\n // Check match criteria\n let matched = true;\n const criteria = waiter.matchCriteria as Record<string, any>;\n if (criteria && typeof criteria === \"object\") {\n for (const [k, v] of Object.entries(criteria)) {\n // simple dot notation check for a flat object or 1 level deep\n let dataValue = data[k];\n if (k.includes(\".\")) {\n const parts = k.split(\".\");\n dataValue = data;\n for (const p of parts) {\n if (dataValue) dataValue = dataValue[p];\n }\n }\n if (dataValue !== v) {\n matched = false;\n break;\n }\n }\n }\n\n if (matched) {\n this.logger.info(\n { instanceId: waiter.instanceId, eventName },\n \"Event matched a sleeping workflow\",\n );\n\n // The resume event must carry everything WorkflowWorker.process requires\n // (name, instanceId, projectId) or it is dropped and the instance — whose\n // waiter we are about to delete — is stranded forever.\n const instance = (\n await this.dbConn\n .select()\n .from(workflowInstances)\n .where(eq(workflowInstances.id, waiter.instanceId))\n .limit(1)\n )[0];\n\n if (!instance) {\n this.logger.warn(\n { instanceId: waiter.instanceId },\n \"waiter references a missing workflow instance — dropping waiter\",\n );\n await this.dbConn.delete(workflowWaiters).where(eq(workflowWaiters.id, waiter.id));\n continue;\n }\n\n // Find the step that is waiting\n const steps = await this.dbConn\n .select()\n .from(workflowSteps)\n .where(\n and(\n eq(workflowSteps.instanceId, waiter.instanceId),\n eq(workflowSteps.action, \"waitForEvent\"),\n ),\n );\n\n // Get the latest one that has no output\n const pendingStep = steps.find((s: any) => s.output === null);\n\n if (pendingStep) {\n // Update the step with the event payload\n await this.dbConn\n .update(workflowSteps)\n .set({ output: data })\n .where(eq(workflowSteps.id, pendingStep.id));\n }\n\n // Wake up workflow. Publish BEFORE deleting the waiter: a crash after the\n // delete but before the publish would leave the instance unrecoverable,\n // whereas a duplicate resume is idempotent (the instance lock and the\n // replayed step outputs both absorb it).\n publishPromises.push(\n new Promise((resolve, reject) => {\n this.eventBuffer.push({\n producer: this.workflowProducer,\n event: buildStreamEvent(\n \"workflow.resumed\",\n {\n projectId: instance.projectId,\n instanceId: waiter.instanceId,\n name: instance.name,\n input: instance.input ?? {},\n reason: \"event_matched\",\n },\n \"events\",\n event.metadata.traceId,\n ),\n resolve,\n reject,\n });\n }),\n );\n\n // Delete the waiter\n await this.dbConn.delete(workflowWaiters).where(eq(workflowWaiters.id, waiter.id));\n\n // The timer ZSET entry is left to expire: the poll loop re-checks the\n // instance status and drops the entry if it is no longer pending.\n }\n }\n\n await Promise.all(publishPromises);\n }\n}\n\nexport async function startEventWorker() {\n logger = createLogger({ name: \"event-worker\", level: config.LOG_LEVEL });\n redis = new RedisClient({ url: config.REDIS_URL, name: \"events\", logger });\n const dbData = createDatabase({ url: config.DATABASE_URL, applicationName: \"events\", logger });\n sql = dbData.sql;\n db = dbData.db;\n workflowProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.WORKFLOW_INBOUND,\n logger,\n });\n consumer = new StreamConsumer({\n redis: redis.native,\n stream: STREAMS.EVENTS_INBOUND as StreamName,\n group: CONSUMER_GROUPS.EVENTS as any,\n consumer: `events-${process.pid}`,\n dlqStream: STREAMS.DEAD_LETTER,\n batchSize: config.WORKER_CONCURRENCY,\n logger,\n });\n\n pendingScanner = new PendingMessageScanner({\n redis: redis.native,\n stream: STREAMS.EVENTS_INBOUND as StreamName,\n group: CONSUMER_GROUPS.EVENTS as any,\n consumer: `events-${process.pid}`,\n logger,\n });\n\n worker = new EventWorker({\n consumer,\n pendingScanner,\n logger,\n concurrency: config.WORKER_CONCURRENCY,\n db,\n workflowProducer,\n });\n\n healthInterval = startHealthReporter(\"events\", worker, redis, logger);\n\n logger.info(\"event worker starting\");\n await worker.start();\n}\n\nexport async function stopEventWorker(): Promise<void> {\n logger?.info(\"shutdown initiated\");\n if (healthInterval) clearInterval(healthInterval);\n if (worker) await worker.stop();\n if (sql) await sql.end();\n if (redis) await redis.disconnect();\n logger?.info(\"event worker stopped\");\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { $t as PUBSUB_CHANNELS, A as ProjectSettingsCache, C as ProjectRepository, G as normaliseTarget, I as DataLoader, J as PendingMessageScanner, Jt as buildStreamEvent, T as TemplateRepository, W as getPriorityBucket, X as StreamProducer, Xt as ENRICHED_STREAMS, Y as StreamConsumer, Yt as CONSUMER_GROUPS, an as registry, b as renderWithTemplate, c as BaseWorker, d as buildUnsubscribeHeaders, dt as suppressions, en as STREAMS, et as createLogger, g as TemplateCache, hn as readBaseConfig, it as createDatabase, j as UserThrottle, k as RedisClient, pn as loadEnv, q as globalEmitter, rt as IdempotencyGuard, u as startHealthReporter, ut as scheduledPayloads, x as ContactRepository } from "./src-DrSN2wCg.mjs";
1
+ import { $t as PUBSUB_CHANNELS, A as ProjectSettingsCache, C as ProjectRepository, G as normaliseTarget, I as DataLoader, J as PendingMessageScanner, Jt as buildStreamEvent, T as TemplateRepository, W as getPriorityBucket, X as StreamProducer, Xt as ENRICHED_STREAMS, Y as StreamConsumer, Yt as CONSUMER_GROUPS, an as registry, b as renderWithTemplate, c as BaseWorker, d as buildUnsubscribeHeaders, dt as suppressions, en as STREAMS, et as createLogger, g as TemplateCache, hn as readBaseConfig, it as createDatabase, j as UserThrottle, k as RedisClient, pn as loadEnv, q as globalEmitter, rt as IdempotencyGuard, u as startHealthReporter, ut as scheduledPayloads, x as ContactRepository } from "./src-C-PfEDMY.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { and, eq } from "drizzle-orm";
4
4
  //#region src/services/engine/main.ts
@@ -568,4 +568,4 @@ async function stopEngineWorker() {
568
568
  //#endregion
569
569
  export { startEngineWorker, stopEngineWorker };
570
570
 
571
- //# sourceMappingURL=main-Dlfy9mWs.mjs.map
571
+ //# sourceMappingURL=main-B561M1d3.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"main-Dlfy9mWs.mjs","names":["sql"],"sources":["../src/services/engine/main.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { loadEnv, readBaseConfig } from \"@/index.js\";\nimport { createLogger } from \"@/index.js\";\nimport { RedisClient, type Redis } from \"@/index.js\";\nimport {\n StreamConsumer,\n PendingMessageScanner,\n StreamProducer,\n type StreamMessage,\n} from \"@/index.js\";\nimport { BaseWorker } from \"@/index.js\";\nimport {\n STREAMS,\n ENRICHED_STREAMS,\n CONSUMER_GROUPS,\n PUBSUB_CHANNELS,\n registry,\n buildStreamEvent,\n type NotificationEnrichedPayload,\n type NotificationDispatchedPayload,\n} from \"@/index.js\";\nimport { type StreamName } from \"@/contracts/streams.js\";\nimport { IdempotencyGuard } from \"@/index.js\";\nimport { UserThrottle, ProjectSettingsCache } from \"@/index.js\";\nimport { TemplateRepository, ContactRepository, ProjectRepository } from \"@/index.js\";\nimport { createDatabase } from \"@/db/index.js\";\nimport { scheduledPayloads, suppressions } from \"@/db/schema.js\";\nimport { and, eq } from \"drizzle-orm\";\nimport {\n getPriorityBucket,\n globalEmitter,\n normaliseTarget,\n type WorkerOptions,\n DataLoader,\n} from \"@/shared/index.js\";\nimport { renderWithTemplate, TemplateCache } from \"@/templates/index.js\";\nimport { buildUnsubscribeHeaders } from \"@/unsubscribe/index.js\";\nimport { startHealthReporter } from \"@/workers/index.js\";\n\nfunction localTimeToUtc(\n year: number,\n month: number,\n day: number,\n hour: number,\n minute: number,\n second: number,\n timezone: string,\n): Date {\n let utcMs = Date.UTC(year, month - 1, day, hour, minute, second);\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n\n for (let iter = 0; iter < 3; iter++) {\n const parts = formatter.formatToParts(new Date(utcMs));\n const pYear = parseInt(parts.find((p) => p.type === \"year\")?.value ?? \"0\", 10);\n const pMonth = parseInt(parts.find((p) => p.type === \"month\")?.value ?? \"0\", 10);\n const pDay = parseInt(parts.find((p) => p.type === \"day\")?.value ?? \"0\", 10);\n const pHour = parseInt(parts.find((p) => p.type === \"hour\")?.value ?? \"0\", 10);\n const pMin = parseInt(parts.find((p) => p.type === \"minute\")?.value ?? \"0\", 10);\n const pSec = parseInt(parts.find((p) => p.type === \"second\")?.value ?? \"0\", 10);\n\n const targetMs = Date.UTC(year, month - 1, day, hour, minute, second);\n const actualMs = Date.UTC(pYear, pMonth - 1, pDay, pHour, pMin, pSec);\n const diff = targetMs - actualMs;\n if (diff === 0) break;\n utcMs += diff;\n }\n return new Date(utcMs);\n}\n\nexport function isInQuietHours(\n timezone: string,\n quietHours: { start: string; end: string }[],\n fromDate: Date = new Date(),\n): { inQuietHours: boolean; nextActiveTime?: Date } {\n if (!quietHours || quietHours.length === 0) {\n return { inQuietHours: false };\n }\n\n const checkWindowAt = (date: Date) => {\n let parts: Intl.DateTimeFormatPart[];\n try {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n parts = formatter.formatToParts(date);\n } catch {\n return null;\n }\n\n const year = parseInt(parts.find((p) => p.type === \"year\")?.value ?? \"0\", 10);\n const month = parseInt(parts.find((p) => p.type === \"month\")?.value ?? \"0\", 10);\n const day = parseInt(parts.find((p) => p.type === \"day\")?.value ?? \"0\", 10);\n const currentHour = parseInt(parts.find((p) => p.type === \"hour\")?.value ?? \"0\", 10);\n const currentMin = parseInt(parts.find((p) => p.type === \"minute\")?.value ?? \"0\", 10);\n\n const currentMinutes = currentHour * 60 + currentMin;\n\n for (const window of quietHours) {\n const [startH, startM] = window.start.split(\":\").map(Number);\n const [endH, endM] = window.end.split(\":\").map(Number);\n\n if (startH === undefined || startM === undefined || endH === undefined || endM === undefined)\n continue;\n\n const startMinutes = startH * 60 + startM;\n const endMinutes = endH * 60 + endM;\n\n let inWindow = false;\n if (startMinutes <= endMinutes) {\n inWindow = currentMinutes >= startMinutes && currentMinutes < endMinutes;\n } else {\n inWindow = currentMinutes >= startMinutes || currentMinutes < endMinutes;\n }\n\n if (inWindow) {\n let targetYear = year;\n let targetMonth = month;\n let targetDay = day;\n\n if (currentMinutes >= endMinutes) {\n const nextDay = new Date(Date.UTC(year, month - 1, day + 1));\n targetYear = nextDay.getUTCFullYear();\n targetMonth = nextDay.getUTCMonth() + 1;\n targetDay = nextDay.getUTCDate();\n }\n\n const nextActive = localTimeToUtc(\n targetYear,\n targetMonth,\n targetDay,\n endH,\n endM,\n 0,\n timezone,\n );\n return { inQuietHours: true, nextActiveTime: nextActive };\n }\n }\n return { inQuietHours: false };\n };\n\n let initialCheck = checkWindowAt(fromDate);\n if (!initialCheck || !initialCheck.inQuietHours) {\n return { inQuietHours: false };\n }\n\n // Chained / overlapping quiet hours intervals\n let candidateTime = initialCheck.nextActiveTime!;\n for (let i = 0; i < 10; i++) {\n const subsequentCheck = checkWindowAt(candidateTime);\n if (subsequentCheck && subsequentCheck.inQuietHours && subsequentCheck.nextActiveTime) {\n if (subsequentCheck.nextActiveTime.getTime() <= candidateTime.getTime()) {\n break;\n }\n candidateTime = subsequentCheck.nextActiveTime;\n } else {\n break;\n }\n }\n\n return { inQuietHours: true, nextActiveTime: candidateTime };\n}\n\n// ─── Bootstrap ─────────────────────────────────────────────────────────────\n\nloadEnv();\nconst config = readBaseConfig();\n\nlet logger: ReturnType<typeof createLogger>;\nlet redis: RedisClient;\nlet sql: any;\nlet db: any;\nlet templateRepo: TemplateRepository;\n\nlet templateCache: TemplateCache;\n\nlet consumer: StreamConsumer;\nlet pendingScanner: PendingMessageScanner;\nlet worker: BaseWorker;\nlet healthInterval: NodeJS.Timeout | null = null;\n\nexport interface EngineWorkerOptions extends WorkerOptions {\n registry: any;\n idempotency: any;\n throttle: any;\n projectSettings: ProjectSettingsCache;\n redis: Redis;\n templateCache: TemplateCache;\n aiPendingProducer: any;\n scheduledProducer: any;\n outboundProducers: any;\n globalEmitter: any;\n contactRepo: any;\n db: any;\n}\n\nexport class EngineWorker extends BaseWorker {\n private readonly registry: any;\n private readonly idempotency: any;\n private readonly throttle: any;\n private readonly projectSettings: ProjectSettingsCache;\n private readonly redisCli: Redis;\n private readonly templateCache: TemplateCache;\n private readonly aiPendingProducer: any;\n private readonly scheduledProducer: any;\n private readonly outboundProducers: any;\n private readonly globalEmitter: any;\n private readonly contactRepo: any;\n private readonly db: any;\n\n constructor(options: EngineWorkerOptions) {\n super(options);\n this.registry = options.registry;\n this.idempotency = options.idempotency;\n this.throttle = options.throttle;\n this.projectSettings = options.projectSettings;\n this.redisCli = options.redis;\n this.templateCache = options.templateCache;\n this.aiPendingProducer = options.aiPendingProducer;\n this.scheduledProducer = options.scheduledProducer;\n this.outboundProducers = options.outboundProducers;\n this.globalEmitter = options.globalEmitter;\n this.contactRepo = options.contactRepo;\n this.db = options.db;\n }\n\n private readonly contactsLoader = new DataLoader<\n { projectId: string; recipientId: string },\n any[]\n >(async (keys) => {\n const byProject = new Map<string, string[]>();\n for (const key of keys) {\n if (!byProject.has(key.projectId)) byProject.set(key.projectId, []);\n byProject.get(key.projectId)!.push(key.recipientId);\n }\n\n const resultsByProjectAndUser = new Map<string, Map<string, any[]>>();\n for (const [projectId, userIds] of byProject) {\n const activeContactsMap = await this.contactRepo.findActiveByUserIds(projectId, userIds);\n resultsByProjectAndUser.set(projectId, activeContactsMap);\n }\n\n return keys.map((key) => {\n const projectMap = resultsByProjectAndUser.get(key.projectId);\n if (!projectMap) return [];\n return projectMap.get(key.recipientId) || [];\n });\n });\n\n /**\n * Suppressed destinations for one (project, channel), as a normalised set.\n *\n * Loaded per project+channel rather than per address: a campaign is thousands\n * of messages against one channel, so this collapses to a single query for\n * the whole batch. Cached for the loader's lifetime of a tick, which means a\n * suppression written mid-batch takes effect on the next batch — acceptable,\n * since the webhook that writes it is itself minutes behind the send.\n */\n private readonly suppressionsLoader = new DataLoader<\n { projectId: string; channel: string },\n Set<string>\n >(async (keys) => {\n const results = new Map<string, Set<string>>();\n for (const key of keys) {\n const cacheKey = `${key.projectId}:${key.channel}`;\n if (results.has(cacheKey)) continue;\n try {\n const rows = await this.db\n .select({ target: suppressions.target })\n .from(suppressions)\n .where(\n and(\n eq(suppressions.projectId, key.projectId),\n eq(suppressions.channel, key.channel as any),\n ),\n );\n results.set(\n cacheKey,\n new Set(rows.map((r: { target: string }) => normaliseTarget(r.target))),\n );\n } catch (err) {\n // A suppression lookup that fails must not silently become \"nothing\n // is suppressed\" — that would resume mailing people who opted out.\n this.logger.error(\n { err, projectId: key.projectId, channel: key.channel },\n \"suppression lookup failed — holding message\",\n );\n throw err;\n }\n }\n return keys.map((key) => results.get(`${key.projectId}:${key.channel}`) ?? new Set<string>());\n });\n\n async process(message: StreamMessage): Promise<void> {\n const { event } = message;\n\n const payloadResult = this.registry.safeParsePayload(\"notification.enriched\", event.payload);\n if (!payloadResult.success) {\n this.logger.warn(\n { messageId: message.id, issues: payloadResult.error.issues },\n \"invalid notification.enriched payload — skipping\",\n );\n return;\n }\n\n const enriched = payloadResult.data as NotificationEnrichedPayload;\n\n // Idempotency\n const idempotencyKey = `${enriched.rawEventId}:${enriched.recipientId}:${enriched.channel}`;\n let customTtl: number | undefined;\n if (enriched.scheduledAt) {\n const msUntil = new Date(enriched.scheduledAt).getTime() - Date.now();\n if (msUntil > 0) {\n // base 24h (86400) + schedule time\n customTtl = 86400 + Math.ceil(msUntil / 1000);\n }\n }\n\n if (!(await this.idempotency.checkAndMark(idempotencyKey, 60))) {\n this.logger.debug({ messageId: message.id, eventId: event.id }, \"duplicate — skipping\");\n return;\n }\n\n try {\n // Opt-in check\n if (enriched.recipient.preferences.optedOut) {\n this.logger.info(\n { messageId: message.id, recipientId: enriched.recipientId, eventType: event.type },\n \"user opted out — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"user_opted_out\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n if (enriched.recipient.preferences.channels?.includes(enriched.channel)) {\n this.logger.info(\n { messageId: message.id, recipientId: enriched.recipientId, channel: enriched.channel },\n \"user disabled notification channel — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"channel_disabled\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n // Quiet hours check\n const qh = enriched.recipient.preferences.quietHours;\n if (qh && qh.length > 0 && enriched.priority !== \"critical\") {\n const qhResult = isInQuietHours(enriched.recipient.timezone, qh);\n if (qhResult.inQuietHours && qhResult.nextActiveTime) {\n this.logger.info(\n {\n messageId: message.id,\n recipientId: enriched.recipientId,\n nextActiveTime: qhResult.nextActiveTime.toISOString(),\n },\n \"user is in quiet hours — deferring notification\",\n );\n enriched.scheduledAt = qhResult.nextActiveTime.toISOString();\n }\n }\n\n // Rate limit. Per-project overrides win over the process-wide default;\n // a lookup failure must not drop the notification, so fall back rather\n // than propagate.\n let projectThrottle: { throttleLimit: number | null; throttleWindowHours: number | null } = {\n throttleLimit: null,\n throttleWindowHours: null,\n };\n try {\n projectThrottle = await this.projectSettings.get(enriched.projectId);\n } catch (err) {\n this.logger.warn(\n { err, projectId: enriched.projectId },\n \"could not read project throttle settings — falling back to the global default\",\n );\n }\n\n const throttleResult = await this.throttle.check(\n enriched.projectId,\n enriched.recipientId,\n enriched.priority,\n {\n limit: projectThrottle.throttleLimit,\n windowHours: projectThrottle.throttleWindowHours,\n scheduledAt: enriched.scheduledAt,\n },\n );\n if (!throttleResult.allowed) {\n this.logger.info(\n {\n messageId: message.id,\n recipientId: enriched.recipientId,\n count: throttleResult.count,\n limit: throttleResult.limit,\n priority: enriched.priority,\n },\n \"user throttled — dropping\",\n );\n this.globalEmitter.emit(\n \"notification:throttled\",\n enriched.recipientId,\n throttleResult.count,\n );\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n // Gather AI Prompts\n // Gather AI Prompts\n let dbTemplate = null;\n if (enriched.templateId) {\n dbTemplate = await this.templateCache.getCachedTemplate(\n enriched.projectId,\n enriched.templateId,\n );\n if (!dbTemplate) {\n this.logger.warn(\n { messageId: message.id, templateId: enriched.templateId },\n \"template not found — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"template_not_found\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n }\n const aiPrompts = {\n ...(dbTemplate?.aiPrompts ?? {}),\n ...(enriched.aiPrompts ?? {}),\n };\n\n // Drives whether this message gets an unsubscribe header, and what the\n // resulting opt-out applies to.\n const templateTopics: string[] = dbTemplate?.topics ?? [];\n\n if (Object.keys(aiPrompts).length > 0) {\n const aiPendingPayload = {\n projectId: enriched.projectId,\n enrichedEventId: event.id,\n recipientId: enriched.recipientId,\n channel: enriched.channel,\n priority: enriched.priority,\n templateId: enriched.templateId,\n templateVariables: enriched.templateVariables,\n recipient: enriched.recipient,\n aiPrompts,\n scheduledAt: enriched.scheduledAt,\n fallbackChain: enriched.fallbackChain,\n };\n\n const aiPendingEnvelope = buildStreamEvent(\n \"notification.ai_pending\",\n aiPendingPayload as Record<string, unknown>,\n \"engine\",\n event.metadata.traceId,\n );\n\n await this.aiPendingProducer.publish(aiPendingEnvelope);\n this.logger.info(\n {\n messageId: message.id,\n eventId: event.id,\n recipientId: enriched.recipientId,\n traceId: event.metadata.traceId,\n },\n \"task routed to AI worker\",\n );\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n // Render template\n const rendered = renderWithTemplate(dbTemplate, enriched.templateVariables);\n\n const allContacts = await this.contactsLoader.load({\n projectId: enriched.projectId,\n recipientId: enriched.recipientId,\n });\n const activeContacts = allContacts.filter(\n (c: any) => c.channel === enriched.channel && c.active,\n );\n\n if (activeContacts.length === 0) {\n this.logger.info(\n { messageId: message.id, recipientId: enriched.recipientId, channel: enriched.channel },\n \"no active contacts for channel — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"no_active_contacts\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n const suppressedTargets = await this.suppressionsLoader.load({\n projectId: enriched.projectId,\n channel: enriched.channel,\n });\n\n for (const contact of activeContacts) {\n if (contact.preferences?.optedOut) {\n continue;\n }\n\n // A suppression outranks every other gate, `critical` included: it\n // records that the person asked us to stop, or that the address is\n // dead. Sending anyway is what gets a domain blocked.\n if (contact.target && suppressedTargets.has(normaliseTarget(contact.target))) {\n this.logger.info(\n {\n messageId: message.id,\n recipientId: enriched.recipientId,\n channel: enriched.channel,\n },\n \"destination suppressed — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"suppressed\",\n });\n continue;\n }\n\n const taskId = `${enriched.rawEventId}:${contact.id || randomUUID()}`;\n const resolvedDestination = contact.target;\n\n // One-click unsubscribe headers, but only on mail that should carry\n // them. A template with no topic is transactional by this codebase's\n // own convention — a password reset, a receipt — and putting an\n // unsubscribe button on those invites people to switch off mail they\n // actually need, with no topic to scope the opt-out to anyway.\n if (\n enriched.channel === \"email\" &&\n templateTopics.length > 0 &&\n !config.UNSUBSCRIBE_SECRET\n ) {\n this.logger.warn(\n { projectId: enriched.projectId, recipientId: enriched.recipientId },\n \"UNSUBSCRIBE_SECRET is not configured — email sent without RFC 8058 one-click unsubscribe headers\",\n );\n }\n\n const unsubscribeHeaders =\n enriched.channel === \"email\" &&\n templateTopics.length > 0 &&\n config.UNSUBSCRIBE_SECRET &&\n config.PUBLIC_URL &&\n resolvedDestination\n ? buildUnsubscribeHeaders({\n claim: {\n projectId: enriched.projectId,\n userId: enriched.recipientId,\n channel: enriched.channel,\n target: resolvedDestination,\n topics: templateTopics,\n },\n secret: config.UNSUBSCRIBE_SECRET,\n publicUrl: config.PUBLIC_URL,\n })\n : undefined;\n\n const taskPayload: NotificationDispatchedPayload = {\n projectId: enriched.projectId,\n taskId,\n enrichedEventId: event.id,\n recipientId: enriched.recipientId,\n channel: enriched.channel,\n priority: enriched.priority,\n templateId: enriched.templateId,\n templateVariables: enriched.templateVariables,\n aiPrompts: enriched.aiPrompts,\n recipient: enriched.recipient,\n renderedContent: rendered,\n destination: resolvedDestination,\n deliveryOptions: {\n maxAttempts: 3,\n timeoutMs: 10_000,\n ...(unsubscribeHeaders ? { headers: unsubscribeHeaders } : {}),\n },\n fallbackChain: enriched.fallbackChain,\n campaignId: enriched.campaignId,\n };\n\n const envelope = buildStreamEvent(\n \"notification.dispatched\",\n taskPayload as Record<string, unknown>,\n \"engine\",\n event.metadata.traceId,\n );\n\n // Route by scheduledAt\n const now = Date.now();\n const scheduledAt = enriched.scheduledAt ? new Date(enriched.scheduledAt).getTime() : now;\n\n if (scheduledAt > now) {\n await this.db\n .insert(scheduledPayloads)\n .values({\n taskId,\n payload: {\n ...taskPayload,\n scheduledAt: enriched.scheduledAt,\n },\n })\n .onConflictDoNothing();\n\n const scheduledEnvelope = buildStreamEvent(\n \"notification.scheduled\",\n {\n projectId: enriched.projectId,\n enrichedEventId: event.id,\n taskId,\n scheduledAt: enriched.scheduledAt!,\n },\n \"engine\",\n event.metadata.traceId,\n );\n\n await this.scheduledProducer.publish(scheduledEnvelope);\n this.logger.info(\n {\n messageId: message.id,\n taskId,\n scheduledAt: enriched.scheduledAt,\n traceId: event.metadata.traceId,\n },\n \"task scheduled and payload cached\",\n );\n } else {\n const p = getPriorityBucket(enriched.priority);\n const outboundProducer = this.outboundProducers[p] ?? this.outboundProducers[\"normal\"]!;\n\n await outboundProducer.publish(envelope);\n this.logger.info(\n {\n messageId: message.id,\n taskId,\n recipientId: enriched.recipientId,\n traceId: event.metadata.traceId,\n },\n \"task dispatched\",\n );\n }\n }\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n } catch (err) {\n await this.idempotency.unmark(idempotencyKey).catch(() => {});\n throw err;\n }\n }\n}\n\nlet subscriber: any = null;\n\nexport async function startEngineWorker() {\n logger = createLogger({ name: \"engine\", level: config.LOG_LEVEL });\n redis = new RedisClient({ url: config.REDIS_URL, name: \"engine\", logger });\n const dbData = createDatabase({ url: config.DATABASE_URL, applicationName: \"engine\", logger });\n sql = dbData.sql;\n db = dbData.db;\n templateRepo = new TemplateRepository(db);\n templateCache = new TemplateCache(templateRepo);\n const contactRepo = new ContactRepository(db);\n consumer = new StreamConsumer({\n redis: redis.native,\n stream: ENRICHED_STREAMS as unknown as StreamName[],\n group: CONSUMER_GROUPS.ENGINE,\n consumer: `engine-${process.pid}`,\n dlqStream: STREAMS.DEAD_LETTER,\n batchSize: config.WORKER_CONCURRENCY,\n logger,\n });\n\n pendingScanner = new PendingMessageScanner({\n redis: redis.native,\n stream: ENRICHED_STREAMS as unknown as StreamName[],\n group: CONSUMER_GROUPS.ENGINE,\n consumer: `engine-${process.pid}`,\n logger,\n });\n\n const outboundProducers = {\n critical: new StreamProducer({\n redis: redis.native,\n stream: STREAMS.OUTBOUND_CRITICAL,\n logger,\n }),\n normal: new StreamProducer({ redis: redis.native, stream: STREAMS.OUTBOUND_NORMAL, logger }),\n low: new StreamProducer({ redis: redis.native, stream: STREAMS.OUTBOUND_LOW, logger }),\n };\n\n const scheduledProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.SCHEDULED,\n logger,\n });\n\n const aiPendingProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.AI_PENDING,\n logger,\n });\n\n const idempotency = new IdempotencyGuard({\n redis: redis.native,\n keyPrefix: \"notif:processed:engine\",\n ttlSeconds: 86_400,\n });\n\n const throttle = new UserThrottle({\n redis: redis.native,\n maxPerHour: parseInt(process.env.RATE_LIMIT_PER_HOUR || \"100\", 10),\n });\n\n // Per-project throttle overrides, cached because this is read once per\n // notification. Stale entries expire on their own; the pub/sub subscriber\n // below only makes an admin's change take effect sooner.\n const projectRepo = new ProjectRepository(db);\n const projectSettings = new ProjectSettingsCache((projectId) =>\n projectRepo.findThrottleSettings(projectId),\n );\n\n // ─── Stage 2: Decision Engine ───────────────────────────────────────────────\n //\n // Pipeline:\n // 1. Parse payload as notification.enriched\n // 2. Idempotency check\n // 3. Check user opt-in (from enriched recipient.preferences)\n // 4. Apply per-user hourly rate limit\n // 5. Render template using user locale\n // 6. Route: if scheduledAt is future → SCHEDULED; else → OUTBOUND\n\n worker = new EngineWorker({\n consumer,\n pendingScanner,\n logger,\n concurrency: config.WORKER_CONCURRENCY,\n registry,\n idempotency,\n throttle,\n projectSettings,\n redis: redis.native,\n templateCache,\n aiPendingProducer,\n scheduledProducer,\n outboundProducers,\n globalEmitter,\n contactRepo,\n db,\n });\n\n subscriber = redis.native.duplicate();\n await subscriber.subscribe(\n PUBSUB_CHANNELS.TEMPLATE_INVALIDATED,\n PUBSUB_CHANNELS.PROJECT_INVALIDATED,\n );\n subscriber.on(\"message\", (channel: string, message: string) => {\n if (channel === PUBSUB_CHANNELS.TEMPLATE_INVALIDATED) {\n templateCache.invalidateKey(message);\n logger.info({ cacheKey: message }, \"invalidated template cache\");\n } else if (channel === PUBSUB_CHANNELS.PROJECT_INVALIDATED) {\n projectSettings.invalidate(message);\n logger.info({ projectId: message }, \"invalidated project settings cache\");\n }\n });\n\n // ─── Health check interval ──────────────────────────────────────────────────\n\n healthInterval = startHealthReporter(\"engine\", worker, redis, logger);\n\n logger.info({ env: config.NODE_ENV }, \"engine starting\");\n await worker.start();\n}\n\n// ─── Shutdown ──────────────────────────────────────────────────────────────\n\nexport async function stopEngineWorker(): Promise<void> {\n logger?.info(\"shutdown initiated\");\n if (healthInterval) {\n clearInterval(healthInterval);\n healthInterval = null;\n }\n if (subscriber) {\n subscriber.disconnect();\n subscriber = null;\n }\n if (worker) await worker.stop();\n if (sql) await sql.end();\n if (redis) await redis.disconnect();\n logger?.info(\"engine stopped\");\n}\n"],"mappings":";;;;AAuCA,SAAS,eACP,MACA,OACA,KACA,MACA,QACA,QACA,UACM;CACN,IAAI,QAAQ,KAAK,IAAI,MAAM,QAAQ,GAAG,KAAK,MAAM,QAAQ,MAAM;CAC/D,MAAM,YAAY,IAAI,KAAK,eAAe,SAAS;EACjD,UAAU;EACV,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;CACV,CAAC;CAED,KAAK,IAAI,OAAO,GAAG,OAAO,GAAG,QAAQ;EACnC,MAAM,QAAQ,UAAU,cAAc,IAAI,KAAK,KAAK,CAAC;EACrD,MAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE;EAC7E,MAAM,SAAS,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,OAAO,CAAC,EAAE,SAAS,KAAK,EAAE;EAC/E,MAAM,OAAO,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,KAAK,CAAC,EAAE,SAAS,KAAK,EAAE;EAC3E,MAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE;EAC7E,MAAM,OAAO,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,QAAQ,CAAC,EAAE,SAAS,KAAK,EAAE;EAC9E,MAAM,OAAO,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,QAAQ,CAAC,EAAE,SAAS,KAAK,EAAE;EAI9E,MAAM,OAFW,KAAK,IAAI,MAAM,QAAQ,GAAG,KAAK,MAAM,QAAQ,MAE1C,IADH,KAAK,IAAI,OAAO,SAAS,GAAG,MAAM,OAAO,MAAM,IACjC;EAC/B,IAAI,SAAS,GAAG;EAChB,SAAS;CACX;CACA,OAAO,IAAI,KAAK,KAAK;AACvB;AAEA,SAAgB,eACd,UACA,YACA,2BAAiB,IAAI,KAAK,GACwB;CAClD,IAAI,CAAC,cAAc,WAAW,WAAW,GACvC,OAAO,EAAE,cAAc,MAAM;CAG/B,MAAM,iBAAiB,SAAe;EACpC,IAAI;EACJ,IAAI;GAWF,QAAQ,IAVc,KAAK,eAAe,SAAS;IACjD,UAAU;IACV,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;GACV,CACgB,CAAC,CAAC,cAAc,IAAI;EACtC,QAAQ;GACN,OAAO;EACT;EAEA,MAAM,OAAO,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE;EAC5E,MAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,OAAO,CAAC,EAAE,SAAS,KAAK,EAAE;EAC9E,MAAM,MAAM,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,KAAK,CAAC,EAAE,SAAS,KAAK,EAAE;EAC1E,MAAM,cAAc,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE;EACnF,MAAM,aAAa,SAAS,MAAM,MAAM,MAAM,EAAE,SAAS,QAAQ,CAAC,EAAE,SAAS,KAAK,EAAE;EAEpF,MAAM,iBAAiB,cAAc,KAAK;EAE1C,KAAK,MAAM,UAAU,YAAY;GAC/B,MAAM,CAAC,QAAQ,UAAU,OAAO,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;GAC3D,MAAM,CAAC,MAAM,QAAQ,OAAO,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;GAErD,IAAI,WAAW,KAAA,KAAa,WAAW,KAAA,KAAa,SAAS,KAAA,KAAa,SAAS,KAAA,GACjF;GAEF,MAAM,eAAe,SAAS,KAAK;GACnC,MAAM,aAAa,OAAO,KAAK;GAE/B,IAAI,WAAW;GACf,IAAI,gBAAgB,YAClB,WAAW,kBAAkB,gBAAgB,iBAAiB;QAE9D,WAAW,kBAAkB,gBAAgB,iBAAiB;GAGhE,IAAI,UAAU;IACZ,IAAI,aAAa;IACjB,IAAI,cAAc;IAClB,IAAI,YAAY;IAEhB,IAAI,kBAAkB,YAAY;KAChC,MAAM,UAAU,IAAI,KAAK,KAAK,IAAI,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC;KAC3D,aAAa,QAAQ,eAAe;KACpC,cAAc,QAAQ,YAAY,IAAI;KACtC,YAAY,QAAQ,WAAW;IACjC;IAWA,OAAO;KAAE,cAAc;KAAM,gBATV,eACjB,YACA,aACA,WACA,MACA,MACA,GACA,QAEoD;IAAE;GAC1D;EACF;EACA,OAAO,EAAE,cAAc,MAAM;CAC/B;CAEA,IAAI,eAAe,cAAc,QAAQ;CACzC,IAAI,CAAC,gBAAgB,CAAC,aAAa,cACjC,OAAO,EAAE,cAAc,MAAM;CAI/B,IAAI,gBAAgB,aAAa;CACjC,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,kBAAkB,cAAc,aAAa;EACnD,IAAI,mBAAmB,gBAAgB,gBAAgB,gBAAgB,gBAAgB;GACrF,IAAI,gBAAgB,eAAe,QAAQ,KAAK,cAAc,QAAQ,GACpE;GAEF,gBAAgB,gBAAgB;EAClC,OACE;CAEJ;CAEA,OAAO;EAAE,cAAc;EAAM,gBAAgB;CAAc;AAC7D;AAIA,QAAQ;AACR,MAAM,SAAS,eAAe;AAE9B,IAAI;AACJ,IAAI;AACJ,IAAIA;AACJ,IAAI;AACJ,IAAI;AAEJ,IAAI;AAEJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI,iBAAwC;AAiB5C,IAAa,eAAb,cAAkC,WAAW;CAC3C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAA8B;EACxC,MAAM,OAAO;EACb,KAAK,WAAW,QAAQ;EACxB,KAAK,cAAc,QAAQ;EAC3B,KAAK,WAAW,QAAQ;EACxB,KAAK,kBAAkB,QAAQ;EAC/B,KAAK,WAAW,QAAQ;EACxB,KAAK,gBAAgB,QAAQ;EAC7B,KAAK,oBAAoB,QAAQ;EACjC,KAAK,oBAAoB,QAAQ;EACjC,KAAK,oBAAoB,QAAQ;EACjC,KAAK,gBAAgB,QAAQ;EAC7B,KAAK,cAAc,QAAQ;EAC3B,KAAK,KAAK,QAAQ;CACpB;CAEA,iBAAkC,IAAI,WAGpC,OAAO,SAAS;EAChB,MAAM,4BAAY,IAAI,IAAsB;EAC5C,KAAK,MAAM,OAAO,MAAM;GACtB,IAAI,CAAC,UAAU,IAAI,IAAI,SAAS,GAAG,UAAU,IAAI,IAAI,WAAW,CAAC,CAAC;GAClE,UAAU,IAAI,IAAI,SAAS,CAAC,CAAE,KAAK,IAAI,WAAW;EACpD;EAEA,MAAM,0CAA0B,IAAI,IAAgC;EACpE,KAAK,MAAM,CAAC,WAAW,YAAY,WAAW;GAC5C,MAAM,oBAAoB,MAAM,KAAK,YAAY,oBAAoB,WAAW,OAAO;GACvF,wBAAwB,IAAI,WAAW,iBAAiB;EAC1D;EAEA,OAAO,KAAK,KAAK,QAAQ;GACvB,MAAM,aAAa,wBAAwB,IAAI,IAAI,SAAS;GAC5D,IAAI,CAAC,YAAY,OAAO,CAAC;GACzB,OAAO,WAAW,IAAI,IAAI,WAAW,KAAK,CAAC;EAC7C,CAAC;CACH,CAAC;;;;;;;;;;CAWD,qBAAsC,IAAI,WAGxC,OAAO,SAAS;EAChB,MAAM,0BAAU,IAAI,IAAyB;EAC7C,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,WAAW,GAAG,IAAI,UAAU,GAAG,IAAI;GACzC,IAAI,QAAQ,IAAI,QAAQ,GAAG;GAC3B,IAAI;IACF,MAAM,OAAO,MAAM,KAAK,GACrB,OAAO,EAAE,QAAQ,aAAa,OAAO,CAAC,CAAC,CACvC,KAAK,YAAY,CAAC,CAClB,MACC,IACE,GAAG,aAAa,WAAW,IAAI,SAAS,GACxC,GAAG,aAAa,SAAS,IAAI,OAAc,CAC7C,CACF;IACF,QAAQ,IACN,UACA,IAAI,IAAI,KAAK,KAAK,MAA0B,gBAAgB,EAAE,MAAM,CAAC,CAAC,CACxE;GACF,SAAS,KAAK;IAGZ,KAAK,OAAO,MACV;KAAE;KAAK,WAAW,IAAI;KAAW,SAAS,IAAI;IAAQ,GACtD,6CACF;IACA,MAAM;GACR;EACF;EACA,OAAO,KAAK,KAAK,QAAQ,QAAQ,IAAI,GAAG,IAAI,UAAU,GAAG,IAAI,SAAS,qBAAK,IAAI,IAAY,CAAC;CAC9F,CAAC;CAED,MAAM,QAAQ,SAAuC;EACnD,MAAM,EAAE,UAAU;EAElB,MAAM,gBAAgB,KAAK,SAAS,iBAAiB,yBAAyB,MAAM,OAAO;EAC3F,IAAI,CAAC,cAAc,SAAS;GAC1B,KAAK,OAAO,KACV;IAAE,WAAW,QAAQ;IAAI,QAAQ,cAAc,MAAM;GAAO,GAC5D,kDACF;GACA;EACF;EAEA,MAAM,WAAW,cAAc;EAG/B,MAAM,iBAAiB,GAAG,SAAS,WAAW,GAAG,SAAS,YAAY,GAAG,SAAS;EAClF,IAAI;EACJ,IAAI,SAAS,aAAa;GACxB,MAAM,UAAU,IAAI,KAAK,SAAS,WAAW,CAAC,CAAC,QAAQ,IAAI,KAAK,IAAI;GACpE,IAAI,UAAU,GAEZ,YAAY,QAAQ,KAAK,KAAK,UAAU,GAAI;EAEhD;EAEA,IAAI,CAAE,MAAM,KAAK,YAAY,aAAa,gBAAgB,EAAE,GAAI;GAC9D,KAAK,OAAO,MAAM;IAAE,WAAW,QAAQ;IAAI,SAAS,MAAM;GAAG,GAAG,sBAAsB;GACtF;EACF;EAEA,IAAI;GAEF,IAAI,SAAS,UAAU,YAAY,UAAU;IAC3C,KAAK,OAAO,KACV;KAAE,WAAW,QAAQ;KAAI,aAAa,SAAS;KAAa,WAAW,MAAM;IAAK,GAClF,2BACF;IACA,KAAK,cAAc,KAAK,wBAAwB;KAC9C,WAAW,SAAS;KACpB,SAAS,MAAM;KACf,aAAa,SAAS;KACtB,QAAQ;IACV,CAAC;IACD,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;IAC9D;GACF;GAEA,IAAI,SAAS,UAAU,YAAY,UAAU,SAAS,SAAS,OAAO,GAAG;IACvE,KAAK,OAAO,KACV;KAAE,WAAW,QAAQ;KAAI,aAAa,SAAS;KAAa,SAAS,SAAS;IAAQ,GACtF,+CACF;IACA,KAAK,cAAc,KAAK,wBAAwB;KAC9C,WAAW,SAAS;KACpB,SAAS,MAAM;KACf,aAAa,SAAS;KACtB,QAAQ;IACV,CAAC;IACD,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;IAC9D;GACF;GAGA,MAAM,KAAK,SAAS,UAAU,YAAY;GAC1C,IAAI,MAAM,GAAG,SAAS,KAAK,SAAS,aAAa,YAAY;IAC3D,MAAM,WAAW,eAAe,SAAS,UAAU,UAAU,EAAE;IAC/D,IAAI,SAAS,gBAAgB,SAAS,gBAAgB;KACpD,KAAK,OAAO,KACV;MACE,WAAW,QAAQ;MACnB,aAAa,SAAS;MACtB,gBAAgB,SAAS,eAAe,YAAY;KACtD,GACA,iDACF;KACA,SAAS,cAAc,SAAS,eAAe,YAAY;IAC7D;GACF;GAKA,IAAI,kBAAwF;IAC1F,eAAe;IACf,qBAAqB;GACvB;GACA,IAAI;IACF,kBAAkB,MAAM,KAAK,gBAAgB,IAAI,SAAS,SAAS;GACrE,SAAS,KAAK;IACZ,KAAK,OAAO,KACV;KAAE;KAAK,WAAW,SAAS;IAAU,GACrC,+EACF;GACF;GAEA,MAAM,iBAAiB,MAAM,KAAK,SAAS,MACzC,SAAS,WACT,SAAS,aACT,SAAS,UACT;IACE,OAAO,gBAAgB;IACvB,aAAa,gBAAgB;IAC7B,aAAa,SAAS;GACxB,CACF;GACA,IAAI,CAAC,eAAe,SAAS;IAC3B,KAAK,OAAO,KACV;KACE,WAAW,QAAQ;KACnB,aAAa,SAAS;KACtB,OAAO,eAAe;KACtB,OAAO,eAAe;KACtB,UAAU,SAAS;IACrB,GACA,2BACF;IACA,KAAK,cAAc,KACjB,0BACA,SAAS,aACT,eAAe,KACjB;IACA,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;IAC9D;GACF;GAIA,IAAI,aAAa;GACjB,IAAI,SAAS,YAAY;IACvB,aAAa,MAAM,KAAK,cAAc,kBACpC,SAAS,WACT,SAAS,UACX;IACA,IAAI,CAAC,YAAY;KACf,KAAK,OAAO,KACV;MAAE,WAAW,QAAQ;MAAI,YAAY,SAAS;KAAW,GACzD,+BACF;KACA,KAAK,cAAc,KAAK,wBAAwB;MAC9C,WAAW,SAAS;MACpB,SAAS,MAAM;MACf,aAAa,SAAS;MACtB,QAAQ;KACV,CAAC;KACD,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;KAC9D;IACF;GACF;GACA,MAAM,YAAY;IAChB,GAAI,YAAY,aAAa,CAAC;IAC9B,GAAI,SAAS,aAAa,CAAC;GAC7B;GAIA,MAAM,iBAA2B,YAAY,UAAU,CAAC;GAExD,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,SAAS,GAAG;IACrC,MAAM,mBAAmB;KACvB,WAAW,SAAS;KACpB,iBAAiB,MAAM;KACvB,aAAa,SAAS;KACtB,SAAS,SAAS;KAClB,UAAU,SAAS;KACnB,YAAY,SAAS;KACrB,mBAAmB,SAAS;KAC5B,WAAW,SAAS;KACpB;KACA,aAAa,SAAS;KACtB,eAAe,SAAS;IAC1B;IAEA,MAAM,oBAAoB,iBACxB,2BACA,kBACA,UACA,MAAM,SAAS,OACjB;IAEA,MAAM,KAAK,kBAAkB,QAAQ,iBAAiB;IACtD,KAAK,OAAO,KACV;KACE,WAAW,QAAQ;KACnB,SAAS,MAAM;KACf,aAAa,SAAS;KACtB,SAAS,MAAM,SAAS;IAC1B,GACA,0BACF;IACA,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;IAC9D;GACF;GAGA,MAAM,WAAW,mBAAmB,YAAY,SAAS,iBAAiB;GAM1E,MAAM,kBAAiB,MAJG,KAAK,eAAe,KAAK;IACjD,WAAW,SAAS;IACpB,aAAa,SAAS;GACxB,CAAC,EAAA,CACkC,QAChC,MAAW,EAAE,YAAY,SAAS,WAAW,EAAE,MAClD;GAEA,IAAI,eAAe,WAAW,GAAG;IAC/B,KAAK,OAAO,KACV;KAAE,WAAW,QAAQ;KAAI,aAAa,SAAS;KAAa,SAAS,SAAS;IAAQ,GACtF,2CACF;IACA,KAAK,cAAc,KAAK,wBAAwB;KAC9C,WAAW,SAAS;KACpB,SAAS,MAAM;KACf,aAAa,SAAS;KACtB,QAAQ;IACV,CAAC;IACD,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;IAC9D;GACF;GAEA,MAAM,oBAAoB,MAAM,KAAK,mBAAmB,KAAK;IAC3D,WAAW,SAAS;IACpB,SAAS,SAAS;GACpB,CAAC;GAED,KAAK,MAAM,WAAW,gBAAgB;IACpC,IAAI,QAAQ,aAAa,UACvB;IAMF,IAAI,QAAQ,UAAU,kBAAkB,IAAI,gBAAgB,QAAQ,MAAM,CAAC,GAAG;KAC5E,KAAK,OAAO,KACV;MACE,WAAW,QAAQ;MACnB,aAAa,SAAS;MACtB,SAAS,SAAS;KACpB,GACA,mCACF;KACA,KAAK,cAAc,KAAK,wBAAwB;MAC9C,WAAW,SAAS;MACpB,SAAS,MAAM;MACf,aAAa,SAAS;MACtB,QAAQ;KACV,CAAC;KACD;IACF;IAEA,MAAM,SAAS,GAAG,SAAS,WAAW,GAAG,QAAQ,MAAM,WAAW;IAClE,MAAM,sBAAsB,QAAQ;IAOpC,IACE,SAAS,YAAY,WACrB,eAAe,SAAS,KACxB,CAAC,OAAO,oBAER,KAAK,OAAO,KACV;KAAE,WAAW,SAAS;KAAW,aAAa,SAAS;IAAY,GACnE,kGACF;IAGF,MAAM,qBACJ,SAAS,YAAY,WACrB,eAAe,SAAS,KACxB,OAAO,sBACP,OAAO,cACP,sBACI,wBAAwB;KACtB,OAAO;MACL,WAAW,SAAS;MACpB,QAAQ,SAAS;MACjB,SAAS,SAAS;MAClB,QAAQ;MACR,QAAQ;KACV;KACA,QAAQ,OAAO;KACf,WAAW,OAAO;IACpB,CAAC,IACD,KAAA;IAEN,MAAM,cAA6C;KACjD,WAAW,SAAS;KACpB;KACA,iBAAiB,MAAM;KACvB,aAAa,SAAS;KACtB,SAAS,SAAS;KAClB,UAAU,SAAS;KACnB,YAAY,SAAS;KACrB,mBAAmB,SAAS;KAC5B,WAAW,SAAS;KACpB,WAAW,SAAS;KACpB,iBAAiB;KACjB,aAAa;KACb,iBAAiB;MACf,aAAa;MACb,WAAW;MACX,GAAI,qBAAqB,EAAE,SAAS,mBAAmB,IAAI,CAAC;KAC9D;KACA,eAAe,SAAS;KACxB,YAAY,SAAS;IACvB;IAEA,MAAM,WAAW,iBACf,2BACA,aACA,UACA,MAAM,SAAS,OACjB;IAGA,MAAM,MAAM,KAAK,IAAI;IAGrB,KAFoB,SAAS,cAAc,IAAI,KAAK,SAAS,WAAW,CAAC,CAAC,QAAQ,IAAI,OAEpE,KAAK;KACrB,MAAM,KAAK,GACR,OAAO,iBAAiB,CAAC,CACzB,OAAO;MACN;MACA,SAAS;OACP,GAAG;OACH,aAAa,SAAS;MACxB;KACF,CAAC,CAAC,CACD,oBAAoB;KAEvB,MAAM,oBAAoB,iBACxB,0BACA;MACE,WAAW,SAAS;MACpB,iBAAiB,MAAM;MACvB;MACA,aAAa,SAAS;KACxB,GACA,UACA,MAAM,SAAS,OACjB;KAEA,MAAM,KAAK,kBAAkB,QAAQ,iBAAiB;KACtD,KAAK,OAAO,KACV;MACE,WAAW,QAAQ;MACnB;MACA,aAAa,SAAS;MACtB,SAAS,MAAM,SAAS;KAC1B,GACA,mCACF;IACF,OAAO;KACL,MAAM,IAAI,kBAAkB,SAAS,QAAQ;KAG7C,OAFyB,KAAK,kBAAkB,MAAM,KAAK,kBAAkB,UAAA,CAEtD,QAAQ,QAAQ;KACvC,KAAK,OAAO,KACV;MACE,WAAW,QAAQ;MACnB;MACA,aAAa,SAAS;MACtB,SAAS,MAAM,SAAS;KAC1B,GACA,iBACF;IACF;GACF;GACA,MAAM,KAAK,YAAY,cAAc,gBAAgB,SAAS;EAChE,SAAS,KAAK;GACZ,MAAM,KAAK,YAAY,OAAO,cAAc,CAAC,CAAC,YAAY,CAAC,CAAC;GAC5D,MAAM;EACR;CACF;AACF;AAEA,IAAI,aAAkB;AAEtB,eAAsB,oBAAoB;CACxC,SAAS,aAAa;EAAE,MAAM;EAAU,OAAO,OAAO;CAAU,CAAC;CACjE,QAAQ,IAAI,YAAY;EAAE,KAAK,OAAO;EAAW,MAAM;EAAU;CAAO,CAAC;CACzE,MAAM,SAAS,eAAe;EAAE,KAAK,OAAO;EAAc,iBAAiB;EAAU;CAAO,CAAC;CAC7F,QAAM,OAAO;CACb,KAAK,OAAO;CACZ,eAAe,IAAI,mBAAmB,EAAE;CACxC,gBAAgB,IAAI,cAAc,YAAY;CAC9C,MAAM,cAAc,IAAI,kBAAkB,EAAE;CAC5C,WAAW,IAAI,eAAe;EAC5B,OAAO,MAAM;EACb,QAAQ;EACR,OAAO,gBAAgB;EACvB,UAAU,UAAU,QAAQ;EAC5B,WAAW,QAAQ;EACnB,WAAW,OAAO;EAClB;CACF,CAAC;CAED,iBAAiB,IAAI,sBAAsB;EACzC,OAAO,MAAM;EACb,QAAQ;EACR,OAAO,gBAAgB;EACvB,UAAU,UAAU,QAAQ;EAC5B;CACF,CAAC;CAED,MAAM,oBAAoB;EACxB,UAAU,IAAI,eAAe;GAC3B,OAAO,MAAM;GACb,QAAQ,QAAQ;GAChB;EACF,CAAC;EACD,QAAQ,IAAI,eAAe;GAAE,OAAO,MAAM;GAAQ,QAAQ,QAAQ;GAAiB;EAAO,CAAC;EAC3F,KAAK,IAAI,eAAe;GAAE,OAAO,MAAM;GAAQ,QAAQ,QAAQ;GAAc;EAAO,CAAC;CACvF;CAEA,MAAM,oBAAoB,IAAI,eAAe;EAC3C,OAAO,MAAM;EACb,QAAQ,QAAQ;EAChB;CACF,CAAC;CAED,MAAM,oBAAoB,IAAI,eAAe;EAC3C,OAAO,MAAM;EACb,QAAQ,QAAQ;EAChB;CACF,CAAC;CAED,MAAM,cAAc,IAAI,iBAAiB;EACvC,OAAO,MAAM;EACb,WAAW;EACX,YAAY;CACd,CAAC;CAED,MAAM,WAAW,IAAI,aAAa;EAChC,OAAO,MAAM;EACb,YAAY,SAAS,QAAQ,IAAI,uBAAuB,OAAO,EAAE;CACnE,CAAC;CAKD,MAAM,cAAc,IAAI,kBAAkB,EAAE;CAC5C,MAAM,kBAAkB,IAAI,sBAAsB,cAChD,YAAY,qBAAqB,SAAS,CAC5C;CAYA,SAAS,IAAI,aAAa;EACxB;EACA;EACA;EACA,aAAa,OAAO;EACpB;EACA;EACA;EACA;EACA,OAAO,MAAM;EACb;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,aAAa,MAAM,OAAO,UAAU;CACpC,MAAM,WAAW,UACf,gBAAgB,sBAChB,gBAAgB,mBAClB;CACA,WAAW,GAAG,YAAY,SAAiB,YAAoB;EAC7D,IAAI,YAAY,gBAAgB,sBAAsB;GACpD,cAAc,cAAc,OAAO;GACnC,OAAO,KAAK,EAAE,UAAU,QAAQ,GAAG,4BAA4B;EACjE,OAAO,IAAI,YAAY,gBAAgB,qBAAqB;GAC1D,gBAAgB,WAAW,OAAO;GAClC,OAAO,KAAK,EAAE,WAAW,QAAQ,GAAG,oCAAoC;EAC1E;CACF,CAAC;CAID,iBAAiB,oBAAoB,UAAU,QAAQ,OAAO,MAAM;CAEpE,OAAO,KAAK,EAAE,KAAK,OAAO,SAAS,GAAG,iBAAiB;CACvD,MAAM,OAAO,MAAM;AACrB;AAIA,eAAsB,mBAAkC;CACtD,QAAQ,KAAK,oBAAoB;CACjC,IAAI,gBAAgB;EAClB,cAAc,cAAc;EAC5B,iBAAiB;CACnB;CACA,IAAI,YAAY;EACd,WAAW,WAAW;EACtB,aAAa;CACf;CACA,IAAI,QAAQ,MAAM,OAAO,KAAK;CAC9B,IAAIA,OAAK,MAAMA,MAAI,IAAI;CACvB,IAAI,OAAO,MAAM,MAAM,WAAW;CAClC,QAAQ,KAAK,gBAAgB;AAC/B"}
1
+ {"version":3,"file":"main-B561M1d3.mjs","names":["sql"],"sources":["../src/services/engine/main.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { loadEnv, readBaseConfig } from \"@/index.js\";\nimport { createLogger } from \"@/index.js\";\nimport { RedisClient, type Redis } from \"@/index.js\";\nimport {\n StreamConsumer,\n PendingMessageScanner,\n StreamProducer,\n type StreamMessage,\n} from \"@/index.js\";\nimport { BaseWorker } from \"@/index.js\";\nimport {\n STREAMS,\n ENRICHED_STREAMS,\n CONSUMER_GROUPS,\n PUBSUB_CHANNELS,\n registry,\n buildStreamEvent,\n type NotificationEnrichedPayload,\n type NotificationDispatchedPayload,\n} from \"@/index.js\";\nimport { type StreamName } from \"@/contracts/streams.js\";\nimport { IdempotencyGuard } from \"@/index.js\";\nimport { UserThrottle, ProjectSettingsCache } from \"@/index.js\";\nimport { TemplateRepository, ContactRepository, ProjectRepository } from \"@/index.js\";\nimport { createDatabase } from \"@/db/index.js\";\nimport { scheduledPayloads, suppressions } from \"@/db/schema.js\";\nimport { and, eq } from \"drizzle-orm\";\nimport {\n getPriorityBucket,\n globalEmitter,\n normaliseTarget,\n type WorkerOptions,\n DataLoader,\n} from \"@/shared/index.js\";\nimport { renderWithTemplate, TemplateCache } from \"@/templates/index.js\";\nimport { buildUnsubscribeHeaders } from \"@/unsubscribe/index.js\";\nimport { startHealthReporter } from \"@/workers/index.js\";\n\nfunction localTimeToUtc(\n year: number,\n month: number,\n day: number,\n hour: number,\n minute: number,\n second: number,\n timezone: string,\n): Date {\n let utcMs = Date.UTC(year, month - 1, day, hour, minute, second);\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n\n for (let iter = 0; iter < 3; iter++) {\n const parts = formatter.formatToParts(new Date(utcMs));\n const pYear = parseInt(parts.find((p) => p.type === \"year\")?.value ?? \"0\", 10);\n const pMonth = parseInt(parts.find((p) => p.type === \"month\")?.value ?? \"0\", 10);\n const pDay = parseInt(parts.find((p) => p.type === \"day\")?.value ?? \"0\", 10);\n const pHour = parseInt(parts.find((p) => p.type === \"hour\")?.value ?? \"0\", 10);\n const pMin = parseInt(parts.find((p) => p.type === \"minute\")?.value ?? \"0\", 10);\n const pSec = parseInt(parts.find((p) => p.type === \"second\")?.value ?? \"0\", 10);\n\n const targetMs = Date.UTC(year, month - 1, day, hour, minute, second);\n const actualMs = Date.UTC(pYear, pMonth - 1, pDay, pHour, pMin, pSec);\n const diff = targetMs - actualMs;\n if (diff === 0) break;\n utcMs += diff;\n }\n return new Date(utcMs);\n}\n\nexport function isInQuietHours(\n timezone: string,\n quietHours: { start: string; end: string }[],\n fromDate: Date = new Date(),\n): { inQuietHours: boolean; nextActiveTime?: Date } {\n if (!quietHours || quietHours.length === 0) {\n return { inQuietHours: false };\n }\n\n const checkWindowAt = (date: Date) => {\n let parts: Intl.DateTimeFormatPart[];\n try {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n parts = formatter.formatToParts(date);\n } catch {\n return null;\n }\n\n const year = parseInt(parts.find((p) => p.type === \"year\")?.value ?? \"0\", 10);\n const month = parseInt(parts.find((p) => p.type === \"month\")?.value ?? \"0\", 10);\n const day = parseInt(parts.find((p) => p.type === \"day\")?.value ?? \"0\", 10);\n const currentHour = parseInt(parts.find((p) => p.type === \"hour\")?.value ?? \"0\", 10);\n const currentMin = parseInt(parts.find((p) => p.type === \"minute\")?.value ?? \"0\", 10);\n\n const currentMinutes = currentHour * 60 + currentMin;\n\n for (const window of quietHours) {\n const [startH, startM] = window.start.split(\":\").map(Number);\n const [endH, endM] = window.end.split(\":\").map(Number);\n\n if (startH === undefined || startM === undefined || endH === undefined || endM === undefined)\n continue;\n\n const startMinutes = startH * 60 + startM;\n const endMinutes = endH * 60 + endM;\n\n let inWindow = false;\n if (startMinutes <= endMinutes) {\n inWindow = currentMinutes >= startMinutes && currentMinutes < endMinutes;\n } else {\n inWindow = currentMinutes >= startMinutes || currentMinutes < endMinutes;\n }\n\n if (inWindow) {\n let targetYear = year;\n let targetMonth = month;\n let targetDay = day;\n\n if (currentMinutes >= endMinutes) {\n const nextDay = new Date(Date.UTC(year, month - 1, day + 1));\n targetYear = nextDay.getUTCFullYear();\n targetMonth = nextDay.getUTCMonth() + 1;\n targetDay = nextDay.getUTCDate();\n }\n\n const nextActive = localTimeToUtc(\n targetYear,\n targetMonth,\n targetDay,\n endH,\n endM,\n 0,\n timezone,\n );\n return { inQuietHours: true, nextActiveTime: nextActive };\n }\n }\n return { inQuietHours: false };\n };\n\n let initialCheck = checkWindowAt(fromDate);\n if (!initialCheck || !initialCheck.inQuietHours) {\n return { inQuietHours: false };\n }\n\n // Chained / overlapping quiet hours intervals\n let candidateTime = initialCheck.nextActiveTime!;\n for (let i = 0; i < 10; i++) {\n const subsequentCheck = checkWindowAt(candidateTime);\n if (subsequentCheck && subsequentCheck.inQuietHours && subsequentCheck.nextActiveTime) {\n if (subsequentCheck.nextActiveTime.getTime() <= candidateTime.getTime()) {\n break;\n }\n candidateTime = subsequentCheck.nextActiveTime;\n } else {\n break;\n }\n }\n\n return { inQuietHours: true, nextActiveTime: candidateTime };\n}\n\n// ─── Bootstrap ─────────────────────────────────────────────────────────────\n\nloadEnv();\nconst config = readBaseConfig();\n\nlet logger: ReturnType<typeof createLogger>;\nlet redis: RedisClient;\nlet sql: any;\nlet db: any;\nlet templateRepo: TemplateRepository;\n\nlet templateCache: TemplateCache;\n\nlet consumer: StreamConsumer;\nlet pendingScanner: PendingMessageScanner;\nlet worker: BaseWorker;\nlet healthInterval: NodeJS.Timeout | null = null;\n\nexport interface EngineWorkerOptions extends WorkerOptions {\n registry: any;\n idempotency: any;\n throttle: any;\n projectSettings: ProjectSettingsCache;\n redis: Redis;\n templateCache: TemplateCache;\n aiPendingProducer: any;\n scheduledProducer: any;\n outboundProducers: any;\n globalEmitter: any;\n contactRepo: any;\n db: any;\n}\n\nexport class EngineWorker extends BaseWorker {\n private readonly registry: any;\n private readonly idempotency: any;\n private readonly throttle: any;\n private readonly projectSettings: ProjectSettingsCache;\n private readonly redisCli: Redis;\n private readonly templateCache: TemplateCache;\n private readonly aiPendingProducer: any;\n private readonly scheduledProducer: any;\n private readonly outboundProducers: any;\n private readonly globalEmitter: any;\n private readonly contactRepo: any;\n private readonly db: any;\n\n constructor(options: EngineWorkerOptions) {\n super(options);\n this.registry = options.registry;\n this.idempotency = options.idempotency;\n this.throttle = options.throttle;\n this.projectSettings = options.projectSettings;\n this.redisCli = options.redis;\n this.templateCache = options.templateCache;\n this.aiPendingProducer = options.aiPendingProducer;\n this.scheduledProducer = options.scheduledProducer;\n this.outboundProducers = options.outboundProducers;\n this.globalEmitter = options.globalEmitter;\n this.contactRepo = options.contactRepo;\n this.db = options.db;\n }\n\n private readonly contactsLoader = new DataLoader<\n { projectId: string; recipientId: string },\n any[]\n >(async (keys) => {\n const byProject = new Map<string, string[]>();\n for (const key of keys) {\n if (!byProject.has(key.projectId)) byProject.set(key.projectId, []);\n byProject.get(key.projectId)!.push(key.recipientId);\n }\n\n const resultsByProjectAndUser = new Map<string, Map<string, any[]>>();\n for (const [projectId, userIds] of byProject) {\n const activeContactsMap = await this.contactRepo.findActiveByUserIds(projectId, userIds);\n resultsByProjectAndUser.set(projectId, activeContactsMap);\n }\n\n return keys.map((key) => {\n const projectMap = resultsByProjectAndUser.get(key.projectId);\n if (!projectMap) return [];\n return projectMap.get(key.recipientId) || [];\n });\n });\n\n /**\n * Suppressed destinations for one (project, channel), as a normalised set.\n *\n * Loaded per project+channel rather than per address: a campaign is thousands\n * of messages against one channel, so this collapses to a single query for\n * the whole batch. Cached for the loader's lifetime of a tick, which means a\n * suppression written mid-batch takes effect on the next batch — acceptable,\n * since the webhook that writes it is itself minutes behind the send.\n */\n private readonly suppressionsLoader = new DataLoader<\n { projectId: string; channel: string },\n Set<string>\n >(async (keys) => {\n const results = new Map<string, Set<string>>();\n for (const key of keys) {\n const cacheKey = `${key.projectId}:${key.channel}`;\n if (results.has(cacheKey)) continue;\n try {\n const rows = await this.db\n .select({ target: suppressions.target })\n .from(suppressions)\n .where(\n and(\n eq(suppressions.projectId, key.projectId),\n eq(suppressions.channel, key.channel as any),\n ),\n );\n results.set(\n cacheKey,\n new Set(rows.map((r: { target: string }) => normaliseTarget(r.target))),\n );\n } catch (err) {\n // A suppression lookup that fails must not silently become \"nothing\n // is suppressed\" — that would resume mailing people who opted out.\n this.logger.error(\n { err, projectId: key.projectId, channel: key.channel },\n \"suppression lookup failed — holding message\",\n );\n throw err;\n }\n }\n return keys.map((key) => results.get(`${key.projectId}:${key.channel}`) ?? new Set<string>());\n });\n\n async process(message: StreamMessage): Promise<void> {\n const { event } = message;\n\n const payloadResult = this.registry.safeParsePayload(\"notification.enriched\", event.payload);\n if (!payloadResult.success) {\n this.logger.warn(\n { messageId: message.id, issues: payloadResult.error.issues },\n \"invalid notification.enriched payload — skipping\",\n );\n return;\n }\n\n const enriched = payloadResult.data as NotificationEnrichedPayload;\n\n // Idempotency\n const idempotencyKey = `${enriched.rawEventId}:${enriched.recipientId}:${enriched.channel}`;\n let customTtl: number | undefined;\n if (enriched.scheduledAt) {\n const msUntil = new Date(enriched.scheduledAt).getTime() - Date.now();\n if (msUntil > 0) {\n // base 24h (86400) + schedule time\n customTtl = 86400 + Math.ceil(msUntil / 1000);\n }\n }\n\n if (!(await this.idempotency.checkAndMark(idempotencyKey, 60))) {\n this.logger.debug({ messageId: message.id, eventId: event.id }, \"duplicate — skipping\");\n return;\n }\n\n try {\n // Opt-in check\n if (enriched.recipient.preferences.optedOut) {\n this.logger.info(\n { messageId: message.id, recipientId: enriched.recipientId, eventType: event.type },\n \"user opted out — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"user_opted_out\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n if (enriched.recipient.preferences.channels?.includes(enriched.channel)) {\n this.logger.info(\n { messageId: message.id, recipientId: enriched.recipientId, channel: enriched.channel },\n \"user disabled notification channel — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"channel_disabled\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n // Quiet hours check\n const qh = enriched.recipient.preferences.quietHours;\n if (qh && qh.length > 0 && enriched.priority !== \"critical\") {\n const qhResult = isInQuietHours(enriched.recipient.timezone, qh);\n if (qhResult.inQuietHours && qhResult.nextActiveTime) {\n this.logger.info(\n {\n messageId: message.id,\n recipientId: enriched.recipientId,\n nextActiveTime: qhResult.nextActiveTime.toISOString(),\n },\n \"user is in quiet hours — deferring notification\",\n );\n enriched.scheduledAt = qhResult.nextActiveTime.toISOString();\n }\n }\n\n // Rate limit. Per-project overrides win over the process-wide default;\n // a lookup failure must not drop the notification, so fall back rather\n // than propagate.\n let projectThrottle: { throttleLimit: number | null; throttleWindowHours: number | null } = {\n throttleLimit: null,\n throttleWindowHours: null,\n };\n try {\n projectThrottle = await this.projectSettings.get(enriched.projectId);\n } catch (err) {\n this.logger.warn(\n { err, projectId: enriched.projectId },\n \"could not read project throttle settings — falling back to the global default\",\n );\n }\n\n const throttleResult = await this.throttle.check(\n enriched.projectId,\n enriched.recipientId,\n enriched.priority,\n {\n limit: projectThrottle.throttleLimit,\n windowHours: projectThrottle.throttleWindowHours,\n scheduledAt: enriched.scheduledAt,\n },\n );\n if (!throttleResult.allowed) {\n this.logger.info(\n {\n messageId: message.id,\n recipientId: enriched.recipientId,\n count: throttleResult.count,\n limit: throttleResult.limit,\n priority: enriched.priority,\n },\n \"user throttled — dropping\",\n );\n this.globalEmitter.emit(\n \"notification:throttled\",\n enriched.recipientId,\n throttleResult.count,\n );\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n // Gather AI Prompts\n // Gather AI Prompts\n let dbTemplate = null;\n if (enriched.templateId) {\n dbTemplate = await this.templateCache.getCachedTemplate(\n enriched.projectId,\n enriched.templateId,\n );\n if (!dbTemplate) {\n this.logger.warn(\n { messageId: message.id, templateId: enriched.templateId },\n \"template not found — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"template_not_found\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n }\n const aiPrompts = {\n ...(dbTemplate?.aiPrompts ?? {}),\n ...(enriched.aiPrompts ?? {}),\n };\n\n // Drives whether this message gets an unsubscribe header, and what the\n // resulting opt-out applies to.\n const templateTopics: string[] = dbTemplate?.topics ?? [];\n\n if (Object.keys(aiPrompts).length > 0) {\n const aiPendingPayload = {\n projectId: enriched.projectId,\n enrichedEventId: event.id,\n recipientId: enriched.recipientId,\n channel: enriched.channel,\n priority: enriched.priority,\n templateId: enriched.templateId,\n templateVariables: enriched.templateVariables,\n recipient: enriched.recipient,\n aiPrompts,\n scheduledAt: enriched.scheduledAt,\n fallbackChain: enriched.fallbackChain,\n };\n\n const aiPendingEnvelope = buildStreamEvent(\n \"notification.ai_pending\",\n aiPendingPayload as Record<string, unknown>,\n \"engine\",\n event.metadata.traceId,\n );\n\n await this.aiPendingProducer.publish(aiPendingEnvelope);\n this.logger.info(\n {\n messageId: message.id,\n eventId: event.id,\n recipientId: enriched.recipientId,\n traceId: event.metadata.traceId,\n },\n \"task routed to AI worker\",\n );\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n // Render template\n const rendered = renderWithTemplate(dbTemplate, enriched.templateVariables);\n\n const allContacts = await this.contactsLoader.load({\n projectId: enriched.projectId,\n recipientId: enriched.recipientId,\n });\n const activeContacts = allContacts.filter(\n (c: any) => c.channel === enriched.channel && c.active,\n );\n\n if (activeContacts.length === 0) {\n this.logger.info(\n { messageId: message.id, recipientId: enriched.recipientId, channel: enriched.channel },\n \"no active contacts for channel — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"no_active_contacts\",\n });\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n return;\n }\n\n const suppressedTargets = await this.suppressionsLoader.load({\n projectId: enriched.projectId,\n channel: enriched.channel,\n });\n\n for (const contact of activeContacts) {\n if (contact.preferences?.optedOut) {\n continue;\n }\n\n // A suppression outranks every other gate, `critical` included: it\n // records that the person asked us to stop, or that the address is\n // dead. Sending anyway is what gets a domain blocked.\n if (contact.target && suppressedTargets.has(normaliseTarget(contact.target))) {\n this.logger.info(\n {\n messageId: message.id,\n recipientId: enriched.recipientId,\n channel: enriched.channel,\n },\n \"destination suppressed — dropping\",\n );\n this.globalEmitter.emit(\"notification:skipped\", {\n projectId: enriched.projectId,\n eventId: event.id,\n recipientId: enriched.recipientId,\n reason: \"suppressed\",\n });\n continue;\n }\n\n const taskId = `${enriched.rawEventId}:${contact.id || randomUUID()}`;\n const resolvedDestination = contact.target;\n\n // One-click unsubscribe headers, but only on mail that should carry\n // them. A template with no topic is transactional by this codebase's\n // own convention — a password reset, a receipt — and putting an\n // unsubscribe button on those invites people to switch off mail they\n // actually need, with no topic to scope the opt-out to anyway.\n if (\n enriched.channel === \"email\" &&\n templateTopics.length > 0 &&\n !config.UNSUBSCRIBE_SECRET\n ) {\n this.logger.warn(\n { projectId: enriched.projectId, recipientId: enriched.recipientId },\n \"UNSUBSCRIBE_SECRET is not configured — email sent without RFC 8058 one-click unsubscribe headers\",\n );\n }\n\n const unsubscribeHeaders =\n enriched.channel === \"email\" &&\n templateTopics.length > 0 &&\n config.UNSUBSCRIBE_SECRET &&\n config.PUBLIC_URL &&\n resolvedDestination\n ? buildUnsubscribeHeaders({\n claim: {\n projectId: enriched.projectId,\n userId: enriched.recipientId,\n channel: enriched.channel,\n target: resolvedDestination,\n topics: templateTopics,\n },\n secret: config.UNSUBSCRIBE_SECRET,\n publicUrl: config.PUBLIC_URL,\n })\n : undefined;\n\n const taskPayload: NotificationDispatchedPayload = {\n projectId: enriched.projectId,\n taskId,\n enrichedEventId: event.id,\n recipientId: enriched.recipientId,\n channel: enriched.channel,\n priority: enriched.priority,\n templateId: enriched.templateId,\n templateVariables: enriched.templateVariables,\n aiPrompts: enriched.aiPrompts,\n recipient: enriched.recipient,\n renderedContent: rendered,\n destination: resolvedDestination,\n deliveryOptions: {\n maxAttempts: 3,\n timeoutMs: 10_000,\n ...(unsubscribeHeaders ? { headers: unsubscribeHeaders } : {}),\n },\n fallbackChain: enriched.fallbackChain,\n campaignId: enriched.campaignId,\n };\n\n const envelope = buildStreamEvent(\n \"notification.dispatched\",\n taskPayload as Record<string, unknown>,\n \"engine\",\n event.metadata.traceId,\n );\n\n // Route by scheduledAt\n const now = Date.now();\n const scheduledAt = enriched.scheduledAt ? new Date(enriched.scheduledAt).getTime() : now;\n\n if (scheduledAt > now) {\n await this.db\n .insert(scheduledPayloads)\n .values({\n taskId,\n payload: {\n ...taskPayload,\n scheduledAt: enriched.scheduledAt,\n },\n })\n .onConflictDoNothing();\n\n const scheduledEnvelope = buildStreamEvent(\n \"notification.scheduled\",\n {\n projectId: enriched.projectId,\n enrichedEventId: event.id,\n taskId,\n scheduledAt: enriched.scheduledAt!,\n },\n \"engine\",\n event.metadata.traceId,\n );\n\n await this.scheduledProducer.publish(scheduledEnvelope);\n this.logger.info(\n {\n messageId: message.id,\n taskId,\n scheduledAt: enriched.scheduledAt,\n traceId: event.metadata.traceId,\n },\n \"task scheduled and payload cached\",\n );\n } else {\n const p = getPriorityBucket(enriched.priority);\n const outboundProducer = this.outboundProducers[p] ?? this.outboundProducers[\"normal\"]!;\n\n await outboundProducer.publish(envelope);\n this.logger.info(\n {\n messageId: message.id,\n taskId,\n recipientId: enriched.recipientId,\n traceId: event.metadata.traceId,\n },\n \"task dispatched\",\n );\n }\n }\n await this.idempotency.markProcessed(idempotencyKey, customTtl);\n } catch (err) {\n await this.idempotency.unmark(idempotencyKey).catch(() => {});\n throw err;\n }\n }\n}\n\nlet subscriber: any = null;\n\nexport async function startEngineWorker() {\n logger = createLogger({ name: \"engine\", level: config.LOG_LEVEL });\n redis = new RedisClient({ url: config.REDIS_URL, name: \"engine\", logger });\n const dbData = createDatabase({ url: config.DATABASE_URL, applicationName: \"engine\", logger });\n sql = dbData.sql;\n db = dbData.db;\n templateRepo = new TemplateRepository(db);\n templateCache = new TemplateCache(templateRepo);\n const contactRepo = new ContactRepository(db);\n consumer = new StreamConsumer({\n redis: redis.native,\n stream: ENRICHED_STREAMS as unknown as StreamName[],\n group: CONSUMER_GROUPS.ENGINE,\n consumer: `engine-${process.pid}`,\n dlqStream: STREAMS.DEAD_LETTER,\n batchSize: config.WORKER_CONCURRENCY,\n logger,\n });\n\n pendingScanner = new PendingMessageScanner({\n redis: redis.native,\n stream: ENRICHED_STREAMS as unknown as StreamName[],\n group: CONSUMER_GROUPS.ENGINE,\n consumer: `engine-${process.pid}`,\n logger,\n });\n\n const outboundProducers = {\n critical: new StreamProducer({\n redis: redis.native,\n stream: STREAMS.OUTBOUND_CRITICAL,\n logger,\n }),\n normal: new StreamProducer({ redis: redis.native, stream: STREAMS.OUTBOUND_NORMAL, logger }),\n low: new StreamProducer({ redis: redis.native, stream: STREAMS.OUTBOUND_LOW, logger }),\n };\n\n const scheduledProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.SCHEDULED,\n logger,\n });\n\n const aiPendingProducer = new StreamProducer({\n redis: redis.native,\n stream: STREAMS.AI_PENDING,\n logger,\n });\n\n const idempotency = new IdempotencyGuard({\n redis: redis.native,\n keyPrefix: \"notif:processed:engine\",\n ttlSeconds: 86_400,\n });\n\n const throttle = new UserThrottle({\n redis: redis.native,\n maxPerHour: parseInt(process.env.RATE_LIMIT_PER_HOUR || \"100\", 10),\n });\n\n // Per-project throttle overrides, cached because this is read once per\n // notification. Stale entries expire on their own; the pub/sub subscriber\n // below only makes an admin's change take effect sooner.\n const projectRepo = new ProjectRepository(db);\n const projectSettings = new ProjectSettingsCache((projectId) =>\n projectRepo.findThrottleSettings(projectId),\n );\n\n // ─── Stage 2: Decision Engine ───────────────────────────────────────────────\n //\n // Pipeline:\n // 1. Parse payload as notification.enriched\n // 2. Idempotency check\n // 3. Check user opt-in (from enriched recipient.preferences)\n // 4. Apply per-user hourly rate limit\n // 5. Render template using user locale\n // 6. Route: if scheduledAt is future → SCHEDULED; else → OUTBOUND\n\n worker = new EngineWorker({\n consumer,\n pendingScanner,\n logger,\n concurrency: config.WORKER_CONCURRENCY,\n registry,\n idempotency,\n throttle,\n projectSettings,\n redis: redis.native,\n templateCache,\n aiPendingProducer,\n scheduledProducer,\n outboundProducers,\n globalEmitter,\n contactRepo,\n db,\n });\n\n subscriber = redis.native.duplicate();\n await subscriber.subscribe(\n PUBSUB_CHANNELS.TEMPLATE_INVALIDATED,\n PUBSUB_CHANNELS.PROJECT_INVALIDATED,\n );\n subscriber.on(\"message\", (channel: string, message: string) => {\n if (channel === PUBSUB_CHANNELS.TEMPLATE_INVALIDATED) {\n templateCache.invalidateKey(message);\n logger.info({ cacheKey: message }, \"invalidated template cache\");\n } else if (channel === PUBSUB_CHANNELS.PROJECT_INVALIDATED) {\n projectSettings.invalidate(message);\n logger.info({ projectId: message }, \"invalidated project settings cache\");\n }\n });\n\n // ─── Health check interval ──────────────────────────────────────────────────\n\n healthInterval = startHealthReporter(\"engine\", worker, redis, logger);\n\n logger.info({ env: config.NODE_ENV }, \"engine starting\");\n await worker.start();\n}\n\n// ─── Shutdown ──────────────────────────────────────────────────────────────\n\nexport async function stopEngineWorker(): Promise<void> {\n logger?.info(\"shutdown initiated\");\n if (healthInterval) {\n clearInterval(healthInterval);\n healthInterval = null;\n }\n if (subscriber) {\n subscriber.disconnect();\n subscriber = null;\n }\n if (worker) await worker.stop();\n if (sql) await sql.end();\n if (redis) await redis.disconnect();\n logger?.info(\"engine stopped\");\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { J as PendingMessageScanner, Jt as buildStreamEvent, U as LUA_SCHEDULER_POLL, W as getPriorityBucket, X as StreamProducer, Y as StreamConsumer, Yt as CONSUMER_GROUPS, an as registry, c as BaseWorker, en as STREAMS, et as createLogger, hn as readBaseConfig, it as createDatabase, k as RedisClient, pn as loadEnv, u as startHealthReporter, ut as scheduledPayloads } from "./src-DrSN2wCg.mjs";
1
+ import { J as PendingMessageScanner, Jt as buildStreamEvent, U as LUA_SCHEDULER_POLL, W as getPriorityBucket, X as StreamProducer, Y as StreamConsumer, Yt as CONSUMER_GROUPS, an as registry, c as BaseWorker, en as STREAMS, et as createLogger, hn as readBaseConfig, it as createDatabase, k as RedisClient, pn as loadEnv, u as startHealthReporter, ut as scheduledPayloads } from "./src-C-PfEDMY.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { inArray } from "drizzle-orm";
4
4
  //#region src/services/scheduler/main.ts
@@ -221,4 +221,4 @@ async function stopSchedulerWorker() {
221
221
  //#endregion
222
222
  export { startSchedulerWorker, stopSchedulerWorker };
223
223
 
224
- //# sourceMappingURL=main-BHYZfBBq.mjs.map
224
+ //# sourceMappingURL=main-C45e7grq.mjs.map