mailery 0.9.0 → 0.10.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/admin/spa/index-BTww-4AA.js +41 -0
- package/dist/admin/spa/index-BTww-4AA.js.map +1 -0
- package/dist/admin/spa/index.html +1 -1
- package/dist/admin/spa/{template-editor-DwMKy5sw.js → template-editor-CrOKLpSw.js} +2 -2
- package/dist/admin/spa/{template-editor-DwMKy5sw.js.map → template-editor-CrOKLpSw.js.map} +1 -1
- package/dist/index.cjs +63 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +63 -6
- package/dist/index.js.map +1 -1
- package/dist/{null-BRSHAxvg.d.cts → null-CU_EApC6.d.cts} +16 -0
- package/dist/{null-BRSHAxvg.d.ts → null-CU_EApC6.d.ts} +16 -0
- package/dist/testing.cjs +56 -5
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +56 -5
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/admin/spa/index-B3ndbezm.js +0 -41
- package/dist/admin/spa/index-B3ndbezm.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-
|
|
2
|
-
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-
|
|
1
|
+
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-CU_EApC6.cjs';
|
|
2
|
+
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-CU_EApC6.cjs';
|
|
3
3
|
import { ObjectId, Db, Filter } from 'mongodb';
|
|
4
4
|
import { Request, Router } from 'express';
|
|
5
5
|
import Handlebars from 'handlebars';
|
|
@@ -367,7 +367,7 @@ interface FlowStepKindOption {
|
|
|
367
367
|
}
|
|
368
368
|
declare const FLOW_STEP_KINDS: readonly FlowStepKindOption[];
|
|
369
369
|
declare function defaultFlowStep(type: FlowStep['type']): FlowStep;
|
|
370
|
-
type PredicateKind = 'hasTag' | 'notHasTag' | 'fieldEquals' | 'fieldExists' | 'hasFiredEvent' | 'notHasFiredEvent' | 'subscriptionStatus' | 'hasOpened' | 'hasClicked' | 'hasOpenedExcludingBots' | 'hasClickedExcludingBots' | 'openedAtLeastN' | 'clickedAtLeastN';
|
|
370
|
+
type PredicateKind = 'hasTag' | 'notHasTag' | 'fieldEquals' | 'fieldExists' | 'triggerPropertyEquals' | 'triggerPropertyTruthy' | 'hasFiredEvent' | 'notHasFiredEvent' | 'subscriptionStatus' | 'hasOpened' | 'hasClicked' | 'hasOpenedExcludingBots' | 'hasClickedExcludingBots' | 'openedAtLeastN' | 'clickedAtLeastN';
|
|
371
371
|
interface PredicateKindOption {
|
|
372
372
|
value: PredicateKind;
|
|
373
373
|
label: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-
|
|
2
|
-
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-
|
|
1
|
+
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-CU_EApC6.js';
|
|
2
|
+
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-CU_EApC6.js';
|
|
3
3
|
import { ObjectId, Db, Filter } from 'mongodb';
|
|
4
4
|
import { Request, Router } from 'express';
|
|
5
5
|
import Handlebars from 'handlebars';
|
|
@@ -367,7 +367,7 @@ interface FlowStepKindOption {
|
|
|
367
367
|
}
|
|
368
368
|
declare const FLOW_STEP_KINDS: readonly FlowStepKindOption[];
|
|
369
369
|
declare function defaultFlowStep(type: FlowStep['type']): FlowStep;
|
|
370
|
-
type PredicateKind = 'hasTag' | 'notHasTag' | 'fieldEquals' | 'fieldExists' | 'hasFiredEvent' | 'notHasFiredEvent' | 'subscriptionStatus' | 'hasOpened' | 'hasClicked' | 'hasOpenedExcludingBots' | 'hasClickedExcludingBots' | 'openedAtLeastN' | 'clickedAtLeastN';
|
|
370
|
+
type PredicateKind = 'hasTag' | 'notHasTag' | 'fieldEquals' | 'fieldExists' | 'triggerPropertyEquals' | 'triggerPropertyTruthy' | 'hasFiredEvent' | 'notHasFiredEvent' | 'subscriptionStatus' | 'hasOpened' | 'hasClicked' | 'hasOpenedExcludingBots' | 'hasClickedExcludingBots' | 'openedAtLeastN' | 'clickedAtLeastN';
|
|
371
371
|
interface PredicateKindOption {
|
|
372
372
|
value: PredicateKind;
|
|
373
373
|
label: string;
|
package/dist/index.js
CHANGED
|
@@ -396,7 +396,25 @@ var tagInputSchema = z.object({
|
|
|
396
396
|
var abortFlowInputSchema = z.object({
|
|
397
397
|
flowSlug: slugSchema,
|
|
398
398
|
externalId: externalIdSchema,
|
|
399
|
-
reason: z.string().min(1).max(200).optional()
|
|
399
|
+
reason: z.string().min(1).max(200).optional(),
|
|
400
|
+
/**
|
|
401
|
+
* Restrict the abort to runs whose trigger event carried these properties —
|
|
402
|
+
* e.g. `{ accountId }` to cancel one account's series while the same
|
|
403
|
+
* contact's other accounts keep running. Omit to abort every active run for
|
|
404
|
+
* the contact on this flow.
|
|
405
|
+
*
|
|
406
|
+
* Keys and values are both constrained because these go straight into a
|
|
407
|
+
* Mongo query. Values are primitives only: an object value like
|
|
408
|
+
* `{ $ne: null }` would reach the query as an OPERATOR and match every
|
|
409
|
+
* scoped run, turning a one-account abort into abort-everything. Hosts
|
|
410
|
+
* typically pass an id from a request body, so treat it as untrusted. The
|
|
411
|
+
* key regex likewise blocks `$`-prefixed keys and dots (a dot would silently
|
|
412
|
+
* extend the path and change match semantics).
|
|
413
|
+
*/
|
|
414
|
+
matchTriggerProperties: z.record(
|
|
415
|
+
z.string().regex(/^[A-Za-z0-9_]+$/),
|
|
416
|
+
z.union([z.string(), z.number(), z.boolean(), z.null()])
|
|
417
|
+
).optional()
|
|
400
418
|
});
|
|
401
419
|
var abortAllFlowsInputSchema = abortFlowInputSchema.omit({ flowSlug: true });
|
|
402
420
|
var sendOneOffInputSchema = z.object({
|
|
@@ -465,6 +483,13 @@ var predicateSchema = z.lazy(
|
|
|
465
483
|
z.object({ notHasTag: z.string() }),
|
|
466
484
|
z.object({ fieldEquals: z.object({ field: z.string(), value: z.unknown() }) }),
|
|
467
485
|
z.object({ fieldExists: z.string() }),
|
|
486
|
+
z.object({
|
|
487
|
+
triggerPropertyEquals: z.object({
|
|
488
|
+
key: z.string().min(1),
|
|
489
|
+
value: z.union([z.string(), z.number(), z.boolean(), z.null()])
|
|
490
|
+
})
|
|
491
|
+
}),
|
|
492
|
+
z.object({ triggerPropertyTruthy: z.string().min(1) }),
|
|
468
493
|
z.object({
|
|
469
494
|
hasFiredEvent: z.string(),
|
|
470
495
|
sinceFlowStart: z.boolean().optional(),
|
|
@@ -1648,6 +1673,12 @@ async function evaluatePredicate(predicate, ctx) {
|
|
|
1648
1673
|
if ("fieldExists" in p) {
|
|
1649
1674
|
return ctx.contact.fields[p.fieldExists] !== void 0;
|
|
1650
1675
|
}
|
|
1676
|
+
if ("triggerPropertyEquals" in p) {
|
|
1677
|
+
return (ctx.run.triggerEvent?.properties ?? {})[p.triggerPropertyEquals.key] === p.triggerPropertyEquals.value;
|
|
1678
|
+
}
|
|
1679
|
+
if ("triggerPropertyTruthy" in p) {
|
|
1680
|
+
return Boolean((ctx.run.triggerEvent?.properties ?? {})[p.triggerPropertyTruthy]);
|
|
1681
|
+
}
|
|
1651
1682
|
if ("subscriptionStatus" in p) {
|
|
1652
1683
|
const sub = await ctx.collections.subscriptions.findOne({ externalId: ctx.contact.externalId });
|
|
1653
1684
|
return sub?.status === p.subscriptionStatus;
|
|
@@ -2400,7 +2431,14 @@ async function handleFireEvent(run, step, ctx) {
|
|
|
2400
2431
|
await ctx.collections.events.insertOne({
|
|
2401
2432
|
externalId: run.externalId,
|
|
2402
2433
|
name: step.eventName,
|
|
2403
|
-
|
|
2434
|
+
// Inherit the triggering event's properties so a handoff carries the
|
|
2435
|
+
// context that identifies what the run is ABOUT (which account, order,
|
|
2436
|
+
// subscription, ...). A step's `properties` are static — authored once in
|
|
2437
|
+
// the flow definition — so without this a fired event can only ever say
|
|
2438
|
+
// "this contact", losing the scope the originating event supplied, and
|
|
2439
|
+
// the receiving flow has nothing to resolve variables against. Explicit
|
|
2440
|
+
// step.properties win on conflict.
|
|
2441
|
+
properties: { ...run.triggerEvent?.properties ?? {}, ...step.properties ?? {} },
|
|
2404
2442
|
dedupeKey,
|
|
2405
2443
|
occurredAt: /* @__PURE__ */ new Date(),
|
|
2406
2444
|
createdAt: /* @__PURE__ */ new Date()
|
|
@@ -4235,14 +4273,25 @@ var Mailer = class _Mailer {
|
|
|
4235
4273
|
* same handler that processes the business event ("user upgraded").
|
|
4236
4274
|
*/
|
|
4237
4275
|
async abortFlow(flowSlug, externalId, opts = {}) {
|
|
4238
|
-
const parsed = abortFlowInputSchema.parse({
|
|
4276
|
+
const parsed = abortFlowInputSchema.parse({
|
|
4277
|
+
flowSlug,
|
|
4278
|
+
externalId,
|
|
4279
|
+
reason: opts.reason,
|
|
4280
|
+
matchTriggerProperties: opts.matchTriggerProperties
|
|
4281
|
+
});
|
|
4239
4282
|
const flow = await this.collections.flows.findOne(
|
|
4240
4283
|
{ slug: parsed.flowSlug },
|
|
4241
4284
|
{ projection: { _id: 1 } }
|
|
4242
4285
|
);
|
|
4243
4286
|
if (!flow) throw new Error(`abortFlow: unknown flow slug "${parsed.flowSlug}"`);
|
|
4287
|
+
const triggerMatch = Object.fromEntries(
|
|
4288
|
+
Object.entries(parsed.matchTriggerProperties ?? {}).map(([k, v]) => [
|
|
4289
|
+
`triggerEvent.properties.${k}`,
|
|
4290
|
+
v
|
|
4291
|
+
])
|
|
4292
|
+
);
|
|
4244
4293
|
const result = await this.abortActiveRuns(
|
|
4245
|
-
{ externalId: parsed.externalId, flowId: flow._id },
|
|
4294
|
+
{ externalId: parsed.externalId, flowId: flow._id, ...triggerMatch },
|
|
4246
4295
|
parsed.reason ? `aborted_by_host:${parsed.reason}` : "aborted_by_host"
|
|
4247
4296
|
);
|
|
4248
4297
|
if (result.abortedRuns > 0 || result.cancelledSends > 0) {
|
|
@@ -4250,7 +4299,9 @@ var Mailer = class _Mailer {
|
|
|
4250
4299
|
actor: "host",
|
|
4251
4300
|
action: "flow.abort",
|
|
4252
4301
|
resource: { collection: "mailer_flow_runs", slug: parsed.flowSlug },
|
|
4253
|
-
|
|
4302
|
+
// Record the scope: without it a one-account abort and an abort-every-
|
|
4303
|
+
// run-for-this-contact are indistinguishable in the audit trail.
|
|
4304
|
+
diffSummary: `abortFlow slug=${parsed.flowSlug} externalId=${parsed.externalId} scope=${parsed.matchTriggerProperties ? JSON.stringify(parsed.matchTriggerProperties) : "all"} runs=${result.abortedRuns} sends=${result.cancelledSends}${parsed.reason ? ` reason=${parsed.reason}` : ""}`
|
|
4254
4305
|
});
|
|
4255
4306
|
}
|
|
4256
4307
|
return result;
|
|
@@ -7416,6 +7467,8 @@ var PREDICATE_KINDS = [
|
|
|
7416
7467
|
{ value: "notHasTag", label: "does NOT have tag" },
|
|
7417
7468
|
{ value: "fieldEquals", label: "field equals" },
|
|
7418
7469
|
{ value: "fieldExists", label: "field exists" },
|
|
7470
|
+
{ value: "triggerPropertyEquals", label: "trigger property equals" },
|
|
7471
|
+
{ value: "triggerPropertyTruthy", label: "trigger property is set" },
|
|
7419
7472
|
{ value: "hasFiredEvent", label: "fired event" },
|
|
7420
7473
|
{ value: "notHasFiredEvent", label: "has NOT fired event" },
|
|
7421
7474
|
{ value: "subscriptionStatus", label: "subscription status" },
|
|
@@ -7443,6 +7496,10 @@ function defaultPredicate(kind) {
|
|
|
7443
7496
|
return { fieldEquals: { field: "tier", value: "Pro" } };
|
|
7444
7497
|
case "fieldExists":
|
|
7445
7498
|
return { fieldExists: "tier" };
|
|
7499
|
+
case "triggerPropertyEquals":
|
|
7500
|
+
return { triggerPropertyEquals: { key: "plan", value: "pro" } };
|
|
7501
|
+
case "triggerPropertyTruthy":
|
|
7502
|
+
return { triggerPropertyTruthy: "wasReferred" };
|
|
7446
7503
|
case "hasFiredEvent":
|
|
7447
7504
|
return { hasFiredEvent: "Activated app" };
|
|
7448
7505
|
case "notHasFiredEvent":
|
|
@@ -7533,7 +7590,7 @@ var DEDUPE_POLICIES = [
|
|
|
7533
7590
|
];
|
|
7534
7591
|
|
|
7535
7592
|
// src/server/index.ts
|
|
7536
|
-
var VERSION = "0.
|
|
7593
|
+
var VERSION = "0.10.0" ;
|
|
7537
7594
|
|
|
7538
7595
|
export { DEDUPE_POLICIES, FLOW_STEP_KINDS, Mailer, MongoContactAdapter, NullProvider, PREDICATE_KINDS, RESERVED_VAR_KEYS, SEGMENT_FILTER_KINDS, SendGridProvider, VERSION, applyTracking, applyWebhookEvent, compileMailyTemplate, compileTemplate, computeDeliveryTime, createAdminRouter, createPublicRouter, defaultFlowStep, defaultPredicate, defaultSegmentFilter, defineVars, derivePlaintext, dispatchSend, ensureIndexes, getCollections, predicateKind, processNewlyFiredEventTriggers, processOneRunStep, renderTemplate, runTick, sha256Hex, signUnsubscribeToken, sweepStrandedFlowRuns, validateSenderDomain, varsJsonSchema, verifyUnsubscribeToken };
|
|
7539
7596
|
//# sourceMappingURL=index.js.map
|