dcim-web-sdk 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/README.md +0 -0
- package/dist/index.cjs +798 -0
- package/dist/index.d.cts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.js +771 -0
- package/package.json +37 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var EVENT = {
|
|
3
|
+
SDK_READY: "SDK_READY",
|
|
4
|
+
SDK_NOT_READY: "SDK_NOT_READY",
|
|
5
|
+
NET_STATE_CHANGE: "NET_STATE_CHANGE",
|
|
6
|
+
ERROR: "ERROR",
|
|
7
|
+
KICKED_OUT: "KICKED_OUT",
|
|
8
|
+
MESSAGE_RECEIVED: "MESSAGE_RECEIVED",
|
|
9
|
+
MESSAGE_MODIFIED: "MESSAGE_MODIFIED"
|
|
10
|
+
};
|
|
11
|
+
var TYPES = {
|
|
12
|
+
CONV_C2C: "C2C"
|
|
13
|
+
};
|
|
14
|
+
var DEFAULT_PLATFORM_ID = 5;
|
|
15
|
+
|
|
16
|
+
// src/adapters/openim-client-adapter.ts
|
|
17
|
+
import {
|
|
18
|
+
CbEvents as CbEvents2,
|
|
19
|
+
LogLevel,
|
|
20
|
+
LoginStatus,
|
|
21
|
+
getSDK
|
|
22
|
+
} from "@openim/client-sdk";
|
|
23
|
+
|
|
24
|
+
// src/emitter.ts
|
|
25
|
+
var SimpleEmitter = class {
|
|
26
|
+
constructor() {
|
|
27
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
28
|
+
}
|
|
29
|
+
on(eventName, listener) {
|
|
30
|
+
const set = this.listeners.get(eventName) ?? /* @__PURE__ */ new Set();
|
|
31
|
+
set.add(listener);
|
|
32
|
+
this.listeners.set(eventName, set);
|
|
33
|
+
}
|
|
34
|
+
off(eventName, listener) {
|
|
35
|
+
const set = this.listeners.get(eventName);
|
|
36
|
+
if (!set) return;
|
|
37
|
+
set.delete(listener);
|
|
38
|
+
if (set.size === 0) this.listeners.delete(eventName);
|
|
39
|
+
}
|
|
40
|
+
emit(eventName, payload) {
|
|
41
|
+
const set = this.listeners.get(eventName);
|
|
42
|
+
if (!set) return;
|
|
43
|
+
set.forEach((listener) => listener(payload));
|
|
44
|
+
}
|
|
45
|
+
clear() {
|
|
46
|
+
this.listeners.clear();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/mappers/event.ts
|
|
51
|
+
import { CbEvents } from "@openim/client-sdk";
|
|
52
|
+
var OPENIM_TO_COMPAT_EVENT = {
|
|
53
|
+
[CbEvents.OnConnectSuccess]: [EVENT.SDK_READY],
|
|
54
|
+
[CbEvents.OnConnecting]: [EVENT.NET_STATE_CHANGE],
|
|
55
|
+
[CbEvents.OnConnectFailed]: [EVENT.SDK_NOT_READY, EVENT.ERROR],
|
|
56
|
+
[CbEvents.OnKickedOffline]: [EVENT.KICKED_OUT],
|
|
57
|
+
[CbEvents.OnUserTokenExpired]: [EVENT.KICKED_OUT],
|
|
58
|
+
[CbEvents.OnUserTokenInvalid]: [EVENT.KICKED_OUT],
|
|
59
|
+
[CbEvents.OnRecvNewMessage]: [EVENT.MESSAGE_RECEIVED],
|
|
60
|
+
[CbEvents.OnRecvNewMessages]: [EVENT.MESSAGE_RECEIVED]
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// src/mappers/message.ts
|
|
64
|
+
import { MessageType } from "@openim/client-sdk";
|
|
65
|
+
|
|
66
|
+
// src/utils.ts
|
|
67
|
+
var createOperationID = () => {
|
|
68
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
69
|
+
return crypto.randomUUID();
|
|
70
|
+
}
|
|
71
|
+
return `dcim_web_sdk_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
72
|
+
};
|
|
73
|
+
var toUnixSeconds = (value) => {
|
|
74
|
+
if (!value) return void 0;
|
|
75
|
+
return value > 1e12 ? Math.floor(value / 1e3) : value;
|
|
76
|
+
};
|
|
77
|
+
var inferFileType = (fileName) => {
|
|
78
|
+
const index = fileName.lastIndexOf(".");
|
|
79
|
+
if (index < 0) return "";
|
|
80
|
+
return fileName.slice(index + 1).toLowerCase();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// src/mappers/message.ts
|
|
84
|
+
var mapPictureToImageInfo = (picture, type = 1) => {
|
|
85
|
+
if (!picture) return void 0;
|
|
86
|
+
return {
|
|
87
|
+
type,
|
|
88
|
+
size: picture.size ?? picture.Size,
|
|
89
|
+
width: picture.width ?? picture.Width,
|
|
90
|
+
height: picture.height ?? picture.Height,
|
|
91
|
+
url: picture.url ?? picture.Url
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
var resolvePicture = (pictureElem, kind) => {
|
|
95
|
+
if (!pictureElem) return void 0;
|
|
96
|
+
if (kind === "source") return pictureElem.sourcePicture ?? pictureElem.SourcePicture;
|
|
97
|
+
if (kind === "big") return pictureElem.bigPicture ?? pictureElem.BigPicture;
|
|
98
|
+
return pictureElem.snapshotPicture ?? pictureElem.SnapshotPicture;
|
|
99
|
+
};
|
|
100
|
+
var resolveFileField = (fileElem, kind) => {
|
|
101
|
+
if (!fileElem) return void 0;
|
|
102
|
+
if (kind === "url") return fileElem.sourceUrl ?? fileElem.sourceURL ?? fileElem.SourceUrl ?? fileElem.SourceURL;
|
|
103
|
+
if (kind === "name") return fileElem.fileName ?? fileElem.FileName;
|
|
104
|
+
return fileElem.fileSize ?? fileElem.FileSize;
|
|
105
|
+
};
|
|
106
|
+
var toOptionalString = (value) => {
|
|
107
|
+
if (value == null) return void 0;
|
|
108
|
+
return String(value);
|
|
109
|
+
};
|
|
110
|
+
var resolveTextContent = (textElem) => textElem?.content ?? textElem?.Content ?? "";
|
|
111
|
+
var resolveAtText = (atTextElem) => atTextElem?.text ?? atTextElem?.Text ?? "";
|
|
112
|
+
var mapIncomingMessage = (message) => {
|
|
113
|
+
const base = {
|
|
114
|
+
ID: message.clientMsgID,
|
|
115
|
+
cloudCustomData: message.ex ?? "",
|
|
116
|
+
time: toUnixSeconds(message.sendTime),
|
|
117
|
+
clientTime: toUnixSeconds(message.createTime),
|
|
118
|
+
conversationID: message.groupID || message.recvID || message.sendID,
|
|
119
|
+
_raw: message
|
|
120
|
+
};
|
|
121
|
+
switch (message.contentType) {
|
|
122
|
+
case MessageType.TextMessage: {
|
|
123
|
+
const textElem = message.textElem;
|
|
124
|
+
return {
|
|
125
|
+
...base,
|
|
126
|
+
type: "TIMTextElem",
|
|
127
|
+
payload: {
|
|
128
|
+
text: resolveTextContent(textElem)
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
case MessageType.AtTextMessage: {
|
|
133
|
+
const atTextElem = message.atTextElem;
|
|
134
|
+
return {
|
|
135
|
+
...base,
|
|
136
|
+
type: "TIMTextElem",
|
|
137
|
+
payload: {
|
|
138
|
+
text: resolveAtText(atTextElem)
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
case MessageType.PictureMessage: {
|
|
143
|
+
const pictureElem = message.pictureElem;
|
|
144
|
+
const sourcePicture = resolvePicture(pictureElem, "source");
|
|
145
|
+
const source = mapPictureToImageInfo(sourcePicture, 1);
|
|
146
|
+
const big = mapPictureToImageInfo(resolvePicture(pictureElem, "big"), 2);
|
|
147
|
+
const snapshot = mapPictureToImageInfo(resolvePicture(pictureElem, "snapshot"), 3);
|
|
148
|
+
return {
|
|
149
|
+
...base,
|
|
150
|
+
type: "TIMImageElem",
|
|
151
|
+
payload: {
|
|
152
|
+
imageInfoArray: [source, big, snapshot].filter(Boolean),
|
|
153
|
+
imageFormat: toOptionalString(sourcePicture?.type ?? sourcePicture?.Type)
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
case MessageType.FileMessage: {
|
|
158
|
+
const fileElem = message.fileElem;
|
|
159
|
+
return {
|
|
160
|
+
...base,
|
|
161
|
+
type: "TIMFileElem",
|
|
162
|
+
payload: {
|
|
163
|
+
fileUrl: toOptionalString(resolveFileField(fileElem, "url")),
|
|
164
|
+
fileName: toOptionalString(resolveFileField(fileElem, "name")),
|
|
165
|
+
fileSize: resolveFileField(fileElem, "size")
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
default:
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
var buildTextSendResult = (payload, raw) => ({
|
|
174
|
+
data: { message: { payload: { ...payload } } },
|
|
175
|
+
message: { payload: { ...payload } },
|
|
176
|
+
raw
|
|
177
|
+
});
|
|
178
|
+
var buildImageSendResult = (upload, raw) => {
|
|
179
|
+
const cloneImageInfoArray = () => (upload.imageInfoArray ?? []).map((item) => ({
|
|
180
|
+
type: item.type,
|
|
181
|
+
size: item.size,
|
|
182
|
+
width: item.width,
|
|
183
|
+
height: item.height,
|
|
184
|
+
url: item.url
|
|
185
|
+
}));
|
|
186
|
+
const payload = {
|
|
187
|
+
imageInfoArray: cloneImageInfoArray(),
|
|
188
|
+
imageFormat: upload.imageFormat,
|
|
189
|
+
url: upload.url
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
data: {
|
|
193
|
+
message: {
|
|
194
|
+
payload: {
|
|
195
|
+
imageInfoArray: cloneImageInfoArray(),
|
|
196
|
+
imageFormat: payload.imageFormat,
|
|
197
|
+
url: payload.url
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
message: {
|
|
202
|
+
payload: {
|
|
203
|
+
imageInfoArray: cloneImageInfoArray(),
|
|
204
|
+
imageFormat: payload.imageFormat,
|
|
205
|
+
url: payload.url
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
raw
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
var buildFileSendResult = (upload, fileName, fileSize, raw) => {
|
|
212
|
+
const payload = {
|
|
213
|
+
fileUrl: upload.url,
|
|
214
|
+
url: upload.url,
|
|
215
|
+
fileName: upload.fileName ?? fileName,
|
|
216
|
+
fileSize: upload.fileSize ?? fileSize,
|
|
217
|
+
fileType: upload.fileType ?? inferFileType(fileName)
|
|
218
|
+
};
|
|
219
|
+
return {
|
|
220
|
+
data: { message: { payload: { ...payload } } },
|
|
221
|
+
message: { payload: { ...payload } },
|
|
222
|
+
raw
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
var buildLocalTextMessage = (input) => ({
|
|
226
|
+
to: input.to,
|
|
227
|
+
conversationType: input.conversationType,
|
|
228
|
+
type: "TIMTextElem",
|
|
229
|
+
payload: { text: input.payload.text },
|
|
230
|
+
cloudCustomData: input.cloudCustomData
|
|
231
|
+
});
|
|
232
|
+
var buildLocalImageMessage = (input) => ({
|
|
233
|
+
to: input.to,
|
|
234
|
+
conversationType: input.conversationType,
|
|
235
|
+
type: "TIMImageElem",
|
|
236
|
+
payload: {
|
|
237
|
+
file: input.payload.file,
|
|
238
|
+
imageInfoArray: [],
|
|
239
|
+
imageFormat: "",
|
|
240
|
+
url: "",
|
|
241
|
+
onProgress: input.onProgress
|
|
242
|
+
},
|
|
243
|
+
cloudCustomData: input.cloudCustomData
|
|
244
|
+
});
|
|
245
|
+
var buildLocalFileMessage = (input) => ({
|
|
246
|
+
to: input.to,
|
|
247
|
+
conversationType: input.conversationType,
|
|
248
|
+
type: "TIMFileElem",
|
|
249
|
+
payload: {
|
|
250
|
+
file: input.payload.file,
|
|
251
|
+
fileName: input.payload.file.name,
|
|
252
|
+
fileSize: input.payload.file.size,
|
|
253
|
+
fileUrl: "",
|
|
254
|
+
onProgress: input.onProgress
|
|
255
|
+
},
|
|
256
|
+
cloudCustomData: input.cloudCustomData
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// src/dcim-upload-plugin.ts
|
|
260
|
+
var DCIMUploadPlugin = { __brand: "dcim-upload-plugin" };
|
|
261
|
+
|
|
262
|
+
// src/providers.ts
|
|
263
|
+
var joinURL = (baseURL, path) => `${baseURL.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
264
|
+
var createFormData = (file, objectName) => {
|
|
265
|
+
const formData = new FormData();
|
|
266
|
+
formData.append("file", file, objectName ?? file.name);
|
|
267
|
+
return formData;
|
|
268
|
+
};
|
|
269
|
+
var canUseXHRUpload = () => typeof XMLHttpRequest !== "undefined";
|
|
270
|
+
var normalizeImageResult = (data) => ({
|
|
271
|
+
url: data?.url ?? "",
|
|
272
|
+
uuid: data?.uuid ?? "",
|
|
273
|
+
imageFormat: data?.imageFormat ?? "",
|
|
274
|
+
imageInfoArray: data?.imageInfoArray ?? []
|
|
275
|
+
});
|
|
276
|
+
var normalizeFileResult = (data) => ({
|
|
277
|
+
url: data?.fileUrl ?? data?.url ?? "",
|
|
278
|
+
uuid: data?.uuid ?? "",
|
|
279
|
+
fileName: data?.fileName ?? "",
|
|
280
|
+
fileSize: data?.fileSize ?? 0
|
|
281
|
+
});
|
|
282
|
+
var createDcimUploadProvider = (options) => {
|
|
283
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
284
|
+
const doUploadByXHR = async (endpoint, file, objectName, onProgress) => {
|
|
285
|
+
const token = await options.getToken?.();
|
|
286
|
+
const url = joinURL(options.baseURL, endpoint);
|
|
287
|
+
return new Promise((resolve, reject) => {
|
|
288
|
+
const xhr = new XMLHttpRequest();
|
|
289
|
+
xhr.open("POST", url, true);
|
|
290
|
+
if (token) xhr.setRequestHeader("token", token);
|
|
291
|
+
xhr.upload.onprogress = (event) => {
|
|
292
|
+
if (!onProgress) return;
|
|
293
|
+
onProgress({
|
|
294
|
+
loaded: event.loaded,
|
|
295
|
+
total: event.total,
|
|
296
|
+
progress: event.lengthComputable && event.total > 0 ? event.loaded / event.total : 0,
|
|
297
|
+
originalEvent: event
|
|
298
|
+
});
|
|
299
|
+
};
|
|
300
|
+
xhr.onerror = () => {
|
|
301
|
+
reject(new Error("Upload failed"));
|
|
302
|
+
};
|
|
303
|
+
xhr.onload = () => {
|
|
304
|
+
if (xhr.status < 200 || xhr.status >= 300) {
|
|
305
|
+
reject(new Error(`Upload failed with status ${xhr.status}`));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
const body = JSON.parse(xhr.responseText);
|
|
310
|
+
if (body?.errCode && body.errCode !== 0) {
|
|
311
|
+
reject(new Error(body.errMsg || "Upload failed"));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
resolve(body?.data ?? body);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
reject(error);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
xhr.send(createFormData(file, objectName));
|
|
320
|
+
});
|
|
321
|
+
};
|
|
322
|
+
const doUploadByFetch = async (endpoint, file, objectName) => {
|
|
323
|
+
const token = await options.getToken?.();
|
|
324
|
+
const headers = {};
|
|
325
|
+
if (token) headers.token = token;
|
|
326
|
+
const response = await fetchImpl(joinURL(options.baseURL, endpoint), {
|
|
327
|
+
method: "POST",
|
|
328
|
+
headers,
|
|
329
|
+
body: createFormData(file, objectName)
|
|
330
|
+
});
|
|
331
|
+
if (!response.ok) {
|
|
332
|
+
throw new Error(`Upload failed with status ${response.status}`);
|
|
333
|
+
}
|
|
334
|
+
const body = await response.json();
|
|
335
|
+
if (body?.errCode && body.errCode !== 0) {
|
|
336
|
+
throw new Error(body.errMsg || "Upload failed");
|
|
337
|
+
}
|
|
338
|
+
return body?.data ?? body;
|
|
339
|
+
};
|
|
340
|
+
const doUpload = async (endpoint, file, onProgress) => {
|
|
341
|
+
const objectName = await options.getObjectName?.(file);
|
|
342
|
+
if (onProgress && canUseXHRUpload()) {
|
|
343
|
+
return doUploadByXHR(endpoint, file, objectName, onProgress);
|
|
344
|
+
}
|
|
345
|
+
return doUploadByFetch(endpoint, file, objectName);
|
|
346
|
+
};
|
|
347
|
+
return {
|
|
348
|
+
async uploadImage({ file, onProgress }) {
|
|
349
|
+
const data = await doUpload(options.imageEndpoint ?? "/tencent/uploadImage", file, onProgress);
|
|
350
|
+
return normalizeImageResult(data);
|
|
351
|
+
},
|
|
352
|
+
async uploadFile({ file, onProgress }) {
|
|
353
|
+
const data = await doUpload(options.fileEndpoint ?? "/tencent/uploadFile", file, onProgress);
|
|
354
|
+
return normalizeFileResult(data);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// src/adapters/openim-client-adapter.ts
|
|
360
|
+
var OpenIMClientAdapter = class {
|
|
361
|
+
constructor(options) {
|
|
362
|
+
this.emitter = new SimpleEmitter();
|
|
363
|
+
this.boundHandlers = [];
|
|
364
|
+
this.inactiveTimer = null;
|
|
365
|
+
this.loggingOut = false;
|
|
366
|
+
this.ready = false;
|
|
367
|
+
this.logLevel = LogLevel.Info;
|
|
368
|
+
this.options = options;
|
|
369
|
+
this.inactiveTimeout = options.inactiveTimeout ?? 0;
|
|
370
|
+
this.sdk = getSDK();
|
|
371
|
+
if (options.debug) this.logLevel = LogLevel.Debug;
|
|
372
|
+
this.bindSdkEvents();
|
|
373
|
+
}
|
|
374
|
+
registerPlugin(plugins) {
|
|
375
|
+
const candidate = plugins?.["dcim-upload-plugin"];
|
|
376
|
+
if (!candidate) return;
|
|
377
|
+
if (candidate === DCIMUploadPlugin) {
|
|
378
|
+
this.pluginUploader = createDcimUploadProvider({
|
|
379
|
+
baseURL: this.options.apiAddr,
|
|
380
|
+
getToken: () => this.token
|
|
381
|
+
});
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
if (typeof candidate === "object" && "uploadImage" in candidate && "uploadFile" in candidate) {
|
|
385
|
+
this.pluginUploader = candidate;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
resetInactiveTimer() {
|
|
389
|
+
if (this.inactiveTimeout <= 0) return;
|
|
390
|
+
this.clearInactiveTimer();
|
|
391
|
+
this.inactiveTimer = setTimeout(() => {
|
|
392
|
+
this.logout().catch(() => {
|
|
393
|
+
});
|
|
394
|
+
}, this.inactiveTimeout);
|
|
395
|
+
}
|
|
396
|
+
clearInactiveTimer() {
|
|
397
|
+
if (this.inactiveTimer) {
|
|
398
|
+
clearTimeout(this.inactiveTimer);
|
|
399
|
+
this.inactiveTimer = null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
setLogLevel(level) {
|
|
403
|
+
if (level <= LogLevel.Trace && level >= LogLevel.Silent) {
|
|
404
|
+
this.logLevel = level;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
on(eventName, listener) {
|
|
408
|
+
this.emitter.on(eventName, listener);
|
|
409
|
+
}
|
|
410
|
+
off(eventName, listener) {
|
|
411
|
+
this.emitter.off(eventName, listener);
|
|
412
|
+
}
|
|
413
|
+
async login(options) {
|
|
414
|
+
const token = options.token ?? this.options.token;
|
|
415
|
+
if (!token) throw new Error("token is required for login");
|
|
416
|
+
this.token = token;
|
|
417
|
+
this.loggingOut = false;
|
|
418
|
+
const userID = options.userID ?? this.options.userID;
|
|
419
|
+
if (!userID) throw new Error("userID is required for login");
|
|
420
|
+
const result = await this.sdk.login({
|
|
421
|
+
userID,
|
|
422
|
+
token,
|
|
423
|
+
platformID: DEFAULT_PLATFORM_ID,
|
|
424
|
+
apiAddr: options.apiAddr ?? this.options.apiAddr,
|
|
425
|
+
wsAddr: options.wsAddr ?? this.options.wsAddr,
|
|
426
|
+
logLevel: this.logLevel
|
|
427
|
+
});
|
|
428
|
+
this.resetInactiveTimer();
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
async logout() {
|
|
432
|
+
this.loggingOut = true;
|
|
433
|
+
this.ready = false;
|
|
434
|
+
this.clearInactiveTimer();
|
|
435
|
+
await this.sdk.logout();
|
|
436
|
+
}
|
|
437
|
+
async destroy() {
|
|
438
|
+
this.loggingOut = true;
|
|
439
|
+
this.ready = false;
|
|
440
|
+
this.clearInactiveTimer();
|
|
441
|
+
try {
|
|
442
|
+
const status = await this.sdk.getLoginStatus();
|
|
443
|
+
if (status.data !== LoginStatus.Logout) {
|
|
444
|
+
await this.sdk.logout();
|
|
445
|
+
}
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
this.boundHandlers.forEach(({ event, handler }) => {
|
|
449
|
+
this.sdk.off(event, handler);
|
|
450
|
+
});
|
|
451
|
+
this.boundHandlers.length = 0;
|
|
452
|
+
this.emitter.clear();
|
|
453
|
+
}
|
|
454
|
+
isReady() {
|
|
455
|
+
return this.ready;
|
|
456
|
+
}
|
|
457
|
+
createTextMessage(input) {
|
|
458
|
+
return buildLocalTextMessage(input);
|
|
459
|
+
}
|
|
460
|
+
createImageMessage(input) {
|
|
461
|
+
return buildLocalImageMessage(input);
|
|
462
|
+
}
|
|
463
|
+
createFileMessage(input) {
|
|
464
|
+
return buildLocalFileMessage(input);
|
|
465
|
+
}
|
|
466
|
+
async sendMessage(message) {
|
|
467
|
+
let result;
|
|
468
|
+
switch (message.type) {
|
|
469
|
+
case "TIMTextElem":
|
|
470
|
+
result = await this.sendTextMessage(message);
|
|
471
|
+
break;
|
|
472
|
+
case "TIMImageElem":
|
|
473
|
+
result = await this.sendImageMessage(message);
|
|
474
|
+
break;
|
|
475
|
+
case "TIMFileElem":
|
|
476
|
+
result = await this.sendFileMessage(message);
|
|
477
|
+
break;
|
|
478
|
+
default:
|
|
479
|
+
throw new Error(`Unsupported message type: ${message.type}`);
|
|
480
|
+
}
|
|
481
|
+
this.resetInactiveTimer();
|
|
482
|
+
return result;
|
|
483
|
+
}
|
|
484
|
+
bindSdkEvents() {
|
|
485
|
+
const listen = (event, handler) => {
|
|
486
|
+
this.sdk.on(event, handler);
|
|
487
|
+
this.boundHandlers.push({ event, handler });
|
|
488
|
+
};
|
|
489
|
+
listen(CbEvents2.OnConnectSuccess, (payload) => {
|
|
490
|
+
this.ready = true;
|
|
491
|
+
this.emitMappedEvents(CbEvents2.OnConnectSuccess, payload);
|
|
492
|
+
});
|
|
493
|
+
listen(CbEvents2.OnConnecting, (payload) => {
|
|
494
|
+
this.ready = false;
|
|
495
|
+
this.emitMappedEvents(CbEvents2.OnConnecting, {
|
|
496
|
+
...payload,
|
|
497
|
+
data: { state: "CONNECTING" }
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
listen(CbEvents2.OnConnectFailed, (payload) => {
|
|
501
|
+
this.ready = false;
|
|
502
|
+
if (this.loggingOut) return;
|
|
503
|
+
this.emitMappedEvents(CbEvents2.OnConnectFailed, payload);
|
|
504
|
+
});
|
|
505
|
+
listen(CbEvents2.OnKickedOffline, (payload) => {
|
|
506
|
+
this.ready = false;
|
|
507
|
+
this.emitMappedEvents(CbEvents2.OnKickedOffline, {
|
|
508
|
+
...payload,
|
|
509
|
+
data: { type: "multipleDevice" }
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
listen(CbEvents2.OnUserTokenExpired, (payload) => {
|
|
513
|
+
this.ready = false;
|
|
514
|
+
this.emitMappedEvents(CbEvents2.OnUserTokenExpired, {
|
|
515
|
+
...payload,
|
|
516
|
+
data: { type: "tokenExpired" }
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
listen(CbEvents2.OnUserTokenInvalid, (payload) => {
|
|
520
|
+
this.ready = false;
|
|
521
|
+
this.emitMappedEvents(CbEvents2.OnUserTokenInvalid, {
|
|
522
|
+
...payload,
|
|
523
|
+
data: { type: "tokenInvalid" }
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
listen(CbEvents2.OnRecvNewMessage, (payload) => {
|
|
527
|
+
this.handleIncomingMessages(payload, false);
|
|
528
|
+
});
|
|
529
|
+
listen(CbEvents2.OnRecvNewMessages, (payload) => {
|
|
530
|
+
this.handleIncomingMessages(payload, true);
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
emitMappedEvents(event, payload) {
|
|
534
|
+
const eventNames = OPENIM_TO_COMPAT_EVENT[event] ?? [];
|
|
535
|
+
eventNames.forEach((eventName) => {
|
|
536
|
+
if (eventName === EVENT.ERROR) {
|
|
537
|
+
this.emitter.emit(eventName, {
|
|
538
|
+
name: eventName,
|
|
539
|
+
data: {
|
|
540
|
+
code: payload.errCode,
|
|
541
|
+
message: payload.errMsg
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
this.emitter.emit(eventName, {
|
|
547
|
+
name: eventName,
|
|
548
|
+
data: payload.data
|
|
549
|
+
});
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
handleIncomingMessages(payload, multiple) {
|
|
553
|
+
const rawMessages = multiple ? payload.data ?? [] : [payload.data];
|
|
554
|
+
const messages = rawMessages.map(mapIncomingMessage).filter(Boolean);
|
|
555
|
+
if (messages.length === 0) return;
|
|
556
|
+
this.emitter.emit(EVENT.MESSAGE_RECEIVED, {
|
|
557
|
+
data: messages
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
async sendTextMessage(message) {
|
|
561
|
+
const text = String(message.payload.text ?? "");
|
|
562
|
+
const created = await this.wrapSdkCall("createTextMessage", () => this.sdk.createTextMessage(text));
|
|
563
|
+
const rawMessage = this.attachEx(created.data, message.cloudCustomData);
|
|
564
|
+
const sent = await this.wrapSdkCall("sendMessage(text)", () => this.sdk.sendMessage({
|
|
565
|
+
recvID: message.to,
|
|
566
|
+
groupID: "",
|
|
567
|
+
message: rawMessage,
|
|
568
|
+
isOnlineOnly: false
|
|
569
|
+
}));
|
|
570
|
+
return buildTextSendResult({ text }, sent);
|
|
571
|
+
}
|
|
572
|
+
async sendImageMessage(message) {
|
|
573
|
+
const file = message.payload.file;
|
|
574
|
+
if (!(file instanceof File)) throw new Error("image file is required");
|
|
575
|
+
const uploader = this.options.uploader ?? this.pluginUploader;
|
|
576
|
+
const upload = uploader ? await uploader.uploadImage({
|
|
577
|
+
file,
|
|
578
|
+
onProgress: message.payload.onProgress
|
|
579
|
+
}) : await this.createNativeImageUpload(file);
|
|
580
|
+
const imageMessage = await this.wrapSdkCall(
|
|
581
|
+
"createImageMessageByURL",
|
|
582
|
+
() => this.sdk.createImageMessageByURL(this.buildImageParams(upload))
|
|
583
|
+
);
|
|
584
|
+
const rawMessage = this.attachEx(imageMessage.data, message.cloudCustomData);
|
|
585
|
+
const sent = await this.wrapSdkCall("sendMessageNotOss(image)", () => this.sdk.sendMessageNotOss({
|
|
586
|
+
recvID: message.to,
|
|
587
|
+
groupID: "",
|
|
588
|
+
message: rawMessage,
|
|
589
|
+
offlinePushInfo: void 0
|
|
590
|
+
}));
|
|
591
|
+
return buildImageSendResult(upload, sent);
|
|
592
|
+
}
|
|
593
|
+
async sendFileMessage(message) {
|
|
594
|
+
const file = message.payload.file;
|
|
595
|
+
if (!(file instanceof File)) throw new Error("file is required");
|
|
596
|
+
const uploader = this.options.uploader ?? this.pluginUploader;
|
|
597
|
+
const upload = uploader ? await uploader.uploadFile({
|
|
598
|
+
file,
|
|
599
|
+
onProgress: message.payload.onProgress
|
|
600
|
+
}) : await this.createNativeFileUpload(file);
|
|
601
|
+
const fileMessage = await this.wrapSdkCall(
|
|
602
|
+
"createFileMessageByURL",
|
|
603
|
+
() => this.sdk.createFileMessageByURL(this.buildFileParams(upload, file))
|
|
604
|
+
);
|
|
605
|
+
const rawMessage = this.attachEx(fileMessage.data, message.cloudCustomData);
|
|
606
|
+
const sent = await this.wrapSdkCall("sendMessageNotOss(file)", () => this.sdk.sendMessageNotOss({
|
|
607
|
+
recvID: message.to,
|
|
608
|
+
groupID: "",
|
|
609
|
+
message: rawMessage,
|
|
610
|
+
offlinePushInfo: void 0
|
|
611
|
+
}));
|
|
612
|
+
return buildFileSendResult(upload, file.name, file.size, sent);
|
|
613
|
+
}
|
|
614
|
+
async createNativeImageUpload(file) {
|
|
615
|
+
const uuid = createOperationID();
|
|
616
|
+
const created = await this.sdk.createImageMessageByFile({
|
|
617
|
+
file,
|
|
618
|
+
sourcePath: file.name,
|
|
619
|
+
sourcePicture: {
|
|
620
|
+
uuid,
|
|
621
|
+
type: inferFileType(file.name),
|
|
622
|
+
size: file.size,
|
|
623
|
+
width: 0,
|
|
624
|
+
height: 0,
|
|
625
|
+
url: ""
|
|
626
|
+
},
|
|
627
|
+
bigPicture: {
|
|
628
|
+
uuid,
|
|
629
|
+
type: inferFileType(file.name),
|
|
630
|
+
size: file.size,
|
|
631
|
+
width: 0,
|
|
632
|
+
height: 0,
|
|
633
|
+
url: ""
|
|
634
|
+
},
|
|
635
|
+
snapshotPicture: {
|
|
636
|
+
uuid,
|
|
637
|
+
type: inferFileType(file.name),
|
|
638
|
+
size: file.size,
|
|
639
|
+
width: 0,
|
|
640
|
+
height: 0,
|
|
641
|
+
url: ""
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
const data = created.data;
|
|
645
|
+
return {
|
|
646
|
+
url: data.pictureElem?.sourcePicture?.url ?? "",
|
|
647
|
+
uuid: data.pictureElem?.sourcePicture?.uuid ?? uuid,
|
|
648
|
+
imageFormat: data.pictureElem?.sourcePicture?.type ?? inferFileType(file.name),
|
|
649
|
+
imageInfoArray: [
|
|
650
|
+
this.toImageInfo(data.pictureElem?.sourcePicture, 1),
|
|
651
|
+
this.toImageInfo(data.pictureElem?.bigPicture, 2),
|
|
652
|
+
this.toImageInfo(data.pictureElem?.snapshotPicture, 3)
|
|
653
|
+
].filter((item) => Boolean(item))
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
async createNativeFileUpload(file) {
|
|
657
|
+
const uuid = createOperationID();
|
|
658
|
+
const created = await this.sdk.createFileMessageByFile({
|
|
659
|
+
file,
|
|
660
|
+
filePath: file.name,
|
|
661
|
+
fileName: file.name,
|
|
662
|
+
uuid,
|
|
663
|
+
sourceUrl: "",
|
|
664
|
+
fileSize: file.size,
|
|
665
|
+
fileType: inferFileType(file.name)
|
|
666
|
+
});
|
|
667
|
+
const data = created.data;
|
|
668
|
+
return {
|
|
669
|
+
url: data.fileElem?.sourceUrl ?? "",
|
|
670
|
+
uuid: data.fileElem?.uuid ?? uuid,
|
|
671
|
+
fileName: data.fileElem?.fileName ?? file.name,
|
|
672
|
+
fileSize: data.fileElem?.fileSize ?? file.size,
|
|
673
|
+
fileType: inferFileType(file.name)
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
buildImageParams(upload) {
|
|
677
|
+
const source = upload.imageInfoArray?.find((item) => item.type === 1) ?? upload.imageInfoArray?.[0];
|
|
678
|
+
const big = upload.imageInfoArray?.find((item) => item.type === 2) ?? source;
|
|
679
|
+
const snapshot = upload.imageInfoArray?.find((item) => item.type === 3) ?? source;
|
|
680
|
+
const format = upload.imageFormat ?? "";
|
|
681
|
+
const uuid = upload.uuid ?? createOperationID();
|
|
682
|
+
return {
|
|
683
|
+
sourcePath: "",
|
|
684
|
+
sourcePicture: {
|
|
685
|
+
uuid,
|
|
686
|
+
type: format,
|
|
687
|
+
size: source?.size ?? 0,
|
|
688
|
+
width: source?.width ?? 0,
|
|
689
|
+
height: source?.height ?? 0,
|
|
690
|
+
url: source?.url ?? upload.url
|
|
691
|
+
},
|
|
692
|
+
bigPicture: {
|
|
693
|
+
uuid,
|
|
694
|
+
type: format,
|
|
695
|
+
size: big?.size ?? source?.size ?? 0,
|
|
696
|
+
width: big?.width ?? source?.width ?? 0,
|
|
697
|
+
height: big?.height ?? source?.height ?? 0,
|
|
698
|
+
url: big?.url ?? upload.url
|
|
699
|
+
},
|
|
700
|
+
snapshotPicture: {
|
|
701
|
+
uuid,
|
|
702
|
+
type: format,
|
|
703
|
+
size: snapshot?.size ?? source?.size ?? 0,
|
|
704
|
+
width: snapshot?.width ?? source?.width ?? 0,
|
|
705
|
+
height: snapshot?.height ?? source?.height ?? 0,
|
|
706
|
+
url: snapshot?.url ?? upload.url
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
buildFileParams(upload, file) {
|
|
711
|
+
return {
|
|
712
|
+
filePath: "",
|
|
713
|
+
fileName: upload.fileName ?? file.name,
|
|
714
|
+
uuid: upload.uuid ?? createOperationID(),
|
|
715
|
+
sourceUrl: upload.url,
|
|
716
|
+
fileSize: upload.fileSize ?? file.size,
|
|
717
|
+
fileType: upload.fileType ?? inferFileType(file.name)
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
attachEx(message, cloudCustomData) {
|
|
721
|
+
const sanitized = cloudCustomData === "null" || cloudCustomData === "undefined" ? "" : cloudCustomData;
|
|
722
|
+
return {
|
|
723
|
+
...message,
|
|
724
|
+
ex: sanitized ?? message.ex ?? ""
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
toImageInfo(picture, type = 1) {
|
|
728
|
+
if (!picture) return void 0;
|
|
729
|
+
return {
|
|
730
|
+
type,
|
|
731
|
+
size: picture.size,
|
|
732
|
+
width: picture.width,
|
|
733
|
+
height: picture.height,
|
|
734
|
+
url: picture.url
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
async wrapSdkCall(label, action) {
|
|
738
|
+
try {
|
|
739
|
+
return await action();
|
|
740
|
+
} catch (error) {
|
|
741
|
+
throw new Error(`${label} failed: ${this.stringifySdkError(error)}`);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
stringifySdkError(error) {
|
|
745
|
+
if (error instanceof Error) return error.message;
|
|
746
|
+
if (typeof error === "string") return error;
|
|
747
|
+
try {
|
|
748
|
+
return JSON.stringify(error);
|
|
749
|
+
} catch {
|
|
750
|
+
return String(error);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
// src/index.ts
|
|
756
|
+
var create = (options) => new OpenIMClientAdapter(options);
|
|
757
|
+
var ChatIMSDK = {
|
|
758
|
+
EVENT,
|
|
759
|
+
TYPES,
|
|
760
|
+
create
|
|
761
|
+
};
|
|
762
|
+
var index_default = ChatIMSDK;
|
|
763
|
+
export {
|
|
764
|
+
DCIMUploadPlugin,
|
|
765
|
+
DEFAULT_PLATFORM_ID,
|
|
766
|
+
EVENT,
|
|
767
|
+
TYPES,
|
|
768
|
+
create,
|
|
769
|
+
createDcimUploadProvider,
|
|
770
|
+
index_default as default
|
|
771
|
+
};
|