mcp-twake-mail 0.1.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 +663 -0
- package/README.md +332 -0
- package/build/auth/index.d.ts +3 -0
- package/build/auth/index.js +4 -0
- package/build/auth/index.js.map +1 -0
- package/build/auth/oidc-flow.d.ts +47 -0
- package/build/auth/oidc-flow.js +146 -0
- package/build/auth/oidc-flow.js.map +1 -0
- package/build/auth/token-refresh.d.ts +56 -0
- package/build/auth/token-refresh.js +132 -0
- package/build/auth/token-refresh.js.map +1 -0
- package/build/auth/token-store.d.ts +33 -0
- package/build/auth/token-store.js +63 -0
- package/build/auth/token-store.js.map +1 -0
- package/build/cli/commands/auth.d.ts +5 -0
- package/build/cli/commands/auth.js +49 -0
- package/build/cli/commands/auth.js.map +1 -0
- package/build/cli/commands/check.d.ts +4 -0
- package/build/cli/commands/check.js +125 -0
- package/build/cli/commands/check.js.map +1 -0
- package/build/cli/commands/setup.d.ts +4 -0
- package/build/cli/commands/setup.js +172 -0
- package/build/cli/commands/setup.js.map +1 -0
- package/build/cli/index.d.ts +15 -0
- package/build/cli/index.js +56 -0
- package/build/cli/index.js.map +1 -0
- package/build/cli/prompts/setup-wizard.d.ts +38 -0
- package/build/cli/prompts/setup-wizard.js +121 -0
- package/build/cli/prompts/setup-wizard.js.map +1 -0
- package/build/config/__tests__/logger.test.d.ts +1 -0
- package/build/config/__tests__/logger.test.js +28 -0
- package/build/config/__tests__/logger.test.js.map +1 -0
- package/build/config/__tests__/schema.test.d.ts +1 -0
- package/build/config/__tests__/schema.test.js +101 -0
- package/build/config/__tests__/schema.test.js.map +1 -0
- package/build/config/logger.d.ts +3 -0
- package/build/config/logger.js +9 -0
- package/build/config/logger.js.map +1 -0
- package/build/config/schema.d.ts +28 -0
- package/build/config/schema.js +81 -0
- package/build/config/schema.js.map +1 -0
- package/build/errors.d.ts +34 -0
- package/build/errors.js +154 -0
- package/build/errors.js.map +1 -0
- package/build/errors.test.d.ts +1 -0
- package/build/errors.test.js +234 -0
- package/build/errors.test.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +12 -0
- package/build/index.js.map +1 -0
- package/build/jmap/client.d.ts +96 -0
- package/build/jmap/client.js +267 -0
- package/build/jmap/client.js.map +1 -0
- package/build/mcp/server.d.ts +24 -0
- package/build/mcp/server.js +68 -0
- package/build/mcp/server.js.map +1 -0
- package/build/mcp/tools/attachment.d.ts +30 -0
- package/build/mcp/tools/attachment.js +246 -0
- package/build/mcp/tools/attachment.js.map +1 -0
- package/build/mcp/tools/attachment.test.d.ts +1 -0
- package/build/mcp/tools/attachment.test.js +457 -0
- package/build/mcp/tools/attachment.test.js.map +1 -0
- package/build/mcp/tools/email-operations.d.ts +10 -0
- package/build/mcp/tools/email-operations.js +828 -0
- package/build/mcp/tools/email-operations.js.map +1 -0
- package/build/mcp/tools/email-operations.test.d.ts +1 -0
- package/build/mcp/tools/email-operations.test.js +453 -0
- package/build/mcp/tools/email-operations.test.js.map +1 -0
- package/build/mcp/tools/email-sending.d.ts +10 -0
- package/build/mcp/tools/email-sending.js +682 -0
- package/build/mcp/tools/email-sending.js.map +1 -0
- package/build/mcp/tools/email.d.ts +10 -0
- package/build/mcp/tools/email.js +365 -0
- package/build/mcp/tools/email.js.map +1 -0
- package/build/mcp/tools/email.test.d.ts +1 -0
- package/build/mcp/tools/email.test.js +332 -0
- package/build/mcp/tools/email.test.js.map +1 -0
- package/build/mcp/tools/index.d.ts +14 -0
- package/build/mcp/tools/index.js +29 -0
- package/build/mcp/tools/index.js.map +1 -0
- package/build/mcp/tools/mailbox.d.ts +10 -0
- package/build/mcp/tools/mailbox.js +195 -0
- package/build/mcp/tools/mailbox.js.map +1 -0
- package/build/mcp/tools/mailbox.test.d.ts +1 -0
- package/build/mcp/tools/mailbox.test.js +231 -0
- package/build/mcp/tools/mailbox.test.js.map +1 -0
- package/build/mcp/tools/thread.d.ts +10 -0
- package/build/mcp/tools/thread.js +282 -0
- package/build/mcp/tools/thread.js.map +1 -0
- package/build/mcp/tools/thread.test.d.ts +1 -0
- package/build/mcp/tools/thread.test.js +384 -0
- package/build/mcp/tools/thread.test.js.map +1 -0
- package/build/transformers/__tests__/email.test.d.ts +1 -0
- package/build/transformers/__tests__/email.test.js +438 -0
- package/build/transformers/__tests__/email.test.js.map +1 -0
- package/build/transformers/__tests__/mailbox.test.d.ts +1 -0
- package/build/transformers/__tests__/mailbox.test.js +222 -0
- package/build/transformers/__tests__/mailbox.test.js.map +1 -0
- package/build/transformers/email.d.ts +76 -0
- package/build/transformers/email.js +138 -0
- package/build/transformers/email.js.map +1 -0
- package/build/transformers/index.d.ts +5 -0
- package/build/transformers/index.js +6 -0
- package/build/transformers/index.js.map +1 -0
- package/build/transformers/mailbox.d.ts +43 -0
- package/build/transformers/mailbox.js +70 -0
- package/build/transformers/mailbox.js.map +1 -0
- package/build/types/dto.d.ts +91 -0
- package/build/types/dto.js +9 -0
- package/build/types/dto.js.map +1 -0
- package/build/types/jmap.d.ts +110 -0
- package/build/types/jmap.js +5 -0
- package/build/types/jmap.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for mailbox transformer - converts JMAP Mailbox objects to SimplifiedMailbox DTOs.
|
|
3
|
+
* TDD RED phase: These tests define the expected behavior.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import { transformMailbox } from '../mailbox.js';
|
|
7
|
+
describe('transformMailbox', () => {
|
|
8
|
+
describe('core fields', () => {
|
|
9
|
+
it('transforms basic mailbox properties', () => {
|
|
10
|
+
const jmapMailbox = {
|
|
11
|
+
id: 'm1',
|
|
12
|
+
name: 'Inbox',
|
|
13
|
+
role: 'inbox',
|
|
14
|
+
totalEmails: 100,
|
|
15
|
+
unreadEmails: 5,
|
|
16
|
+
sortOrder: 1,
|
|
17
|
+
parentId: null,
|
|
18
|
+
};
|
|
19
|
+
const result = transformMailbox(jmapMailbox);
|
|
20
|
+
expect(result.id).toBe('m1');
|
|
21
|
+
expect(result.name).toBe('Inbox');
|
|
22
|
+
expect(result.role).toBe('inbox');
|
|
23
|
+
expect(result.totalEmails).toBe(100);
|
|
24
|
+
expect(result.unreadEmails).toBe(5);
|
|
25
|
+
expect(result.sortOrder).toBe(1);
|
|
26
|
+
expect(result.parentId).toBeNull();
|
|
27
|
+
});
|
|
28
|
+
it('preserves null role for custom folders', () => {
|
|
29
|
+
const jmapMailbox = {
|
|
30
|
+
id: 'm2',
|
|
31
|
+
name: 'Custom Folder',
|
|
32
|
+
role: null,
|
|
33
|
+
totalEmails: 50,
|
|
34
|
+
unreadEmails: 0,
|
|
35
|
+
sortOrder: 100,
|
|
36
|
+
parentId: null,
|
|
37
|
+
};
|
|
38
|
+
const result = transformMailbox(jmapMailbox);
|
|
39
|
+
expect(result.role).toBeNull();
|
|
40
|
+
expect(result.name).toBe('Custom Folder');
|
|
41
|
+
});
|
|
42
|
+
it('preserves parentId for nested folders', () => {
|
|
43
|
+
const jmapMailbox = {
|
|
44
|
+
id: 'm3',
|
|
45
|
+
name: 'Subfolder',
|
|
46
|
+
role: null,
|
|
47
|
+
totalEmails: 10,
|
|
48
|
+
unreadEmails: 2,
|
|
49
|
+
sortOrder: 50,
|
|
50
|
+
parentId: 'm1',
|
|
51
|
+
};
|
|
52
|
+
const result = transformMailbox(jmapMailbox);
|
|
53
|
+
expect(result.parentId).toBe('m1');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('standard roles', () => {
|
|
57
|
+
// Non-null roles only for testing
|
|
58
|
+
const standardRoles = [
|
|
59
|
+
'inbox',
|
|
60
|
+
'drafts',
|
|
61
|
+
'sent',
|
|
62
|
+
'trash',
|
|
63
|
+
'junk',
|
|
64
|
+
'archive',
|
|
65
|
+
'all',
|
|
66
|
+
'important',
|
|
67
|
+
'subscribed',
|
|
68
|
+
];
|
|
69
|
+
it.each([...standardRoles])('preserves standard role: %s', (role) => {
|
|
70
|
+
const jmapMailbox = {
|
|
71
|
+
id: `m-${role}`,
|
|
72
|
+
name: role.charAt(0).toUpperCase() + role.slice(1),
|
|
73
|
+
role: role,
|
|
74
|
+
totalEmails: 10,
|
|
75
|
+
unreadEmails: 1,
|
|
76
|
+
sortOrder: 1,
|
|
77
|
+
parentId: null,
|
|
78
|
+
};
|
|
79
|
+
const result = transformMailbox(jmapMailbox);
|
|
80
|
+
expect(result.role).toBe(role);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('email counts', () => {
|
|
84
|
+
it('handles zero counts', () => {
|
|
85
|
+
const jmapMailbox = {
|
|
86
|
+
id: 'm4',
|
|
87
|
+
name: 'Empty Folder',
|
|
88
|
+
role: null,
|
|
89
|
+
totalEmails: 0,
|
|
90
|
+
unreadEmails: 0,
|
|
91
|
+
sortOrder: 10,
|
|
92
|
+
parentId: null,
|
|
93
|
+
};
|
|
94
|
+
const result = transformMailbox(jmapMailbox);
|
|
95
|
+
expect(result.totalEmails).toBe(0);
|
|
96
|
+
expect(result.unreadEmails).toBe(0);
|
|
97
|
+
});
|
|
98
|
+
it('handles large counts', () => {
|
|
99
|
+
const jmapMailbox = {
|
|
100
|
+
id: 'm5',
|
|
101
|
+
name: 'Archive',
|
|
102
|
+
role: 'archive',
|
|
103
|
+
totalEmails: 100000,
|
|
104
|
+
unreadEmails: 50000,
|
|
105
|
+
sortOrder: 10,
|
|
106
|
+
parentId: null,
|
|
107
|
+
};
|
|
108
|
+
const result = transformMailbox(jmapMailbox);
|
|
109
|
+
expect(result.totalEmails).toBe(100000);
|
|
110
|
+
expect(result.unreadEmails).toBe(50000);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe('optional fields', () => {
|
|
114
|
+
it('handles missing optional fields gracefully', () => {
|
|
115
|
+
const jmapMailbox = {
|
|
116
|
+
id: 'm6',
|
|
117
|
+
name: 'Minimal Mailbox',
|
|
118
|
+
role: null,
|
|
119
|
+
totalEmails: 5,
|
|
120
|
+
unreadEmails: 1,
|
|
121
|
+
sortOrder: 1,
|
|
122
|
+
parentId: null,
|
|
123
|
+
};
|
|
124
|
+
const result = transformMailbox(jmapMailbox);
|
|
125
|
+
expect(result.id).toBe('m6');
|
|
126
|
+
// Should not throw and should return valid object
|
|
127
|
+
expect(result).toHaveProperty('id');
|
|
128
|
+
expect(result).toHaveProperty('name');
|
|
129
|
+
expect(result).toHaveProperty('role');
|
|
130
|
+
expect(result).toHaveProperty('totalEmails');
|
|
131
|
+
expect(result).toHaveProperty('unreadEmails');
|
|
132
|
+
});
|
|
133
|
+
it('includes totalThreads when present', () => {
|
|
134
|
+
const jmapMailbox = {
|
|
135
|
+
id: 'm7',
|
|
136
|
+
name: 'With Threads',
|
|
137
|
+
role: 'inbox',
|
|
138
|
+
totalEmails: 100,
|
|
139
|
+
unreadEmails: 10,
|
|
140
|
+
totalThreads: 80,
|
|
141
|
+
unreadThreads: 8,
|
|
142
|
+
sortOrder: 1,
|
|
143
|
+
parentId: null,
|
|
144
|
+
};
|
|
145
|
+
const result = transformMailbox(jmapMailbox);
|
|
146
|
+
expect(result.totalThreads).toBe(80);
|
|
147
|
+
expect(result.unreadThreads).toBe(8);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
describe('sorting', () => {
|
|
151
|
+
it('preserves sortOrder values', () => {
|
|
152
|
+
const mailboxes = [
|
|
153
|
+
{ id: 'm1', name: 'Inbox', role: 'inbox', totalEmails: 100, unreadEmails: 5, sortOrder: 1, parentId: null },
|
|
154
|
+
{ id: 'm2', name: 'Sent', role: 'sent', totalEmails: 50, unreadEmails: 0, sortOrder: 2, parentId: null },
|
|
155
|
+
{ id: 'm3', name: 'Custom', role: null, totalEmails: 10, unreadEmails: 1, sortOrder: 100, parentId: null },
|
|
156
|
+
];
|
|
157
|
+
const results = mailboxes.map(transformMailbox);
|
|
158
|
+
expect(results[0].sortOrder).toBe(1);
|
|
159
|
+
expect(results[1].sortOrder).toBe(2);
|
|
160
|
+
expect(results[2].sortOrder).toBe(100);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('myRights', () => {
|
|
164
|
+
it('includes myRights when present', () => {
|
|
165
|
+
const jmapMailbox = {
|
|
166
|
+
id: 'm8',
|
|
167
|
+
name: 'Shared Folder',
|
|
168
|
+
role: null,
|
|
169
|
+
totalEmails: 10,
|
|
170
|
+
unreadEmails: 2,
|
|
171
|
+
sortOrder: 50,
|
|
172
|
+
parentId: null,
|
|
173
|
+
myRights: {
|
|
174
|
+
mayReadItems: true,
|
|
175
|
+
mayAddItems: true,
|
|
176
|
+
mayRemoveItems: false,
|
|
177
|
+
maySetSeen: true,
|
|
178
|
+
maySetKeywords: true,
|
|
179
|
+
mayCreateChild: false,
|
|
180
|
+
mayRename: false,
|
|
181
|
+
mayDelete: false,
|
|
182
|
+
maySubmit: true,
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
const result = transformMailbox(jmapMailbox);
|
|
186
|
+
expect(result.myRights).toBeDefined();
|
|
187
|
+
expect(result.myRights.mayReadItems).toBe(true);
|
|
188
|
+
expect(result.myRights.mayRemoveItems).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe('isSubscribed', () => {
|
|
192
|
+
it('includes isSubscribed when present', () => {
|
|
193
|
+
const jmapMailbox = {
|
|
194
|
+
id: 'm9',
|
|
195
|
+
name: 'Subscribed Folder',
|
|
196
|
+
role: null,
|
|
197
|
+
totalEmails: 10,
|
|
198
|
+
unreadEmails: 0,
|
|
199
|
+
sortOrder: 50,
|
|
200
|
+
parentId: null,
|
|
201
|
+
isSubscribed: true,
|
|
202
|
+
};
|
|
203
|
+
const result = transformMailbox(jmapMailbox);
|
|
204
|
+
expect(result.isSubscribed).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
it('handles isSubscribed: false', () => {
|
|
207
|
+
const jmapMailbox = {
|
|
208
|
+
id: 'm10',
|
|
209
|
+
name: 'Unsubscribed Folder',
|
|
210
|
+
role: null,
|
|
211
|
+
totalEmails: 10,
|
|
212
|
+
unreadEmails: 0,
|
|
213
|
+
sortOrder: 50,
|
|
214
|
+
parentId: null,
|
|
215
|
+
isSubscribed: false,
|
|
216
|
+
};
|
|
217
|
+
const result = transformMailbox(jmapMailbox);
|
|
218
|
+
expect(result.isSubscribed).toBe(false);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
//# sourceMappingURL=mailbox.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mailbox.test.js","sourceRoot":"","sources":["../../../src/transformers/__tests__/mailbox.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email transformer - converts JMAP Email objects to SimplifiedEmail DTOs.
|
|
3
|
+
* Implements TRANS-03: keyword to boolean flag conversion.
|
|
4
|
+
*/
|
|
5
|
+
import type { SimplifiedEmail } from '../types/dto.js';
|
|
6
|
+
/**
|
|
7
|
+
* JMAP Email address structure (from RFC 8621).
|
|
8
|
+
*/
|
|
9
|
+
interface JMAPEmailAddress {
|
|
10
|
+
name: string | null;
|
|
11
|
+
email: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* JMAP Attachment structure.
|
|
15
|
+
*/
|
|
16
|
+
interface JMAPAttachment {
|
|
17
|
+
blobId: string;
|
|
18
|
+
type: string;
|
|
19
|
+
name: string | null;
|
|
20
|
+
size: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* JMAP body part reference.
|
|
24
|
+
*/
|
|
25
|
+
interface JMAPBodyPart {
|
|
26
|
+
partId: string;
|
|
27
|
+
type: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* JMAP body value.
|
|
31
|
+
*/
|
|
32
|
+
interface JMAPBodyValue {
|
|
33
|
+
value: string;
|
|
34
|
+
isEncodingProblem: boolean;
|
|
35
|
+
isTruncated: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* JMAP Email object structure (subset needed for transformation).
|
|
39
|
+
*/
|
|
40
|
+
interface JMAPEmail {
|
|
41
|
+
id: string;
|
|
42
|
+
blobId: string;
|
|
43
|
+
threadId: string;
|
|
44
|
+
mailboxIds: Record<string, boolean>;
|
|
45
|
+
keywords?: Record<string, boolean>;
|
|
46
|
+
receivedAt: string;
|
|
47
|
+
subject: string | null;
|
|
48
|
+
from: JMAPEmailAddress[];
|
|
49
|
+
to: JMAPEmailAddress[];
|
|
50
|
+
cc?: JMAPEmailAddress[];
|
|
51
|
+
bcc?: JMAPEmailAddress[];
|
|
52
|
+
replyTo?: JMAPEmailAddress[];
|
|
53
|
+
preview?: string;
|
|
54
|
+
size?: number;
|
|
55
|
+
hasAttachment?: boolean;
|
|
56
|
+
textBody?: JMAPBodyPart[];
|
|
57
|
+
htmlBody?: JMAPBodyPart[];
|
|
58
|
+
bodyValues?: Record<string, JMAPBodyValue>;
|
|
59
|
+
attachments?: JMAPAttachment[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Transform a JMAP Email object to SimplifiedEmail DTO.
|
|
63
|
+
* Converts keywords to boolean flags and mailboxIds to array.
|
|
64
|
+
*
|
|
65
|
+
* Keyword mapping:
|
|
66
|
+
* - $seen -> isRead
|
|
67
|
+
* - $flagged -> isFlagged
|
|
68
|
+
* - $draft -> isDraft
|
|
69
|
+
* - $answered -> isAnswered
|
|
70
|
+
* - $forwarded -> isForwarded
|
|
71
|
+
*
|
|
72
|
+
* @param jmapEmail JMAP Email object
|
|
73
|
+
* @returns SimplifiedEmail DTO
|
|
74
|
+
*/
|
|
75
|
+
export declare function transformEmail(jmapEmail: JMAPEmail): SimplifiedEmail;
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert JMAP mailboxIds object to string array.
|
|
3
|
+
* Filters to only include mailboxes where value is true.
|
|
4
|
+
* @param mailboxIds Record of mailbox ID to boolean
|
|
5
|
+
* @returns Array of mailbox IDs
|
|
6
|
+
*/
|
|
7
|
+
function convertMailboxIds(mailboxIds) {
|
|
8
|
+
return Object.entries(mailboxIds)
|
|
9
|
+
.filter(([, isInMailbox]) => isInMailbox)
|
|
10
|
+
.map(([mailboxId]) => mailboxId);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Extract boolean flag from keywords object.
|
|
14
|
+
* @param keywords Keywords object or undefined
|
|
15
|
+
* @param keyword Keyword to check (e.g., '$seen')
|
|
16
|
+
* @returns true if keyword is set, false otherwise
|
|
17
|
+
*/
|
|
18
|
+
function hasKeyword(keywords, keyword) {
|
|
19
|
+
return keywords?.[keyword] === true;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Transform JMAP email addresses to EmailAddress DTOs.
|
|
23
|
+
* @param addresses JMAP email addresses
|
|
24
|
+
* @returns EmailAddress array
|
|
25
|
+
*/
|
|
26
|
+
function transformAddresses(addresses) {
|
|
27
|
+
if (!addresses) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return addresses.map((addr) => ({
|
|
31
|
+
name: addr.name,
|
|
32
|
+
email: addr.email,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extract body content from JMAP body parts and values.
|
|
37
|
+
* @param bodyParts Body part references (textBody or htmlBody)
|
|
38
|
+
* @param bodyValues Body values keyed by partId
|
|
39
|
+
* @returns Extracted body text or undefined
|
|
40
|
+
*/
|
|
41
|
+
function extractBodyContent(bodyParts, bodyValues) {
|
|
42
|
+
if (!bodyParts || !bodyValues || bodyParts.length === 0) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
// Use first body part
|
|
46
|
+
const firstPart = bodyParts[0];
|
|
47
|
+
const value = bodyValues[firstPart.partId];
|
|
48
|
+
return value?.value;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Transform JMAP attachments to SimplifiedAttachment DTOs.
|
|
52
|
+
* @param attachments JMAP attachments
|
|
53
|
+
* @returns SimplifiedAttachment array or undefined
|
|
54
|
+
*/
|
|
55
|
+
function transformAttachments(attachments) {
|
|
56
|
+
if (!attachments || attachments.length === 0) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return attachments.map((att) => ({
|
|
60
|
+
blobId: att.blobId,
|
|
61
|
+
type: att.type,
|
|
62
|
+
name: att.name,
|
|
63
|
+
size: att.size,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Transform a JMAP Email object to SimplifiedEmail DTO.
|
|
68
|
+
* Converts keywords to boolean flags and mailboxIds to array.
|
|
69
|
+
*
|
|
70
|
+
* Keyword mapping:
|
|
71
|
+
* - $seen -> isRead
|
|
72
|
+
* - $flagged -> isFlagged
|
|
73
|
+
* - $draft -> isDraft
|
|
74
|
+
* - $answered -> isAnswered
|
|
75
|
+
* - $forwarded -> isForwarded
|
|
76
|
+
*
|
|
77
|
+
* @param jmapEmail JMAP Email object
|
|
78
|
+
* @returns SimplifiedEmail DTO
|
|
79
|
+
*/
|
|
80
|
+
export function transformEmail(jmapEmail) {
|
|
81
|
+
const keywords = jmapEmail.keywords;
|
|
82
|
+
const result = {
|
|
83
|
+
// Core identifiers
|
|
84
|
+
id: jmapEmail.id,
|
|
85
|
+
blobId: jmapEmail.blobId,
|
|
86
|
+
threadId: jmapEmail.threadId,
|
|
87
|
+
// Convert mailboxIds from object to array
|
|
88
|
+
mailboxIds: convertMailboxIds(jmapEmail.mailboxIds),
|
|
89
|
+
// Convert keywords to boolean flags
|
|
90
|
+
isRead: hasKeyword(keywords, '$seen'),
|
|
91
|
+
isFlagged: hasKeyword(keywords, '$flagged'),
|
|
92
|
+
isDraft: hasKeyword(keywords, '$draft'),
|
|
93
|
+
isAnswered: hasKeyword(keywords, '$answered'),
|
|
94
|
+
isForwarded: hasKeyword(keywords, '$forwarded'),
|
|
95
|
+
// Timestamp
|
|
96
|
+
receivedAt: jmapEmail.receivedAt,
|
|
97
|
+
// Content metadata
|
|
98
|
+
subject: jmapEmail.subject,
|
|
99
|
+
// Address fields
|
|
100
|
+
from: transformAddresses(jmapEmail.from),
|
|
101
|
+
to: transformAddresses(jmapEmail.to),
|
|
102
|
+
};
|
|
103
|
+
// Add optional fields only if present
|
|
104
|
+
if (jmapEmail.preview !== undefined) {
|
|
105
|
+
result.preview = jmapEmail.preview;
|
|
106
|
+
}
|
|
107
|
+
if (jmapEmail.size !== undefined) {
|
|
108
|
+
result.size = jmapEmail.size;
|
|
109
|
+
}
|
|
110
|
+
if (jmapEmail.hasAttachment !== undefined) {
|
|
111
|
+
result.hasAttachment = jmapEmail.hasAttachment;
|
|
112
|
+
}
|
|
113
|
+
if (jmapEmail.cc) {
|
|
114
|
+
result.cc = transformAddresses(jmapEmail.cc);
|
|
115
|
+
}
|
|
116
|
+
if (jmapEmail.bcc) {
|
|
117
|
+
result.bcc = transformAddresses(jmapEmail.bcc);
|
|
118
|
+
}
|
|
119
|
+
if (jmapEmail.replyTo) {
|
|
120
|
+
result.replyTo = transformAddresses(jmapEmail.replyTo);
|
|
121
|
+
}
|
|
122
|
+
// Extract body content if available
|
|
123
|
+
const textBody = extractBodyContent(jmapEmail.textBody, jmapEmail.bodyValues);
|
|
124
|
+
if (textBody !== undefined) {
|
|
125
|
+
result.textBody = textBody;
|
|
126
|
+
}
|
|
127
|
+
const htmlBody = extractBodyContent(jmapEmail.htmlBody, jmapEmail.bodyValues);
|
|
128
|
+
if (htmlBody !== undefined) {
|
|
129
|
+
result.htmlBody = htmlBody;
|
|
130
|
+
}
|
|
131
|
+
// Transform attachments
|
|
132
|
+
const attachments = transformAttachments(jmapEmail.attachments);
|
|
133
|
+
if (attachments !== undefined) {
|
|
134
|
+
result.attachments = attachments;
|
|
135
|
+
}
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../../src/transformers/email.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transformers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mailbox transformer - converts JMAP Mailbox objects to SimplifiedMailbox DTOs.
|
|
3
|
+
*/
|
|
4
|
+
import type { SimplifiedMailbox } from '../types/dto.js';
|
|
5
|
+
/**
|
|
6
|
+
* JMAP Mailbox rights structure (from RFC 8621).
|
|
7
|
+
*/
|
|
8
|
+
interface JMAPMailboxRights {
|
|
9
|
+
mayReadItems: boolean;
|
|
10
|
+
mayAddItems: boolean;
|
|
11
|
+
mayRemoveItems: boolean;
|
|
12
|
+
maySetSeen: boolean;
|
|
13
|
+
maySetKeywords: boolean;
|
|
14
|
+
mayCreateChild: boolean;
|
|
15
|
+
mayRename: boolean;
|
|
16
|
+
mayDelete: boolean;
|
|
17
|
+
maySubmit: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* JMAP Mailbox object structure (subset needed for transformation).
|
|
21
|
+
*/
|
|
22
|
+
interface JMAPMailbox {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
role: string | null;
|
|
26
|
+
totalEmails: number;
|
|
27
|
+
unreadEmails: number;
|
|
28
|
+
sortOrder: number;
|
|
29
|
+
parentId: string | null;
|
|
30
|
+
totalThreads?: number;
|
|
31
|
+
unreadThreads?: number;
|
|
32
|
+
myRights?: JMAPMailboxRights;
|
|
33
|
+
isSubscribed?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Transform a JMAP Mailbox object to SimplifiedMailbox DTO.
|
|
37
|
+
* Straightforward property mapping with type safety.
|
|
38
|
+
*
|
|
39
|
+
* @param jmapMailbox JMAP Mailbox object
|
|
40
|
+
* @returns SimplifiedMailbox DTO
|
|
41
|
+
*/
|
|
42
|
+
export declare function transformMailbox(jmapMailbox: JMAPMailbox): SimplifiedMailbox;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate and type-cast role to MailboxRole.
|
|
3
|
+
* @param role Raw role string from JMAP
|
|
4
|
+
* @returns Typed MailboxRole
|
|
5
|
+
*/
|
|
6
|
+
function castRole(role) {
|
|
7
|
+
if (role === null) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
// Known roles are passed through; unknown roles are treated as null
|
|
11
|
+
const knownRoles = ['inbox', 'drafts', 'sent', 'trash', 'junk', 'archive', 'all', 'important', 'subscribed'];
|
|
12
|
+
return knownRoles.includes(role) ? role : null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Transform JMAP mailbox rights to MailboxRights DTO.
|
|
16
|
+
* @param rights JMAP rights object
|
|
17
|
+
* @returns MailboxRights or undefined
|
|
18
|
+
*/
|
|
19
|
+
function transformRights(rights) {
|
|
20
|
+
if (!rights) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
mayReadItems: rights.mayReadItems,
|
|
25
|
+
mayAddItems: rights.mayAddItems,
|
|
26
|
+
mayRemoveItems: rights.mayRemoveItems,
|
|
27
|
+
maySetSeen: rights.maySetSeen,
|
|
28
|
+
maySetKeywords: rights.maySetKeywords,
|
|
29
|
+
mayCreateChild: rights.mayCreateChild,
|
|
30
|
+
mayRename: rights.mayRename,
|
|
31
|
+
mayDelete: rights.mayDelete,
|
|
32
|
+
maySubmit: rights.maySubmit,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Transform a JMAP Mailbox object to SimplifiedMailbox DTO.
|
|
37
|
+
* Straightforward property mapping with type safety.
|
|
38
|
+
*
|
|
39
|
+
* @param jmapMailbox JMAP Mailbox object
|
|
40
|
+
* @returns SimplifiedMailbox DTO
|
|
41
|
+
*/
|
|
42
|
+
export function transformMailbox(jmapMailbox) {
|
|
43
|
+
const result = {
|
|
44
|
+
// Core identifiers
|
|
45
|
+
id: jmapMailbox.id,
|
|
46
|
+
name: jmapMailbox.name,
|
|
47
|
+
role: castRole(jmapMailbox.role),
|
|
48
|
+
// Hierarchy
|
|
49
|
+
parentId: jmapMailbox.parentId,
|
|
50
|
+
sortOrder: jmapMailbox.sortOrder,
|
|
51
|
+
// Email counts
|
|
52
|
+
totalEmails: jmapMailbox.totalEmails,
|
|
53
|
+
unreadEmails: jmapMailbox.unreadEmails,
|
|
54
|
+
};
|
|
55
|
+
// Add optional fields only if present
|
|
56
|
+
if (jmapMailbox.totalThreads !== undefined) {
|
|
57
|
+
result.totalThreads = jmapMailbox.totalThreads;
|
|
58
|
+
}
|
|
59
|
+
if (jmapMailbox.unreadThreads !== undefined) {
|
|
60
|
+
result.unreadThreads = jmapMailbox.unreadThreads;
|
|
61
|
+
}
|
|
62
|
+
if (jmapMailbox.myRights !== undefined) {
|
|
63
|
+
result.myRights = transformRights(jmapMailbox.myRights);
|
|
64
|
+
}
|
|
65
|
+
if (jmapMailbox.isSubscribed !== undefined) {
|
|
66
|
+
result.isSubscribed = jmapMailbox.isSubscribed;
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=mailbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../../src/transformers/mailbox.ts"],"names":[],"mappings":"AAqCA;;;;GAIG;AACH,SAAS,QAAQ,CAAC,IAAmB;IACnC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,oEAAoE;IACpE,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IAC7G,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAoB,CAAC,CAAC,CAAC,IAAI,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,MAAqC;IAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAwB;IACvD,MAAM,MAAM,GAAsB;QAChC,mBAAmB;QACnB,EAAE,EAAE,WAAW,CAAC,EAAE;QAClB,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC;QAEhC,YAAY;QACZ,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,SAAS,EAAE,WAAW,CAAC,SAAS;QAEhC,eAAe;QACf,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,YAAY,EAAE,WAAW,CAAC,YAAY;KACvC,CAAC;IAEF,sCAAsC;IACtC,IAAI,WAAW,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,CAAC,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;IACjD,CAAC;IACD,IAAI,WAAW,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,CAAC,aAAa,GAAG,WAAW,CAAC,aAAa,CAAC;IACnD,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,CAAC,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,WAAW,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,CAAC,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;IACjD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|