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/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
+ };