@awiki/dsh-plugin 0.3.7 → 0.3.11-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 +112 -73
- package/README.zh.md +91 -62
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/cordis.patch.yml +6 -5
- package/lib/builtin-tenants.json +22 -0
- package/lib/builtin-tenants.sha256 +1 -0
- package/lib/client.js +9281 -2379
- package/lib/client.js.map +1 -1
- package/lib/index.js +3553 -1138
- package/lib/model-proxy-contract.js +19 -11
- package/lib/provider.js +73 -17
- package/lib/{sdk-adapter--trNlr-T.mjs → sdk-adapter-CYcJH7sM.mjs} +374 -101
- package/lib/typert.host.js +1595 -168
- package/lib/typert.remote-client.d.ts +43 -7
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +1595 -168
- package/lib/types/builtin-tenant-config.d.ts +19 -0
- package/lib/types/builtin-tenant-config.d.ts.map +1 -0
- package/lib/types/builtin-tenant-config.js +57 -0
- package/lib/types/builtin-tenant-config.js.map +1 -0
- package/lib/types/client/AwikiDeviceJoinReminder.d.ts +15 -0
- package/lib/types/client/AwikiDeviceJoinReminder.d.ts.map +1 -0
- package/lib/types/client/AwikiDeviceJoinReminder.js +74 -0
- package/lib/types/client/AwikiDeviceJoinReminder.js.map +1 -0
- package/lib/types/client/AwikiDevices.d.ts +33 -0
- package/lib/types/client/AwikiDevices.d.ts.map +1 -0
- package/lib/types/client/AwikiDevices.js +141 -0
- package/lib/types/client/AwikiDevices.js.map +1 -0
- package/lib/types/client/AwikiGroupDetails.d.ts.map +1 -1
- package/lib/types/client/AwikiGroupDetails.js +16 -13
- package/lib/types/client/AwikiGroupDetails.js.map +1 -1
- package/lib/types/client/AwikiIdentityAccess.d.ts +17 -8
- package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
- package/lib/types/client/AwikiIdentityAccess.js +269 -37
- package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
- package/lib/types/client/AwikiIntegrationSettings.d.ts +21 -0
- package/lib/types/client/AwikiIntegrationSettings.d.ts.map +1 -0
- package/lib/types/client/AwikiIntegrationSettings.js +105 -0
- package/lib/types/client/AwikiIntegrationSettings.js.map +1 -0
- package/lib/types/client/AwikiMail.d.ts +1 -1
- package/lib/types/client/AwikiMail.d.ts.map +1 -1
- package/lib/types/client/AwikiMail.js +17 -137
- package/lib/types/client/AwikiMail.js.map +1 -1
- package/lib/types/client/AwikiOverlay.d.ts +0 -1
- package/lib/types/client/AwikiOverlay.d.ts.map +1 -1
- package/lib/types/client/AwikiOverlay.js +26 -28
- package/lib/types/client/AwikiOverlay.js.map +1 -1
- package/lib/types/client/AwikiProfileCard.d.ts.map +1 -1
- package/lib/types/client/AwikiProfileCard.js +17 -18
- package/lib/types/client/AwikiProfileCard.js.map +1 -1
- package/lib/types/client/AwikiRecoveryForm.d.ts +6 -1
- package/lib/types/client/AwikiRecoveryForm.d.ts.map +1 -1
- package/lib/types/client/AwikiRecoveryForm.js +74 -30
- package/lib/types/client/AwikiRecoveryForm.js.map +1 -1
- package/lib/types/client/AwikiSettingsSection.d.ts +28 -13
- package/lib/types/client/AwikiSettingsSection.d.ts.map +1 -1
- package/lib/types/client/AwikiSettingsSection.js +93 -61
- package/lib/types/client/AwikiSettingsSection.js.map +1 -1
- package/lib/types/client/AwikiUpdates.d.ts +10 -0
- package/lib/types/client/AwikiUpdates.d.ts.map +1 -0
- package/lib/types/client/AwikiUpdates.js +57 -0
- package/lib/types/client/AwikiUpdates.js.map +1 -0
- package/lib/types/client/awiki-client-bridge.d.ts +2 -2
- package/lib/types/client/awiki-client-bridge.d.ts.map +1 -1
- package/lib/types/client/awiki-client-bridge.js +4 -1
- package/lib/types/client/awiki-client-bridge.js.map +1 -1
- package/lib/types/client/controller.d.ts +92 -44
- package/lib/types/client/controller.d.ts.map +1 -1
- package/lib/types/client/controller.js +761 -334
- package/lib/types/client/controller.js.map +1 -1
- package/lib/types/client/drafts.d.ts +31 -0
- package/lib/types/client/drafts.d.ts.map +1 -0
- package/lib/types/client/drafts.js +94 -0
- package/lib/types/client/drafts.js.map +1 -0
- package/lib/types/client/image-cache.d.ts +2 -2
- package/lib/types/client/image-cache.d.ts.map +1 -1
- package/lib/types/client/image-cache.js +15 -2
- package/lib/types/client/image-cache.js.map +1 -1
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +64 -19
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/integration-operation.d.ts +9 -0
- package/lib/types/client/integration-operation.d.ts.map +1 -0
- package/lib/types/client/integration-operation.js +54 -0
- package/lib/types/client/integration-operation.js.map +1 -0
- package/lib/types/client/mail-list-cache.d.ts +2 -0
- package/lib/types/client/mail-list-cache.d.ts.map +1 -1
- package/lib/types/client/mail-list-cache.js +18 -0
- package/lib/types/client/mail-list-cache.js.map +1 -1
- package/lib/types/client/otp-cooldown.d.ts +7 -0
- package/lib/types/client/otp-cooldown.d.ts.map +1 -0
- package/lib/types/client/otp-cooldown.js +29 -0
- package/lib/types/client/otp-cooldown.js.map +1 -0
- package/lib/types/client/settings-controller.d.ts +38 -2
- package/lib/types/client/settings-controller.d.ts.map +1 -1
- package/lib/types/client/settings-controller.js +206 -10
- package/lib/types/client/settings-controller.js.map +1 -1
- 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 +192 -14
- package/lib/types/client/settings-locales.js.map +1 -1
- package/lib/types/client/slots.d.ts +21 -10
- package/lib/types/client/slots.d.ts.map +1 -1
- package/lib/types/client/slots.js +0 -1
- package/lib/types/client/slots.js.map +1 -1
- package/lib/types/client/store.d.ts +1 -1
- package/lib/types/client/store.d.ts.map +1 -1
- package/lib/types/client/store.js +1 -1
- package/lib/types/client/store.js.map +1 -1
- package/lib/types/conversation-preferences.d.ts.map +1 -1
- package/lib/types/conversation-preferences.js +0 -17
- package/lib/types/conversation-preferences.js.map +1 -1
- package/lib/types/desktop-distribution.d.ts +25 -0
- package/lib/types/desktop-distribution.d.ts.map +1 -0
- package/lib/types/desktop-distribution.js +57 -0
- package/lib/types/desktop-distribution.js.map +1 -0
- package/lib/types/domain.d.ts +1 -1
- package/lib/types/domain.d.ts.map +1 -1
- package/lib/types/domain.js +2 -1
- package/lib/types/domain.js.map +1 -1
- package/lib/types/index.d.ts +165 -41
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1594 -535
- package/lib/types/index.js.map +1 -1
- package/lib/types/integration-client.d.ts +17 -0
- package/lib/types/integration-client.d.ts.map +1 -0
- package/lib/types/integration-client.js +233 -0
- package/lib/types/integration-client.js.map +1 -0
- package/lib/types/legacy-sent-mail-cache.d.ts +4 -0
- package/lib/types/legacy-sent-mail-cache.d.ts.map +1 -0
- package/lib/types/legacy-sent-mail-cache.js +29 -0
- package/lib/types/legacy-sent-mail-cache.js.map +1 -0
- package/lib/types/listener-state.d.ts +5 -3
- package/lib/types/listener-state.d.ts.map +1 -1
- package/lib/types/listener-state.js +28 -13
- package/lib/types/listener-state.js.map +1 -1
- package/lib/types/listener.d.ts +9 -32
- package/lib/types/listener.d.ts.map +1 -1
- package/lib/types/listener.js +13 -128
- package/lib/types/listener.js.map +1 -1
- package/lib/types/mail-list-client.d.ts +12 -0
- package/lib/types/mail-list-client.d.ts.map +1 -0
- package/lib/types/mail-list-client.js +254 -0
- package/lib/types/mail-list-client.js.map +1 -0
- package/lib/types/mail-recovery-observability.d.ts +8 -0
- package/lib/types/mail-recovery-observability.d.ts.map +1 -0
- package/lib/types/mail-recovery-observability.js +119 -0
- package/lib/types/mail-recovery-observability.js.map +1 -0
- package/lib/types/mail.d.ts +2 -28
- package/lib/types/mail.d.ts.map +1 -1
- package/lib/types/mail.js +2 -79
- package/lib/types/mail.js.map +1 -1
- package/lib/types/model-proxy-contract.d.ts +8 -8
- package/lib/types/model-proxy-contract.d.ts.map +1 -1
- package/lib/types/model-proxy-contract.js +15 -8
- package/lib/types/model-proxy-contract.js.map +1 -1
- package/lib/types/package-version.generated.d.ts +4 -0
- package/lib/types/package-version.generated.d.ts.map +1 -0
- package/lib/types/package-version.generated.js +4 -0
- package/lib/types/package-version.generated.js.map +1 -0
- package/lib/types/profile-state.d.ts +2 -13
- package/lib/types/profile-state.d.ts.map +1 -1
- package/lib/types/profile-state.js +3 -20
- package/lib/types/profile-state.js.map +1 -1
- package/lib/types/provider-api.d.ts +134 -43
- package/lib/types/provider-api.d.ts.map +1 -1
- package/lib/types/provider.d.ts +8 -2
- package/lib/types/provider.d.ts.map +1 -1
- package/lib/types/provider.js +76 -16
- package/lib/types/provider.js.map +1 -1
- package/lib/types/realtime-supervisor.d.ts +60 -0
- package/lib/types/realtime-supervisor.d.ts.map +1 -0
- package/lib/types/realtime-supervisor.js +255 -0
- package/lib/types/realtime-supervisor.js.map +1 -0
- package/lib/types/registration-policy.d.ts +7 -0
- package/lib/types/registration-policy.d.ts.map +1 -0
- package/lib/types/registration-policy.js +21 -0
- package/lib/types/registration-policy.js.map +1 -0
- package/lib/types/sdk-adapter.d.ts +62 -11
- package/lib/types/sdk-adapter.d.ts.map +1 -1
- package/lib/types/sdk-adapter.js +285 -123
- package/lib/types/sdk-adapter.js.map +1 -1
- package/lib/types/settings-rpc-contract.d.ts +63 -5
- package/lib/types/settings-rpc-contract.d.ts.map +1 -1
- package/lib/types/settings-rpc-contract.js +108 -5
- package/lib/types/settings-rpc-contract.js.map +1 -1
- package/lib/types/settings-rpc.d.ts +14 -1
- package/lib/types/settings-rpc.d.ts.map +1 -1
- package/lib/types/settings-rpc.js +132 -3
- package/lib/types/settings-rpc.js.map +1 -1
- package/lib/types/settings-transport.d.ts +7 -0
- package/lib/types/settings-transport.d.ts.map +1 -0
- package/lib/types/settings-transport.js +52 -0
- package/lib/types/settings-transport.js.map +1 -0
- package/lib/types/tenant-registry.d.ts +74 -0
- package/lib/types/tenant-registry.d.ts.map +1 -0
- package/lib/types/tenant-registry.js +440 -0
- package/lib/types/tenant-registry.js.map +1 -0
- package/lib/types/tools.d.ts +1 -1
- package/lib/types/tools.d.ts.map +1 -1
- package/lib/types/tools.js +4 -20
- package/lib/types/tools.js.map +1 -1
- package/lib/types/types.d.ts +249 -66
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js.map +1 -1
- package/lib/types/update-policy.d.ts +51 -0
- package/lib/types/update-policy.d.ts.map +1 -0
- package/lib/types/update-policy.js +379 -0
- package/lib/types/update-policy.js.map +1 -0
- package/lib/types/version.d.ts +4 -0
- package/lib/types/version.d.ts.map +1 -0
- package/lib/types/version.js +44 -0
- package/lib/types/version.js.map +1 -0
- package/package.json +88 -61
- package/lib/types/base64.d.ts +0 -4
- package/lib/types/base64.d.ts.map +0 -1
- package/lib/types/base64.js +0 -28
- package/lib/types/base64.js.map +0 -1
- package/lib/types/client/mail-attachment.d.ts +0 -40
- package/lib/types/client/mail-attachment.d.ts.map +0 -1
- package/lib/types/client/mail-attachment.js +0 -187
- package/lib/types/client/mail-attachment.js.map +0 -1
- package/lib/types/sent-mail-store.d.ts +0 -27
- package/lib/types/sent-mail-store.d.ts.map +0 -1
- package/lib/types/sent-mail-store.js +0 -348
- package/lib/types/sent-mail-store.js.map +0 -1
package/lib/types/sdk-adapter.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Rust IM Core adapter that copies native values into Host-owned public DTOs. */
|
|
2
|
+
import { mailRecoveryFailureFields } from "./mail-recovery-observability.js";
|
|
2
3
|
const GROUP_LOOKUP_LIMIT = 100;
|
|
3
4
|
const MAX_GROUP_LOOKUP_PAGES = 20;
|
|
4
5
|
const RUST_FAILURE_CODES = {
|
|
@@ -16,14 +17,16 @@ const RUST_FAILURE_CODES = {
|
|
|
16
17
|
permission_denied: 'forbidden',
|
|
17
18
|
group_not_member: 'group-membership-required',
|
|
18
19
|
group_identity_stale: 'group-identity-stale',
|
|
19
|
-
auth_revoked: '
|
|
20
|
+
auth_revoked: 'device-rejoin-required',
|
|
21
|
+
local_identity_recovery_required: 'identity-recovery-required',
|
|
20
22
|
conflict: 'conflict',
|
|
21
23
|
join_required: 'handle-unavailable',
|
|
22
|
-
state_in_use: '
|
|
24
|
+
state_in_use: 'conflict',
|
|
23
25
|
rate_limited: 'rate-limited',
|
|
24
26
|
timeout: 'network',
|
|
25
27
|
transport_unavailable: 'network',
|
|
26
28
|
sync_failed: 'network',
|
|
29
|
+
sync_blocked: 'conflict',
|
|
27
30
|
session_expired: 'network',
|
|
28
31
|
attachment_transfer_network: 'network',
|
|
29
32
|
recovery_reconciliation_unavailable: 'network',
|
|
@@ -32,15 +35,72 @@ const RUST_FAILURE_CODES = {
|
|
|
32
35
|
/** Closed provider error consumed by the Host's fixed public failure mapping. */
|
|
33
36
|
export class AwikiSdkError extends Error {
|
|
34
37
|
code;
|
|
38
|
+
realtimeFailureCode;
|
|
35
39
|
name = 'AwikiSdkError';
|
|
36
|
-
|
|
40
|
+
mail_ingress_classification;
|
|
41
|
+
auth_status_class;
|
|
42
|
+
auth_stable_machine_code;
|
|
43
|
+
retryable;
|
|
44
|
+
mail_closed_classification;
|
|
45
|
+
constructor(code, realtimeFailureCode, mailRecoveryFailure) {
|
|
37
46
|
super(`AWiki SDK operation failed: ${code}`);
|
|
38
47
|
this.code = code;
|
|
48
|
+
this.realtimeFailureCode = realtimeFailureCode;
|
|
49
|
+
if (mailRecoveryFailure !== undefined)
|
|
50
|
+
Object.assign(this, mailRecoveryFailure);
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
53
|
function fail(code = 'remote') {
|
|
42
54
|
throw new AwikiSdkError(code);
|
|
43
55
|
}
|
|
56
|
+
const REALTIME_RETRY_WARNING_PRIORITY = [
|
|
57
|
+
'sync.retry.local_state.actor_closed',
|
|
58
|
+
'sync.retry.local_state.database_busy',
|
|
59
|
+
'sync.retry.local_state.constraint_failed',
|
|
60
|
+
'sync.retry.local_state.schema_unavailable',
|
|
61
|
+
'sync.retry.local_state.storage_unavailable',
|
|
62
|
+
'sync.retry.local_state.codec_unavailable',
|
|
63
|
+
'sync.retry.local_state.other',
|
|
64
|
+
'sync.retry.transport_unavailable',
|
|
65
|
+
'sync.retry.service_unavailable',
|
|
66
|
+
'sync.retry.local_state_unavailable',
|
|
67
|
+
];
|
|
68
|
+
function realtimeSyncFailureCode(status, warnings, errorCode) {
|
|
69
|
+
if (status === 'retryable_failure') {
|
|
70
|
+
return REALTIME_RETRY_WARNING_PRIORITY.find(code => warnings.includes(code))
|
|
71
|
+
?? 'sync.retryable_failure';
|
|
72
|
+
}
|
|
73
|
+
if (status === 'recovery_required')
|
|
74
|
+
return 'sync.recovery_required';
|
|
75
|
+
if (status === 'auth_revoked')
|
|
76
|
+
return 'sync.auth_revoked';
|
|
77
|
+
if (status === 'blocked') {
|
|
78
|
+
if (errorCode === 'sync.client_upgrade_required') {
|
|
79
|
+
return 'sync.blocked.client_upgrade_required';
|
|
80
|
+
}
|
|
81
|
+
if (errorCode === 'device_reprovision_required') {
|
|
82
|
+
return 'sync.blocked.device_reprovision_required';
|
|
83
|
+
}
|
|
84
|
+
if (errorCode === 'server_repair_required') {
|
|
85
|
+
return 'sync.blocked.server_repair_required';
|
|
86
|
+
}
|
|
87
|
+
if (errorCode === 'sync.snapshot_item_too_large'
|
|
88
|
+
|| errorCode === 'sync.snapshot_required_state_too_large') {
|
|
89
|
+
return 'sync.blocked.snapshot_capacity';
|
|
90
|
+
}
|
|
91
|
+
if (errorCode === 'sync.invalid_request')
|
|
92
|
+
return 'sync.blocked.invalid_request';
|
|
93
|
+
if (errorCode === 'sync.invalid_cursor')
|
|
94
|
+
return 'sync.blocked.invalid_cursor';
|
|
95
|
+
return errorCode === undefined ? 'sync.blocked' : 'sync.blocked.other';
|
|
96
|
+
}
|
|
97
|
+
return 'sync.unexpected_status';
|
|
98
|
+
}
|
|
99
|
+
function syncResultErrorCode(result) {
|
|
100
|
+
if (!('errorCode' in result))
|
|
101
|
+
return undefined;
|
|
102
|
+
return typeof result.errorCode === 'string' ? result.errorCode : undefined;
|
|
103
|
+
}
|
|
44
104
|
function mapError(error, ambiguousSend = false) {
|
|
45
105
|
if (error instanceof AwikiSdkError)
|
|
46
106
|
throw error;
|
|
@@ -56,7 +116,7 @@ function mapError(error, ambiguousSend = false) {
|
|
|
56
116
|
}
|
|
57
117
|
}
|
|
58
118
|
catch { }
|
|
59
|
-
|
|
119
|
+
throw new AwikiSdkError(code, undefined, mailRecoveryFailureFields(error));
|
|
60
120
|
}
|
|
61
121
|
function safeInteger(value, minimum = 0) {
|
|
62
122
|
if (!/^(?:0|[1-9]\d*)$/u.test(value))
|
|
@@ -111,24 +171,6 @@ function mailAddress(value) {
|
|
|
111
171
|
fail();
|
|
112
172
|
return value;
|
|
113
173
|
}
|
|
114
|
-
function mailFileName(value) {
|
|
115
|
-
if (typeof value !== 'string'
|
|
116
|
-
|| value.length === 0
|
|
117
|
-
|| value.trim() !== value
|
|
118
|
-
|| value.replace(/[. ]+$/u, '') !== value
|
|
119
|
-
|| value === '.'
|
|
120
|
-
|| value === '..'
|
|
121
|
-
|| Buffer.byteLength(value, 'utf8') > 255
|
|
122
|
-
|| /[\\/\p{C}]/u.test(value))
|
|
123
|
-
fail();
|
|
124
|
-
return value;
|
|
125
|
-
}
|
|
126
|
-
function mailContentType(value) {
|
|
127
|
-
if (typeof value !== 'string'
|
|
128
|
-
|| !/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/u.test(value))
|
|
129
|
-
fail();
|
|
130
|
-
return value;
|
|
131
|
-
}
|
|
132
174
|
function mailAddresses(value) {
|
|
133
175
|
if (!Array.isArray(value) || value.length > 100)
|
|
134
176
|
fail();
|
|
@@ -148,14 +190,6 @@ function uint32(value) {
|
|
|
148
190
|
fail();
|
|
149
191
|
return value;
|
|
150
192
|
}
|
|
151
|
-
function recoveryE2eeGroupCount(impact) {
|
|
152
|
-
if (typeof impact !== 'object' || impact === null)
|
|
153
|
-
fail();
|
|
154
|
-
const value = impact;
|
|
155
|
-
return uint32(value.unsupportedE2eeGroupCount !== undefined
|
|
156
|
-
? value.unsupportedE2eeGroupCount
|
|
157
|
-
: value.unsupportedE2EeGroupCount);
|
|
158
|
-
}
|
|
159
193
|
function boolean(value) {
|
|
160
194
|
if (typeof value !== 'boolean')
|
|
161
195
|
fail();
|
|
@@ -254,6 +288,26 @@ function identity(value) {
|
|
|
254
288
|
registeredAt: safeInteger(value.registeredAtMs),
|
|
255
289
|
};
|
|
256
290
|
}
|
|
291
|
+
function joinProgress(value) {
|
|
292
|
+
return {
|
|
293
|
+
joinSessionId: required(value.joinSessionId),
|
|
294
|
+
localPhase: value.localPhase,
|
|
295
|
+
remoteState: value.remoteState,
|
|
296
|
+
expiresAt: required(value.expiresAt),
|
|
297
|
+
...value.sas === undefined ? {} : { sas: required(value.sas) },
|
|
298
|
+
completed: boolean(value.completed),
|
|
299
|
+
...value.identity === undefined ? {} : { identity: identity(value.identity) },
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function adminJoinProgress(value) {
|
|
303
|
+
return {
|
|
304
|
+
joinSessionId: required(value.joinSessionId),
|
|
305
|
+
localPhase: value.localPhase,
|
|
306
|
+
remoteState: value.remoteState,
|
|
307
|
+
expiresAt: required(value.expiresAt),
|
|
308
|
+
...value.sas === undefined ? {} : { sas: required(value.sas) },
|
|
309
|
+
};
|
|
310
|
+
}
|
|
257
311
|
function profile(value) {
|
|
258
312
|
return {
|
|
259
313
|
did: required(value.did),
|
|
@@ -377,20 +431,51 @@ function externalHttpAttempt(value) {
|
|
|
377
431
|
}
|
|
378
432
|
/** Adapt the Rust Node bridge to the frozen Host provider interface. */
|
|
379
433
|
export class RustSdkAdapter {
|
|
434
|
+
trustedUserPresenceSupported = process.platform === 'darwin' && process.arch === 'x64';
|
|
380
435
|
client;
|
|
436
|
+
refreshingDisplayPeers = new Set();
|
|
437
|
+
scheduleDisplayRefresh(client, peers) {
|
|
438
|
+
if (this.disposal !== undefined)
|
|
439
|
+
return;
|
|
440
|
+
const pending = [...new Set(peers)].filter(peer => peer.startsWith('did:') && !this.refreshingDisplayPeers.has(peer)).slice(0, 100);
|
|
441
|
+
if (pending.length === 0)
|
|
442
|
+
return;
|
|
443
|
+
for (const peer of pending)
|
|
444
|
+
this.refreshingDisplayPeers.add(peer);
|
|
445
|
+
void client.refreshDisplayProfiles({ peers: pending }).catch(() => undefined).finally(() => {
|
|
446
|
+
for (const peer of pending)
|
|
447
|
+
this.refreshingDisplayPeers.delete(peer);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
getDisplayProfiles(peers) {
|
|
451
|
+
return this.run(async (client) => {
|
|
452
|
+
const profiles = await client.hydrateDisplayProfiles({ peers });
|
|
453
|
+
this.scheduleDisplayRefresh(client, peers);
|
|
454
|
+
return profiles.flatMap(profile => profile.did === undefined ? [] : [{
|
|
455
|
+
did: profile.did, cacheHit: profile.cacheHit,
|
|
456
|
+
...profile.handle === undefined ? {} : { handle: profile.handle },
|
|
457
|
+
...profile.displayName === undefined ? {} : { displayName: profile.displayName },
|
|
458
|
+
}]);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
381
461
|
attachmentConversations = new Map();
|
|
382
462
|
disposal;
|
|
463
|
+
realtime;
|
|
464
|
+
agentInbox;
|
|
383
465
|
listener;
|
|
384
466
|
constructor(client) {
|
|
385
467
|
this.client = Promise.resolve(client);
|
|
386
|
-
this.
|
|
468
|
+
this.realtime = {
|
|
387
469
|
syncNow: reason => this.listenerSyncNow(reason),
|
|
388
470
|
startRealtime: () => this.listenerStartRealtime(),
|
|
471
|
+
};
|
|
472
|
+
this.agentInbox = {
|
|
389
473
|
listConversations: request => this.listenerConversations(request),
|
|
390
474
|
getHistory: request => this.listenerHistory(request),
|
|
391
475
|
markConversationRead: conversationId => this.markConversationRead(conversationId),
|
|
392
476
|
sendText: request => this.sendText(request),
|
|
393
477
|
};
|
|
478
|
+
this.listener = { ...this.realtime, ...this.agentInbox };
|
|
394
479
|
}
|
|
395
480
|
async run(operation, ambiguousSend = false) {
|
|
396
481
|
try {
|
|
@@ -404,13 +489,12 @@ export class RustSdkAdapter {
|
|
|
404
489
|
const messages = values.filter(displayableMessage);
|
|
405
490
|
const peers = [...new Set(messages
|
|
406
491
|
.filter(message => (message.conversationKind === 'group'
|
|
407
|
-
&& !message.outgoing
|
|
408
|
-
&& message.senderHandle === undefined
|
|
409
|
-
&& message.senderDisplayName === undefined))
|
|
492
|
+
&& !message.outgoing))
|
|
410
493
|
.map(message => message.senderDid))];
|
|
411
494
|
if (peers.length === 0)
|
|
412
495
|
return [...messages];
|
|
413
496
|
const profiles = await client.hydrateDisplayProfiles({ peers });
|
|
497
|
+
this.scheduleDisplayRefresh(client, peers);
|
|
414
498
|
const byDid = new Map();
|
|
415
499
|
for (const profile of profiles) {
|
|
416
500
|
if (profile.did !== undefined)
|
|
@@ -418,10 +502,11 @@ export class RustSdkAdapter {
|
|
|
418
502
|
}
|
|
419
503
|
return messages.map((message) => {
|
|
420
504
|
const profile = byDid.get(message.senderDid);
|
|
421
|
-
if (profile === undefined)
|
|
505
|
+
if (profile === undefined || !profile.cacheHit)
|
|
422
506
|
return message;
|
|
507
|
+
const { senderDisplayName: _snapshot, ...rest } = message;
|
|
423
508
|
return {
|
|
424
|
-
...
|
|
509
|
+
...rest,
|
|
425
510
|
...profile.handle === undefined ? {} : { senderHandle: profile.handle },
|
|
426
511
|
...profile.displayName === undefined ? {} : { senderDisplayName: profile.displayName },
|
|
427
512
|
};
|
|
@@ -567,7 +652,7 @@ export class RustSdkAdapter {
|
|
|
567
652
|
...value.peerPersonaId === undefined ? {} : { peerPersonaId: value.peerPersonaId },
|
|
568
653
|
...value.did === undefined ? {} : { did: value.did },
|
|
569
654
|
...value.credentialDid === undefined ? {} : { credentialDid: value.credentialDid },
|
|
570
|
-
...value.handle === undefined ? {} : { handle: value.handle },
|
|
655
|
+
...(profile?.handle ?? value.handle) === undefined ? {} : { handle: (profile?.handle ?? value.handle) },
|
|
571
656
|
...profile?.displayName === undefined ? {} : { displayName: profile.displayName },
|
|
572
657
|
...value.role === undefined ? {} : { role: value.role },
|
|
573
658
|
...value.status === undefined ? {} : { status: value.status },
|
|
@@ -608,11 +693,14 @@ export class RustSdkAdapter {
|
|
|
608
693
|
listenerSyncNow(reason) {
|
|
609
694
|
return this.run(async (client) => {
|
|
610
695
|
const result = await client.syncNow({ reason });
|
|
611
|
-
if (result.status === 'idle' || result.status === 'changed')
|
|
612
|
-
return
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
696
|
+
if (result.status === 'idle' || result.status === 'changed') {
|
|
697
|
+
return {
|
|
698
|
+
pagesFetched: uint32(result.pagesFetched),
|
|
699
|
+
messagesHydrated: uint32(result.messagesHydrated),
|
|
700
|
+
olderHistoryExcluded: boolean(result.olderHistoryExcluded),
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
throw new AwikiSdkError(result.status === 'auth_revoked' ? 'device-rejoin-required' : 'network', realtimeSyncFailureCode(result.status, result.warnings, syncResultErrorCode(result)));
|
|
616
704
|
});
|
|
617
705
|
}
|
|
618
706
|
listenerStartRealtime() {
|
|
@@ -620,6 +708,10 @@ export class RustSdkAdapter {
|
|
|
620
708
|
const session = await client.startRealtime();
|
|
621
709
|
return {
|
|
622
710
|
nextEvent: () => this.run(() => session.nextEvent()),
|
|
711
|
+
getStatus: () => this.run(async () => {
|
|
712
|
+
const status = await session.getStatus();
|
|
713
|
+
return { connected: status.connected };
|
|
714
|
+
}),
|
|
623
715
|
stop: () => this.run(() => session.stop()),
|
|
624
716
|
};
|
|
625
717
|
});
|
|
@@ -676,7 +768,137 @@ export class RustSdkAdapter {
|
|
|
676
768
|
});
|
|
677
769
|
}
|
|
678
770
|
registerIdentity(request) {
|
|
679
|
-
return this.run(async (client) =>
|
|
771
|
+
return this.run(async (client) => {
|
|
772
|
+
const value = await client.completeRegistrationWithOutcome(request);
|
|
773
|
+
if (value.status === 'registered') {
|
|
774
|
+
return { status: 'registered', identity: identity(value.identity) };
|
|
775
|
+
}
|
|
776
|
+
return {
|
|
777
|
+
status: 'join-required',
|
|
778
|
+
continuationId: required(value.existingHandle.continuationId),
|
|
779
|
+
fullHandle: required(value.existingHandle.fullHandle),
|
|
780
|
+
mode: value.existingHandle.mode === 'handle_recovery_rebind'
|
|
781
|
+
? 'handle-recovery-rebind'
|
|
782
|
+
: 'ordinary',
|
|
783
|
+
requiresUserPresence: boolean(value.existingHandle.requiresUserPresence),
|
|
784
|
+
};
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
beginDeviceJoin(request) {
|
|
788
|
+
return this.run(async (client) => joinProgress(await client.beginPreparedRegistrationJoin(request)));
|
|
789
|
+
}
|
|
790
|
+
getDeviceJoinStatus(joinSessionId) {
|
|
791
|
+
return this.run(async (client) => joinProgress(await client.resumePreparedRegistrationJoin({ joinSessionId })));
|
|
792
|
+
}
|
|
793
|
+
listLocalDeviceJoinSessions() {
|
|
794
|
+
return this.run(async (client) => (await client.listLocalDeviceJoinSessions()).map(value => ({
|
|
795
|
+
joinSessionId: required(value.joinSessionId),
|
|
796
|
+
side: value.side,
|
|
797
|
+
localPhase: value.localPhase,
|
|
798
|
+
expiresAt: required(value.expiresAt),
|
|
799
|
+
})));
|
|
800
|
+
}
|
|
801
|
+
cancelDeviceJoin(joinSessionId) {
|
|
802
|
+
return this.run(async (client) => {
|
|
803
|
+
const value = await client.cancelPreparedRegistrationJoin({ joinSessionId });
|
|
804
|
+
return {
|
|
805
|
+
joinSessionId: required(value.joinSessionId),
|
|
806
|
+
side: value.side,
|
|
807
|
+
localPhase: value.localPhase,
|
|
808
|
+
expiresAt: required(value.expiresAt),
|
|
809
|
+
};
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
getCurrentDeviceSummary() {
|
|
813
|
+
return this.run(async (client) => {
|
|
814
|
+
const value = await client.getCurrentDeviceSummary();
|
|
815
|
+
return {
|
|
816
|
+
...value.role === undefined ? {} : { role: value.role },
|
|
817
|
+
readiness: value.readiness,
|
|
818
|
+
canManage: boolean(value.canManage),
|
|
819
|
+
};
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
syncDeviceManagement() {
|
|
823
|
+
return this.run(async (client) => {
|
|
824
|
+
await client.syncNow({ reason: 'foreground_reconcile' });
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
getDeviceRegistry() {
|
|
828
|
+
return this.run(async (client) => (await client.getDeviceRegistry()).devices.map(value => ({
|
|
829
|
+
deviceId: required(value.protocolDeviceId),
|
|
830
|
+
status: value.status,
|
|
831
|
+
role: value.role,
|
|
832
|
+
managementReady: boolean(value.managementReady),
|
|
833
|
+
isCurrent: boolean(value.isCurrent),
|
|
834
|
+
})));
|
|
835
|
+
}
|
|
836
|
+
listLocalDeviceJoinRequests() {
|
|
837
|
+
return this.run(async (client) => (await client.listLocalDeviceJoinRequests()).map(value => ({
|
|
838
|
+
joinSessionId: required(value.joinSessionId),
|
|
839
|
+
protocolDeviceId: required(value.protocolDeviceId),
|
|
840
|
+
candidateKeyFingerprint: required(value.candidateKeyFingerprint),
|
|
841
|
+
issuedAt: required(value.issuedAt),
|
|
842
|
+
expiresAt: required(value.expiresAt),
|
|
843
|
+
state: value.state,
|
|
844
|
+
claimedByCurrentDevice: boolean(value.claimedByCurrentDevice),
|
|
845
|
+
canStartVerification: boolean(value.canStartVerification),
|
|
846
|
+
})));
|
|
847
|
+
}
|
|
848
|
+
startDeviceJoinVerification(request) {
|
|
849
|
+
return this.run(async (client) => adminJoinProgress(await client.startDeviceJoinVerification(request)));
|
|
850
|
+
}
|
|
851
|
+
getLocalDeviceJoinVerificationProgress(joinSessionId) {
|
|
852
|
+
return this.run(async (client) => adminJoinProgress(await client.getLocalDeviceJoinVerificationProgress({ joinSessionId })));
|
|
853
|
+
}
|
|
854
|
+
prepareDeviceJoinApproval(joinSessionId) {
|
|
855
|
+
return this.run(async (client) => {
|
|
856
|
+
const value = await client.prepareDeviceJoinApproval({ joinSessionId, sasConfirmed: true });
|
|
857
|
+
return { approvalHandle: required(value.approvalHandle) };
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
confirmDeviceJoinApproval(approvalHandle) {
|
|
861
|
+
return this.run(async (client) => adminJoinProgress(await client.confirmDeviceJoinApproval({
|
|
862
|
+
approvalHandle,
|
|
863
|
+
userPresenceConfirmed: true,
|
|
864
|
+
})));
|
|
865
|
+
}
|
|
866
|
+
rejectDeviceJoin(joinSessionId, reason) {
|
|
867
|
+
return this.run(async (client) => adminJoinProgress(await client.rejectDeviceJoin({ joinSessionId, reason })));
|
|
868
|
+
}
|
|
869
|
+
revokeDevice(deviceId) {
|
|
870
|
+
return this.run(async (client) => {
|
|
871
|
+
await client.revokeDevice({ targetDeviceId: deviceId, userPresenceConfirmed: true });
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
confirmUserPresence(reason) {
|
|
875
|
+
return this.run(client => client.confirmUserPresence({ reason }));
|
|
876
|
+
}
|
|
877
|
+
prepareRootKeyTransfer(deviceId) {
|
|
878
|
+
return this.run(async (client) => {
|
|
879
|
+
const value = await client.prepareRootKeyTransfer({ recipientDeviceId: deviceId });
|
|
880
|
+
return {
|
|
881
|
+
authorizationHandle: required(value.authorizationHandle),
|
|
882
|
+
recipient: {
|
|
883
|
+
did: required(value.recipient.did),
|
|
884
|
+
deviceId: required(value.recipient.deviceId),
|
|
885
|
+
registryVersion: required(value.recipient.registryVersion),
|
|
886
|
+
},
|
|
887
|
+
expiresAt: required(value.expiresAt),
|
|
888
|
+
};
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
confirmAndSendRootKeyTransfer(authorizationHandle) {
|
|
892
|
+
return this.run(async (client) => {
|
|
893
|
+
const value = await client.confirmAndSendRootKeyTransfer({
|
|
894
|
+
authorizationHandle,
|
|
895
|
+
userPresenceConfirmed: true,
|
|
896
|
+
});
|
|
897
|
+
return {
|
|
898
|
+
recipientDeviceId: required(value.recipientDeviceId),
|
|
899
|
+
acceptedAt: required(value.acceptedAt),
|
|
900
|
+
};
|
|
901
|
+
});
|
|
680
902
|
}
|
|
681
903
|
updateDisplayName(request) {
|
|
682
904
|
return this.run(async (client) => identity(await client.updateDisplayName(request.displayName)));
|
|
@@ -698,12 +920,11 @@ export class RustSdkAdapter {
|
|
|
698
920
|
...value.previousDid === undefined ? {} : { previousDid: value.previousDid },
|
|
699
921
|
currentDid: required(value.currentDid),
|
|
700
922
|
phase: value.phase,
|
|
923
|
+
allowedActions: [...(value.allowedActions ?? [])],
|
|
701
924
|
...value.failureCode === undefined ? {} : { failureCode: value.failureCode },
|
|
702
925
|
retryable: boolean(value.retryable),
|
|
703
926
|
localOrdinaryDataWillMigrate: boolean(value.impact.localOrdinaryDataWillMigrate),
|
|
704
927
|
otherDevicesMustRejoin: boolean(value.impact.otherDevicesMustRejoin),
|
|
705
|
-
unsupportedE2eeGroupCount: recoveryE2eeGroupCount(value.impact),
|
|
706
|
-
unsupportedDidOnlyGroupCount: uint32(value.impact.unsupportedDidOnlyGroupCount),
|
|
707
928
|
};
|
|
708
929
|
}
|
|
709
930
|
sendRecoveryOtp(request) {
|
|
@@ -723,21 +944,17 @@ export class RustSdkAdapter {
|
|
|
723
944
|
activateRecovery(request) {
|
|
724
945
|
return this.run(async (client) => this.recoveryProgress(await client.activateHandleRecovery(request)));
|
|
725
946
|
}
|
|
947
|
+
listPendingRecoveries() {
|
|
948
|
+
return this.run(async (client) => (await client.listPendingHandleRecoveryOperations()).map(value => ({
|
|
949
|
+
operationId: required(value.operationId), fullHandle: required(value.fullHandle),
|
|
950
|
+
})));
|
|
951
|
+
}
|
|
726
952
|
getRecoveryStatus(request) {
|
|
727
953
|
return this.run(async (client) => this.recoveryProgress(await client.getHandleRecoveryStatus(request)));
|
|
728
954
|
}
|
|
729
955
|
resumeRecovery(request) {
|
|
730
956
|
return this.run(async (client) => this.recoveryProgress(await client.resumeHandleRecovery(request)));
|
|
731
957
|
}
|
|
732
|
-
issueRecoveryAttestation(request) {
|
|
733
|
-
return this.run(async (client) => {
|
|
734
|
-
const value = await client.issueHandleRecoveryAttestation(request);
|
|
735
|
-
return {
|
|
736
|
-
attestation: required(value.attestation),
|
|
737
|
-
expiresAt: required(value.expiresAt),
|
|
738
|
-
};
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
958
|
discardRecovery(request) {
|
|
742
959
|
return this.run(async (client) => {
|
|
743
960
|
await client.discardHandleRecovery(request);
|
|
@@ -781,6 +998,7 @@ export class RustSdkAdapter {
|
|
|
781
998
|
});
|
|
782
999
|
const peers = [...new Set(value.items.flatMap(member => member.did ?? member.handle ?? []))];
|
|
783
1000
|
const profiles = peers.length === 0 ? [] : await client.hydrateDisplayProfiles({ peers });
|
|
1001
|
+
this.scheduleDisplayRefresh(client, peers);
|
|
784
1002
|
const byPeer = new Map();
|
|
785
1003
|
for (const [index, profile] of profiles.entries()) {
|
|
786
1004
|
const requested = peers[index];
|
|
@@ -808,48 +1026,6 @@ export class RustSdkAdapter {
|
|
|
808
1026
|
member,
|
|
809
1027
|
})));
|
|
810
1028
|
}
|
|
811
|
-
resumeGroupRebindRecovery() {
|
|
812
|
-
return this.run(async (client) => {
|
|
813
|
-
const value = await client.resumeGroupRebindRecovery(100);
|
|
814
|
-
const journal = value;
|
|
815
|
-
const statuses = new Map();
|
|
816
|
-
for (const item of journal.items ?? []) {
|
|
817
|
-
const { groupDid: rawGroupDid, layer: rawLayer, phase: rawPhase } = item;
|
|
818
|
-
if (typeof rawGroupDid !== 'string'
|
|
819
|
-
|| typeof rawLayer !== 'string'
|
|
820
|
-
|| typeof rawPhase !== 'string'
|
|
821
|
-
|| typeof item.blocked !== 'boolean') {
|
|
822
|
-
throw new TypeError('invalid group recovery item');
|
|
823
|
-
}
|
|
824
|
-
const groupDid = required(rawGroupDid);
|
|
825
|
-
const layer = required(rawLayer);
|
|
826
|
-
const phase = required(rawPhase);
|
|
827
|
-
if (layer !== 'p4' && layer !== 'p6')
|
|
828
|
-
throw new TypeError('invalid group recovery item');
|
|
829
|
-
if (phase === 'complete')
|
|
830
|
-
continue;
|
|
831
|
-
const status = item.blocked || phase === 'blocked' ? 'blocked' : 'pending';
|
|
832
|
-
if (statuses.get(groupDid) !== 'blocked')
|
|
833
|
-
statuses.set(groupDid, status);
|
|
834
|
-
}
|
|
835
|
-
for (const group of journal.sendPausedGroups ?? []) {
|
|
836
|
-
if (typeof group !== 'string')
|
|
837
|
-
throw new TypeError('invalid paused recovery group');
|
|
838
|
-
const groupDid = required(group);
|
|
839
|
-
if (!statuses.has(groupDid))
|
|
840
|
-
statuses.set(groupDid, 'pending');
|
|
841
|
-
}
|
|
842
|
-
const items = [...statuses].map(([groupDid, status]) => ({ groupDid, status }));
|
|
843
|
-
const hasJournal = journal.items !== undefined || journal.sendPausedGroups !== undefined;
|
|
844
|
-
return {
|
|
845
|
-
processed: uint32(value.processed),
|
|
846
|
-
completed: uint32(value.completed),
|
|
847
|
-
pending: hasJournal ? items.filter(item => item.status === 'pending').length : uint32(value.pending),
|
|
848
|
-
blocked: hasJournal ? items.filter(item => item.status === 'blocked').length : uint32(value.blocked),
|
|
849
|
-
items,
|
|
850
|
-
};
|
|
851
|
-
});
|
|
852
|
-
}
|
|
853
1029
|
listConversations(request) {
|
|
854
1030
|
return this.run(async (client) => {
|
|
855
1031
|
const conversations = await client.listConversations(request);
|
|
@@ -968,21 +1144,12 @@ export class RustSdkAdapter {
|
|
|
968
1144
|
});
|
|
969
1145
|
}
|
|
970
1146
|
sendMail(request) {
|
|
971
|
-
const attachments = request.attachments?.map(attachment => ({
|
|
972
|
-
fileName: attachment.fileName,
|
|
973
|
-
contentType: attachment.contentType,
|
|
974
|
-
bytes: Uint8Array.from(attachment.bytes),
|
|
975
|
-
}));
|
|
976
1147
|
return this.run(async (client) => {
|
|
977
|
-
const
|
|
1148
|
+
const value = await client.sendMail({
|
|
978
1149
|
to: [...request.to],
|
|
979
1150
|
...request.cc === undefined ? {} : { cc: [...request.cc] },
|
|
980
1151
|
subject: request.subject,
|
|
981
1152
|
bodyText: request.bodyText,
|
|
982
|
-
};
|
|
983
|
-
const value = await client.sendMail({
|
|
984
|
-
...input,
|
|
985
|
-
...attachments === undefined || attachments.length === 0 ? {} : { attachments },
|
|
986
1153
|
});
|
|
987
1154
|
if (!Array.isArray(value.warnings) || value.warnings.length > 100)
|
|
988
1155
|
fail();
|
|
@@ -996,26 +1163,21 @@ export class RustSdkAdapter {
|
|
|
996
1163
|
};
|
|
997
1164
|
}, true);
|
|
998
1165
|
}
|
|
999
|
-
downloadMailAttachment(request) {
|
|
1000
|
-
return this.run(async (client) => {
|
|
1001
|
-
const value = await client.downloadMailAttachment({
|
|
1002
|
-
messageId: mailToken(request.messageId, 2_048),
|
|
1003
|
-
attachmentIndex: uint32(request.attachmentIndex),
|
|
1004
|
-
});
|
|
1005
|
-
const sizeBytes = safeInteger(remoteString(value.sizeBytes, 20));
|
|
1006
|
-
if (!(value.bytes instanceof Uint8Array) || value.bytes.byteLength !== sizeBytes)
|
|
1007
|
-
fail();
|
|
1008
|
-
return {
|
|
1009
|
-
fileName: mailFileName(value.fileName),
|
|
1010
|
-
contentType: mailContentType(value.contentType),
|
|
1011
|
-
sizeBytes,
|
|
1012
|
-
bytes: Uint8Array.from(value.bytes),
|
|
1013
|
-
};
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
1166
|
clearLocalData() {
|
|
1017
1167
|
return this.run(client => client.clearLocalData());
|
|
1018
1168
|
}
|
|
1169
|
+
retireDefaultIdentityForRejoin() {
|
|
1170
|
+
return this.run((client) => {
|
|
1171
|
+
const retire = client.retireDefaultIdentityForRejoin;
|
|
1172
|
+
if (typeof retire !== 'function') {
|
|
1173
|
+
throw Object.assign(new Error('device rejoin is unavailable in this IM Core build'), {
|
|
1174
|
+
name: 'AwikiSdkError',
|
|
1175
|
+
code: 'remote',
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
return retire.call(client);
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1019
1181
|
dispose() {
|
|
1020
1182
|
this.disposal ??= this.client.then(async (client) => {
|
|
1021
1183
|
try {
|