@astralibx/email-rule-engine 12.10.0 → 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/README.md +1 -0
- package/dist/index.cjs +60 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.mjs +60 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -128,7 +128,7 @@ interface QueryTarget {
|
|
|
128
128
|
role: string;
|
|
129
129
|
platform: string;
|
|
130
130
|
conditions: RuleCondition[];
|
|
131
|
-
|
|
131
|
+
collectionName?: string;
|
|
132
132
|
}
|
|
133
133
|
interface ListTarget {
|
|
134
134
|
mode: 'list';
|
|
@@ -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
|
@@ -128,7 +128,7 @@ interface QueryTarget {
|
|
|
128
128
|
role: string;
|
|
129
129
|
platform: string;
|
|
130
130
|
conditions: RuleCondition[];
|
|
131
|
-
|
|
131
|
+
collectionName?: string;
|
|
132
132
|
}
|
|
133
133
|
interface ListTarget {
|
|
134
134
|
mode: 'list';
|
|
@@ -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
|
@@ -198,7 +198,7 @@ function createEmailRuleSchema(platformValues, audienceValues, collectionPrefix)
|
|
|
198
198
|
},
|
|
199
199
|
conditions: [RuleConditionSchema],
|
|
200
200
|
identifiers: [{ type: String }],
|
|
201
|
-
|
|
201
|
+
collectionName: { type: String }
|
|
202
202
|
}, { _id: false });
|
|
203
203
|
const RuleRunStatsSchema = createRunStatsSchema();
|
|
204
204
|
const schema = new Schema(
|
|
@@ -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,
|
|
@@ -1086,8 +1095,8 @@ var RuleService = class {
|
|
|
1086
1095
|
throw new RuleTemplateIncompatibleError("target.identifiers must be a non-empty array for list mode, validation failed");
|
|
1087
1096
|
}
|
|
1088
1097
|
}
|
|
1089
|
-
if (isQueryTarget(input.target) && input.target.
|
|
1090
|
-
const condErrors = validateConditions(input.target.conditions, input.target.
|
|
1098
|
+
if (isQueryTarget(input.target) && input.target.collectionName && this.config.collections?.length) {
|
|
1099
|
+
const condErrors = validateConditions(input.target.conditions, input.target.collectionName, this.config.collections);
|
|
1091
1100
|
if (condErrors.length > 0) {
|
|
1092
1101
|
throw new RuleTemplateIncompatibleError(
|
|
1093
1102
|
`Invalid conditions: ${condErrors.map((e) => e.message).join("; ")}`
|
|
@@ -1125,8 +1134,8 @@ var RuleService = class {
|
|
|
1125
1134
|
}
|
|
1126
1135
|
if (isQueryTarget(effectiveTarget)) {
|
|
1127
1136
|
const qt = effectiveTarget;
|
|
1128
|
-
if (qt.
|
|
1129
|
-
const condErrors = validateConditions(qt.conditions || [], qt.
|
|
1137
|
+
if (qt.collectionName && this.config.collections?.length) {
|
|
1138
|
+
const condErrors = validateConditions(qt.conditions || [], qt.collectionName, this.config.collections);
|
|
1130
1139
|
if (condErrors.length > 0) {
|
|
1131
1140
|
throw new RuleTemplateIncompatibleError(
|
|
1132
1141
|
`Invalid conditions: ${condErrors.map((e) => e.message).join("; ")}`
|
|
@@ -1184,7 +1193,7 @@ var RuleService = class {
|
|
|
1184
1193
|
return { matchedCount: matchedCount2, effectiveLimit, willProcess: willProcess2, ruleId: id, sample: sample2 };
|
|
1185
1194
|
}
|
|
1186
1195
|
const queryTarget = rule.target;
|
|
1187
|
-
const collectionName = queryTarget.
|
|
1196
|
+
const collectionName = queryTarget.collectionName;
|
|
1188
1197
|
const collectionSchema = collectionName ? this.config.collections?.find((c) => c.name === collectionName) : void 0;
|
|
1189
1198
|
const users = await this.config.adapters.queryUsers(rule.target, 5e4, collectionSchema ? { collectionSchema } : void 0);
|
|
1190
1199
|
const matchedCount = users.length;
|
|
@@ -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);
|
|
@@ -1703,7 +1713,7 @@ var RuleRunnerService = class {
|
|
|
1703
1713
|
const limit = rule.maxPerRun || this.config.options?.defaultMaxPerRun || 500;
|
|
1704
1714
|
let users;
|
|
1705
1715
|
try {
|
|
1706
|
-
const collectionName = rule.target?.
|
|
1716
|
+
const collectionName = rule.target?.collectionName;
|
|
1707
1717
|
const collectionSchema = collectionName ? this.config.collections?.find((c) => c.name === collectionName) : void 0;
|
|
1708
1718
|
users = await this.config.adapters.queryUsers(rule.target, limit, collectionSchema ? { collectionSchema } : void 0);
|
|
1709
1719
|
} catch (err) {
|
|
@@ -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
|
-
|
|
2277
|
+
updateOp,
|
|
2239
2278
|
{ new: true }
|
|
2240
2279
|
);
|
|
2241
2280
|
res.json({ success: true, data: { config: updated } });
|