@mj-biz-apps/common-activity-sync 0.0.0 → 5.37.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/ActivitySyncEngine.d.ts +118 -0
- package/dist/ActivitySyncEngine.d.ts.map +1 -0
- package/dist/ActivitySyncEngine.js +620 -0
- package/dist/ActivitySyncEngine.js.map +1 -0
- package/dist/BaseActivitySyncExtension.d.ts +99 -0
- package/dist/BaseActivitySyncExtension.d.ts.map +1 -0
- package/dist/BaseActivitySyncExtension.js +3 -0
- package/dist/BaseActivitySyncExtension.js.map +1 -0
- package/dist/BaseActivitySyncProvider.d.ts +40 -0
- package/dist/BaseActivitySyncProvider.d.ts.map +1 -0
- package/dist/BaseActivitySyncProvider.js +76 -0
- package/dist/BaseActivitySyncProvider.js.map +1 -0
- package/dist/action-result.d.ts +38 -0
- package/dist/action-result.d.ts.map +1 -0
- package/dist/action-result.js +43 -0
- package/dist/action-result.js.map +1 -0
- package/dist/entity-names.d.ts +19 -0
- package/dist/entity-names.d.ts.map +1 -0
- package/dist/entity-names.js +19 -0
- package/dist/entity-names.js.map +1 -0
- package/dist/extensions.d.ts +37 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +80 -0
- package/dist/extensions.js.map +1 -0
- package/dist/identity.d.ts +30 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +90 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/load.d.ts +17 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +29 -0
- package/dist/load.js.map +1 -0
- package/dist/manual-log.d.ts +33 -0
- package/dist/manual-log.d.ts.map +1 -0
- package/dist/manual-log.js +230 -0
- package/dist/manual-log.js.map +1 -0
- package/dist/participants.d.ts +47 -0
- package/dist/participants.d.ts.map +1 -0
- package/dist/participants.js +59 -0
- package/dist/participants.js.map +1 -0
- package/dist/providers/FixtureActivitySyncProvider.d.ts +21 -0
- package/dist/providers/FixtureActivitySyncProvider.d.ts.map +1 -0
- package/dist/providers/FixtureActivitySyncProvider.js +58 -0
- package/dist/providers/FixtureActivitySyncProvider.js.map +1 -0
- package/dist/providers/GraphMessageMapper.d.ts +37 -0
- package/dist/providers/GraphMessageMapper.d.ts.map +1 -0
- package/dist/providers/GraphMessageMapper.js +91 -0
- package/dist/providers/GraphMessageMapper.js.map +1 -0
- package/dist/providers/MSGraphActivitySyncProvider.d.ts +22 -0
- package/dist/providers/MSGraphActivitySyncProvider.d.ts.map +1 -0
- package/dist/providers/MSGraphActivitySyncProvider.js +62 -0
- package/dist/providers/MSGraphActivitySyncProvider.js.map +1 -0
- package/dist/providers/MSGraphCalendarSyncProvider.d.ts +60 -0
- package/dist/providers/MSGraphCalendarSyncProvider.d.ts.map +1 -0
- package/dist/providers/MSGraphCalendarSyncProvider.js +145 -0
- package/dist/providers/MSGraphCalendarSyncProvider.js.map +1 -0
- package/dist/qualification.d.ts +91 -0
- package/dist/qualification.d.ts.map +1 -0
- package/dist/qualification.js +62 -0
- package/dist/qualification.js.map +1 -0
- package/dist/run.d.ts +67 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +84 -0
- package/dist/run.js.map +1 -0
- package/dist/sql.d.ts +17 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +50 -0
- package/dist/sql.js.map +1 -0
- package/dist/stages.d.ts +55 -0
- package/dist/stages.d.ts.map +1 -0
- package/dist/stages.js +109 -0
- package/dist/stages.js.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +38 -0
- package/dist/types.js.map +1 -0
- package/dist/watermark.d.ts +63 -0
- package/dist/watermark.d.ts.map +1 -0
- package/dist/watermark.js +103 -0
- package/dist/watermark.js.map +1 -0
- package/dist/writer.d.ts +132 -0
- package/dist/writer.d.ts.map +1 -0
- package/dist/writer.js +326 -0
- package/dist/writer.js.map +1 -0
- package/package.json +32 -5
- package/README.md +0 -12
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw Microsoft Graph message JSON → NormalizedItem.
|
|
3
|
+
*
|
|
4
|
+
* Maps Graph's own payload, not MJ's Message shape (GetMessages sets To from replyTo[0]).
|
|
5
|
+
*/
|
|
6
|
+
import type { NormalizedItem } from '../types.js';
|
|
7
|
+
export interface GraphEmailAddress {
|
|
8
|
+
name?: string | null;
|
|
9
|
+
address?: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface GraphRecipient {
|
|
12
|
+
emailAddress?: GraphEmailAddress | null;
|
|
13
|
+
}
|
|
14
|
+
export interface GraphMessage {
|
|
15
|
+
id?: string | null;
|
|
16
|
+
conversationId?: string | null;
|
|
17
|
+
subject?: string | null;
|
|
18
|
+
bodyPreview?: string | null;
|
|
19
|
+
body?: {
|
|
20
|
+
content?: string | null;
|
|
21
|
+
} | null;
|
|
22
|
+
sentDateTime?: string | null;
|
|
23
|
+
receivedDateTime?: string | null;
|
|
24
|
+
from?: GraphRecipient | null;
|
|
25
|
+
sender?: GraphRecipient | null;
|
|
26
|
+
toRecipients?: GraphRecipient[] | null;
|
|
27
|
+
ccRecipients?: GraphRecipient[] | null;
|
|
28
|
+
bccRecipients?: GraphRecipient[] | null;
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
export interface MapResult {
|
|
32
|
+
Items: NormalizedItem[];
|
|
33
|
+
Issues: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare function MapGraphMessage(message: GraphMessage, mailbox: string, issues: string[]): NormalizedItem | null;
|
|
36
|
+
export declare function MapGraphMessages(payload: unknown, mailbox: string): MapResult;
|
|
37
|
+
//# sourceMappingURL=GraphMessageMapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphMessageMapper.d.ts","sourceRoot":"","sources":["../../src/providers/GraphMessageMapper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAsC,cAAc,EAAE,MAAM,aAAa,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC3B,YAAY,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IACvC,YAAY,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IACxC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACtB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AAuCD,wBAAgB,eAAe,CAC3B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EAAE,GACjB,cAAc,GAAG,IAAI,CAsCvB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAkB7E"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
function isUsableAddress(trimmed) {
|
|
2
|
+
if (!trimmed)
|
|
3
|
+
return false;
|
|
4
|
+
const at = trimmed.indexOf('@');
|
|
5
|
+
return at > 0 && at < trimmed.length - 1 && !/\s/.test(trimmed);
|
|
6
|
+
}
|
|
7
|
+
function normalize(value) {
|
|
8
|
+
return value.trim().toLowerCase();
|
|
9
|
+
}
|
|
10
|
+
function participantFrom(recipient, role, issues, context) {
|
|
11
|
+
const ea = recipient?.emailAddress ?? null;
|
|
12
|
+
const raw = (ea?.address ?? '').trim();
|
|
13
|
+
const name = (ea?.name ?? '').trim() || null;
|
|
14
|
+
if (!isUsableAddress(raw)) {
|
|
15
|
+
if (raw) {
|
|
16
|
+
issues.push(`${context}: ${role} address is not usable and was dropped: ${JSON.stringify(raw)}`);
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return { Address: normalize(raw), Name: name, Role: role, IdentityKind: 'Email' };
|
|
21
|
+
}
|
|
22
|
+
function decideDirection(mailbox, participants) {
|
|
23
|
+
const box = normalize(mailbox);
|
|
24
|
+
const from = participants.find((p) => p.Role === 'From');
|
|
25
|
+
const others = participants.filter((p) => p.Role !== 'From' && p.Address !== box);
|
|
26
|
+
const sentByMailbox = !!from && from.Address === box;
|
|
27
|
+
if (sentByMailbox && others.length === 0)
|
|
28
|
+
return 'Internal';
|
|
29
|
+
return sentByMailbox ? 'Outbound' : 'Inbound';
|
|
30
|
+
}
|
|
31
|
+
export function MapGraphMessage(message, mailbox, issues) {
|
|
32
|
+
const id = (message.id ?? '').trim();
|
|
33
|
+
const context = `message ${id ? id.slice(0, 24) : '(no id)'}`;
|
|
34
|
+
if (!id) {
|
|
35
|
+
issues.push('a message arrived with no id and was skipped — it has no dedupe key');
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const participants = [];
|
|
39
|
+
const push = (p) => {
|
|
40
|
+
if (p)
|
|
41
|
+
participants.push(p);
|
|
42
|
+
};
|
|
43
|
+
push(participantFrom(message.from ?? message.sender, 'From', issues, context));
|
|
44
|
+
for (const r of message.toRecipients ?? [])
|
|
45
|
+
push(participantFrom(r, 'To', issues, context));
|
|
46
|
+
for (const r of message.ccRecipients ?? [])
|
|
47
|
+
push(participantFrom(r, 'Cc', issues, context));
|
|
48
|
+
for (const r of message.bccRecipients ?? [])
|
|
49
|
+
push(participantFrom(r, 'Bcc', issues, context));
|
|
50
|
+
const stamp = (message.sentDateTime ?? message.receivedDateTime ?? '').trim();
|
|
51
|
+
const startedAt = stamp ? new Date(stamp) : null;
|
|
52
|
+
if (!startedAt || Number.isNaN(startedAt.getTime())) {
|
|
53
|
+
issues.push(`${context}: no usable sentDateTime/receivedDateTime, skipped`);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
ExternalID: id,
|
|
58
|
+
ExternalThreadID: (message.conversationId ?? '').trim() || null,
|
|
59
|
+
TypeCode: 'Email',
|
|
60
|
+
Subject: (message.subject ?? '').trim() || '(no subject)',
|
|
61
|
+
Body: (message.bodyPreview ?? message.body?.content ?? '').trim() || null,
|
|
62
|
+
StartedAt: startedAt,
|
|
63
|
+
EndedAt: null,
|
|
64
|
+
Location: null,
|
|
65
|
+
Direction: decideDirection(mailbox, participants),
|
|
66
|
+
Participants: participants,
|
|
67
|
+
Cancelled: false,
|
|
68
|
+
Raw: message,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function MapGraphMessages(payload, mailbox) {
|
|
72
|
+
const issues = [];
|
|
73
|
+
const raw = payload;
|
|
74
|
+
const list = Array.isArray(raw)
|
|
75
|
+
? raw
|
|
76
|
+
: Array.isArray(raw?.value)
|
|
77
|
+
? raw.value
|
|
78
|
+
: [];
|
|
79
|
+
if (!list.length) {
|
|
80
|
+
issues.push('payload contained no messages — expected an array or an object with a `value` array');
|
|
81
|
+
return { Items: [], Issues: issues };
|
|
82
|
+
}
|
|
83
|
+
const items = [];
|
|
84
|
+
for (const entry of list) {
|
|
85
|
+
const mapped = MapGraphMessage(entry, mailbox, issues);
|
|
86
|
+
if (mapped)
|
|
87
|
+
items.push(mapped);
|
|
88
|
+
}
|
|
89
|
+
return { Items: items, Issues: issues };
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=GraphMessageMapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphMessageMapper.js","sourceRoot":"","sources":["../../src/providers/GraphMessageMapper.ts"],"names":[],"mappings":"AAqCA,SAAS,eAAe,CAAC,OAAe;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC5B,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,eAAe,CACpB,SAA4C,EAC5C,IAA6B,EAC7B,MAAgB,EAChB,OAAe;IAEf,MAAM,EAAE,GAAG,SAAS,EAAE,YAAY,IAAI,IAAI,CAAC;IAC3C,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC7C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,GAAG,EAAE,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,KAAK,IAAI,2CAA2C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrG,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACtF,CAAC;AAED,SAAS,eAAe,CAAC,OAAe,EAAE,YAA+B;IACrE,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,CAAC;IAClF,MAAM,aAAa,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,CAAC;IACrD,IAAI,aAAa,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC5D,OAAO,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,OAAqB,EACrB,OAAe,EACf,MAAgB;IAEhB,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAC9D,IAAI,CAAC,EAAE,EAAE,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,YAAY,GAAsB,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,CAAyB,EAAQ,EAAE;QAC7C,IAAI,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/E,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,YAAY,IAAI,EAAE;QAAE,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5F,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,YAAY,IAAI,EAAE;QAAE,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5F,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,aAAa,IAAI,EAAE;QAAE,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAE9F,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9E,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,oDAAoD,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO;QACH,UAAU,EAAE,EAAE;QACd,gBAAgB,EAAE,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI;QAC/D,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,cAAc;QACzD,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI;QACzE,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,eAAe,CAAC,OAAO,EAAE,YAAY,CAAC;QACjD,YAAY,EAAE,YAAY;QAC1B,SAAS,EAAE,KAAK;QAChB,GAAG,EAAE,OAAkC;KAC1C,CAAC;AACN,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgB,EAAE,OAAe;IAC9D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,OAAiD,CAAC;IAC9D,MAAM,IAAI,GAAc,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QACtC,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,KAAK,CAAC,OAAO,CAAE,GAA2B,EAAE,KAAK,CAAC;YAClD,CAAC,CAAE,GAA4B,CAAC,KAAK;YACrC,CAAC,CAAC,EAAE,CAAC;IACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAC;QACnG,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACzC,CAAC;IACD,MAAM,KAAK,GAAqB,EAAE,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,eAAe,CAAC,KAAqB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACvE,IAAI,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseActivitySyncProvider } from '../BaseActivitySyncProvider.js';
|
|
2
|
+
import type { ActivitySourceQuery, NormalizedItem, RawBatch } from '../types.js';
|
|
3
|
+
export declare const LIVE_GRAPH_REFUSAL: string;
|
|
4
|
+
export declare class MSGraphActivitySyncProvider extends BaseActivitySyncProvider {
|
|
5
|
+
/**
|
|
6
|
+
* Default FALSE. Turning it on is a deliberate act by someone who has confirmed
|
|
7
|
+
* the Application Access Policy exists. This PR never does that.
|
|
8
|
+
*/
|
|
9
|
+
private readonly AllowLiveFetch;
|
|
10
|
+
readonly Kind: "Message";
|
|
11
|
+
readonly ProviderTypeCode = "Microsoft365";
|
|
12
|
+
readonly IsLive = true;
|
|
13
|
+
constructor(
|
|
14
|
+
/**
|
|
15
|
+
* Default FALSE. Turning it on is a deliberate act by someone who has confirmed
|
|
16
|
+
* the Application Access Policy exists. This PR never does that.
|
|
17
|
+
*/
|
|
18
|
+
AllowLiveFetch?: boolean);
|
|
19
|
+
protected FetchRaw(query: ActivitySourceQuery): Promise<RawBatch>;
|
|
20
|
+
protected Normalize(raw: RawBatch, query: ActivitySourceQuery): NormalizedItem[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=MSGraphActivitySyncProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MSGraphActivitySyncProvider.d.ts","sourceRoot":"","sources":["../../src/providers/MSGraphActivitySyncProvider.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGjF,eAAO,MAAM,kBAAkB,QAI4B,CAAC;AAE5D,qBACa,2BAA4B,SAAQ,wBAAwB;IAMjE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc;IATnC,SAAgB,IAAI,EAAG,SAAS,CAAU;IAC1C,SAAgB,gBAAgB,kBAAkB;IAClD,SAAgB,MAAM,QAAQ;;IAG1B;;;OAGG;IACc,cAAc,GAAE,OAAe;cAKpC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcvE,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,GAAG,cAAc,EAAE;CAOnF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Microsoft Graph mail. Written, typechecked, and refused until an Exchange Application
|
|
12
|
+
* Access Policy scopes app-only Mail.Read. Fixture is how the engine is exercised.
|
|
13
|
+
*/
|
|
14
|
+
import { LogError } from '@memberjunction/core';
|
|
15
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
16
|
+
import { BaseActivitySyncProvider } from '../BaseActivitySyncProvider.js';
|
|
17
|
+
import { MapGraphMessages } from './GraphMessageMapper.js';
|
|
18
|
+
export const LIVE_GRAPH_REFUSAL = 'Live Graph fetch is disabled. MSGraphProvider uses app-only auth, so Mail.Read reads ' +
|
|
19
|
+
'EVERY mailbox in the tenant until an Exchange Application Access Policy scopes the ' +
|
|
20
|
+
'app registration to a security group. Confirm that policy exists before enabling ' +
|
|
21
|
+
'this, and use FixtureActivitySyncProvider until then.';
|
|
22
|
+
let MSGraphActivitySyncProvider = class MSGraphActivitySyncProvider extends BaseActivitySyncProvider {
|
|
23
|
+
constructor(
|
|
24
|
+
/**
|
|
25
|
+
* Default FALSE. Turning it on is a deliberate act by someone who has confirmed
|
|
26
|
+
* the Application Access Policy exists. This PR never does that.
|
|
27
|
+
*/
|
|
28
|
+
AllowLiveFetch = false) {
|
|
29
|
+
super();
|
|
30
|
+
this.AllowLiveFetch = AllowLiveFetch;
|
|
31
|
+
this.Kind = 'Message';
|
|
32
|
+
this.ProviderTypeCode = 'Microsoft365';
|
|
33
|
+
this.IsLive = true;
|
|
34
|
+
}
|
|
35
|
+
async FetchRaw(query) {
|
|
36
|
+
if (!this.AllowLiveFetch) {
|
|
37
|
+
return { Payloads: [], Issues: [LIVE_GRAPH_REFUSAL] };
|
|
38
|
+
}
|
|
39
|
+
LogError(`MSGraphActivitySyncProvider.FetchRaw was enabled for ${query.Mailbox} — not supported in this build.`);
|
|
40
|
+
return {
|
|
41
|
+
Payloads: [],
|
|
42
|
+
Issues: [
|
|
43
|
+
'Live Graph fetch was opted in but no mailbox transport is wired in this package. ' +
|
|
44
|
+
'Keep AllowLiveFetch false and use FixtureActivitySyncProvider.',
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
Normalize(raw, query) {
|
|
49
|
+
if (raw.Payloads.length === 0)
|
|
50
|
+
return [];
|
|
51
|
+
const mapped = MapGraphMessages(raw.Payloads.length === 1 ? raw.Payloads[0] : raw.Payloads, query.Mailbox);
|
|
52
|
+
raw.Issues.push(...mapped.Issues);
|
|
53
|
+
const since = query.Since ? query.Since.getTime() : null;
|
|
54
|
+
return since === null ? mapped.Items : mapped.Items.filter((i) => i.StartedAt.getTime() > since);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
MSGraphActivitySyncProvider = __decorate([
|
|
58
|
+
RegisterClass(BaseActivitySyncProvider, 'Microsoft365'),
|
|
59
|
+
__metadata("design:paramtypes", [Boolean])
|
|
60
|
+
], MSGraphActivitySyncProvider);
|
|
61
|
+
export { MSGraphActivitySyncProvider };
|
|
62
|
+
//# sourceMappingURL=MSGraphActivitySyncProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MSGraphActivitySyncProvider.js","sourceRoot":"","sources":["../../src/providers/MSGraphActivitySyncProvider.ts"],"names":[],"mappings":";;;;;;;;;AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,CAAC,MAAM,kBAAkB,GAC3B,uFAAuF;IACvF,qFAAqF;IACrF,mFAAmF;IACnF,uDAAuD,CAAC;AAGrD,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,wBAAwB;IAKrE;IACI;;;OAGG;IACc,iBAA0B,KAAK;QAEhD,KAAK,EAAE,CAAC;QAFS,mBAAc,GAAd,cAAc,CAAiB;QATpC,SAAI,GAAG,SAAkB,CAAC;QAC1B,qBAAgB,GAAG,cAAc,CAAC;QAClC,WAAM,GAAG,IAAI,CAAC;IAU9B,CAAC;IAES,KAAK,CAAC,QAAQ,CAAC,KAA0B;QAC/C,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC1D,CAAC;QACD,QAAQ,CAAC,wDAAwD,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;QACjH,OAAO;YACH,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE;gBACJ,mFAAmF;oBAC/E,gEAAgE;aACvE;SACJ,CAAC;IACN,CAAC;IAES,SAAS,CAAC,GAAa,EAAE,KAA0B;QACzD,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3G,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;IACrG,CAAC;CACJ,CAAA;AApCY,2BAA2B;IADvC,aAAa,CAAC,wBAAwB,EAAE,cAAc,CAAC;;GAC3C,2BAA2B,CAoCvC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { BaseActivitySyncProvider } from '../BaseActivitySyncProvider.js';
|
|
2
|
+
import type { ActivitySourceQuery, NormalizedItem, RawBatch } from '../types.js';
|
|
3
|
+
export declare const LIVE_GRAPH_CALENDAR_REFUSAL: string;
|
|
4
|
+
export interface GraphAttendeeLike {
|
|
5
|
+
type?: string;
|
|
6
|
+
emailAddress?: {
|
|
7
|
+
address?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export interface GraphEventLike {
|
|
12
|
+
id?: string;
|
|
13
|
+
iCalUId?: string;
|
|
14
|
+
subject?: string;
|
|
15
|
+
bodyPreview?: string;
|
|
16
|
+
start?: {
|
|
17
|
+
dateTime?: string;
|
|
18
|
+
timeZone?: string;
|
|
19
|
+
};
|
|
20
|
+
end?: {
|
|
21
|
+
dateTime?: string;
|
|
22
|
+
timeZone?: string;
|
|
23
|
+
};
|
|
24
|
+
location?: {
|
|
25
|
+
displayName?: string;
|
|
26
|
+
};
|
|
27
|
+
organizer?: {
|
|
28
|
+
emailAddress?: {
|
|
29
|
+
address?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
attendees?: GraphAttendeeLike[];
|
|
34
|
+
isCancelled?: boolean;
|
|
35
|
+
seriesMasterId?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface GraphEventFetcher {
|
|
38
|
+
GetEvents(params: {
|
|
39
|
+
Mailbox: string;
|
|
40
|
+
Since: Date | null;
|
|
41
|
+
Top: number;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
Success?: boolean;
|
|
44
|
+
ErrorMessage?: string;
|
|
45
|
+
Events?: GraphEventLike[];
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
/** Map one Graph event. Exported so a check can prove the mapping without a mailbox. */
|
|
49
|
+
export declare function MapGraphEvent(event: GraphEventLike, issues: string[]): NormalizedItem | null;
|
|
50
|
+
export declare class MSGraphCalendarSyncProvider extends BaseActivitySyncProvider {
|
|
51
|
+
private readonly AllowLiveFetch;
|
|
52
|
+
private readonly fetcher?;
|
|
53
|
+
readonly Kind: "Calendar";
|
|
54
|
+
readonly ProviderTypeCode = "Microsoft365";
|
|
55
|
+
readonly IsLive = true;
|
|
56
|
+
constructor(AllowLiveFetch?: boolean, fetcher?: GraphEventFetcher | undefined);
|
|
57
|
+
protected FetchRaw(query: ActivitySourceQuery): Promise<RawBatch>;
|
|
58
|
+
protected Normalize(raw: RawBatch): NormalizedItem[];
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=MSGraphCalendarSyncProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MSGraphCalendarSyncProvider.d.ts","sourceRoot":"","sources":["../../src/providers/MSGraphCalendarSyncProvider.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAmB,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElG,eAAO,MAAM,2BAA2B,QAImC,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,QAAQ,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACnE,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,CAAC,MAAM,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC,CAAC;CACxF;AAiBD,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAgD5F;AAED,qBACa,2BAA4B,SAAQ,wBAAwB;IAMjE,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IAN7B,SAAgB,IAAI,EAAG,UAAU,CAAU;IAC3C,SAAgB,gBAAgB,kBAAkB;IAClD,SAAgB,MAAM,QAAQ;gBAGT,cAAc,GAAE,OAAe,EAC/B,OAAO,CAAC,EAAE,iBAAiB,YAAA;cAKhC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmCvE,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,cAAc,EAAE;CAQvD"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Microsoft Graph calendar. Written, typechecked, and refused until an Exchange
|
|
12
|
+
* Application Access Policy scopes app-only Calendars.Read. Same tenant-wide
|
|
13
|
+
* grant as Mail.Read; fixture is how the engine is exercised.
|
|
14
|
+
*/
|
|
15
|
+
import { LogError } from '@memberjunction/core';
|
|
16
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
17
|
+
import { BaseActivitySyncProvider } from '../BaseActivitySyncProvider.js';
|
|
18
|
+
export const LIVE_GRAPH_CALENDAR_REFUSAL = 'Live Graph calendar fetch is disabled. App-only auth makes Calendars.Read tenant-wide, ' +
|
|
19
|
+
'so it reads EVERY calendar until an Exchange Application Access Policy scopes the app ' +
|
|
20
|
+
'registration to a security group — the same policy Mail.Read needs. Confirm it exists ' +
|
|
21
|
+
'before enabling this, and use FixtureActivitySyncProvider until then.';
|
|
22
|
+
function normalize(value) {
|
|
23
|
+
const trimmed = value?.trim().toLowerCase();
|
|
24
|
+
return trimmed ? trimmed : null;
|
|
25
|
+
}
|
|
26
|
+
function graphDate(slot) {
|
|
27
|
+
const raw = slot?.dateTime?.trim();
|
|
28
|
+
if (!raw)
|
|
29
|
+
return null;
|
|
30
|
+
const zone = (slot?.timeZone ?? 'UTC').trim().toUpperCase();
|
|
31
|
+
if (zone !== 'UTC' && !/[Zz]|[+-]\d{2}:?\d{2}$/.test(raw))
|
|
32
|
+
return null;
|
|
33
|
+
const stamped = /[Zz]|[+-]\d{2}:?\d{2}$/.test(raw) ? raw : `${raw}Z`;
|
|
34
|
+
const parsed = new Date(stamped);
|
|
35
|
+
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
36
|
+
}
|
|
37
|
+
/** Map one Graph event. Exported so a check can prove the mapping without a mailbox. */
|
|
38
|
+
export function MapGraphEvent(event, issues) {
|
|
39
|
+
const externalID = event.id?.trim();
|
|
40
|
+
if (!externalID) {
|
|
41
|
+
issues.push('An event carried no id and was skipped — it cannot be deduped.');
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const startedAt = graphDate(event.start);
|
|
45
|
+
if (!startedAt) {
|
|
46
|
+
issues.push(`Event ${externalID} had no usable start time and was skipped.`);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const participants = [];
|
|
50
|
+
const organizer = normalize(event.organizer?.emailAddress?.address);
|
|
51
|
+
if (organizer) {
|
|
52
|
+
participants.push({
|
|
53
|
+
Address: organizer,
|
|
54
|
+
Name: event.organizer?.emailAddress?.name ?? null,
|
|
55
|
+
Role: 'Organizer',
|
|
56
|
+
IdentityKind: 'Email',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
for (const attendee of event.attendees ?? []) {
|
|
60
|
+
const address = normalize(attendee.emailAddress?.address);
|
|
61
|
+
if (!address || address === organizer)
|
|
62
|
+
continue;
|
|
63
|
+
participants.push({
|
|
64
|
+
Address: address,
|
|
65
|
+
Name: attendee.emailAddress?.name ?? null,
|
|
66
|
+
Role: 'Attendee',
|
|
67
|
+
IdentityKind: 'Email',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const endedAt = graphDate(event.end);
|
|
71
|
+
return {
|
|
72
|
+
ExternalID: externalID,
|
|
73
|
+
ExternalThreadID: event.seriesMasterId?.trim() || null,
|
|
74
|
+
TypeCode: 'Meeting',
|
|
75
|
+
Subject: event.subject?.trim() || '(no subject)',
|
|
76
|
+
Body: event.bodyPreview ?? null,
|
|
77
|
+
StartedAt: startedAt,
|
|
78
|
+
EndedAt: endedAt && endedAt.getTime() >= startedAt.getTime() ? endedAt : null,
|
|
79
|
+
Location: event.location?.displayName?.trim() || null,
|
|
80
|
+
Direction: 'Internal',
|
|
81
|
+
Participants: participants,
|
|
82
|
+
Cancelled: event.isCancelled === true,
|
|
83
|
+
Raw: { ...event, iCalUId: event.iCalUId ?? null },
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
let MSGraphCalendarSyncProvider = class MSGraphCalendarSyncProvider extends BaseActivitySyncProvider {
|
|
87
|
+
constructor(AllowLiveFetch = false, fetcher) {
|
|
88
|
+
super();
|
|
89
|
+
this.AllowLiveFetch = AllowLiveFetch;
|
|
90
|
+
this.fetcher = fetcher;
|
|
91
|
+
this.Kind = 'Calendar';
|
|
92
|
+
this.ProviderTypeCode = 'Microsoft365';
|
|
93
|
+
this.IsLive = true;
|
|
94
|
+
}
|
|
95
|
+
async FetchRaw(query) {
|
|
96
|
+
if (!this.AllowLiveFetch) {
|
|
97
|
+
return { Payloads: [], Issues: [LIVE_GRAPH_CALENDAR_REFUSAL] };
|
|
98
|
+
}
|
|
99
|
+
if (!this.fetcher) {
|
|
100
|
+
LogError(`MSGraphCalendarSyncProvider.FetchRaw was enabled for ${query.Mailbox} — no transport is wired.`);
|
|
101
|
+
return {
|
|
102
|
+
Payloads: [],
|
|
103
|
+
Issues: [
|
|
104
|
+
'Live Graph calendar fetch was opted in but no mailbox transport is wired in this package. ' +
|
|
105
|
+
'Keep AllowLiveFetch false and use FixtureActivitySyncProvider.',
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const response = await this.fetcher.GetEvents({
|
|
111
|
+
Mailbox: query.Mailbox,
|
|
112
|
+
Since: query.Since,
|
|
113
|
+
Top: query.Limit,
|
|
114
|
+
});
|
|
115
|
+
if (response?.Success === false) {
|
|
116
|
+
return {
|
|
117
|
+
Payloads: [],
|
|
118
|
+
Issues: [`Graph refused the calendar read: ${response.ErrorMessage ?? 'no reason given'}`],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
Payloads: (response?.Events ?? []),
|
|
123
|
+
Issues: [],
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
return { Payloads: [], Issues: [`Graph calendar read failed: ${String(err)}`] };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
Normalize(raw) {
|
|
131
|
+
const items = [];
|
|
132
|
+
for (const payload of raw.Payloads) {
|
|
133
|
+
const mapped = MapGraphEvent(payload, raw.Issues);
|
|
134
|
+
if (mapped)
|
|
135
|
+
items.push(mapped);
|
|
136
|
+
}
|
|
137
|
+
return items;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
MSGraphCalendarSyncProvider = __decorate([
|
|
141
|
+
RegisterClass(BaseActivitySyncProvider, 'Microsoft365.Calendar'),
|
|
142
|
+
__metadata("design:paramtypes", [Boolean, Object])
|
|
143
|
+
], MSGraphCalendarSyncProvider);
|
|
144
|
+
export { MSGraphCalendarSyncProvider };
|
|
145
|
+
//# sourceMappingURL=MSGraphCalendarSyncProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MSGraphCalendarSyncProvider.js","sourceRoot":"","sources":["../../src/providers/MSGraphCalendarSyncProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The qualification cascade — ordered stages, each deciding or deferring.
|
|
3
|
+
*
|
|
4
|
+
* ── THE ORDERING IS A PRIVACY GUARANTEE, SO IT IS ENFORCED, NOT DOCUMENTED ──────────────────────
|
|
5
|
+
*
|
|
6
|
+
* A stage that calls a model must never run before the deterministic stages. A message whose
|
|
7
|
+
* participants match no known contact is discarded having been read only by a string comparison;
|
|
8
|
+
* putting inference first would send the contents of every message in a mailbox — including the
|
|
9
|
+
* private ones — to a third party.
|
|
10
|
+
*
|
|
11
|
+
* {@link RunQualificationCascade} therefore REJECTS a stage list where a local stage follows an
|
|
12
|
+
* inference stage, rather than trusting the caller to order it correctly. A comment could be
|
|
13
|
+
* ignored by the next person to add a stage; a thrown error cannot.
|
|
14
|
+
*
|
|
15
|
+
* ── AND ABSTENTION IS FIRST-CLASS ────────────────────────────────────────────────────
|
|
16
|
+
*
|
|
17
|
+
* A stage that is not confident returns `Undecided` instead of guessing. When every stage abstains,
|
|
18
|
+
* the provider type's default policy decides — and for anything mailbox-shaped that default is
|
|
19
|
+
* `Exclude`. Capturing a private message is worse than missing a business one, so the cascade fails
|
|
20
|
+
* CLOSED.
|
|
21
|
+
*
|
|
22
|
+
* @module @mj-biz-apps/common-activity-sync
|
|
23
|
+
*/
|
|
24
|
+
import { NormalizedItem } from './types.js';
|
|
25
|
+
export type QualificationDecision = 'Include' | 'Exclude' | 'Undecided';
|
|
26
|
+
/** What an `Undecided` chain resolves to. Mirrors `ActivitySyncProviderType.DefaultQualificationPolicy`. */
|
|
27
|
+
export type QualificationPolicy = 'Include' | 'Exclude';
|
|
28
|
+
/**
|
|
29
|
+
* The cascade's fail-closed default.
|
|
30
|
+
*
|
|
31
|
+
* `ActivitySyncProviderTypeID` is nullable, and a host install currently ships
|
|
32
|
+
* zero provider-type rows until a release-engineer Metadata_Sync. Whatever the
|
|
33
|
+
* engine passes as `RunQualificationCascade`'s last argument *is* the real
|
|
34
|
+
* default — `ResolvePolicy`'s first parameter is required, so a missing type
|
|
35
|
+
* cannot silently fall through.
|
|
36
|
+
*
|
|
37
|
+
* Only an explicit `'Include'` on the type row opts in. Null, missing, empty,
|
|
38
|
+
* or any other value is `'Exclude'`. A `?? 'Include'` at the engine call site
|
|
39
|
+
* would defeat the cascade while every test still passed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function DefaultPolicyFromProviderType(policy: string | null | undefined): QualificationPolicy;
|
|
42
|
+
/** One stage's answer. `Reason` is always populated — including on `Include`, so a capture is explicable. */
|
|
43
|
+
export interface QualificationVerdict {
|
|
44
|
+
Decision: QualificationDecision;
|
|
45
|
+
Reason: string;
|
|
46
|
+
StageName: string;
|
|
47
|
+
/** 0–1 where a stage can express one. Absent for deterministic stages, which are certain or abstain. */
|
|
48
|
+
Confidence?: number;
|
|
49
|
+
/** Set when the verdict came from an AI Prompt, for trace. */
|
|
50
|
+
AIPromptRunID?: string;
|
|
51
|
+
/**
|
|
52
|
+
* The rule or exclusion that decided, when one did.
|
|
53
|
+
*
|
|
54
|
+
* Carried on the verdict rather than reconstructed by the caller, because these are what
|
|
55
|
+
* `ActivitySyncRunDetail` records — and "which rule ate my message" is the question the run log
|
|
56
|
+
* exists to answer. A verdict that cannot name its cause makes the log a narrative instead of
|
|
57
|
+
* evidence.
|
|
58
|
+
*/
|
|
59
|
+
ActivitySyncRuleID?: string;
|
|
60
|
+
ActivitySyncExclusionID?: string;
|
|
61
|
+
}
|
|
62
|
+
/** Whatever a stage needs beyond the item itself — known addresses, the connection's rules, and so on. */
|
|
63
|
+
export interface QualificationContext {
|
|
64
|
+
ConnectionID: string;
|
|
65
|
+
/** Provider type `Code`, for stages that behave differently per source. */
|
|
66
|
+
ProviderTypeCode: string;
|
|
67
|
+
}
|
|
68
|
+
export interface IQualificationStage {
|
|
69
|
+
readonly Name: string;
|
|
70
|
+
/**
|
|
71
|
+
* True when this stage sends item content to a model.
|
|
72
|
+
*
|
|
73
|
+
* Load-bearing: the cascade uses it to enforce that inference never precedes deterministic work.
|
|
74
|
+
*/
|
|
75
|
+
readonly RequiresInference: boolean;
|
|
76
|
+
Evaluate(item: NormalizedItem, context: QualificationContext): Promise<QualificationVerdict>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Runs stages in order and returns the first decisive verdict.
|
|
80
|
+
*
|
|
81
|
+
* @throws if a non-inference stage follows an inference stage — see the file header.
|
|
82
|
+
*/
|
|
83
|
+
export declare function RunQualificationCascade(stages: readonly IQualificationStage[], item: NormalizedItem, context: QualificationContext, defaultPolicy: QualificationPolicy): Promise<QualificationVerdict>;
|
|
84
|
+
/**
|
|
85
|
+
* Guards the one ordering that cannot be left to convention.
|
|
86
|
+
*
|
|
87
|
+
* Keyed on the CAUSE (an inference stage exists and something local follows it) rather than on a
|
|
88
|
+
* position or a count, so it still holds when someone adds a fourth stage years from now.
|
|
89
|
+
*/
|
|
90
|
+
export declare function AssertInferenceRunsLast(stages: readonly IQualificationStage[]): void;
|
|
91
|
+
//# sourceMappingURL=qualification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qualification.d.ts","sourceRoot":"","sources":["../src/qualification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAExE,4GAA4G;AAC5G,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CACzC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,mBAAmB,CAErB;AAED,6GAA6G;AAC7G,MAAM,WAAW,oBAAoB;IACjC,QAAQ,EAAE,qBAAqB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,0GAA0G;AAC1G,MAAM,WAAW,oBAAoB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAChG;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CACzC,MAAM,EAAE,SAAS,mBAAmB,EAAE,EACtC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,mBAAmB,GACnC,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,GAAG,IAAI,CAepF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cascade's fail-closed default.
|
|
3
|
+
*
|
|
4
|
+
* `ActivitySyncProviderTypeID` is nullable, and a host install currently ships
|
|
5
|
+
* zero provider-type rows until a release-engineer Metadata_Sync. Whatever the
|
|
6
|
+
* engine passes as `RunQualificationCascade`'s last argument *is* the real
|
|
7
|
+
* default — `ResolvePolicy`'s first parameter is required, so a missing type
|
|
8
|
+
* cannot silently fall through.
|
|
9
|
+
*
|
|
10
|
+
* Only an explicit `'Include'` on the type row opts in. Null, missing, empty,
|
|
11
|
+
* or any other value is `'Exclude'`. A `?? 'Include'` at the engine call site
|
|
12
|
+
* would defeat the cascade while every test still passed.
|
|
13
|
+
*/
|
|
14
|
+
export function DefaultPolicyFromProviderType(policy) {
|
|
15
|
+
return policy === 'Include' ? 'Include' : 'Exclude';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Runs stages in order and returns the first decisive verdict.
|
|
19
|
+
*
|
|
20
|
+
* @throws if a non-inference stage follows an inference stage — see the file header.
|
|
21
|
+
*/
|
|
22
|
+
export async function RunQualificationCascade(stages, item, context, defaultPolicy) {
|
|
23
|
+
AssertInferenceRunsLast(stages);
|
|
24
|
+
for (const stage of stages) {
|
|
25
|
+
const verdict = await stage.Evaluate(item, context);
|
|
26
|
+
if (verdict.Decision !== 'Undecided') {
|
|
27
|
+
return verdict;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return AbstainedVerdict(stages, defaultPolicy);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Guards the one ordering that cannot be left to convention.
|
|
34
|
+
*
|
|
35
|
+
* Keyed on the CAUSE (an inference stage exists and something local follows it) rather than on a
|
|
36
|
+
* position or a count, so it still holds when someone adds a fourth stage years from now.
|
|
37
|
+
*/
|
|
38
|
+
export function AssertInferenceRunsLast(stages) {
|
|
39
|
+
let seenInference = null;
|
|
40
|
+
for (const stage of stages) {
|
|
41
|
+
if (stage.RequiresInference) {
|
|
42
|
+
seenInference = stage;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (seenInference !== null) {
|
|
46
|
+
throw new Error(`Qualification stage "${stage.Name}" is deterministic but is ordered AFTER the ` +
|
|
47
|
+
`inference stage "${seenInference.Name}". Inference must run last: a deterministic ` +
|
|
48
|
+
`stage placed after it would let unfiltered content reach a model first.`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** The verdict when every stage abstained. Names the policy so an operator can see why. */
|
|
53
|
+
function AbstainedVerdict(stages, defaultPolicy) {
|
|
54
|
+
const stageNames = stages.length > 0 ? stages.map((s) => s.Name).join(', ') : '(none)';
|
|
55
|
+
return {
|
|
56
|
+
Decision: defaultPolicy,
|
|
57
|
+
StageName: 'DefaultPolicy',
|
|
58
|
+
Reason: `No stage reached a decision (${stageNames}); the provider type's ` +
|
|
59
|
+
`DefaultQualificationPolicy of "${defaultPolicy}" applied.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=qualification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qualification.js","sourceRoot":"","sources":["../src/qualification.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,6BAA6B,CACzC,MAAiC;IAEjC,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;AAyCD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CACzC,MAAsC,EACtC,IAAoB,EACpB,OAA6B,EAC7B,aAAkC;IAElC,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAEhC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,OAAO,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC;QACnB,CAAC;IACL,CAAC;IACD,OAAO,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAsC;IAC1E,IAAI,aAAa,GAA+B,IAAI,CAAC;IACrD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,aAAa,GAAG,KAAK,CAAC;YACtB,SAAS;QACb,CAAC;QACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACX,wBAAwB,KAAK,CAAC,IAAI,8CAA8C;gBAC5E,oBAAoB,aAAa,CAAC,IAAI,8CAA8C;gBACpF,yEAAyE,CAChF,CAAC;QACN,CAAC;IACL,CAAC;AACL,CAAC;AAED,2FAA2F;AAC3F,SAAS,gBAAgB,CACrB,MAAsC,EACtC,aAAkC;IAElC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACvF,OAAO;QACH,QAAQ,EAAE,aAAa;QACvB,SAAS,EAAE,eAAe;QAC1B,MAAM,EACF,gCAAgC,UAAU,yBAAyB;YACnE,kCAAkC,aAAa,YAAY;KAClE,CAAC;AACN,CAAC"}
|