@astralibx/email-rule-engine 12.10.1 → 12.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -578,18 +578,25 @@ declare function createEmailRuleRunLogSchema(collectionPrefix?: string): Schema<
578
578
  __v: number;
579
579
  }>;
580
580
 
581
+ interface SendWindowConfig {
582
+ startHour: number;
583
+ endHour: number;
584
+ timezone: string;
585
+ }
581
586
  interface EmailThrottleConfig {
582
587
  _id: string;
583
588
  maxPerUserPerDay: number;
584
589
  maxPerUserPerWeek: number;
585
590
  minGapDays: number;
586
591
  throttleWindow: ThrottleWindow;
592
+ sendWindow?: SendWindowConfig;
587
593
  updatedAt: Date;
588
594
  }
589
595
  interface UpdateEmailThrottleConfigInput {
590
596
  maxPerUserPerDay?: number;
591
597
  maxPerUserPerWeek?: number;
592
598
  minGapDays?: number;
599
+ sendWindow?: SendWindowConfig | null;
593
600
  }
594
601
 
595
602
  interface IEmailThrottleConfig extends Omit<EmailThrottleConfig, '_id'> {
@@ -881,4 +888,4 @@ interface EmailRuleEngine {
881
888
  */
882
889
  declare function createEmailRuleEngine(config: EmailRuleEngineConfig): EmailRuleEngine;
883
890
 
884
- export { type AgentSelection, AlxEmailError, type BeforeSendParams, type BeforeSendResult, type CollectionSchema, type CompiledTemplate, type ConditionValidationError, ConfigValidationError, type CreateEmailRuleInput, type CreateEmailTemplateInput, DuplicateSlugError, EMAIL_SEND_STATUS, EMAIL_TYPE, type EmailAttachment, type EmailRule, type EmailRuleDocument, type EmailRuleEngine, type EmailRuleEngineConfig, type EmailRuleModel, type EmailRuleRunLog, type EmailRuleRunLogDocument, type EmailRuleRunLogModel, type EmailRuleRunLogStatics, type EmailRuleSend, type EmailRuleSendDocument, type EmailRuleSendModel, type EmailRuleSendStatics, type EmailRuleStatics, type EmailSendStatus, type EmailTemplate, type EmailTemplateDocument, type EmailTemplateModel, type EmailTemplateStatics, type EmailThrottleConfig, type EmailThrottleConfigDocument, type EmailThrottleConfigModel, type EmailThrottleConfigStatics, type EmailType, FIELD_TYPE, type FieldDefinition, type FieldType, type FlattenedField, type IEmailRule, type IEmailRuleRunLog, type IEmailRuleSend, type IEmailTemplate, type IEmailThrottleConfig, type JoinDefinition, type ListTarget, LockAcquisitionError, type PerRuleStats, type QueryTarget, RULE_OPERATOR, RUN_LOG_STATUS, RUN_TRIGGER, type RecipientIdentifier, type RenderResult, type RuleCondition, RuleNotFoundError, type RuleOperator, type RuleRunStats, RuleRunnerService, RuleService, type RuleTarget, RuleTemplateIncompatibleError, type RunLogStatus, type RunTrigger, SchedulerService, type SendEmailParams, TARGET_MODE, TEMPLATE_AUDIENCE, TEMPLATE_CATEGORY, THROTTLE_WINDOW, TYPE_OPERATORS, type TargetMode, type TemplateAudience, type TemplateCategory, TemplateNotFoundError, TemplateRenderService, TemplateService, TemplateSyntaxError, type ThrottleWindow, type UpdateEmailRuleInput, type UpdateEmailTemplateInput, type UpdateEmailThrottleConfigInput, createEmailRuleEngine, createEmailRuleRunLogSchema, createEmailRuleSchema, createEmailRuleSendSchema, createEmailTemplateSchema, createEmailThrottleConfigSchema, flattenFields, validateConditions, validateConfig };
891
+ export { type AgentSelection, AlxEmailError, type BeforeSendParams, type BeforeSendResult, type CollectionSchema, type CompiledTemplate, type ConditionValidationError, ConfigValidationError, type CreateEmailRuleInput, type CreateEmailTemplateInput, DuplicateSlugError, EMAIL_SEND_STATUS, EMAIL_TYPE, type EmailAttachment, type EmailRule, type EmailRuleDocument, type EmailRuleEngine, type EmailRuleEngineConfig, type EmailRuleModel, type EmailRuleRunLog, type EmailRuleRunLogDocument, type EmailRuleRunLogModel, type EmailRuleRunLogStatics, type EmailRuleSend, type EmailRuleSendDocument, type EmailRuleSendModel, type EmailRuleSendStatics, type EmailRuleStatics, type EmailSendStatus, type EmailTemplate, type EmailTemplateDocument, type EmailTemplateModel, type EmailTemplateStatics, type EmailThrottleConfig, type EmailThrottleConfigDocument, type EmailThrottleConfigModel, type EmailThrottleConfigStatics, type EmailType, FIELD_TYPE, type FieldDefinition, type FieldType, type FlattenedField, type IEmailRule, type IEmailRuleRunLog, type IEmailRuleSend, type IEmailTemplate, type IEmailThrottleConfig, type JoinDefinition, type ListTarget, LockAcquisitionError, type PerRuleStats, type QueryTarget, RULE_OPERATOR, RUN_LOG_STATUS, RUN_TRIGGER, type RecipientIdentifier, type RenderResult, type RuleCondition, RuleNotFoundError, type RuleOperator, type RuleRunStats, RuleRunnerService, RuleService, type RuleTarget, RuleTemplateIncompatibleError, type RunLogStatus, type RunTrigger, SchedulerService, type SendEmailParams, type SendWindowConfig, TARGET_MODE, TEMPLATE_AUDIENCE, TEMPLATE_CATEGORY, THROTTLE_WINDOW, TYPE_OPERATORS, type TargetMode, type TemplateAudience, type TemplateCategory, TemplateNotFoundError, TemplateRenderService, TemplateService, TemplateSyntaxError, type ThrottleWindow, type UpdateEmailRuleInput, type UpdateEmailTemplateInput, type UpdateEmailThrottleConfigInput, createEmailRuleEngine, createEmailRuleRunLogSchema, createEmailRuleSchema, createEmailRuleSendSchema, createEmailTemplateSchema, createEmailThrottleConfigSchema, flattenFields, validateConditions, validateConfig };
package/dist/index.d.ts CHANGED
@@ -578,18 +578,25 @@ declare function createEmailRuleRunLogSchema(collectionPrefix?: string): Schema<
578
578
  __v: number;
579
579
  }>;
580
580
 
581
+ interface SendWindowConfig {
582
+ startHour: number;
583
+ endHour: number;
584
+ timezone: string;
585
+ }
581
586
  interface EmailThrottleConfig {
582
587
  _id: string;
583
588
  maxPerUserPerDay: number;
584
589
  maxPerUserPerWeek: number;
585
590
  minGapDays: number;
586
591
  throttleWindow: ThrottleWindow;
592
+ sendWindow?: SendWindowConfig;
587
593
  updatedAt: Date;
588
594
  }
589
595
  interface UpdateEmailThrottleConfigInput {
590
596
  maxPerUserPerDay?: number;
591
597
  maxPerUserPerWeek?: number;
592
598
  minGapDays?: number;
599
+ sendWindow?: SendWindowConfig | null;
593
600
  }
594
601
 
595
602
  interface IEmailThrottleConfig extends Omit<EmailThrottleConfig, '_id'> {
@@ -881,4 +888,4 @@ interface EmailRuleEngine {
881
888
  */
882
889
  declare function createEmailRuleEngine(config: EmailRuleEngineConfig): EmailRuleEngine;
883
890
 
884
- export { type AgentSelection, AlxEmailError, type BeforeSendParams, type BeforeSendResult, type CollectionSchema, type CompiledTemplate, type ConditionValidationError, ConfigValidationError, type CreateEmailRuleInput, type CreateEmailTemplateInput, DuplicateSlugError, EMAIL_SEND_STATUS, EMAIL_TYPE, type EmailAttachment, type EmailRule, type EmailRuleDocument, type EmailRuleEngine, type EmailRuleEngineConfig, type EmailRuleModel, type EmailRuleRunLog, type EmailRuleRunLogDocument, type EmailRuleRunLogModel, type EmailRuleRunLogStatics, type EmailRuleSend, type EmailRuleSendDocument, type EmailRuleSendModel, type EmailRuleSendStatics, type EmailRuleStatics, type EmailSendStatus, type EmailTemplate, type EmailTemplateDocument, type EmailTemplateModel, type EmailTemplateStatics, type EmailThrottleConfig, type EmailThrottleConfigDocument, type EmailThrottleConfigModel, type EmailThrottleConfigStatics, type EmailType, FIELD_TYPE, type FieldDefinition, type FieldType, type FlattenedField, type IEmailRule, type IEmailRuleRunLog, type IEmailRuleSend, type IEmailTemplate, type IEmailThrottleConfig, type JoinDefinition, type ListTarget, LockAcquisitionError, type PerRuleStats, type QueryTarget, RULE_OPERATOR, RUN_LOG_STATUS, RUN_TRIGGER, type RecipientIdentifier, type RenderResult, type RuleCondition, RuleNotFoundError, type RuleOperator, type RuleRunStats, RuleRunnerService, RuleService, type RuleTarget, RuleTemplateIncompatibleError, type RunLogStatus, type RunTrigger, SchedulerService, type SendEmailParams, TARGET_MODE, TEMPLATE_AUDIENCE, TEMPLATE_CATEGORY, THROTTLE_WINDOW, TYPE_OPERATORS, type TargetMode, type TemplateAudience, type TemplateCategory, TemplateNotFoundError, TemplateRenderService, TemplateService, TemplateSyntaxError, type ThrottleWindow, type UpdateEmailRuleInput, type UpdateEmailTemplateInput, type UpdateEmailThrottleConfigInput, createEmailRuleEngine, createEmailRuleRunLogSchema, createEmailRuleSchema, createEmailRuleSendSchema, createEmailTemplateSchema, createEmailThrottleConfigSchema, flattenFields, validateConditions, validateConfig };
891
+ export { type AgentSelection, AlxEmailError, type BeforeSendParams, type BeforeSendResult, type CollectionSchema, type CompiledTemplate, type ConditionValidationError, ConfigValidationError, type CreateEmailRuleInput, type CreateEmailTemplateInput, DuplicateSlugError, EMAIL_SEND_STATUS, EMAIL_TYPE, type EmailAttachment, type EmailRule, type EmailRuleDocument, type EmailRuleEngine, type EmailRuleEngineConfig, type EmailRuleModel, type EmailRuleRunLog, type EmailRuleRunLogDocument, type EmailRuleRunLogModel, type EmailRuleRunLogStatics, type EmailRuleSend, type EmailRuleSendDocument, type EmailRuleSendModel, type EmailRuleSendStatics, type EmailRuleStatics, type EmailSendStatus, type EmailTemplate, type EmailTemplateDocument, type EmailTemplateModel, type EmailTemplateStatics, type EmailThrottleConfig, type EmailThrottleConfigDocument, type EmailThrottleConfigModel, type EmailThrottleConfigStatics, type EmailType, FIELD_TYPE, type FieldDefinition, type FieldType, type FlattenedField, type IEmailRule, type IEmailRuleRunLog, type IEmailRuleSend, type IEmailTemplate, type IEmailThrottleConfig, type JoinDefinition, type ListTarget, LockAcquisitionError, type PerRuleStats, type QueryTarget, RULE_OPERATOR, RUN_LOG_STATUS, RUN_TRIGGER, type RecipientIdentifier, type RenderResult, type RuleCondition, RuleNotFoundError, type RuleOperator, type RuleRunStats, RuleRunnerService, RuleService, type RuleTarget, RuleTemplateIncompatibleError, type RunLogStatus, type RunTrigger, SchedulerService, type SendEmailParams, type SendWindowConfig, TARGET_MODE, TEMPLATE_AUDIENCE, TEMPLATE_CATEGORY, THROTTLE_WINDOW, TYPE_OPERATORS, type TargetMode, type TemplateAudience, type TemplateCategory, TemplateNotFoundError, TemplateRenderService, TemplateService, TemplateSyntaxError, type ThrottleWindow, type UpdateEmailRuleInput, type UpdateEmailTemplateInput, type UpdateEmailThrottleConfigInput, createEmailRuleEngine, createEmailRuleRunLogSchema, createEmailRuleSchema, createEmailRuleSendSchema, createEmailTemplateSchema, createEmailThrottleConfigSchema, flattenFields, validateConditions, validateConfig };
package/dist/index.mjs CHANGED
@@ -368,7 +368,16 @@ function createEmailThrottleConfigSchema(collectionPrefix) {
368
368
  maxPerUserPerDay: { type: Number, default: 1 },
369
369
  maxPerUserPerWeek: { type: Number, default: 2 },
370
370
  minGapDays: { type: Number, default: 3 },
371
- throttleWindow: { type: String, enum: Object.values(THROTTLE_WINDOW), default: THROTTLE_WINDOW.Rolling }
371
+ throttleWindow: { type: String, enum: Object.values(THROTTLE_WINDOW), default: THROTTLE_WINDOW.Rolling },
372
+ sendWindow: {
373
+ type: {
374
+ startHour: { type: Number, min: 0, max: 23 },
375
+ endHour: { type: Number, min: 0, max: 23 },
376
+ timezone: { type: String }
377
+ },
378
+ _id: false,
379
+ default: void 0
380
+ }
372
381
  },
373
382
  {
374
383
  timestamps: true,
@@ -1272,16 +1281,6 @@ var RuleRunnerService = class {
1272
1281
  async runAllRules(triggeredBy = RUN_TRIGGER.Cron, runId) {
1273
1282
  if (!runId) runId = crypto.randomUUID();
1274
1283
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
1275
- if (this.config.options?.sendWindow) {
1276
- const { startHour, endHour, timezone } = this.config.options.sendWindow;
1277
- const now = /* @__PURE__ */ new Date();
1278
- const formatter = new Intl.DateTimeFormat("en-US", { hour: "numeric", hour12: false, timeZone: timezone });
1279
- const currentHour = parseInt(formatter.format(now), 10);
1280
- if (currentHour < startHour || currentHour >= endHour) {
1281
- this.logger.info("Outside send window, skipping run", { currentHour, startHour, endHour, timezone });
1282
- return { runId };
1283
- }
1284
- }
1285
1284
  const lockAcquired = await this.lock.acquire();
1286
1285
  if (!lockAcquired) {
1287
1286
  this.logger.warn("Rule runner already executing, skipping");
@@ -1300,9 +1299,20 @@ var RuleRunnerService = class {
1300
1299
  let runStatus = "completed";
1301
1300
  try {
1302
1301
  const throttleConfig = await this.EmailThrottleConfig.getConfig();
1302
+ const sendWindow = throttleConfig.sendWindow ?? this.config.options?.sendWindow;
1303
+ if (sendWindow) {
1304
+ const { startHour, endHour, timezone } = sendWindow;
1305
+ const now2 = /* @__PURE__ */ new Date();
1306
+ const formatter = new Intl.DateTimeFormat("en-US", { hour: "numeric", hour12: false, timeZone: timezone });
1307
+ const currentHour = parseInt(formatter.format(now2), 10);
1308
+ if (currentHour < startHour || currentHour >= endHour) {
1309
+ this.logger.info("Outside send window, skipping run", { currentHour, startHour, endHour, timezone });
1310
+ return { runId };
1311
+ }
1312
+ }
1303
1313
  const allActiveRules = await this.EmailRule.findActive();
1304
1314
  const now = /* @__PURE__ */ new Date();
1305
- const tz = this.config.options?.sendWindow?.timezone;
1315
+ const tz = sendWindow?.timezone ?? this.config.options?.sendWindow?.timezone;
1306
1316
  const activeRules = allActiveRules.filter((rule) => {
1307
1317
  if (rule.validFrom) {
1308
1318
  const localNow = getLocalDate(now, tz);
@@ -2204,7 +2214,7 @@ function createSettingsController(EmailThrottleConfig) {
2204
2214
  res.json({ success: true, data: { config } });
2205
2215
  });
2206
2216
  const updateThrottleConfig = asyncHandler(async (req, res) => {
2207
- const { maxPerUserPerDay, maxPerUserPerWeek, minGapDays } = req.body;
2217
+ const { maxPerUserPerDay, maxPerUserPerWeek, minGapDays, sendWindow } = req.body;
2208
2218
  const updates = {};
2209
2219
  if (maxPerUserPerDay !== void 0) {
2210
2220
  if (!Number.isInteger(maxPerUserPerDay) || maxPerUserPerDay < 1) {
@@ -2224,6 +2234,23 @@ function createSettingsController(EmailThrottleConfig) {
2224
2234
  }
2225
2235
  updates.minGapDays = minGapDays;
2226
2236
  }
2237
+ if (sendWindow !== void 0) {
2238
+ if (sendWindow === null) {
2239
+ updates.sendWindow = void 0;
2240
+ } else {
2241
+ const { startHour, endHour, timezone } = sendWindow;
2242
+ if (!Number.isInteger(startHour) || startHour < 0 || startHour > 23) {
2243
+ return res.status(400).json({ success: false, error: "sendWindow.startHour must be an integer 0-23" });
2244
+ }
2245
+ if (!Number.isInteger(endHour) || endHour < 0 || endHour > 23) {
2246
+ return res.status(400).json({ success: false, error: "sendWindow.endHour must be an integer 0-23" });
2247
+ }
2248
+ if (typeof timezone !== "string" || !timezone.trim()) {
2249
+ return res.status(400).json({ success: false, error: "sendWindow.timezone must be a non-empty string" });
2250
+ }
2251
+ updates.sendWindow = { startHour, endHour, timezone: timezone.trim() };
2252
+ }
2253
+ }
2227
2254
  if (Object.keys(updates).length === 0) {
2228
2255
  return res.status(400).json({ success: false, error: "No valid fields to update" });
2229
2256
  }
@@ -2233,9 +2260,21 @@ function createSettingsController(EmailThrottleConfig) {
2233
2260
  if (finalWeekly < finalDaily) {
2234
2261
  return res.status(400).json({ success: false, error: "maxPerUserPerWeek must be >= maxPerUserPerDay" });
2235
2262
  }
2263
+ const setFields = {};
2264
+ const unsetFields = {};
2265
+ for (const [key, value] of Object.entries(updates)) {
2266
+ if (value === void 0) {
2267
+ unsetFields[key] = "";
2268
+ } else {
2269
+ setFields[key] = value;
2270
+ }
2271
+ }
2272
+ const updateOp = {};
2273
+ if (Object.keys(setFields).length > 0) updateOp["$set"] = setFields;
2274
+ if (Object.keys(unsetFields).length > 0) updateOp["$unset"] = unsetFields;
2236
2275
  const updated = await EmailThrottleConfig.findByIdAndUpdate(
2237
2276
  config._id,
2238
- { $set: updates },
2277
+ updateOp,
2239
2278
  { new: true }
2240
2279
  );
2241
2280
  res.json({ success: true, data: { config: updated } });