@memberjunction/communication-engine 5.34.1 → 5.36.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.
@@ -0,0 +1,75 @@
1
+ import { UserInfo, type IMetadataProvider } from '@memberjunction/core';
2
+ import { type Message, type MessageResult, type ProviderCredentialsBase } from '@memberjunction/communication-types';
3
+ import type { AudienceSource } from '@memberjunction/lists-base';
4
+ /**
5
+ * Reasons a record was excluded from a `SendToAudience` send. The set is
6
+ * intentionally small — anything more granular belongs in the underlying
7
+ * provider's bounce/return-path handling.
8
+ */
9
+ export type AudienceSkipReason = 'MISSING_RECIPIENT_FIELD' | 'INVALID_RECIPIENT_FIELD';
10
+ export interface AudienceSkipDetail {
11
+ RecordID: string;
12
+ Reason: AudienceSkipReason;
13
+ Message: string;
14
+ }
15
+ /**
16
+ * Result of a `SendToAudience` call. Mirrors the per-message
17
+ * `MessageResult[]` from `SendMessages` and additionally surfaces the
18
+ * audience-resolution metadata so the caller can render an "Audience
19
+ * Summary" panel (per mockup 21) without re-running the resolve.
20
+ */
21
+ export interface SendToAudienceResult {
22
+ TotalAudienceSize: number;
23
+ WillReceiveCount: number;
24
+ SkippedCount: number;
25
+ Skipped: AudienceSkipDetail[];
26
+ Results: MessageResult[];
27
+ /** When `previewOnly` is true, `Results` is empty and this flag indicates we never dispatched. */
28
+ PreviewOnly: boolean;
29
+ }
30
+ /**
31
+ * Args for `SendToAudience`. Kept separate from `Message` because the
32
+ * audience layer adds its own dimensions (source, field mapping) that
33
+ * don't belong on the underlying transport-level `Message` type.
34
+ */
35
+ export interface SendToAudienceParams {
36
+ /** Where the audience comes from — a List, View, or ad-hoc filter. */
37
+ Source: AudienceSource;
38
+ /**
39
+ * Name of the field on the audience entity that holds the recipient
40
+ * address (e.g. `'Email'` for Contacts, `'PhoneNumber'` for SMS). Records
41
+ * that don't have a non-empty value for this field are skipped and
42
+ * surfaced in `Skipped` so the UI can show them to the sender.
43
+ */
44
+ RecipientField: string;
45
+ /** Optional name of a "full name" field, used to populate `MessageRecipient.FullName`. */
46
+ FullNameField?: string;
47
+ /** Provider name (e.g. `'SendGrid'`). Same value the underlying `SendMessages` takes. */
48
+ ProviderName: string;
49
+ /** Provider message type name (e.g. `'SingleEmail'`). */
50
+ ProviderMessageTypeName: string;
51
+ /** Base message — `From`, subject/body, etc. `To` is overwritten per recipient. */
52
+ Message: Message;
53
+ /** Optional per-request credentials override. Forwarded to `SendMessages`. */
54
+ Credentials?: ProviderCredentialsBase;
55
+ /** When true, resolve + build recipient list but don't actually send. */
56
+ PreviewOnly?: boolean;
57
+ /** Context user — required, used for authorization on the underlying provider. */
58
+ ContextUser: UserInfo;
59
+ /** Optional multi-provider scope. Forwarded to the resolver + RunView. */
60
+ Provider?: IMetadataProvider;
61
+ }
62
+ /**
63
+ * Resolve an `AudienceSource` into concrete `MessageRecipient`s, then
64
+ * fan out via `CommunicationEngine.SendMessages`. The translation step
65
+ * is deliberately kept here (not on the engine) because it's
66
+ * audience-aware: it knows about entity primary keys, the recipient
67
+ * field mapping, and the skip-on-missing-field policy.
68
+ *
69
+ * Records whose `RecipientField` is missing or empty are skipped and
70
+ * returned in `Skipped` rather than failing the whole send — matches
71
+ * the plan's "skip records missing the mapped field with a warning"
72
+ * contract.
73
+ */
74
+ export declare function SendToAudience(args: SendToAudienceParams): Promise<SendToAudienceResult>;
75
+ //# sourceMappingURL=SendToAudience.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SendToAudience.d.ts","sourceRoot":"","sources":["../src/SendToAudience.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,QAAQ,EAAE,KAAK,iBAAiB,EAAY,MAAM,sBAAsB,CAAC;AACrG,OAAO,EAAoB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAEvI,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAIjE;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,yBAAyB,GAAG,yBAAyB,CAAC;AAEvF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,kGAAkG;IAClG,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,MAAM,EAAE,cAAc,CAAC;IACvB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,uBAAuB,EAAE,MAAM,CAAC;IAChC,mFAAmF;IACnF,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,yEAAyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kFAAkF;IAClF,WAAW,EAAE,QAAQ,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4G9F"}
@@ -0,0 +1,121 @@
1
+ import { Metadata, RunView, LogError } from '@memberjunction/core';
2
+ import { MessageRecipient } from '@memberjunction/communication-types';
3
+ import { AudienceResolver } from '@memberjunction/lists';
4
+ import { CommunicationEngine } from './Engine.js';
5
+ /**
6
+ * Resolve an `AudienceSource` into concrete `MessageRecipient`s, then
7
+ * fan out via `CommunicationEngine.SendMessages`. The translation step
8
+ * is deliberately kept here (not on the engine) because it's
9
+ * audience-aware: it knows about entity primary keys, the recipient
10
+ * field mapping, and the skip-on-missing-field policy.
11
+ *
12
+ * Records whose `RecipientField` is missing or empty are skipped and
13
+ * returned in `Skipped` rather than failing the whole send — matches
14
+ * the plan's "skip records missing the mapped field with a warning"
15
+ * contract.
16
+ */
17
+ export async function SendToAudience(args) {
18
+ // 1. Resolve the audience.
19
+ const resolver = new AudienceResolver(args.ContextUser, args.Provider);
20
+ const resolved = await resolver.Resolve(args.Source);
21
+ const total = resolved.RecordIds.length;
22
+ if (total === 0) {
23
+ return emptyResult(args.PreviewOnly === true);
24
+ }
25
+ // 2. Bulk-load the underlying records so we can extract the recipient field.
26
+ const md = args.Provider ?? new Metadata();
27
+ const entityInfo = md.EntityByName(resolved.EntityName);
28
+ if (!entityInfo) {
29
+ throw new Error(`Entity '${resolved.EntityName}' not found in metadata`);
30
+ }
31
+ const pkFields = entityInfo.PrimaryKeys.map((pk) => pk.Name);
32
+ const fields = unique([...pkFields, args.RecipientField, ...(args.FullNameField ? [args.FullNameField] : [])]);
33
+ const rv = args.Provider ? RunView.FromMetadataProvider(args.Provider) : new RunView();
34
+ // For single-PK entities the resolved IDs are raw values. Composite
35
+ // PKs serialize to `Field1|Value1||Field2|Value2`; we don't support
36
+ // composite-PK recipient lookups here yet — surface clearly and skip.
37
+ if (pkFields.length !== 1) {
38
+ LogError(`SendToAudience: composite-PK entities ('${resolved.EntityName}', PK=${pkFields.join('+')}) are not yet supported. ` +
39
+ 'All records will be reported as skipped.');
40
+ return {
41
+ TotalAudienceSize: total,
42
+ WillReceiveCount: 0,
43
+ SkippedCount: total,
44
+ Skipped: resolved.RecordIds.map((id) => ({
45
+ RecordID: id,
46
+ Reason: 'INVALID_RECIPIENT_FIELD',
47
+ Message: 'Composite-PK entities are not yet supported for SendToAudience',
48
+ })),
49
+ Results: [],
50
+ PreviewOnly: args.PreviewOnly === true,
51
+ };
52
+ }
53
+ const pk = pkFields[0];
54
+ const idList = resolved.RecordIds.map((id) => `'${id.replace(/'/g, "''")}'`).join(',');
55
+ const loadResult = await rv.RunView({
56
+ EntityName: resolved.EntityName,
57
+ ExtraFilter: `${pk} IN (${idList})`,
58
+ Fields: fields,
59
+ ResultType: 'simple',
60
+ }, args.ContextUser);
61
+ if (!loadResult.Success) {
62
+ throw new Error(`Failed to load audience records: ${loadResult.ErrorMessage}`);
63
+ }
64
+ // 3. Build recipients + collect skip reasons.
65
+ const recipients = [];
66
+ const skipped = [];
67
+ for (const row of loadResult.Results ?? []) {
68
+ const recordId = String(row[pk]);
69
+ const to = row[args.RecipientField];
70
+ const toStr = to == null ? '' : String(to).trim();
71
+ if (toStr.length === 0) {
72
+ skipped.push({
73
+ RecordID: recordId,
74
+ Reason: 'MISSING_RECIPIENT_FIELD',
75
+ Message: `Record has no ${args.RecipientField} value`,
76
+ });
77
+ continue;
78
+ }
79
+ const recipient = new MessageRecipient();
80
+ recipient.To = toStr;
81
+ if (args.FullNameField && row[args.FullNameField] != null) {
82
+ recipient.FullName = String(row[args.FullNameField]);
83
+ }
84
+ recipient.ContextData = row;
85
+ recipients.push(recipient);
86
+ }
87
+ // 4. Either preview-only return, or fan out via the engine.
88
+ if (args.PreviewOnly) {
89
+ return {
90
+ TotalAudienceSize: total,
91
+ WillReceiveCount: recipients.length,
92
+ SkippedCount: skipped.length,
93
+ Skipped: skipped,
94
+ Results: [],
95
+ PreviewOnly: true,
96
+ };
97
+ }
98
+ const results = await CommunicationEngine.Instance.SendMessages(args.ProviderName, args.ProviderMessageTypeName, args.Message, recipients, false, args.Credentials);
99
+ return {
100
+ TotalAudienceSize: total,
101
+ WillReceiveCount: recipients.length,
102
+ SkippedCount: skipped.length,
103
+ Skipped: skipped,
104
+ Results: results,
105
+ PreviewOnly: false,
106
+ };
107
+ }
108
+ function emptyResult(previewOnly) {
109
+ return {
110
+ TotalAudienceSize: 0,
111
+ WillReceiveCount: 0,
112
+ SkippedCount: 0,
113
+ Skipped: [],
114
+ Results: [],
115
+ PreviewOnly: previewOnly,
116
+ };
117
+ }
118
+ function unique(items) {
119
+ return Array.from(new Set(items));
120
+ }
121
+ //# sourceMappingURL=SendToAudience.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SendToAudience.js","sourceRoot":"","sources":["../src/SendToAudience.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './Engine.js';
2
2
  export * from './BaseProvider.js';
3
+ export * from './SendToAudience.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // PUBLIC API SURFACE AREA
2
2
  export * from './Engine.js';
3
3
  export * from './BaseProvider.js';
4
+ export * from './SendToAudience.js';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/communication-engine",
3
3
  "type": "module",
4
- "version": "5.34.1",
4
+ "version": "5.36.0",
5
5
  "description": "MemberJunction: Core Communication Framework Library",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -11,7 +11,8 @@
11
11
  "scripts": {
12
12
  "start": "ts-node-dev src/index.ts",
13
13
  "build": "tsc && tsc-alias -f",
14
- "test": "echo \"No tests configured yet\""
14
+ "test": "vitest run",
15
+ "test:watch": "vitest"
15
16
  },
16
17
  "author": "MemberJunction.com",
17
18
  "license": "ISC",
@@ -20,11 +21,13 @@
20
21
  "typescript": "^5.9.3"
21
22
  },
22
23
  "dependencies": {
23
- "@memberjunction/global": "5.34.1",
24
- "@memberjunction/core": "5.34.1",
25
- "@memberjunction/templates": "5.34.1",
26
- "@memberjunction/core-entities": "5.34.1",
27
- "@memberjunction/communication-types": "5.34.1",
24
+ "@memberjunction/global": "5.36.0",
25
+ "@memberjunction/core": "5.36.0",
26
+ "@memberjunction/templates": "5.36.0",
27
+ "@memberjunction/core-entities": "5.36.0",
28
+ "@memberjunction/communication-types": "5.36.0",
29
+ "@memberjunction/lists": "5.36.0",
30
+ "@memberjunction/lists-base": "5.36.0",
28
31
  "rxjs": "^7.8.2"
29
32
  },
30
33
  "repository": {