@cored-im/openapi-sdk 0.28.102

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,1463 @@
1
+ // src/core/types.ts
2
+ var LoggerLevel = /* @__PURE__ */ ((LoggerLevel2) => {
3
+ LoggerLevel2[LoggerLevel2["Debug"] = 0] = "Debug";
4
+ LoggerLevel2[LoggerLevel2["Info"] = 1] = "Info";
5
+ LoggerLevel2[LoggerLevel2["Warn"] = 2] = "Warn";
6
+ LoggerLevel2[LoggerLevel2["Error"] = 3] = "Error";
7
+ return LoggerLevel2;
8
+ })(LoggerLevel || {});
9
+
10
+ // src/core/version.ts
11
+ var VERSION = "0.28.102";
12
+ var USER_AGENT = "cored-openapi-sdk-js/0.28.102";
13
+
14
+ // src/core/consts.ts
15
+ var DEFAULT_PING_PATH = "/oapi/stat/v1/ping";
16
+ var DEFAULT_TOKEN_PATH = "/oapi/auth/v1/app/token";
17
+ var DEFAULT_GATEWAY_PATH = "/oapi/transport/v1/gateway";
18
+ var DEFAULT_WS_PATH = "/oapi/transport/v1/ws";
19
+ var DEFAULT_SECURE_VERSION = "1.0";
20
+
21
+ // src/core/crypto.ts
22
+ var ALPHANUMERIC = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
23
+ var CryptoManager = class {
24
+ constructor(config) {
25
+ this.counter = [0, 0, 0, 0, 0];
26
+ this.config = config;
27
+ this.prefix = randomAlphanumeric(6);
28
+ }
29
+ async encryptMessage(secret, data) {
30
+ const timestamp = this.config.timeManager.getServerTimestamp();
31
+ const nonce = this.getNonce();
32
+ const initKey = await sha256Bytes(`${timestamp}:${secret}:${nonce}`);
33
+ const aesKey = randomBytes(32);
34
+ const compressed = await compressGzip(data);
35
+ const encryptedKey = await encryptAES256CBC(aesKey, initKey);
36
+ const encryptedData = await encryptAES256CBC(compressed, aesKey);
37
+ return {
38
+ version: DEFAULT_SECURE_VERSION,
39
+ timestamp,
40
+ nonce,
41
+ encryptedKey,
42
+ encryptedData
43
+ };
44
+ }
45
+ async decryptMessage(secret, message) {
46
+ if (message.version !== DEFAULT_SECURE_VERSION) {
47
+ throw new Error(`unsupported secure message version: ${message.version}`);
48
+ }
49
+ const initKey = await sha256Bytes(`${message.timestamp}:${secret}:${message.nonce}`);
50
+ const aesKey = await decryptAES256CBC(message.encryptedKey, initKey);
51
+ const compressed = await decryptAES256CBC(message.encryptedData, aesKey);
52
+ return await decompressGzip(compressed);
53
+ }
54
+ getNonce() {
55
+ const random = randomAlphanumeric(5);
56
+ const counter = this.formatCounter();
57
+ this.addCounter();
58
+ return this.prefix + random + counter;
59
+ }
60
+ formatCounter() {
61
+ let result = "";
62
+ for (let i = 0; i < 5; i++) {
63
+ result += ALPHANUMERIC[this.counter[i]];
64
+ }
65
+ return result;
66
+ }
67
+ addCounter() {
68
+ for (let i = 4; i >= 0; i--) {
69
+ this.counter[i]++;
70
+ if (this.counter[i] < 62) {
71
+ break;
72
+ }
73
+ this.counter[i] = 0;
74
+ }
75
+ }
76
+ };
77
+ async function sha256Bytes(input) {
78
+ const data = new TextEncoder().encode(input);
79
+ const hash = await crypto.subtle.digest("SHA-256", data);
80
+ return new Uint8Array(hash);
81
+ }
82
+ async function sha256Hex(input) {
83
+ const bytes = await sha256Bytes(input);
84
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
85
+ }
86
+ async function encryptAES256CBC(data, key) {
87
+ const padded = pkcs7Pad(data);
88
+ const iv = randomBytes(16);
89
+ const cryptoKey = await crypto.subtle.importKey("raw", toBuffer(key), { name: "AES-CBC" }, false, ["encrypt"]);
90
+ const encrypted = await crypto.subtle.encrypt({ name: "AES-CBC", iv: toBuffer(iv) }, cryptoKey, toBuffer(padded));
91
+ const result = new Uint8Array(iv.length + encrypted.byteLength);
92
+ result.set(iv, 0);
93
+ result.set(new Uint8Array(encrypted), iv.length);
94
+ return result;
95
+ }
96
+ async function decryptAES256CBC(data, key) {
97
+ if (data.length < 16 || data.length % 16 !== 0) {
98
+ throw new Error("invalid encrypted data length");
99
+ }
100
+ const iv = data.slice(0, 16);
101
+ const ciphertext = data.slice(16);
102
+ const cryptoKey = await crypto.subtle.importKey("raw", toBuffer(key), { name: "AES-CBC" }, false, ["decrypt"]);
103
+ const decrypted = await crypto.subtle.decrypt({ name: "AES-CBC", iv: toBuffer(iv) }, cryptoKey, toBuffer(ciphertext));
104
+ return new Uint8Array(decrypted);
105
+ }
106
+ function pkcs7Pad(data) {
107
+ const blockSize = 16;
108
+ const padding = blockSize - data.length % blockSize;
109
+ const padded = new Uint8Array(data.length + padding);
110
+ padded.set(data);
111
+ padded.fill(padding, data.length);
112
+ return padded;
113
+ }
114
+ async function compressGzip(data) {
115
+ if (typeof CompressionStream !== "undefined") {
116
+ const stream = new CompressionStream("gzip");
117
+ const writer = stream.writable.getWriter();
118
+ void writer.write(toBuffer(data));
119
+ void writer.close();
120
+ const chunks = [];
121
+ const reader = stream.readable.getReader();
122
+ for (; ; ) {
123
+ const { done, value } = await reader.read();
124
+ if (done) break;
125
+ chunks.push(value);
126
+ }
127
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
128
+ const result = new Uint8Array(totalLength);
129
+ let offset = 0;
130
+ for (const chunk of chunks) {
131
+ result.set(chunk, offset);
132
+ offset += chunk.length;
133
+ }
134
+ return result;
135
+ }
136
+ throw new Error("CompressionStream not available. Please use a modern browser or Node.js 18+.");
137
+ }
138
+ async function decompressGzip(data) {
139
+ if (typeof DecompressionStream !== "undefined") {
140
+ const stream = new DecompressionStream("gzip");
141
+ const writer = stream.writable.getWriter();
142
+ void writer.write(toBuffer(data));
143
+ void writer.close();
144
+ const chunks = [];
145
+ const reader = stream.readable.getReader();
146
+ for (; ; ) {
147
+ const { done, value } = await reader.read();
148
+ if (done) break;
149
+ chunks.push(value);
150
+ }
151
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
152
+ const result = new Uint8Array(totalLength);
153
+ let offset = 0;
154
+ for (const chunk of chunks) {
155
+ result.set(chunk, offset);
156
+ offset += chunk.length;
157
+ }
158
+ return result;
159
+ }
160
+ throw new Error("DecompressionStream not available. Please use a modern browser or Node.js 18+.");
161
+ }
162
+ function toBuffer(data) {
163
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
164
+ }
165
+ function randomBytes(size) {
166
+ const bytes = new Uint8Array(size);
167
+ crypto.getRandomValues(bytes);
168
+ return bytes;
169
+ }
170
+ function randomAlphanumeric(size) {
171
+ const bytes = randomBytes(size);
172
+ let result = "";
173
+ for (let i = 0; i < size; i++) {
174
+ result += ALPHANUMERIC[bytes[i] % 62];
175
+ }
176
+ return result;
177
+ }
178
+
179
+ // src/internal/transport.ts
180
+ var ProtoWriter = class {
181
+ constructor() {
182
+ this.pos = 0;
183
+ this.forkStack = [];
184
+ this.buf = new Uint8Array(256);
185
+ }
186
+ grow(need) {
187
+ if (this.pos + need <= this.buf.length) return;
188
+ let newLen = this.buf.length * 2;
189
+ while (newLen < this.pos + need) newLen *= 2;
190
+ const next = new Uint8Array(newLen);
191
+ next.set(this.buf);
192
+ this.buf = next;
193
+ }
194
+ uint32(value) {
195
+ this.grow(5);
196
+ value >>>= 0;
197
+ while (value > 127) {
198
+ this.buf[this.pos++] = value & 127 | 128;
199
+ value >>>= 7;
200
+ }
201
+ this.buf[this.pos++] = value;
202
+ return this;
203
+ }
204
+ uint64(value) {
205
+ this.grow(10);
206
+ let lo = value >>> 0;
207
+ let hi = (value - lo) / 4294967296 >>> 0;
208
+ while (hi > 0) {
209
+ this.buf[this.pos++] = lo & 127 | 128;
210
+ lo = (lo >>> 7 | hi << 25) >>> 0;
211
+ hi >>>= 7;
212
+ }
213
+ while (lo > 127) {
214
+ this.buf[this.pos++] = lo & 127 | 128;
215
+ lo >>>= 7;
216
+ }
217
+ this.buf[this.pos++] = lo;
218
+ return this;
219
+ }
220
+ int32(value) {
221
+ if (value >= 0) return this.uint32(value);
222
+ this.grow(10);
223
+ for (let i = 0; i < 9; i++) {
224
+ this.buf[this.pos++] = value & 127 | 128;
225
+ value >>= 7;
226
+ }
227
+ this.buf[this.pos++] = 1;
228
+ return this;
229
+ }
230
+ bytes(value) {
231
+ this.uint32(value.length);
232
+ this.grow(value.length);
233
+ this.buf.set(value, this.pos);
234
+ this.pos += value.length;
235
+ return this;
236
+ }
237
+ string(value) {
238
+ const encoded = textEncoder.encode(value);
239
+ return this.bytes(encoded);
240
+ }
241
+ /** Start a nested sub-message. Call ldelim() to close it. */
242
+ fork() {
243
+ this.forkStack.push(this.pos);
244
+ this.grow(5);
245
+ this.pos += 5;
246
+ return this;
247
+ }
248
+ /** Close a fork: writes the sub-message length prefix. */
249
+ ldelim() {
250
+ const startPos = this.forkStack.pop();
251
+ const contentStart = startPos + 5;
252
+ const contentLen = this.pos - contentStart;
253
+ const lenBytes = [];
254
+ let v = contentLen;
255
+ while (v > 127) {
256
+ lenBytes.push(v & 127 | 128);
257
+ v >>>= 7;
258
+ }
259
+ lenBytes.push(v);
260
+ const newContentStart = startPos + lenBytes.length;
261
+ this.buf.copyWithin(newContentStart, contentStart, this.pos);
262
+ for (let i = 0; i < lenBytes.length; i++) {
263
+ this.buf[startPos + i] = lenBytes[i];
264
+ }
265
+ this.pos = newContentStart + contentLen;
266
+ return this;
267
+ }
268
+ finish() {
269
+ return this.buf.slice(0, this.pos);
270
+ }
271
+ };
272
+ var ProtoReader = class {
273
+ constructor(data) {
274
+ this.buf = data;
275
+ this.pos = 0;
276
+ this.len = data.length;
277
+ }
278
+ uint32() {
279
+ let value = 0;
280
+ let shift = 0;
281
+ let b;
282
+ do {
283
+ b = this.buf[this.pos++];
284
+ value |= (b & 127) << shift;
285
+ shift += 7;
286
+ } while (b & 128);
287
+ return value >>> 0;
288
+ }
289
+ uint64() {
290
+ let lo = 0;
291
+ let hi = 0;
292
+ let shift = 0;
293
+ let b;
294
+ for (let i = 0; i < 4; i++) {
295
+ b = this.buf[this.pos++];
296
+ lo |= (b & 127) << shift;
297
+ shift += 7;
298
+ if (!(b & 128)) return lo >>> 0;
299
+ }
300
+ b = this.buf[this.pos++];
301
+ lo |= (b & 127) << 28;
302
+ hi = (b & 127) >> 4;
303
+ if (!(b & 128)) return hi * 4294967296 + (lo >>> 0);
304
+ shift = 3;
305
+ do {
306
+ b = this.buf[this.pos++];
307
+ hi |= (b & 127) << shift;
308
+ shift += 7;
309
+ } while (b & 128);
310
+ return (hi >>> 0) * 4294967296 + (lo >>> 0);
311
+ }
312
+ int32() {
313
+ return this.uint32() | 0;
314
+ }
315
+ bytes() {
316
+ const len = this.uint32();
317
+ const value = this.buf.slice(this.pos, this.pos + len);
318
+ this.pos += len;
319
+ return value;
320
+ }
321
+ string() {
322
+ const bytes = this.bytes();
323
+ return textDecoder.decode(bytes);
324
+ }
325
+ skipType(wireType) {
326
+ switch (wireType) {
327
+ case 0:
328
+ while (this.buf[this.pos++] & 128) {
329
+ }
330
+ break;
331
+ case 1:
332
+ this.pos += 8;
333
+ break;
334
+ case 2:
335
+ this.pos += this.uint32();
336
+ break;
337
+ case 5:
338
+ this.pos += 4;
339
+ break;
340
+ default:
341
+ throw new Error(`unknown wire type: ${wireType}`);
342
+ }
343
+ }
344
+ };
345
+ var textEncoder = new TextEncoder();
346
+ var textDecoder = new TextDecoder();
347
+ function encodeSecureMessage(msg) {
348
+ const w = new ProtoWriter();
349
+ if (msg.version) w.uint32(10).string(msg.version);
350
+ if (msg.timestamp) w.uint32(16).uint64(msg.timestamp);
351
+ if (msg.nonce) w.uint32(26).string(msg.nonce);
352
+ if (msg.encryptedKey?.length) w.uint32(34).bytes(msg.encryptedKey);
353
+ if (msg.encryptedData?.length) w.uint32(42).bytes(msg.encryptedData);
354
+ return w.finish();
355
+ }
356
+ function decodeSecureMessage(data) {
357
+ const r = new ProtoReader(data);
358
+ const msg = { version: "", timestamp: 0, nonce: "", encryptedKey: new Uint8Array(0), encryptedData: new Uint8Array(0) };
359
+ while (r.pos < r.len) {
360
+ const tag = r.uint32();
361
+ switch (tag >>> 3) {
362
+ case 1:
363
+ msg.version = r.string();
364
+ break;
365
+ case 2:
366
+ msg.timestamp = r.uint64();
367
+ break;
368
+ case 3:
369
+ msg.nonce = r.string();
370
+ break;
371
+ case 4:
372
+ msg.encryptedKey = r.bytes();
373
+ break;
374
+ case 5:
375
+ msg.encryptedData = r.bytes();
376
+ break;
377
+ default:
378
+ r.skipType(tag & 7);
379
+ break;
380
+ }
381
+ }
382
+ return msg;
383
+ }
384
+ function encodeHttpRequest(msg) {
385
+ const w = new ProtoWriter();
386
+ if (msg.method) w.uint32(10).string(msg.method);
387
+ if (msg.path) w.uint32(18).string(msg.path);
388
+ if (msg.headers) {
389
+ for (const [k, v] of Object.entries(msg.headers)) {
390
+ w.uint32(26).fork().uint32(10).string(k).uint32(18).string(v).ldelim();
391
+ }
392
+ }
393
+ if (msg.body?.length) w.uint32(34).bytes(msg.body);
394
+ if (msg.reqId) w.uint32(42).string(msg.reqId);
395
+ return w.finish();
396
+ }
397
+ function decodeHttpRequest(data) {
398
+ const r = new ProtoReader(data);
399
+ const msg = { method: "", path: "", headers: {}, body: new Uint8Array(0), reqId: "" };
400
+ while (r.pos < r.len) {
401
+ const tag = r.uint32();
402
+ switch (tag >>> 3) {
403
+ case 1:
404
+ msg.method = r.string();
405
+ break;
406
+ case 2:
407
+ msg.path = r.string();
408
+ break;
409
+ case 3: {
410
+ const entryEnd = r.uint32() + r.pos;
411
+ let key = "", value = "";
412
+ while (r.pos < entryEnd) {
413
+ const entryTag = r.uint32();
414
+ switch (entryTag >>> 3) {
415
+ case 1:
416
+ key = r.string();
417
+ break;
418
+ case 2:
419
+ value = r.string();
420
+ break;
421
+ default:
422
+ r.skipType(entryTag & 7);
423
+ break;
424
+ }
425
+ }
426
+ msg.headers[key] = value;
427
+ break;
428
+ }
429
+ case 4:
430
+ msg.body = r.bytes();
431
+ break;
432
+ case 5:
433
+ msg.reqId = r.string();
434
+ break;
435
+ default:
436
+ r.skipType(tag & 7);
437
+ break;
438
+ }
439
+ }
440
+ return msg;
441
+ }
442
+ function decodeHttpResponse(data) {
443
+ const r = new ProtoReader(data);
444
+ const msg = { statusCode: 0, statusText: "", headers: {}, body: new Uint8Array(0), reqId: "" };
445
+ while (r.pos < r.len) {
446
+ const tag = r.uint32();
447
+ switch (tag >>> 3) {
448
+ case 1:
449
+ msg.statusCode = r.int32();
450
+ break;
451
+ case 2:
452
+ msg.statusText = r.string();
453
+ break;
454
+ case 3: {
455
+ const entryEnd = r.uint32() + r.pos;
456
+ let key = "", value = "";
457
+ while (r.pos < entryEnd) {
458
+ const entryTag = r.uint32();
459
+ switch (entryTag >>> 3) {
460
+ case 1:
461
+ key = r.string();
462
+ break;
463
+ case 2:
464
+ value = r.string();
465
+ break;
466
+ default:
467
+ r.skipType(entryTag & 7);
468
+ break;
469
+ }
470
+ }
471
+ msg.headers[key] = value;
472
+ break;
473
+ }
474
+ case 4:
475
+ msg.body = r.bytes();
476
+ break;
477
+ case 5:
478
+ msg.reqId = r.string();
479
+ break;
480
+ default:
481
+ r.skipType(tag & 7);
482
+ break;
483
+ }
484
+ }
485
+ return msg;
486
+ }
487
+ function encodeWebSocketMessage(msg) {
488
+ const w = new ProtoWriter();
489
+ if (msg.ping) {
490
+ w.uint32(10).fork();
491
+ if (msg.ping.timestamp) w.uint32(8).uint64(msg.ping.timestamp);
492
+ w.ldelim();
493
+ }
494
+ if (msg.pong) {
495
+ w.uint32(18).fork();
496
+ if (msg.pong.timestamp) w.uint32(8).uint64(msg.pong.timestamp);
497
+ w.ldelim();
498
+ }
499
+ if (msg.initRequest) {
500
+ w.uint32(26).fork();
501
+ if (msg.initRequest.userAgent) w.uint32(10).string(msg.initRequest.userAgent);
502
+ w.ldelim();
503
+ }
504
+ if (msg.initResponse) {
505
+ w.uint32(34).fork().ldelim();
506
+ }
507
+ if (msg.event) {
508
+ w.uint32(42).fork();
509
+ if (msg.event.eventHeader) {
510
+ w.uint32(10).fork();
511
+ if (msg.event.eventHeader.eventId) w.uint32(10).string(msg.event.eventHeader.eventId);
512
+ if (msg.event.eventHeader.eventType) w.uint32(18).string(msg.event.eventHeader.eventType);
513
+ if (msg.event.eventHeader.eventCreatedAt) w.uint32(24).uint64(msg.event.eventHeader.eventCreatedAt);
514
+ w.ldelim();
515
+ }
516
+ if (msg.event.eventBody?.length) w.uint32(18).bytes(msg.event.eventBody);
517
+ w.ldelim();
518
+ }
519
+ if (msg.eventAck) {
520
+ w.uint32(50).fork();
521
+ if (msg.eventAck.eventId) w.uint32(10).string(msg.eventAck.eventId);
522
+ w.ldelim();
523
+ }
524
+ if (msg.httpRequest) {
525
+ w.uint32(58).bytes(encodeHttpRequest(msg.httpRequest));
526
+ }
527
+ return w.finish();
528
+ }
529
+ function decodeWebSocketMessage(data) {
530
+ const r = new ProtoReader(data);
531
+ const msg = {};
532
+ while (r.pos < r.len) {
533
+ const tag = r.uint32();
534
+ switch (tag >>> 3) {
535
+ case 1: {
536
+ const subEnd = r.uint32() + r.pos;
537
+ const ping = { timestamp: 0 };
538
+ while (r.pos < subEnd) {
539
+ const subTag = r.uint32();
540
+ if (subTag >>> 3 === 1) ping.timestamp = r.uint64();
541
+ else r.skipType(subTag & 7);
542
+ }
543
+ msg.ping = ping;
544
+ break;
545
+ }
546
+ case 2: {
547
+ const subEnd = r.uint32() + r.pos;
548
+ const pong = { timestamp: 0 };
549
+ while (r.pos < subEnd) {
550
+ const subTag = r.uint32();
551
+ if (subTag >>> 3 === 1) pong.timestamp = r.uint64();
552
+ else r.skipType(subTag & 7);
553
+ }
554
+ msg.pong = pong;
555
+ break;
556
+ }
557
+ case 3: {
558
+ const subEnd = r.uint32() + r.pos;
559
+ const initReq = { userAgent: "" };
560
+ while (r.pos < subEnd) {
561
+ const subTag = r.uint32();
562
+ if (subTag >>> 3 === 1) initReq.userAgent = r.string();
563
+ else r.skipType(subTag & 7);
564
+ }
565
+ msg.initRequest = initReq;
566
+ break;
567
+ }
568
+ case 4: {
569
+ const subEnd = r.uint32() + r.pos;
570
+ r.pos = subEnd;
571
+ msg.initResponse = {};
572
+ break;
573
+ }
574
+ case 5: {
575
+ const subEnd = r.uint32() + r.pos;
576
+ const event = { eventBody: new Uint8Array(0) };
577
+ while (r.pos < subEnd) {
578
+ const subTag = r.uint32();
579
+ switch (subTag >>> 3) {
580
+ case 1: {
581
+ const headerEnd = r.uint32() + r.pos;
582
+ const header = { eventId: "", eventType: "", eventCreatedAt: 0 };
583
+ while (r.pos < headerEnd) {
584
+ const hTag = r.uint32();
585
+ switch (hTag >>> 3) {
586
+ case 1:
587
+ header.eventId = r.string();
588
+ break;
589
+ case 2:
590
+ header.eventType = r.string();
591
+ break;
592
+ case 3:
593
+ header.eventCreatedAt = r.uint64();
594
+ break;
595
+ default:
596
+ r.skipType(hTag & 7);
597
+ break;
598
+ }
599
+ }
600
+ event.eventHeader = header;
601
+ break;
602
+ }
603
+ case 2:
604
+ event.eventBody = r.bytes();
605
+ break;
606
+ default:
607
+ r.skipType(subTag & 7);
608
+ break;
609
+ }
610
+ }
611
+ msg.event = event;
612
+ break;
613
+ }
614
+ case 6: {
615
+ const subEnd = r.uint32() + r.pos;
616
+ const ack = { eventId: "" };
617
+ while (r.pos < subEnd) {
618
+ const subTag = r.uint32();
619
+ if (subTag >>> 3 === 1) ack.eventId = r.string();
620
+ else r.skipType(subTag & 7);
621
+ }
622
+ msg.eventAck = ack;
623
+ break;
624
+ }
625
+ case 7: {
626
+ const bytes = r.bytes();
627
+ msg.httpRequest = decodeHttpRequest(bytes);
628
+ break;
629
+ }
630
+ case 8: {
631
+ const bytes = r.bytes();
632
+ msg.httpResponse = decodeHttpResponse(bytes);
633
+ break;
634
+ }
635
+ default:
636
+ r.skipType(tag & 7);
637
+ break;
638
+ }
639
+ }
640
+ return msg;
641
+ }
642
+
643
+ // src/core/ws_client.ts
644
+ var _WebSocketImpl;
645
+ async function getWebSocket() {
646
+ if (_WebSocketImpl) return _WebSocketImpl;
647
+ if (typeof WebSocket !== "undefined") {
648
+ _WebSocketImpl = WebSocket;
649
+ return _WebSocketImpl;
650
+ }
651
+ try {
652
+ const mod = await Function('return import("ws")')();
653
+ _WebSocketImpl = mod.default || mod;
654
+ return _WebSocketImpl;
655
+ } catch {
656
+ throw new Error(
657
+ 'No WebSocket implementation found. Install the "ws" package: npm install ws'
658
+ );
659
+ }
660
+ }
661
+ var RECONNECT_CHECK_INTERVAL = 1e4;
662
+ var HEALTH_CHECK_INTERVAL = 2e4;
663
+ var ALIVE_TIMEOUT = 4e4;
664
+ var CONNECT_TIMEOUT = 5e3;
665
+ var WRITE_TIMEOUT = 6e4;
666
+ var WsClient = class {
667
+ constructor(options) {
668
+ this.eventHandlerMap = /* @__PURE__ */ new Map();
669
+ this.socket = null;
670
+ this.isConnecting = false;
671
+ this.isReconnecting = false;
672
+ this.shouldClose = false;
673
+ this.reqCount = 0;
674
+ this.reqCallbacks = /* @__PURE__ */ new Map();
675
+ this.reconnectAttempt = 0;
676
+ this.lastMessageAt = 0;
677
+ this.healthCheckTimer = null;
678
+ this.reconnectCheckTimer = null;
679
+ this.reconnectTimer = null;
680
+ this.initDone = false;
681
+ this.initPromise = null;
682
+ this.config = options.config;
683
+ this.getSecret = options.getSecret;
684
+ this.getToken = options.getToken;
685
+ this.ensurePing = options.ensurePing;
686
+ this.cryptoManager = options.cryptoManager;
687
+ }
688
+ onEvent(eventType, handler) {
689
+ this.ensureInit();
690
+ let handlers = this.eventHandlerMap.get(eventType);
691
+ if (!handlers) {
692
+ handlers = [];
693
+ this.eventHandlerMap.set(eventType, handlers);
694
+ }
695
+ handlers.push(handler);
696
+ }
697
+ offEvent(eventType, handler) {
698
+ const handlers = this.eventHandlerMap.get(eventType);
699
+ if (!handlers) return;
700
+ const idx = handlers.indexOf(handler);
701
+ if (idx >= 0) {
702
+ handlers.splice(idx, 1);
703
+ }
704
+ }
705
+ async httpRequest(req) {
706
+ await this.ensureInit();
707
+ const reqId = String(++this.reqCount);
708
+ req.reqId = reqId;
709
+ return new Promise((resolve, reject) => {
710
+ const timer = setTimeout(() => {
711
+ this.reqCallbacks.delete(reqId);
712
+ reject(new Error(`websocket request timeout: ${WRITE_TIMEOUT}ms`));
713
+ }, WRITE_TIMEOUT);
714
+ this.reqCallbacks.set(reqId, { resolve, reject, timer });
715
+ const reqBytes = encodeHttpRequest(req);
716
+ this.sendMessage({
717
+ httpRequest: {
718
+ method: req.method,
719
+ path: req.path,
720
+ headers: req.headers,
721
+ body: req.body,
722
+ reqId
723
+ }
724
+ }).catch((err) => {
725
+ clearTimeout(timer);
726
+ this.reqCallbacks.delete(reqId);
727
+ reject(err);
728
+ });
729
+ });
730
+ }
731
+ close() {
732
+ this.shouldClose = true;
733
+ this.clearTimers();
734
+ if (this.socket) {
735
+ try {
736
+ this.socket.close(1e3, "client close");
737
+ } catch {
738
+ }
739
+ this.socket = null;
740
+ }
741
+ for (const [, cb] of this.reqCallbacks) {
742
+ clearTimeout(cb.timer);
743
+ cb.reject(new Error("websocket closed"));
744
+ }
745
+ this.reqCallbacks.clear();
746
+ }
747
+ // --- Internal ---
748
+ ensureInit() {
749
+ if (this.initDone) return;
750
+ if (!this.initPromise) {
751
+ this.initPromise = this.doInit();
752
+ }
753
+ }
754
+ async doInit() {
755
+ if (this.initDone) return;
756
+ try {
757
+ await this.ensurePing();
758
+ await this.connect();
759
+ this.initDone = true;
760
+ } catch (err) {
761
+ this.config.logger.error("ws init failed", err);
762
+ this.reconnect();
763
+ }
764
+ }
765
+ async connect() {
766
+ if (this.isConnecting) return;
767
+ this.isConnecting = true;
768
+ try {
769
+ if (this.socket) {
770
+ try {
771
+ this.socket.close();
772
+ } catch {
773
+ }
774
+ this.socket = null;
775
+ }
776
+ for (const [, cb] of this.reqCallbacks) {
777
+ clearTimeout(cb.timer);
778
+ cb.reject(new Error("websocket reconnecting"));
779
+ }
780
+ this.reqCallbacks.clear();
781
+ await this.ensurePing();
782
+ const token = await this.getToken();
783
+ let wsUrl = this.config.backendUrl.replace(/^http/, "ws") + DEFAULT_WS_PATH + `?token=${encodeURIComponent(token)}`;
784
+ const WS = await getWebSocket();
785
+ await new Promise((resolve, reject) => {
786
+ const timer = setTimeout(() => {
787
+ reject(new Error("websocket connect timeout"));
788
+ }, CONNECT_TIMEOUT);
789
+ const ws = new WS(wsUrl);
790
+ ws.binaryType = "arraybuffer";
791
+ ws.onopen = async () => {
792
+ clearTimeout(timer);
793
+ this.socket = ws;
794
+ try {
795
+ await this.sendMessage({ initRequest: { userAgent: USER_AGENT } });
796
+ await new Promise((resolveInit, rejectInit) => {
797
+ const initTimer = setTimeout(() => {
798
+ rejectInit(new Error("init response timeout"));
799
+ }, CONNECT_TIMEOUT);
800
+ const origHandler = ws.onmessage;
801
+ ws.onmessage = async (event) => {
802
+ clearTimeout(initTimer);
803
+ try {
804
+ const data = new Uint8Array(event.data);
805
+ const secureMsg = decodeSecureMessage(data);
806
+ const decrypted = await this.cryptoManager.decryptMessage(this.getSecret(), secureMsg);
807
+ const wsMsg = decodeWebSocketMessage(decrypted);
808
+ if (wsMsg.initResponse) {
809
+ resolveInit();
810
+ } else {
811
+ rejectInit(new Error("unexpected message during init"));
812
+ }
813
+ } catch (err) {
814
+ rejectInit(err);
815
+ }
816
+ };
817
+ });
818
+ ws.onmessage = (event) => this.handleMessage(event);
819
+ ws.onclose = () => this.handleClose();
820
+ ws.onerror = (err) => {
821
+ this.config.logger.error("ws error", err);
822
+ };
823
+ this.lastMessageAt = Date.now();
824
+ this.startHealthCheck();
825
+ this.startReconnectCheck();
826
+ this.reconnectAttempt = 0;
827
+ this.isReconnecting = false;
828
+ resolve();
829
+ } catch (err) {
830
+ reject(err);
831
+ }
832
+ };
833
+ ws.onerror = () => {
834
+ clearTimeout(timer);
835
+ reject(new Error("websocket connect failed"));
836
+ };
837
+ });
838
+ } finally {
839
+ this.isConnecting = false;
840
+ }
841
+ }
842
+ handleClose() {
843
+ this.socket = null;
844
+ this.clearTimers();
845
+ if (!this.shouldClose) {
846
+ this.reconnect();
847
+ }
848
+ }
849
+ async handleMessage(event) {
850
+ this.lastMessageAt = Date.now();
851
+ try {
852
+ const data = new Uint8Array(event.data);
853
+ const secureMsg = decodeSecureMessage(data);
854
+ const decrypted = await this.cryptoManager.decryptMessage(this.getSecret(), secureMsg);
855
+ const wsMsg = decodeWebSocketMessage(decrypted);
856
+ if (wsMsg.pong) {
857
+ this.config.timeManager.syncServerTimestamp(Number(wsMsg.pong.timestamp));
858
+ } else if (wsMsg.event) {
859
+ const header = {
860
+ event_id: wsMsg.event.eventHeader?.eventId ?? "",
861
+ event_type: wsMsg.event.eventHeader?.eventType ?? "",
862
+ event_created_at: String(wsMsg.event.eventHeader?.eventCreatedAt ?? "0")
863
+ };
864
+ const handlers = this.eventHandlerMap.get(header.event_type);
865
+ if (handlers) {
866
+ for (const handler of handlers) {
867
+ try {
868
+ handler(header, wsMsg.event.eventBody ?? new Uint8Array(0));
869
+ } catch (err) {
870
+ this.config.logger.error("event handler error", err);
871
+ }
872
+ }
873
+ }
874
+ this.sendMessage({ eventAck: { eventId: header.event_id } }).catch(() => {
875
+ });
876
+ } else if (wsMsg.httpResponse) {
877
+ const reqId = wsMsg.httpResponse.reqId;
878
+ const cb = this.reqCallbacks.get(reqId);
879
+ if (cb) {
880
+ clearTimeout(cb.timer);
881
+ this.reqCallbacks.delete(reqId);
882
+ cb.resolve(wsMsg.httpResponse);
883
+ }
884
+ }
885
+ } catch (err) {
886
+ this.config.logger.error("ws message parse error", err);
887
+ }
888
+ }
889
+ async sendMessage(msg) {
890
+ const WS = await getWebSocket();
891
+ if (!this.socket || this.socket.readyState !== WS.OPEN) {
892
+ throw new Error("websocket not connected");
893
+ }
894
+ const msgBytes = encodeWebSocketMessage(msg);
895
+ const secureMsg = await this.cryptoManager.encryptMessage(this.getSecret(), msgBytes);
896
+ const data = encodeSecureMessage(secureMsg);
897
+ this.socket.send(data);
898
+ }
899
+ reconnect() {
900
+ if (this.shouldClose || this.isReconnecting) return;
901
+ this.isReconnecting = true;
902
+ const delay = this.getReconnectDelay();
903
+ this.config.logger.info(`ws reconnecting in ${delay}ms (attempt ${this.reconnectAttempt + 1})`);
904
+ this.reconnectTimer = setTimeout(async () => {
905
+ this.reconnectAttempt++;
906
+ try {
907
+ await this.connect();
908
+ this.config.logger.info("ws reconnected");
909
+ } catch (err) {
910
+ this.config.logger.error("ws reconnect failed", err);
911
+ this.isReconnecting = false;
912
+ this.reconnect();
913
+ }
914
+ }, delay);
915
+ }
916
+ getReconnectDelay() {
917
+ const attempt = this.reconnectAttempt;
918
+ if (attempt === 0) {
919
+ return 250 + Math.floor(Math.random() * 250);
920
+ }
921
+ if (attempt <= 4) {
922
+ return 750 + Math.floor(Math.random() * 500);
923
+ }
924
+ const base = Math.min(1e4, Math.max(750, (attempt - 4) * 2e3));
925
+ const jitter = Math.floor(Math.random() * 1e3);
926
+ return Math.min(15e3, base + jitter);
927
+ }
928
+ startHealthCheck() {
929
+ this.stopHealthCheck();
930
+ this.healthCheckTimer = setInterval(async () => {
931
+ try {
932
+ const timestamp = this.config.timeManager.getServerTimestamp();
933
+ await this.sendMessage({ ping: { timestamp } });
934
+ } catch {
935
+ }
936
+ }, HEALTH_CHECK_INTERVAL);
937
+ }
938
+ stopHealthCheck() {
939
+ if (this.healthCheckTimer) {
940
+ clearInterval(this.healthCheckTimer);
941
+ this.healthCheckTimer = null;
942
+ }
943
+ }
944
+ startReconnectCheck() {
945
+ this.stopReconnectCheck();
946
+ this.reconnectCheckTimer = setInterval(() => {
947
+ if (Date.now() - this.lastMessageAt > ALIVE_TIMEOUT) {
948
+ this.config.logger.warn("ws alive timeout, reconnecting");
949
+ this.clearTimers();
950
+ if (this.socket) {
951
+ try {
952
+ this.socket.close();
953
+ } catch {
954
+ }
955
+ this.socket = null;
956
+ }
957
+ this.reconnect();
958
+ }
959
+ }, RECONNECT_CHECK_INTERVAL);
960
+ }
961
+ stopReconnectCheck() {
962
+ if (this.reconnectCheckTimer) {
963
+ clearInterval(this.reconnectCheckTimer);
964
+ this.reconnectCheckTimer = null;
965
+ }
966
+ }
967
+ clearTimers() {
968
+ this.stopHealthCheck();
969
+ this.stopReconnectCheck();
970
+ if (this.reconnectTimer) {
971
+ clearTimeout(this.reconnectTimer);
972
+ this.reconnectTimer = null;
973
+ }
974
+ }
975
+ };
976
+
977
+ // src/core/api_client.ts
978
+ var TIMESTAMP_HEADER = "X-Cored-Timestamp";
979
+ var NONCE_HEADER = "X-Cored-Nonce";
980
+ var DefaultApiClient = class {
981
+ constructor(config) {
982
+ this.secret = "";
983
+ this.token = "";
984
+ this.tokenRefreshAt = 0;
985
+ this.tokenExpiresAt = 0;
986
+ this.tokenFetching = false;
987
+ this.tokenPromise = null;
988
+ this.pingCalled = false;
989
+ this.pingExpiresAt = 0;
990
+ this.pingFetching = false;
991
+ this.pingPromise = null;
992
+ this.config = config;
993
+ this.cryptoManager = new CryptoManager(config);
994
+ this.ws = new WsClient({
995
+ config,
996
+ getSecret: () => this.secret,
997
+ getToken: () => this.getToken(),
998
+ ensurePing: () => this.ensurePing(),
999
+ cryptoManager: this.cryptoManager
1000
+ });
1001
+ }
1002
+ async init() {
1003
+ this.secret = await sha256Hex(`${this.config.appId}:${this.config.appSecret}`);
1004
+ }
1005
+ async preheat() {
1006
+ await this.ensurePing();
1007
+ await this.getToken();
1008
+ }
1009
+ async close() {
1010
+ this.ws.close();
1011
+ }
1012
+ onEvent(eventType, handler) {
1013
+ this.ws.onEvent(eventType, handler);
1014
+ }
1015
+ offEvent(eventType, handler) {
1016
+ this.ws.offEvent(eventType, handler);
1017
+ }
1018
+ async request(req) {
1019
+ await this.ensurePing();
1020
+ let path = req.path;
1021
+ if (req.pathParams) {
1022
+ for (const [key, value] of Object.entries(req.pathParams)) {
1023
+ path = path.replace(`:${key}`, encodeURIComponent(value));
1024
+ }
1025
+ }
1026
+ let url = this.config.backendUrl + path;
1027
+ if (req.queryParams) {
1028
+ const params = new URLSearchParams();
1029
+ for (const [key, value] of Object.entries(req.queryParams)) {
1030
+ if (value) params.set(key, value);
1031
+ }
1032
+ const qs = params.toString();
1033
+ if (qs) url += "?" + qs;
1034
+ }
1035
+ if (this.config.enableEncryption && req.withAppAccessToken) {
1036
+ const token = await this.getToken();
1037
+ const bodyBytes = req.body ? new TextEncoder().encode(this.config.jsonMarshal(req.body)) : new Uint8Array(0);
1038
+ const headers2 = {
1039
+ "Content-Type": "application/json",
1040
+ "User-Agent": USER_AGENT,
1041
+ [TIMESTAMP_HEADER]: String(this.config.timeManager.getServerTimestamp()),
1042
+ [NONCE_HEADER]: randomAlphanumeric2(16)
1043
+ };
1044
+ if (req.headerParams) {
1045
+ Object.assign(headers2, req.headerParams);
1046
+ }
1047
+ const httpReq = {
1048
+ method: req.method,
1049
+ path: url.replace(this.config.backendUrl, ""),
1050
+ headers: headers2,
1051
+ body: bodyBytes,
1052
+ reqId: ""
1053
+ };
1054
+ if (req.withWebSocket) {
1055
+ const httpResp2 = await this.ws.httpRequest(httpReq);
1056
+ return {
1057
+ json: async () => JSON.parse(new TextDecoder().decode(httpResp2.body)),
1058
+ body: async () => httpResp2.body instanceof Uint8Array ? httpResp2.body : new Uint8Array(httpResp2.body)
1059
+ };
1060
+ }
1061
+ const httpReqBytes = encodeHttpRequest(httpReq);
1062
+ const secureMessage = await this.cryptoManager.encryptMessage(this.secret, httpReqBytes);
1063
+ const secureBytes = encodeSecureMessage(secureMessage);
1064
+ const gatewayUrl = this.config.backendUrl + DEFAULT_GATEWAY_PATH;
1065
+ const resp2 = await this.config.httpClient.fetch(gatewayUrl, {
1066
+ method: "POST",
1067
+ headers: {
1068
+ "Content-Type": "application/x-protobuf",
1069
+ "Authorization": `Bearer ${token}`,
1070
+ "User-Agent": USER_AGENT
1071
+ },
1072
+ body: secureBytes
1073
+ });
1074
+ const respBytes = new Uint8Array(await resp2.arrayBuffer());
1075
+ const respSecureMessage = decodeSecureMessage(respBytes);
1076
+ const decryptedBytes = await this.cryptoManager.decryptMessage(this.secret, respSecureMessage);
1077
+ const httpResp = decodeHttpResponse(decryptedBytes);
1078
+ return {
1079
+ json: async () => JSON.parse(new TextDecoder().decode(httpResp.body)),
1080
+ body: async () => httpResp.body instanceof Uint8Array ? httpResp.body : new Uint8Array(httpResp.body)
1081
+ };
1082
+ }
1083
+ const timestamp = String(this.config.timeManager.getServerTimestamp());
1084
+ const nonce = randomAlphanumeric2(16);
1085
+ const headers = {
1086
+ "Content-Type": "application/json",
1087
+ "User-Agent": USER_AGENT,
1088
+ [TIMESTAMP_HEADER]: timestamp,
1089
+ [NONCE_HEADER]: nonce
1090
+ };
1091
+ if (req.withAppAccessToken) {
1092
+ const token = await this.getToken();
1093
+ headers["Authorization"] = `Bearer ${token}`;
1094
+ }
1095
+ if (req.headerParams) {
1096
+ for (const [key, value] of Object.entries(req.headerParams)) {
1097
+ if (value) headers[key] = value;
1098
+ }
1099
+ }
1100
+ const fetchInit = {
1101
+ method: req.method,
1102
+ headers
1103
+ };
1104
+ if (req.body && req.method !== "GET") {
1105
+ fetchInit.body = this.config.jsonMarshal(req.body);
1106
+ }
1107
+ const resp = await this.config.httpClient.fetch(url, fetchInit);
1108
+ return {
1109
+ json: async () => resp.json(),
1110
+ body: async () => new Uint8Array(await resp.arrayBuffer())
1111
+ };
1112
+ }
1113
+ // --- Token management ---
1114
+ async getToken() {
1115
+ const now = this.config.timeManager.getServerTimestamp();
1116
+ if (this.token && this.tokenRefreshAt > now) {
1117
+ return this.token;
1118
+ }
1119
+ if (!this.token || this.tokenExpiresAt <= now) {
1120
+ if (this.tokenPromise) {
1121
+ await this.tokenPromise;
1122
+ return this.token;
1123
+ }
1124
+ this.tokenPromise = this.fetchToken();
1125
+ try {
1126
+ await this.tokenPromise;
1127
+ } finally {
1128
+ this.tokenPromise = null;
1129
+ }
1130
+ return this.token;
1131
+ }
1132
+ if (!this.tokenFetching) {
1133
+ this.tokenFetching = true;
1134
+ this.fetchToken().finally(() => {
1135
+ this.tokenFetching = false;
1136
+ });
1137
+ }
1138
+ return this.token;
1139
+ }
1140
+ async fetchToken() {
1141
+ const timestamp = String(this.config.timeManager.getServerTimestamp());
1142
+ const nonce = randomAlphanumeric2(16);
1143
+ const signPayload = `${this.config.appId}:${timestamp}:${this.config.appSecret}:${nonce}`;
1144
+ const signature = await sha256Hex(signPayload);
1145
+ const url = this.config.backendUrl + DEFAULT_TOKEN_PATH;
1146
+ const resp = await this.config.httpClient.fetch(url, {
1147
+ method: "POST",
1148
+ headers: {
1149
+ "Content-Type": "application/json",
1150
+ "User-Agent": USER_AGENT
1151
+ },
1152
+ body: JSON.stringify({
1153
+ app_id: this.config.appId,
1154
+ timestamp,
1155
+ nonce,
1156
+ signature: `v1:${signature}`
1157
+ })
1158
+ });
1159
+ const data = await resp.json();
1160
+ if (data.code !== 0 || !data.data) {
1161
+ throw new Error(`fetch token failed: code=${data.code}, msg=${data.msg}`);
1162
+ }
1163
+ this.token = data.data.access_token;
1164
+ const now = this.config.timeManager.getServerTimestamp();
1165
+ this.tokenExpiresAt = now + (data.data.expires_in - 60) * 1e3;
1166
+ this.tokenRefreshAt = this.tokenExpiresAt - 5 * 60 * 1e3;
1167
+ }
1168
+ // --- Ping / server time sync ---
1169
+ async ensurePing() {
1170
+ const now = Date.now();
1171
+ if (this.pingCalled && this.pingExpiresAt > now) {
1172
+ return;
1173
+ }
1174
+ if (!this.pingCalled || this.pingExpiresAt <= now) {
1175
+ if (this.pingPromise) {
1176
+ await this.pingPromise;
1177
+ return;
1178
+ }
1179
+ this.pingPromise = this.fetchPing();
1180
+ try {
1181
+ await this.pingPromise;
1182
+ } finally {
1183
+ this.pingPromise = null;
1184
+ }
1185
+ return;
1186
+ }
1187
+ if (!this.pingFetching) {
1188
+ this.pingFetching = true;
1189
+ this.fetchPing().finally(() => {
1190
+ this.pingFetching = false;
1191
+ });
1192
+ }
1193
+ }
1194
+ async fetchPing() {
1195
+ const url = this.config.backendUrl + DEFAULT_PING_PATH;
1196
+ const resp = await this.config.httpClient.fetch(url, {
1197
+ method: "GET",
1198
+ headers: { "User-Agent": USER_AGENT }
1199
+ });
1200
+ const data = await resp.json();
1201
+ if (data.code !== 0 || !data.data) {
1202
+ throw new Error(`ping failed: code=${data.code}, msg=${data.msg}`);
1203
+ }
1204
+ this.config.timeManager.syncServerTimestamp(data.data.timestamp);
1205
+ this.pingCalled = true;
1206
+ this.pingExpiresAt = Date.now() + 10 * 60 * 1e3;
1207
+ this.config.logger.info(`ping ok, server version=${data.data.version}, org_code=${data.data.org_code}`);
1208
+ }
1209
+ };
1210
+ var ALPHANUMERIC2 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1211
+ function randomAlphanumeric2(size) {
1212
+ const bytes = new Uint8Array(size);
1213
+ crypto.getRandomValues(bytes);
1214
+ let result = "";
1215
+ for (let i = 0; i < size; i++) {
1216
+ result += ALPHANUMERIC2[bytes[i] % 62];
1217
+ }
1218
+ return result;
1219
+ }
1220
+
1221
+ // src/core/http_client.ts
1222
+ var DefaultHttpClient = class {
1223
+ constructor(timeout = 6e4) {
1224
+ this.timeout = timeout;
1225
+ }
1226
+ async fetch(url, init) {
1227
+ if (this.timeout > 0) {
1228
+ const controller = new AbortController();
1229
+ const timer = setTimeout(() => controller.abort(), this.timeout);
1230
+ try {
1231
+ return await fetch(url, { ...init, signal: controller.signal });
1232
+ } finally {
1233
+ clearTimeout(timer);
1234
+ }
1235
+ }
1236
+ return fetch(url, init);
1237
+ }
1238
+ };
1239
+
1240
+ // src/core/logger.ts
1241
+ var DefaultLogger = class {
1242
+ constructor(level = 1 /* Info */) {
1243
+ this.level = level;
1244
+ }
1245
+ debug(msg, ...args) {
1246
+ if (this.level <= 0 /* Debug */) {
1247
+ console.debug(`[sdk] DEBUG ${msg}`, ...args);
1248
+ }
1249
+ }
1250
+ info(msg, ...args) {
1251
+ if (this.level <= 1 /* Info */) {
1252
+ console.info(`[sdk] INFO ${msg}`, ...args);
1253
+ }
1254
+ }
1255
+ warn(msg, ...args) {
1256
+ if (this.level <= 2 /* Warn */) {
1257
+ console.warn(`[sdk] WARN ${msg}`, ...args);
1258
+ }
1259
+ }
1260
+ error(msg, ...args) {
1261
+ if (this.level <= 3 /* Error */) {
1262
+ console.error(`[sdk] ERROR ${msg}`, ...args);
1263
+ }
1264
+ }
1265
+ };
1266
+
1267
+ // src/core/time_manager.ts
1268
+ var DefaultTimeManager = class {
1269
+ constructor() {
1270
+ this.serverTimeBase = 0;
1271
+ this.systemTimeBase = 0;
1272
+ }
1273
+ getSystemTimestamp() {
1274
+ return Date.now();
1275
+ }
1276
+ getServerTimestamp() {
1277
+ if (this.serverTimeBase === 0) {
1278
+ return this.getSystemTimestamp();
1279
+ }
1280
+ return this.getSystemTimestamp() - this.systemTimeBase + this.serverTimeBase;
1281
+ }
1282
+ syncServerTimestamp(timestamp) {
1283
+ if (timestamp <= this.serverTimeBase) {
1284
+ return;
1285
+ }
1286
+ this.serverTimeBase = timestamp;
1287
+ this.systemTimeBase = this.getSystemTimestamp();
1288
+ }
1289
+ };
1290
+
1291
+ // src/service/im/v1/chat.ts
1292
+ var Chat = class {
1293
+ constructor(config) {
1294
+ this.config = config;
1295
+ }
1296
+ /**
1297
+ * Set typing status
1298
+ *
1299
+ * Set the typing status, lasts only 5 seconds, direct messages only
1300
+ */
1301
+ async createTyping(req) {
1302
+ const resp = await this.config.apiClient.request({
1303
+ method: "POST",
1304
+ path: `/oapi/im/v1/chats/${req.chat_id ?? ""}/typing`,
1305
+ body: req,
1306
+ withAppAccessToken: true
1307
+ });
1308
+ return await resp.json();
1309
+ }
1310
+ /**
1311
+ * Clear typing status
1312
+ *
1313
+ * Direct messages only
1314
+ */
1315
+ async deleteTyping(req) {
1316
+ const resp = await this.config.apiClient.request({
1317
+ method: "DELETE",
1318
+ path: `/oapi/im/v1/chats/${req.chat_id ?? ""}/typing`,
1319
+ body: req,
1320
+ withAppAccessToken: true
1321
+ });
1322
+ return await resp.json();
1323
+ }
1324
+ };
1325
+
1326
+ // src/service/im/v1/message_event.ts
1327
+ var MessageEvent = class {
1328
+ constructor(config) {
1329
+ this.handlerMap = /* @__PURE__ */ new Map();
1330
+ this.config = config;
1331
+ }
1332
+ /** Message received */
1333
+ onMessageReceive(handler) {
1334
+ const wrappedHandler = (header, body) => {
1335
+ const event = {
1336
+ header,
1337
+ body: typeof body === "string" ? JSON.parse(body) : JSON.parse(new TextDecoder().decode(body))
1338
+ };
1339
+ handler(event);
1340
+ };
1341
+ this.handlerMap.set(handler, wrappedHandler);
1342
+ this.config.apiClient.onEvent("im.v1.message.receive", wrappedHandler);
1343
+ }
1344
+ offMessageReceive(handler) {
1345
+ const wrappedHandler = this.handlerMap.get(handler);
1346
+ if (wrappedHandler) {
1347
+ this.config.apiClient.offEvent("im.v1.message.receive", wrappedHandler);
1348
+ this.handlerMap.delete(handler);
1349
+ }
1350
+ }
1351
+ };
1352
+
1353
+ // src/service/im/v1/message.ts
1354
+ var Message = class {
1355
+ constructor(config) {
1356
+ this.config = config;
1357
+ this.Event = new MessageEvent(config);
1358
+ }
1359
+ /** Send a message */
1360
+ async sendMessage(req) {
1361
+ const resp = await this.config.apiClient.request({
1362
+ method: "POST",
1363
+ path: "/oapi/im/v1/messages",
1364
+ body: req,
1365
+ withAppAccessToken: true,
1366
+ withWebSocket: true
1367
+ });
1368
+ return await resp.json();
1369
+ }
1370
+ /** Get a message */
1371
+ async getMessage(req) {
1372
+ const resp = await this.config.apiClient.request({
1373
+ method: "GET",
1374
+ path: `/oapi/im/v1/messages/${req.message_id ?? ""}`,
1375
+ body: req,
1376
+ withAppAccessToken: true
1377
+ });
1378
+ return await resp.json();
1379
+ }
1380
+ /** Recall a message */
1381
+ async recallMessage(req) {
1382
+ const resp = await this.config.apiClient.request({
1383
+ method: "POST",
1384
+ path: `/oapi/im/v1/messages/${req.message_id ?? ""}/recall`,
1385
+ body: req,
1386
+ withAppAccessToken: true
1387
+ });
1388
+ return await resp.json();
1389
+ }
1390
+ /** Mark message as read */
1391
+ async readMessage(req) {
1392
+ const resp = await this.config.apiClient.request({
1393
+ method: "POST",
1394
+ path: `/oapi/im/v1/messages/${req.message_id ?? ""}/read`,
1395
+ body: req,
1396
+ withAppAccessToken: true
1397
+ });
1398
+ return await resp.json();
1399
+ }
1400
+ };
1401
+
1402
+ // src/service/im/v1/v1.ts
1403
+ var V1 = class {
1404
+ constructor(config) {
1405
+ this.Chat = new Chat(config);
1406
+ this.Message = new Message(config);
1407
+ }
1408
+ };
1409
+
1410
+ // src/service/im/index.ts
1411
+ var Service = class {
1412
+ constructor(config) {
1413
+ this.v1 = new V1(config);
1414
+ }
1415
+ };
1416
+
1417
+ // src/client.ts
1418
+ var CoredClient = class _CoredClient {
1419
+ constructor(config) {
1420
+ this.config = config;
1421
+ this.apiClient = config.apiClient;
1422
+ this.Im = new Service(config);
1423
+ }
1424
+ static async create(backendUrl, appId, appSecret, options = {}) {
1425
+ backendUrl = backendUrl.replace(/\/+$/, "");
1426
+ const logger = options.logger ?? new DefaultLogger(options.logLevel ?? 1 /* Info */);
1427
+ const httpClient = options.httpClient ?? new DefaultHttpClient(options.requestTimeout ?? 6e4);
1428
+ const timeManager = options.timeManager ?? new DefaultTimeManager();
1429
+ const jsonMarshal = options.jsonMarshal ?? ((v) => JSON.stringify(v));
1430
+ const jsonUnmarshal = options.jsonUnmarshal ?? ((s) => JSON.parse(s));
1431
+ const config = {
1432
+ appId,
1433
+ appSecret,
1434
+ backendUrl,
1435
+ httpClient,
1436
+ apiClient: null,
1437
+ // will be set below
1438
+ enableEncryption: options.enableEncryption ?? true,
1439
+ requestTimeout: options.requestTimeout ?? 6e4,
1440
+ timeManager,
1441
+ logger,
1442
+ jsonMarshal,
1443
+ jsonUnmarshal
1444
+ };
1445
+ const apiClient = new DefaultApiClient(config);
1446
+ await apiClient.init();
1447
+ config.apiClient = apiClient;
1448
+ return new _CoredClient(config);
1449
+ }
1450
+ async preheat() {
1451
+ await this.apiClient.preheat();
1452
+ }
1453
+ async close() {
1454
+ await this.apiClient.close();
1455
+ }
1456
+ };
1457
+ export {
1458
+ CoredClient,
1459
+ LoggerLevel,
1460
+ USER_AGENT,
1461
+ VERSION
1462
+ };
1463
+ //# sourceMappingURL=index.js.map