@rapidmx/activesync 1.0.0-beta.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/LICENSE +382 -0
- package/README.md +57 -0
- package/dist/lib/BaseDeviceSyncStateRoute.js +90 -0
- package/dist/lib/BaseDeviceSyncStateRoute.js.map +1 -0
- package/dist/lib/BaseEasRoute.js +213 -0
- package/dist/lib/BaseEasRoute.js.map +1 -0
- package/dist/lib/CompactDateTime.js +43 -0
- package/dist/lib/CompactDateTime.js.map +1 -0
- package/dist/lib/EasCommandHandler.js +2 -0
- package/dist/lib/EasCommandHandler.js.map +1 -0
- package/dist/lib/EasSyncKeyUtils.js +119 -0
- package/dist/lib/EasSyncKeyUtils.js.map +1 -0
- package/dist/lib/adapters/CalendarSyncAdapter.js +255 -0
- package/dist/lib/adapters/CalendarSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/ContactsSyncAdapter.js +164 -0
- package/dist/lib/adapters/ContactsSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/EasCollectionSyncAdapter.js +2 -0
- package/dist/lib/adapters/EasCollectionSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/EmailSyncAdapter.js +230 -0
- package/dist/lib/adapters/EmailSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/TasksSyncAdapter.js +100 -0
- package/dist/lib/adapters/TasksSyncAdapter.js.map +1 -0
- package/dist/lib/codec/WbxmlCodePages.js +706 -0
- package/dist/lib/codec/WbxmlCodePages.js.map +1 -0
- package/dist/lib/codec/WbxmlDecoder.js +154 -0
- package/dist/lib/codec/WbxmlDecoder.js.map +1 -0
- package/dist/lib/codec/WbxmlElement.js +31 -0
- package/dist/lib/codec/WbxmlElement.js.map +1 -0
- package/dist/lib/codec/WbxmlEncoder.js +88 -0
- package/dist/lib/codec/WbxmlEncoder.js.map +1 -0
- package/dist/lib/commands/ComposeMailCommand.js +187 -0
- package/dist/lib/commands/ComposeMailCommand.js.map +1 -0
- package/dist/lib/commands/FolderSyncCommand.js +150 -0
- package/dist/lib/commands/FolderSyncCommand.js.map +1 -0
- package/dist/lib/commands/GetItemEstimateCommand.js +149 -0
- package/dist/lib/commands/GetItemEstimateCommand.js.map +1 -0
- package/dist/lib/commands/ItemOperationsCommand.js +337 -0
- package/dist/lib/commands/ItemOperationsCommand.js.map +1 -0
- package/dist/lib/commands/MeetingResponseCommand.js +120 -0
- package/dist/lib/commands/MeetingResponseCommand.js.map +1 -0
- package/dist/lib/commands/MoveItemsCommand.js +103 -0
- package/dist/lib/commands/MoveItemsCommand.js.map +1 -0
- package/dist/lib/commands/PingCommand.js +145 -0
- package/dist/lib/commands/PingCommand.js.map +1 -0
- package/dist/lib/commands/ProvisionCommand.js +164 -0
- package/dist/lib/commands/ProvisionCommand.js.map +1 -0
- package/dist/lib/commands/ResolveRecipientsCommand.js +124 -0
- package/dist/lib/commands/ResolveRecipientsCommand.js.map +1 -0
- package/dist/lib/commands/SearchCommand.js +137 -0
- package/dist/lib/commands/SearchCommand.js.map +1 -0
- package/dist/lib/commands/SendMailCommand.js +18 -0
- package/dist/lib/commands/SendMailCommand.js.map +1 -0
- package/dist/lib/commands/SettingsCommand.js +138 -0
- package/dist/lib/commands/SettingsCommand.js.map +1 -0
- package/dist/lib/commands/SmartForwardCommand.js +22 -0
- package/dist/lib/commands/SmartForwardCommand.js.map +1 -0
- package/dist/lib/commands/SmartReplyCommand.js +22 -0
- package/dist/lib/commands/SmartReplyCommand.js.map +1 -0
- package/dist/lib/commands/SyncCommand.js +406 -0
- package/dist/lib/commands/SyncCommand.js.map +1 -0
- package/dist/lib/commands/mongo/FolderSyncCommandMongo.js +16 -0
- package/dist/lib/commands/mongo/FolderSyncCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/GetItemEstimateCommandMongo.js +21 -0
- package/dist/lib/commands/mongo/GetItemEstimateCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/ItemOperationsCommandMongo.js +18 -0
- package/dist/lib/commands/mongo/ItemOperationsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/MeetingResponseCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/MeetingResponseCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/MoveItemsCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/MoveItemsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/ResolveRecipientsCommandMongo.js +20 -0
- package/dist/lib/commands/mongo/ResolveRecipientsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SearchCommandMongo.js +20 -0
- package/dist/lib/commands/mongo/SearchCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SendMailCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/SendMailCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SettingsCommandMongo.js +16 -0
- package/dist/lib/commands/mongo/SettingsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SmartForwardCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/SmartForwardCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SmartReplyCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/SmartReplyCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SyncCommandMongo.js +26 -0
- package/dist/lib/commands/mongo/SyncCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/index.js +14 -0
- package/dist/lib/commands/mongo/index.js.map +1 -0
- package/dist/lib/commands/sql/FolderSyncCommandSQL.js +16 -0
- package/dist/lib/commands/sql/FolderSyncCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/GetItemEstimateCommandSQL.js +21 -0
- package/dist/lib/commands/sql/GetItemEstimateCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/ItemOperationsCommandSQL.js +18 -0
- package/dist/lib/commands/sql/ItemOperationsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/MeetingResponseCommandSQL.js +17 -0
- package/dist/lib/commands/sql/MeetingResponseCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/MoveItemsCommandSQL.js +17 -0
- package/dist/lib/commands/sql/MoveItemsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/ResolveRecipientsCommandSQL.js +20 -0
- package/dist/lib/commands/sql/ResolveRecipientsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SearchCommandSQL.js +20 -0
- package/dist/lib/commands/sql/SearchCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SendMailCommandSQL.js +17 -0
- package/dist/lib/commands/sql/SendMailCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SettingsCommandSQL.js +16 -0
- package/dist/lib/commands/sql/SettingsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SmartForwardCommandSQL.js +17 -0
- package/dist/lib/commands/sql/SmartForwardCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SmartReplyCommandSQL.js +17 -0
- package/dist/lib/commands/sql/SmartReplyCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SyncCommandSQL.js +26 -0
- package/dist/lib/commands/sql/SyncCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/index.js +14 -0
- package/dist/lib/commands/sql/index.js.map +1 -0
- package/dist/lib/index.js +56 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/mongo/DeviceSyncStateRouteMongo.js +16 -0
- package/dist/lib/mongo/DeviceSyncStateRouteMongo.js.map +1 -0
- package/dist/lib/mongo/EasRouteMongo.js +51 -0
- package/dist/lib/mongo/EasRouteMongo.js.map +1 -0
- package/dist/lib/mongo/index.js +8 -0
- package/dist/lib/mongo/index.js.map +1 -0
- package/dist/lib/mongo.js +6 -0
- package/dist/lib/mongo.js.map +1 -0
- package/dist/lib/sql/DeviceSyncStateRouteSQL.js +16 -0
- package/dist/lib/sql/DeviceSyncStateRouteSQL.js.map +1 -0
- package/dist/lib/sql/EasRouteSQL.js +50 -0
- package/dist/lib/sql/EasRouteSQL.js.map +1 -0
- package/dist/lib/sql/index.js +8 -0
- package/dist/lib/sql/index.js.map +1 -0
- package/dist/lib/sql.js +6 -0
- package/dist/lib/sql.js.map +1 -0
- package/dist/types/BaseDeviceSyncStateRoute.d.ts +34 -0
- package/dist/types/BaseEasRoute.d.ts +64 -0
- package/dist/types/CompactDateTime.d.ts +22 -0
- package/dist/types/EasCommandHandler.d.ts +59 -0
- package/dist/types/EasSyncKeyUtils.d.ts +89 -0
- package/dist/types/adapters/CalendarSyncAdapter.d.ts +52 -0
- package/dist/types/adapters/ContactsSyncAdapter.d.ts +33 -0
- package/dist/types/adapters/EasCollectionSyncAdapter.d.ts +52 -0
- package/dist/types/adapters/EmailSyncAdapter.d.ts +53 -0
- package/dist/types/adapters/TasksSyncAdapter.d.ts +32 -0
- package/dist/types/codec/WbxmlCodePages.d.ts +45 -0
- package/dist/types/codec/WbxmlDecoder.d.ts +33 -0
- package/dist/types/codec/WbxmlElement.d.ts +43 -0
- package/dist/types/codec/WbxmlEncoder.d.ts +20 -0
- package/dist/types/commands/ComposeMailCommand.d.ts +50 -0
- package/dist/types/commands/FolderSyncCommand.d.ts +25 -0
- package/dist/types/commands/GetItemEstimateCommand.d.ts +43 -0
- package/dist/types/commands/ItemOperationsCommand.d.ts +72 -0
- package/dist/types/commands/MeetingResponseCommand.d.ts +32 -0
- package/dist/types/commands/MoveItemsCommand.d.ts +29 -0
- package/dist/types/commands/PingCommand.d.ts +33 -0
- package/dist/types/commands/ProvisionCommand.d.ts +54 -0
- package/dist/types/commands/ResolveRecipientsCommand.d.ts +34 -0
- package/dist/types/commands/SearchCommand.d.ts +39 -0
- package/dist/types/commands/SendMailCommand.d.ts +10 -0
- package/dist/types/commands/SettingsCommand.d.ts +37 -0
- package/dist/types/commands/SmartForwardCommand.d.ts +17 -0
- package/dist/types/commands/SmartReplyCommand.d.ts +17 -0
- package/dist/types/commands/SyncCommand.d.ts +100 -0
- package/dist/types/commands/mongo/FolderSyncCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/GetItemEstimateCommandMongo.d.ts +7 -0
- package/dist/types/commands/mongo/ItemOperationsCommandMongo.d.ts +9 -0
- package/dist/types/commands/mongo/MeetingResponseCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/MoveItemsCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/ResolveRecipientsCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SearchCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SendMailCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SettingsCommandMongo.d.ts +7 -0
- package/dist/types/commands/mongo/SmartForwardCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SmartReplyCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SyncCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/index.d.ts +9 -0
- package/dist/types/commands/sql/FolderSyncCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/GetItemEstimateCommandSQL.d.ts +7 -0
- package/dist/types/commands/sql/ItemOperationsCommandSQL.d.ts +9 -0
- package/dist/types/commands/sql/MeetingResponseCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/MoveItemsCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/ResolveRecipientsCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SearchCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SendMailCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SettingsCommandSQL.d.ts +7 -0
- package/dist/types/commands/sql/SmartForwardCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SmartReplyCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SyncCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/index.d.ts +9 -0
- package/dist/types/index.d.ts +51 -0
- package/dist/types/mongo/DeviceSyncStateRouteMongo.d.ts +8 -0
- package/dist/types/mongo/EasRouteMongo.d.ts +14 -0
- package/dist/types/mongo/index.d.ts +3 -0
- package/dist/types/mongo.d.ts +1 -0
- package/dist/types/sql/DeviceSyncStateRouteSQL.d.ts +8 -0
- package/dist/types/sql/EasRouteSQL.d.ts +13 -0
- package/dist/types/sql/index.d.ts +3 -0
- package/dist/types/sql.d.ts +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import * as crypto from "crypto";
|
|
6
|
+
import { WbxmlCodePage } from "../codec/WbxmlCodePages.js";
|
|
7
|
+
import { childText, element, findChild, textElement } from "../codec/WbxmlElement.js";
|
|
8
|
+
import { fromCompactDateTime, toCompactDateTime } from "../CompactDateTime.js";
|
|
9
|
+
import { AttendeeResponseStatus, AttendeeRole, BusyStatus, RecurrenceFrequency, RecipientType, } from "@rapidmx/restapi";
|
|
10
|
+
/** Builds the reverse of a forward code-table once at module load, rather than re-deriving it per call. */
|
|
11
|
+
function invert(table) {
|
|
12
|
+
return Object.fromEntries(Object.entries(table).map(([k, v]) => [v, k]));
|
|
13
|
+
}
|
|
14
|
+
/** MS-ASCAL `BusyStatus`: 0=Free, 1=Tentative, 2=Busy, 3=Out of Office. Confirmed against the published
|
|
15
|
+
* MS-ASCAL spec, not assumed - note the value order does not match this library's own `BusyStatus` enum
|
|
16
|
+
* declaration order, so an identity/positional mapping would have been silently wrong. */
|
|
17
|
+
const BUSY_STATUS_CODES = {
|
|
18
|
+
[BusyStatus.FREE]: "0",
|
|
19
|
+
[BusyStatus.TENTATIVE]: "1",
|
|
20
|
+
[BusyStatus.BUSY]: "2",
|
|
21
|
+
[BusyStatus.OUT_OF_OFFICE]: "3",
|
|
22
|
+
};
|
|
23
|
+
/** MS-ASCAL `AttendeeStatus`: 0=Response unknown, 2=Tentative, 3=Accept, 4=Decline, 5=Not responded. This
|
|
24
|
+
* library's own `AttendeeResponseStatus.NEEDS_ACTION` maps to 0 (unknown) rather than 5 (not responded) - both
|
|
25
|
+
* are defensible for "no response yet", and 0 is the spec's own documented fallback/default value. */
|
|
26
|
+
const ATTENDEE_STATUS_CODES = {
|
|
27
|
+
[AttendeeResponseStatus.NEEDS_ACTION]: "0",
|
|
28
|
+
[AttendeeResponseStatus.TENTATIVE]: "2",
|
|
29
|
+
[AttendeeResponseStatus.ACCEPTED]: "3",
|
|
30
|
+
[AttendeeResponseStatus.DECLINED]: "4",
|
|
31
|
+
};
|
|
32
|
+
/** MS-ASCAL `AttendeeType`: 1=Required, 2=Optional, 3=Resource. */
|
|
33
|
+
const ATTENDEE_TYPE_CODES = {
|
|
34
|
+
[AttendeeRole.REQUIRED]: "1",
|
|
35
|
+
[AttendeeRole.OPTIONAL]: "2",
|
|
36
|
+
[AttendeeRole.RESOURCE]: "3",
|
|
37
|
+
};
|
|
38
|
+
/** MS-ASCAL `Recurrence.Type`: 0=Daily, 1=Weekly, 2=Monthly, 5=Yearly (3="monthly on the nth day" and
|
|
39
|
+
* 6="yearly on the nth day" - patterns keyed by an ordinal weekday, e.g. "the 2nd Tuesday" - are a documented,
|
|
40
|
+
* out-of-scope gap for this pragmatic subset; `RecurrenceRule` has no ordinal-weekday field to source them
|
|
41
|
+
* from anyway, only plain day-of-month/day-of-week lists). */
|
|
42
|
+
const RECURRENCE_TYPE_CODES = {
|
|
43
|
+
[RecurrenceFrequency.DAILY]: "0",
|
|
44
|
+
[RecurrenceFrequency.WEEKLY]: "1",
|
|
45
|
+
[RecurrenceFrequency.MONTHLY]: "2",
|
|
46
|
+
[RecurrenceFrequency.YEARLY]: "5",
|
|
47
|
+
};
|
|
48
|
+
/** MS-ASCAL `DayOfWeek` bitmask: Sunday=1, Monday=2, Tuesday=4, Wednesday=8, Thursday=16, Friday=32,
|
|
49
|
+
* Saturday=64 - summed when a recurrence applies to more than one day. `RecurrenceRule.byDay` uses RFC 5545's
|
|
50
|
+
* two-letter day codes. */
|
|
51
|
+
const DAY_OF_WEEK_BITS = { SU: 1, MO: 2, TU: 4, WE: 8, TH: 16, FR: 32, SA: 64 };
|
|
52
|
+
const BUSY_STATUS_FROM_CODE = invert(BUSY_STATUS_CODES);
|
|
53
|
+
const ATTENDEE_STATUS_FROM_CODE = invert(ATTENDEE_STATUS_CODES);
|
|
54
|
+
const ATTENDEE_TYPE_FROM_CODE = invert(ATTENDEE_TYPE_CODES);
|
|
55
|
+
const RECURRENCE_FREQUENCY_FROM_CODE = invert(RECURRENCE_TYPE_CODES);
|
|
56
|
+
/**
|
|
57
|
+
* Maps `CalendarEvent` to/from the EAS `Sync` `Calendar` collection class (MS-ASCAL).
|
|
58
|
+
*
|
|
59
|
+
* **Pragmatic subset, deliberately not the full MS-ASCAL semantics**:
|
|
60
|
+
* - `TimeZone` is not emitted - the real element is a base64-encoded binary Win32 `TIME_ZONE_INFORMATION`
|
|
61
|
+
* structure, not a plain IANA string; `CalendarEvent.timezone` (an IANA identifier) can't be losslessly
|
|
62
|
+
* re-encoded into that format without a full IANA-to-Windows zone mapping table, and a real device would
|
|
63
|
+
* rather see no `TimeZone` element (falling back to its own default) than a malformed one.
|
|
64
|
+
* - `Sensitivity` is always reported `0` (Normal) - this library's `CalendarEvent` has no privacy dimension of
|
|
65
|
+
* its own to source a real value from.
|
|
66
|
+
* - Recurrence patterns keyed by an ordinal weekday (MS-ASCAL `Type` 3/6, e.g. "the 2nd Tuesday of the month")
|
|
67
|
+
* are not emitted - see `RECURRENCE_TYPE_CODES`'s own doc comment.
|
|
68
|
+
* - Recurrence exceptions (individually modified/cancelled occurrences of a recurring series) are not synced -
|
|
69
|
+
* deferred, matching this library's "pragmatic subset" precedent elsewhere (e.g. `FolderSyncCommand`'s SyncKey
|
|
70
|
+
* replay-protection gap).
|
|
71
|
+
*
|
|
72
|
+
* @author Jean-Philippe Steinmetz
|
|
73
|
+
*/
|
|
74
|
+
export class CalendarSyncAdapter {
|
|
75
|
+
constructor() {
|
|
76
|
+
this.collectionClass = "Calendar";
|
|
77
|
+
}
|
|
78
|
+
toApplicationData(event) {
|
|
79
|
+
const hasAttendees = event.attendees.length > 0;
|
|
80
|
+
return element(WbxmlCodePage.AirSync, "ApplicationData", [
|
|
81
|
+
textElement(WbxmlCodePage.Calendar, "Subject", event.title),
|
|
82
|
+
...(event.location ? [textElement(WbxmlCodePage.Calendar, "Location", event.location)] : []),
|
|
83
|
+
textElement(WbxmlCodePage.Calendar, "StartTime", toCompactDateTime(event.startDate)),
|
|
84
|
+
textElement(WbxmlCodePage.Calendar, "EndTime", toCompactDateTime(event.endDate)),
|
|
85
|
+
textElement(WbxmlCodePage.Calendar, "AllDayEvent", event.allDay ? "1" : "0"),
|
|
86
|
+
textElement(WbxmlCodePage.Calendar, "DtStamp", toCompactDateTime(event.dateModified)),
|
|
87
|
+
textElement(WbxmlCodePage.Calendar, "BusyStatus", BUSY_STATUS_CODES[event.busyStatus]),
|
|
88
|
+
textElement(WbxmlCodePage.Calendar, "Sensitivity", "0"),
|
|
89
|
+
textElement(WbxmlCodePage.Calendar, "MeetingStatus", hasAttendees ? "1" : "0"),
|
|
90
|
+
textElement(WbxmlCodePage.Calendar, "OrganizerEmail", event.organizer.address),
|
|
91
|
+
...(event.organizer.displayName
|
|
92
|
+
? [textElement(WbxmlCodePage.Calendar, "OrganizerName", event.organizer.displayName)]
|
|
93
|
+
: []),
|
|
94
|
+
...(hasAttendees
|
|
95
|
+
? [
|
|
96
|
+
element(WbxmlCodePage.Calendar, "Attendees", event.attendees.map((attendee) => element(WbxmlCodePage.Calendar, "Attendee", [
|
|
97
|
+
textElement(WbxmlCodePage.Calendar, "Email", attendee.address),
|
|
98
|
+
...(attendee.displayName
|
|
99
|
+
? [textElement(WbxmlCodePage.Calendar, "Name", attendee.displayName)]
|
|
100
|
+
: []),
|
|
101
|
+
textElement(WbxmlCodePage.Calendar, "AttendeeType", ATTENDEE_TYPE_CODES[attendee.role]),
|
|
102
|
+
textElement(WbxmlCodePage.Calendar, "AttendeeStatus", ATTENDEE_STATUS_CODES[attendee.responseStatus]),
|
|
103
|
+
]))),
|
|
104
|
+
]
|
|
105
|
+
: []),
|
|
106
|
+
// `!= null` (not `!== undefined`) deliberately - TypeORM hydrates an unset nullable SQL column as
|
|
107
|
+
// `null`, not `undefined` (confirmed by a real test failure against the SQL backend: `undefined`
|
|
108
|
+
// survives a Mongo round-trip for a genuinely-absent field, but SQL hands back `null` instead, and
|
|
109
|
+
// a strict `!== undefined` check would then wrongly treat that "absent" value as present).
|
|
110
|
+
...(event.reminderMinutesBeforeStart != null
|
|
111
|
+
? [textElement(WbxmlCodePage.Calendar, "Reminder", String(event.reminderMinutesBeforeStart))]
|
|
112
|
+
: []),
|
|
113
|
+
...(event.recurrenceRule ? [this.recurrenceElement(event.recurrenceRule, event.startDate)] : []),
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
recurrenceElement(rule, startDate) {
|
|
117
|
+
const dayOfWeekBits = (rule.byDay ?? []).reduce((sum, day) => sum + (DAY_OF_WEEK_BITS[day] ?? 0), 0);
|
|
118
|
+
return element(WbxmlCodePage.Calendar, "Recurrence", [
|
|
119
|
+
textElement(WbxmlCodePage.Calendar, "Type", RECURRENCE_TYPE_CODES[rule.freq]),
|
|
120
|
+
textElement(WbxmlCodePage.Calendar, "Interval", String(rule.interval)),
|
|
121
|
+
...(rule.freq === RecurrenceFrequency.WEEKLY && dayOfWeekBits > 0
|
|
122
|
+
? [textElement(WbxmlCodePage.Calendar, "DayOfWeek", String(dayOfWeekBits))]
|
|
123
|
+
: []),
|
|
124
|
+
...(rule.freq === RecurrenceFrequency.MONTHLY || rule.freq === RecurrenceFrequency.YEARLY
|
|
125
|
+
? [textElement(WbxmlCodePage.Calendar, "DayOfMonth", String(rule.byMonthDay?.[0] ?? startDate.getUTCDate()))]
|
|
126
|
+
: []),
|
|
127
|
+
...(rule.freq === RecurrenceFrequency.YEARLY
|
|
128
|
+
? [textElement(WbxmlCodePage.Calendar, "MonthOfYear", String(rule.byMonth?.[0] ?? startDate.getUTCMonth() + 1))]
|
|
129
|
+
: []),
|
|
130
|
+
...(rule.until ? [textElement(WbxmlCodePage.Calendar, "Until", toCompactDateTime(rule.until))] : []),
|
|
131
|
+
// See the identical `!= null` reasoning on `reminderMinutesBeforeStart` above.
|
|
132
|
+
...(rule.count != null ? [textElement(WbxmlCodePage.Calendar, "Occurrences", String(rule.count))] : []),
|
|
133
|
+
]);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Reverse of `toApplicationData`. `timezone`/`status`/`sequence`/`icalUid` have no wire representation at
|
|
137
|
+
* all (see this class's own "pragmatic subset" doc comment for `timezone`; the other three are purely
|
|
138
|
+
* server-managed identifiers/state a client was never sent in the first place) and are never included in
|
|
139
|
+
* the returned partial - `newEntityDefaults()` below supplies `icalUid`/`sequence` for a brand new event
|
|
140
|
+
* (`status`/`timezone` are left at the model's own constructor defaults), and `applyChange` leaves all four
|
|
141
|
+
* untouched by construction (merging onto `existing`).
|
|
142
|
+
*
|
|
143
|
+
* `OrganizerEmail` is required for a new event (there is nowhere else to default it from - this adapter
|
|
144
|
+
* has no mailbox context of its own) - a real calendar client always sends it regardless, since it already
|
|
145
|
+
* knows its own account's address. Omitting it on an `Add` throws, which `SyncCommand.applyAdd` turns into
|
|
146
|
+
* Status `6` ("client has sent a malformed or invalid item"), the spec's own designated code for exactly
|
|
147
|
+
* this case.
|
|
148
|
+
*
|
|
149
|
+
* `Attendees`/`Recurrence` are ghosted as a whole element, like `ContactsSyncAdapter`'s arrays: present at
|
|
150
|
+
* all -> rebuilt entirely from what's there; absent -> left untouched on a `Change`.
|
|
151
|
+
*/
|
|
152
|
+
fromApplicationData(el) {
|
|
153
|
+
const partial = {};
|
|
154
|
+
const subject = childText(el, "Subject");
|
|
155
|
+
if (subject !== undefined)
|
|
156
|
+
partial.title = subject;
|
|
157
|
+
const location = childText(el, "Location");
|
|
158
|
+
if (location !== undefined)
|
|
159
|
+
partial.location = location;
|
|
160
|
+
const startTime = childText(el, "StartTime");
|
|
161
|
+
if (startTime !== undefined)
|
|
162
|
+
partial.startDate = fromCompactDateTime(startTime);
|
|
163
|
+
const endTime = childText(el, "EndTime");
|
|
164
|
+
if (endTime !== undefined)
|
|
165
|
+
partial.endDate = fromCompactDateTime(endTime);
|
|
166
|
+
const allDayEvent = childText(el, "AllDayEvent");
|
|
167
|
+
if (allDayEvent !== undefined)
|
|
168
|
+
partial.allDay = allDayEvent === "1";
|
|
169
|
+
const busyStatus = childText(el, "BusyStatus");
|
|
170
|
+
if (busyStatus !== undefined) {
|
|
171
|
+
const mapped = BUSY_STATUS_FROM_CODE[busyStatus];
|
|
172
|
+
if (!mapped) {
|
|
173
|
+
throw new Error(`Unrecognized BusyStatus value: '${busyStatus}'`);
|
|
174
|
+
}
|
|
175
|
+
partial.busyStatus = mapped;
|
|
176
|
+
}
|
|
177
|
+
const organizerEmail = childText(el, "OrganizerEmail");
|
|
178
|
+
if (organizerEmail !== undefined) {
|
|
179
|
+
partial.organizer = {
|
|
180
|
+
address: organizerEmail,
|
|
181
|
+
displayName: childText(el, "OrganizerName"),
|
|
182
|
+
type: RecipientType.TO,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const reminder = childText(el, "Reminder");
|
|
186
|
+
if (reminder !== undefined)
|
|
187
|
+
partial.reminderMinutesBeforeStart = Number(reminder);
|
|
188
|
+
const attendeesEl = findChild(el, "Attendees");
|
|
189
|
+
if (attendeesEl) {
|
|
190
|
+
partial.attendees = attendeesEl.children
|
|
191
|
+
.filter((child) => child.tag === "Attendee")
|
|
192
|
+
.map((attendeeEl) => this.attendeeFromElement(attendeeEl));
|
|
193
|
+
}
|
|
194
|
+
const recurrenceEl = findChild(el, "Recurrence");
|
|
195
|
+
if (recurrenceEl) {
|
|
196
|
+
partial.recurrenceRule = this.recurrenceRuleFromElement(recurrenceEl);
|
|
197
|
+
}
|
|
198
|
+
return partial;
|
|
199
|
+
}
|
|
200
|
+
/** `icalUid`/`sequence` have no wire representation on `Add` (see `fromApplicationData`'s own doc comment)
|
|
201
|
+
* - without this, every Sync-created event would fall back to `CalendarEventMongo`/`CalendarEventSQL`'s own
|
|
202
|
+
* constructor default of `icalUid: ""`, violating RFC 5545's uniqueness expectation for `UID`. Mirrors
|
|
203
|
+
* MAPI's identical `RopSaveChangesMessageHandler` pattern (`${crypto.randomUUID()}@mapi`), `@eas` suffix
|
|
204
|
+
* instead. */
|
|
205
|
+
newEntityDefaults() {
|
|
206
|
+
return { icalUid: `${crypto.randomUUID()}@eas`, sequence: 0 };
|
|
207
|
+
}
|
|
208
|
+
attendeeFromElement(el) {
|
|
209
|
+
const address = childText(el, "Email");
|
|
210
|
+
if (!address) {
|
|
211
|
+
throw new Error("Attendee element is missing its required Email child.");
|
|
212
|
+
}
|
|
213
|
+
const attendeeType = childText(el, "AttendeeType");
|
|
214
|
+
const attendeeStatus = childText(el, "AttendeeStatus");
|
|
215
|
+
return {
|
|
216
|
+
address,
|
|
217
|
+
displayName: childText(el, "Name"),
|
|
218
|
+
role: (attendeeType && ATTENDEE_TYPE_FROM_CODE[attendeeType]) || AttendeeRole.REQUIRED,
|
|
219
|
+
responseStatus: (attendeeStatus && ATTENDEE_STATUS_FROM_CODE[attendeeStatus]) || AttendeeResponseStatus.NEEDS_ACTION,
|
|
220
|
+
isOrganizer: false,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
recurrenceRuleFromElement(el) {
|
|
224
|
+
const type = childText(el, "Type");
|
|
225
|
+
const freq = type && RECURRENCE_FREQUENCY_FROM_CODE[type];
|
|
226
|
+
if (!freq) {
|
|
227
|
+
throw new Error(`Unrecognized or unsupported Recurrence Type value: '${type}'`);
|
|
228
|
+
}
|
|
229
|
+
const interval = childText(el, "Interval");
|
|
230
|
+
const dayOfWeek = childText(el, "DayOfWeek");
|
|
231
|
+
const dayOfMonth = childText(el, "DayOfMonth");
|
|
232
|
+
const monthOfYear = childText(el, "MonthOfYear");
|
|
233
|
+
const until = childText(el, "Until");
|
|
234
|
+
const occurrences = childText(el, "Occurrences");
|
|
235
|
+
const byDay = [];
|
|
236
|
+
if (dayOfWeek !== undefined) {
|
|
237
|
+
const bits = Number(dayOfWeek);
|
|
238
|
+
for (const [code, bit] of Object.entries(DAY_OF_WEEK_BITS)) {
|
|
239
|
+
if ((bits & bit) !== 0)
|
|
240
|
+
byDay.push(code);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
freq,
|
|
245
|
+
interval: interval !== undefined ? Number(interval) : 1,
|
|
246
|
+
...(byDay.length > 0 ? { byDay } : {}),
|
|
247
|
+
...(dayOfMonth !== undefined ? { byMonthDay: [Number(dayOfMonth)] } : {}),
|
|
248
|
+
...(monthOfYear !== undefined ? { byMonth: [Number(monthOfYear)] } : {}),
|
|
249
|
+
...(until !== undefined ? { until: fromCompactDateTime(until) } : {}),
|
|
250
|
+
...(occurrences !== undefined ? { count: Number(occurrences) } : {}),
|
|
251
|
+
exceptions: [],
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=CalendarSyncAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CalendarSyncAdapter.js","sourceRoot":"","sources":["../../../src/adapters/CalendarSyncAdapter.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAqB,MAAM,0BAA0B,CAAC;AACzG,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/E,OAAO,EACH,sBAAsB,EACtB,YAAY,EACZ,UAAU,EAGV,mBAAmB,EACnB,aAAa,GAEhB,MAAM,kBAAkB,CAAC;AAE1B,2GAA2G;AAC3G,SAAS,MAAM,CAAmB,KAAwB;IACtD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAsB,CAAC;AAClG,CAAC;AAED;;0FAE0F;AAC1F,MAAM,iBAAiB,GAA+B;IAClD,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG;IACtB,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG;IAC3B,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG;IACtB,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,GAAG;CAClC,CAAC;AAEF;;sGAEsG;AACtG,MAAM,qBAAqB,GAA2C;IAClE,CAAC,sBAAsB,CAAC,YAAY,CAAC,EAAE,GAAG;IAC1C,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,GAAG;IACvC,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,GAAG;IACtC,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,GAAG;CACzC,CAAC;AAEF,mEAAmE;AACnE,MAAM,mBAAmB,GAAiC;IACtD,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG;IAC5B,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG;IAC5B,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG;CAC/B,CAAC;AAEF;;;8DAG8D;AAC9D,MAAM,qBAAqB,GAAwC;IAC/D,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,GAAG;IAChC,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,GAAG;IACjC,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,GAAG;IAClC,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,GAAG;CACpC,CAAC;AAEF;;2BAE2B;AAC3B,MAAM,gBAAgB,GAA2B,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AAExG,MAAM,qBAAqB,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACxD,MAAM,yBAAyB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAChE,MAAM,uBAAuB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC5D,MAAM,8BAA8B,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAErE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,mBAAmB;IAAhC;QACoB,oBAAe,GAAG,UAAU,CAAC;IAgMjD,CAAC;IA9LU,iBAAiB,CAAC,KAAoB;QACzC,MAAM,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QAEhD,OAAO,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,iBAAiB,EAAE;YACrD,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC;YAC3D,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5F,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACpF,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAChF,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAC5E,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACrF,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACtF,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC;YACvD,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAC9E,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC;YAC9E,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW;gBAC3B,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;gBACrF,CAAC,CAAC,EAAE,CAAC;YACT,GAAG,CAAC,YAAY;gBACZ,CAAC,CAAC;oBACI,OAAO,CACH,aAAa,CAAC,QAAQ,EACtB,WAAW,EACX,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC7B,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE;wBACxC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;wBAC9D,GAAG,CAAC,QAAQ,CAAC,WAAW;4BACpB,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;4BACrE,CAAC,CAAC,EAAE,CAAC;wBACT,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;wBACvF,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;qBACxG,CAAC,CACL,CACJ;iBACJ;gBACH,CAAC,CAAC,EAAE,CAAC;YACT,kGAAkG;YAClG,iGAAiG;YACjG,mGAAmG;YACnG,2FAA2F;YAC3F,GAAG,CAAC,KAAK,CAAC,0BAA0B,IAAI,IAAI;gBACxC,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;gBAC7F,CAAC,CAAC,EAAE,CAAC;YACT,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACnG,CAAC,CAAC;IACP,CAAC;IAEO,iBAAiB,CAAC,IAAoB,EAAE,SAAe;QAC3D,MAAM,aAAa,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAErG,OAAO,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE;YACjD,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7E,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,MAAM,IAAI,aAAa,GAAG,CAAC;gBAC7D,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;gBAC3E,CAAC,CAAC,EAAE,CAAC;YACT,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,MAAM;gBACrF,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC7G,CAAC,CAAC,EAAE,CAAC;YACT,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,MAAM;gBACxC,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAChH,CAAC,CAAC,EAAE,CAAC;YACT,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpG,+EAA+E;YAC/E,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1G,CAAC,CAAC;IACP,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACI,mBAAmB,CAAC,EAAgB;QACvC,MAAM,OAAO,GAA2B,EAAE,CAAC;QAE3C,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC;QACnD,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACxD,MAAM,SAAS,GAAG,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7C,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,CAAC,SAAS,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAChF,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC1E,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACjD,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,CAAC,MAAM,GAAG,WAAW,KAAK,GAAG,CAAC;QACpE,MAAM,UAAU,GAAG,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QAC/C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACjD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,mCAAmC,UAAU,GAAG,CAAC,CAAC;YACtE,CAAC;YACD,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC;QAChC,CAAC;QAED,MAAM,cAAc,GAAG,SAAS,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;QACvD,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,SAAS,GAAG;gBAChB,OAAO,EAAE,cAAc;gBACvB,WAAW,EAAE,SAAS,CAAC,EAAE,EAAE,eAAe,CAAC;gBAC3C,IAAI,EAAE,aAAa,CAAC,EAAE;aACzB,CAAC;QACN,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,0BAA0B,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAElF,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC/C,IAAI,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,SAAS,GAAG,WAAW,CAAC,QAAQ;iBACnC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC;iBAC3C,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,YAAY,GAAG,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QACjD,IAAI,YAAY,EAAE,CAAC;YACf,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,yBAAyB,CAAC,YAAY,CAAC,CAAC;QAC1E,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;kBAIc;IACP,iBAAiB;QACpB,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAClE,CAAC;IAEO,mBAAmB,CAAC,EAAgB;QACxC,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,YAAY,GAAG,SAAS,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,cAAc,GAAG,SAAS,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;QACvD,OAAO;YACH,OAAO;YACP,WAAW,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC;YAClC,IAAI,EAAE,CAAC,YAAY,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAC,IAAI,YAAY,CAAC,QAAQ;YACtF,cAAc,EAAE,CAAC,cAAc,IAAI,yBAAyB,CAAC,cAAc,CAAC,CAAC,IAAI,sBAAsB,CAAC,YAAY;YACpH,WAAW,EAAE,KAAK;SACrB,CAAC;IACN,CAAC;IAEO,yBAAyB,CAAC,EAAgB;QAC9C,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,IAAI,8BAA8B,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,MAAM,IAAI,KAAK,CAAC,uDAAuD,IAAI,GAAG,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QAEjD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;YAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACzD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;QAED,OAAO;YACH,IAAI;YACJ,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,UAAU,EAAE,EAAE;SACjB,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { WbxmlCodePage } from "../codec/WbxmlCodePages.js";
|
|
6
|
+
import { childText, element, findChild, findChildren, textElement } from "../codec/WbxmlElement.js";
|
|
7
|
+
import { ContactAddressKind } from "@rapidmx/restapi";
|
|
8
|
+
/** MS-ASCMD only has three positional email slots (`Email1Address`/`Email2Address`/`Email3Address`) - unlike
|
|
9
|
+
* `ContactEmail.type`, EAS doesn't distinguish a "kind" per address, only position. Extra addresses beyond the
|
|
10
|
+
* third are dropped, matching this library's "pragmatic subset" precedent elsewhere. */
|
|
11
|
+
const EMAIL_TAGS = ["Email1Address", "Email2Address", "Email3Address"];
|
|
12
|
+
/** MS-ASCONTACTS street/city/state/postalCode/country tag prefixes, keyed by `ContactAddressKind`. There is no
|
|
13
|
+
* generic "OtherPhoneNumber"-equivalent tag family gap here (Home/Business/Other all exist for addresses,
|
|
14
|
+
* unlike phone numbers below), so all three kinds round-trip. */
|
|
15
|
+
const ADDRESS_PREFIX = {
|
|
16
|
+
[ContactAddressKind.HOME]: "Home",
|
|
17
|
+
[ContactAddressKind.WORK]: "Business",
|
|
18
|
+
[ContactAddressKind.OTHER]: "Other",
|
|
19
|
+
};
|
|
20
|
+
/** MS-ASCONTACTS has no `OtherPhoneNumber`-equivalent tag - only Home/Business phone numbers exist as plain
|
|
21
|
+
* single-value tags (plus several Home2/Business2/Car/Radio/Pager/Fax variants this pragmatic subset doesn't
|
|
22
|
+
* use). A phone tagged `OTHER` in this library's model has nowhere to go and is dropped, documented here rather
|
|
23
|
+
* than silently - matching `FolderSyncCommand`'s own precedent for this kind of unavoidable field-count gap. */
|
|
24
|
+
const PHONE_TAG = {
|
|
25
|
+
[ContactAddressKind.HOME]: "HomePhoneNumber",
|
|
26
|
+
[ContactAddressKind.WORK]: "BusinessPhoneNumber",
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Maps `Contact` to/from the EAS `Sync` `Contacts` collection class (MS-ASCONTACTS/MS-ASCNTC2). Contacts are
|
|
30
|
+
* also this library's GAL source (see the architecture note on `Contact` itself), but that's `SearchCommand`'s
|
|
31
|
+
* concern, not this adapter's.
|
|
32
|
+
*
|
|
33
|
+
* @author Jean-Philippe Steinmetz
|
|
34
|
+
*/
|
|
35
|
+
export class ContactsSyncAdapter {
|
|
36
|
+
constructor() {
|
|
37
|
+
this.collectionClass = "Contacts";
|
|
38
|
+
}
|
|
39
|
+
toApplicationData(contact) {
|
|
40
|
+
const children = [
|
|
41
|
+
textElement(WbxmlCodePage.Contacts, "FileAs", contact.displayName),
|
|
42
|
+
...(contact.givenName ? [textElement(WbxmlCodePage.Contacts, "FirstName", contact.givenName)] : []),
|
|
43
|
+
...(contact.surname ? [textElement(WbxmlCodePage.Contacts, "LastName", contact.surname)] : []),
|
|
44
|
+
...(contact.company ? [textElement(WbxmlCodePage.Contacts, "CompanyName", contact.company)] : []),
|
|
45
|
+
...(contact.jobTitle ? [textElement(WbxmlCodePage.Contacts, "JobTitle", contact.jobTitle)] : []),
|
|
46
|
+
];
|
|
47
|
+
contact.emails.slice(0, EMAIL_TAGS.length).forEach((email, i) => {
|
|
48
|
+
children.push(textElement(WbxmlCodePage.Contacts, EMAIL_TAGS[i], email.address));
|
|
49
|
+
});
|
|
50
|
+
for (const phone of contact.phones) {
|
|
51
|
+
const tag = PHONE_TAG[phone.type];
|
|
52
|
+
if (tag) {
|
|
53
|
+
children.push(textElement(WbxmlCodePage.Contacts, tag, phone.phoneNumber));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const address of contact.addresses) {
|
|
57
|
+
children.push(...this.addressElements(address));
|
|
58
|
+
}
|
|
59
|
+
if (contact.notes) {
|
|
60
|
+
children.push(element(WbxmlCodePage.AirSyncBase, "Body", [
|
|
61
|
+
textElement(WbxmlCodePage.AirSyncBase, "Type", "1"),
|
|
62
|
+
textElement(WbxmlCodePage.AirSyncBase, "EstimatedDataSize", String(Buffer.byteLength(contact.notes, "utf8"))),
|
|
63
|
+
textElement(WbxmlCodePage.AirSyncBase, "Data", contact.notes),
|
|
64
|
+
]));
|
|
65
|
+
}
|
|
66
|
+
if (contact.categories && contact.categories.length > 0) {
|
|
67
|
+
children.push(element(WbxmlCodePage.Contacts, "Categories", contact.categories.map((category) => textElement(WbxmlCodePage.Contacts, "Category", category))));
|
|
68
|
+
}
|
|
69
|
+
return element(WbxmlCodePage.AirSync, "ApplicationData", children);
|
|
70
|
+
}
|
|
71
|
+
addressElements(address) {
|
|
72
|
+
const prefix = ADDRESS_PREFIX[address.type];
|
|
73
|
+
const parts = [
|
|
74
|
+
[`${prefix}Street`, address.street],
|
|
75
|
+
[`${prefix}City`, address.city],
|
|
76
|
+
[`${prefix}State`, address.state],
|
|
77
|
+
[`${prefix}PostalCode`, address.postalCode],
|
|
78
|
+
[`${prefix}Country`, address.country],
|
|
79
|
+
];
|
|
80
|
+
return parts
|
|
81
|
+
.filter((part) => part[1] !== undefined)
|
|
82
|
+
.map(([tag, value]) => textElement(WbxmlCodePage.Contacts, tag, value));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Reverse of `toApplicationData`. Scalar fields (`FileAs`/`FirstName`/.../`JobTitle`, and the `Body`
|
|
86
|
+
* `notes`) are properly ghosted - a field's own tag missing from `el` leaves that `Contact` field
|
|
87
|
+
* untouched. `emails`/`phones`/`addresses` are ghosted only as a **whole group**, not per slot: if *none*
|
|
88
|
+
* of a group's tags are present the group is left untouched, but if *any* one is, the entire group is
|
|
89
|
+
* rebuilt from just what's present in `el` (a real client's own Contacts edit UI typically resends every
|
|
90
|
+
* field it manages anyway, so this only under-preserves data for a client that deliberately sends a
|
|
91
|
+
* single-slot partial update within one of these groups - a documented simplification, not silent data
|
|
92
|
+
* loss for the common case). Emails lose their original `type` on any round trip through a `Change`
|
|
93
|
+
* (rebuilt as `ContactAddressKind.OTHER`) since EAS's own `Email1/2/3Address` tags carry no kind at all,
|
|
94
|
+
* matching `toApplicationData`'s own already-documented encode-side loss of the same information.
|
|
95
|
+
* `categories` is ghosted as its own whole group (same rule as `emails`/`phones`/`addresses`): an absent
|
|
96
|
+
* `Categories` element leaves `Contact.categories` untouched, while a present one - even `<Categories/>`
|
|
97
|
+
* with no `Category` children - rebuilds it from scratch (an empty array clears it).
|
|
98
|
+
*/
|
|
99
|
+
fromApplicationData(el) {
|
|
100
|
+
const partial = {};
|
|
101
|
+
const fileAs = childText(el, "FileAs");
|
|
102
|
+
if (fileAs !== undefined)
|
|
103
|
+
partial.displayName = fileAs;
|
|
104
|
+
const firstName = childText(el, "FirstName");
|
|
105
|
+
if (firstName !== undefined)
|
|
106
|
+
partial.givenName = firstName;
|
|
107
|
+
const lastName = childText(el, "LastName");
|
|
108
|
+
if (lastName !== undefined)
|
|
109
|
+
partial.surname = lastName;
|
|
110
|
+
const companyName = childText(el, "CompanyName");
|
|
111
|
+
if (companyName !== undefined)
|
|
112
|
+
partial.company = companyName;
|
|
113
|
+
const jobTitle = childText(el, "JobTitle");
|
|
114
|
+
if (jobTitle !== undefined)
|
|
115
|
+
partial.jobTitle = jobTitle;
|
|
116
|
+
if (EMAIL_TAGS.some((tag) => findChild(el, tag))) {
|
|
117
|
+
partial.emails = EMAIL_TAGS.map((tag) => childText(el, tag))
|
|
118
|
+
.filter((address) => !!address)
|
|
119
|
+
.map((address) => ({ address, type: ContactAddressKind.OTHER }));
|
|
120
|
+
}
|
|
121
|
+
const phoneEntries = Object.entries(PHONE_TAG);
|
|
122
|
+
if (phoneEntries.some(([, tag]) => findChild(el, tag))) {
|
|
123
|
+
partial.phones = phoneEntries
|
|
124
|
+
.map(([type, tag]) => ({ type, phoneNumber: childText(el, tag) }))
|
|
125
|
+
.filter((phone) => !!phone.phoneNumber);
|
|
126
|
+
}
|
|
127
|
+
const addressKinds = Object.values(ContactAddressKind);
|
|
128
|
+
const touchedKinds = addressKinds.filter((kind) => this.addressTags(kind).some((tag) => findChild(el, tag)));
|
|
129
|
+
if (touchedKinds.length > 0) {
|
|
130
|
+
partial.addresses = touchedKinds
|
|
131
|
+
.map((kind) => this.parseAddress(el, kind))
|
|
132
|
+
.filter((address) => address !== undefined);
|
|
133
|
+
}
|
|
134
|
+
const bodyEl = findChild(el, "Body");
|
|
135
|
+
const notes = bodyEl ? childText(bodyEl, "Data") : undefined;
|
|
136
|
+
if (notes !== undefined)
|
|
137
|
+
partial.notes = notes;
|
|
138
|
+
const categoriesEl = findChild(el, "Categories");
|
|
139
|
+
if (categoriesEl) {
|
|
140
|
+
partial.categories = findChildren(categoriesEl, "Category")
|
|
141
|
+
.map((category) => category.text)
|
|
142
|
+
.filter((category) => !!category);
|
|
143
|
+
}
|
|
144
|
+
return partial;
|
|
145
|
+
}
|
|
146
|
+
addressTags(kind) {
|
|
147
|
+
const prefix = ADDRESS_PREFIX[kind];
|
|
148
|
+
return [`${prefix}Street`, `${prefix}City`, `${prefix}State`, `${prefix}PostalCode`, `${prefix}Country`];
|
|
149
|
+
}
|
|
150
|
+
parseAddress(el, kind) {
|
|
151
|
+
const prefix = ADDRESS_PREFIX[kind];
|
|
152
|
+
const address = {
|
|
153
|
+
type: kind,
|
|
154
|
+
street: childText(el, `${prefix}Street`),
|
|
155
|
+
city: childText(el, `${prefix}City`),
|
|
156
|
+
state: childText(el, `${prefix}State`),
|
|
157
|
+
postalCode: childText(el, `${prefix}PostalCode`),
|
|
158
|
+
country: childText(el, `${prefix}Country`),
|
|
159
|
+
};
|
|
160
|
+
const hasAnyField = address.street || address.city || address.state || address.postalCode || address.country;
|
|
161
|
+
return hasAnyField ? address : undefined;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=ContactsSyncAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactsSyncAdapter.js","sourceRoot":"","sources":["../../../src/adapters/ContactsSyncAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EasCollectionSyncAdapter.js","sourceRoot":"","sources":["../../../src/adapters/EasCollectionSyncAdapter.ts"],"names":[],"mappings":""}
|