@awiki/dsh-plugin 0.2.4 → 0.3.0-rc.1
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/README.md +131 -22
- package/README.zh.md +110 -20
- package/THIRD_PARTY_NOTICES.md +8 -1
- package/cordis.patch.yml +5 -0
- package/lib/client.js +12534 -2647
- package/lib/client.js.map +1 -1
- package/lib/index.js +2431 -92
- package/lib/model-proxy-contract.js +96 -0
- package/lib/provider.js +4 -1
- package/lib/sdk-adapter-DLhLrLI6.mjs +886 -0
- package/lib/typert.host.js +1269 -534
- package/lib/typert.remote-client.d.ts +47 -1
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +1254 -141
- package/lib/types/attachment-cache.d.ts +28 -0
- package/lib/types/attachment-cache.d.ts.map +1 -0
- package/lib/types/attachment-cache.js +194 -0
- package/lib/types/attachment-cache.js.map +1 -0
- package/lib/types/client/AwikiGroupDetails.d.ts +16 -0
- package/lib/types/client/AwikiGroupDetails.d.ts.map +1 -0
- package/lib/types/client/AwikiGroupDetails.js +108 -0
- package/lib/types/client/AwikiGroupDetails.js.map +1 -0
- package/lib/types/client/AwikiIdentityAccess.d.ts +21 -0
- package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -0
- package/lib/types/client/AwikiIdentityAccess.js +148 -0
- package/lib/types/client/AwikiIdentityAccess.js.map +1 -0
- package/lib/types/client/AwikiIdentityPage.d.ts +11 -0
- package/lib/types/client/AwikiIdentityPage.d.ts.map +1 -0
- package/lib/types/client/AwikiIdentityPage.js +8 -0
- package/lib/types/client/AwikiIdentityPage.js.map +1 -0
- package/lib/types/client/AwikiMail.d.ts +15 -0
- package/lib/types/client/AwikiMail.d.ts.map +1 -0
- package/lib/types/client/AwikiMail.js +380 -0
- package/lib/types/client/AwikiMail.js.map +1 -0
- package/lib/types/client/AwikiOnboarding.d.ts +22 -0
- package/lib/types/client/AwikiOnboarding.d.ts.map +1 -0
- package/lib/types/client/AwikiOnboarding.js +104 -0
- package/lib/types/client/AwikiOnboarding.js.map +1 -0
- package/lib/types/client/AwikiOverlay.d.ts +10 -0
- package/lib/types/client/AwikiOverlay.d.ts.map +1 -1
- package/lib/types/client/AwikiOverlay.js +370 -127
- package/lib/types/client/AwikiOverlay.js.map +1 -1
- package/lib/types/client/AwikiProfileCard.d.ts +9 -0
- package/lib/types/client/AwikiProfileCard.d.ts.map +1 -0
- package/lib/types/client/AwikiProfileCard.js +90 -0
- package/lib/types/client/AwikiProfileCard.js.map +1 -0
- package/lib/types/client/AwikiRecoveryForm.d.ts +24 -0
- package/lib/types/client/AwikiRecoveryForm.d.ts.map +1 -0
- package/lib/types/client/AwikiRecoveryForm.js +148 -0
- package/lib/types/client/AwikiRecoveryForm.js.map +1 -0
- package/lib/types/client/AwikiSettingsSection.d.ts +18 -4
- package/lib/types/client/AwikiSettingsSection.d.ts.map +1 -1
- package/lib/types/client/AwikiSettingsSection.js +277 -23
- package/lib/types/client/AwikiSettingsSection.js.map +1 -1
- package/lib/types/client/MentionText.d.ts +7 -0
- package/lib/types/client/MentionText.d.ts.map +1 -0
- package/lib/types/client/MentionText.js +10 -0
- package/lib/types/client/MentionText.js.map +1 -0
- package/lib/types/client/RechargeComingSoonDialog.d.ts +11 -0
- package/lib/types/client/RechargeComingSoonDialog.d.ts.map +1 -0
- package/lib/types/client/RechargeComingSoonDialog.js +8 -0
- package/lib/types/client/RechargeComingSoonDialog.js.map +1 -0
- package/lib/types/client/controller.d.ts +174 -4
- package/lib/types/client/controller.d.ts.map +1 -1
- package/lib/types/client/controller.js +975 -79
- package/lib/types/client/controller.js.map +1 -1
- package/lib/types/client/image-cache.d.ts +20 -0
- package/lib/types/client/image-cache.d.ts.map +1 -0
- package/lib/types/client/image-cache.js +177 -0
- package/lib/types/client/image-cache.js.map +1 -0
- package/lib/types/client/index.d.ts +2 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +102 -42
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/mail-list-cache.d.ts +15 -0
- package/lib/types/client/mail-list-cache.d.ts.map +1 -0
- package/lib/types/client/mail-list-cache.js +212 -0
- package/lib/types/client/mail-list-cache.js.map +1 -0
- package/lib/types/client/mentions.d.ts +51 -0
- package/lib/types/client/mentions.d.ts.map +1 -0
- package/lib/types/client/mentions.js +165 -0
- package/lib/types/client/mentions.js.map +1 -0
- package/lib/types/client/model-availability-controller.d.ts +27 -0
- package/lib/types/client/model-availability-controller.d.ts.map +1 -0
- package/lib/types/client/model-availability-controller.js +111 -0
- package/lib/types/client/model-availability-controller.js.map +1 -0
- package/lib/types/client/model-proxy-controller.d.ts +45 -0
- package/lib/types/client/model-proxy-controller.d.ts.map +1 -0
- package/lib/types/client/model-proxy-controller.js +306 -0
- package/lib/types/client/model-proxy-controller.js.map +1 -0
- package/lib/types/client/recharge-availability.d.ts +6 -0
- package/lib/types/client/recharge-availability.d.ts.map +1 -0
- package/lib/types/client/recharge-availability.js +6 -0
- package/lib/types/client/recharge-availability.js.map +1 -0
- package/lib/types/client/settings-locales.d.ts +1 -1
- package/lib/types/client/settings-locales.d.ts.map +1 -1
- package/lib/types/client/settings-locales.js +186 -8
- package/lib/types/client/settings-locales.js.map +1 -1
- package/lib/types/client/slots.d.ts +34 -2
- package/lib/types/client/slots.d.ts.map +1 -1
- package/lib/types/index.d.ts +95 -7
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +968 -37
- package/lib/types/index.js.map +1 -1
- package/lib/types/listener-state.d.ts +23 -0
- package/lib/types/listener-state.d.ts.map +1 -0
- package/lib/types/listener-state.js +124 -0
- package/lib/types/listener-state.js.map +1 -0
- package/lib/types/listener.d.ts +96 -0
- package/lib/types/listener.d.ts.map +1 -0
- package/lib/types/listener.js +575 -0
- package/lib/types/listener.js.map +1 -0
- package/lib/types/mail.d.ts +8 -0
- package/lib/types/mail.d.ts.map +1 -0
- package/lib/types/mail.js +75 -0
- package/lib/types/mail.js.map +1 -0
- package/lib/types/model-proxy-contract.d.ts +67 -0
- package/lib/types/model-proxy-contract.d.ts.map +1 -0
- package/lib/types/model-proxy-contract.js +135 -0
- package/lib/types/model-proxy-contract.js.map +1 -0
- package/lib/types/provider-api.d.ts +106 -2
- package/lib/types/provider-api.d.ts.map +1 -1
- package/lib/types/provider.d.ts.map +1 -1
- package/lib/types/provider.js +3 -0
- package/lib/types/provider.js.map +1 -1
- package/lib/types/sdk-adapter.d.ts +43 -2
- package/lib/types/sdk-adapter.d.ts.map +1 -1
- package/lib/types/sdk-adapter.js +622 -24
- package/lib/types/sdk-adapter.js.map +1 -1
- package/lib/types/sent-mail-store.d.ts +22 -0
- package/lib/types/sent-mail-store.d.ts.map +1 -0
- package/lib/types/sent-mail-store.js +246 -0
- package/lib/types/sent-mail-store.js.map +1 -0
- package/lib/types/tools.d.ts +10 -0
- package/lib/types/tools.d.ts.map +1 -1
- package/lib/types/tools.js +98 -0
- package/lib/types/tools.js.map +1 -1
- package/lib/types/types.d.ts +254 -2
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js.map +1 -1
- package/package.json +31 -17
- package/lib/sdk-adapter-DK6RqV-c.mjs +0 -355
package/lib/types/sdk-adapter.js
CHANGED
|
@@ -14,6 +14,8 @@ const RUST_FAILURE_CODES = {
|
|
|
14
14
|
handle_unavailable: 'handle-unavailable',
|
|
15
15
|
not_found: 'not-found',
|
|
16
16
|
permission_denied: 'forbidden',
|
|
17
|
+
group_not_member: 'group-membership-required',
|
|
18
|
+
group_identity_stale: 'group-identity-stale',
|
|
17
19
|
auth_revoked: 'forbidden',
|
|
18
20
|
conflict: 'conflict',
|
|
19
21
|
join_required: 'handle-unavailable',
|
|
@@ -37,7 +39,7 @@ export class AwikiSdkError extends Error {
|
|
|
37
39
|
function fail(code = 'remote') {
|
|
38
40
|
throw new AwikiSdkError(code);
|
|
39
41
|
}
|
|
40
|
-
function mapError(error) {
|
|
42
|
+
function mapError(error, ambiguousSend = false) {
|
|
41
43
|
if (error instanceof AwikiSdkError)
|
|
42
44
|
throw error;
|
|
43
45
|
let code = 'remote';
|
|
@@ -45,7 +47,9 @@ function mapError(error) {
|
|
|
45
47
|
if (typeof error === 'object' && error !== null) {
|
|
46
48
|
const value = error;
|
|
47
49
|
if (value.name === 'ImCoreNodeError' && typeof value.code === 'string') {
|
|
48
|
-
code =
|
|
50
|
+
code = ambiguousSend && (value.code === 'timeout' || value.code === 'transport_unavailable')
|
|
51
|
+
? 'delivery-unknown'
|
|
52
|
+
: RUST_FAILURE_CODES[value.code] ?? 'remote';
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -71,6 +75,143 @@ function required(value) {
|
|
|
71
75
|
fail();
|
|
72
76
|
return value;
|
|
73
77
|
}
|
|
78
|
+
/** Recover the browser's exact optimistic message identity without widening the Remote schema. */
|
|
79
|
+
function browserMessageId(idempotencyKey) {
|
|
80
|
+
return /^msg-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.test(idempotencyKey)
|
|
81
|
+
? idempotencyKey
|
|
82
|
+
: undefined;
|
|
83
|
+
}
|
|
84
|
+
function remoteString(value, maxBytes) {
|
|
85
|
+
if (typeof value !== 'string' || value.includes('\0') || Buffer.byteLength(value, 'utf8') > maxBytes)
|
|
86
|
+
fail();
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
function remoteOptionalString(value, maxBytes) {
|
|
90
|
+
return value === undefined ? undefined : remoteString(value, maxBytes);
|
|
91
|
+
}
|
|
92
|
+
function mailToken(value, maxCharacters) {
|
|
93
|
+
if (typeof value !== 'string'
|
|
94
|
+
|| value.length === 0
|
|
95
|
+
|| value.trim() !== value
|
|
96
|
+
|| Array.from(value).length > maxCharacters
|
|
97
|
+
|| /[\u0000-\u001f\u007f-\u009f]/u.test(value))
|
|
98
|
+
fail();
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
function mailAddress(value) {
|
|
102
|
+
if (typeof value !== 'string')
|
|
103
|
+
fail();
|
|
104
|
+
const length = Array.from(value).length;
|
|
105
|
+
if (length < 3
|
|
106
|
+
|| length > 320
|
|
107
|
+
|| !value.includes('@')
|
|
108
|
+
|| /[\s\u0000-\u001f\u007f-\u009f]/u.test(value))
|
|
109
|
+
fail();
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
function mailAddresses(value) {
|
|
113
|
+
if (!Array.isArray(value) || value.length > 100)
|
|
114
|
+
fail();
|
|
115
|
+
return value.map(mailAddress);
|
|
116
|
+
}
|
|
117
|
+
function mailTimestamp(value) {
|
|
118
|
+
if (value === undefined)
|
|
119
|
+
return undefined;
|
|
120
|
+
const copied = remoteString(value, 64);
|
|
121
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/u.test(copied)
|
|
122
|
+
|| !Number.isFinite(Date.parse(copied)))
|
|
123
|
+
fail();
|
|
124
|
+
return copied;
|
|
125
|
+
}
|
|
126
|
+
function uint32(value) {
|
|
127
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > 0xffff_ffff)
|
|
128
|
+
fail();
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
function recoveryE2eeGroupCount(impact) {
|
|
132
|
+
if (typeof impact !== 'object' || impact === null)
|
|
133
|
+
fail();
|
|
134
|
+
const value = impact;
|
|
135
|
+
return uint32(value.unsupportedE2eeGroupCount !== undefined
|
|
136
|
+
? value.unsupportedE2eeGroupCount
|
|
137
|
+
: value.unsupportedE2EeGroupCount);
|
|
138
|
+
}
|
|
139
|
+
function boolean(value) {
|
|
140
|
+
if (typeof value !== 'boolean')
|
|
141
|
+
fail();
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
function mailSummary(value) {
|
|
145
|
+
const receivedAt = mailTimestamp(value.receivedAt);
|
|
146
|
+
const sentAt = mailTimestamp(value.sentAt);
|
|
147
|
+
const folder = value.folder === undefined ? undefined : mailToken(value.folder, 64);
|
|
148
|
+
const preview = remoteOptionalString(value.preview, 4_096);
|
|
149
|
+
const attachmentCount = value.attachmentCount === undefined ? undefined : uint32(value.attachmentCount);
|
|
150
|
+
return {
|
|
151
|
+
id: mailToken(value.id, 2_048),
|
|
152
|
+
...folder === undefined ? {} : { folder },
|
|
153
|
+
from: mailAddresses(value.from),
|
|
154
|
+
to: mailAddresses(value.to),
|
|
155
|
+
cc: mailAddresses(value.cc),
|
|
156
|
+
subject: remoteString(value.subject, 1_024),
|
|
157
|
+
subjectTruncated: boolean(value.subjectTruncated),
|
|
158
|
+
...preview === undefined ? {} : { preview },
|
|
159
|
+
previewTruncated: boolean(value.previewTruncated),
|
|
160
|
+
...receivedAt === undefined ? {} : { receivedAt },
|
|
161
|
+
...sentAt === undefined ? {} : { sentAt },
|
|
162
|
+
unread: boolean(value.unread),
|
|
163
|
+
hasAttachments: boolean(value.hasAttachments),
|
|
164
|
+
...attachmentCount === undefined ? {} : { attachmentCount },
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function mailAttachment(value) {
|
|
168
|
+
const fileName = remoteOptionalString(value.fileName, 512);
|
|
169
|
+
const contentType = remoteOptionalString(value.contentType, 255);
|
|
170
|
+
const sizeBytes = value.sizeBytes === undefined ? undefined : remoteString(value.sizeBytes, 20);
|
|
171
|
+
if (sizeBytes !== undefined && !/^(?:0|[1-9]\d*)$/u.test(sizeBytes))
|
|
172
|
+
fail();
|
|
173
|
+
return {
|
|
174
|
+
index: uint32(value.index),
|
|
175
|
+
...fileName === undefined ? {} : { fileName },
|
|
176
|
+
...contentType === undefined ? {} : { contentType },
|
|
177
|
+
...sizeBytes === undefined ? {} : { sizeBytes },
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function mailAccount(value) {
|
|
181
|
+
const mailboxAddress = value.mailboxAddress === undefined ? undefined : mailAddress(value.mailboxAddress);
|
|
182
|
+
const displayName = remoteOptionalString(value.displayName, 512);
|
|
183
|
+
const status = remoteOptionalString(value.status, 128);
|
|
184
|
+
return {
|
|
185
|
+
...mailboxAddress === undefined ? {} : { mailboxAddress },
|
|
186
|
+
...displayName === undefined ? {} : { displayName },
|
|
187
|
+
...status === undefined ? {} : { status },
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function mailInbox(value) {
|
|
191
|
+
if (!Array.isArray(value.items) || value.items.length > 100)
|
|
192
|
+
fail();
|
|
193
|
+
const hasMore = boolean(value.hasMore);
|
|
194
|
+
const nextOffset = value.nextOffset === undefined ? undefined : uint32(value.nextOffset);
|
|
195
|
+
if ((hasMore && nextOffset === undefined) || (!hasMore && nextOffset !== undefined))
|
|
196
|
+
fail();
|
|
197
|
+
return {
|
|
198
|
+
items: value.items.map(mailSummary),
|
|
199
|
+
...nextOffset === undefined ? {} : { nextOffset },
|
|
200
|
+
hasMore,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function mailMessage(value) {
|
|
204
|
+
if (!Array.isArray(value.attachments) || value.attachments.length > 100)
|
|
205
|
+
fail();
|
|
206
|
+
const bodyText = remoteOptionalString(value.bodyText, 65_536);
|
|
207
|
+
return {
|
|
208
|
+
summary: mailSummary(value.summary),
|
|
209
|
+
...bodyText === undefined ? {} : { bodyText },
|
|
210
|
+
bodyTruncated: boolean(value.bodyTruncated),
|
|
211
|
+
hasHtmlBody: boolean(value.hasHtmlBody),
|
|
212
|
+
attachments: value.attachments.map(mailAttachment),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
74
215
|
function sha256(value) {
|
|
75
216
|
const provided = value.sha256Hex?.toLowerCase();
|
|
76
217
|
if (provided !== undefined && /^[a-f0-9]{64}$/u.test(provided))
|
|
@@ -93,6 +234,67 @@ function identity(value) {
|
|
|
93
234
|
registeredAt: safeInteger(value.registeredAtMs),
|
|
94
235
|
};
|
|
95
236
|
}
|
|
237
|
+
function profile(value) {
|
|
238
|
+
return {
|
|
239
|
+
did: required(value.did),
|
|
240
|
+
...value.handle === undefined ? {} : { handle: value.handle },
|
|
241
|
+
displayName: value.displayName?.trim() ?? '',
|
|
242
|
+
bio: value.bio ?? '',
|
|
243
|
+
tags: [...value.tags],
|
|
244
|
+
...value.updatedAt === undefined ? {} : { updatedAt: value.updatedAt },
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function mentionPayload(value) {
|
|
248
|
+
if (value.content.kind !== 'payload' || value.content.payloadJson === undefined)
|
|
249
|
+
return undefined;
|
|
250
|
+
let parsed;
|
|
251
|
+
try {
|
|
252
|
+
parsed = JSON.parse(value.content.payloadJson);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return undefined;
|
|
256
|
+
}
|
|
257
|
+
if (typeof parsed !== 'object' || parsed === null || !('text' in parsed) || typeof parsed.text !== 'string')
|
|
258
|
+
return undefined;
|
|
259
|
+
const text = parsed.text;
|
|
260
|
+
if (!('mentions' in parsed) || !Array.isArray(parsed.mentions))
|
|
261
|
+
return { text };
|
|
262
|
+
const length = Array.from(text).length;
|
|
263
|
+
const mentions = [];
|
|
264
|
+
for (const raw of parsed.mentions) {
|
|
265
|
+
if (typeof raw !== 'object' || raw === null
|
|
266
|
+
|| !('id' in raw) || typeof raw.id !== 'string' || raw.id.trim() === ''
|
|
267
|
+
|| !('range' in raw) || typeof raw.range !== 'object' || raw.range === null
|
|
268
|
+
|| !('start' in raw.range) || !Number.isSafeInteger(raw.range.start)
|
|
269
|
+
|| !('end' in raw.range) || !Number.isSafeInteger(raw.range.end)
|
|
270
|
+
|| !('unit' in raw.range) || raw.range.unit !== 'unicode_code_point'
|
|
271
|
+
|| raw.range.start < 0
|
|
272
|
+
|| raw.range.end <= raw.range.start
|
|
273
|
+
|| raw.range.end > length
|
|
274
|
+
|| !('target' in raw) || typeof raw.target !== 'object' || raw.target === null
|
|
275
|
+
|| !('kind' in raw.target) || raw.target.kind !== 'human'
|
|
276
|
+
|| !('did' in raw.target) || typeof raw.target.did !== 'string' || !raw.target.did.startsWith('did:')) {
|
|
277
|
+
return { text };
|
|
278
|
+
}
|
|
279
|
+
const displayName = 'display_name' in raw.target && typeof raw.target.display_name === 'string'
|
|
280
|
+
? raw.target.display_name
|
|
281
|
+
: undefined;
|
|
282
|
+
mentions.push({
|
|
283
|
+
id: raw.id,
|
|
284
|
+
start: raw.range.start,
|
|
285
|
+
end: raw.range.end,
|
|
286
|
+
did: raw.target.did,
|
|
287
|
+
...displayName === undefined ? {} : { displayName },
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
const ordered = [...mentions].sort((left, right) => left.start - right.start || left.end - right.end);
|
|
291
|
+
if (ordered.some((item, index) => index > 0 && item.start < ordered[index - 1].end))
|
|
292
|
+
return { text };
|
|
293
|
+
const characters = Array.from(text);
|
|
294
|
+
if (ordered.some(item => !characters.slice(item.start, item.end).join('').startsWith('@')))
|
|
295
|
+
return { text };
|
|
296
|
+
return ordered.length === 0 ? { text } : { text, mentions: ordered };
|
|
297
|
+
}
|
|
96
298
|
/** Copy one native attachment and normalize its decimal/digest encodings. */
|
|
97
299
|
function attachment(value) {
|
|
98
300
|
return {
|
|
@@ -112,9 +314,16 @@ function preview(value) {
|
|
|
112
314
|
const fileName = value.content.attachment?.fileName;
|
|
113
315
|
return fileName === undefined ? undefined : `[附件] ${fileName}`;
|
|
114
316
|
}
|
|
317
|
+
case 'payload': return mentionPayload(value)?.text;
|
|
115
318
|
default: return undefined;
|
|
116
319
|
}
|
|
117
320
|
}
|
|
321
|
+
/** Provider-only protocol events are not part of the browser's text/attachment history contract. */
|
|
322
|
+
function displayableMessage(value) {
|
|
323
|
+
return value.content.kind === 'text'
|
|
324
|
+
|| value.content.kind === 'attachment'
|
|
325
|
+
|| mentionPayload(value) !== undefined;
|
|
326
|
+
}
|
|
118
327
|
/** Copy one native page and brand its opaque cursor for the Host API. */
|
|
119
328
|
function page(value, copy) {
|
|
120
329
|
return {
|
|
@@ -151,17 +360,77 @@ export class RustSdkAdapter {
|
|
|
151
360
|
client;
|
|
152
361
|
attachmentConversations = new Map();
|
|
153
362
|
disposal;
|
|
363
|
+
listener;
|
|
154
364
|
constructor(client) {
|
|
155
365
|
this.client = Promise.resolve(client);
|
|
366
|
+
this.listener = {
|
|
367
|
+
syncNow: reason => this.listenerSyncNow(reason),
|
|
368
|
+
startRealtime: () => this.listenerStartRealtime(),
|
|
369
|
+
listConversations: request => this.listenerConversations(request),
|
|
370
|
+
getHistory: request => this.listenerHistory(request),
|
|
371
|
+
markConversationRead: conversationId => this.markConversationRead(conversationId),
|
|
372
|
+
sendText: request => this.sendText(request),
|
|
373
|
+
};
|
|
156
374
|
}
|
|
157
|
-
async run(operation) {
|
|
375
|
+
async run(operation, ambiguousSend = false) {
|
|
158
376
|
try {
|
|
159
377
|
return await operation(await this.client);
|
|
160
378
|
}
|
|
161
379
|
catch (error) {
|
|
162
|
-
mapError(error);
|
|
380
|
+
mapError(error, ambiguousSend);
|
|
163
381
|
}
|
|
164
382
|
}
|
|
383
|
+
async displayableMessages(client, values) {
|
|
384
|
+
const messages = values.filter(displayableMessage);
|
|
385
|
+
const peers = [...new Set(messages
|
|
386
|
+
.filter(message => (message.conversationKind === 'group'
|
|
387
|
+
&& !message.outgoing
|
|
388
|
+
&& message.senderHandle === undefined
|
|
389
|
+
&& message.senderDisplayName === undefined))
|
|
390
|
+
.map(message => message.senderDid))];
|
|
391
|
+
if (peers.length === 0)
|
|
392
|
+
return [...messages];
|
|
393
|
+
const profiles = await client.hydrateDisplayProfiles({ peers });
|
|
394
|
+
const byDid = new Map();
|
|
395
|
+
for (const profile of profiles) {
|
|
396
|
+
if (profile.did !== undefined)
|
|
397
|
+
byDid.set(profile.did, profile);
|
|
398
|
+
}
|
|
399
|
+
return messages.map((message) => {
|
|
400
|
+
const profile = byDid.get(message.senderDid);
|
|
401
|
+
if (profile === undefined)
|
|
402
|
+
return message;
|
|
403
|
+
return {
|
|
404
|
+
...message,
|
|
405
|
+
...profile.handle === undefined ? {} : { senderHandle: profile.handle },
|
|
406
|
+
...profile.displayName === undefined ? {} : { senderDisplayName: profile.displayName },
|
|
407
|
+
};
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Join the persisted Core peer-profile projection onto direct roster rows.
|
|
412
|
+
* The conversation registry intentionally keeps routing identifiers separate
|
|
413
|
+
* from display metadata, so a bare roster row may otherwise regress to a Handle.
|
|
414
|
+
*/
|
|
415
|
+
async displayableConversations(client, values) {
|
|
416
|
+
const peers = [...new Set(values
|
|
417
|
+
.filter((conversation) => (conversation.kind === 'direct' && conversation.peerDid !== undefined))
|
|
418
|
+
.map(conversation => conversation.peerDid))];
|
|
419
|
+
const profiles = peers.length === 0 ? [] : await client.hydrateDisplayProfiles({ peers });
|
|
420
|
+
const byPeer = new Map();
|
|
421
|
+
for (const [index, profile] of profiles.entries()) {
|
|
422
|
+
const requested = peers[index];
|
|
423
|
+
if (requested !== undefined)
|
|
424
|
+
byPeer.set(requested, profile);
|
|
425
|
+
if (profile.did !== undefined)
|
|
426
|
+
byPeer.set(profile.did, profile);
|
|
427
|
+
if (profile.handle !== undefined)
|
|
428
|
+
byPeer.set(profile.handle, profile);
|
|
429
|
+
}
|
|
430
|
+
return values.map(value => this.conversation(value, value.kind === 'direct'
|
|
431
|
+
? byPeer.get(value.peerDid ?? '') ?? byPeer.get(value.peerHandle ?? '')
|
|
432
|
+
: undefined));
|
|
433
|
+
}
|
|
165
434
|
message(value) {
|
|
166
435
|
const sentAt = value.sentAt === undefined ? fail() : timestamp(value.sentAt);
|
|
167
436
|
const common = {
|
|
@@ -193,12 +462,29 @@ export class RustSdkAdapter {
|
|
|
193
462
|
},
|
|
194
463
|
};
|
|
195
464
|
}
|
|
465
|
+
case 'payload': {
|
|
466
|
+
const parsed = mentionPayload(value);
|
|
467
|
+
if (parsed === undefined)
|
|
468
|
+
fail();
|
|
469
|
+
return {
|
|
470
|
+
...common,
|
|
471
|
+
content: {
|
|
472
|
+
kind: 'text',
|
|
473
|
+
text: parsed.text,
|
|
474
|
+
...parsed.mentions === undefined ? {} : { mentions: parsed.mentions },
|
|
475
|
+
},
|
|
476
|
+
};
|
|
477
|
+
}
|
|
196
478
|
default: fail();
|
|
197
479
|
}
|
|
198
480
|
}
|
|
199
|
-
conversation(value) {
|
|
481
|
+
conversation(value, profile) {
|
|
200
482
|
const id = required(value.id);
|
|
201
|
-
const
|
|
483
|
+
const displayName = profile?.displayName?.trim();
|
|
484
|
+
const profileHandle = profile?.handle?.trim();
|
|
485
|
+
const title = displayName === undefined || displayName.length === 0
|
|
486
|
+
? value.title?.trim()
|
|
487
|
+
: displayName;
|
|
202
488
|
const lastMessagePreview = preview(value.lastMessage);
|
|
203
489
|
const common = {
|
|
204
490
|
id,
|
|
@@ -209,14 +495,17 @@ export class RustSdkAdapter {
|
|
|
209
495
|
...value.lastMessageAt === undefined ? {} : { lastMessageAt: timestamp(value.lastMessageAt) },
|
|
210
496
|
...lastMessagePreview === undefined ? {} : { lastMessagePreview },
|
|
211
497
|
};
|
|
212
|
-
if (value.lastMessage !== undefined)
|
|
498
|
+
if (value.lastMessage !== undefined && displayableMessage(value.lastMessage))
|
|
213
499
|
this.message(value.lastMessage);
|
|
214
500
|
switch (value.kind) {
|
|
215
501
|
case 'direct': return {
|
|
216
502
|
kind: 'direct',
|
|
217
503
|
...common,
|
|
218
|
-
peerDid: required(value.peerDid),
|
|
219
|
-
...
|
|
504
|
+
peerDid: required(profile?.did ?? value.peerDid),
|
|
505
|
+
...profileHandle === undefined && value.peerHandle === undefined
|
|
506
|
+
? {}
|
|
507
|
+
: { peerHandle: required(profileHandle ?? value.peerHandle) },
|
|
508
|
+
...displayName === undefined || displayName.length === 0 ? {} : { displayName },
|
|
220
509
|
};
|
|
221
510
|
case 'group': return {
|
|
222
511
|
kind: 'group',
|
|
@@ -226,6 +515,108 @@ export class RustSdkAdapter {
|
|
|
226
515
|
default: fail();
|
|
227
516
|
}
|
|
228
517
|
}
|
|
518
|
+
createdGroup(value) {
|
|
519
|
+
return {
|
|
520
|
+
kind: 'group',
|
|
521
|
+
id: required(value.conversationId),
|
|
522
|
+
groupDid: required(value.did),
|
|
523
|
+
title: required(value.title),
|
|
524
|
+
unreadCount: 0,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
groupSnapshot(value) {
|
|
528
|
+
return {
|
|
529
|
+
groupDid: required(value.did),
|
|
530
|
+
conversationId: required(value.conversationId),
|
|
531
|
+
title: required(value.title),
|
|
532
|
+
...value.description === undefined ? {} : { description: value.description },
|
|
533
|
+
...value.myRole === undefined ? {} : { myRole: value.myRole },
|
|
534
|
+
...value.membershipStatus === undefined ? {} : { membershipStatus: value.membershipStatus },
|
|
535
|
+
...value.memberCount === undefined ? {} : { memberCount: value.memberCount },
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
groupMember(value) {
|
|
539
|
+
return {
|
|
540
|
+
did: required(value.did),
|
|
541
|
+
...value.handle === undefined ? {} : { handle: value.handle },
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
groupMemberRecord(value, profile) {
|
|
545
|
+
return {
|
|
546
|
+
...value.membershipId === undefined ? {} : { membershipId: value.membershipId },
|
|
547
|
+
...value.peerPersonaId === undefined ? {} : { peerPersonaId: value.peerPersonaId },
|
|
548
|
+
...value.did === undefined ? {} : { did: value.did },
|
|
549
|
+
...value.credentialDid === undefined ? {} : { credentialDid: value.credentialDid },
|
|
550
|
+
...value.handle === undefined ? {} : { handle: value.handle },
|
|
551
|
+
...profile?.displayName === undefined ? {} : { displayName: profile.displayName },
|
|
552
|
+
...value.role === undefined ? {} : { role: value.role },
|
|
553
|
+
...value.status === undefined ? {} : { status: value.status },
|
|
554
|
+
...value.joinedAt === undefined ? {} : { joinedAt: value.joinedAt },
|
|
555
|
+
...value.subjectType === undefined ? {} : { subjectType: value.subjectType },
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
listenerConversation(value) {
|
|
559
|
+
const common = {
|
|
560
|
+
id: required(value.id),
|
|
561
|
+
unreadCount: value.unreadCount,
|
|
562
|
+
...value.lastMessageAt === undefined ? {} : { lastMessageAt: timestamp(value.lastMessageAt) },
|
|
563
|
+
};
|
|
564
|
+
if (value.kind === 'direct') {
|
|
565
|
+
return {
|
|
566
|
+
kind: 'direct',
|
|
567
|
+
...common,
|
|
568
|
+
peerDid: required(value.peerDid),
|
|
569
|
+
...value.peerHandle === undefined ? {} : { peerHandle: value.peerHandle },
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
return { kind: 'group', ...common };
|
|
573
|
+
}
|
|
574
|
+
listenerMessage(value) {
|
|
575
|
+
const sentAt = value.sentAt === undefined ? fail() : timestamp(value.sentAt);
|
|
576
|
+
const common = {
|
|
577
|
+
id: required(value.id),
|
|
578
|
+
conversationId: required(value.conversationId),
|
|
579
|
+
conversationKind: value.conversationKind,
|
|
580
|
+
senderDid: required(value.senderDid),
|
|
581
|
+
sentAt,
|
|
582
|
+
outgoing: value.outgoing,
|
|
583
|
+
};
|
|
584
|
+
return value.content.kind === 'text' && value.content.text !== undefined
|
|
585
|
+
? { ...common, content: { kind: 'text', text: required(value.content.text) } }
|
|
586
|
+
: { ...common, content: { kind: 'ignored' } };
|
|
587
|
+
}
|
|
588
|
+
listenerSyncNow(reason) {
|
|
589
|
+
return this.run(async (client) => {
|
|
590
|
+
const result = await client.syncNow({ reason });
|
|
591
|
+
if (result.status === 'idle' || result.status === 'changed')
|
|
592
|
+
return;
|
|
593
|
+
if (result.status === 'auth_revoked')
|
|
594
|
+
fail('forbidden');
|
|
595
|
+
fail('network');
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
listenerStartRealtime() {
|
|
599
|
+
return this.run(async (client) => {
|
|
600
|
+
const session = await client.startRealtime();
|
|
601
|
+
return {
|
|
602
|
+
nextEvent: () => this.run(() => session.nextEvent()),
|
|
603
|
+
stop: () => this.run(() => session.stop()),
|
|
604
|
+
};
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
listenerConversations(request) {
|
|
608
|
+
return this.run(async (client) => page(await client.listConversations(request), value => this.listenerConversation(value)));
|
|
609
|
+
}
|
|
610
|
+
listenerHistory(request) {
|
|
611
|
+
return this.run(async (client) => {
|
|
612
|
+
const history = await client.getHistory({
|
|
613
|
+
conversationId: String(request.conversationId),
|
|
614
|
+
...request.cursor === undefined ? {} : { cursor: String(request.cursor) },
|
|
615
|
+
...request.limit === undefined ? {} : { limit: request.limit },
|
|
616
|
+
});
|
|
617
|
+
return page({ ...history, items: [...history.items].reverse() }, value => this.listenerMessage(value));
|
|
618
|
+
});
|
|
619
|
+
}
|
|
229
620
|
async conversationId(client, target) {
|
|
230
621
|
if (target.kind === 'direct')
|
|
231
622
|
return required((await client.resolvePeer(target.peer)).conversationId);
|
|
@@ -270,6 +661,59 @@ export class RustSdkAdapter {
|
|
|
270
661
|
updateDisplayName(request) {
|
|
271
662
|
return this.run(async (client) => identity(await client.updateDisplayName(request.displayName)));
|
|
272
663
|
}
|
|
664
|
+
getProfile() {
|
|
665
|
+
return this.run(async (client) => profile(await client.getProfile()));
|
|
666
|
+
}
|
|
667
|
+
updateProfile(request) {
|
|
668
|
+
return this.run(async (client) => profile(await client.updateProfile({
|
|
669
|
+
displayName: request.displayName,
|
|
670
|
+
bio: request.bio,
|
|
671
|
+
tags: [...request.tags],
|
|
672
|
+
})));
|
|
673
|
+
}
|
|
674
|
+
recoveryProgress(value) {
|
|
675
|
+
return {
|
|
676
|
+
operationId: required(value.operationId),
|
|
677
|
+
fullHandle: required(value.fullHandle),
|
|
678
|
+
...value.previousDid === undefined ? {} : { previousDid: value.previousDid },
|
|
679
|
+
currentDid: required(value.currentDid),
|
|
680
|
+
phase: value.phase,
|
|
681
|
+
...value.failureCode === undefined ? {} : { failureCode: value.failureCode },
|
|
682
|
+
retryable: boolean(value.retryable),
|
|
683
|
+
localOrdinaryDataWillMigrate: boolean(value.impact.localOrdinaryDataWillMigrate),
|
|
684
|
+
otherDevicesMustRejoin: boolean(value.impact.otherDevicesMustRejoin),
|
|
685
|
+
unsupportedE2eeGroupCount: recoveryE2eeGroupCount(value.impact),
|
|
686
|
+
unsupportedDidOnlyGroupCount: uint32(value.impact.unsupportedDidOnlyGroupCount),
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
sendRecoveryOtp(request) {
|
|
690
|
+
return this.run(async (client) => {
|
|
691
|
+
const value = await client.requestHandleRecoveryOtp(request);
|
|
692
|
+
return {
|
|
693
|
+
operationId: required(value.operationId),
|
|
694
|
+
fullHandle: required(value.fullHandle),
|
|
695
|
+
retryAfterSeconds: value.retryAfterSeconds,
|
|
696
|
+
retryAt: value.retryAt,
|
|
697
|
+
};
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
prepareRecovery(request) {
|
|
701
|
+
return this.run(async (client) => this.recoveryProgress(await client.prepareHandleRecovery(request)));
|
|
702
|
+
}
|
|
703
|
+
activateRecovery(request) {
|
|
704
|
+
return this.run(async (client) => this.recoveryProgress(await client.activateHandleRecovery(request)));
|
|
705
|
+
}
|
|
706
|
+
getRecoveryStatus(request) {
|
|
707
|
+
return this.run(async (client) => this.recoveryProgress(await client.getHandleRecoveryStatus(request)));
|
|
708
|
+
}
|
|
709
|
+
resumeRecovery(request) {
|
|
710
|
+
return this.run(async (client) => this.recoveryProgress(await client.resumeHandleRecovery(request)));
|
|
711
|
+
}
|
|
712
|
+
discardRecovery(request) {
|
|
713
|
+
return this.run(async (client) => {
|
|
714
|
+
await client.discardHandleRecovery(request);
|
|
715
|
+
});
|
|
716
|
+
}
|
|
273
717
|
resolvePeer(peer) {
|
|
274
718
|
return this.run(async (client) => {
|
|
275
719
|
const value = await client.resolvePeer(peer);
|
|
@@ -281,8 +725,79 @@ export class RustSdkAdapter {
|
|
|
281
725
|
};
|
|
282
726
|
});
|
|
283
727
|
}
|
|
728
|
+
createGroup(name) {
|
|
729
|
+
return this.run(async (client) => this.createdGroup(await client.createGroup({ name })));
|
|
730
|
+
}
|
|
731
|
+
addGroupMember(groupDid, member) {
|
|
732
|
+
return this.run(async (client) => this.groupMember(await client.addGroupMember({
|
|
733
|
+
groupDid: String(groupDid),
|
|
734
|
+
member,
|
|
735
|
+
})));
|
|
736
|
+
}
|
|
737
|
+
getGroup(groupDid) {
|
|
738
|
+
return this.run(async (client) => this.groupSnapshot(await client.getGroup({ groupDid: String(groupDid) })));
|
|
739
|
+
}
|
|
740
|
+
joinGroup(groupDid) {
|
|
741
|
+
return this.run(async (client) => this.groupSnapshot(await client.joinGroup({ groupDid: String(groupDid) })));
|
|
742
|
+
}
|
|
743
|
+
leaveGroup(groupDid) {
|
|
744
|
+
return this.run(client => client.leaveGroup({ groupDid: String(groupDid) }));
|
|
745
|
+
}
|
|
746
|
+
listGroupMembers(request) {
|
|
747
|
+
return this.run(async (client) => {
|
|
748
|
+
const value = await client.listGroupMembers({
|
|
749
|
+
groupDid: String(request.groupDid),
|
|
750
|
+
...request.cursor === undefined ? {} : { cursor: String(request.cursor) },
|
|
751
|
+
...request.limit === undefined ? {} : { limit: request.limit },
|
|
752
|
+
});
|
|
753
|
+
const peers = [...new Set(value.items.flatMap(member => member.did ?? member.handle ?? []))];
|
|
754
|
+
const profiles = peers.length === 0 ? [] : await client.hydrateDisplayProfiles({ peers });
|
|
755
|
+
const byPeer = new Map();
|
|
756
|
+
for (const [index, profile] of profiles.entries()) {
|
|
757
|
+
const requested = peers[index];
|
|
758
|
+
if (requested !== undefined)
|
|
759
|
+
byPeer.set(requested, profile);
|
|
760
|
+
if (profile.did !== undefined)
|
|
761
|
+
byPeer.set(profile.did, profile);
|
|
762
|
+
if (profile.handle !== undefined)
|
|
763
|
+
byPeer.set(profile.handle, profile);
|
|
764
|
+
}
|
|
765
|
+
return {
|
|
766
|
+
items: value.items.map(item => this.groupMemberRecord(item, byPeer.get(item.did ?? '') ?? byPeer.get(item.handle ?? ''))),
|
|
767
|
+
...value.total === undefined ? {} : { total: value.total },
|
|
768
|
+
...value.nextCursor === undefined ? {} : { nextCursor: value.nextCursor },
|
|
769
|
+
hasMore: value.hasMore,
|
|
770
|
+
...value.pageGroup === undefined ? {} : { pageGroup: value.pageGroup },
|
|
771
|
+
...value.groupStateVersion === undefined ? {} : { groupStateVersion: value.groupStateVersion },
|
|
772
|
+
warnings: [...value.warnings],
|
|
773
|
+
};
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
removeGroupMember(groupDid, member) {
|
|
777
|
+
return this.run(async (client) => this.groupMember(await client.removeGroupMember({
|
|
778
|
+
groupDid: String(groupDid),
|
|
779
|
+
member,
|
|
780
|
+
})));
|
|
781
|
+
}
|
|
782
|
+
resumeGroupRebindRecovery() {
|
|
783
|
+
return this.run(async (client) => {
|
|
784
|
+
const value = await client.resumeGroupRebindRecovery(100);
|
|
785
|
+
return {
|
|
786
|
+
processed: uint32(value.processed),
|
|
787
|
+
completed: uint32(value.completed),
|
|
788
|
+
pending: uint32(value.pending),
|
|
789
|
+
blocked: uint32(value.blocked),
|
|
790
|
+
};
|
|
791
|
+
});
|
|
792
|
+
}
|
|
284
793
|
listConversations(request) {
|
|
285
|
-
return this.run(async (client) =>
|
|
794
|
+
return this.run(async (client) => {
|
|
795
|
+
const conversations = await client.listConversations(request);
|
|
796
|
+
return {
|
|
797
|
+
...page(conversations, value => value),
|
|
798
|
+
items: await this.displayableConversations(client, conversations.items),
|
|
799
|
+
};
|
|
800
|
+
});
|
|
286
801
|
}
|
|
287
802
|
getHistory(request) {
|
|
288
803
|
return this.run(async (client) => {
|
|
@@ -293,28 +808,69 @@ export class RustSdkAdapter {
|
|
|
293
808
|
});
|
|
294
809
|
return page(
|
|
295
810
|
// Rust Core pages newest-first; the Host/UI contract is chronological.
|
|
296
|
-
{ ...history, items: [...history.items].reverse() }, value => this.message(value));
|
|
811
|
+
{ ...history, items: await this.displayableMessages(client, [...history.items].reverse()) }, value => this.message(value));
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
getLocalHistory(request) {
|
|
815
|
+
return this.run(async (client) => {
|
|
816
|
+
const history = await client.getLocalConversationTimeline({
|
|
817
|
+
conversationId: String(request.conversationId),
|
|
818
|
+
...request.cursor === undefined ? {} : { cursor: String(request.cursor) },
|
|
819
|
+
...request.limit === undefined ? {} : { limit: request.limit },
|
|
820
|
+
});
|
|
821
|
+
return page(
|
|
822
|
+
// Rust Core local pages are newest-first; the Host/UI contract is chronological.
|
|
823
|
+
{ ...history, items: await this.displayableMessages(client, [...history.items].reverse()) }, value => this.message(value));
|
|
297
824
|
});
|
|
298
825
|
}
|
|
299
826
|
markConversationRead(conversationId) {
|
|
300
827
|
return this.run(async (client) => (await client.markConversationRead(String(conversationId))).updatedCount);
|
|
301
828
|
}
|
|
302
829
|
sendText(request) {
|
|
303
|
-
return this.run(async (client) =>
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
830
|
+
return this.run(async (client) => {
|
|
831
|
+
const clientMessageId = browserMessageId(request.idempotencyKey);
|
|
832
|
+
const conversationId = await this.conversationId(client, request.target);
|
|
833
|
+
if (request.mentions !== undefined && request.mentions.length > 0) {
|
|
834
|
+
return this.message(await client.sendPayload({
|
|
835
|
+
conversationId,
|
|
836
|
+
payloadJson: JSON.stringify({
|
|
837
|
+
text: request.text,
|
|
838
|
+
mentions: request.mentions.map(mention => ({
|
|
839
|
+
id: mention.id,
|
|
840
|
+
range: { start: mention.start, end: mention.end, unit: 'unicode_code_point' },
|
|
841
|
+
target: {
|
|
842
|
+
kind: 'human',
|
|
843
|
+
did: mention.did,
|
|
844
|
+
...mention.displayName === undefined ? {} : { display_name: mention.displayName },
|
|
845
|
+
},
|
|
846
|
+
mention_role: 'addressee',
|
|
847
|
+
})),
|
|
848
|
+
}),
|
|
849
|
+
...clientMessageId === undefined ? {} : { clientMessageId },
|
|
850
|
+
idempotencyKey: request.idempotencyKey,
|
|
851
|
+
}));
|
|
852
|
+
}
|
|
853
|
+
return this.message(await client.sendText({
|
|
854
|
+
conversationId,
|
|
855
|
+
text: request.text,
|
|
856
|
+
...clientMessageId === undefined ? {} : { clientMessageId },
|
|
857
|
+
idempotencyKey: request.idempotencyKey,
|
|
858
|
+
}));
|
|
859
|
+
});
|
|
308
860
|
}
|
|
309
861
|
sendAttachment(request) {
|
|
310
|
-
return this.run(async (client) =>
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
862
|
+
return this.run(async (client) => {
|
|
863
|
+
const clientMessageId = browserMessageId(request.idempotencyKey);
|
|
864
|
+
return this.message(await client.sendAttachment({
|
|
865
|
+
conversationId: await this.conversationId(client, request.target),
|
|
866
|
+
fileName: request.attachment.fileName,
|
|
867
|
+
mimeType: request.attachment.mimeType,
|
|
868
|
+
bytes: request.attachment.bytes,
|
|
869
|
+
...request.caption === undefined ? {} : { caption: request.caption },
|
|
870
|
+
...clientMessageId === undefined ? {} : { clientMessageId },
|
|
871
|
+
idempotencyKey: request.idempotencyKey,
|
|
872
|
+
}));
|
|
873
|
+
});
|
|
318
874
|
}
|
|
319
875
|
downloadAttachment(request) {
|
|
320
876
|
return this.run(async (client) => {
|
|
@@ -329,6 +885,48 @@ export class RustSdkAdapter {
|
|
|
329
885
|
return { attachment: attachment(value.attachment), bytes: Uint8Array.from(value.bytes) };
|
|
330
886
|
});
|
|
331
887
|
}
|
|
888
|
+
getMailAccount() {
|
|
889
|
+
return this.run(async (client) => mailAccount(await client.getMailAccount()));
|
|
890
|
+
}
|
|
891
|
+
listMailInbox(request = {}) {
|
|
892
|
+
return this.run(async (client) => mailInbox(await client.listMailInbox({
|
|
893
|
+
...request.folder === undefined ? {} : { folder: request.folder },
|
|
894
|
+
...request.unreadOnly === undefined ? {} : { unreadOnly: request.unreadOnly },
|
|
895
|
+
...request.limit === undefined ? {} : { limit: request.limit },
|
|
896
|
+
...request.offset === undefined ? {} : { offset: request.offset },
|
|
897
|
+
})));
|
|
898
|
+
}
|
|
899
|
+
readMail(request) {
|
|
900
|
+
return this.run(async (client) => mailMessage(await client.readMail(request.messageId)));
|
|
901
|
+
}
|
|
902
|
+
markMailRead(request) {
|
|
903
|
+
return this.run(async (client) => {
|
|
904
|
+
const value = await client.markMailRead({
|
|
905
|
+
messageIds: [...request.messageIds],
|
|
906
|
+
});
|
|
907
|
+
return { updated: uint32(value.updated) };
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
sendMail(request) {
|
|
911
|
+
return this.run(async (client) => {
|
|
912
|
+
const value = await client.sendMail({
|
|
913
|
+
to: [...request.to],
|
|
914
|
+
...request.cc === undefined ? {} : { cc: [...request.cc] },
|
|
915
|
+
subject: request.subject,
|
|
916
|
+
bodyText: request.bodyText,
|
|
917
|
+
});
|
|
918
|
+
if (!Array.isArray(value.warnings) || value.warnings.length > 100)
|
|
919
|
+
fail();
|
|
920
|
+
const messageId = value.messageId === undefined
|
|
921
|
+
? undefined
|
|
922
|
+
: mailToken(value.messageId, 2_048);
|
|
923
|
+
return {
|
|
924
|
+
accepted: boolean(value.accepted),
|
|
925
|
+
...messageId === undefined ? {} : { messageId },
|
|
926
|
+
warnings: value.warnings.map(warning => remoteString(warning, 1_024)),
|
|
927
|
+
};
|
|
928
|
+
}, true);
|
|
929
|
+
}
|
|
332
930
|
clearLocalData() {
|
|
333
931
|
return this.run(client => client.clearLocalData());
|
|
334
932
|
}
|